public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6]
@ 2012-07-30 14:21 Richard Earnshaw
  2012-07-30 14:28 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes Yufeng Zhang
                   ` (7 more replies)
  0 siblings, 8 replies; 41+ messages in thread
From: Richard Earnshaw @ 2012-07-30 14:21 UTC (permalink / raw)
  To: binutils; +Cc: Yufeng Zhang

ARM is pleased to announce a port of binutils, gas and ld to its
AArch64 architecture.

Please note that while these tools have been used to build a large
body of software, they cannot yet be considered complete.  We believe
that the code is now in a state where it is worth starting the process
of a public review.

In order to ensure that the assembler and disassembler remain
synchronized we have implemented a unified instruction description
table in opcodes that is shared by both the assembler and the
disassembler.  A generator is used at compile time to generate both
the decoding decision tree used by the disassembler and the various
functions required by both disassembler and assembler.

No target independent changes are required to support this port beyond
those that are necessary for any new target (such as adding
relocations to bfd/reloc.c).

There are still a number of features that require some further
work.  Issues that we are aware of include:
- Linker support for garbage collection of unused sections.
- Further memory and TLS models
- Support for ifunc.

The patches to support this are separated as follows:

 0/6 - This message
 1/6 - Toplevel configury changes
 2/6 - opcode changes
 3/6 - bfd changes
 4/6 - gas changes
 5/6 - ld changes
 6/6 - binutils changes

R.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes
  2012-07-30 14:21 [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Richard Earnshaw
@ 2012-07-30 14:28 ` Yufeng Zhang
  2012-07-30 14:49   ` Joseph S. Myers
  2012-08-07 17:39   ` Yufeng Zhang
  2012-07-30 14:30 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Jan Beulich
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-07-30 14:28 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 670 bytes --]

This patch adds the top level configury changes for the AArch64 target 
support.


Yufeng


ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * configure.ac: Add AArch64.
         * configure: Regenerate.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: aarch64-config.patch --]
[-- Type: text/x-patch; name=aarch64-config.patch, Size: 678 bytes --]

diff --git a/configure.ac b/configure.ac
index 5efb4a3..83ea5bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -842,6 +842,17 @@ case "${target}" in
     ;;
   *-*-vxworks*)
     ;;
+  aarch64*-*-elf* )
+    noconfigdirs="$noconfigdirs target-libffi target-qthreads"
+    libgloss_dir=aarch64
+    ;;
+  aarch64*-*-linux* )
+    noconfigdirs="$noconfigdirs target-libffi target-qthreads"
+    case ${with_newlib} in
+      no) noconfigdirs="$noconfigdirs target-newlib target-libgloss"
+    esac
+    libgloss_dir=aarch64
+    ;;
   alpha*-dec-osf*)
     # ld works, but does not support shared libraries.
     # gas doesn't generate exception information.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6]
  2012-07-30 14:21 [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Richard Earnshaw
  2012-07-30 14:28 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes Yufeng Zhang
@ 2012-07-30 14:30 ` Jan Beulich
  2012-08-09 14:50   ` Richard Earnshaw
  2012-07-30 14:47 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes Yufeng Zhang
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 41+ messages in thread
From: Jan Beulich @ 2012-07-30 14:30 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: Yufeng Zhang, binutils

>>> On 30.07.12 at 16:21, Richard Earnshaw <rearnsha@arm.com> wrote:
> ARM is pleased to announce a port of binutils, gas and ld to its
> AArch64 architecture.
> 
> Please note that while these tools have been used to build a large
> body of software, they cannot yet be considered complete.  We believe
> that the code is now in a state where it is worth starting the process
> of a public review.

Since it was just yesterday that I looked at arm.com, and there
still was no public documentation available - where would that be
found (as it would be needed in order to do a meaningful review)?

Thanks, Jan

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes
  2012-07-30 14:21 [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Richard Earnshaw
  2012-07-30 14:28 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes Yufeng Zhang
  2012-07-30 14:30 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Jan Beulich
@ 2012-07-30 14:47 ` Yufeng Zhang
  2012-07-31 18:22   ` nick clifton
  2012-08-07 17:18   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes v2 Yufeng Zhang
  2012-07-30 14:51 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes Yufeng Zhang
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-07-30 14:47 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 2528 bytes --]

This patch adds opcodes changes for the AArch64 target.


include/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * dis-asm.h (print_insn_aarch64): New declaration.
         (print_aarch64_disassembler_options): New declaration.
         (aarch64_symbol_is_valid): New declaration.


include/opcode/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * aarch64.h: New file.


opcodes/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * Makefile.am: Add AArch64.
         * Makefile.in: Regenerate.
         * aarch64-asm.c: New file.
         * aarch64-asm.h: New file.
         * aarch64-dis.c: New file.
         * aarch64-dis.h: New file.
         * aarch64-gen.c: New file.
         * aarch64-opc.c: New file.
         * aarch64-opc.h: New file.
         * aarch64-tbl.h: New file.
         * configure.in: Add AArch64.
         * configure: Regenerate.
         * disassemble.c: Add AArch64.
         * aarch64-asm-2.c: New file (automatically generated).
         * aarch64-dis-2.c: New file (automatically generated).
         * aarch64-opc-2.c: New file (automatically generated).
         * po/POTFILES.in: Regenerate.

[-- Attachment #2: aarch64-opcodes.patch.bz2 --]
[-- Type: application/x-bzip, Size: 76968 bytes --]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes
  2012-07-30 14:28 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes Yufeng Zhang
@ 2012-07-30 14:49   ` Joseph S. Myers
  2012-08-01 14:59     ` Yufeng Zhang
  2012-08-07 17:39   ` Yufeng Zhang
  1 sibling, 1 reply; 41+ messages in thread
From: Joseph S. Myers @ 2012-07-30 14:49 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

On Mon, 30 Jul 2012, Yufeng Zhang wrote:

> diff --git a/configure.ac b/configure.ac
> index 5efb4a3..83ea5bc 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -842,6 +842,17 @@ case "${target}" in
>      ;;
>    *-*-vxworks*)
>      ;;
> +  aarch64*-*-elf* )
> +    noconfigdirs="$noconfigdirs target-libffi target-qthreads"
> +    libgloss_dir=aarch64
> +    ;;
> +  aarch64*-*-linux* )
> +    noconfigdirs="$noconfigdirs target-libffi target-qthreads"
> +    case ${with_newlib} in
> +      no) noconfigdirs="$noconfigdirs target-newlib target-libgloss"
> +    esac
> +    libgloss_dir=aarch64
> +    ;;

This appears to be modifying the miscellaneous section of configure.ac, 
not taking account of the various cleanups I did a while back.

Java is disabled in the "# Disable Java if libffi is not supported." 
section, using a whitelist of targets supported by libffi, so you don't 
need to disable it here.  I removed all references to target-qthreads on 
2011-04-06 so you shouldn't need to handle that either.  newlib is 
disabled by default for *-*-linux* under "# Disable newlib and libgloss 
for various target OSes."; if you have a newlib port for 
aarch64*-*-linux*, then at the time you submit that port you can add 
special code like that for i[[3456789]]86-*-linux* to control whether 
newlib may be built for that target.  Finally, libgloss_dir should be set 
in the cases below "# Default libgloss CPU subdirectory.", based on the 
architecture not the OS.

Thus, to the extent that this patch does things that are still relevant 
after my cleanups, (a) those things need to go in more logical places in 
configure.ac and (b) those things relate to newlib/libgloss and so would 
better be submitted with the newlib/libgloss port, to the newlib list, 
rather than as part of a binutils port to the binutils list.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes
  2012-07-30 14:21 [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Richard Earnshaw
                   ` (2 preceding siblings ...)
  2012-07-30 14:47 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes Yufeng Zhang
@ 2012-07-30 14:51 ` Yufeng Zhang
  2012-07-30 14:57   ` Joseph S. Myers
                     ` (3 more replies)
  2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes Yufeng Zhang
                   ` (3 subsequent siblings)
  7 siblings, 4 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-07-30 14:51 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 2905 bytes --]

This patch adds the bfd changes of the AArch64 target support.


include/elf/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * aarch64.h: New file.
         * common.h (EM_res183): Rename to EM_AARCH64.
         (EM_res184): Rename to EM_ARM184.


bfd/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * Makefile.am: Add AArch64 files.
         * Makefile.in: Regenerate.
         * archures.c (bfd_aarch64_arch): New declaration.
         (bfd_archures_list): Use bfd_archures_list.
         * bfd-in.h (bfd_elf64_aarch64_init_maps): New declaration.
         (bfd_aarch64_process_before_allocation): New declaration.
         (bfd_elf64_aarch64_process_before_allocation): New declaration.
         (bfd_elf64_aarch64_set_options): New declaration.
         (bfd_elf64_aarch64_add_glue_sections_to_bfd): New declaration.
         (BFD_AARCH64_SPECIAL_SYM_TYPE_MAP): New definition.
         (BFD_AARCH64_SPECIAL_SYM_TYPE_TAG): New definition.
         (BFD_AARCH64_SPECIAL_SYM_TYPE_OTHER): New definition.
         (BFD_AARCH64_SPECIAL_SYM_TYPE_ANY): New definition.
         (bfd_is_aarch64_special_symbol_name): New declaration.
         (bfd_aarch64_merge_machines): New declaration.
         (bfd_aarch64_update_notes): New declaration.
         (int bfd_aarch64_get_mach_from_notes): New declaration.
         (elf64_aarch64_setup_section_lists): New declaration.
         (elf64_aarch64_next_input_section): New declaration.
         (elf64_aarch64_size_stubs): New declaration.
         (elf64_aarch64_build_stubs): New declaration.
         * config.bfd: Add AArch64.
         * configure.in: Add AArch64.
         * configure: Regenerate.
         * cpu-aarch64.c: New file.
         * elf-bfd.h: Add AArch64.
         * bfd-in2.h: Regenerate.
         * libbfd.h: Regenerate.
         * elf64-aarch64.c: New file.
         * reloc.c: Add AArch64 relocations.
         * targets.c: Add AArch64.
         * po/SRC-POTFILES.in: Regenerate.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: aarch64-bfd.patch --]
[-- Type: text/x-patch; name=aarch64-bfd.patch, Size: 252025 bytes --]

diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h
new file mode 100644
index 0000000..71a9730
--- /dev/null
+++ b/include/elf/aarch64.h
@@ -0,0 +1,214 @@
+/* AArch64 ELF support for BFD.
+
+   Copyright 2009, 2010, 2011, 2012  Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of GNU Binutils.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the license, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING3. If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ELF_AARCH64_H
+#define _ELF_AARCH64_H
+
+#include "elf/reloc-macros.h"
+
+/* Processor specific program header types.  */
+#define PT_AARCH64_ARCHEXT	(PT_LOPROC + 0)
+
+/* Additional section types.  */
+#define SHT_AARCH64_ATTRIBUTES	0x70000003  /* Section holds attributes.  */
+
+/* ARM-specific values for sh_flags.  */
+#define SHF_ENTRYSECT		0x10000000   /* Section contains an
+						entry point.  */
+#define SHF_COMDEF		0x80000000   /* Section may be multiply defined
+						in the input to a link step.  */
+
+/* Relocation types.  */
+
+START_RELOC_NUMBERS (elf_aarch64_reloc_type)
+
+/* Null relocations. */
+RELOC_NUMBER (R_AARCH64_NONE, 0) /* No reloc */
+
+FAKE_RELOC (R_AARCH64_static_min, 256)
+
+RELOC_NUMBER (R_AARCH64_NULL, 256) /* No reloc */
+
+/* Basic data relocations. */
+
+/* .xword: (S+A) */
+RELOC_NUMBER (R_AARCH64_ABS64, 257)
+
+/* .word:  (S+A) */
+RELOC_NUMBER (R_AARCH64_ABS32, 258)
+
+/* .half: (S+A) */
+RELOC_NUMBER (R_AARCH64_ABS16, 259)
+
+/* .xword: (S+A-P) */
+RELOC_NUMBER (R_AARCH64_PREL64, 260)
+
+/* .word: (S+A-P) */
+RELOC_NUMBER (R_AARCH64_PREL32, 261)
+
+/* .half:  (S+A-P) */
+RELOC_NUMBER (R_AARCH64_PREL16, 262)
+
+/* Group relocations to create a 16, 32, 48 or 64 bit
+   unsigned data or abs address inline. */
+
+/* MOV[ZK]:   ((S+A) >>  0) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G0,		263)
+
+/* MOV[ZK]:   ((S+A) >>  0) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G0_NC, 264)
+
+/* MOV[ZK]:   ((S+A) >> 16) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G1, 265)
+
+/* MOV[ZK]:   ((S+A) >> 16) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G1_NC, 266)
+
+/* MOV[ZK]:   ((S+A) >> 32) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G2, 267)
+
+/* MOV[ZK]:   ((S+A) >> 32) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G2_NC, 268)
+
+/* MOV[ZK]:   ((S+A) >> 48) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G3, 269)
+
+/* Group relocations to create high part of a 16, 32, 48 or 64 bit
+   signed data or abs address inline. Will change instruction
+   to MOVN or MOVZ depending on sign of calculated value. */
+
+/* MOV[ZN]:   ((S+A) >>  0) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_SABS_G0, 270)
+
+/* MOV[ZN]:   ((S+A) >> 16) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_SABS_G1, 271)
+
+/* MOV[ZN]:   ((S+A) >> 32) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_SABS_G2, 272)
+
+/* Relocations to generate 19, 21 and 33 bit PC-relative load/store
+   addresses: PG(x) is (x & ~0xfff). */
+
+/* LD-lit: ((S+A-P) >> 2) & 0x7ffff */
+RELOC_NUMBER (R_AARCH64_LD_PREL_LO19, 273)
+
+/* ADR:    (S+A-P) & 0x1fffff */
+RELOC_NUMBER (R_AARCH64_ADR_PREL_LO21, 274)
+
+/* ADRH:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+RELOC_NUMBER (R_AARCH64_ADR_PREL_PG_HI21, 275)
+
+/* ADRH:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+RELOC_NUMBER (R_AARCH64_ADR_PREL_PG_HI21_NC, 276)
+
+/* ADD:    (S+A) & 0xfff */
+RELOC_NUMBER (R_AARCH64_ADD_ABS_LO12_NC, 277)
+
+/* LD/ST8: (S+A) & 0xfff */
+RELOC_NUMBER (R_AARCH64_LDST8_ABS_LO12_NC, 278)
+
+/* Relocations for control-flow instructions. */
+
+/* TBZ/NZ: ((S+A-P) >> 2) & 0x3fff */
+RELOC_NUMBER (R_AARCH64_TSTBR14, 279)
+
+/* B.cond: ((S+A-P) >> 2) & 0x7ffff */
+RELOC_NUMBER (R_AARCH64_CONDBR19, 280)
+
+/* 281 unused */
+
+/* B:      ((S+A-P) >> 2) & 0x3ffffff */
+RELOC_NUMBER (R_AARCH64_JUMP26, 282)
+
+/* BL:     ((S+A-P) >> 2) & 0x3ffffff */
+RELOC_NUMBER (R_AARCH64_CALL26, 283)
+
+/* LD/ST16: (S+A) & 0xffe */
+RELOC_NUMBER (R_AARCH64_LDST16_ABS_LO12_NC, 284)
+
+/* LD/ST32: (S+A) & 0xffc */
+RELOC_NUMBER (R_AARCH64_LDST32_ABS_LO12_NC, 285)
+
+/* LD/ST64: (S+A) & 0xff8 */
+RELOC_NUMBER (R_AARCH64_LDST64_ABS_LO12_NC, 286)
+
+/* LD/ST128: (S+A) & 0xff0 */
+RELOC_NUMBER (R_AARCH64_LDST128_ABS_LO12_NC, 299)
+
+RELOC_NUMBER (R_AARCH64_ADR_GOT_PAGE, 311)
+RELOC_NUMBER (R_AARCH64_LD64_GOT_LO12_NC, 312)
+
+FAKE_RELOC (R_AARCH64_static_max, 313)
+
+FAKE_RELOC (R_AARCH64_tls_min, 512)
+RELOC_NUMBER (R_AARCH64_TLSGD_ADR_PAGE21, 513)
+RELOC_NUMBER (R_AARCH64_TLSGD_ADD_LO12_NC, 514)
+RELOC_NUMBER (R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 539)
+RELOC_NUMBER (R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 540)
+RELOC_NUMBER (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 541)
+RELOC_NUMBER (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 542)
+RELOC_NUMBER (R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 543)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G2, 544)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G1, 545)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 546)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G0, 547)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 548)
+RELOC_NUMBER (R_AARCH64_TLSLE_ADD_TPREL_HI12, 549)
+RELOC_NUMBER (R_AARCH64_TLSLE_ADD_TPREL_LO12, 550)
+RELOC_NUMBER (R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 551)
+FAKE_RELOC (R_AARCH64_tls_max, 552)
+
+FAKE_RELOC (R_AARCH64_tlsdesc_min, 560)
+RELOC_NUMBER (R_AARCH64_TLSDESC_LD64_PREL19, 560)
+RELOC_NUMBER (R_AARCH64_TLSDESC_ADR_PREL21, 561)
+RELOC_NUMBER (R_AARCH64_TLSDESC_ADR_PAGE, 562)
+RELOC_NUMBER (R_AARCH64_TLSDESC_LD64_LO12_NC, 563)
+RELOC_NUMBER (R_AARCH64_TLSDESC_ADD_LO12_NC, 564)
+RELOC_NUMBER (R_AARCH64_TLSDESC_OFF_G1, 565)
+RELOC_NUMBER (R_AARCH64_TLSDESC_OFF_G0_NC, 566)
+RELOC_NUMBER (R_AARCH64_TLSDESC_LDR, 567)
+RELOC_NUMBER (R_AARCH64_TLSDESC_ADD, 568)
+RELOC_NUMBER (R_AARCH64_TLSDESC_CALL, 569)
+FAKE_RELOC (R_AARCH64_tlsdesc_max, 570)
+
+/* Dynamic relocations */
+FAKE_RELOC (R_AARCH64_dyn_min, 1024)
+
+/* Copy symbol at runtime.  */
+RELOC_NUMBER (R_AARCH64_COPY, 1024)
+
+/* Create GOT entry.  */
+RELOC_NUMBER (R_AARCH64_GLOB_DAT, 1025)
+
+ /* Create PLT entry.  */
+RELOC_NUMBER (R_AARCH64_JUMP_SLOT, 1026)
+
+/* Adjust by program base.  */
+RELOC_NUMBER (R_AARCH64_RELATIVE, 1027)
+RELOC_NUMBER (R_AARCH64_TLS_DTPMOD64, 1028)
+RELOC_NUMBER (R_AARCH64_TLS_DTPREL64, 1029)
+RELOC_NUMBER (R_AARCH64_TLS_TPREL64, 1030)
+RELOC_NUMBER (R_AARCH64_TLSDESC, 1031)
+FAKE_RELOC (R_AARCH64_dyn_max, 1032)
+
+END_RELOC_NUMBERS (R_AARCH64_end)
+
+#endif /* _ELF_AARCH64_H */
diff --git a/include/elf/common.h b/include/elf/common.h
index 58e489a..1c681d5 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -287,8 +287,8 @@
 #define EM_L1OM		180	/* Intel L1OM */
 #define EM_K1OM		181	/* Intel K1OM */
 #define EM_INTEL182	182	/* Reserved by Intel */
-#define EM_res183	183	/* Reserved by ARM */
-#define EM_res184	184	/* Reserved by ARM */
+#define EM_AARCH64	183	/* ARM 64-bit architecture */
+#define EM_ARM184	184	/* Reserved by ARM */
 #define EM_AVR32	185	/* Atmel Corporation 32-bit microprocessor family */
 #define EM_STM8	186	/* STMicroeletronics STM8 8-bit microcontroller */
 #define EM_TILE64	187	/* Tilera TILE64 multicore architecture family */
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index b7271cc..49f9662 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -71,6 +71,7 @@ BFD64_LIBS_CFILES = archive64.c
 # This list is alphabetized to make it easier to keep in sync
 # with the decls and initializer in archures.c.
 ALL_MACHINES = \
+	cpu-aarch64.lo \
 	cpu-alpha.lo \
 	cpu-arc.lo \
 	cpu-arm.lo \
@@ -151,6 +152,7 @@ ALL_MACHINES = \
 	cpu-z8k.lo
 
 ALL_MACHINES_CFILES = \
+	cpu-aarch64.c \
 	cpu-alpha.c \
 	cpu-arc.c \
 	cpu-arm.c \
@@ -613,6 +615,7 @@ BFD32_BACKENDS_CFILES = \
 # elf32-ia64.c requires a 64-bit bfd_vma, and hence can not be put in
 # BFD32_BACKENDS.
 BFD64_BACKENDS = \
+	elf64-aarch64.lo \
 	aix5ppc-core.lo \
 	aout64.lo \
 	coff-alpha.lo \
@@ -651,6 +654,7 @@ BFD64_BACKENDS = \
 	vms-alpha.lo
 
 BFD64_BACKENDS_CFILES = \
+	elf64-aarch64.c \
 	aix5ppc-core.c \
 	aout64.c \
 	coff-alpha.c \
diff --git a/bfd/archures.c b/bfd/archures.c
index a23534b..3198436 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -461,6 +461,8 @@ DESCRIPTION
 .#define bfd_mach_tilepro   1
 .#define bfd_mach_tilegx    1
 .#define bfd_mach_tilegx32  2
+.  bfd_arch_aarch64,   {* AArch64  *}
+.#define bfd_mach_aarch64 0
 .  bfd_arch_last
 .  };
 */
@@ -505,6 +507,7 @@ DESCRIPTION
 .
 */
 
+extern const bfd_arch_info_type bfd_aarch64_arch;
 extern const bfd_arch_info_type bfd_alpha_arch;
 extern const bfd_arch_info_type bfd_arc_arch;
 extern const bfd_arch_info_type bfd_arm_arch;
@@ -590,6 +593,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
 #ifdef SELECT_ARCHITECTURES
     SELECT_ARCHITECTURES,
 #else
+    &bfd_aarch64_arch,
     &bfd_alpha_arch,
     &bfd_arc_arch,
     &bfd_arm_arch,
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 5300b14..a8c2db1 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -928,6 +928,32 @@ extern unsigned int _bfd_elf_ppc_at_tls_transform
 extern unsigned int _bfd_elf_ppc_at_tprel_transform
   (unsigned int, unsigned int);
 
+extern void bfd_elf64_aarch64_init_maps
+  (bfd *);
+
+void bfd_elf64_aarch64_set_options
+  (bfd *, struct bfd_link_info *, int, int, int);
+
+/* ELF AArch64 mapping symbol support.  */
+#define BFD_AARCH64_SPECIAL_SYM_TYPE_MAP	(1 << 0)
+#define BFD_AARCH64_SPECIAL_SYM_TYPE_TAG	(1 << 1)
+#define BFD_AARCH64_SPECIAL_SYM_TYPE_OTHER	(1 << 2)
+#define BFD_AARCH64_SPECIAL_SYM_TYPE_ANY	(~0)
+extern bfd_boolean bfd_is_aarch64_special_symbol_name
+  (const char * name, int type);
+
+/* AArch64 stub generation support.  Called from the linker.  */
+extern int elf64_aarch64_setup_section_lists
+  (bfd *, struct bfd_link_info *);
+extern void elf64_aarch64_next_input_section
+  (struct bfd_link_info *, struct bfd_section *);
+extern bfd_boolean elf64_aarch64_size_stubs
+  (bfd *, bfd *, struct bfd_link_info *, bfd_signed_vma,
+   struct bfd_section * (*) (const char *, struct bfd_section *),
+   void (*) (void));
+extern bfd_boolean elf64_aarch64_build_stubs
+  (struct bfd_link_info *);
+  
 /* TI COFF load page support.  */
 extern void bfd_ticoff_set_section_load_page
   (struct bfd_section *, int);
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 783d1f3..4b9ee4a 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -69,6 +69,7 @@ esac
 
 targ_cpu=`echo $targ | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
 case "${targ_cpu}" in
+aarch64*)	 targ_archs="bfd_aarch64_arch bfd_arm_arch";;
 alpha*)		 targ_archs=bfd_alpha_arch ;;
 am34*|am33_2.0*) targ_archs=bfd_mn10300_arch ;;
 arm*)		 targ_archs=bfd_arm_arch ;;
@@ -143,6 +144,26 @@ case "${targ}" in
 
 # START OF targmatch.h
 #ifdef BFD64
+  aarch64-*-elf)
+    targ_defvec=bfd_elf64_littleaarch64_vec
+    targ_selvecs="bfd_elf64_bigaarch64_vec bfd_elf32_littlearm_vec bfd_elf32_bigarm_vec"
+    want64=true
+    ;;
+  aarch64_be-*-elf)
+    targ_defvec=bfd_elf64_bigaarch64_vec
+    targ_selvecs="bfd_elf64_littleaarch64_vec bfd_elf32_bigarm_vec bfd_elf32_littlearm_vec"
+    want64=true
+    ;;
+  aarch64-*-linux*)
+    targ_defvec=bfd_elf64_littleaarch64_vec
+    targ_selvecs="bfd_elf64_bigaarch64_vec bfd_elf32_littlearm_vec bfd_elf32_bigarm_vec"
+    want64=true
+    ;;
+  aarch64_be-*-linux*)
+    targ_defvec=bfd_elf64_bigaarch64_vec
+    targ_selvecs="bfd_elf64_littleaarch64_vec bfd_elf32_bigarm_vec bfd_elf32_littlearm_vec"
+    want64=true
+    ;;
   alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
     targ_defvec=bfd_elf64_alpha_freebsd_vec
     targ_selvecs="bfd_elf64_alpha_vec ecoffalpha_little_vec"
diff --git a/bfd/configure.in b/bfd/configure.in
index 5922961..947c389 100644
--- a/bfd/configure.in
+++ b/bfd/configure.in
@@ -832,6 +832,7 @@ do
     bfd_elf32_xtensa_be_vec)	tb="$tb xtensa-isa.lo xtensa-modules.lo elf32-xtensa.lo elf32.lo $elf" ;;
     bfd_elf64_alpha_freebsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_alpha_vec)	tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
+    bfd_elf64_bigaarch64_vec)	tb="$tb elf64-aarch64.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_big_generic_vec) 	tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_bigmips_vec) 	tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
     bfd_elf64_hppa_linux_vec)	tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;;
@@ -840,6 +841,7 @@ do
     bfd_elf64_ia64_hpux_big_vec) tb="$tb elf64-ia64.lo elfxx-ia64.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_ia64_little_vec)	tb="$tb elf64-ia64.lo elfxx-ia64.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_ia64_vms_vec)	tb="$tb elf64-ia64-vms.lo elf64-ia64.lo elfxx-ia64.lo elf64.lo vms-lib.lo vms-misc.lo $elf"; target_size=64 ;;    
+    bfd_elf64_littleaarch64_vec)tb="$tb elf64-aarch64.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_little_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_littlemips_vec) 	tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
     bfd_elf64_mmix_vec) 	tb="$tb elf64-mmix.lo elf64.lo $elf" target_size=64 ;;
diff --git a/bfd/cpu-aarch64.c b/bfd/cpu-aarch64.c
new file mode 100644
index 0000000..fde409b
--- /dev/null
+++ b/bfd/cpu-aarch64.c
@@ -0,0 +1,117 @@
+/* BFD support for AArch64.
+   Copyright 2009, 2010, 2011, 2012  Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING3. If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "libiberty.h"
+
+/* This routine is provided two arch_infos and works out which Aarch64
+   machine which would be compatible with both and returns a pointer
+   to its info structure.  */
+
+static const bfd_arch_info_type *
+compatible (const bfd_arch_info_type * a, const bfd_arch_info_type * b)
+{
+  /* If a & b are for different architecture we can do nothing.  */
+  if (a->arch != b->arch)
+    return NULL;
+
+  /* If a & b are for the same machine then all is well.  */
+  if (a->mach == b->mach)
+    return a;
+
+  /* Otherwise if either a or b is the 'default' machine
+     then it can be polymorphed into the other.  */
+  if (a->the_default)
+    return b;
+
+  if (b->the_default)
+    return a;
+
+  /* So far all newer cores are
+     supersets of previous cores.  */
+  if (a->mach < b->mach)
+    return b;
+  else if (a->mach > b->mach)
+    return a;
+
+  /* Never reached!  */
+  return NULL;
+}
+
+static struct
+{
+  unsigned int mach;
+  char *name;
+}
+processors[] =
+{
+};
+
+static bfd_boolean
+scan (const struct bfd_arch_info *info, const char *string)
+{
+  int i;
+
+  /* First test for an exact match.  */
+  if (strcasecmp (string, info->printable_name) == 0)
+    return TRUE;
+
+  /* Next check for a processor name instead of an Architecture name.  */
+  for (i = sizeof (processors) / sizeof (processors[0]); i--;)
+    {
+      if (strcasecmp (string, processors[i].name) == 0)
+	break;
+    }
+
+  if (i != -1 && info->mach == processors[i].mach)
+    return TRUE;
+
+  /* Finally check for the default architecture.  */
+  if (strcasecmp (string, "aarch64") == 0)
+    return info->the_default;
+
+  return FALSE;
+}
+
+#define N(NUMBER, PRINT, DEFAULT, NEXT)				\
+  { 64, 64, 8, bfd_arch_aarch64, NUMBER,			\
+    "aarch64", PRINT, 4, DEFAULT, compatible, scan,		\
+    bfd_arch_default_fill, NEXT }
+
+const bfd_arch_info_type bfd_aarch64_arch =
+  N (0, "aarch64", TRUE, NULL);
+
+
+bfd_boolean
+bfd_is_aarch64_special_symbol_name (const char *name, int type)
+{
+  if (!name || name[0] != '$')
+    return FALSE;
+  if (name[1] == 'x' || name[1] == 'd')
+    type &= BFD_AARCH64_SPECIAL_SYM_TYPE_MAP;
+  else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
+    type &= BFD_AARCH64_SPECIAL_SYM_TYPE_TAG;
+  else
+    return FALSE;
+
+  return (type != 0 && (name[2] == 0 || name[2] == '.'));
+}
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 889ce12..5a11483 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -402,7 +402,8 @@ struct eh_frame_hdr_info
    one line.  */
 enum elf_target_id
 {
-  ALPHA_ELF_DATA = 1,
+  AARCH64_ELF_DATA = 1,
+  ALPHA_ELF_DATA,
   ARM_ELF_DATA,
   AVR_ELF_DATA,
   BFIN_ELF_DATA,
diff --git a/bfd/elf64-aarch64.c b/bfd/elf64-aarch64.c
new file mode 100644
index 0000000..290e087
--- /dev/null
+++ b/bfd/elf64-aarch64.c
@@ -0,0 +1,7010 @@
+/* ELF support for AArch64.
+   Copyright 2009, 2010, 2011, 2012  Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING3. If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+/* Notes on implementation:
+
+  Thread Local Store (TLS)
+
+  Overview:
+
+  The implementation currently supports both traditional TLS and TLS
+  descriptors, but only general dynamic (GD).
+
+  For traditional TLS the assembler will present us with code
+  fragments of the form:
+
+  adrp x0, :tlsgd:foo
+                           R_AARCH64_TLSGD_ADR_PAGE21(foo)
+  add  x0, :tlsgd_lo12:foo
+                           R_AARCH64_TLSGD_ADD_LO12_NC(foo)
+  bl   __tls_get_addr
+  nop
+
+  For TLS descriptors the assembler will present us with code
+  fragments of the form:
+
+  adrp  x0, :tlsdesc:foo                      R_AARCH64_TLSDESC_ADR_PAGE(foo)
+  ldr   x1, [x0, #:tlsdesc_lo12:foo]          R_AARCH64_TLSDESC_LD64_LO12(foo)
+  add   x0, x0, #:tlsdesc_lo12:foo            R_AARCH64_TLSDESC_ADD_LO12(foo)
+  .tlsdesccall foo
+  blr   x1                                    R_AARCH64_TLSDESC_CALL(foo)
+
+  The relocations R_AARCH64_TLSGD_{ADR_PREL21,ADD_LO12_NC} against foo
+  indicate that foo is thread local and should be accessed via the
+  traditional TLS mechanims.
+
+  The relocations R_AARCH64_TLSDESC_{ADR_PAGE,LD64_LO12_NC,ADD_LO12_NC}
+  against foo indicate that 'foo' is thread local and should be accessed
+  via a TLS descriptor mechanism.
+
+  The precise instruction sequence is only relevant from the
+  perspective of linker relaxation which is currently not implemented.
+
+  The static linker must detect that 'foo' is a TLS object and
+  allocate a double GOT entry. The GOT entry must be created for both
+  global and local TLS symbols. Note that this is different to none
+  TLS local objects which do not need a GOT entry.
+
+  In the traditional TLS mechanism, the double GOT entry is used to
+  provide the tls_index structure, containing module and offset
+  entries. The static linker places the relocation R_AARCH64_TLS_DTPMOD64
+  on the module entry. The loader will subsequently fixup this
+  relocation with the module identity.
+
+  For global traditional TLS symbols the static linker places an
+  R_AARCH64_TLS_DTPREL64 relocation on the offset entry. The loader
+  will subsequently fixup the offset. For local TLS symbols the static
+  linker fixes up offset.
+
+  In the TLS descriptor mechanism the double GOT entry is used to
+  provide the descriptor. The static linker places the relocation
+  R_AARCH64_TLSDESC on the first GOT slot. The loader will
+  subsequently fix this up.
+
+  Implementation:
+
+  The handling of TLS symbols is implemented across a number of
+  different backend functions. The following is a top level view of
+  what processing is performed where.
+
+  The TLS implementation maintains state information for each TLS
+  symbol. The state information for local and global symbols is kept
+  in different places. Global symbols use generic BFD structures while
+  local symbols use backend specific structures that are allocated and
+  maintained entirely by the backend.
+
+  The flow:
+
+  aarch64_check_relocs()
+
+  This function is invoked for each relocation.
+
+  The TLS relocations R_AARCH64_TLSGD_{ADR_PREL21,ADD_LO12_NC} and
+  R_AARCH64_TLSDESC_{ADR_PAGE,LD64_LO12_NC,ADD_LO12_NC} are
+  spotted. One time creation of local symbol data structures are
+  created when the first local symbol is seen.
+
+  The reference count for a symbol is incremented.  The GOT type for
+  each symbol is marked as general dynamic.
+
+  elf64_aarch64_allocate_dynrelocs ()
+
+  For each global with positive reference count we allocate a double
+  GOT slot. For a traditional TLS symbol we allocate space for two
+  relocation entries on the GOT, for a TLS descriptor symbol we
+  allocate space for one relocation on the slot. Record the GOT offset
+  for this symbol.
+
+  elf64_aarch64_size_dynamic_sections ()
+
+  Iterate all input BFDS, look for in the local symbol data structure
+  constructed earlier for local TLS symbols and allocate them double
+  GOT slots along with space for a single GOT relocation. Update the
+  local symbol structure to record the GOT offset allocated.
+
+  elf64_aarch64_relocate_section ()
+
+  Calls elf64_aarch64_final_link_relocate ()
+
+  Emit the relevant TLS relocations against the GOT for each TLS
+  symbol. For local TLS symbols emit the GOT offset directly. The GOT
+  relocations are emitted once the first time a TLS symbol is
+  encountered. The implementation uses the LSB of the GOT offset to
+  flag that the relevant GOT relocations for a symbol have been
+  emitted. All of the TLS code that uses the GOT offset needs to take
+  care to mask out this flag bit before using the offset.
+
+  elf64_aarch64_final_link_relocate ()
+
+  Fixup the R_AARCH64_TLSGD_{ADR_PREL21, ADD_LO12_NC} relocations.
+
+ */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libiberty.h"
+#include "libbfd.h"
+#include "bfd_stdint.h"
+#include "elf-bfd.h"
+#include "bfdlink.h"
+#include "elf/aarch64.h"
+
+static bfd_reloc_status_type
+bfd_elf_aarch64_put_addend (bfd * abfd,
+			    bfd_byte * address,
+			    reloc_howto_type * howto, bfd_signed_vma addend);
+
+#define IS_AARCH64_TLS_RELOC(R_TYPE)			\
+  ((R_TYPE) == R_AARCH64_TLSGD_ADR_PAGE21		\
+   || (R_TYPE) == R_AARCH64_TLSGD_ADD_LO12_NC		\
+   || (R_TYPE) == R_AARCH64_TLSIE_MOVW_GOTTPREL_G1	\
+   || (R_TYPE) == R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC	\
+   || (R_TYPE) == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21	\
+   || (R_TYPE) == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC	\
+   || (R_TYPE) == R_AARCH64_TLSIE_LD_GOTTPREL_PREL19	\
+   || (R_TYPE) == R_AARCH64_TLSLE_ADD_TPREL_LO12	\
+   || (R_TYPE) == R_AARCH64_TLSLE_ADD_TPREL_HI12	\
+   || (R_TYPE) == R_AARCH64_TLSLE_ADD_TPREL_LO12_NC	\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G2		\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G1		\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G1_NC	\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G0		\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G0_NC	\
+   || (R_TYPE) == R_AARCH64_TLS_DTPMOD64		\
+   || (R_TYPE) == R_AARCH64_TLS_DTPREL64		\
+   || (R_TYPE) == R_AARCH64_TLS_TPREL64			\
+   || IS_AARCH64_TLSDESC_RELOC ((R_TYPE)))
+
+#define IS_AARCH64_TLSDESC_RELOC(R_TYPE)		\
+  ((R_TYPE) == R_AARCH64_TLSDESC_LD64_PREL19		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_ADR_PREL21		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_ADR_PAGE		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_ADD_LO12_NC		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_LD64_LO12_NC	\
+   || (R_TYPE) == R_AARCH64_TLSDESC_OFF_G1		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_OFF_G0_NC		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_LDR			\
+   || (R_TYPE) == R_AARCH64_TLSDESC_ADD			\
+   || (R_TYPE) == R_AARCH64_TLSDESC_CALL		\
+   || (R_TYPE) == R_AARCH64_TLSDESC)
+
+#define ELIMINATE_COPY_RELOCS 0
+
+/* Return the relocation section associated with NAME.  HTAB is the
+   bfd's elf64_aarch64_link_hash_entry.  */
+#define RELOC_SECTION(HTAB, NAME) \
+  ((HTAB)->use_rel ? ".rel" NAME : ".rela" NAME)
+
+/* Return size of a relocation entry.  HTAB is the bfd's
+   elf64_aarch64_link_hash_entry.  */
+#define RELOC_SIZE(HTAB) (sizeof (Elf64_External_Rela))
+
+/* Return function to swap relocations in.  HTAB is the bfd's
+   elf64_aarch64_link_hash_entry.  */
+#define SWAP_RELOC_IN(HTAB) (bfd_elf64_swap_reloca_in)
+
+/* Return function to swap relocations out.  HTAB is the bfd's
+   elf64_aarch64_link_hash_entry.  */
+#define SWAP_RELOC_OUT(HTAB) (bfd_elf64_swap_reloca_out)
+
+/* GOT Entry size - 8 bytes.  */
+#define GOT_ENTRY_SIZE                  (8)
+#define PLT_ENTRY_SIZE                  (32)
+#define PLT_SMALL_ENTRY_SIZE            (16)
+#define PLT_TLSDESC_ENTRY_SIZE          (32)
+
+/* Take the PAGE component of an address or offset. */
+#define PG(x) ((x) & ~ 0xfff)
+#define PG_OFFSET(x) ((x) & 0xfff)
+
+/* Encoding of the nop instruction */
+#define INSN_NOP 0xd503201f
+
+#define aarch64_compute_jump_table_size(htab)		\
+  (((htab)->root.srelplt == NULL) ? 0			\
+   : (htab)->root.srelplt->reloc_count * GOT_ENTRY_SIZE)
+
+/* The first entry in a procedure linkage table looks like this
+   if the distance between the PLTGOT and the PLT is < 4GB use
+   these PLT entries. Note that the dynamic linker gets &PLTGOT[2]
+   in x16 and needs to work out PLTGOT[1] by using an address of
+   [x16,#-8].  */
+static const bfd_byte elf64_aarch64_small_plt0_entry[PLT_ENTRY_SIZE] = {
+  0xf0, 0x7b, 0xbf, 0xa9,	/* stp x16, x30, [sp, #-16]!  */
+  0x10, 0x00, 0x00, 0x90,	/* adrp x16, (GOT+16)  */
+  0x11, 0x0A, 0x40, 0xf9,	/* ldr x17, [x16, #PLT_GOT+0x10]  */
+  0x10, 0x42, 0x00, 0x91,	/* add x16, x16,#PLT_GOT+0x10   */
+  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
+   if the distance between the PLTGOT and the PLT is < 4GB use
+   these PLT entries.  */
+static const bfd_byte elf64_aarch64_small_plt_entry[PLT_SMALL_ENTRY_SIZE] = {
+  0x10, 0x00, 0x00, 0x90,	/* adrp x16, PLTGOT + n * 8  */
+  0x11, 0x02, 0x40, 0xf9,	/* ldr x17, [x16, PLTGOT + n * 8] */
+  0x10, 0x02, 0x00, 0x91,	/* add x16, x16, :lo12:PLTGOT + n * 8  */
+  0x20, 0x02, 0x1f, 0xd6,	/* br x17.  */
+};
+
+static const bfd_byte
+  elf64_aarch64_tlsdesc_small_plt_entry[PLT_TLSDESC_ENTRY_SIZE] = {
+  0xe2, 0x0f, 0xbf, 0xa9,	/* stp x2, x3, [sp, #-16]! */
+  0x02, 0x00, 0x00, 0x90,	/* adrp x2, 0 */
+  0x03, 0x00, 0x00, 0x90,	/* adrp x3, 0 */
+  0x42, 0x08, 0x40, 0xF9,	/* ldr x2, [x2, #0] */
+  0x63, 0x00, 0x00, 0x91,	/* add x3, x3, 0 */
+  0x40, 0x00, 0x1F, 0xD6,	/* br x2 */
+  0x1f, 0x20, 0x03, 0xd5,	/* nop */
+  0x1f, 0x20, 0x03, 0xd5,	/* nop */
+};
+
+#define elf_info_to_howto               elf64_aarch64_info_to_howto
+#define elf_info_to_howto_rel           elf64_aarch64_info_to_howto
+
+#define AARCH64_ELF_ABI_VERSION		0
+#define AARCH64_ELF_OS_ABI_VERSION	0
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
+#define ALL_ONES (~ (bfd_vma) 0)
+
+static reloc_howto_type elf64_aarch64_howto_none =
+  HOWTO (R_AARCH64_NONE,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_NONE",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 FALSE);		/* pcrel_offset */
+
+static reloc_howto_type elf64_aarch64_howto_dynrelocs[] = {
+
+  HOWTO (R_AARCH64_COPY,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_COPY",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_GLOB_DAT,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_GLOB_DAT",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_JUMP_SLOT,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_JUMP_SLOT",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_RELATIVE,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_RELATIVE",	/* name */
+	 TRUE,			/* partial_inplace */
+	 ALL_ONES,		/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLS_DTPMOD64,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLS_DTPMOD64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pc_reloffset */
+
+  HOWTO (R_AARCH64_TLS_DTPREL64,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLS_DTPREL64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLS_TPREL64,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLS_TPREL64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+};
+
+/* Note: code such as elf64_aarch64_reloc_type_lookup expect to use e.g.
+   R_AARCH64_PREL64 as an index into this, and find the R_AARCH64_PREL64 HOWTO
+   in that slot.  */
+
+static reloc_howto_type elf64_aarch64_howto_table[] = {
+  /* Basic data relocations. */
+
+  HOWTO (R_AARCH64_NULL,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_NULL",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* .xword: (S+A) */
+  HOWTO (R_AARCH64_ABS64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (4 = long long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ABS64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 ALL_ONES,		/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* .word: (S+A) */
+  HOWTO (R_AARCH64_ABS32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ABS32",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* .half:  (S+A) */
+  HOWTO (R_AARCH64_ABS16,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ABS16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* .xword: (S+A-P) */
+  HOWTO (R_AARCH64_PREL64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (4 = long long) */
+	 64,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_PREL64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 ALL_ONES,		/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* .word: (S+A-P) */
+  HOWTO (R_AARCH64_PREL32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_PREL32",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* .half: (S+A-P) */
+  HOWTO (R_AARCH64_PREL16,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_PREL16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* Group relocations to create a 16, 32, 48 or 64 bit
+     unsigned data or abs address inline. */
+
+  /* MOVZ:   ((S+A) >>  0) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_UABS_G0,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G0",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVK:   ((S+A) >>  0) & 0xffff [no overflow check] */
+  HOWTO (R_AARCH64_MOVW_UABS_G0_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G0_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVZ:   ((S+A) >> 16) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_UABS_G1,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVK:   ((S+A) >> 16) & 0xffff [no overflow check] */
+  HOWTO (R_AARCH64_MOVW_UABS_G1_NC,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G1_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVZ:   ((S+A) >> 32) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_UABS_G2,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVK:   ((S+A) >> 32) & 0xffff [no overflow check] */
+  HOWTO (R_AARCH64_MOVW_UABS_G2_NC,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G2_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVZ:   ((S+A) >> 48) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_UABS_G3,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G3",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* Group relocations to create high part of a 16, 32, 48 or 64 bit
+     signed data or abs address inline. Will change instruction
+     to MOVN or MOVZ depending on sign of calculated value. */
+
+  /* MOV[ZN]:   ((S+A) >>  0) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_SABS_G0,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_SABS_G0",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOV[ZN]:   ((S+A) >> 16) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_SABS_G1,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_SABS_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOV[ZN]:   ((S+A) >> 32) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_SABS_G2,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_SABS_G2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+/* Relocations to generate 19, 21 and 33 bit PC-relative load/store
+   addresses: PG(x) is (x & ~0xfff). */
+
+  /* LD-lit: ((S+A-P) >> 2) & 0x7ffff */
+  HOWTO (R_AARCH64_LD_PREL_LO19,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LD_PREL_LO19",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x7ffff,		/* src_mask */
+	 0x7ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADR:    (S+A-P) & 0x1fffff */
+  HOWTO (R_AARCH64_ADR_PREL_LO21,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ADR_PREL_LO21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+  HOWTO (R_AARCH64_ADR_PREL_PG_HI21,	/* type */
+	 12,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ADR_PREL_PG_HI21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff [no overflow check] */
+  HOWTO (R_AARCH64_ADR_PREL_PG_HI21_NC,	/* type */
+	 12,			/* 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 */
+	 "R_AARCH64_ADR_PREL_PG_HI21_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADD:    (S+A) & 0xfff [no overflow check] */
+  HOWTO (R_AARCH64_ADD_ABS_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ADD_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x3ffc00,		/* src_mask */
+	 0x3ffc00,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* LD/ST8:  (S+A) & 0xfff */
+  HOWTO (R_AARCH64_LDST8_ABS_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST8_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* Relocations for control-flow instructions. */
+
+  /* TBZ/NZ: ((S+A-P) >> 2) & 0x3fff */
+  HOWTO (R_AARCH64_TSTBR14,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 14,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TSTBR14",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x3fff,		/* src_mask */
+	 0x3fff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* B.cond: ((S+A-P) >> 2) & 0x7ffff */
+  HOWTO (R_AARCH64_CONDBR19,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_CONDBR19",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x7ffff,		/* src_mask */
+	 0x7ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  EMPTY_HOWTO (281),
+
+  /* B:      ((S+A-P) >> 2) & 0x3ffffff */
+  HOWTO (R_AARCH64_JUMP26,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_JUMP26",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x3ffffff,		/* src_mask */
+	 0x3ffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* BL:     ((S+A-P) >> 2) & 0x3ffffff */
+  HOWTO (R_AARCH64_CALL26,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_CALL26",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x3ffffff,		/* src_mask */
+	 0x3ffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* LD/ST16:  (S+A) & 0xffe */
+  HOWTO (R_AARCH64_LDST16_ABS_LO12_NC,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST16_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffe,			/* src_mask */
+	 0xffe,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* LD/ST32:  (S+A) & 0xffc */
+  HOWTO (R_AARCH64_LDST32_ABS_LO12_NC,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST32_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffc,			/* src_mask */
+	 0xffc,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* LD/ST64:  (S+A) & 0xff8 */
+  HOWTO (R_AARCH64_LDST64_ABS_LO12_NC,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST64_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xff8,			/* src_mask */
+	 0xff8,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (287),
+  EMPTY_HOWTO (288),
+  EMPTY_HOWTO (289),
+  EMPTY_HOWTO (290),
+  EMPTY_HOWTO (291),
+  EMPTY_HOWTO (292),
+  EMPTY_HOWTO (293),
+  EMPTY_HOWTO (294),
+  EMPTY_HOWTO (295),
+  EMPTY_HOWTO (296),
+  EMPTY_HOWTO (297),
+  EMPTY_HOWTO (298),
+
+  /* LD/ST128:  (S+A) & 0xff0 */
+  HOWTO (R_AARCH64_LDST128_ABS_LO12_NC,	/* type */
+	 4,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST128_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xff0,			/* src_mask */
+	 0xff0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (300),
+  EMPTY_HOWTO (301),
+  EMPTY_HOWTO (302),
+  EMPTY_HOWTO (303),
+  EMPTY_HOWTO (304),
+  EMPTY_HOWTO (305),
+  EMPTY_HOWTO (306),
+  EMPTY_HOWTO (307),
+  EMPTY_HOWTO (308),
+  EMPTY_HOWTO (309),
+  EMPTY_HOWTO (310),
+
+  /* Get to the page for the GOT entry for the symbol
+     (G(S) - P) using an ADRP instruction.  */
+  HOWTO (R_AARCH64_ADR_GOT_PAGE,	/* type */
+	 12,			/* 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 */
+	 "R_AARCH64_ADR_GOT_PAGE",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* LD64: GOT offset G(S) & 0xff8 */
+  HOWTO (R_AARCH64_LD64_GOT_LO12_NC,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LD64_GOT_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xff8,			/* src_mask */
+	 0xff8,			/* dst_mask */
+	 FALSE)			/* pcrel_offset */
+};
+
+static reloc_howto_type elf64_aarch64_tls_howto_table[] = {
+  EMPTY_HOWTO (512),
+
+  /* Get to the page for the GOT entry for the symbol
+     (G(S) - P) using an ADRP instruction.  */
+  HOWTO (R_AARCH64_TLSGD_ADR_PAGE21,	/* type */
+	 12,			/* 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 */
+	 "R_AARCH64_TLSGD_ADR_PAGE21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADD: GOT offset G(S) & 0xff8 [no overflow check] */
+  HOWTO (R_AARCH64_TLSGD_ADD_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSGD_ADD_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (515),
+  EMPTY_HOWTO (516),
+  EMPTY_HOWTO (517),
+  EMPTY_HOWTO (518),
+  EMPTY_HOWTO (519),
+  EMPTY_HOWTO (520),
+  EMPTY_HOWTO (521),
+  EMPTY_HOWTO (522),
+  EMPTY_HOWTO (523),
+  EMPTY_HOWTO (524),
+  EMPTY_HOWTO (525),
+  EMPTY_HOWTO (526),
+  EMPTY_HOWTO (527),
+  EMPTY_HOWTO (528),
+  EMPTY_HOWTO (529),
+  EMPTY_HOWTO (530),
+  EMPTY_HOWTO (531),
+  EMPTY_HOWTO (532),
+  EMPTY_HOWTO (533),
+  EMPTY_HOWTO (534),
+  EMPTY_HOWTO (535),
+  EMPTY_HOWTO (536),
+  EMPTY_HOWTO (537),
+  EMPTY_HOWTO (538),
+
+  HOWTO (R_AARCH64_TLSIE_MOVW_GOTTPREL_G1,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_MOVW_GOTTPREL_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21,	/* type */
+	 12,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xff8,			/* src_mask */
+	 0xff8,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSIE_LD_GOTTPREL_PREL19,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_LD_GOTTPREL_PREL19",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1ffffc,		/* src_mask */
+	 0x1ffffc,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G2,	/* type */
+	 8,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G1,	/* type */
+	 4,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G1_NC,	/* type */
+	 4,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G1_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G0,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G0",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G0_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G0_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_ADD_TPREL_HI12,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_ADD_TPREL_HI12",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_ADD_TPREL_LO12,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_ADD_TPREL_LO12",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_ADD_TPREL_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_ADD_TPREL_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+};
+
+static reloc_howto_type elf64_aarch64_tlsdesc_howto_table[] = {
+  HOWTO (R_AARCH64_TLSDESC_LD64_PREL19,	/* 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 */
+	 "R_AARCH64_TLSDESC_LD64_PREL19",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1ffffc,		/* src_mask */
+	 0x1ffffc,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_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 */
+	 "R_AARCH64_TLSDESC_ADR_PREL21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* Get to the page for the GOT entry for the symbol
+     (G(S) - P) using an ADRP instruction.  */
+  HOWTO (R_AARCH64_TLSDESC_ADR_PAGE,	/* type */
+	 12,			/* 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 */
+	 "R_AARCH64_TLSDESC_ADR_PAGE",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* LD64: GOT offset G(S) & 0xfff.  */
+  HOWTO (R_AARCH64_TLSDESC_LD64_LO12_NC,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_LD64_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* ADD: GOT offset G(S) & 0xfff.  */
+  HOWTO (R_AARCH64_TLSDESC_ADD_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_ADD_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_OFF_G1,	/* type */
+	 4,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_OFF_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_OFF_G0_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_OFF_G0_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_LDR,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_LDR",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_ADD,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_ADD",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_CALL,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_CALL",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+};
+
+static reloc_howto_type *
+elf64_aarch64_howto_from_type (unsigned int r_type)
+{
+  if (r_type >= R_AARCH64_static_min && r_type < R_AARCH64_static_max)
+    return &elf64_aarch64_howto_table[r_type - R_AARCH64_static_min];
+
+  if (r_type >= R_AARCH64_tls_min && r_type < R_AARCH64_tls_max)
+    return &elf64_aarch64_tls_howto_table[r_type - R_AARCH64_tls_min];
+
+  if (r_type >= R_AARCH64_tlsdesc_min && r_type < R_AARCH64_tlsdesc_max)
+    return &elf64_aarch64_tlsdesc_howto_table[r_type - R_AARCH64_tlsdesc_min];
+
+  if (r_type >= R_AARCH64_dyn_min && r_type < R_AARCH64_dyn_max)
+    return &elf64_aarch64_howto_dynrelocs[r_type - R_AARCH64_dyn_min];
+
+  switch (r_type)
+    {
+    case R_AARCH64_NONE:
+      return &elf64_aarch64_howto_none;
+
+    }
+  bfd_set_error (bfd_error_bad_value);
+  return NULL;
+}
+
+static void
+elf64_aarch64_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * bfd_reloc,
+			     Elf_Internal_Rela * elf_reloc)
+{
+  unsigned int r_type;
+
+  r_type = ELF64_R_TYPE (elf_reloc->r_info);
+  bfd_reloc->howto = elf64_aarch64_howto_from_type (r_type);
+}
+
+struct elf64_aarch64_reloc_map
+{
+  bfd_reloc_code_real_type bfd_reloc_val;
+  unsigned int elf_reloc_val;
+};
+
+/* All entries in this list must also be present in
+   elf64_aarch64_howto_table.  */
+static const struct elf64_aarch64_reloc_map elf64_aarch64_reloc_map[] = {
+  {BFD_RELOC_NONE, R_AARCH64_NONE},
+
+  /* Basic data relocations.  */
+  {BFD_RELOC_CTOR, R_AARCH64_ABS64},
+  {BFD_RELOC_64, R_AARCH64_ABS64},
+  {BFD_RELOC_32, R_AARCH64_ABS32},
+  {BFD_RELOC_16, R_AARCH64_ABS16},
+  {BFD_RELOC_64_PCREL, R_AARCH64_PREL64},
+  {BFD_RELOC_32_PCREL, R_AARCH64_PREL32},
+  {BFD_RELOC_16_PCREL, R_AARCH64_PREL16},
+
+  /* Group relocations to low order bits of a 16, 32, 48 or 64 bit
+     value inline.  */
+  {BFD_RELOC_AARCH64_MOVW_G0_NC, R_AARCH64_MOVW_UABS_G0_NC},
+  {BFD_RELOC_AARCH64_MOVW_G1_NC, R_AARCH64_MOVW_UABS_G1_NC},
+  {BFD_RELOC_AARCH64_MOVW_G2_NC, R_AARCH64_MOVW_UABS_G2_NC},
+
+  /* Group relocations to create high bits of a 16, 32, 48 or 64 bit
+     signed value inline.  */
+  {BFD_RELOC_AARCH64_MOVW_G0_S, R_AARCH64_MOVW_SABS_G0},
+  {BFD_RELOC_AARCH64_MOVW_G1_S, R_AARCH64_MOVW_SABS_G1},
+  {BFD_RELOC_AARCH64_MOVW_G2_S, R_AARCH64_MOVW_SABS_G2},
+
+  /* Group relocations to create high bits of a 16, 32, 48 or 64 bit
+     unsigned value inline.  */
+  {BFD_RELOC_AARCH64_MOVW_G0, R_AARCH64_MOVW_UABS_G0},
+  {BFD_RELOC_AARCH64_MOVW_G1, R_AARCH64_MOVW_UABS_G1},
+  {BFD_RELOC_AARCH64_MOVW_G2, R_AARCH64_MOVW_UABS_G2},
+  {BFD_RELOC_AARCH64_MOVW_G3, R_AARCH64_MOVW_UABS_G3},
+
+  /* Relocations to generate 19, 21 and 33 bit PC-relative load/store.  */
+  {BFD_RELOC_AARCH64_LD_LO19_PCREL, R_AARCH64_LD_PREL_LO19},
+  {BFD_RELOC_AARCH64_ADR_LO21_PCREL, R_AARCH64_ADR_PREL_LO21},
+  {BFD_RELOC_AARCH64_ADR_HI21_PCREL, R_AARCH64_ADR_PREL_PG_HI21},
+  {BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL, R_AARCH64_ADR_PREL_PG_HI21_NC},
+  {BFD_RELOC_AARCH64_ADD_LO12, R_AARCH64_ADD_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST8_LO12, R_AARCH64_LDST8_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST16_LO12, R_AARCH64_LDST16_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST32_LO12, R_AARCH64_LDST32_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST64_LO12, R_AARCH64_LDST64_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST128_LO12, R_AARCH64_LDST128_ABS_LO12_NC},
+
+  /* Relocations for control-flow instructions. */
+  {BFD_RELOC_AARCH64_TSTBR14, R_AARCH64_TSTBR14},
+  {BFD_RELOC_AARCH64_BRANCH19, R_AARCH64_CONDBR19},
+  {BFD_RELOC_AARCH64_JUMP26, R_AARCH64_JUMP26},
+  {BFD_RELOC_AARCH64_CALL26, R_AARCH64_CALL26},
+
+  /* Relocations for PIC.  */
+  {BFD_RELOC_AARCH64_ADR_GOT_PAGE, R_AARCH64_ADR_GOT_PAGE},
+  {BFD_RELOC_AARCH64_LD64_GOT_LO12_NC, R_AARCH64_LD64_GOT_LO12_NC},
+
+  /* Relocations for TLS. */
+  {BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21, R_AARCH64_TLSGD_ADR_PAGE21},
+  {BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC, R_AARCH64_TLSGD_ADD_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1,
+   R_AARCH64_TLSIE_MOVW_GOTTPREL_G1},
+  {BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC,
+   R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC},
+  {BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21,
+   R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21},
+  {BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC,
+   R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19,
+   R_AARCH64_TLSIE_LD_GOTTPREL_PREL19},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2, R_AARCH64_TLSLE_MOVW_TPREL_G2},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1, R_AARCH64_TLSLE_MOVW_TPREL_G1},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC,
+   R_AARCH64_TLSLE_MOVW_TPREL_G1_NC},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0, R_AARCH64_TLSLE_MOVW_TPREL_G0},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC,
+   R_AARCH64_TLSLE_MOVW_TPREL_G0_NC},
+  {BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12, R_AARCH64_TLSLE_ADD_TPREL_LO12},
+  {BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12, R_AARCH64_TLSLE_ADD_TPREL_HI12},
+  {BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC,
+   R_AARCH64_TLSLE_ADD_TPREL_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSDESC_LD64_PREL19, R_AARCH64_TLSDESC_LD64_PREL19},
+  {BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21, R_AARCH64_TLSDESC_ADR_PREL21},
+  {BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE, R_AARCH64_TLSDESC_ADR_PAGE},
+  {BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC, R_AARCH64_TLSDESC_ADD_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC, R_AARCH64_TLSDESC_LD64_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSDESC_OFF_G1, R_AARCH64_TLSDESC_OFF_G1},
+  {BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC, R_AARCH64_TLSDESC_OFF_G0_NC},
+  {BFD_RELOC_AARCH64_TLSDESC_LDR, R_AARCH64_TLSDESC_LDR},
+  {BFD_RELOC_AARCH64_TLSDESC_ADD, R_AARCH64_TLSDESC_ADD},
+  {BFD_RELOC_AARCH64_TLSDESC_CALL, R_AARCH64_TLSDESC_CALL},
+  {BFD_RELOC_AARCH64_TLS_DTPMOD64, R_AARCH64_TLS_DTPMOD64},
+  {BFD_RELOC_AARCH64_TLS_DTPREL64, R_AARCH64_TLS_DTPREL64},
+  {BFD_RELOC_AARCH64_TLS_TPREL64, R_AARCH64_TLS_TPREL64},
+  {BFD_RELOC_AARCH64_TLSDESC, R_AARCH64_TLSDESC},
+};
+
+static reloc_howto_type *
+elf64_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
+				 bfd_reloc_code_real_type code)
+{
+  unsigned int i;
+
+  for (i = 0; i < ARRAY_SIZE (elf64_aarch64_reloc_map); i++)
+    if (elf64_aarch64_reloc_map[i].bfd_reloc_val == code)
+      return elf64_aarch64_howto_from_type
+	(elf64_aarch64_reloc_map[i].elf_reloc_val);
+
+  bfd_set_error (bfd_error_bad_value);
+  return NULL;
+}
+
+static reloc_howto_type *
+elf64_aarch64_reloc_name_lookup (bfd * abfd ATTRIBUTE_UNUSED,
+				 const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0; i < ARRAY_SIZE (elf64_aarch64_howto_table); i++)
+    if (elf64_aarch64_howto_table[i].name != NULL
+	&& strcasecmp (elf64_aarch64_howto_table[i].name, r_name) == 0)
+      return &elf64_aarch64_howto_table[i];
+
+  return NULL;
+}
+
+#define TARGET_LITTLE_SYM               bfd_elf64_littleaarch64_vec
+#define TARGET_LITTLE_NAME              "elf64-littleaarch64"
+#define TARGET_BIG_SYM                  bfd_elf64_bigaarch64_vec
+#define TARGET_BIG_NAME                 "elf64-bigaarch64"
+
+typedef unsigned long int insn32;
+
+/* The linker script knows the section names for placement.
+   The entry_names are used to do simple name mangling on the stubs.
+   Given a function name, and its type, the stub can be found. The
+   name can be changed. The only requirement is the %s be present.  */
+#define STUB_ENTRY_NAME   "__%s_veneer"
+
+/* The name of the dynamic interpreter.  This is put in the .interp
+   section.  */
+#define ELF_DYNAMIC_INTERPRETER     "/lib/ld.so.1"
+
+#define AARCH64_MAX_FWD_BRANCH_OFFSET \
+  (((1 << 25) - 1) << 2)
+#define AARCH64_MAX_BWD_BRANCH_OFFSET \
+  (-((1 << 25) << 2))
+
+#define AARCH64_MAX_ADRP_IMM ((1 << 20) - 1)
+#define AARCH64_MIN_ADRP_IMM (-(1 << 20))
+
+static int
+aarch64_valid_for_adrp_p (bfd_vma value, bfd_vma place)
+{
+  bfd_signed_vma offset = (bfd_signed_vma) (PG (value) - PG (place)) >> 12;
+  return offset <= AARCH64_MAX_ADRP_IMM && offset >= AARCH64_MIN_ADRP_IMM;
+}
+
+static int
+aarch64_valid_branch_p (bfd_vma value, bfd_vma place)
+{
+  bfd_signed_vma offset = (bfd_signed_vma) (value - place);
+  return (offset <= AARCH64_MAX_FWD_BRANCH_OFFSET
+	  && offset >= AARCH64_MAX_BWD_BRANCH_OFFSET);
+}
+
+static const uint32_t aarch64_adrp_branch_stub [] = {
+  0x90000010,			/*	adrp	ip0, X */
+				/*		R_AARCH64_ADR_HI21_PCREL(X) */
+  0x91000210,			/*	add	ip0, ip0, :lo12:X */
+				/*		R_AARCH64_ADD_ABS_LO12_NC(X) */
+  0xd61f0200,			/*	br	ip0 */
+};
+
+static const uint32_t aarch64_long_branch_stub[] = {
+  0x58000090,			/*	ldr   ip0, 1f */
+  0x10000011,			/*	adr   ip1, #0 */
+  0x8b110210,			/*	add   ip0, ip0, ip1 */
+  0xd61f0200,			/*	br	ip0 */
+  0x00000000,			/* 1:	.xword
+				   R_AARCH64_PREL64(X) + 12
+				 */
+  0x00000000,
+};
+
+/* Section name for stubs is the associated section name plus this
+   string.  */
+#define STUB_SUFFIX ".stub"
+
+enum elf64_aarch64_stub_type
+{
+  aarch64_stub_none,
+  aarch64_stub_adrp_branch,
+  aarch64_stub_long_branch,
+};
+
+struct elf64_aarch64_stub_hash_entry
+{
+  /* Base hash table entry structure.  */
+  struct bfd_hash_entry root;
+
+
+  /* The stub section.  */
+  asection *stub_sec;
+
+  /* Offset within stub_sec of the beginning of this stub.  */
+  bfd_vma stub_offset;
+
+  /* Given the symbol's value and its section we can determine its final
+     value when building the stubs (so the stub knows where to jump).  */
+  bfd_vma target_value;
+  asection *target_section;
+
+  enum elf64_aarch64_stub_type stub_type;
+
+  /* The symbol table entry, if any, that this was derived from.  */
+  struct elf64_aarch64_link_hash_entry *h;
+
+  /* Destination symbol type */
+  unsigned char st_type;
+
+  /* Where this stub is being called from, or, in the case of combined
+     stub sections, the first input section in the group.  */
+  asection *id_sec;
+
+  /* The name for the local symbol at the start of this stub.  The
+     stub name in the hash table has to be unique; this does not, so
+     it can be friendlier.  */
+  char *output_name;
+};
+
+/* Used to build a map of a section.  This is required for mixed-endian
+   code/data.  */
+
+typedef struct elf64_elf_section_map
+{
+  bfd_vma vma;
+  char type;
+}
+elf64_aarch64_section_map;
+
+
+typedef struct _aarch64_elf_section_data
+{
+  struct bfd_elf_section_data elf;
+  unsigned int mapcount;
+  unsigned int mapsize;
+  elf64_aarch64_section_map *map;
+}
+_aarch64_elf_section_data;
+
+#define elf64_aarch64_section_data(sec) \
+  ((_aarch64_elf_section_data *) elf_section_data (sec))
+
+/* The size of the thread control block.  */
+#define TCB_SIZE	16
+
+struct elf_aarch64_local_symbol
+{
+  unsigned int got_type;
+  bfd_signed_vma got_refcount;
+  bfd_vma got_offset;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor. The
+     offset is from the end of the jump table and reserved entries
+     within the PLTGOT.
+
+     The magic value (bfd_vma) -1 indicates that an offset has not be
+     allocated.  */
+  bfd_vma tlsdesc_got_jump_table_offset;
+};
+
+struct elf_aarch64_obj_tdata
+{
+  struct elf_obj_tdata root;
+
+  /* local symbol descriptors */
+  struct elf_aarch64_local_symbol *locals;
+
+  /* Zero to warn when linking objects with incompatible enum sizes.  */
+  int no_enum_size_warning;
+
+  /* Zero to warn when linking objects with incompatible wchar_t sizes.  */
+  int no_wchar_size_warning;
+};
+
+#define elf_aarch64_tdata(bfd)				\
+  ((struct elf_aarch64_obj_tdata *) (bfd)->tdata.any)
+
+#define elf64_aarch64_locals(bfd) (elf_aarch64_tdata (bfd)->locals)
+
+#define is_aarch64_elf(bfd)				\
+  (bfd_get_flavour (bfd) == bfd_target_elf_flavour	\
+   && elf_tdata (bfd) != NULL				\
+   && elf_object_id (bfd) == AARCH64_ELF_DATA)
+
+static bfd_boolean
+elf64_aarch64_mkobject (bfd * abfd)
+{
+  return bfd_elf_allocate_object (abfd, sizeof (struct elf_aarch64_obj_tdata),
+				  AARCH64_ELF_DATA);
+}
+
+/* The AArch64 linker needs to keep track of the number of relocs that it
+   decides to copy in check_relocs for each symbol.  This is so that
+   it can discard PC relative relocs if it doesn't need them when
+   linking with -Bsymbolic.  We store the information in a field
+   extending the regular ELF linker hash table.  */
+
+/* This structure keeps track of the number of relocs we have copied
+   for a given symbol.  */
+struct elf64_aarch64_relocs_copied
+{
+  /* Next section.  */
+  struct elf64_aarch64_relocs_copied *next;
+  /* A section in dynobj.  */
+  asection *section;
+  /* Number of relocs copied in this section.  */
+  bfd_size_type count;
+  /* Number of PC-relative relocs copied in this section.  */
+  bfd_size_type pc_count;
+};
+
+#define elf64_aarch64_hash_entry(ent) \
+  ((struct elf64_aarch64_link_hash_entry *)(ent))
+
+#define GOT_UNKNOWN    0
+#define GOT_NORMAL     1
+#define GOT_TLS_GD     2
+#define GOT_TLS_IE     4
+#define GOT_TLSDESC_GD 8
+
+#define GOT_TLS_GD_ANY_P(type)	((type & GOT_TLS_GD) || (type & GOT_TLSDESC_GD))
+
+/* AArch64 ELF linker hash entry.  */
+struct elf64_aarch64_link_hash_entry
+{
+  struct elf_link_hash_entry root;
+
+  /* Track dynamic relocs copied for this symbol.  */
+  struct elf_dyn_relocs *dyn_relocs;
+
+  /* Number of PC relative relocs copied for this symbol.  */
+  struct elf64_aarch64_relocs_copied *relocs_copied;
+
+  /* Since PLT entries have variable size, we need to record the
+     index into .got.plt instead of recomputing it from the PLT
+     offset.  */
+  bfd_signed_vma plt_got_offset;
+
+  /* Bit mask representing the type of GOT entry(s) if any required by
+     this symbol.  */
+  unsigned int got_type;
+
+  /* A pointer to the most recently used stub hash entry against this
+     symbol.  */
+  struct elf64_aarch64_stub_hash_entry *stub_cache;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor.  The offset
+     is from the end of the jump table and reserved entries within the PLTGOT.
+
+     The magic value (bfd_vma) -1 indicates that an offset has not
+     be allocated.  */
+  bfd_vma tlsdesc_got_jump_table_offset;
+};
+
+static unsigned int
+elf64_aarch64_symbol_got_type (struct elf_link_hash_entry *h,
+			       bfd *abfd,
+			       unsigned long r_symndx)
+{
+  if (h)
+    return elf64_aarch64_hash_entry (h)->got_type;
+
+  if (! elf64_aarch64_locals (abfd))
+    return GOT_UNKNOWN;
+
+  return elf64_aarch64_locals (abfd)[r_symndx].got_type;
+}
+
+/* Traverse an AArch64 ELF linker hash table.  */
+#define elf64_aarch64_link_hash_traverse(table, func, info)		\
+  (elf_link_hash_traverse						\
+   (&(table)->root,							\
+    (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func),	\
+    (info)))
+
+/* Get the AArch64 elf linker hash table from a link_info structure.  */
+#define elf64_aarch64_hash_table(info)					\
+  ((struct elf64_aarch64_link_hash_table *) ((info)->hash))
+
+#define aarch64_stub_hash_lookup(table, string, create, copy)		\
+  ((struct elf64_aarch64_stub_hash_entry *)				\
+   bfd_hash_lookup ((table), (string), (create), (copy)))
+
+/* AArch64 ELF linker hash table.  */
+struct elf64_aarch64_link_hash_table
+{
+  /* The main hash table.  */
+  struct elf_link_hash_table root;
+
+  /* Nonzero to force PIC branch veneers.  */
+  int pic_veneer;
+
+  /* The number of bytes in the initial entry in the PLT.  */
+  bfd_size_type plt_header_size;
+
+  /* The number of bytes in the subsequent PLT etries.  */
+  bfd_size_type plt_entry_size;
+
+  /* Short-cuts to get to dynamic linker sections.  */
+  asection *sdynbss;
+  asection *srelbss;
+
+  /* Small local sym cache.  */
+  struct sym_cache sym_cache;
+
+  /* For convenience in allocate_dynrelocs.  */
+  bfd *obfd;
+
+  /* The amount of space used by the reserved portion of the sgotplt
+     section, plus whatever space is used by the jump slots.  */
+  bfd_vma sgotplt_jump_table_size;
+
+  /* The stub hash table.  */
+  struct bfd_hash_table stub_hash_table;
+
+  /* Linker stub bfd.  */
+  bfd *stub_bfd;
+
+  /* Linker call-backs.  */
+  asection *(*add_stub_section) (const char *, asection *);
+  void (*layout_sections_again) (void);
+
+  /* Array to keep track of which stub sections have been created, and
+     information on stub grouping.  */
+  struct map_stub
+  {
+    /* This is the section to which stubs in the group will be
+       attached.  */
+    asection *link_sec;
+    /* The stub section.  */
+    asection *stub_sec;
+  } *stub_group;
+
+  /* Assorted information used by elf64_aarch64_size_stubs.  */
+  unsigned int bfd_count;
+  int top_index;
+  asection **input_list;
+
+  /* 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
+     yet.  */
+  bfd_vma tlsdesc_plt;
+
+  /* The GOT offset for the lazy trampoline.  Communicated to the
+     loader via DT_TLSDESC_GOT.  The magic value (bfd_vma) -1
+     indicates an offset is not allocated.  */
+  bfd_vma dt_tlsdesc_got;
+};
+
+
+/* Return non-zero if the indicated VALUE has overflowed the maximum
+   range expressible by a unsigned number with the indicated number of
+   BITS.  */
+
+static bfd_reloc_status_type
+aarch64_unsigned_overflow (bfd_vma value, unsigned int bits)
+{
+  bfd_vma lim;
+  if (bits >= sizeof (bfd_vma) * 8)
+    return bfd_reloc_ok;
+  lim = (bfd_vma) 1 << bits;
+  if (value >= lim)
+    return bfd_reloc_overflow;
+  return bfd_reloc_ok;
+}
+
+
+/* Return non-zero if the indicated VALUE has overflowed the maximum
+   range expressible by an signed number with the indicated number of
+   BITS.  */
+
+static bfd_reloc_status_type
+aarch64_signed_overflow (bfd_vma value, unsigned int bits)
+{
+  bfd_signed_vma svalue = (bfd_signed_vma) value;
+  bfd_signed_vma lim;
+
+  if (bits >= sizeof (bfd_vma) * 8)
+    return bfd_reloc_ok;
+  lim = (bfd_signed_vma) 1 << (bits - 1);
+  if (svalue < -lim || svalue >= lim)
+    return bfd_reloc_overflow;
+  return bfd_reloc_ok;
+}
+
+/* Create an entry in an AArch64 ELF linker hash table.  */
+
+static struct bfd_hash_entry *
+elf64_aarch64_link_hash_newfunc (struct bfd_hash_entry *entry,
+				 struct bfd_hash_table *table,
+				 const char *string)
+{
+  struct elf64_aarch64_link_hash_entry *ret =
+    (struct elf64_aarch64_link_hash_entry *) entry;
+
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (ret == NULL)
+    ret = bfd_hash_allocate (table,
+			     sizeof (struct elf64_aarch64_link_hash_entry));
+  if (ret == NULL)
+    return (struct bfd_hash_entry *) ret;
+
+  /* Call the allocation method of the superclass.  */
+  ret = ((struct elf64_aarch64_link_hash_entry *)
+	 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+				     table, string));
+  if (ret != NULL)
+    {
+      ret->dyn_relocs = NULL;
+      ret->relocs_copied = NULL;
+      ret->got_type = GOT_UNKNOWN;
+      ret->plt_got_offset = (bfd_vma) - 1;
+      ret->stub_cache = NULL;
+      ret->tlsdesc_got_jump_table_offset = (bfd_vma) - 1;
+    }
+
+  return (struct bfd_hash_entry *) ret;
+}
+
+/* Initialize an entry in the stub hash table.  */
+
+static struct bfd_hash_entry *
+stub_hash_newfunc (struct bfd_hash_entry *entry,
+		   struct bfd_hash_table *table, const char *string)
+{
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (entry == NULL)
+    {
+      entry = bfd_hash_allocate (table,
+				 sizeof (struct
+					 elf64_aarch64_stub_hash_entry));
+      if (entry == NULL)
+	return entry;
+    }
+
+  /* Call the allocation method of the superclass.  */
+  entry = bfd_hash_newfunc (entry, table, string);
+  if (entry != NULL)
+    {
+      struct elf64_aarch64_stub_hash_entry *eh;
+
+      /* Initialize the local fields.  */
+      eh = (struct elf64_aarch64_stub_hash_entry *) entry;
+      eh->stub_sec = NULL;
+      eh->stub_offset = 0;
+      eh->target_value = 0;
+      eh->target_section = NULL;
+      eh->stub_type = aarch64_stub_none;
+      eh->h = NULL;
+      eh->id_sec = NULL;
+    }
+
+  return entry;
+}
+
+
+/* Copy the extra info we tack onto an elf_link_hash_entry.  */
+
+static void
+elf64_aarch64_copy_indirect_symbol (struct bfd_link_info *info,
+				    struct elf_link_hash_entry *dir,
+				    struct elf_link_hash_entry *ind)
+{
+  struct elf64_aarch64_link_hash_entry *edir, *eind;
+
+  edir = (struct elf64_aarch64_link_hash_entry *) dir;
+  eind = (struct elf64_aarch64_link_hash_entry *) ind;
+
+  if (eind->dyn_relocs != NULL)
+    {
+      if (edir->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;)
+	    {
+	      struct elf_dyn_relocs *q;
+
+	      for (q = edir->dyn_relocs; q != NULL; q = q->next)
+		if (q->sec == p->sec)
+		  {
+		    q->pc_count += p->pc_count;
+		    q->count += p->count;
+		    *pp = p->next;
+		    break;
+		  }
+	      if (q == NULL)
+		pp = &p->next;
+	    }
+	  *pp = edir->dyn_relocs;
+	}
+
+      edir->dyn_relocs = eind->dyn_relocs;
+      eind->dyn_relocs = NULL;
+    }
+
+  if (eind->relocs_copied != NULL)
+    {
+      if (edir->relocs_copied != NULL)
+	{
+	  struct elf64_aarch64_relocs_copied **pp;
+	  struct elf64_aarch64_relocs_copied *p;
+
+	  /* Add reloc counts against the indirect sym to the direct sym
+	     list.  Merge any entries against the same section.  */
+	  for (pp = &eind->relocs_copied; (p = *pp) != NULL;)
+	    {
+	      struct elf64_aarch64_relocs_copied *q;
+
+	      for (q = edir->relocs_copied; q != NULL; q = q->next)
+		if (q->section == p->section)
+		  {
+		    q->pc_count += p->pc_count;
+		    q->count += p->count;
+		    *pp = p->next;
+		    break;
+		  }
+	      if (q == NULL)
+		pp = &p->next;
+	    }
+	  *pp = edir->relocs_copied;
+	}
+
+      edir->relocs_copied = eind->relocs_copied;
+      eind->relocs_copied = NULL;
+    }
+
+  if (ind->root.type == bfd_link_hash_indirect)
+    {
+      /* Copy over PLT info.  */
+      if (dir->got.refcount <= 0)
+	{
+	  edir->got_type = eind->got_type;
+	  eind->got_type = GOT_UNKNOWN;
+	}
+    }
+
+  _bfd_elf_link_hash_copy_indirect (info, dir, ind);
+}
+
+/* Create an AArch64 elf linker hash table.  */
+
+static struct bfd_link_hash_table *
+elf64_aarch64_link_hash_table_create (bfd * abfd)
+{
+  struct elf64_aarch64_link_hash_table *ret;
+  bfd_size_type amt = sizeof (struct elf64_aarch64_link_hash_table);
+
+  ret = bfd_malloc (amt);
+  if (ret == NULL)
+    return NULL;
+
+  if (!_bfd_elf_link_hash_table_init
+      (&ret->root, abfd, elf64_aarch64_link_hash_newfunc,
+       sizeof (struct elf64_aarch64_link_hash_entry), AARCH64_ELF_DATA))
+    {
+      free (ret);
+      return NULL;
+    }
+
+  ret->sdynbss = NULL;
+  ret->srelbss = NULL;
+
+  ret->plt_header_size = PLT_ENTRY_SIZE;
+  ret->plt_entry_size = PLT_SMALL_ENTRY_SIZE;
+
+  ret->sym_cache.abfd = NULL;
+  ret->obfd = abfd;
+
+  ret->stub_bfd = NULL;
+  ret->add_stub_section = NULL;
+  ret->layout_sections_again = NULL;
+  ret->stub_group = NULL;
+  ret->bfd_count = 0;
+  ret->top_index = 0;
+  ret->input_list = NULL;
+  ret->tlsdesc_plt = 0;
+  ret->dt_tlsdesc_got = (bfd_vma) - 1;
+
+  if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc,
+			    sizeof (struct elf64_aarch64_stub_hash_entry)))
+    {
+      free (ret);
+      return NULL;
+    }
+
+  return &ret->root.root;
+}
+
+/* Free the derived linker hash table.  */
+
+static void
+elf64_aarch64_hash_table_free (struct bfd_link_hash_table *hash)
+{
+  struct elf64_aarch64_link_hash_table *ret
+    = (struct elf64_aarch64_link_hash_table *) hash;
+
+  bfd_hash_table_free (&ret->stub_hash_table);
+  _bfd_generic_link_hash_table_free (hash);
+}
+
+static bfd_vma
+aarch64_resolve_relocation (unsigned int r_type, bfd_vma place, bfd_vma value,
+			    bfd_vma addend, bfd_boolean weak_undef_p)
+{
+  switch (r_type)
+    {
+    case R_AARCH64_TLSDESC_CALL:
+    case R_AARCH64_NONE:
+    case R_AARCH64_NULL:
+      break;
+
+    case R_AARCH64_ADR_PREL_LO21:
+    case R_AARCH64_CONDBR19:
+    case R_AARCH64_LD_PREL_LO19:
+    case R_AARCH64_PREL16:
+    case R_AARCH64_PREL32:
+    case R_AARCH64_PREL64:
+    case R_AARCH64_TSTBR14:
+      if (weak_undef_p)
+	value = place;
+      value = value + addend - place;
+      break;
+
+    case R_AARCH64_CALL26:
+    case R_AARCH64_JUMP26:
+      value = value + addend - place;
+      break;
+
+    case R_AARCH64_ABS16:
+    case R_AARCH64_ABS32:
+    case R_AARCH64_MOVW_SABS_G0:
+    case R_AARCH64_MOVW_SABS_G1:
+    case R_AARCH64_MOVW_SABS_G2:
+    case R_AARCH64_MOVW_UABS_G0:
+    case R_AARCH64_MOVW_UABS_G0_NC:
+    case R_AARCH64_MOVW_UABS_G1:
+    case R_AARCH64_MOVW_UABS_G1_NC:
+    case R_AARCH64_MOVW_UABS_G2:
+    case R_AARCH64_MOVW_UABS_G2_NC:
+    case R_AARCH64_MOVW_UABS_G3:
+      value = value + addend;
+      break;
+
+    case R_AARCH64_ADR_PREL_PG_HI21:
+    case R_AARCH64_ADR_PREL_PG_HI21_NC:
+      if (weak_undef_p)
+	value = PG (place);
+      value = PG (value + addend) - PG (place);
+      break;
+
+    case R_AARCH64_ADR_GOT_PAGE:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+      value = PG (value + addend) - PG (place);
+      break;
+
+    case R_AARCH64_ADD_ABS_LO12_NC:
+    case R_AARCH64_LD64_GOT_LO12_NC:
+    case R_AARCH64_LDST8_ABS_LO12_NC:
+    case R_AARCH64_LDST16_ABS_LO12_NC:
+    case R_AARCH64_LDST32_ABS_LO12_NC:
+    case R_AARCH64_LDST64_ABS_LO12_NC:
+    case R_AARCH64_LDST128_ABS_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+    case R_AARCH64_TLSDESC_LDR:
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+      value = PG_OFFSET (value + addend);
+      break;
+
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+      value = (value + addend) & (bfd_vma) 0xffff0000;
+      break;
+    case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+      value = (value + addend) & (bfd_vma) 0xfff000;
+      break;
+
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+      value = (value + addend) & (bfd_vma) 0xffff;
+      break;
+
+    case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+      value = (value + addend) & ~(bfd_vma) 0xffffffff;
+      value -= place & ~(bfd_vma) 0xffffffff;
+      break;
+    }
+  return value;
+}
+
+static bfd_boolean
+aarch64_relocate (unsigned int r_type, bfd *input_bfd, asection *input_section,
+		  bfd_vma offset, bfd_vma value)
+{
+  reloc_howto_type *howto;
+  bfd_vma place;
+
+  howto = elf64_aarch64_howto_from_type (r_type);
+  place = (input_section->output_section->vma + input_section->output_offset
+	   + offset);
+  value = aarch64_resolve_relocation (r_type, place, value, 0, FALSE);
+  return bfd_elf_aarch64_put_addend (input_bfd,
+				     input_section->contents + offset,
+				     howto, value);
+}
+
+static enum elf64_aarch64_stub_type
+aarch64_select_branch_stub (bfd_vma value, bfd_vma place)
+{
+  if (aarch64_valid_for_adrp_p (value, place))
+    return aarch64_stub_adrp_branch;
+  return aarch64_stub_long_branch;
+}
+
+/* Determine the type of stub needed, if any, for a call.  */
+
+static enum elf64_aarch64_stub_type
+aarch64_type_of_stub (struct bfd_link_info *info,
+		      asection * input_sec,
+		      const Elf_Internal_Rela * rel,
+		      unsigned char st_type,
+		      struct elf64_aarch64_link_hash_entry *hash,
+		      bfd_vma destination)
+{
+  bfd_vma location;
+  bfd_signed_vma branch_offset;
+  unsigned int r_type;
+  struct elf64_aarch64_link_hash_table *globals;
+  enum elf64_aarch64_stub_type stub_type = aarch64_stub_none;
+  bfd_boolean via_plt_p;
+
+  if (st_type != STT_FUNC)
+    return stub_type;
+
+  globals = elf64_aarch64_hash_table (info);
+  via_plt_p = (globals->root.splt != NULL && hash != NULL
+	       && hash->root.plt.offset != (bfd_vma) - 1);
+
+  if (via_plt_p)
+    return stub_type;
+
+  /* Determine where the call point is.  */
+  location = (input_sec->output_offset
+	      + input_sec->output_section->vma + rel->r_offset);
+
+  branch_offset = (bfd_signed_vma) (destination - location);
+
+  r_type = ELF64_R_TYPE (rel->r_info);
+
+  /* We don't want to redirect any old unconditional jump in this way,
+     only one which is being used for a sibcall, where it is
+     acceptable for the IP0 and IP1 registers to be clobbered.  */
+  if ((r_type == R_AARCH64_CALL26 || r_type == R_AARCH64_JUMP26)
+      && (branch_offset > AARCH64_MAX_FWD_BRANCH_OFFSET
+	  || branch_offset < AARCH64_MAX_BWD_BRANCH_OFFSET))
+    {
+      stub_type = aarch64_stub_long_branch;
+    }
+
+  return stub_type;
+}
+
+/* Build a name for an entry in the stub hash table.  */
+
+static char *
+elf64_aarch64_stub_name (const asection * input_section,
+			 const asection * sym_sec,
+			 const struct elf64_aarch64_link_hash_entry *hash,
+			 const Elf_Internal_Rela * rel)
+{
+  char *stub_name;
+  bfd_size_type len;
+
+  if (hash)
+    {
+      len = 8 + 1 + strlen (hash->root.root.root.string) + 1 + 16 + 1;
+      stub_name = bfd_malloc (len);
+      if (stub_name != NULL)
+	snprintf (stub_name, len, "%08x_%s+%" BFD_VMA_FMT "x",
+		  (unsigned int) input_section->id,
+		  hash->root.root.root.string,
+		  rel->r_addend);
+    }
+  else
+    {
+      len = 8 + 1 + 8 + 1 + 8 + 1 + 16 + 1;
+      stub_name = bfd_malloc (len);
+      if (stub_name != NULL)
+	snprintf (stub_name, len, "%08x_%x:%x+%" BFD_VMA_FMT "x",
+		  (unsigned int) input_section->id,
+		  (unsigned int) sym_sec->id,
+		  (unsigned int) ELF64_R_SYM (rel->r_info),
+		  rel->r_addend);
+    }
+
+  return stub_name;
+}
+
+/* Look up an entry in the stub hash.  Stub entries are cached because
+   creating the stub name takes a bit of time.  */
+
+static struct elf64_aarch64_stub_hash_entry *
+elf64_aarch64_get_stub_entry (const asection * input_section,
+			      const asection * sym_sec,
+			      struct elf_link_hash_entry *hash,
+			      const Elf_Internal_Rela * rel,
+			      struct elf64_aarch64_link_hash_table *htab)
+{
+  struct elf64_aarch64_stub_hash_entry *stub_entry;
+  struct elf64_aarch64_link_hash_entry *h =
+    (struct elf64_aarch64_link_hash_entry *) hash;
+  const asection *id_sec;
+
+  if ((input_section->flags & SEC_CODE) == 0)
+    return NULL;
+
+  /* If this input section is part of a group of sections sharing one
+     stub section, then use the id of the first section in the group.
+     Stub names need to include a section id, as there may well be
+     more than one stub used to reach say, printf, and we need to
+     distinguish between them.  */
+  id_sec = htab->stub_group[input_section->id].link_sec;
+
+  if (h != NULL && h->stub_cache != NULL
+      && h->stub_cache->h == h && h->stub_cache->id_sec == id_sec)
+    {
+      stub_entry = h->stub_cache;
+    }
+  else
+    {
+      char *stub_name;
+
+      stub_name = elf64_aarch64_stub_name (id_sec, sym_sec, h, rel);
+      if (stub_name == NULL)
+	return NULL;
+
+      stub_entry = aarch64_stub_hash_lookup (&htab->stub_hash_table,
+					     stub_name, FALSE, FALSE);
+      if (h != NULL)
+	h->stub_cache = stub_entry;
+
+      free (stub_name);
+    }
+
+  return stub_entry;
+}
+
+/* Add a new stub entry to the stub hash.  Not all fields of the new
+   stub entry are initialised.  */
+
+static struct elf64_aarch64_stub_hash_entry *
+elf64_aarch64_add_stub (const char *stub_name,
+			asection * section,
+			struct elf64_aarch64_link_hash_table *htab)
+{
+  asection *link_sec;
+  asection *stub_sec;
+  struct elf64_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;
+    }
+
+  /* Enter this entry into the linker stub hash table.  */
+  stub_entry = aarch64_stub_hash_lookup (&htab->stub_hash_table, stub_name,
+					 TRUE, FALSE);
+  if (stub_entry == NULL)
+    {
+      (*_bfd_error_handler) (_("%s: cannot create stub entry %s"),
+			     section->owner, stub_name);
+      return NULL;
+    }
+
+  stub_entry->stub_sec = stub_sec;
+  stub_entry->stub_offset = 0;
+  stub_entry->id_sec = link_sec;
+
+  return stub_entry;
+}
+
+static bfd_boolean
+aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
+			void *in_arg ATTRIBUTE_UNUSED)
+{
+  struct elf64_aarch64_stub_hash_entry *stub_entry;
+  asection *stub_sec;
+  bfd *stub_bfd;
+  bfd_byte *loc;
+  bfd_vma sym_value;
+  unsigned int template_size;
+  const uint32_t *template;
+  unsigned int i;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf64_aarch64_stub_hash_entry *) gen_entry;
+
+  stub_sec = stub_entry->stub_sec;
+
+  /* Make a note of the offset within the stubs for this entry.  */
+  stub_entry->stub_offset = stub_sec->size;
+  loc = stub_sec->contents + stub_entry->stub_offset;
+
+  stub_bfd = stub_sec->owner;
+
+  /* This is the address of the stub destination.  */
+  sym_value = (stub_entry->target_value
+	       + stub_entry->target_section->output_offset
+	       + stub_entry->target_section->output_section->vma);
+
+  if (stub_entry->stub_type == aarch64_stub_long_branch)
+    {
+      bfd_vma place = (stub_entry->stub_offset + stub_sec->output_section->vma
+		       + stub_sec->output_offset);
+
+      /* See if we can relax the stub.  */
+      if (aarch64_valid_for_adrp_p (sym_value, place))
+	stub_entry->stub_type = aarch64_select_branch_stub (sym_value, place);
+    }
+
+  switch (stub_entry->stub_type)
+    {
+    case aarch64_stub_adrp_branch:
+      template = aarch64_adrp_branch_stub;
+      template_size = sizeof (aarch64_adrp_branch_stub);
+      break;
+    case aarch64_stub_long_branch:
+      template = aarch64_long_branch_stub;
+      template_size = sizeof (aarch64_long_branch_stub);
+      break;
+    default:
+      BFD_FAIL ();
+      return FALSE;
+    }
+
+  for (i = 0; i < (template_size / sizeof template[0]); i++)
+    {
+      bfd_putl32 (template[i], loc);
+      loc += 4;
+    }
+
+  template_size = (template_size + 7) & ~7;
+  stub_sec->size += template_size;
+
+  switch (stub_entry->stub_type)
+    {
+    case aarch64_stub_adrp_branch:
+      if (aarch64_relocate (R_AARCH64_ADR_PREL_PG_HI21, stub_bfd, stub_sec,
+			    stub_entry->stub_offset, sym_value))
+	/* The stub would not have been relaxed if the offset was out
+	   of range.  */
+	BFD_FAIL ();
+
+      _bfd_final_link_relocate
+	(elf64_aarch64_howto_from_type (R_AARCH64_ADD_ABS_LO12_NC),
+	 stub_bfd,
+	 stub_sec,
+	 stub_sec->contents,
+	 stub_entry->stub_offset + 4,
+	 sym_value,
+	 0);
+      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 (elf64_aarch64_howto_from_type
+				(R_AARCH64_PREL64), stub_bfd, stub_sec,
+				stub_sec->contents,
+				stub_entry->stub_offset + 16,
+				sym_value + 12, 0);
+      break;
+    default:
+      break;
+    }
+
+  return TRUE;
+}
+
+/* As above, but don't actually build the stub.  Just bump offset so
+   we know stub section sizes.  */
+
+static bfd_boolean
+aarch64_size_one_stub (struct bfd_hash_entry *gen_entry,
+		       void *in_arg ATTRIBUTE_UNUSED)
+{
+  struct elf64_aarch64_stub_hash_entry *stub_entry;
+  int size;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf64_aarch64_stub_hash_entry *) gen_entry;
+
+  switch (stub_entry->stub_type)
+    {
+    case aarch64_stub_adrp_branch:
+      size = sizeof (aarch64_adrp_branch_stub);
+      break;
+    case aarch64_stub_long_branch:
+      size = sizeof (aarch64_long_branch_stub);
+      break;
+    default:
+      BFD_FAIL ();
+      return FALSE;
+      break;
+    }
+
+  size = (size + 7) & ~7;
+  stub_entry->stub_sec->size += size;
+  return TRUE;
+}
+
+/* External entry points for sizing and building linker stubs.  */
+
+/* Set up various things so that we can make a list of input sections
+   for each output section included in the link.  Returns -1 on error,
+   0 when no stubs will be needed, and 1 on success.  */
+
+int
+elf64_aarch64_setup_section_lists (bfd * output_bfd,
+				   struct bfd_link_info *info)
+{
+  bfd *input_bfd;
+  unsigned int bfd_count;
+  int top_id, top_index;
+  asection *section;
+  asection **input_list, **list;
+  bfd_size_type amt;
+  struct elf64_aarch64_link_hash_table *htab =
+    elf64_aarch64_hash_table (info);
+
+  if (!is_elf_hash_table (htab))
+    return 0;
+
+  /* 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)
+    {
+      bfd_count += 1;
+      for (section = input_bfd->sections;
+	   section != NULL; section = section->next)
+	{
+	  if (top_id < section->id)
+	    top_id = section->id;
+	}
+    }
+  htab->bfd_count = bfd_count;
+
+  amt = sizeof (struct map_stub) * (top_id + 1);
+  htab->stub_group = bfd_zmalloc (amt);
+  if (htab->stub_group == NULL)
+    return -1;
+
+  /* We can't use output_bfd->section_count here to find the top output
+     section index as some sections may have been removed, and
+     _bfd_strip_section_from_output doesn't renumber the indices.  */
+  for (section = output_bfd->sections, top_index = 0;
+       section != NULL; section = section->next)
+    {
+      if (top_index < section->index)
+	top_index = section->index;
+    }
+
+  htab->top_index = top_index;
+  amt = sizeof (asection *) * (top_index + 1);
+  input_list = bfd_malloc (amt);
+  htab->input_list = input_list;
+  if (input_list == NULL)
+    return -1;
+
+  /* For sections we aren't interested in, mark their entries with a
+     value we can check later.  */
+  list = input_list + top_index;
+  do
+    *list = bfd_abs_section_ptr;
+  while (list-- != input_list);
+
+  for (section = output_bfd->sections;
+       section != NULL; section = section->next)
+    {
+      if ((section->flags & SEC_CODE) != 0)
+	input_list[section->index] = NULL;
+    }
+
+  return 1;
+}
+
+/* Used by elf64_aarch64_next_input_section and group_sections.  */
+#define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec)
+
+/* The linker repeatedly calls this function for each input section,
+   in the order that input sections are linked into output sections.
+   Build lists of input sections to determine groupings between which
+   we may insert linker stubs.  */
+
+void
+elf64_aarch64_next_input_section (struct bfd_link_info *info, asection * isec)
+{
+  struct elf64_aarch64_link_hash_table *htab =
+    elf64_aarch64_hash_table (info);
+
+  if (isec->output_section->index <= htab->top_index)
+    {
+      asection **list = htab->input_list + isec->output_section->index;
+
+      if (*list != bfd_abs_section_ptr)
+	{
+	  /* Steal the link_sec pointer for our list.  */
+	  /* This happens to make the list in reverse order,
+	     which is what we want.  */
+	  PREV_SEC (isec) = *list;
+	  *list = isec;
+	}
+    }
+}
+
+/* See whether we can group stub sections together.  Grouping stub
+   sections may result in fewer stubs.  More importantly, we need to
+   put all .init* and .fini* stubs at the beginning of the .init or
+   .fini output sections respectively, because glibc splits the
+   _init and _fini functions into multiple parts.  Putting a stub in
+   the middle of a function is not a good idea.  */
+
+static void
+group_sections (struct elf64_aarch64_link_hash_table *htab,
+		bfd_size_type stub_group_size,
+		bfd_boolean stubs_always_before_branch)
+{
+  asection **list = htab->input_list + htab->top_index;
+
+  do
+    {
+      asection *tail = *list;
+
+      if (tail == bfd_abs_section_ptr)
+	continue;
+
+      while (tail != NULL)
+	{
+	  asection *curr;
+	  asection *prev;
+	  bfd_size_type total;
+
+	  curr = tail;
+	  total = tail->size;
+	  while ((prev = PREV_SEC (curr)) != NULL
+		 && ((total += curr->output_offset - prev->output_offset)
+		     < stub_group_size))
+	    curr = prev;
+
+	  /* OK, the size from the start of CURR to the end is less
+	     than stub_group_size and thus can be handled by one stub
+	     section.  (Or the tail 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);
+	      /* Set up this stub group.  */
+	      htab->stub_group[tail->id].link_sec = curr;
+	    }
+	  while (tail != curr && (tail = prev) != 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)
+	    {
+	      total = 0;
+	      while (prev != NULL
+		     && ((total += tail->output_offset - prev->output_offset)
+			 < stub_group_size))
+		{
+		  tail = prev;
+		  prev = PREV_SEC (tail);
+		  htab->stub_group[tail->id].link_sec = curr;
+		}
+	    }
+	  tail = prev;
+	}
+    }
+  while (list-- != htab->input_list);
+
+  free (htab->input_list);
+}
+
+#undef PREV_SEC
+
+/* Determine and set the size of the stub section for a final link.
+
+   The basic idea here is to examine all the relocations looking for
+   PC-relative calls to a target that is unreachable with a "bl"
+   instruction.  */
+
+bfd_boolean
+elf64_aarch64_size_stubs (bfd * output_bfd,
+			  bfd * stub_bfd,
+			  struct bfd_link_info *info,
+			  bfd_signed_vma group_size,
+			  asection * (*add_stub_section) (const char *,
+							  asection *),
+			  void (*layout_sections_again) (void))
+{
+  bfd_size_type stub_group_size;
+  bfd_boolean stubs_always_before_branch;
+  bfd_boolean stub_changed = 0;
+  struct elf64_aarch64_link_hash_table *htab = elf64_aarch64_hash_table (info);
+
+  /* Propagate mach to stub bfd, because it may not have been
+     finalized when we created stub_bfd.  */
+  bfd_set_arch_mach (stub_bfd, bfd_get_arch (output_bfd),
+		     bfd_get_mach (output_bfd));
+
+  /* Stash our params away.  */
+  htab->stub_bfd = stub_bfd;
+  htab->add_stub_section = add_stub_section;
+  htab->layout_sections_again = layout_sections_again;
+  stubs_always_before_branch = group_size < 0;
+  if (group_size < 0)
+    stub_group_size = -group_size;
+  else
+    stub_group_size = group_size;
+
+  if (stub_group_size == 1)
+    {
+      /* Default values.  */
+      /* Aarch64 branch range is +-128MB. The value used is 1MB less. */
+      stub_group_size = 127 * 1024 * 1024;
+    }
+
+  group_sections (htab, stub_group_size, stubs_always_before_branch);
+
+  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++)
+	{
+	  Elf_Internal_Shdr *symtab_hdr;
+	  asection *section;
+	  Elf_Internal_Sym *local_syms = NULL;
+
+	  /* We'll need the symbol table in a second.  */
+	  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+	  if (symtab_hdr->sh_info == 0)
+	    continue;
+
+	  /* Walk over each section attached to the input bfd.  */
+	  for (section = input_bfd->sections;
+	       section != NULL; section = section->next)
+	    {
+	      Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
+
+	      /* If there aren't any relocs, then there's nothing more
+		 to do.  */
+	      if ((section->flags & SEC_RELOC) == 0
+		  || section->reloc_count == 0
+		  || (section->flags & SEC_CODE) == 0)
+		continue;
+
+	      /* If this section is a link-once section that will be
+		 discarded, then don't create any stubs.  */
+	      if (section->output_section == NULL
+		  || section->output_section->owner != output_bfd)
+		continue;
+
+	      /* Get the relocs.  */
+	      internal_relocs
+		= _bfd_elf_link_read_relocs (input_bfd, section, NULL,
+					     NULL, info->keep_memory);
+	      if (internal_relocs == NULL)
+		goto error_ret_free_local;
+
+	      /* Now examine each relocation.  */
+	      irela = internal_relocs;
+	      irelaend = irela + section->reloc_count;
+	      for (; irela < irelaend; irela++)
+		{
+		  unsigned int r_type, r_indx;
+		  enum elf64_aarch64_stub_type stub_type;
+		  struct elf64_aarch64_stub_hash_entry *stub_entry;
+		  asection *sym_sec;
+		  bfd_vma sym_value;
+		  bfd_vma destination;
+		  struct elf64_aarch64_link_hash_entry *hash;
+		  const char *sym_name;
+		  char *stub_name;
+		  const asection *id_sec;
+		  unsigned char st_type;
+		  bfd_size_type len;
+
+		  r_type = ELF64_R_TYPE (irela->r_info);
+		  r_indx = ELF64_R_SYM (irela->r_info);
+
+		  if (r_type >= (unsigned int) R_AARCH64_end)
+		    {
+		      bfd_set_error (bfd_error_bad_value);
+		    error_ret_free_internal:
+		      if (elf_section_data (section)->relocs == NULL)
+			free (internal_relocs);
+		      goto error_ret_free_local;
+		    }
+
+		  /* Only look for stubs on unconditional branch and
+		     branch and link instructions.  */
+		  if (r_type != (unsigned int) R_AARCH64_CALL26
+		      && r_type != (unsigned int) R_AARCH64_JUMP26)
+		    continue;
+
+		  /* Now determine the call target, its name, value,
+		     section.  */
+		  sym_sec = NULL;
+		  sym_value = 0;
+		  destination = 0;
+		  hash = NULL;
+		  sym_name = NULL;
+		  if (r_indx < symtab_hdr->sh_info)
+		    {
+		      /* It's a local symbol.  */
+		      Elf_Internal_Sym *sym;
+		      Elf_Internal_Shdr *hdr;
+
+		      if (local_syms == NULL)
+			{
+			  local_syms
+			    = (Elf_Internal_Sym *) symtab_hdr->contents;
+			  if (local_syms == NULL)
+			    local_syms
+			      = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+						      symtab_hdr->sh_info, 0,
+						      NULL, NULL, NULL);
+			  if (local_syms == NULL)
+			    goto error_ret_free_internal;
+			}
+
+		      sym = local_syms + r_indx;
+		      hdr = elf_elfsections (input_bfd)[sym->st_shndx];
+		      sym_sec = hdr->bfd_section;
+		      if (!sym_sec)
+			/* This is an undefined symbol.  It can never
+			   be resolved. */
+			continue;
+
+		      if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
+			sym_value = sym->st_value;
+		      destination = (sym_value + irela->r_addend
+				     + sym_sec->output_offset
+				     + sym_sec->output_section->vma);
+		      st_type = ELF_ST_TYPE (sym->st_info);
+		      sym_name
+			= bfd_elf_string_from_elf_section (input_bfd,
+							   symtab_hdr->sh_link,
+							   sym->st_name);
+		    }
+		  else
+		    {
+		      int e_indx;
+
+		      e_indx = r_indx - symtab_hdr->sh_info;
+		      hash = ((struct elf64_aarch64_link_hash_entry *)
+			      elf_sym_hashes (input_bfd)[e_indx]);
+
+		      while (hash->root.root.type == bfd_link_hash_indirect
+			     || hash->root.root.type == bfd_link_hash_warning)
+			hash = ((struct elf64_aarch64_link_hash_entry *)
+				hash->root.root.u.i.link);
+
+		      if (hash->root.root.type == bfd_link_hash_defined
+			  || hash->root.root.type == bfd_link_hash_defweak)
+			{
+			  struct elf64_aarch64_link_hash_table *globals =
+			    elf64_aarch64_hash_table (info);
+			  sym_sec = hash->root.root.u.def.section;
+			  sym_value = hash->root.root.u.def.value;
+			  /* For a destination in a shared library,
+			     use the PLT stub as target address to
+			     decide whether a branch stub is
+			     needed.  */
+			  if (globals->root.splt != NULL && hash != NULL
+			      && hash->root.plt.offset != (bfd_vma) - 1)
+			    {
+			      sym_sec = globals->root.splt;
+			      sym_value = hash->root.plt.offset;
+			      if (sym_sec->output_section != NULL)
+				destination = (sym_value
+					       + sym_sec->output_offset
+					       +
+					       sym_sec->output_section->vma);
+			    }
+			  else if (sym_sec->output_section != NULL)
+			    destination = (sym_value + irela->r_addend
+					   + sym_sec->output_offset
+					   + sym_sec->output_section->vma);
+			}
+		      else if (hash->root.root.type == bfd_link_hash_undefined
+			       || (hash->root.root.type
+				   == bfd_link_hash_undefweak))
+			{
+			  /* For a shared library, use the PLT stub as
+			     target address to decide whether a long
+			     branch stub is needed.
+			     For absolute code, they cannot be handled.  */
+			  struct elf64_aarch64_link_hash_table *globals =
+			    elf64_aarch64_hash_table (info);
+
+			  if (globals->root.splt != NULL && hash != NULL
+			      && hash->root.plt.offset != (bfd_vma) - 1)
+			    {
+			      sym_sec = globals->root.splt;
+			      sym_value = hash->root.plt.offset;
+			      if (sym_sec->output_section != NULL)
+				destination = (sym_value
+					       + sym_sec->output_offset
+					       +
+					       sym_sec->output_section->vma);
+			    }
+			  else
+			    continue;
+			}
+		      else
+			{
+			  bfd_set_error (bfd_error_bad_value);
+			  goto error_ret_free_internal;
+			}
+		      st_type = ELF_ST_TYPE (hash->root.type);
+		      sym_name = hash->root.root.root.string;
+		    }
+
+		  /* Determine what (if any) linker stub is needed.  */
+		  stub_type = aarch64_type_of_stub
+		    (info, section, irela, st_type, hash, destination);
+		  if (stub_type == aarch64_stub_none)
+		    continue;
+
+		  /* Support for grouping stub sections.  */
+		  id_sec = htab->stub_group[section->id].link_sec;
+
+		  /* Get the name of this stub.  */
+		  stub_name = elf64_aarch64_stub_name (id_sec, sym_sec, hash,
+						       irela);
+		  if (!stub_name)
+		    goto error_ret_free_internal;
+
+		  stub_entry =
+		    aarch64_stub_hash_lookup (&htab->stub_hash_table,
+					      stub_name, FALSE, FALSE);
+		  if (stub_entry != NULL)
+		    {
+		      /* The proper stub has already been created.  */
+		      free (stub_name);
+		      continue;
+		    }
+
+		  stub_entry = elf64_aarch64_add_stub (stub_name, section,
+						       htab);
+		  if (stub_entry == NULL)
+		    {
+		      free (stub_name);
+		      goto error_ret_free_internal;
+		    }
+
+		  stub_entry->target_value = sym_value;
+		  stub_entry->target_section = sym_sec;
+		  stub_entry->stub_type = stub_type;
+		  stub_entry->h = hash;
+		  stub_entry->st_type = st_type;
+
+		  if (sym_name == NULL)
+		    sym_name = "unnamed";
+		  len = sizeof (STUB_ENTRY_NAME) + strlen (sym_name);
+		  stub_entry->output_name = bfd_alloc (htab->stub_bfd, len);
+		  if (stub_entry->output_name == NULL)
+		    {
+		      free (stub_name);
+		      goto error_ret_free_internal;
+		    }
+
+		  snprintf (stub_entry->output_name, len, STUB_ENTRY_NAME,
+			    sym_name);
+
+		  stub_changed = TRUE;
+		}
+
+	      /* We're done with the internal relocs, free them.  */
+	      if (elf_section_data (section)->relocs == NULL)
+		free (internal_relocs);
+	    }
+	}
+
+      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);
+
+      /* Ask the linker to do its stuff.  */
+      (*htab->layout_sections_again) ();
+      stub_changed = FALSE;
+    }
+
+  return TRUE;
+
+error_ret_free_local:
+  return FALSE;
+}
+
+/* Build all the stubs associated with the current output file.  The
+   stubs are kept in a hash table attached to the main linker hash
+   table.  We also set up the .plt entries for statically linked PIC
+   functions here.  This function is called via aarch64_elf_finish in the
+   linker.  */
+
+bfd_boolean
+elf64_aarch64_build_stubs (struct bfd_link_info * info)
+{
+  asection *stub_sec;
+  struct bfd_hash_table *table;
+  struct elf64_aarch64_link_hash_table *htab;
+
+  htab = elf64_aarch64_hash_table (info);
+
+  for (stub_sec = htab->stub_bfd->sections;
+       stub_sec != NULL; stub_sec = stub_sec->next)
+    {
+      bfd_size_type size;
+
+      /* Ignore non-stub sections.  */
+      if (!strstr (stub_sec->name, STUB_SUFFIX))
+	continue;
+
+      /* Allocate memory to hold the linker stubs.  */
+      size = stub_sec->size;
+      stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
+      if (stub_sec->contents == NULL && size != 0)
+	return FALSE;
+      stub_sec->size = 0;
+    }
+
+  /* Build the stubs as directed by the stub hash table.  */
+  table = &htab->stub_hash_table;
+  bfd_hash_traverse (table, aarch64_build_one_stub, info);
+
+  return TRUE;
+}
+
+
+/* Add an entry to the code/data map for section SEC.  */
+
+static void
+elf64_aarch64_section_map_add (asection * sec, char type, bfd_vma vma)
+{
+  struct _aarch64_elf_section_data *sec_data =
+    elf64_aarch64_section_data (sec);
+  unsigned int newidx;
+
+  if (sec_data->map == NULL)
+    {
+      sec_data->map = bfd_malloc (sizeof (elf64_aarch64_section_map));
+      sec_data->mapcount = 0;
+      sec_data->mapsize = 1;
+    }
+
+  newidx = sec_data->mapcount++;
+
+  if (sec_data->mapcount > sec_data->mapsize)
+    {
+      sec_data->mapsize *= 2;
+      sec_data->map = bfd_realloc_or_free
+	(sec_data->map, sec_data->mapsize * sizeof (elf64_aarch64_section_map));
+    }
+
+  if (sec_data->map)
+    {
+      sec_data->map[newidx].vma = vma;
+      sec_data->map[newidx].type = type;
+    }
+}
+
+
+/* Initialise maps of insn/data for input BFDs.  */
+void
+bfd_elf64_aarch64_init_maps (bfd * abfd)
+{
+  Elf_Internal_Sym *isymbuf;
+  Elf_Internal_Shdr *hdr;
+  unsigned int i, localsyms;
+
+  /* Make sure that we are dealing with an AArch64 elf binary.  */
+  if (!is_aarch64_elf (abfd))
+    return;
+
+  if ((abfd->flags & DYNAMIC) != 0)
+    return;
+
+  hdr = &elf_symtab_hdr (abfd);
+  localsyms = hdr->sh_info;
+
+  /* Obtain a buffer full of symbols for this BFD. The hdr->sh_info field
+     should contain the number of local symbols, which should come before any
+     global symbols.  Mapping symbols are always local.  */
+  isymbuf = bfd_elf_get_elf_syms (abfd, hdr, localsyms, 0, NULL, NULL, NULL);
+
+  /* No internal symbols read?  Skip this BFD.  */
+  if (isymbuf == NULL)
+    return;
+
+  for (i = 0; i < localsyms; i++)
+    {
+      Elf_Internal_Sym *isym = &isymbuf[i];
+      asection *sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+      const char *name;
+
+      if (sec != NULL && ELF_ST_BIND (isym->st_info) == STB_LOCAL)
+	{
+	  name = bfd_elf_string_from_elf_section (abfd,
+						  hdr->sh_link,
+						  isym->st_name);
+
+	  if (bfd_is_aarch64_special_symbol_name
+	      (name, BFD_AARCH64_SPECIAL_SYM_TYPE_MAP))
+	    elf64_aarch64_section_map_add (sec, name[1], isym->st_value);
+	}
+    }
+}
+
+/* Set option values needed during linking.  */
+void
+bfd_elf64_aarch64_set_options (struct bfd *output_bfd,
+			       struct bfd_link_info *link_info,
+			       int no_enum_warn,
+			       int no_wchar_warn, int pic_veneer)
+{
+  struct elf64_aarch64_link_hash_table *globals;
+
+  globals = elf64_aarch64_hash_table (link_info);
+  globals->pic_veneer = pic_veneer;
+
+  BFD_ASSERT (is_aarch64_elf (output_bfd));
+  elf_aarch64_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
+  elf_aarch64_tdata (output_bfd)->no_wchar_size_warning = no_wchar_warn;
+}
+
+#define MASK(n) ((1u << (n)) - 1)
+
+/* Decode the 26-bit offset of unconditional branch.  */
+static inline uint32_t
+decode_branch_ofs_26 (uint32_t insn)
+{
+  return insn & MASK (26);
+}
+
+/* Decode the 19-bit offset of conditional branch and compare & branch.  */
+static inline uint32_t
+decode_cond_branch_ofs_19 (uint32_t insn)
+{
+  return (insn >> 5) & MASK (19);
+}
+
+/* Decode the 19-bit offset of load literal.  */
+static inline uint32_t
+decode_ld_lit_ofs_19 (uint32_t insn)
+{
+  return (insn >> 5) & MASK (19);
+}
+
+/* Decode the 14-bit offset of test & branch.  */
+static inline uint32_t
+decode_tst_branch_ofs_14 (uint32_t insn)
+{
+  return (insn >> 5) & MASK (14);
+}
+
+/* Decode the 16-bit imm of move wide.  */
+static inline uint32_t
+decode_movw_imm (uint32_t insn)
+{
+  return (insn >> 5) & MASK (16);
+}
+
+/* Decode the 21-bit imm of adr.  */
+static inline uint32_t
+decode_adr_imm (uint32_t insn)
+{
+  return ((insn >> 29) & MASK (2)) | ((insn >> 3) & (MASK (19) << 2));
+}
+
+/* Decode the 12-bit imm of add immediate.  */
+static inline uint32_t
+decode_add_imm (uint32_t insn)
+{
+  return (insn >> 10) & MASK (12);
+}
+
+
+/* Encode the 26-bit offset of unconditional branch.  */
+static inline uint32_t
+reencode_branch_ofs_26 (uint32_t insn, uint32_t ofs)
+{
+  return (insn & ~MASK (26)) | (ofs & MASK (26));
+}
+
+/* Encode the 19-bit offset of conditional branch and compare & branch.  */
+static inline uint32_t
+reencode_cond_branch_ofs_19 (uint32_t insn, uint32_t ofs)
+{
+  return (insn & ~(MASK (19) << 5)) | ((ofs & MASK (19)) << 5);
+}
+
+/* Decode the 19-bit offset of load literal.  */
+static inline uint32_t
+reencode_ld_lit_ofs_19 (uint32_t insn, uint32_t ofs)
+{
+  return (insn & ~(MASK (19) << 5)) | ((ofs & MASK (19)) << 5);
+}
+
+/* Encode the 14-bit offset of test & branch. */
+static inline uint32_t
+reencode_tst_branch_ofs_14 (uint32_t insn, uint32_t ofs)
+{
+  return (insn & ~(MASK (14) << 5)) | ((ofs & MASK (14)) << 5);
+}
+
+/* Reencode the imm field of move wide. */
+static inline uint32_t
+reencode_movw_imm (uint32_t insn, uint32_t imm)
+{
+  return (insn & ~(MASK (16) << 5)) | ((imm & MASK (16)) << 5);
+}
+
+/* Reencode the imm field of adr.  */
+static inline uint32_t
+reencode_adr_imm (uint32_t insn, uint32_t imm)
+{
+  return (insn & ~((MASK (2) << 29) | (MASK (19) << 5)))
+    | ((imm & MASK (2)) << 29) | ((imm & (MASK (19) << 2)) << 3);
+}
+
+/* Reencode the imm field of ld/st pos immediate.  */
+static inline uint32_t
+reencode_ldst_pos_imm (uint32_t insn, uint32_t imm)
+{
+  return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10);
+}
+
+/* Reencode the imm field of add immediate. */
+static inline uint32_t
+reencode_add_imm (uint32_t insn, uint32_t imm)
+{
+  return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10);
+}
+
+/* Reencode mov[zn] to movz.  */
+static inline uint32_t
+reencode_movzn_to_movz (uint32_t opcode)
+{
+  return opcode | (1 << 30);
+}
+
+/* Reencode mov[zn] to movn. */
+static inline uint32_t
+reencode_movzn_to_movn (uint32_t opcode)
+{
+  return opcode & ~(1 << 30);
+}
+
+/* Insert the addend/value into the instruction or data object being
+   relocated.  */
+static bfd_reloc_status_type
+bfd_elf_aarch64_put_addend (bfd * abfd,
+			    bfd_byte * address,
+			    reloc_howto_type * howto, bfd_signed_vma addend)
+{
+  bfd_reloc_status_type status = bfd_reloc_ok;
+  bfd_signed_vma old_addend = addend;
+  bfd_vma contents;
+  int size;
+
+  size = bfd_get_reloc_size (howto);
+  switch (size)
+    {
+    case 2:
+      contents = bfd_get_16 (abfd, address);
+      break;
+    case 4:
+      if (howto->src_mask != 0xffffffff)
+	/* Must be 32-bit instruction, always little-endian.  */
+	contents = bfd_getl32 (address);
+      else
+	/* Must be 32-bit data (endianness dependent).  */
+	contents = bfd_get_32 (abfd, address);
+      break;
+    case 8:
+      contents = bfd_get_64 (abfd, address);
+      break;
+    default:
+      abort ();
+    }
+
+  switch (howto->complain_on_overflow)
+    {
+    case complain_overflow_dont:
+      break;
+    case complain_overflow_signed:
+      status = aarch64_signed_overflow (addend,
+					howto->bitsize + howto->rightshift);
+      break;
+    case complain_overflow_unsigned:
+      status = aarch64_unsigned_overflow (addend,
+					  howto->bitsize + howto->rightshift);
+      break;
+    case complain_overflow_bitfield:
+    default:
+      abort ();
+    }
+
+  addend >>= howto->rightshift;
+
+  switch (howto->type)
+    {
+    case R_AARCH64_JUMP26:
+    case R_AARCH64_CALL26:
+      contents = reencode_branch_ofs_26 (contents, addend);
+      break;
+
+    case R_AARCH64_CONDBR19:
+      contents = reencode_cond_branch_ofs_19 (contents, addend);
+      break;
+
+    case R_AARCH64_TSTBR14:
+      contents = reencode_tst_branch_ofs_14 (contents, addend);
+      break;
+
+    case R_AARCH64_LD_PREL_LO19:
+      if (old_addend & ((1 << howto->rightshift) - 1))
+	return bfd_reloc_overflow;
+      contents = reencode_ld_lit_ofs_19 (contents, addend);
+      break;
+
+    case R_AARCH64_TLSDESC_CALL:
+      break;
+
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+    case R_AARCH64_ADR_GOT_PAGE:
+    case R_AARCH64_ADR_PREL_LO21:
+    case R_AARCH64_ADR_PREL_PG_HI21:
+    case R_AARCH64_ADR_PREL_PG_HI21_NC:
+      contents = reencode_adr_imm (contents, addend);
+      break;
+
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+    case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_ADD_ABS_LO12_NC:
+      /* Corresponds to: add rd, rn, #uimm12 to provide the low order
+         12 bits of the page offset following
+         R_AARCH64_ADR_PREL_PG_HI21 which computes the
+         (pc-relative) page base.  */
+      contents = reencode_add_imm (contents, addend);
+      break;
+
+    case R_AARCH64_LDST8_ABS_LO12_NC:
+    case R_AARCH64_LDST16_ABS_LO12_NC:
+    case R_AARCH64_LDST32_ABS_LO12_NC:
+    case R_AARCH64_LDST64_ABS_LO12_NC:
+    case R_AARCH64_LDST128_ABS_LO12_NC:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+    case R_AARCH64_LD64_GOT_LO12_NC:
+      if (old_addend & ((1 << howto->rightshift) - 1))
+	return bfd_reloc_overflow;
+      /* Used for ldr*|str* rt, [rn, #uimm12] to provide the low order
+         12 bits of the page offset following R_AARCH64_ADR_PREL_PG_HI21
+         which computes the (pc-relative) page base. */
+      contents = reencode_ldst_pos_imm (contents, addend);
+      break;
+
+      /* Group relocations to create high bits of a 16, 32, 48 or 64
+         bit signed data or abs address inline. Will change
+         instruction to MOVN or MOVZ depending on sign of calculated
+         value. */
+
+    case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+    case R_AARCH64_MOVW_SABS_G0:
+    case R_AARCH64_MOVW_SABS_G1:
+    case R_AARCH64_MOVW_SABS_G2:
+      /* NOTE: We can only come here with movz or movn. */
+      if (addend < 0)
+	{
+	  /* Force use of MOVN.  */
+	  addend = ~addend;
+	  contents = reencode_movzn_to_movn (contents);
+	}
+      else
+	{
+	  /* Force use of MOVZ.  */
+	  contents = reencode_movzn_to_movz (contents);
+	}
+      /* fall through */
+
+      /* Group relocations to create a 16, 32, 48 or 64 bit unsigned
+         data or abs address inline. */
+
+    case R_AARCH64_MOVW_UABS_G0:
+    case R_AARCH64_MOVW_UABS_G0_NC:
+    case R_AARCH64_MOVW_UABS_G1:
+    case R_AARCH64_MOVW_UABS_G1_NC:
+    case R_AARCH64_MOVW_UABS_G2:
+    case R_AARCH64_MOVW_UABS_G2_NC:
+    case R_AARCH64_MOVW_UABS_G3:
+      contents = reencode_movw_imm (contents, addend);
+      break;
+
+    default:
+      /* Repack simple data */
+      if (howto->dst_mask & (howto->dst_mask + 1))
+	return bfd_reloc_notsupported;
+
+      contents = ((contents & ~howto->dst_mask) | (addend & howto->dst_mask));
+      break;
+    }
+
+  switch (size)
+    {
+    case 2:
+      bfd_put_16 (abfd, contents, address);
+      break;
+    case 4:
+      if (howto->dst_mask != 0xffffffff)
+	/* must be 32-bit instruction, always little-endian */
+	bfd_putl32 (contents, address);
+      else
+	/* must be 32-bit data (endianness dependent) */
+	bfd_put_32 (abfd, contents, address);
+      break;
+    case 8:
+      bfd_put_64 (abfd, contents, address);
+      break;
+    default:
+      abort ();
+    }
+
+  return status;
+}
+
+static bfd_vma
+aarch64_calculate_got_entry_vma (struct elf_link_hash_entry *h,
+				 struct elf64_aarch64_link_hash_table
+				 *globals, struct bfd_link_info *info,
+				 bfd_vma value, bfd * output_bfd,
+				 bfd_boolean * unresolved_reloc_p)
+{
+  bfd_vma off = (bfd_vma) - 1;
+  asection *basegot = globals->root.sgot;
+  bfd_boolean dyn = globals->root.dynamic_sections_created;
+
+  if (h != NULL)
+    {
+      off = h->got.offset;
+      BFD_ASSERT (off != (bfd_vma) - 1);
+      if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
+	  || (info->shared
+	      && SYMBOL_REFERENCES_LOCAL (info, h))
+	  || (ELF_ST_VISIBILITY (h->other)
+	      && h->root.type == bfd_link_hash_undefweak))
+	{
+	  /* This is actually a static link, or it is a -Bsymbolic link
+	     and the symbol is defined locally.  We must initialize this
+	     entry in the global offset table.  Since the offset must
+	     always be a multiple of 8, we use the least significant bit
+	     to record whether we have initialized it already.
+	     When doing a dynamic link, we create a .rel(a).got relocation
+	     entry to initialize the value.  This is done in the
+	     finish_dynamic_symbol routine.  */
+	  if ((off & 1) != 0)
+	    off &= ~1;
+	  else
+	    {
+	      bfd_put_64 (output_bfd, value, basegot->contents + off);
+	      h->got.offset |= 1;
+	    }
+	}
+      else
+	*unresolved_reloc_p = FALSE;
+
+      off = off + basegot->output_section->vma + basegot->output_offset;
+    }
+
+  return off;
+}
+
+/* Change R_TYPE to a more efficient access model where possible,
+   return the new reloc type.  */
+
+static unsigned int
+aarch64_tls_transition_without_check (unsigned int r_type,
+				      struct elf_link_hash_entry *h)
+{
+  bfd_boolean is_local = h == NULL;
+  switch (r_type)
+    {
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+      return is_local
+	? R_AARCH64_TLSLE_MOVW_TPREL_G1 : R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21;
+
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+      return is_local
+	? R_AARCH64_TLSLE_MOVW_TPREL_G0_NC
+	: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
+
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+      return is_local ? R_AARCH64_TLSLE_MOVW_TPREL_G1 : r_type;
+
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+      return is_local ? R_AARCH64_TLSLE_MOVW_TPREL_G0_NC : r_type;
+
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_CALL:
+      /* Instructions with these relocations will become NOPs.  */
+      return R_AARCH64_NONE;
+    }
+
+  return r_type;
+}
+
+static unsigned int
+aarch64_reloc_got_type (unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case R_AARCH64_LD64_GOT_LO12_NC:
+    case R_AARCH64_ADR_GOT_PAGE:
+      return GOT_NORMAL;
+
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+      return GOT_TLS_GD;
+
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+    case R_AARCH64_TLSDESC_CALL:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+      return GOT_TLSDESC_GD;
+
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+      return GOT_TLS_IE;
+
+    case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+      return GOT_UNKNOWN;
+    }
+  return GOT_UNKNOWN;
+}
+
+static bfd_boolean
+aarch64_can_relax_tls (bfd *input_bfd,
+		       struct bfd_link_info *info,
+		       unsigned int r_type,
+		       struct elf_link_hash_entry *h,
+		       unsigned long r_symndx)
+{
+  unsigned int symbol_got_type;
+  unsigned int reloc_got_type;
+
+  if (! IS_AARCH64_TLS_RELOC (r_type))
+    return FALSE;
+
+  symbol_got_type = elf64_aarch64_symbol_got_type (h, input_bfd, r_symndx);
+  reloc_got_type = aarch64_reloc_got_type (r_type);
+
+  if (symbol_got_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (reloc_got_type))
+    return TRUE;
+
+  if (info->shared)
+    return FALSE;
+
+  if  (h && h->root.type == bfd_link_hash_undefweak)
+    return FALSE;
+
+  return TRUE;
+}
+
+static unsigned int
+aarch64_tls_transition (bfd *input_bfd,
+			struct bfd_link_info *info,
+			unsigned int r_type,
+			struct elf_link_hash_entry *h,
+			unsigned long r_symndx)
+{
+  if (! aarch64_can_relax_tls (input_bfd, info, r_type, h, r_symndx))
+    return r_type;
+
+  return aarch64_tls_transition_without_check (r_type, h);
+}
+
+/* Return the base VMA address which should be subtracted from real addresses
+   when resolving R_AARCH64_TLS_DTPREL64 relocation. */
+
+static bfd_vma
+dtpoff_base (struct bfd_link_info *info)
+{
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
+  return elf_hash_table (info)->tls_sec->vma;
+}
+
+
+/* Return the base VMA address which should be subtracted from real addresses
+   when resolving R_AARCH64_TLS_GOTTPREL64 relocations.  */
+
+static bfd_vma
+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_vma base = align_power ((bfd_vma) TCB_SIZE,
+			      htab->tls_sec->alignment_power);
+  return htab->tls_sec->vma - base;
+}
+
+static bfd_vma *
+symbol_got_offset_ref (bfd *input_bfd, struct elf_link_hash_entry *h,
+		       unsigned long r_symndx)
+{
+  /* Calculate the address of the GOT entry for symbol
+     referred to in h.  */
+  if (h != NULL)
+    return &h->got.offset;
+  else
+    {
+      /* local symbol */
+      struct elf_aarch64_local_symbol *l;
+
+      l = elf64_aarch64_locals (input_bfd);
+      return &l[r_symndx].got_offset;
+    }
+}
+
+static void
+symbol_got_offset_mark (bfd *input_bfd, struct elf_link_hash_entry *h,
+			unsigned long r_symndx)
+{
+  bfd_vma *p;
+  p = symbol_got_offset_ref (input_bfd, h, r_symndx);
+  *p |= 1;
+}
+
+static int
+symbol_got_offset_mark_p (bfd *input_bfd, struct elf_link_hash_entry *h,
+			  unsigned long r_symndx)
+{
+  bfd_vma value;
+  value = * symbol_got_offset_ref (input_bfd, h, r_symndx);
+  return value & 1;
+}
+
+static bfd_vma
+symbol_got_offset (bfd *input_bfd, struct elf_link_hash_entry *h,
+		   unsigned long r_symndx)
+{
+  bfd_vma value;
+  value = * symbol_got_offset_ref (input_bfd, h, r_symndx);
+  value &= ~1;
+  return value;
+}
+
+static bfd_vma *
+symbol_tlsdesc_got_offset_ref (bfd *input_bfd, struct elf_link_hash_entry *h,
+			       unsigned long r_symndx)
+{
+  /* Calculate the address of the GOT entry for symbol
+     referred to in h.  */
+  if (h != NULL)
+    {
+      struct elf64_aarch64_link_hash_entry *eh;
+      eh = (struct elf64_aarch64_link_hash_entry *) h;
+      return &eh->tlsdesc_got_jump_table_offset;
+    }
+  else
+    {
+      /* local symbol */
+      struct elf_aarch64_local_symbol *l;
+
+      l = elf64_aarch64_locals (input_bfd);
+      return &l[r_symndx].tlsdesc_got_jump_table_offset;
+    }
+}
+
+static void
+symbol_tlsdesc_got_offset_mark (bfd *input_bfd, struct elf_link_hash_entry *h,
+				unsigned long r_symndx)
+{
+  bfd_vma *p;
+  p = symbol_tlsdesc_got_offset_ref (input_bfd, h, r_symndx);
+  *p |= 1;
+}
+
+static int
+symbol_tlsdesc_got_offset_mark_p (bfd *input_bfd,
+				  struct elf_link_hash_entry *h,
+				  unsigned long r_symndx)
+{
+  bfd_vma value;
+  value = * symbol_tlsdesc_got_offset_ref (input_bfd, h, r_symndx);
+  return value & 1;
+}
+
+static bfd_vma
+symbol_tlsdesc_got_offset (bfd *input_bfd, struct elf_link_hash_entry *h,
+			  unsigned long r_symndx)
+{
+  bfd_vma value;
+  value = * symbol_tlsdesc_got_offset_ref (input_bfd, h, r_symndx);
+  value &= ~1;
+  return value;
+}
+
+/* Perform a relocation as part of a final link.  */
+static bfd_reloc_status_type
+elf64_aarch64_final_link_relocate (reloc_howto_type * howto,
+				   bfd * input_bfd,
+				   bfd * output_bfd,
+				   asection * input_section,
+				   bfd_byte * contents,
+				   Elf_Internal_Rela * rel,
+				   bfd_vma value,
+				   struct bfd_link_info *info,
+				   asection * sym_sec,
+				   struct elf_link_hash_entry *h,
+				   bfd_boolean * unresolved_reloc_p,
+				   bfd_boolean save_addend,
+				   bfd_vma * saved_addend)
+{
+  unsigned int r_type = howto->type;
+  unsigned long r_symndx;
+  bfd_byte *hit_data = contents + rel->r_offset;
+  bfd_vma place;
+  bfd_signed_vma signed_addend;
+  struct elf64_aarch64_link_hash_table *globals;
+  bfd_boolean weak_undef_p;
+
+  globals = elf64_aarch64_hash_table (info);
+
+  BFD_ASSERT (is_aarch64_elf (input_bfd));
+
+  r_symndx = ELF64_R_SYM (rel->r_info);
+
+  /* It is possible to have linker relaxations on some TLS access
+     models.  Update our information here.  */
+  r_type = aarch64_tls_transition (input_bfd, info, r_type, h, r_symndx);
+
+  if (r_type != howto->type)
+    howto = elf64_aarch64_howto_from_type (r_type);
+
+  place = input_section->output_section->vma
+    + input_section->output_offset + rel->r_offset;
+
+  /* Get addend, accumulating the addend for consecutive relocs
+     which refer to the same offset. */
+  signed_addend = saved_addend ? *saved_addend : 0;
+  signed_addend += rel->r_addend;
+
+  weak_undef_p = (h ? h->root.type == bfd_link_hash_undefweak
+		  : bfd_is_und_section (sym_sec));
+  switch (r_type)
+    {
+    case R_AARCH64_NONE:
+    case R_AARCH64_NULL:
+    case R_AARCH64_TLSDESC_CALL:
+      *unresolved_reloc_p = FALSE;
+      return bfd_reloc_ok;
+
+    case R_AARCH64_ABS64:
+
+      /* When generating a shared object or relocatable executable, these
+         relocations are copied into the output file to be resolved at
+         run time.  */
+      if (((info->shared == TRUE) || globals->root.is_relocatable_executable)
+	  && (input_section->flags & SEC_ALLOC)
+	  && (h == NULL
+	      || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+	      || h->root.type != bfd_link_hash_undefweak))
+	{
+	  Elf_Internal_Rela outrel;
+	  bfd_byte *loc;
+	  bfd_boolean skip, relocate;
+	  asection *sreloc;
+
+	  *unresolved_reloc_p = FALSE;
+
+	  sreloc = _bfd_elf_get_dynamic_reloc_section (input_bfd,
+						       input_section, 1);
+	  if (sreloc == NULL)
+	    return bfd_reloc_notsupported;
+
+	  skip = FALSE;
+	  relocate = FALSE;
+
+	  outrel.r_addend = signed_addend;
+	  outrel.r_offset =
+	    _bfd_elf_section_offset (output_bfd, info, input_section,
+				     rel->r_offset);
+	  if (outrel.r_offset == (bfd_vma) - 1)
+	    skip = TRUE;
+	  else if (outrel.r_offset == (bfd_vma) - 2)
+	    {
+	      skip = TRUE;
+	      relocate = TRUE;
+	    }
+
+	  outrel.r_offset += (input_section->output_section->vma
+			      + input_section->output_offset);
+
+	  if (skip)
+	    memset (&outrel, 0, sizeof outrel);
+	  else if (h != NULL
+		   && h->dynindx != -1
+		   && (!info->shared || !info->symbolic || !h->def_regular))
+	    outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
+	  else
+	    {
+	      int symbol;
+
+	      /* On SVR4-ish systems, the dynamic loader cannot
+		 relocate the text and data segments independently,
+		 so the symbol does not matter.  */
+	      symbol = 0;
+	      outrel.r_info = ELF64_R_INFO (symbol, R_AARCH64_RELATIVE);
+	      outrel.r_addend += value;
+	    }
+
+	  loc = sreloc->contents + sreloc->reloc_count++ * RELOC_SIZE (htab);
+	  bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+
+	  if (sreloc->reloc_count * RELOC_SIZE (htab) > sreloc->size)
+	    {
+	      /* Sanity to check that we have previously allocated
+		 sufficient space in the relocation section for the
+		 number of relocations we actually want to emit. */
+	      abort ();
+	    }
+
+	  /* If this reloc is against an external symbol, we do not want to
+	     fiddle with the addend.  Otherwise, we need to include the symbol
+	     value so that it becomes an addend for the dynamic reloc.  */
+	  if (!relocate)
+	    return bfd_reloc_ok;
+
+	  return _bfd_final_link_relocate (howto, input_bfd, input_section,
+					   contents, rel->r_offset, value,
+					   signed_addend);
+	}
+      else
+	value += signed_addend;
+      break;
+
+    case R_AARCH64_JUMP26:
+    case R_AARCH64_CALL26:
+      {
+	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.
+	   The jump to the next instruction is optimized as a NOP.
+	   Do the same for local undefined symbols. */
+	if (weak_undef_p && ! via_plt_p)
+	  {
+	    bfd_putl32 (INSN_NOP, hit_data);
+	    return bfd_reloc_ok;
+	  }
+
+	/* If the call goes through a PLT entry, make sure to
+	   check distance to the right destination address.  */
+	if (via_plt_p)
+	  {
+	    value = (splt->output_section->vma
+		     + splt->output_offset + h->plt.offset);
+	    *unresolved_reloc_p = FALSE;
+	  }
+
+	/* If the target symbol is global and marked as a function the
+	   relocation applies a function call or a tail call.  In this
+	   situation we can veneer out of range branches.  The veneers
+	   use IP0 and IP1 hence cannot be used arbitrary out of range
+	   branches that occur within the body of a function.  */
+	if (h && h->type == STT_FUNC)
+	  {
+	    /* Check if a stub has to be inserted because the destination
+	       is too far away.  */
+	    if (! aarch64_valid_branch_p (value, place))
+	      {
+		/* The target is out of reach, so redirect the branch to
+		   the local stub for this function.  */
+		struct elf64_aarch64_stub_hash_entry *stub_entry;
+		stub_entry = elf64_aarch64_get_stub_entry (input_section,
+							   sym_sec, h,
+							   rel, globals);
+		if (stub_entry != NULL)
+		  value = (stub_entry->stub_offset
+			   + stub_entry->stub_sec->output_offset
+			   + stub_entry->stub_sec->output_section->vma);
+	      }
+	  }
+      }
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  signed_addend, weak_undef_p);
+      break;
+
+    case R_AARCH64_ABS16:
+    case R_AARCH64_ABS32:
+    case R_AARCH64_ADD_ABS_LO12_NC:
+    case R_AARCH64_ADR_PREL_LO21:
+    case R_AARCH64_ADR_PREL_PG_HI21:
+    case R_AARCH64_ADR_PREL_PG_HI21_NC:
+    case R_AARCH64_CONDBR19:
+    case R_AARCH64_LD_PREL_LO19:
+    case R_AARCH64_LDST8_ABS_LO12_NC:
+    case R_AARCH64_LDST16_ABS_LO12_NC:
+    case R_AARCH64_LDST32_ABS_LO12_NC:
+    case R_AARCH64_LDST64_ABS_LO12_NC:
+    case R_AARCH64_LDST128_ABS_LO12_NC:
+    case R_AARCH64_MOVW_SABS_G0:
+    case R_AARCH64_MOVW_SABS_G1:
+    case R_AARCH64_MOVW_SABS_G2:
+    case R_AARCH64_MOVW_UABS_G0:
+    case R_AARCH64_MOVW_UABS_G0_NC:
+    case R_AARCH64_MOVW_UABS_G1:
+    case R_AARCH64_MOVW_UABS_G1_NC:
+    case R_AARCH64_MOVW_UABS_G2:
+    case R_AARCH64_MOVW_UABS_G2_NC:
+    case R_AARCH64_MOVW_UABS_G3:
+    case R_AARCH64_PREL16:
+    case R_AARCH64_PREL32:
+    case R_AARCH64_PREL64:
+    case R_AARCH64_TSTBR14:
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  signed_addend, weak_undef_p);
+      break;
+
+    case R_AARCH64_LD64_GOT_LO12_NC:
+    case R_AARCH64_ADR_GOT_PAGE:
+      if (globals->root.sgot == NULL)
+	BFD_ASSERT (h != NULL);
+
+      if (h != NULL)
+	{
+	  value = aarch64_calculate_got_entry_vma (h, globals, info, value,
+						   output_bfd,
+						   unresolved_reloc_p);
+	  value = aarch64_resolve_relocation (r_type, place, value,
+					      0, weak_undef_p);
+	}
+      break;
+
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+      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);
+
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  0, weak_undef_p);
+      *unresolved_reloc_p = FALSE;
+      break;
+
+    case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  - tpoff_base (info), weak_undef_p);
+      *unresolved_reloc_p = FALSE;
+      break;
+
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD:
+    case R_AARCH64_TLSDESC_LDR:
+      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->sgotplt_jump_table_size);
+
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  0, weak_undef_p);
+      *unresolved_reloc_p = FALSE;
+      break;
+
+    default:
+      return bfd_reloc_notsupported;
+    }
+
+  if (saved_addend)
+    *saved_addend = value;
+
+  /* Only apply the final relocation in a sequence.  */
+  if (save_addend)
+    return bfd_reloc_continue;
+
+  return bfd_elf_aarch64_put_addend (input_bfd, hit_data, howto, value);
+}
+
+/* Handle TLS relaxations.  Relaxing is possible for symbols that use
+   R_AARCH64_TLSDESC_ADR_{PAGE, LD64_LO12_NC, ADD_LO12_NC} during a static
+   link.
+
+   Return bfd_reloc_ok if we're done, bfd_reloc_continue if the caller
+   is to then call final_link_relocate.  Return other values in the
+   case of error.  */
+
+static bfd_reloc_status_type
+elf64_aarch64_tls_relax (struct elf64_aarch64_link_hash_table *globals,
+			 bfd * input_bfd, bfd_byte * contents,
+			 Elf_Internal_Rela * rel, struct elf_link_hash_entry *h)
+{
+  bfd_boolean is_local = h == NULL;
+  unsigned int r_type = ELF64_R_TYPE (rel->r_info);
+  unsigned long insn;
+
+  BFD_ASSERT (globals && input_bfd && contents && rel);
+
+  switch (r_type)
+    {
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+      if (is_local)
+	{
+	  /* GD->LE relaxation:
+	     adrp x0, :tlsgd:var     =>   movz x0, :tprel_g1:var
+	     or
+	     adrp x0, :tlsdesc:var   =>   movz x0, :tprel_g1:var
+	   */
+	  bfd_putl32 (0xd2a00000, contents + rel->r_offset);
+	  return bfd_reloc_continue;
+	}
+      else
+	{
+	  /* GD->IE relaxation:
+	     adrp x0, :tlsgd:var     =>   adrp x0, :gottprel:var
+	     or
+	     adrp x0, :tlsdesc:var   =>   adrp x0, :gottprel:var
+	   */
+	  insn = bfd_getl32 (contents + rel->r_offset);
+	  return bfd_reloc_continue;
+	}
+
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+      if (is_local)
+	{
+	  /* GD->LE relaxation:
+	     ldr xd, [x0, #:tlsdesc_lo12:var]   =>   movk x0, :tprel_g0_nc:var
+	   */
+	  bfd_putl32 (0xf2800000, contents + rel->r_offset);
+	  return bfd_reloc_continue;
+	}
+      else
+	{
+	  /* GD->IE relaxation:
+	     ldr xd, [x0, #:tlsdesc_lo12:var] => ldr x0, [x0, #:gottprel_lo12:var]
+	   */
+	  insn = bfd_getl32 (contents + rel->r_offset);
+	  insn &= 0xfffffff0;
+	  bfd_putl32 (insn, contents + rel->r_offset);
+	  return bfd_reloc_continue;
+	}
+
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+      if (is_local)
+	{
+	  /* GD->LE relaxation
+	     add  x0, #:tlsgd_lo12:var  => movk x0, :tprel_g0_nc:var
+	     bl   __tls_get_addr        => mrs  x1, tpidr_el0
+	     nop                        => add  x0, x1, x0
+	   */
+
+	  /* 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 = ELF64_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+
+	  bfd_putl32 (0xf2800000, contents + rel->r_offset);
+	  bfd_putl32 (0xd53bd041, contents + rel->r_offset + 4);
+	  bfd_putl32 (0x8b000020, contents + rel->r_offset + 8);
+	  return bfd_reloc_continue;
+	}
+      else
+	{
+	  /* GD->IE relaxation
+	     ADD  x0, #:tlsgd_lo12:var  => ldr  x0, [x0, #:gottprel_lo12:var]
+	     BL   __tls_get_addr        => mrs  x1, tpidr_el0
+	       R_AARCH64_CALL26
+	     NOP                        => add  x0, x1, x0
+	   */
+
+	  BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_AARCH64_CALL26);
+
+	  /* Remove the relocation on the BL instruction.  */
+	  rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+
+	  bfd_putl32 (0xf9400000, contents + rel->r_offset);
+
+	  /* We choose to fixup the BL and NOP instructions using the
+	     offset from the second relocation to allow flexibility in
+	     scheduling instructions between the ADD and BL.  */
+	  bfd_putl32 (0xd53bd041, contents + rel[1].r_offset);
+	  bfd_putl32 (0x8b000020, contents + rel[1].r_offset + 4);
+	  return bfd_reloc_continue;
+	}
+
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_CALL:
+      /* GD->IE/LE relaxation:
+         add x0, x0, #:tlsdesc_lo12:var   =>   nop
+         blr xd                           =>   nop
+       */
+      bfd_putl32 (INSN_NOP, contents + rel->r_offset);
+      return bfd_reloc_ok;
+
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+      /* IE->LE relaxation:
+         adrp xd, :gottprel:var   =>   movz xd, :tprel_g1:var
+       */
+      if (is_local)
+	{
+	  insn = bfd_getl32 (contents + rel->r_offset);
+	  bfd_putl32 (0xd2a00000 | (insn & 0x1f), contents + rel->r_offset);
+	}
+      return bfd_reloc_continue;
+
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+      /* IE->LE relaxation:
+         ldr  xd, [xm, #:gottprel_lo12:var]   =>   movk xd, :tprel_g0_nc:var
+       */
+      if (is_local)
+	{
+	  insn = bfd_getl32 (contents + rel->r_offset);
+	  bfd_putl32 (0xf2800000 | (insn & 0x1f), contents + rel->r_offset);
+	}
+      return bfd_reloc_continue;
+
+    default:
+      return bfd_reloc_continue;
+    }
+
+  return bfd_reloc_ok;
+}
+
+/* Relocate an AArch64 ELF section.  */
+
+static bfd_boolean
+elf64_aarch64_relocate_section (bfd * output_bfd,
+				struct bfd_link_info *info,
+				bfd * input_bfd,
+				asection * input_section,
+				bfd_byte * contents,
+				Elf_Internal_Rela * relocs,
+				Elf_Internal_Sym * local_syms,
+				asection ** local_sections)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  Elf_Internal_Rela *rel;
+  Elf_Internal_Rela *relend;
+  const char *name;
+  struct elf64_aarch64_link_hash_table *globals;
+  bfd_boolean save_addend = FALSE;
+  bfd_vma addend = 0;
+
+  globals = elf64_aarch64_hash_table (info);
+
+  symtab_hdr = &elf_symtab_hdr (input_bfd);
+  sym_hashes = elf_sym_hashes (input_bfd);
+
+  rel = relocs;
+  relend = relocs + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      unsigned int r_type;
+      unsigned int relaxed_r_type;
+      reloc_howto_type *howto;
+      unsigned long r_symndx;
+      Elf_Internal_Sym *sym;
+      asection *sec;
+      struct elf_link_hash_entry *h;
+      bfd_vma relocation;
+      bfd_reloc_status_type r;
+      arelent bfd_reloc;
+      char sym_type;
+      bfd_boolean unresolved_reloc = FALSE;
+      char *error_message = NULL;
+
+      r_symndx = ELF64_R_SYM (rel->r_info);
+      r_type = ELF64_R_TYPE (rel->r_info);
+
+      bfd_reloc.howto = elf64_aarch64_howto_from_type (r_type);
+      howto = bfd_reloc.howto;
+
+      h = NULL;
+      sym = NULL;
+      sec = NULL;
+
+      if (r_symndx < symtab_hdr->sh_info)
+	{
+	  sym = local_syms + r_symndx;
+	  sym_type = ELF64_ST_TYPE (sym->st_info);
+	  sec = local_sections[r_symndx];
+
+	  /* An object file might have a reference to a local
+	     undefined symbol.  This is a daft object file, but we
+	     should at least do something about it.  */
+	  if (r_type != R_AARCH64_NONE && r_type != R_AARCH64_NULL
+	      && bfd_is_und_section (sec)
+	      && ELF_ST_BIND (sym->st_info) != STB_WEAK)
+	    {
+	      if (!info->callbacks->undefined_symbol
+		  (info, bfd_elf_string_from_elf_section
+		   (input_bfd, symtab_hdr->sh_link, sym->st_name),
+		   input_bfd, input_section, rel->r_offset, TRUE))
+		return FALSE;
+	    }
+
+	  if (r_type >= R_AARCH64_dyn_max)
+	    {
+	      bfd_set_error (bfd_error_bad_value);
+	      return FALSE;
+	    }
+
+	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+	}
+      else
+	{
+	  bfd_boolean warned;
+
+	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+				   r_symndx, symtab_hdr, sym_hashes,
+				   h, sec, relocation,
+				   unresolved_reloc, warned);
+
+	  sym_type = h->type;
+	}
+
+      if (sec != NULL && discarded_section (sec))
+	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+					 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;
+	}
+
+      if (h != NULL)
+	name = h->root.root.string;
+      else
+	{
+	  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);
+	}
+
+      if (r_symndx != 0
+	  && r_type != R_AARCH64_NONE
+	  && r_type != R_AARCH64_NULL
+	  && (h == NULL
+	      || h->root.type == bfd_link_hash_defined
+	      || h->root.type == bfd_link_hash_defweak)
+	  && IS_AARCH64_TLS_RELOC (r_type) != (sym_type == STT_TLS))
+	{
+	  (*_bfd_error_handler)
+	    ((sym_type == STT_TLS
+	      ? _("%B(%A+0x%lx): %s used with TLS symbol %s")
+	      : _("%B(%A+0x%lx): %s used with non-TLS symbol %s")),
+	     input_bfd,
+	     input_section, (long) rel->r_offset, howto->name, name);
+	}
+
+
+      /* We relax only if we can see that there can be a valid transition
+         from a reloc type to another.
+         We call elf64_aarch64_final_link_relocate unless we're completely
+         done, i.e., the relaxation produced the final output we want.  */
+
+      relaxed_r_type = aarch64_tls_transition (input_bfd, info, r_type,
+					       h, r_symndx);
+      if (relaxed_r_type != r_type)
+	{
+	  r_type = relaxed_r_type;
+	  howto = elf64_aarch64_howto_from_type (r_type);
+
+	  r = elf64_aarch64_tls_relax (globals, input_bfd, contents, rel, h);
+	  unresolved_reloc = 0;
+	}
+      else
+	r = bfd_reloc_continue;
+
+      /* There may be multiple consecutive relocations for the
+         same offset.  In that case we are supposed to treat the
+         output of each relocation as the addend for the next.  */
+      if (rel + 1 < relend
+	  && rel->r_offset == rel[1].r_offset
+	  && ELF64_R_TYPE (rel[1].r_info) != R_AARCH64_NONE
+	  && ELF64_R_TYPE (rel[1].r_info) != R_AARCH64_NULL)
+	save_addend = TRUE;
+      else
+	save_addend = FALSE;
+
+      if (r == bfd_reloc_continue)
+	r = elf64_aarch64_final_link_relocate (howto, input_bfd, output_bfd,
+					       input_section, contents, rel,
+					       relocation, info, sec,
+					       h, &unresolved_reloc,
+					       save_addend, &addend);
+
+      switch (r_type)
+	{
+	case R_AARCH64_TLSGD_ADR_PAGE21:
+	case R_AARCH64_TLSGD_ADD_LO12_NC:
+	  if (! symbol_got_offset_mark_p (input_bfd, h, r_symndx))
+	    {
+	      bfd_boolean need_relocs = FALSE;
+	      bfd_byte *loc;
+	      int indx;
+	      bfd_vma off;
+
+	      off = symbol_got_offset (input_bfd, h, r_symndx);
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      need_relocs =
+		(info->shared || indx != 0) &&
+		(h == NULL
+		 || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		 || h->root.type != bfd_link_hash_undefweak);
+
+	      BFD_ASSERT (globals->root.srelgot != NULL);
+
+	      if (need_relocs)
+		{
+		  Elf_Internal_Rela rela;
+		  rela.r_info = ELF64_R_INFO (indx, R_AARCH64_TLS_DTPMOD64);
+		  rela.r_addend = 0;
+		  rela.r_offset = globals->root.sgot->output_section->vma +
+		    globals->root.sgot->output_offset + off;
+
+
+		  loc = globals->root.srelgot->contents;
+		  loc += globals->root.srelgot->reloc_count++
+		    * RELOC_SIZE (htab);
+		  bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+
+		  if (indx == 0)
+		    {
+		      bfd_put_64 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  globals->root.sgot->contents + off
+				  + GOT_ENTRY_SIZE);
+		    }
+		  else
+		    {
+		      /* This TLS symbol is global. We emit a
+			 relocation to fixup the tls offset at load
+			 time.  */
+		      rela.r_info =
+			ELF64_R_INFO (indx, R_AARCH64_TLS_DTPREL64);
+		      rela.r_addend = 0;
+		      rela.r_offset =
+			(globals->root.sgot->output_section->vma
+			 + globals->root.sgot->output_offset + off
+			 + GOT_ENTRY_SIZE);
+
+		      loc = globals->root.srelgot->contents;
+		      loc += globals->root.srelgot->reloc_count++
+			* RELOC_SIZE (globals);
+		      bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+		      bfd_put_64 (output_bfd, (bfd_vma) 0,
+				  globals->root.sgot->contents + off
+				  + GOT_ENTRY_SIZE);
+		    }
+		}
+	      else
+		{
+		  bfd_put_64 (output_bfd, (bfd_vma) 1,
+			      globals->root.sgot->contents + off);
+		  bfd_put_64 (output_bfd,
+			      relocation - dtpoff_base (info),
+			      globals->root.sgot->contents + off
+			      + GOT_ENTRY_SIZE);
+		}
+
+	      symbol_got_offset_mark (input_bfd, h, r_symndx);
+	    }
+	  break;
+
+	case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+	case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+	  if (! symbol_got_offset_mark_p (input_bfd, h, r_symndx))
+	    {
+	      bfd_boolean need_relocs = FALSE;
+	      bfd_byte *loc;
+	      int indx;
+	      bfd_vma off;
+
+	      off = symbol_got_offset (input_bfd, h, r_symndx);
+
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      need_relocs =
+		(info->shared || indx != 0) &&
+		(h == NULL
+		 || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		 || h->root.type != bfd_link_hash_undefweak);
+
+	      BFD_ASSERT (globals->root.srelgot != NULL);
+
+	      if (need_relocs)
+		{
+		  Elf_Internal_Rela rela;
+
+		  if (indx == 0)
+		    rela.r_addend = relocation - dtpoff_base (info);
+		  else
+		    rela.r_addend = 0;
+
+		  rela.r_info = ELF64_R_INFO (indx, R_AARCH64_TLS_TPREL64);
+		  rela.r_offset = globals->root.sgot->output_section->vma +
+		    globals->root.sgot->output_offset + off;
+
+		  loc = globals->root.srelgot->contents;
+		  loc += globals->root.srelgot->reloc_count++
+		    * RELOC_SIZE (htab);
+
+		  bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+
+		  bfd_put_64 (output_bfd, rela.r_addend,
+			      globals->root.sgot->contents + off);
+		}
+	      else
+		bfd_put_64 (output_bfd, relocation - tpoff_base (info),
+			    globals->root.sgot->contents + off);
+
+	      symbol_got_offset_mark (input_bfd, h, r_symndx);
+	    }
+	  break;
+
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+	case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+	  break;
+
+	case R_AARCH64_TLSDESC_ADR_PAGE:
+	case R_AARCH64_TLSDESC_LD64_LO12_NC:
+	case R_AARCH64_TLSDESC_ADD_LO12_NC:
+	  if (! symbol_tlsdesc_got_offset_mark_p (input_bfd, h, r_symndx))
+	    {
+	      bfd_boolean need_relocs = FALSE;
+	      int indx = h && h->dynindx != -1 ? h->dynindx : 0;
+	      bfd_vma off = symbol_tlsdesc_got_offset (input_bfd, h, r_symndx);
+
+	      need_relocs = (h == NULL
+			     || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+			     || h->root.type != bfd_link_hash_undefweak);
+
+	      BFD_ASSERT (globals->root.srelgot != NULL);
+	      BFD_ASSERT (globals->root.sgot != NULL);
+
+	      if (need_relocs)
+		{
+		  bfd_byte *loc;
+		  Elf_Internal_Rela rela;
+		  rela.r_info = ELF64_R_INFO (indx, R_AARCH64_TLSDESC);
+		  rela.r_addend = 0;
+		  rela.r_offset = (globals->root.sgotplt->output_section->vma
+				   + globals->root.sgotplt->output_offset
+				   + off + globals->sgotplt_jump_table_size);
+
+		  if (indx == 0)
+		    rela.r_addend = relocation - dtpoff_base (info);
+
+		  /* Allocate the next available slot in the PLT reloc
+		     section to hold our R_AARCH64_TLSDESC, the next
+		     available slot is determined from reloc_count,
+		     which we step. But note, reloc_count was
+		     artifically moved down while allocating slots for
+		     real PLT relocs such that all of the PLT relocs
+		     will fit above the initial reloc_count and the
+		     extra stuff will fit below.  */
+		  loc = globals->root.srelplt->contents;
+		  loc += globals->root.srelplt->reloc_count++
+		    * RELOC_SIZE (globals);
+
+		  bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+
+		  bfd_put_64 (output_bfd, (bfd_vma) 0,
+			      globals->root.sgotplt->contents + off +
+			      globals->sgotplt_jump_table_size);
+		  bfd_put_64 (output_bfd, (bfd_vma) 0,
+			      globals->root.sgotplt->contents + off +
+			      globals->sgotplt_jump_table_size +
+			      GOT_ENTRY_SIZE);
+		}
+
+	      symbol_tlsdesc_got_offset_mark (input_bfd, h, r_symndx);
+	    }
+	  break;
+	}
+
+      if (!save_addend)
+	addend = 0;
+
+
+      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
+         because such sections are not SEC_ALLOC and thus ld.so will
+         not process them.  */
+      if (unresolved_reloc
+	  && !((input_section->flags & SEC_DEBUGGING) != 0
+	       && h->def_dynamic)
+	  && _bfd_elf_section_offset (output_bfd, info, input_section,
+				      +rel->r_offset) != (bfd_vma) - 1)
+	{
+	  (*_bfd_error_handler)
+	    (_
+	     ("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
+	     input_bfd, input_section, (long) rel->r_offset, howto->name,
+	     h->root.root.string);
+	  return FALSE;
+	}
+
+      if (r != bfd_reloc_ok && r != bfd_reloc_continue)
+	{
+	  switch (r)
+	    {
+	    case bfd_reloc_overflow:
+	      /* If the overflowing reloc was to an undefined symbol,
+		 we have already printed one error message and there
+		 is no point complaining again.  */
+	      if ((!h ||
+		   h->root.type != bfd_link_hash_undefined)
+		  && (!((*info->callbacks->reloc_overflow)
+			(info, (h ? &h->root : NULL), name, howto->name,
+			 (bfd_vma) 0, input_bfd, input_section,
+			 rel->r_offset))))
+		return FALSE;
+	      break;
+
+	    case bfd_reloc_undefined:
+	      if (!((*info->callbacks->undefined_symbol)
+		    (info, name, input_bfd, input_section,
+		     rel->r_offset, TRUE)))
+		return FALSE;
+	      break;
+
+	    case bfd_reloc_outofrange:
+	      error_message = _("out of range");
+	      goto common_error;
+
+	    case bfd_reloc_notsupported:
+	      error_message = _("unsupported relocation");
+	      goto common_error;
+
+	    case bfd_reloc_dangerous:
+	      /* error_message should already be set.  */
+	      goto common_error;
+
+	    default:
+	      error_message = _("unknown error");
+	      /* Fall through.  */
+
+	    common_error:
+	      BFD_ASSERT (error_message != NULL);
+	      if (!((*info->callbacks->reloc_dangerous)
+		    (info, error_message, input_bfd, input_section,
+		     rel->r_offset)))
+		return FALSE;
+	      break;
+	    }
+	}
+    }
+
+  return TRUE;
+}
+
+/* Set the right machine number.  */
+
+static bfd_boolean
+elf64_aarch64_object_p (bfd * abfd)
+{
+  bfd_default_set_arch_mach (abfd, bfd_arch_aarch64, bfd_mach_aarch64);
+  return TRUE;
+}
+
+/* Function to keep AArch64 specific flags in the ELF header.  */
+
+static bfd_boolean
+elf64_aarch64_set_private_flags (bfd * abfd, flagword flags)
+{
+  if (elf_flags_init (abfd) && elf_elfheader (abfd)->e_flags != flags)
+    {
+    }
+  else
+    {
+      elf_elfheader (abfd)->e_flags = flags;
+      elf_flags_init (abfd) = TRUE;
+    }
+
+  return TRUE;
+}
+
+/* Copy backend specific data from one object module to another.  */
+
+static bfd_boolean
+elf64_aarch64_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
+{
+  flagword in_flags;
+
+  if (!is_aarch64_elf (ibfd) || !is_aarch64_elf (obfd))
+    return TRUE;
+
+  in_flags = elf_elfheader (ibfd)->e_flags;
+
+  elf_elfheader (obfd)->e_flags = in_flags;
+  elf_flags_init (obfd) = TRUE;
+
+  /* Also copy the EI_OSABI field.  */
+  elf_elfheader (obfd)->e_ident[EI_OSABI] =
+    elf_elfheader (ibfd)->e_ident[EI_OSABI];
+
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
+  return TRUE;
+}
+
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bfd_boolean
+elf64_aarch64_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
+{
+  flagword out_flags;
+  flagword in_flags;
+  bfd_boolean flags_compatible = TRUE;
+  asection *sec;
+
+  /* Check if we have the same endianess.  */
+  if (!_bfd_generic_verify_endian_match (ibfd, obfd))
+    return FALSE;
+
+  if (!is_aarch64_elf (ibfd) || !is_aarch64_elf (obfd))
+    return TRUE;
+
+  /* The input BFD must have had its flags initialised.  */
+  /* The following seems bogus to me -- The flags are initialized in
+     the assembler but I don't think an elf_flags_init field is
+     written into the object.  */
+  /* BFD_ASSERT (elf_flags_init (ibfd)); */
+
+  in_flags = elf_elfheader (ibfd)->e_flags;
+  out_flags = elf_elfheader (obfd)->e_flags;
+
+  if (!elf_flags_init (obfd))
+    {
+      /* If the input is the default architecture and had the default
+         flags then do not bother setting the flags for the output
+         architecture, instead allow future merges to do this.  If no
+         future merges ever set these flags then they will retain their
+         uninitialised values, which surprise surprise, correspond
+         to the default values.  */
+      if (bfd_get_arch_info (ibfd)->the_default
+	  && elf_elfheader (ibfd)->e_flags == 0)
+	return TRUE;
+
+      elf_flags_init (obfd) = TRUE;
+      elf_elfheader (obfd)->e_flags = in_flags;
+
+      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
+	  && bfd_get_arch_info (obfd)->the_default)
+	return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
+				  bfd_get_mach (ibfd));
+
+      return TRUE;
+    }
+
+  /* Identical flags must be compatible.  */
+  if (in_flags == out_flags)
+    return TRUE;
+
+  /* Check to see if the input BFD actually contains any sections.  If
+     not, its flags may not have been initialised either, but it
+     cannot actually cause any incompatiblity.  Do not short-circuit
+     dynamic objects; their section list may be emptied by
+     elf_link_add_object_symbols.
+
+     Also check to see if there are no code sections in the input.
+     In this case there is no need to check for code specific flags.
+     XXX - do we need to worry about floating-point format compatability
+     in data sections ?  */
+  if (!(ibfd->flags & DYNAMIC))
+    {
+      bfd_boolean null_input_bfd = TRUE;
+      bfd_boolean only_data_sections = TRUE;
+
+      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+	{
+	  if ((bfd_get_section_flags (ibfd, sec)
+	       & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+	      == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+	    only_data_sections = FALSE;
+
+	  null_input_bfd = FALSE;
+	  break;
+	}
+
+      if (null_input_bfd || only_data_sections)
+	return TRUE;
+    }
+
+  return flags_compatible;
+}
+
+/* Display the flags field.  */
+
+static bfd_boolean
+elf64_aarch64_print_private_bfd_data (bfd * abfd, void *ptr)
+{
+  FILE *file = (FILE *) ptr;
+  unsigned long flags;
+
+  BFD_ASSERT (abfd != NULL && ptr != NULL);
+
+  /* Print normal ELF private data.  */
+  _bfd_elf_print_private_bfd_data (abfd, ptr);
+
+  flags = elf_elfheader (abfd)->e_flags;
+  /* Ignore init flag - it may not be set, despite the flags field
+     containing valid data.  */
+
+  /* xgettext:c-format */
+  fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
+
+  if (flags)
+    fprintf (file, _("<Unrecognised flag bits set>"));
+
+  fputc ('\n', file);
+
+  return TRUE;
+}
+
+/* Update the got entry reference counts for the section being removed.  */
+
+static bfd_boolean
+elf64_aarch64_gc_sweep_hook (bfd * abfd ATTRIBUTE_UNUSED,
+			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
+			     asection * sec ATTRIBUTE_UNUSED,
+			     const Elf_Internal_Rela *
+			     relocs ATTRIBUTE_UNUSED)
+{
+  return TRUE;
+}
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+   regular object.  The current definition is in some section of the
+   dynamic object, but we're not including those sections.  We have to
+   change the definition to something the rest of the link can
+   understand.	*/
+
+static bfd_boolean
+elf64_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
+				     struct elf_link_hash_entry *h)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  asection *s;
+
+  /* If this is a function, put it in the procedure linkage table.  We
+     will fill in the contents of the procedure linkage table later,
+     when we know the address of the .got section.  */
+  if (h->type == STT_FUNC || h->needs_plt)
+    {
+      if (h->plt.refcount <= 0
+	  || SYMBOL_CALLS_LOCAL (info, h)
+	  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+	      && h->root.type == bfd_link_hash_undefweak))
+	{
+	  /* This case can occur if we saw a CALL26 reloc in
+	     an input file, but the symbol wasn't referred to
+	     by a dynamic object or all references were
+	     garbage collected. In which case we can end up
+	     resolving.  */
+	  h->plt.offset = (bfd_vma) - 1;
+	  h->needs_plt = 0;
+	}
+
+      return TRUE;
+    }
+  else
+    /* It's possible that we incorrectly decided a .plt reloc was
+       needed for an R_X86_64_PC32 reloc to a non-function sym in
+       check_relocs.  We can't decide accurately between function and
+       non-function syms in check-relocs;  Objects loaded later in
+       the link may change h->type.  So fix it now.  */
+    h->plt.offset = (bfd_vma) - 1;
+
+
+  /* If this is a weak symbol, and there is a real definition, the
+     processor independent code will have arranged for us to see the
+     real definition first, and we can just use the same value.  */
+  if (h->u.weakdef != NULL)
+    {
+      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+		  || h->u.weakdef->root.type == bfd_link_hash_defweak);
+      h->root.u.def.section = h->u.weakdef->root.u.def.section;
+      h->root.u.def.value = h->u.weakdef->root.u.def.value;
+      if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
+	h->non_got_ref = h->u.weakdef->non_got_ref;
+      return TRUE;
+    }
+
+  /* If we are creating a shared library, we must presume that the
+     only references to the symbol are via the global offset table.
+     For such cases we need not do anything here; the relocations will
+     be handled correctly by relocate_section.  */
+  if (info->shared)
+    return TRUE;
+
+  /* If there are no references to this symbol that do not use the
+     GOT, we don't need to generate a copy reloc.  */
+  if (!h->non_got_ref)
+    return TRUE;
+
+  /* If -z nocopyreloc was given, we won't generate them either.  */
+  if (info->nocopyreloc)
+    {
+      h->non_got_ref = 0;
+      return TRUE;
+    }
+
+  /* We must allocate the symbol in our .dynbss section, which will
+     become part of the .bss section of the executable.  There will be
+     an entry for this symbol in the .dynsym section.  The dynamic
+     object will contain position independent code, so all references
+     from the dynamic object to this symbol will go through the global
+     offset table.  The dynamic linker will use the .dynsym entry to
+     determine the address it must put in the global offset table, so
+     both the dynamic object and the regular object will refer to the
+     same memory location for the variable.  */
+
+  htab = elf64_aarch64_hash_table (info);
+
+  /* We must generate a R_AARCH64_COPY reloc to tell the dynamic linker
+     to copy the initial value out of the dynamic object and into the
+     runtime process image.  */
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
+    {
+      htab->srelbss->size += RELOC_SIZE (htab);
+      h->needs_copy = 1;
+    }
+
+  s = htab->sdynbss;
+
+  return _bfd_elf_adjust_dynamic_copy (h, s);
+
+}
+
+static bfd_boolean
+elf64_aarch64_allocate_local_symbols (bfd * abfd, unsigned number)
+{
+  struct elf_aarch64_local_symbol *locals;
+  locals = elf64_aarch64_locals (abfd);
+  if (locals == NULL)
+    {
+      locals = (struct elf_aarch64_local_symbol *)
+	bfd_zalloc (abfd, number * sizeof (struct elf_aarch64_local_symbol));
+      if (locals == NULL)
+	return FALSE;
+      elf64_aarch64_locals (abfd) = locals;
+    }
+  return TRUE;
+}
+
+/* Look through the relocs for a section during the first phase.  */
+
+static bfd_boolean
+elf64_aarch64_check_relocs (bfd * abfd, struct bfd_link_info *info,
+			    asection * sec, const Elf_Internal_Rela * relocs)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  const Elf_Internal_Rela *rel;
+  const Elf_Internal_Rela *rel_end;
+  asection *sreloc;
+
+  struct elf64_aarch64_link_hash_table *htab;
+
+  unsigned long nsyms;
+
+  if (info->relocatable)
+    return TRUE;
+
+  BFD_ASSERT (is_aarch64_elf (abfd));
+
+  htab = elf64_aarch64_hash_table (info);
+  sreloc = NULL;
+
+  symtab_hdr = &elf_symtab_hdr (abfd);
+  sym_hashes = elf_sym_hashes (abfd);
+  nsyms = NUM_SHDR_ENTRIES (symtab_hdr);
+
+  rel_end = relocs + sec->reloc_count;
+  for (rel = relocs; rel < rel_end; rel++)
+    {
+      struct elf_link_hash_entry *h;
+      unsigned long r_symndx;
+      unsigned int r_type;
+
+      r_symndx = ELF64_R_SYM (rel->r_info);
+      r_type = ELF64_R_TYPE (rel->r_info);
+
+      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
+	{
+	  (*_bfd_error_handler) (_("%B: bad symbol index: %d"), abfd,
+				 r_symndx);
+	  return FALSE;
+	}
+
+      if (r_symndx >= nsyms
+	  /* PR 9934: It is possible to have relocations that do not
+	     refer to symbols, thus it is also possible to have an
+	     object file containing relocations but no symbol table.  */
+	  && (r_symndx > 0 || nsyms > 0))
+	{
+	  (*_bfd_error_handler) (_("%B: bad symbol index: %d"), abfd,
+				 r_symndx);
+	  return FALSE;
+	}
+
+      if (nsyms == 0 || r_symndx < symtab_hdr->sh_info)
+	h = NULL;
+      else
+	{
+	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	}
+
+      /* Could be done earlier, if h were already available.  */
+      r_type = aarch64_tls_transition (abfd, info, r_type, h, r_symndx);
+
+      switch (r_type)
+	{
+	case R_AARCH64_ABS64:
+
+	  /* We don't need to handle relocs into sections not going into
+	     the "real" output.  */
+	  if ((sec->flags & SEC_ALLOC) == 0)
+	    break;
+
+	  if (h != NULL)
+	    {
+	      if (!info->shared)
+		h->non_got_ref = 1;
+
+	      h->plt.refcount += 1;
+	      h->pointer_equality_needed = 1;
+	    }
+
+	  /* No need to do anything if we're not creating a shared
+	     object.  */
+	  if (! info->shared)
+	    break;
+
+	  {
+	    struct elf_dyn_relocs *p;
+	    struct elf_dyn_relocs **head;
+
+	    /* We must copy these reloc types into the output file.
+	       Create a reloc section in dynobj and make room for
+	       this reloc.  */
+	    if (sreloc == NULL)
+	      {
+		if (htab->root.dynobj == NULL)
+		  htab->root.dynobj = abfd;
+
+		sreloc = _bfd_elf_make_dynamic_reloc_section
+		  (sec, htab->root.dynobj, 3, abfd, /*rela? */ TRUE);
+
+		if (sreloc == NULL)
+		  return FALSE;
+	      }
+
+	    /* If this is a global symbol, we count the number of
+	       relocations we need for this symbol.  */
+	    if (h != NULL)
+	      {
+		struct elf64_aarch64_link_hash_entry *eh;
+		eh = (struct elf64_aarch64_link_hash_entry *) h;
+		head = &eh->dyn_relocs;
+	      }
+	    else
+	      {
+		/*   Track dynamic relocs needed for local syms too.
+		     We really need local syms available to do this
+		     easily.  Oh well. */
+
+		asection *s;
+		void **vpp;
+		Elf_Internal_Sym *isym;
+
+		isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+					      abfd, r_symndx);
+		if (isym == NULL)
+		  return FALSE;
+
+		s = bfd_section_from_elf_index (abfd, isym->st_shndx);
+		if (s == NULL)
+		  s = sec;
+
+		/* Beware of type punned pointers vs strict aliasing
+		   rules.  */
+		vpp = &(elf_section_data (s)->local_dynrel);
+		head = (struct elf_dyn_relocs **) vpp;
+	      }
+
+	    p = *head;
+	    if (p == NULL || p->sec != sec)
+	      {
+		bfd_size_type amt = sizeof *p;
+		p = ((struct elf_dyn_relocs *)
+		     bfd_zalloc (htab->root.dynobj, amt));
+		if (p == NULL)
+		  return FALSE;
+		p->next = *head;
+		*head = p;
+		p->sec = sec;
+	      }
+
+	    p->count += 1;
+
+	  }
+	  break;
+
+	  /* RR: We probably want to keep a consistency check that
+	     there are no dangling GOT_PAGE relocs.  */
+	case R_AARCH64_LD64_GOT_LO12_NC:
+	case R_AARCH64_ADR_GOT_PAGE:
+	case R_AARCH64_TLSGD_ADR_PAGE21:
+	case R_AARCH64_TLSGD_ADD_LO12_NC:
+	case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+	case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+	case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+	case R_AARCH64_TLSDESC_ADR_PAGE:
+	case R_AARCH64_TLSDESC_ADD_LO12_NC:
+	case R_AARCH64_TLSDESC_LD64_LO12_NC:
+	  {
+	    unsigned got_type;
+	    unsigned old_got_type;
+
+	    got_type = aarch64_reloc_got_type (r_type);
+
+	    if (h)
+	      {
+		h->got.refcount += 1;
+		old_got_type = elf64_aarch64_hash_entry (h)->got_type;
+	      }
+	    else
+	      {
+		struct elf_aarch64_local_symbol *locals;
+
+		if (!elf64_aarch64_allocate_local_symbols
+		    (abfd, symtab_hdr->sh_info))
+		  return FALSE;
+
+		locals = elf64_aarch64_locals (abfd);
+		BFD_ASSERT (r_symndx < symtab_hdr->sh_info);
+		locals[r_symndx].got_refcount += 1;
+		old_got_type = locals[r_symndx].got_type;
+	      }
+
+	    /* If a variable is accessed with both general dynamic TLS
+	       methods, two slots may be created.  */
+	    if (GOT_TLS_GD_ANY_P (old_got_type) && GOT_TLS_GD_ANY_P (got_type))
+	      got_type |= old_got_type;
+
+	    /* We will already have issued an error message if there
+	       is a TLS/non-TLS mismatch, based on the symbol type.
+	       So just combine any TLS types needed.  */
+	    if (old_got_type != GOT_UNKNOWN && old_got_type != GOT_NORMAL
+		&& got_type != GOT_NORMAL)
+	      got_type |= old_got_type;
+
+	    /* If the symbol is accessed by both IE and GD methods, we
+	       are able to relax.  Turn off the GD flag, without
+	       messing up with any other kind of TLS types that may be
+	       involved.  */
+	    if ((got_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (got_type))
+	      got_type &= ~ (GOT_TLSDESC_GD | GOT_TLS_GD);
+
+	    if (old_got_type != got_type)
+	      {
+		if (h != NULL)
+		  elf64_aarch64_hash_entry (h)->got_type = got_type;
+		else
+		  {
+		    struct elf_aarch64_local_symbol *locals;
+		    locals = elf64_aarch64_locals (abfd);
+		    BFD_ASSERT (r_symndx < symtab_hdr->sh_info);
+		    locals[r_symndx].got_type = got_type;
+		  }
+	      }
+
+	    if (htab->root.sgot == NULL)
+	      {
+		if (htab->root.dynobj == NULL)
+		  htab->root.dynobj = abfd;
+		if (!_bfd_elf_create_got_section (htab->root.dynobj, info))
+		  return FALSE;
+	      }
+	    break;
+	  }
+
+	case R_AARCH64_ADR_PREL_PG_HI21_NC:
+	case R_AARCH64_ADR_PREL_PG_HI21:
+	  if (h != NULL && info->executable)
+	    {
+	      /* If this reloc is in a read-only section, we might
+		 need a copy reloc.  We can't check reliably at this
+		 stage whether the section is read-only, as input
+		 sections have not yet been mapped to output sections.
+		 Tentatively set the flag for now, and correct in
+		 adjust_dynamic_symbol.  */
+	      h->non_got_ref = 1;
+	      h->plt.refcount += 1;
+	      h->pointer_equality_needed = 1;
+	    }
+	  /* FIXME:: RR need to handle these in shared libraries
+	     and essentially bomb out as these being non-PIC
+	     relocations in shared libraries.  */
+	  break;
+
+	case R_AARCH64_CALL26:
+	case R_AARCH64_JUMP26:
+	  /* If this is a local symbol then we resolve it
+	     directly without creating a PLT entry.  */
+	  if (h == NULL)
+	    continue;
+
+	  h->needs_plt = 1;
+	  h->plt.refcount += 1;
+	  break;
+	}
+    }
+  return TRUE;
+}
+
+/* Treat mapping symbols as special target symbols.  */
+
+static bfd_boolean
+elf64_aarch64_is_target_special_symbol (bfd * abfd ATTRIBUTE_UNUSED,
+					asymbol * sym)
+{
+  return bfd_is_aarch64_special_symbol_name (sym->name,
+					     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.  */
+
+static bfd_boolean
+aarch64_elf_find_function (bfd * abfd ATTRIBUTE_UNUSED,
+			   asection * section,
+			   asymbol ** symbols,
+			   bfd_vma offset,
+			   const char **filename_ptr,
+			   const char **functionname_ptr)
+{
+  const char *filename = NULL;
+  asymbol *func = NULL;
+  bfd_vma low_func = 0;
+  asymbol **p;
+
+  for (p = symbols; *p != NULL; p++)
+    {
+      elf_symbol_type *q;
+
+      q = (elf_symbol_type *) * p;
+
+      switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
+	{
+	default:
+	  break;
+	case STT_FILE:
+	  filename = bfd_asymbol_name (&q->symbol);
+	  break;
+	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
+elf64_aarch64_find_nearest_line (bfd * abfd,
+				 asection * section,
+				 asymbol ** symbols,
+				 bfd_vma offset,
+				 const char **filename_ptr,
+				 const char **functionname_ptr,
+				 unsigned int *line_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,
+				     filename_ptr, functionname_ptr,
+				     line_ptr, 0,
+				     &elf_tdata
+				     (abfd)->dwarf2_find_line_info))
+    {
+      if (!*functionname_ptr)
+	aarch64_elf_find_function (abfd, section, symbols, offset,
+				   *filename_ptr ? NULL : filename_ptr,
+				   functionname_ptr);
+
+      return TRUE;
+    }
+
+  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;
+
+  if (!aarch64_elf_find_function (abfd, section, symbols, offset,
+				  filename_ptr, functionname_ptr))
+    return FALSE;
+
+  *line_ptr = 0;
+  return TRUE;
+}
+
+static bfd_boolean
+elf64_aarch64_find_inliner_info (bfd * abfd,
+				 const char **filename_ptr,
+				 const char **functionname_ptr,
+				 unsigned int *line_ptr)
+{
+  bfd_boolean found;
+  found = _bfd_dwarf2_find_inliner_info
+    (abfd, filename_ptr,
+     functionname_ptr, line_ptr, &elf_tdata (abfd)->dwarf2_find_line_info);
+  return found;
+}
+
+
+static void
+elf64_aarch64_post_process_headers (bfd * abfd,
+				    struct bfd_link_info *link_info
+				    ATTRIBUTE_UNUSED)
+{
+  Elf_Internal_Ehdr *i_ehdrp;	/* ELF file header, internal form.  */
+
+  i_ehdrp = elf_elfheader (abfd);
+  i_ehdrp->e_ident[EI_OSABI] = 0;
+  i_ehdrp->e_ident[EI_ABIVERSION] = AARCH64_ELF_ABI_VERSION;
+}
+
+static enum elf_reloc_type_class
+elf64_aarch64_reloc_type_class (const Elf_Internal_Rela * rela)
+{
+  switch ((int) ELF64_R_TYPE (rela->r_info))
+    {
+    case R_AARCH64_RELATIVE:
+      return reloc_class_relative;
+    case R_AARCH64_JUMP_SLOT:
+      return reloc_class_plt;
+    case R_AARCH64_COPY:
+      return reloc_class_copy;
+    default:
+      return reloc_class_normal;
+    }
+}
+
+/* Set the right machine number for an AArch64 ELF file.  */
+
+static bfd_boolean
+elf64_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.  */
+
+static bfd_boolean
+elf64_aarch64_section_from_shdr (bfd * abfd,
+				 Elf_Internal_Shdr * hdr,
+				 const char *name, int shindex)
+{
+  /* There ought to be a place to keep ELF backend specific flags, but
+     at the moment there isn't one.  We just keep track of the
+     sections by their name, instead.  Fortunately, the ABI gives
+     names for all the AArch64 specific sections, so we will probably get
+     away with this.  */
+  switch (hdr->sh_type)
+    {
+    case SHT_AARCH64_ATTRIBUTES:
+      break;
+
+    default:
+      return FALSE;
+    }
+
+  if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* A structure used to record a list of sections, independently
+   of the next and prev fields in the asection structure.  */
+typedef struct section_list
+{
+  asection *sec;
+  struct section_list *next;
+  struct section_list *prev;
+}
+section_list;
+
+/* Unfortunately we need to keep a list of sections for which
+   an _aarch64_elf_section_data structure has been allocated.  This
+   is because it is possible for functions like elf64_aarch64_write_section
+   to be called on a section which has had an elf_data_structure
+   allocated for it (and so the used_by_bfd field is valid) but
+   for which the AArch64 extended version of this structure - the
+   _aarch64_elf_section_data structure - has not been allocated.  */
+static section_list *sections_with_aarch64_elf_section_data = NULL;
+
+static void
+record_section_with_aarch64_elf_section_data (asection * sec)
+{
+  struct section_list *entry;
+
+  entry = bfd_malloc (sizeof (*entry));
+  if (entry == NULL)
+    return;
+  entry->sec = sec;
+  entry->next = sections_with_aarch64_elf_section_data;
+  entry->prev = NULL;
+  if (entry->next != NULL)
+    entry->next->prev = entry;
+  sections_with_aarch64_elf_section_data = entry;
+}
+
+static struct section_list *
+find_aarch64_elf_section_entry (asection * sec)
+{
+  struct section_list *entry;
+  static struct section_list *last_entry = NULL;
+
+  /* This is a short cut for the typical case where the sections are added
+     to the sections_with_aarch64_elf_section_data list in forward order and
+     then looked up here in backwards order.  This makes a real difference
+     to the ld-srec/sec64k.exp linker test.  */
+  entry = sections_with_aarch64_elf_section_data;
+  if (last_entry != NULL)
+    {
+      if (last_entry->sec == sec)
+	entry = last_entry;
+      else if (last_entry->next != NULL && last_entry->next->sec == sec)
+	entry = last_entry->next;
+    }
+
+  for (; entry; entry = entry->next)
+    if (entry->sec == sec)
+      break;
+
+  if (entry)
+    /* Record the entry prior to this one - it is the entry we are
+       most likely to want to locate next time.  Also this way if we
+       have been called from
+       unrecord_section_with_aarch64_elf_section_data () we will not
+       be caching a pointer that is about to be freed.  */
+    last_entry = entry->prev;
+
+  return entry;
+}
+
+static void
+unrecord_section_with_aarch64_elf_section_data (asection * sec)
+{
+  struct section_list *entry;
+
+  entry = find_aarch64_elf_section_entry (sec);
+
+  if (entry)
+    {
+      if (entry->prev != NULL)
+	entry->prev->next = entry->next;
+      if (entry->next != NULL)
+	entry->next->prev = entry->prev;
+      if (entry == sections_with_aarch64_elf_section_data)
+	sections_with_aarch64_elf_section_data = entry->next;
+      free (entry);
+    }
+}
+
+
+typedef struct
+{
+  void *finfo;
+  struct bfd_link_info *info;
+  asection *sec;
+  int sec_shndx;
+  int (*func) (void *, const char *, Elf_Internal_Sym *,
+	       asection *, struct elf_link_hash_entry *);
+} output_arch_syminfo;
+
+enum map_symbol_type
+{
+  AARCH64_MAP_INSN,
+  AARCH64_MAP_DATA
+};
+
+
+/* Output a single mapping symbol.  */
+
+static bfd_boolean
+elf64_aarch64_output_map_sym (output_arch_syminfo * osi,
+			      enum map_symbol_type type, bfd_vma offset)
+{
+  static const char *names[2] = { "$x", "$d" };
+  Elf_Internal_Sym sym;
+
+  sym.st_value = (osi->sec->output_section->vma
+		  + osi->sec->output_offset + offset);
+  sym.st_size = 0;
+  sym.st_other = 0;
+  sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
+  sym.st_shndx = osi->sec_shndx;
+  return osi->func (osi->finfo, names[type], &sym, osi->sec, NULL) == 1;
+}
+
+
+
+/* Output mapping symbols for PLT entries associated with H.  */
+
+static bfd_boolean
+elf64_aarch64_output_plt_map (struct elf_link_hash_entry *h, void *inf)
+{
+  output_arch_syminfo *osi = (output_arch_syminfo *) inf;
+  bfd_vma addr;
+
+  if (h->root.type == bfd_link_hash_indirect)
+    return TRUE;
+
+  if (h->root.type == bfd_link_hash_warning)
+    /* When warning symbols are created, they **replace** the "real"
+       entry in the hash table, thus we never get to see the real
+       symbol in a hash traversal.  So look at it now.  */
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if (h->plt.offset == (bfd_vma) - 1)
+    return TRUE;
+
+  addr = h->plt.offset;
+  if (addr == 32)
+    {
+      if (!elf64_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr))
+	return FALSE;
+    }
+  return TRUE;
+}
+
+
+/* Output a single local symbol for a generated stub.  */
+
+static bfd_boolean
+elf64_aarch64_output_stub_sym (output_arch_syminfo * osi, const char *name,
+			       bfd_vma offset, bfd_vma size)
+{
+  Elf_Internal_Sym sym;
+
+  sym.st_value = (osi->sec->output_section->vma
+		  + osi->sec->output_offset + offset);
+  sym.st_size = size;
+  sym.st_other = 0;
+  sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
+  sym.st_shndx = osi->sec_shndx;
+  return osi->func (osi->finfo, name, &sym, osi->sec, NULL) == 1;
+}
+
+static bfd_boolean
+aarch64_map_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
+{
+  struct elf64_aarch64_stub_hash_entry *stub_entry;
+  asection *stub_sec;
+  bfd_vma addr;
+  char *stub_name;
+  output_arch_syminfo *osi;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf64_aarch64_stub_hash_entry *) gen_entry;
+  osi = (output_arch_syminfo *) in_arg;
+
+  stub_sec = stub_entry->stub_sec;
+
+  /* Ensure this stub is attached to the current section being
+     processed.  */
+  if (stub_sec != osi->sec)
+    return TRUE;
+
+  addr = (bfd_vma) stub_entry->stub_offset;
+
+  stub_name = stub_entry->output_name;
+
+  switch (stub_entry->stub_type)
+    {
+    case aarch64_stub_adrp_branch:
+      if (!elf64_aarch64_output_stub_sym (osi, stub_name, addr,
+					  sizeof (aarch64_adrp_branch_stub)))
+	return FALSE;
+      if (!elf64_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr))
+	return FALSE;
+      break;
+    case aarch64_stub_long_branch:
+      if (!elf64_aarch64_output_stub_sym
+	  (osi, stub_name, addr, sizeof (aarch64_long_branch_stub)))
+	return FALSE;
+      if (!elf64_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr))
+	return FALSE;
+      if (!elf64_aarch64_output_map_sym (osi, AARCH64_MAP_DATA, addr + 16))
+	return FALSE;
+      break;
+    default:
+      BFD_FAIL ();
+    }
+
+  return TRUE;
+}
+
+/* Output mapping symbols for linker generated sections.  */
+
+static bfd_boolean
+elf64_aarch64_output_arch_local_syms (bfd * output_bfd,
+				      struct bfd_link_info *info,
+				      void *finfo,
+				      int (*func) (void *, const char *,
+						   Elf_Internal_Sym *,
+						   asection *,
+						   struct elf_link_hash_entry
+						   *))
+{
+  output_arch_syminfo osi;
+  struct elf64_aarch64_link_hash_table *htab;
+
+  htab = elf64_aarch64_hash_table (info);
+
+  osi.finfo = finfo;
+  osi.info = info;
+  osi.func = func;
+
+  /* Long calls stubs.  */
+  if (htab->stub_bfd && htab->stub_bfd->sections)
+    {
+      asection *stub_sec;
+
+      for (stub_sec = htab->stub_bfd->sections;
+	   stub_sec != NULL; stub_sec = stub_sec->next)
+	{
+	  /* Ignore non-stub sections.  */
+	  if (!strstr (stub_sec->name, STUB_SUFFIX))
+	    continue;
+
+	  osi.sec = stub_sec;
+
+	  osi.sec_shndx = _bfd_elf_section_from_bfd_section
+	    (output_bfd, osi.sec->output_section);
+
+	  bfd_hash_traverse (&htab->stub_hash_table, aarch64_map_one_stub,
+			     &osi);
+	}
+    }
+
+  /* Finally, output mapping symbols for the PLT.  */
+  if (!htab->root.splt || htab->root.splt->size == 0)
+    return TRUE;
+
+  /* For now live without mapping symbols for the plt.  */
+  osi.sec_shndx = _bfd_elf_section_from_bfd_section
+    (output_bfd, htab->root.splt->output_section);
+  osi.sec = htab->root.splt;
+
+  elf_link_hash_traverse (&htab->root, elf64_aarch64_output_plt_map,
+			  (void *) &osi);
+
+  return TRUE;
+
+}
+
+/* Allocate target specific section data.  */
+
+static bfd_boolean
+elf64_aarch64_new_section_hook (bfd * abfd, asection * sec)
+{
+  if (!sec->used_by_bfd)
+    {
+      _aarch64_elf_section_data *sdata;
+      bfd_size_type amt = sizeof (*sdata);
+
+      sdata = bfd_zalloc (abfd, amt);
+      if (sdata == NULL)
+	return FALSE;
+      sec->used_by_bfd = sdata;
+    }
+
+  record_section_with_aarch64_elf_section_data (sec);
+
+  return _bfd_elf_new_section_hook (abfd, sec);
+}
+
+
+static void
+unrecord_section_via_map_over_sections (bfd * abfd ATTRIBUTE_UNUSED,
+					asection * sec,
+					void *ignore ATTRIBUTE_UNUSED)
+{
+  unrecord_section_with_aarch64_elf_section_data (sec);
+}
+
+static bfd_boolean
+elf64_aarch64_close_and_cleanup (bfd * abfd)
+{
+  if (abfd->sections)
+    bfd_map_over_sections (abfd,
+			   unrecord_section_via_map_over_sections, NULL);
+
+  return _bfd_elf_close_and_cleanup (abfd);
+}
+
+static bfd_boolean
+elf64_aarch64_bfd_free_cached_info (bfd * abfd)
+{
+  if (abfd->sections)
+    bfd_map_over_sections (abfd,
+			   unrecord_section_via_map_over_sections, NULL);
+
+  return _bfd_free_cached_info (abfd);
+}
+
+static bfd_boolean
+elf64_aarch64_is_function_type (unsigned int type)
+{
+  return type == STT_FUNC;
+}
+
+/* Create dynamic sections. This is different from the ARM backend in that
+   the got, plt, gotplt and their relocation sections are all created in the
+   standard part of the bfd elf backend.  */
+
+static bfd_boolean
+elf64_aarch64_create_dynamic_sections (bfd * dynobj,
+				       struct bfd_link_info *info)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  struct elf_link_hash_entry *h;
+
+  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
+    return FALSE;
+
+  htab = elf64_aarch64_hash_table (info);
+  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
+  if (!info->shared)
+    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
+
+  if (!htab->sdynbss || (!info->shared && !htab->srelbss))
+    abort ();
+
+  /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
+     dynobj's .got section.  We don't do this in the linker script
+     because we don't want to define the symbol if we are not creating
+     a global offset table.  */
+  h = _bfd_elf_define_linkage_sym (dynobj, info,
+				   htab->root.sgot, "_GLOBAL_OFFSET_TABLE_");
+  elf_hash_table (info)->hgot = h;
+  if (h == NULL)
+    return FALSE;
+
+  return TRUE;
+}
+
+
+/* Allocate space in .plt, .got and associated reloc sections for
+   dynamic relocs.  */
+
+static bfd_boolean
+elf64_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
+{
+  struct bfd_link_info *info;
+  struct elf64_aarch64_link_hash_table *htab;
+  struct elf64_aarch64_link_hash_entry *eh;
+  struct elf_dyn_relocs *p;
+
+  /* An example of a bfd_link_hash_indirect symbol is versioned
+     symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
+     -> __gxx_personality_v0(bfd_link_hash_defined)
+
+     There is no need to process bfd_link_hash_indirect symbols here
+     because we will also be presented with the concrete instance of
+     the symbol and elf64_aarch64_copy_indirect_symbol () will have been
+     called to copy all relevant data from the generic to the concrete
+     symbol instance.
+   */
+  if (h->root.type == bfd_link_hash_indirect)
+    return TRUE;
+
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  info = (struct bfd_link_info *) inf;
+  htab = elf64_aarch64_hash_table (info);
+
+  if (htab->root.dynamic_sections_created && h->plt.refcount > 0)
+    {
+      /* Make sure this symbol is output as a dynamic symbol.
+         Undefined weak syms won't yet be marked as dynamic.  */
+      if (h->dynindx == -1 && !h->forced_local)
+	{
+	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
+	    return FALSE;
+	}
+
+      if (info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
+	{
+	  asection *s = htab->root.splt;
+
+	  /* If this is the first .plt entry, make room for the special
+	     first entry.  */
+	  if (s->size == 0)
+	    s->size += htab->plt_header_size;
+
+	  h->plt.offset = s->size;
+
+	  /* If this symbol is not defined in a regular file, and we are
+	     not generating a shared library, then set the symbol to this
+	     location in the .plt.  This is required to make function
+	     pointers compare as equal between the normal executable and
+	     the shared library.  */
+	  if (!info->shared && !h->def_regular)
+	    {
+	      h->root.u.def.section = s;
+	      h->root.u.def.value = h->plt.offset;
+	    }
+
+	  /* Make room for this entry. For now we only create the
+	     small model PLT entries. We later need to find a way
+	     of relaxing into these from the large model PLT entries.  */
+	  s->size += PLT_SMALL_ENTRY_SIZE;
+
+	  /* We also need to make an entry in the .got.plt section, which
+	     will be placed in the .got section by the linker script.  */
+	  htab->root.sgotplt->size += GOT_ENTRY_SIZE;
+
+	  /* We also need to make an entry in the .rela.plt section.  */
+	  htab->root.srelplt->size += RELOC_SIZE (htab);
+
+	  /* We need to ensure that all GOT entries that serve the PLT
+	     are consecutive with the special GOT slots [0] [1] and
+	     [2]. Any addtional relocations, such as
+	     R_AARCH64_TLSDESC, must be placed after the PLT related
+	     entries.  We abuse the reloc_count such that during
+	     sizing we adjust reloc_count to indicate the number of
+	     PLT related reserved entries.  In subsequent phases when
+	     filling in the contents of the reloc entries, PLT related
+	     entries are placed by computing their PLT index (0
+	     .. reloc_count). While other none PLT relocs are placed
+	     at the slot indicated by reloc_count and reloc_count is
+	     updated.  */
+
+	  htab->root.srelplt->reloc_count++;
+	}
+      else
+	{
+	  h->plt.offset = (bfd_vma) - 1;
+	  h->needs_plt = 0;
+	}
+    }
+  else
+    {
+      h->plt.offset = (bfd_vma) - 1;
+      h->needs_plt = 0;
+    }
+
+  eh = (struct elf64_aarch64_link_hash_entry *) h;
+  eh->tlsdesc_got_jump_table_offset = (bfd_vma) - 1;
+
+  if (h->got.refcount > 0)
+    {
+      bfd_boolean dyn;
+      unsigned got_type = elf64_aarch64_hash_entry (h)->got_type;
+
+      h->got.offset = (bfd_vma) - 1;
+
+      dyn = htab->root.dynamic_sections_created;
+
+      /* Make sure this symbol is output as a dynamic symbol.
+         Undefined weak syms won't yet be marked as dynamic.  */
+      if (dyn && h->dynindx == -1 && !h->forced_local)
+	{
+	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
+	    return FALSE;
+	}
+
+      if (got_type == GOT_UNKNOWN)
+	{
+	}
+      else if (got_type == GOT_NORMAL)
+	{
+	  h->got.offset = htab->root.sgot->size;
+	  htab->root.sgot->size += GOT_ENTRY_SIZE;
+	  if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+	       || h->root.type != bfd_link_hash_undefweak)
+	      && (info->shared
+		  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
+	    {
+	      htab->root.srelgot->size += RELOC_SIZE (htab);
+	    }
+	}
+      else
+	{
+	  int indx;
+	  if (got_type & GOT_TLSDESC_GD)
+	    {
+	      eh->tlsdesc_got_jump_table_offset =
+		(htab->root.sgotplt->size
+		 - aarch64_compute_jump_table_size (htab));
+	      htab->root.sgotplt->size += GOT_ENTRY_SIZE * 2;
+	      h->got.offset = (bfd_vma) - 2;
+	    }
+
+	  if (got_type & GOT_TLS_GD)
+	    {
+	      h->got.offset = htab->root.sgot->size;
+	      htab->root.sgot->size += GOT_ENTRY_SIZE * 2;
+	    }
+
+	  if (got_type & GOT_TLS_IE)
+	    {
+	      h->got.offset = htab->root.sgot->size;
+	      htab->root.sgot->size += GOT_ENTRY_SIZE;
+	    }
+
+	  indx = h && h->dynindx != -1 ? h->dynindx : 0;
+	  if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+	       || h->root.type != bfd_link_hash_undefweak)
+	      && (info->shared
+		  || indx != 0
+		  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
+	    {
+	      if (got_type & GOT_TLSDESC_GD)
+		{
+		  htab->root.srelplt->size += RELOC_SIZE (htab);
+		  /* Note reloc_count not incremented here!  We have
+		     already adjusted reloc_count for this relocation
+		     type.  */
+
+		  /* TLSDESC PLT is now needed, but not yet determined.  */
+		  htab->tlsdesc_plt = (bfd_vma) - 1;
+		}
+
+	      if (got_type & GOT_TLS_GD)
+		htab->root.srelgot->size += RELOC_SIZE (htab) * 2;
+
+	      if (got_type & GOT_TLS_IE)
+		htab->root.srelgot->size += RELOC_SIZE (htab);
+	    }
+	}
+    }
+  else
+    {
+      h->got.offset = (bfd_vma) - 1;
+    }
+
+  if (eh->dyn_relocs == NULL)
+    return TRUE;
+
+  /* In the shared -Bsymbolic case, discard space allocated for
+     dynamic pc-relative relocs against symbols which turn out to be
+     defined in regular objects.  For the normal shared case, discard
+     space for pc-relative relocs that have become local due to symbol
+     visibility changes.  */
+
+  if (info->shared)
+    {
+      /* Relocs that use pc_count are those that appear on a call
+         insn, or certain REL relocs that can generated via assembly.
+         We want calls to protected symbols to resolve directly to the
+         function rather than going via the plt.  If people want
+         function pointer comparisons to work as expected then they
+         should avoid writing weird assembly.  */
+      if (SYMBOL_CALLS_LOCAL (info, h))
+	{
+	  struct elf_dyn_relocs **pp;
+
+	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL;)
+	    {
+	      p->count -= p->pc_count;
+	      p->pc_count = 0;
+	      if (p->count == 0)
+		*pp = p->next;
+	      else
+		pp = &p->next;
+	    }
+	}
+
+      /* Also discard relocs on undefined weak syms with non-default
+         visibility.  */
+      if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak)
+	{
+	  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+	    eh->dyn_relocs = NULL;
+
+	  /* Make sure undefined weak symbols are output as a dynamic
+	     symbol in PIEs.  */
+	  else if (h->dynindx == -1
+		   && !h->forced_local
+		   && !bfd_elf_link_record_dynamic_symbol (info, h))
+	    return FALSE;
+	}
+
+    }
+  else if (ELIMINATE_COPY_RELOCS)
+    {
+      /* For the non-shared case, discard space for relocs against
+         symbols which turn out to need copy relocs or are not
+         dynamic.  */
+
+      if (!h->non_got_ref
+	  && ((h->def_dynamic
+	       && !h->def_regular)
+	      || (htab->root.dynamic_sections_created
+		  && (h->root.type == bfd_link_hash_undefweak
+		      || h->root.type == bfd_link_hash_undefined))))
+	{
+	  /* Make sure this symbol is output as a dynamic symbol.
+	     Undefined weak syms won't yet be marked as dynamic.  */
+	  if (h->dynindx == -1
+	      && !h->forced_local
+	      && !bfd_elf_link_record_dynamic_symbol (info, h))
+	    return FALSE;
+
+	  /* If that succeeded, we know we'll be keeping all the
+	     relocs.  */
+	  if (h->dynindx != -1)
+	    goto keep;
+	}
+
+      eh->dyn_relocs = NULL;
+
+    keep:;
+    }
+
+  /* Finally, allocate space.  */
+  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+    {
+      asection *sreloc;
+
+      sreloc = elf_section_data (p->sec)->sreloc;
+
+      BFD_ASSERT (sreloc != NULL);
+
+      sreloc->size += p->count * RELOC_SIZE (htab);
+    }
+
+  return TRUE;
+}
+
+
+
+
+/* This is the most important function of all . Innocuosly named
+   though !  */
+static bfd_boolean
+elf64_aarch64_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
+				     struct bfd_link_info *info)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  bfd *dynobj;
+  asection *s;
+  bfd_boolean relocs;
+  bfd *ibfd;
+
+  htab = elf64_aarch64_hash_table ((info));
+  dynobj = htab->root.dynobj;
+
+  BFD_ASSERT (dynobj != NULL);
+
+  if (htab->root.dynamic_sections_created)
+    {
+      if (info->executable)
+	{
+	  s = bfd_get_linker_section (dynobj, ".interp");
+	  if (s == NULL)
+	    abort ();
+	  s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+	}
+    }
+
+  /* Set up .got offsets for local syms, and space for local dynamic
+     relocs.  */
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+    {
+      struct elf_aarch64_local_symbol *locals = NULL;
+      Elf_Internal_Shdr *symtab_hdr;
+      asection *srel;
+      unsigned int i;
+
+      if (!is_aarch64_elf (ibfd))
+	continue;
+
+      for (s = ibfd->sections; s != NULL; s = s->next)
+	{
+	  struct elf_dyn_relocs *p;
+
+	  for (p = (struct elf_dyn_relocs *)
+	       (elf_section_data (s)->local_dynrel); p != NULL; p = p->next)
+	    {
+	      if (!bfd_is_abs_section (p->sec)
+		  && bfd_is_abs_section (p->sec->output_section))
+		{
+		  /* Input section has been discarded, either because
+		     it is a copy of a linkonce section or due to
+		     linker script /DISCARD/, so we'll be discarding
+		     the relocs too.  */
+		}
+	      else if (p->count != 0)
+		{
+		  srel = elf_section_data (p->sec)->sreloc;
+		  srel->size += p->count * RELOC_SIZE (htab);
+		  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
+		    info->flags |= DF_TEXTREL;
+		}
+	    }
+	}
+
+      locals = elf64_aarch64_locals (ibfd);
+      if (!locals)
+	continue;
+
+      symtab_hdr = &elf_symtab_hdr (ibfd);
+      srel = htab->root.srelgot;
+      for (i = 0; i < symtab_hdr->sh_info; i++)
+	{
+	  locals[i].got_offset = (bfd_vma) - 1;
+	  locals[i].tlsdesc_got_jump_table_offset = (bfd_vma) - 1;
+	  if (locals[i].got_refcount > 0)
+	    {
+	      unsigned got_type = locals[i].got_type;
+	      if (got_type & GOT_TLSDESC_GD)
+		{
+		  locals[i].tlsdesc_got_jump_table_offset =
+		    (htab->root.sgotplt->size
+		     - aarch64_compute_jump_table_size (htab));
+		  htab->root.sgotplt->size += GOT_ENTRY_SIZE * 2;
+		  locals[i].got_offset = (bfd_vma) - 2;
+		}
+
+	      if (got_type & GOT_TLS_GD)
+		{
+		  locals[i].got_offset = htab->root.sgot->size;
+		  htab->root.sgot->size += GOT_ENTRY_SIZE * 2;
+		}
+
+	      if (got_type & GOT_TLS_IE)
+		{
+		  locals[i].got_offset = htab->root.sgot->size;
+		  htab->root.sgot->size += GOT_ENTRY_SIZE;
+		}
+
+	      if (got_type == GOT_UNKNOWN)
+		{
+		}
+
+	      if (got_type == GOT_NORMAL)
+		{
+		}
+
+	      if (info->shared)
+		{
+		  if (got_type & GOT_TLSDESC_GD)
+		    {
+		      htab->root.srelplt->size += RELOC_SIZE (htab);
+		      /* Note RELOC_COUNT not incremented here! */
+		      htab->tlsdesc_plt = (bfd_vma) - 1;
+		    }
+
+		  if (got_type & GOT_TLS_GD)
+		    htab->root.srelgot->size += RELOC_SIZE (htab) * 2;
+
+		  if (got_type & GOT_TLS_IE)
+		    htab->root.srelgot->size += RELOC_SIZE (htab);
+		}
+	    }
+	  else
+	    {
+	      locals[i].got_refcount = (bfd_vma) - 1;
+	    }
+	}
+    }
+
+
+  /* Allocate global sym .plt and .got entries, and space for global
+     sym dynamic relocs.  */
+  elf_link_hash_traverse (&htab->root, elf64_aarch64_allocate_dynrelocs,
+			  info);
+
+
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     for them, it suffices to multiply the reloc count by the jump
+     slot size.  */
+
+  if (htab->root.srelplt)
+    htab->sgotplt_jump_table_size = aarch64_compute_jump_table_size (htab);
+
+  if (htab->tlsdesc_plt)
+    {
+      if (htab->root.splt->size == 0)
+	htab->root.splt->size += PLT_ENTRY_SIZE;
+
+      htab->tlsdesc_plt = htab->root.splt->size;
+      htab->root.splt->size += PLT_TLSDESC_ENTRY_SIZE;
+
+      /* If we're not using lazy TLS relocations, don't generate the
+         GOT entry required.  */
+      if (!(info->flags & DF_BIND_NOW))
+	{
+	  htab->dt_tlsdesc_got = htab->root.sgot->size;
+	  htab->root.sgot->size += GOT_ENTRY_SIZE;
+	}
+    }
+
+  /* We now have determined the sizes of the various dynamic sections.
+     Allocate memory for them.  */
+  relocs = FALSE;
+  for (s = dynobj->sections; s != NULL; s = s->next)
+    {
+      if ((s->flags & SEC_LINKER_CREATED) == 0)
+	continue;
+
+      if (s == htab->root.splt
+	  || s == htab->root.sgot
+	  || s == htab->root.sgotplt
+	  || s == htab->root.iplt
+	  || s == htab->root.igotplt || s == htab->sdynbss)
+	{
+	  /* Strip this section if we don't need it; see the
+	     comment below.  */
+	}
+      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
+	{
+	  if (s->size != 0 && s != htab->root.srelplt)
+	    relocs = TRUE;
+
+	  /* We use the reloc_count field as a counter if we need
+	     to copy relocs into the output file.  */
+	  if (s != htab->root.srelplt)
+	    s->reloc_count = 0;
+	}
+      else
+	{
+	  /* It's not one of our sections, so don't allocate space.  */
+	  continue;
+	}
+
+      if (s->size == 0)
+	{
+	  /* If we don't need this section, strip it from the
+	     output file.  This is mostly to handle .rela.bss and
+	     .rela.plt.  We must create both sections in
+	     create_dynamic_sections, because they must be created
+	     before the linker maps input sections to output
+	     sections.  The linker does that before
+	     adjust_dynamic_symbol is called, and it is that
+	     function which decides whether anything needs to go
+	     into these sections.  */
+
+	  s->flags |= SEC_EXCLUDE;
+	  continue;
+	}
+
+      if ((s->flags & SEC_HAS_CONTENTS) == 0)
+	continue;
+
+      /* Allocate memory for the section contents.  We use bfd_zalloc
+         here in case unused entries are not reclaimed before the
+         section's contents are written out.  This should not happen,
+         but this way if it does, we get a R_AARCH64_NONE reloc instead
+         of garbage.  */
+      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
+      if (s->contents == NULL)
+	return FALSE;
+    }
+
+  if (htab->root.dynamic_sections_created)
+    {
+      /* Add some entries to the .dynamic section.  We fill in the
+         values later, in elf64_aarch64_finish_dynamic_sections, but we
+         must add the entries now so that we get the correct size for
+         the .dynamic section.  The DT_DEBUG entry is filled in by the
+         dynamic linker and used by the debugger.  */
+#define add_dynamic_entry(TAG, VAL)			\
+      _bfd_elf_add_dynamic_entry (info, TAG, VAL)
+
+      if (info->executable)
+	{
+	  if (!add_dynamic_entry (DT_DEBUG, 0))
+	    return FALSE;
+	}
+
+      if (htab->root.splt->size != 0)
+	{
+	  if (!add_dynamic_entry (DT_PLTGOT, 0)
+	      || !add_dynamic_entry (DT_PLTRELSZ, 0)
+	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+	      || !add_dynamic_entry (DT_JMPREL, 0))
+	    return FALSE;
+
+	  if (htab->tlsdesc_plt
+	      && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
+		  || !add_dynamic_entry (DT_TLSDESC_GOT, 0)))
+	    return FALSE;
+	}
+
+      if (relocs)
+	{
+	  if (!add_dynamic_entry (DT_RELA, 0)
+	      || !add_dynamic_entry (DT_RELASZ, 0)
+	      || !add_dynamic_entry (DT_RELAENT, RELOC_SIZE (htab)))
+	    return FALSE;
+
+	  /* If any dynamic relocs apply to a read-only section,
+	     then we need a DT_TEXTREL entry.  */
+	  if ((info->flags & DF_TEXTREL) != 0)
+	    {
+	      if (!add_dynamic_entry (DT_TEXTREL, 0))
+		return FALSE;
+	    }
+	}
+    }
+#undef add_dynamic_entry
+
+  return TRUE;
+
+
+}
+
+static inline void
+elf64_aarch64_update_plt_entry (bfd * output_bfd,
+				unsigned int r_type,
+				bfd_byte * plt_entry, bfd_vma value)
+{
+  reloc_howto_type *howto;
+  howto = elf64_aarch64_howto_from_type (r_type);
+  bfd_elf_aarch64_put_addend (output_bfd, plt_entry, howto, value);
+}
+
+static void
+elf64_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
+				       struct elf64_aarch64_link_hash_table
+				       *htab, bfd * output_bfd)
+{
+  bfd_byte *plt_entry;
+  bfd_vma plt_index;
+  bfd_vma got_offset;
+  bfd_vma gotplt_entry_address;
+  bfd_vma plt_entry_address;
+  Elf_Internal_Rela rela;
+  bfd_byte *loc;
+
+  plt_index = (h->plt.offset - htab->plt_header_size) / htab->plt_entry_size;
+
+  /* Offset in the GOT is PLT index plus got GOT headers(3)
+     times 8.  */
+  got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
+  plt_entry = htab->root.splt->contents + h->plt.offset;
+  plt_entry_address = htab->root.splt->output_section->vma
+    + htab->root.splt->output_section->output_offset + h->plt.offset;
+  gotplt_entry_address = htab->root.sgotplt->output_section->vma +
+    htab->root.sgotplt->output_offset + got_offset;
+
+  /* Copy in the boiler-plate for the PLTn entry.  */
+  memcpy (plt_entry, elf64_aarch64_small_plt_entry, PLT_SMALL_ENTRY_SIZE);
+
+  /* Fill in the top 21 bits for this: ADRP x16, PLT_GOT + n * 8.
+     ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_ADR_PREL_PG_HI21,
+				  plt_entry,
+				  PG (gotplt_entry_address) -
+				  PG (plt_entry_address));
+
+  /* Fill in the lo12 bits for the load from the pltgot.  */
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_LDST64_ABS_LO12_NC,
+				  plt_entry + 4,
+				  PG_OFFSET (gotplt_entry_address));
+
+  /* Fill in the the lo12 bits for the add from the pltgot entry.  */
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_ADD_ABS_LO12_NC,
+				  plt_entry + 8,
+				  PG_OFFSET (gotplt_entry_address));
+
+  /* All the GOTPLT Entries are essentially initialized to PLT0.  */
+  bfd_put_64 (output_bfd,
+	      (htab->root.splt->output_section->vma
+	       + htab->root.splt->output_offset),
+	      htab->root.sgotplt->contents + got_offset);
+
+  /* Fill in the entry in the .rela.plt section.  */
+  rela.r_offset = gotplt_entry_address;
+  rela.r_info = ELF64_R_INFO (h->dynindx, R_AARCH64_JUMP_SLOT);
+  rela.r_addend = 0;
+
+  /* Compute the relocation entry to used based on PLT index and do
+     not adjust reloc_count. The reloc_count has already been adjusted
+     to account for this entry.  */
+  loc = htab->root.srelplt->contents + plt_index * RELOC_SIZE (htab);
+  bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+}
+
+/* Size sections even though they're not dynamic.  We use it to setup
+   _TLS_MODULE_BASE_, if needed.  */
+
+static bfd_boolean
+elf64_aarch64_always_size_sections (bfd * output_bfd,
+				    struct bfd_link_info *info)
+{
+  asection *tls_sec;
+
+  if (info->relocatable)
+    return TRUE;
+
+  tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_", TRUE, TRUE, FALSE);
+
+      if (tlsbase)
+	{
+	  struct bfd_link_hash_entry *h = NULL;
+	  const struct elf_backend_data *bed =
+	    get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE, bed->collect, &h)))
+	    return FALSE;
+
+	  tlsbase->type = STT_TLS;
+	  tlsbase = (struct elf_link_hash_entry *) h;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  return TRUE;
+}
+
+/* Finish up dynamic symbol handling.  We set the contents of various
+   dynamic sections here.  */
+static bfd_boolean
+elf64_aarch64_finish_dynamic_symbol (bfd * output_bfd,
+				     struct bfd_link_info *info,
+				     struct elf_link_hash_entry *h,
+				     Elf_Internal_Sym * sym)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  htab = elf64_aarch64_hash_table (info);
+
+  if (h->plt.offset != (bfd_vma) - 1)
+    {
+      /* This symbol has an entry in the procedure linkage table.  Set
+         it up.  */
+
+      if (h->dynindx == -1
+	  || htab->root.splt == NULL
+	  || htab->root.sgotplt == NULL || htab->root.srelplt == NULL)
+	abort ();
+
+      elf64_aarch64_create_small_pltn_entry (h, htab, 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.  */
+	  sym->st_shndx = SHN_UNDEF;
+	}
+    }
+
+  if (h->got.offset != (bfd_vma) - 1
+      && elf64_aarch64_hash_entry (h)->got_type == GOT_NORMAL)
+    {
+      Elf_Internal_Rela rela;
+      bfd_byte *loc;
+
+      /* This symbol has an entry in the global offset table.  Set it
+         up.  */
+      if (htab->root.sgot == NULL || htab->root.srelgot == NULL)
+	abort ();
+
+      rela.r_offset = (htab->root.sgot->output_section->vma
+		       + htab->root.sgot->output_offset
+		       + (h->got.offset & ~(bfd_vma) 1));
+
+      if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
+	{
+	  if (!h->def_regular)
+	    return FALSE;
+
+	  BFD_ASSERT ((h->got.offset & 1) != 0);
+	  rela.r_info = ELF64_R_INFO (0, R_AARCH64_RELATIVE);
+	  rela.r_addend = (h->root.u.def.value
+			   + h->root.u.def.section->output_section->vma
+			   + h->root.u.def.section->output_offset);
+	}
+      else
+	{
+	  BFD_ASSERT ((h->got.offset & 1) == 0);
+	  bfd_put_64 (output_bfd, (bfd_vma) 0,
+		      htab->root.sgot->contents + h->got.offset);
+	  rela.r_info = ELF64_R_INFO (h->dynindx, R_AARCH64_GLOB_DAT);
+	  rela.r_addend = 0;
+	}
+
+      loc = htab->root.srelgot->contents;
+      loc += htab->root.srelgot->reloc_count++ * RELOC_SIZE (htab);
+      bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+    }
+
+  if (h->needs_copy)
+    {
+      Elf_Internal_Rela rela;
+      bfd_byte *loc;
+
+      /* This symbol needs a copy reloc.  Set it up.  */
+
+      if (h->dynindx == -1
+	  || (h->root.type != bfd_link_hash_defined
+	      && h->root.type != bfd_link_hash_defweak)
+	  || htab->srelbss == NULL)
+	abort ();
+
+      rela.r_offset = (h->root.u.def.value
+		       + h->root.u.def.section->output_section->vma
+		       + h->root.u.def.section->output_offset);
+      rela.r_info = ELF64_R_INFO (h->dynindx, R_AARCH64_COPY);
+      rela.r_addend = 0;
+      loc = htab->srelbss->contents;
+      loc += htab->srelbss->reloc_count++ * RELOC_SIZE (htab);
+      bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+    }
+
+  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  SYM may
+     be NULL for local symbols.  */
+  if (sym != NULL
+      && (strcmp (h->root.root.string, "_DYNAMIC") == 0
+	  || h == elf_hash_table (info)->hgot))
+    sym->st_shndx = SHN_ABS;
+
+  return TRUE;
+}
+
+static void
+elf64_aarch64_init_small_plt0_entry (bfd * output_bfd ATTRIBUTE_UNUSED,
+				     struct elf64_aarch64_link_hash_table
+				     *htab)
+{
+  /* Fill in PLT0. Fixme:RR Note this doesn't distinguish between
+     small and large plts and at the minute just generates
+     the small PLT.  */
+
+  /* PLT0 of the small PLT looks like this -
+     stp x16, x30, [sp, #-16]!		// Save the reloc and lr on stack.
+     adrp x16, PLT_GOT + 16		// Get the page base of the GOTPLT
+     ldr  x17, [x16, #:lo12:PLT_GOT+16] // Load the address of the
+					// symbol resolver
+     add  x16, x16, #:lo12:PLT_GOT+16   // Load the lo12 bits of the
+					// GOTPLT entry for this.
+     br   x17
+   */
+  bfd_vma plt_got_base;
+  bfd_vma plt_base;
+
+
+  memcpy (htab->root.splt->contents, elf64_aarch64_small_plt0_entry,
+	  PLT_ENTRY_SIZE);
+  elf_section_data (htab->root.splt->output_section)->this_hdr.sh_entsize =
+    PLT_ENTRY_SIZE;
+
+  plt_got_base = (htab->root.sgotplt->output_section->vma
+		  + htab->root.sgotplt->output_offset);
+
+  plt_base = htab->root.splt->output_section->vma +
+    htab->root.splt->output_section->output_offset;
+
+  /* Fill in the top 21 bits for this: ADRP x16, PLT_GOT + n * 8.
+     ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_ADR_PREL_PG_HI21,
+				  htab->root.splt->contents + 4,
+				  PG (plt_got_base + 16) - PG (plt_base + 4));
+
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_LDST64_ABS_LO12_NC,
+				  htab->root.splt->contents + 8,
+				  PG_OFFSET (plt_got_base + 16));
+
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_ADD_ABS_LO12_NC,
+				  htab->root.splt->contents + 12,
+				  PG_OFFSET (plt_got_base + 16));
+}
+
+static bfd_boolean
+elf64_aarch64_finish_dynamic_sections (bfd * output_bfd,
+				       struct bfd_link_info *info)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  bfd *dynobj;
+  asection *sdyn;
+
+  htab = elf64_aarch64_hash_table (info);
+  dynobj = htab->root.dynobj;
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
+
+  if (htab->root.dynamic_sections_created)
+    {
+      Elf64_External_Dyn *dyncon, *dynconend;
+
+      if (sdyn == NULL || htab->root.sgot == NULL)
+	abort ();
+
+      dyncon = (Elf64_External_Dyn *) sdyn->contents;
+      dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size);
+      for (; dyncon < dynconend; dyncon++)
+	{
+	  Elf_Internal_Dyn dyn;
+	  asection *s;
+
+	  bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
+
+	  switch (dyn.d_tag)
+	    {
+	    default:
+	      continue;
+
+	    case DT_PLTGOT:
+	      s = htab->root.sgotplt;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+	      break;
+
+	    case DT_JMPREL:
+	      dyn.d_un.d_ptr = htab->root.srelplt->output_section->vma;
+	      break;
+
+	    case DT_PLTRELSZ:
+	      s = htab->root.srelplt->output_section;
+	      dyn.d_un.d_val = s->size;
+	      break;
+
+	    case DT_RELASZ:
+	      /* The procedure linkage table relocs (DT_JMPREL) should
+		 not be included in the overall relocs (DT_RELA).
+		 Therefore, we override the DT_RELASZ entry here to
+		 make it not include the JMPREL relocs.  Since the
+		 linker script arranges for .rela.plt to follow all
+		 other relocation sections, we don't have to worry
+		 about changing the DT_RELA entry.  */
+	      if (htab->root.srelplt != NULL)
+		{
+		  s = htab->root.srelplt->output_section;
+		  dyn.d_un.d_val -= s->size;
+		}
+	      break;
+
+	    case DT_TLSDESC_PLT:
+	      s = htab->root.splt;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_plt;
+	      break;
+
+	    case DT_TLSDESC_GOT:
+	      s = htab->root.sgot;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->dt_tlsdesc_got;
+	      break;
+	    }
+
+	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
+	}
+
+    }
+
+  /* Fill in the special first entry in the procedure linkage table.  */
+  if (htab->root.splt && htab->root.splt->size > 0)
+    {
+      elf64_aarch64_init_small_plt0_entry (output_bfd, htab);
+
+      elf_section_data (htab->root.splt->output_section)->
+	this_hdr.sh_entsize = htab->plt_entry_size;
+
+
+      if (htab->tlsdesc_plt)
+	{
+	  bfd_put_64 (output_bfd, (bfd_vma) 0,
+		      htab->root.sgot->contents + htab->dt_tlsdesc_got);
+
+	  memcpy (htab->root.splt->contents + htab->tlsdesc_plt,
+		  elf64_aarch64_tlsdesc_small_plt_entry,
+		  sizeof (elf64_aarch64_tlsdesc_small_plt_entry));
+
+	  {
+	    bfd_vma adrp1_addr =
+	      htab->root.splt->output_section->vma
+	      + htab->root.splt->output_offset + htab->tlsdesc_plt + 4;
+
+	    bfd_vma adrp2_addr =
+	      htab->root.splt->output_section->vma
+	      + htab->root.splt->output_offset + htab->tlsdesc_plt + 8;
+
+	    bfd_vma got_addr =
+	      htab->root.sgot->output_section->vma
+	      + htab->root.sgot->output_offset;
+
+	    bfd_vma pltgot_addr =
+	      htab->root.sgotplt->output_section->vma
+	      + htab->root.sgotplt->output_offset;
+
+	    bfd_vma dt_tlsdesc_got = got_addr + htab->dt_tlsdesc_got;
+	    bfd_vma opcode;
+
+	    /* adrp x2, DT_TLSDESC_GOT */
+	    opcode = bfd_get_32 (output_bfd,
+				 htab->root.splt->contents
+				 + htab->tlsdesc_plt + 4);
+	    opcode = reencode_adr_imm
+	      (opcode, (PG (dt_tlsdesc_got) - PG (adrp1_addr)) >> 12);
+	    bfd_put_32 (output_bfd, opcode,
+			htab->root.splt->contents + htab->tlsdesc_plt + 4);
+
+	    /* adrp x3, 0 */
+	    opcode = bfd_get_32 (output_bfd,
+				 htab->root.splt->contents
+				 + htab->tlsdesc_plt + 8);
+	    opcode = reencode_adr_imm
+	      (opcode, (PG (pltgot_addr) - PG (adrp2_addr)) >> 12);
+	    bfd_put_32 (output_bfd, opcode,
+			htab->root.splt->contents + htab->tlsdesc_plt + 8);
+
+	    /* ldr x2, [x2, #0] */
+	    opcode = bfd_get_32 (output_bfd,
+				 htab->root.splt->contents
+				 + htab->tlsdesc_plt + 12);
+	    opcode = reencode_ldst_pos_imm (opcode,
+					    PG_OFFSET (dt_tlsdesc_got) >> 3);
+	    bfd_put_32 (output_bfd, opcode,
+			htab->root.splt->contents + htab->tlsdesc_plt + 12);
+
+	    /* add x3, x3, 0 */
+	    opcode = bfd_get_32 (output_bfd,
+				 htab->root.splt->contents
+				 + htab->tlsdesc_plt + 16);
+	    opcode = reencode_add_imm (opcode, PG_OFFSET (pltgot_addr));
+	    bfd_put_32 (output_bfd, opcode,
+			htab->root.splt->contents + htab->tlsdesc_plt + 16);
+	  }
+	}
+    }
+
+  if (htab->root.sgotplt)
+    {
+      if (bfd_is_abs_section (htab->root.sgotplt->output_section))
+	{
+	  (*_bfd_error_handler)
+	    (_("discarded output section: `%A'"), htab->root.sgotplt);
+	  return FALSE;
+	}
+
+      /* Fill in the first three entries in the global offset table.  */
+      if (htab->root.sgotplt->size > 0)
+	{
+	  /* Set the first entry in the global offset table to the address of
+	     the dynamic section.  */
+	  if (sdyn == NULL)
+	    bfd_put_64 (output_bfd, (bfd_vma) 0,
+			htab->root.sgotplt->contents);
+	  else
+	    bfd_put_64 (output_bfd,
+			sdyn->output_section->vma + sdyn->output_offset,
+			htab->root.sgotplt->contents);
+	  /* Write GOT[1] and GOT[2], needed for the dynamic linker.  */
+	  bfd_put_64 (output_bfd,
+		      (bfd_vma) 0,
+		      htab->root.sgotplt->contents + GOT_ENTRY_SIZE);
+	  bfd_put_64 (output_bfd,
+		      (bfd_vma) 0,
+		      htab->root.sgotplt->contents + GOT_ENTRY_SIZE * 2);
+	}
+
+      elf_section_data (htab->root.sgotplt->output_section)->
+	this_hdr.sh_entsize = GOT_ENTRY_SIZE;
+    }
+
+  if (htab->root.sgot && htab->root.sgot->size > 0)
+    elf_section_data (htab->root.sgot->output_section)->this_hdr.sh_entsize
+      = GOT_ENTRY_SIZE;
+
+  return TRUE;
+}
+
+/* Return address for Ith PLT stub in section PLT, for relocation REL
+   or (bfd_vma) -1 if it should not be included.  */
+
+static bfd_vma
+elf64_aarch64_plt_sym_val (bfd_vma i, const asection * plt,
+			   const arelent * rel ATTRIBUTE_UNUSED)
+{
+  return plt->vma + PLT_ENTRY_SIZE + i * PLT_SMALL_ENTRY_SIZE;
+}
+
+
+/* We use this so we can override certain functions
+   (though currently we don't).  */
+
+const struct elf_size_info elf64_aarch64_size_info = {
+  sizeof (Elf64_External_Ehdr),
+  sizeof (Elf64_External_Phdr),
+  sizeof (Elf64_External_Shdr),
+  sizeof (Elf64_External_Rel),
+  sizeof (Elf64_External_Rela),
+  sizeof (Elf64_External_Sym),
+  sizeof (Elf64_External_Dyn),
+  sizeof (Elf_External_Note),
+  4,				/* hash-table entry size.  */
+  1,				/* internal relocs per external relocs.  */
+  64,				/* arch_size.  */
+  3,				/* log_file_align.  */
+  ELFCLASS64, EV_CURRENT,
+  bfd_elf64_write_out_phdrs,
+  bfd_elf64_write_shdrs_and_ehdr,
+  bfd_elf64_checksum_contents,
+  bfd_elf64_write_relocs,
+  bfd_elf64_swap_symbol_in,
+  bfd_elf64_swap_symbol_out,
+  bfd_elf64_slurp_reloc_table,
+  bfd_elf64_slurp_symbol_table,
+  bfd_elf64_swap_dyn_in,
+  bfd_elf64_swap_dyn_out,
+  bfd_elf64_swap_reloc_in,
+  bfd_elf64_swap_reloc_out,
+  bfd_elf64_swap_reloca_in,
+  bfd_elf64_swap_reloca_out
+};
+
+#define ELF_ARCH			bfd_arch_aarch64
+#define ELF_MACHINE_CODE		EM_AARCH64
+#define ELF_MAXPAGESIZE			0x10000
+#define ELF_MINPAGESIZE			0x1000
+#define ELF_COMMONPAGESIZE		0x1000
+
+#define bfd_elf64_close_and_cleanup             \
+  elf64_aarch64_close_and_cleanup
+
+#define bfd_elf64_bfd_copy_private_bfd_data	\
+  elf64_aarch64_copy_private_bfd_data
+
+#define bfd_elf64_bfd_free_cached_info          \
+  elf64_aarch64_bfd_free_cached_info
+
+#define bfd_elf64_bfd_is_target_special_symbol	\
+  elf64_aarch64_is_target_special_symbol
+
+#define bfd_elf64_bfd_link_hash_table_create    \
+  elf64_aarch64_link_hash_table_create
+
+#define bfd_elf64_bfd_link_hash_table_free      \
+  elf64_aarch64_hash_table_free
+
+#define bfd_elf64_bfd_merge_private_bfd_data	\
+  elf64_aarch64_merge_private_bfd_data
+
+#define bfd_elf64_bfd_print_private_bfd_data	\
+  elf64_aarch64_print_private_bfd_data
+
+#define bfd_elf64_bfd_reloc_type_lookup		\
+  elf64_aarch64_reloc_type_lookup
+
+#define bfd_elf64_bfd_reloc_name_lookup		\
+  elf64_aarch64_reloc_name_lookup
+
+#define bfd_elf64_bfd_set_private_flags		\
+  elf64_aarch64_set_private_flags
+
+#define bfd_elf64_find_inliner_info		\
+  elf64_aarch64_find_inliner_info
+
+#define bfd_elf64_find_nearest_line		\
+  elf64_aarch64_find_nearest_line
+
+#define bfd_elf64_mkobject			\
+  elf64_aarch64_mkobject
+
+#define bfd_elf64_new_section_hook		\
+  elf64_aarch64_new_section_hook
+
+#define elf_backend_adjust_dynamic_symbol	\
+  elf64_aarch64_adjust_dynamic_symbol
+
+#define elf_backend_always_size_sections	\
+  elf64_aarch64_always_size_sections
+
+#define elf_backend_check_relocs		\
+  elf64_aarch64_check_relocs
+
+#define elf_backend_copy_indirect_symbol	\
+  elf64_aarch64_copy_indirect_symbol
+
+/* Create .dynbss, and .rela.bss sections in DYNOBJ, and set up shortcuts
+   to them in our hash.  */
+#define elf_backend_create_dynamic_sections	\
+  elf64_aarch64_create_dynamic_sections
+
+#define elf_backend_init_index_section		\
+  _bfd_elf_init_2_index_sections
+
+#define elf_backend_is_function_type		\
+  elf64_aarch64_is_function_type
+
+#define elf_backend_finish_dynamic_sections	\
+  elf64_aarch64_finish_dynamic_sections
+
+#define elf_backend_finish_dynamic_symbol	\
+  elf64_aarch64_finish_dynamic_symbol
+
+#define elf_backend_gc_sweep_hook		\
+  elf64_aarch64_gc_sweep_hook
+
+#define elf_backend_object_p			\
+  elf64_aarch64_object_p
+
+#define elf_backend_output_arch_local_syms      \
+  elf64_aarch64_output_arch_local_syms
+
+#define elf_backend_plt_sym_val			\
+  elf64_aarch64_plt_sym_val
+
+#define elf_backend_post_process_headers	\
+  elf64_aarch64_post_process_headers
+
+#define elf_backend_relocate_section		\
+  elf64_aarch64_relocate_section
+
+#define elf_backend_reloc_type_class		\
+  elf64_aarch64_reloc_type_class
+
+#define elf_backend_section_flags		\
+  elf64_aarch64_section_flags
+
+#define elf_backend_section_from_shdr		\
+  elf64_aarch64_section_from_shdr
+
+#define elf_backend_size_dynamic_sections	\
+  elf64_aarch64_size_dynamic_sections
+
+#define elf_backend_size_info			\
+  elf64_aarch64_size_info
+
+#define elf_backend_can_refcount       1
+#define elf_backend_can_gc_sections    0
+#define elf_backend_plt_readonly       1
+#define elf_backend_want_got_plt       1
+#define elf_backend_want_plt_sym       0
+#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_got_header_size (GOT_ENTRY_SIZE * 3)
+
+#undef  elf_backend_obj_attrs_section
+#define elf_backend_obj_attrs_section		".ARM.attributes"
+
+#include "elf64-target.h"
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 19c1f96..47d052d 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -5884,6 +5884,278 @@ ENUMDOC
   the dynamic object into the runtime process image.
 
 ENUM
+  BFD_RELOC_AARCH64_ADD_LO12
+ENUMDOC
+  AArch64 ADD immediate instruction, holding bits 0 to 11 of the address.
+  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_ADR_GOT_PAGE
+ENUMDOC
+  Get to the page base of the global offset table entry for a symbol as
+  part of an ADRP instruction using a 21 bit PC relative value.Used in
+  conjunction with BFD_RELOC_AARCH64_LD64_GOT_LO12_NC.
+ENUM
+  BFD_RELOC_AARCH64_ADR_HI21_PCREL
+ENUMDOC
+  AArch64 ADRP instruction, with bits 12 to 32 of a pc-relative page
+  offset, giving a 4KB aligned page base address.
+ENUM
+  BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL
+ENUMDOC
+  AArch64 ADRP instruction, with bits 12 to 32 of a pc-relative page
+  offset, giving a 4KB aligned page base address, but with no overflow
+  checking.
+ENUM
+  BFD_RELOC_AARCH64_ADR_LO21_PCREL
+ENUMDOC
+  AArch64 ADR instruction, holding a simple 21 bit pc-relative byte offset.
+ENUM
+  BFD_RELOC_AARCH64_BRANCH19
+ENUMDOC
+  AArch64 19 bit pc-relative conditional branch and compare & branch.
+  The lowest two bits must be zero and are not stored in the instruction,
+  giving a 21 bit signed byte offset.
+ENUM
+  BFD_RELOC_AARCH64_CALL26
+ENUMDOC
+  AArch64 26 bit pc-relative unconditional branch and link.
+  The lowest two bits must be zero and are not stored in the instruction,
+  giving a 28 bit signed byte offset.
+ENUM
+  BFD_RELOC_AARCH64_GAS_INTERNAL_FIXUP
+ENUMDOC
+  AArch64 pseudo relocation code to be used internally by the AArch64
+  assembler and not (currently) written to any object files.
+ENUM
+  BFD_RELOC_AARCH64_JUMP26
+ENUMDOC
+  AArch64 26 bit pc-relative unconditional branch.
+  The lowest two bits must be zero and are not stored in the instruction,
+  giving a 28 bit signed byte offset.
+ENUM
+  BFD_RELOC_AARCH64_LD_LO19_PCREL
+ENUMDOC
+  AArch64 Load Literal instruction, holding a 19 bit pc-relative word
+  offset.  The lowest two bits must be zero and are not stored in the
+  instruction, giving a 21 bit signed byte offset.
+ENUM
+  BFD_RELOC_AARCH64_LD64_GOT_LO12_NC
+ENUMDOC
+  Unsigned 12 bit byte offset for 64 bit load/store from the page of
+  the GOT entry for this symbol.  Used in conjunction with
+  BFD_RELOC_AARCH64_ADR_GOTPAGE.
+ENUM
+  BFD_RELOC_AARCH64_LDST_LO12
+ENUMDOC
+  AArch64 unspecified load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST8_LO12
+ENUMDOC
+  AArch64 8-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST16_LO12
+ENUMDOC
+  AArch64 16-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST32_LO12
+ENUMDOC
+  AArch64 32-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST64_LO12
+ENUMDOC
+  AArch64 64-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST128_LO12
+ENUMDOC
+  AArch64 128-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G0
+ENUMDOC
+  AArch64 MOV[NZK] instruction with most significant bits 0 to 15
+  of an unsigned address/value.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G0_S
+ENUMDOC
+  AArch64 MOV[NZ] instruction with most significant bits 0 to 15
+  of a signed value.  Changes instruction to MOVZ or MOVN depending on the
+  value's sign.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G0_NC
+ENUMDOC
+  AArch64 MOV[NZK] instruction with less significant bits 0 to 15 of
+  an address/value.  No overflow checking.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G1
+ENUMDOC
+  AArch64 MOV[NZK] instruction with most significant bits 16 to 31
+  of an unsigned address/value.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G1_NC
+ENUMDOC
+  AArch64 MOV[NZK] instruction with less significant bits 16 to 31
+  of an address/value.  No overflow checking.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G1_S
+ENUMDOC
+  AArch64 MOV[NZ] instruction with most significant bits 16 to 31
+  of a signed value.  Changes instruction to MOVZ or MOVN depending on the
+  value's sign.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G2
+ENUMDOC
+  AArch64 MOV[NZK] instruction with most significant bits 32 to 47
+  of an unsigned address/value.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G2_NC
+ENUMDOC
+  AArch64 MOV[NZK] instruction with less significant bits 32 to 47
+  of an address/value.  No overflow checking.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G2_S
+ENUMDOC
+  AArch64 MOV[NZ] instruction with most significant bits 32 to 47
+  of a signed value.  Changes instruction to MOVZ or MOVN depending on the
+  value's sign.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G3
+ENUMDOC
+  AArch64 MOV[NZK] instruction with most signficant bits 48 to 64
+  of a signed or unsigned address/value.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC
+ENUMDOC
+  AArch64 TLS relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_ADD
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_CALL
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_LD64_PREL19
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_LDR
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_OFF_G1
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC
+ENUMDOC
+  Unsigned 12 bit byte offset to global offset table entry for a symbols
+  tls_index structure.  Used in conjunction with
+  BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21.
+ENUM
+  BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21
+ENUMDOC
+  Get to the page base of the global offset table entry for a symbols
+  tls_index structure as part of an adrp instruction using a 21 bit PC
+  relative value.  Used in conjunction with
+  BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLS_DTPMOD64
+ENUMDOC
+  AArch64 TLS relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLS_DTPREL64
+ENUMDOC
+  AArch64 TLS relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLS_TPREL64
+ENUMDOC
+  AArch64 TLS relocation.
+ENUM
+  BFD_RELOC_AARCH64_TSTBR14
+ENUMDOC
+  AArch64 14 bit pc-relative test bit and branch.
+  The lowest two bits must be zero and are not stored in the instruction,
+  giving a 16 bit signed byte offset.
+
+ENUM
   BFD_RELOC_TILEPRO_COPY
 ENUMX
   BFD_RELOC_TILEPRO_GLOB_DAT
@@ -6043,7 +6315,6 @@ ENUMX
   BFD_RELOC_TILEPRO_IMM16_X1_TLS_LE_HA
 ENUMDOC
   Tilera TILEPro Relocations.
-
 ENUM
   BFD_RELOC_TILEGX_HW0
 ENUMX
@@ -6236,7 +6507,6 @@ ENUMX
   BFD_RELOC_TILEGX_IMM8_Y1_TLS_ADD
 ENUMDOC
   Tilera TILE-Gx Relocations.
-
 ENUM
   BFD_RELOC_EPIPHANY_SIMM8
 ENUMDOC
diff --git a/bfd/targets.c b/bfd/targets.c
index cfa91a8..0551b6f 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -726,6 +726,7 @@ extern const bfd_target bfd_elf64_alpha_freebsd_vec;
 extern const bfd_target bfd_elf64_alpha_vec;
 extern const bfd_target bfd_elf64_big_generic_vec;
 extern const bfd_target bfd_elf64_bigmips_vec;
+extern const bfd_target bfd_elf64_bigaarch64_vec;
 extern const bfd_target bfd_elf64_hppa_linux_vec;
 extern const bfd_target bfd_elf64_hppa_vec;
 extern const bfd_target bfd_elf64_ia64_big_vec;
@@ -734,6 +735,7 @@ extern const bfd_target bfd_elf64_ia64_little_vec;
 extern const bfd_target bfd_elf64_ia64_vms_vec;
 extern const bfd_target bfd_elf64_little_generic_vec;
 extern const bfd_target bfd_elf64_littlemips_vec;
+extern const bfd_target bfd_elf64_littleaarch64_vec;
 extern const bfd_target bfd_elf64_mmix_vec;
 extern const bfd_target bfd_elf64_powerpc_vec;
 extern const bfd_target bfd_elf64_powerpcle_vec;
@@ -1101,6 +1103,7 @@ static const bfd_target * const _bfd_target_vector[] =
 	&bfd_elf64_alpha_vec,
 	&bfd_elf64_big_generic_vec,
 	&bfd_elf64_bigmips_vec,
+	&bfd_elf64_bigaarch64_vec,
 	&bfd_elf64_hppa_linux_vec,
 	&bfd_elf64_hppa_vec,
 	&bfd_elf64_ia64_big_vec,
@@ -1109,6 +1112,7 @@ static const bfd_target * const _bfd_target_vector[] =
 	&bfd_elf64_ia64_vms_vec,
 	&bfd_elf64_little_generic_vec,
 	&bfd_elf64_littlemips_vec,
+	&bfd_elf64_littleaarch64_vec,
 	&bfd_elf64_mmix_vec,
 	&bfd_elf64_powerpc_vec,
 	&bfd_elf64_powerpcle_vec,

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6]
  2012-07-30 14:21 [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Richard Earnshaw
                   ` (4 preceding siblings ...)
  2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes Yufeng Zhang
@ 2012-07-30 14:54 ` Joseph S. Myers
  2012-07-31 16:37   ` Yufeng Zhang
  2012-07-30 15:00 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes Yufeng Zhang
  2012-07-30 15:02 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes Yufeng Zhang
  7 siblings, 1 reply; 41+ messages in thread
From: Joseph S. Myers @ 2012-07-30 14:54 UTC (permalink / raw)
  To: Richard Earnshaw; +Cc: binutils, Yufeng Zhang

On Mon, 30 Jul 2012, Richard Earnshaw wrote:

> ARM is pleased to announce a port of binutils, gas and ld to its
> AArch64 architecture.

Could you confirm the target triplets for which you have run the binutils, 
gas and ld testsuites for this port, and confirm that you have 100% clean 
test results for them (except for any failures you specifically identify 
in patch submissions), tested on both 32-bit and 64-bit hosts (since it's 
quite common for some assembler issues not to appear on both 32-bit and 
64-bit)?

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes
  2012-07-30 14:21 [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Richard Earnshaw
                   ` (3 preceding siblings ...)
  2012-07-30 14:51 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes Yufeng Zhang
@ 2012-07-30 14:54 ` Yufeng Zhang
  2012-07-30 15:02   ` Joseph S. Myers
                     ` (2 more replies)
  2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Joseph S. Myers
                   ` (2 subsequent siblings)
  7 siblings, 3 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-07-30 14:54 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 6910 bytes --]

This patch adds the AArch64 gas port.


gas/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * Makefile.am: Add AArch64.
         * Makefile.in: Regenerate.
         * config/tc-aarch64.c: New file.
         * config/tc-aarch64.h: New file.
         * configure.tgt: Add AArch64.
         * doc/Makefile.am: Add AArch64.
         * doc/Makefile.in: Regenerate.
         * doc/all.texi: Add AArch64.
         * doc/as.texinfo: Add AArch64.
         * doc/c-aarch64.texi: New file.
         * po/POTFILES.in: Regenerate.


gas/testsuite/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * gas/aarch64/aarch64.exp: New file.
         * gas/aarch64/addsub.d: New file.
         * gas/aarch64/addsub.s: New file.
         * gas/aarch64/advsimd-across.d: New file.
         * gas/aarch64/advsimd-across.s: New file.
         * gas/aarch64/advsimd-misc.d: New file.
         * gas/aarch64/advsimd-misc.s: New file.
         * gas/aarch64/advsisd-copy.d: New file.
         * gas/aarch64/advsisd-copy.s: New file.
         * gas/aarch64/advsisd-misc.d: New file.
         * gas/aarch64/advsisd-misc.s: New file.
         * gas/aarch64/alias.d: New file.
         * gas/aarch64/alias.s: New file.
         * gas/aarch64/bitfield-alias.d: New file.
         * gas/aarch64/bitfield-alias.s: New file.
         * gas/aarch64/bitfield-bfm.d: New file.
         * gas/aarch64/bitfield-bfm.s: New file.
         * gas/aarch64/bitfield-dump: New file.
         * gas/aarch64/bitfield-no-aliases.d: New file.
         * gas/aarch64/crypto.d: New file.
         * gas/aarch64/crypto.s: New file.
         * gas/aarch64/diagnostic.d: New file.
         * gas/aarch64/diagnostic.l: New file.
         * gas/aarch64/diagnostic.s: New file.
         * gas/aarch64/floatdp2.d: New file.
         * gas/aarch64/floatdp2.s: New file.
         * gas/aarch64/fp_cvt_int.d: New file.
         * gas/aarch64/fp_cvt_int.s: New file.
         * gas/aarch64/illegal-2.d: New file.
         * gas/aarch64/illegal-2.l: New file.
         * gas/aarch64/illegal-2.s: New file.
         * gas/aarch64/illegal.d: New file.
         * gas/aarch64/illegal.l: New file.
         * gas/aarch64/illegal.s: New file.
         * gas/aarch64/inst-directive.d: New file.
         * gas/aarch64/inst-directive.s: New file.
         * gas/aarch64/int-insns.d: New file.
         * gas/aarch64/int-insns.s: New file.
         * gas/aarch64/ldst-exclusive.d: New file.
         * gas/aarch64/ldst-exclusive.s: New file.
         * gas/aarch64/ldst-reg-imm-post-ind.d: New file.
         * gas/aarch64/ldst-reg-imm-post-ind.s: New file.
         * gas/aarch64/ldst-reg-imm-pre-ind.d: New file.
         * gas/aarch64/ldst-reg-imm-pre-ind.s: New file.
         * gas/aarch64/ldst-reg-pair.d: New file.
         * gas/aarch64/ldst-reg-pair.s: New file.
         * gas/aarch64/ldst-reg-reg-offset.d: New file.
         * gas/aarch64/ldst-reg-reg-offset.s: New file.
         * gas/aarch64/ldst-reg-uns-imm.d: New file.
         * gas/aarch64/ldst-reg-uns-imm.s: New file.
         * gas/aarch64/ldst-reg-unscaled-imm.d: New file.
         * gas/aarch64/ldst-reg-unscaled-imm.s: New file.
         * gas/aarch64/legacy_reg_names.d: New file.
         * gas/aarch64/legacy_reg_names.l: New file.
         * gas/aarch64/legacy_reg_names.s: New file.
         * gas/aarch64/mapmisc.d: New file.
         * gas/aarch64/mapmisc.dat: New file.
         * gas/aarch64/mapmisc.s: New file.
         * gas/aarch64/mapping.d: New file.
         * gas/aarch64/mapping.s: New file.
         * gas/aarch64/mapping2.d: New file.
         * gas/aarch64/mapping2.s: New file.
         * gas/aarch64/mapping3.d: New file.
         * gas/aarch64/mapping3.s: New file.
         * gas/aarch64/mapping4.d: New file.
         * gas/aarch64/mapping4.s: New file.
         * gas/aarch64/mov-no-aliases.d: New file.
         * gas/aarch64/mov.d: New file.
         * gas/aarch64/mov.s: New file.
         * gas/aarch64/movi.d: New file.
         * gas/aarch64/movi.s: New file.
         * gas/aarch64/msr.d: New file.
         * gas/aarch64/msr.s: New file.
         * gas/aarch64/neon-fp-cvt-int.d: New file.
         * gas/aarch64/neon-fp-cvt-int.s: New file.
         * gas/aarch64/neon-frint.d: New file.
         * gas/aarch64/neon-frint.s: New file.
         * gas/aarch64/neon-ins.d: New file.
         * gas/aarch64/neon-ins.s: New file.
         * gas/aarch64/neon-not.d: New file.
         * gas/aarch64/neon-not.s: New file.
         * gas/aarch64/neon-vfp-reglist-post.d: New file.
         * gas/aarch64/neon-vfp-reglist-post.s: New file.
         * gas/aarch64/neon-vfp-reglist.d: New file.
         * gas/aarch64/neon-vfp-reglist.s: New file.
         * gas/aarch64/no-aliases.d: New file.
         * gas/aarch64/optional.d: New file.
         * gas/aarch64/optional.s: New file.
         * gas/aarch64/programmer-friendly.d: New file.
         * gas/aarch64/programmer-friendly.s: New file.
         * gas/aarch64/reloc-data.d: New file.
         * gas/aarch64/reloc-data.s: New file.
         * gas/aarch64/reloc-insn.d: New file.
         * gas/aarch64/reloc-insn.s: New file.
         * gas/aarch64/shifted.d: New file.
         * gas/aarch64/shifted.s: New file.
         * gas/aarch64/symbol.d: New file.
         * gas/aarch64/symbol.s: New file.
         * gas/aarch64/sysreg-1.d: New file.
         * gas/aarch64/sysreg-1.s: New file.
         * gas/aarch64/sysreg.d: New file.
         * gas/aarch64/sysreg.s: New file.
         * gas/aarch64/system.d: New file.
         * gas/aarch64/system.s: New file.
         * gas/aarch64/tlbi_op.d: New file.
         * gas/aarch64/tlbi_op.s: New file.
         * gas/aarch64/tls.d: New file.
         * gas/aarch64/tls.s: New file.
         * gas/aarch64/verbose-error.d: New file.
         * gas/aarch64/verbose-error.l: New file.
         * gas/aarch64/verbose-error.s: New file.

[-- Attachment #2: aarch64-gas.patch.bz2 --]
[-- Type: application/x-bzip, Size: 207933 bytes --]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes
  2012-07-30 14:51 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes Yufeng Zhang
@ 2012-07-30 14:57   ` Joseph S. Myers
  2012-07-31 18:29   ` nick clifton
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 41+ messages in thread
From: Joseph S. Myers @ 2012-07-30 14:57 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

On Mon, 30 Jul 2012, Yufeng Zhang wrote:

> +static struct
> +{
> +  unsigned int mach;
> +  char *name;
> +}
> +processors[] =
> +{
> +};

Empty initializers such as this are not valid ISO C.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes
  2012-07-30 14:21 [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Richard Earnshaw
                   ` (5 preceding siblings ...)
  2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Joseph S. Myers
@ 2012-07-30 15:00 ` Yufeng Zhang
  2012-07-30 15:08   ` Joseph S. Myers
  2012-07-30 15:02 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes Yufeng Zhang
  7 siblings, 1 reply; 41+ messages in thread
From: Yufeng Zhang @ 2012-07-30 15:00 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 8112 bytes --]

This patch adds the ld changes of the AArch64 target support.


ld/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * Makefile.am: Add AArch64.
         * Makefile.in: Regenerate.
         * configure.tgt: Add AArch64.
         * emulparams/aarch64elf.sh: New file.
         * emulparams/aarch64elfb.sh: New file.
         * emulparams/aarch64linux.sh: New file.
         * emulparams/aarch64linuxb.sh: New file.
         * emultempl/aarch64elf.em: New file.


ld/testsuite/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * ld-aarch64/aarch64-elf.exp: New file.
         * ld-aarch64/aarch64.ld: New file.
         * ld-aarch64/eh-frame-bar.s: New file.
         * ld-aarch64/eh-frame-foo.s: New file.
         * ld-aarch64/eh-frame.d: New file.
         * ld-aarch64/emit-relocs-257-be.d: New file.
         * ld-aarch64/emit-relocs-257.d: New file.
         * ld-aarch64/emit-relocs-257.s: New file.
         * ld-aarch64/emit-relocs-260-be.d: New file.
         * ld-aarch64/emit-relocs-260.d: New file.
         * ld-aarch64/emit-relocs-260.s: New file.
         * ld-aarch64/emit-relocs-262.d: New file.
         * ld-aarch64/emit-relocs-262.s: New file.
         * ld-aarch64/emit-relocs-263.d: New file.
         * ld-aarch64/emit-relocs-263.s: New file.
         * ld-aarch64/emit-relocs-264.d: New file.
         * ld-aarch64/emit-relocs-264.s: New file.
         * ld-aarch64/emit-relocs-265.d: New file.
         * ld-aarch64/emit-relocs-266.d: New file.
         * ld-aarch64/emit-relocs-266.s: New file.
         * ld-aarch64/emit-relocs-267.d: New file.
         * ld-aarch64/emit-relocs-267.s: New file.
         * ld-aarch64/emit-relocs-268.d: New file.
         * ld-aarch64/emit-relocs-268.s: New file.
         * ld-aarch64/emit-relocs-269.d: New file.
         * ld-aarch64/emit-relocs-269.s: New file.
         * ld-aarch64/emit-relocs-270-bad.d: New file.
         * ld-aarch64/emit-relocs-270.d: New file.
         * ld-aarch64/emit-relocs-270.s: New file.
         * ld-aarch64/emit-relocs-271.d: New file.
         * ld-aarch64/emit-relocs-271.s: New file.
         * ld-aarch64/emit-relocs-272.d: New file.
         * ld-aarch64/emit-relocs-272.s: New file.
         * ld-aarch64/emit-relocs-273.d: New file.
         * ld-aarch64/emit-relocs-273.s: New file.
         * ld-aarch64/emit-relocs-274.d: New file.
         * ld-aarch64/emit-relocs-274.s: New file.
         * ld-aarch64/emit-relocs-275.d: New file.
         * ld-aarch64/emit-relocs-275.s: New file.
         * ld-aarch64/emit-relocs-276.d: New file.
         * ld-aarch64/emit-relocs-276.s: New file.
         * ld-aarch64/emit-relocs-277.d: New file.
         * ld-aarch64/emit-relocs-277.s: New file.
         * ld-aarch64/emit-relocs-278.d: New file.
         * ld-aarch64/emit-relocs-278.s: New file.
         * ld-aarch64/emit-relocs-279-bad.d: New file.
         * ld-aarch64/emit-relocs-279.d: New file.
         * ld-aarch64/emit-relocs-279.s: New file.
         * ld-aarch64/emit-relocs-280.d: New file.
         * ld-aarch64/emit-relocs-280.s: New file.
         * ld-aarch64/emit-relocs-282.d: New file.
         * ld-aarch64/emit-relocs-282.s: New file.
         * ld-aarch64/emit-relocs-283.d: New file.
         * ld-aarch64/emit-relocs-283.s: New file.
         * ld-aarch64/emit-relocs-284.d: New file.
         * ld-aarch64/emit-relocs-284.s: New file.
         * ld-aarch64/emit-relocs-285.d: New file.
         * ld-aarch64/emit-relocs-285.s: New file.
         * ld-aarch64/emit-relocs-286-bad.d: New file.
         * ld-aarch64/emit-relocs-286.d: New file.
         * ld-aarch64/emit-relocs-286.s: New file.
         * ld-aarch64/emit-relocs-287.d: New file.
         * ld-aarch64/emit-relocs-287.s: New file.
         * ld-aarch64/emit-relocs-299.d: New file.
         * ld-aarch64/emit-relocs-299.s: New file.
         * ld-aarch64/emit-relocs-311.d: New file.
         * ld-aarch64/emit-relocs-311.s: New file.
         * ld-aarch64/emit-relocs-312.d: New file.
         * ld-aarch64/emit-relocs-312.s: New file.
         * ld-aarch64/emit-relocs1.s: New file.
         * ld-aarch64/farcall-b-none-function.d: New file.
         * ld-aarch64/farcall-b-none-function.s: New file.
         * ld-aarch64/farcall-b.d: New file.
         * ld-aarch64/farcall-b.s: New file.
         * ld-aarch64/farcall-back.d: New file.
         * ld-aarch64/farcall-back.s: New file.
         * ld-aarch64/farcall-bl-none-function.d: New file.
         * ld-aarch64/farcall-bl-none-function.s: New file.
         * ld-aarch64/farcall-bl.d: New file.
         * ld-aarch64/farcall-bl.s: New file.
         * ld-aarch64/farcall-section.d: New file.
         * ld-aarch64/farcall-section.s: New file.
         * ld-aarch64/limit-b.d: New file.
         * ld-aarch64/limit-b.s: New file.
         * ld-aarch64/limit-bl.d: New file.
         * ld-aarch64/limit-bl.s: New file.
         * ld-aarch64/relocs.ld: New file.
         * ld-aarch64/tls-desc-ie.d: New file.
         * ld-aarch64/tls-desc-ie.s: New file.
         * ld-aarch64/tls-relax-all.d: New file.
         * ld-aarch64/tls-relax-all.s: New file.
         * ld-aarch64/tls-relax-gd-ie.d: New file.
         * ld-aarch64/tls-relax-gd-ie.s: New file.
         * ld-aarch64/tls-relax-gd-le.d: New file.
         * ld-aarch64/tls-relax-gd-le.s: New file.
         * ld-aarch64/tls-relax-gdesc-ie-2.d: New file.
         * ld-aarch64/tls-relax-gdesc-ie-2.s: New file.
         * ld-aarch64/tls-relax-gdesc-ie.d: New file.
         * ld-aarch64/tls-relax-gdesc-ie.s: New file.
         * ld-aarch64/tls-relax-gdesc-le-2.d: New file.
         * ld-aarch64/tls-relax-gdesc-le-2.s: New file.
         * ld-aarch64/tls-relax-gdesc-le.d: New file.
         * ld-aarch64/tls-relax-gdesc-le.s: New file.
         * ld-aarch64/tls-relax-ie-le-2.d: New file.
         * ld-aarch64/tls-relax-ie-le-2.s: New file.
         * ld-aarch64/tls-relax-ie-le-3.d: New file.
         * ld-aarch64/tls-relax-ie-le-3.s: New file.
         * ld-aarch64/tls-relax-ie-le.d: New file.
         * ld-aarch64/tls-relax-ie-le.s: New file.
         * ld-aarch64/weak-undefined.d: New file.
         * ld-aarch64/weak-undefined.s: New file.
         * ld-elf/binutils.exp (binutils_test): Add optional parameter
         'test_name'; change to construct 'test_name' from the 'prog_name'
         and 'ld_options' only when "$test_name" == "".
         * ld-elf/exclude.exp: Add AArch64.
         * ld-elf/frame.exp: Add AArch64.
         * ld-elf/group8a.d (#notarget): Add AArch64.
         * ld-elf/group8b.d (#notarget): Add AArch64.
         * ld-elf/group9a.d (#notarget): Add AArch64.
         * ld-elf/group9b.d (#notarget): Add AArch64.
         * ld-elf/pr12851.d (#notarget): Add AArch64.
         * ld-elf/pr12975.d (#notarget): Add AArch64.
         * ld-elf/pr13177.d (#notarget): Add AArch64.
         * ld-elf/pr13195.d (#notarget): Add AArch64.
         * ld-elfvers/vers.exp: Add AArch64.
         * ld-shared/shared.exp: Add AArch64.
         * ld-srec/srec.exp: Add AArch64.
         * lib/ld-lib.exp: Add AArch64.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: aarch64-ld.patch --]
[-- Type: text/x-patch; name=aarch64-ld.patch, Size: 103838 bytes --]

diff --git a/ld/Makefile.am b/ld/Makefile.am
index f35ba4b..8ee8655 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -127,6 +127,10 @@ BFDLIB = ../bfd/libbfd.la
 LIBIBERTY = ../libiberty/libiberty.a
 
 ALL_EMULATION_SOURCES = \
+	eaarch64elf.c \
+	eaarch64elfb.c \
+	eaarch64linux.c \
+	eaarch64linuxb.c \
 	eaix5ppc.c \
 	eaix5rs6.c \
 	eaixppc.c \
@@ -1719,6 +1723,22 @@ ens32knbsd.c:	$(srcdir)/emulparams/ns32knbsd.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/netbsd.em \
   $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} ns32knbsd "$(tdir_ns32knbsd)"
+eaarch64elf.c: $(srcdir)/emulparams/aarch64elf.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64elf "$(tdir_aarch64elf)"
+eaarch64elfb.c: $(srcdir)/emulparams/aarch64elfb.sh $(srcdir)/emulparams/aarch64elf.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64elfb "$(tdir_aarch64elfb)"
+eaarch64linux.c: $(srcdir)/emulparams/aarch64linux.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64linux "$(tdir_aarch64linux)"
+eaarch64linuxb.c: $(srcdir)/emulparams/aarch64linuxb.sh $(srcdir)/emulparams/aarch64linux.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64linuxb "$(tdir_aarch64linuxb)"
 eor32.c: $(srcdir)/emulparams/or32.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/or32.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} or32 "$(tdir_or32)"
diff --git a/ld/configure.tgt b/ld/configure.tgt
index e58f4b8..507f1e7 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -27,6 +27,14 @@ targ64_extra_libpath=
 # architecture variants should be kept together even if their names
 # break the alpha sorting.
 case "${targ}" in
+aarch64_be-*-elf)	targ_emul=aarch64elfb
+			targ_extra_emuls="aarch64elf armelfb armelf" ;;
+aarch64-*-elf)		targ_emul=aarch64elf
+			targ_extra_emuls="aarch64elfb armelf armelfb" ;;
+aarch64_be-*-linux*)	targ_emul=aarch64linuxb
+			targ_extra_emuls="aarch64linux aarch64elfb aarch64elf armelfb_linux_eabi armelf_linux_eabi armelfb armelf" ;;
+aarch64-*-linux*)       targ_emul=aarch64linux
+			targ_extra_emuls="aarch64linuxb aarch64elf aarch64elfb armelf_linux_eabi armelfb_linux_eabi armelf armelfb" ;;
 alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
 		        targ_emul=elf64alpha_fbsd
 			targ_extra_emuls="elf64alpha alpha"
@@ -726,6 +734,7 @@ z8k-*-coff) 		targ_emul=z8002; targ_extra_emuls=z8001
 esac
 
 NATIVE_LIB_DIRS='/usr/local/lib /lib /usr/lib'
+
 case "${target}" in
 
 *-*-dragonfly*)
@@ -736,6 +745,11 @@ case "${target}" in
   NATIVE_LIB_DIRS='/lib /usr/lib /usr/local/lib'
   ;;
 
+aarch64*-*-linux*)
+  MULTIARCHTUPLE=aarch64-linux-gnu
+  NATIVE_LIB_DIRS="/usr/local/lib/$MULTIARCHTUPLE /lib/$MULTIARCHTUPLE /usr/lib/$MULTIARCHTUPLE"
+  ;;
+
 hppa*64*-*-hpux11*)
   NATIVE_LIB_DIRS=/usr/lib/pa20_64
   ;;
diff --git a/ld/emulparams/aarch64elf.sh b/ld/emulparams/aarch64elf.sh
new file mode 100644
index 0000000..d72e5f7
--- /dev/null
+++ b/ld/emulparams/aarch64elf.sh
@@ -0,0 +1,35 @@
+ARCH=aarch64
+MACHINE=
+NOP=0
+
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf64-littleaarch64"
+BIG_OUTPUT_FORMAT="elf64-bigaarch64"
+LITTLE_OUTPUT_FORMAT="elf64-littleaarch64"
+NO_REL_RELOCS=yes
+
+TEMPLATE_NAME=elf32
+EXTRA_EM_FILE=aarch64elf
+
+GENERATE_SHLIB_SCRIPT=yes
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+
+ENTRY=_start
+EMBEDDED=yes
+SEPARATE_GOTPLT=24
+TEXT_START_ADDR=0x00400000
+
+DATA_START_SYMBOLS='__data_start = . ;';
+
+# AArch64 does not support .s* sections.
+NO_SMALL_DATA=yes
+
+OTHER_BSS_SYMBOLS='__bss_start__ = .;'
+OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
+OTHER_END_SYMBOLS='__end__ = . ;'
+
+OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
+ATTRS_SECTIONS='.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }'
+
+# This sets the stack to the top of the simulator memory (2^19 bytes).
+STACK_ADDR=0x80000
diff --git a/ld/emulparams/aarch64elfb.sh b/ld/emulparams/aarch64elfb.sh
new file mode 100644
index 0000000..7a3ff97
--- /dev/null
+++ b/ld/emulparams/aarch64elfb.sh
@@ -0,0 +1,2 @@
+. ${srcdir}/emulparams/aarch64elf.sh
+OUTPUT_FORMAT="elf64-bigaarch64"
diff --git a/ld/emulparams/aarch64linux.sh b/ld/emulparams/aarch64linux.sh
new file mode 100644
index 0000000..a5a2500
--- /dev/null
+++ b/ld/emulparams/aarch64linux.sh
@@ -0,0 +1,36 @@
+ARCH=aarch64
+MACHINE=
+NOP=0
+
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf64-littleaarch64"
+BIG_OUTPUT_FORMAT="elf64-bigaarch64"
+LITTLE_OUTPUT_FORMAT="elf64-littleaarch64"
+NO_REL_RELOCS=yes
+
+TEMPLATE_NAME=elf32
+EXTRA_EM_FILE=aarch64elf
+
+GENERATE_SHLIB_SCRIPT=yes
+GENERATE_PIE_SCRIPT=yes
+
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
+SEPARATE_GOTPLT=24
+IREL_IN_PLT=
+
+TEXT_START_ADDR=0x400000
+
+DATA_START_SYMBOLS='PROVIDE (__data_start = .);';
+
+# AArch64 does not support .s* sections.
+NO_SMALL_DATA=yes
+
+OTHER_BSS_SYMBOLS='__bss_start__ = .;'
+OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
+OTHER_END_SYMBOLS='__end__ = . ;'
+
+OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
+ATTRS_SECTIONS='.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }'
+# Ensure each PLT entry is aligned to a cache line.
+PLT=".plt          ${RELOCATING-0} : ALIGN(16) { *(.plt)${IREL_IN_PLT+ *(.iplt)} }"
diff --git a/ld/emulparams/aarch64linuxb.sh b/ld/emulparams/aarch64linuxb.sh
new file mode 100644
index 0000000..2bdf602
--- /dev/null
+++ b/ld/emulparams/aarch64linuxb.sh
@@ -0,0 +1,2 @@
+. ${srcdir}/emulparams/aarch64linux.sh
+OUTPUT_FORMAT="elf64-bigaarch64"
diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em
new file mode 100644
index 0000000..4c03ffd
--- /dev/null
+++ b/ld/emultempl/aarch64elf.em
@@ -0,0 +1,415 @@
+# This shell script emits a C file. -*- C -*-
+#   Copyright 2009-2012  Free Software Foundation, Inc.
+#   Contributed by ARM Ltd.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not,
+# see <http://www.gnu.org/licenses/>.
+#
+
+# This file is sourced from elf32.em, and defines extra aarch64-elf
+# specific routines.
+#
+fragment <<EOF
+
+#include "ldctor.h"
+#include "elf/aarch64.h"
+
+static int no_enum_size_warning = 0;
+static int no_wchar_size_warning = 0;
+static int pic_veneer = 0;
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+#ifndef TARGET_			/* I.e., if not generic.  */
+  ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+  input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
+  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
+}
+
+static void
+aarch64_elf_before_allocation (void)
+{
+  /* We should be able to set the size of the interworking stub section.  We
+     can't do it until later if we have dynamic sections, though.  */
+  if (! elf_hash_table (&link_info)->dynamic_sections_created)
+    {
+      /* Here we rummage through the found bfds to collect information.  */
+      LANG_FOR_EACH_INPUT_STATEMENT (is)
+	{
+          /* Initialise mapping tables for code/data.  */
+          bfd_elf64_aarch64_init_maps (is->the_bfd);
+	}
+    }
+
+  /* Call the standard elf routine.  */
+  gld${EMULATION_NAME}_before_allocation ();
+}
+
+/* Fake input file for stubs.  */
+static lang_input_statement_type *stub_file;
+
+/* Whether we need to call gldarm_layout_sections_again.  */
+static int need_laying_out = 0;
+
+/* Maximum size of a group of input sections that can be handled by
+   one stub section.  A value of +/-1 indicates the bfd back-end
+   should use a suitable default size.  */
+static bfd_signed_vma group_size = 1;
+
+struct hook_stub_info
+{
+  lang_statement_list_type add;
+  asection *input_section;
+};
+
+/* Traverse the linker tree to find the spot where the stub goes.  */
+
+static bfd_boolean
+hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
+{
+  lang_statement_union_type *l;
+  bfd_boolean ret;
+
+  for (; (l = *lp) != NULL; lp = &l->header.next)
+    {
+      switch (l->header.type)
+	{
+	case lang_constructors_statement_enum:
+	  ret = hook_in_stub (info, &constructor_list.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_output_section_statement_enum:
+	  ret = hook_in_stub (info,
+			      &l->output_section_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_wild_statement_enum:
+	  ret = hook_in_stub (info, &l->wild_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_group_statement_enum:
+	  ret = hook_in_stub (info, &l->group_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_input_section_enum:
+	  if (l->input_section.section == info->input_section)
+	    {
+	      /* We've found our section.  Insert the stub immediately
+		 after its associated input section.  */
+	      *(info->add.tail) = l->header.next;
+	      l->header.next = info->add.head;
+	      return TRUE;
+	    }
+	  break;
+
+	case lang_data_statement_enum:
+	case lang_reloc_statement_enum:
+	case lang_object_symbols_statement_enum:
+	case lang_output_statement_enum:
+	case lang_target_statement_enum:
+	case lang_input_statement_enum:
+	case lang_assignment_statement_enum:
+	case lang_padding_statement_enum:
+	case lang_address_statement_enum:
+	case lang_fill_statement_enum:
+	  break;
+
+	default:
+	  FAIL ();
+	  break;
+	}
+    }
+  return FALSE;
+}
+
+
+/* Call-back for elf64_aarch64_size_stubs.  */
+
+/* Create a new stub section, and arrange for it to be linked
+   immediately after INPUT_SECTION.  */
+
+static asection *
+elf64_aarch64_add_stub_section (const char *stub_sec_name,
+				asection *input_section)
+{
+  asection *stub_sec;
+  flagword flags;
+  asection *output_section;
+  const char *secname;
+  lang_output_section_statement_type *os;
+  struct hook_stub_info info;
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+  stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
+						 stub_sec_name, flags);
+  if (stub_sec == NULL)
+    goto err_ret;
+
+  bfd_set_section_alignment (stub_file->the_bfd, stub_sec, 3);
+
+  output_section = input_section->output_section;
+  secname = bfd_get_section_name (output_section->owner, output_section);
+  os = lang_output_section_find (secname);
+
+  info.input_section = input_section;
+  lang_list_init (&info.add);
+  lang_add_section (&info.add, stub_sec, NULL, os);
+
+  if (info.add.head == NULL)
+    goto err_ret;
+
+  if (hook_in_stub (&info, &os->children.head))
+    return stub_sec;
+
+ err_ret:
+  einfo ("%X%P: can not make stub section: %E\n");
+  return NULL;
+}
+
+/* Another call-back for elf_arm_size_stubs.  */
+
+static void
+gldaarch64_layout_sections_again (void)
+{
+  /* If we have changed sizes of the stub sections, then we need
+     to recalculate all the section offsets.  This may mean we need to
+     add even more stubs.  */
+  gld${EMULATION_NAME}_map_segments (TRUE);
+  need_laying_out = -1;
+}
+
+static void
+build_section_lists (lang_statement_union_type *statement)
+{
+  if (statement->header.type == lang_input_section_enum)
+    {
+      asection *i = statement->input_section.section;
+
+      if (!((lang_input_statement_type *) i->owner->usrdata)->flags.just_syms
+	  && (i->flags & SEC_EXCLUDE) == 0
+	  && i->output_section != NULL
+	  && i->output_section->owner == link_info.output_bfd)
+	elf64_aarch64_next_input_section (& link_info, i);
+    }
+}
+
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+  /* bfd_elf32_discard_info just plays with debugging sections,
+     ie. doesn't affect any code, so we can delay resizing the
+     sections.  It's likely we'll resize everything in the process of
+     adding stubs.  */
+  if (bfd_elf_discard_info (link_info.output_bfd, & link_info))
+    need_laying_out = 1;
+
+  /* If generating a relocatable output file, then we don't
+     have to examine the relocs.  */
+  if (stub_file != NULL && !link_info.relocatable)
+    {
+      int ret = elf64_aarch64_setup_section_lists (link_info.output_bfd,
+						   & link_info);
+
+      if (ret != 0)
+	{
+	  if (ret < 0)
+	    {
+	      einfo ("%X%P: could not compute sections lists for stub generation: %E\n");
+	      return;
+	    }
+
+	  lang_for_each_statement (build_section_lists);
+
+	  /* Call into the BFD backend to do the real work.  */
+	  if (! elf64_aarch64_size_stubs (link_info.output_bfd,
+					  stub_file->the_bfd,
+					  & link_info,
+					  group_size,
+					  & elf64_aarch64_add_stub_section,
+					  & gldaarch64_layout_sections_again))
+	    {
+	      einfo ("%X%P: cannot size stub section: %E\n");
+	      return;
+	    }
+	}
+    }
+
+  if (need_laying_out != -1)
+    gld${EMULATION_NAME}_map_segments (need_laying_out);
+}
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+  if (! link_info.relocatable)
+    {
+      /* Now build the linker stubs.  */
+      if (stub_file->the_bfd->sections != NULL)
+	{
+	  if (! elf64_aarch64_build_stubs (& link_info))
+	    einfo ("%X%P: can not build stubs: %E\n");
+	}
+    }
+
+  finish_default ();
+}
+
+/* This is a convenient point to tell BFD about target specific flags.
+   After the output has been created, but before inputs are read.  */
+static void
+aarch64_elf_create_output_section_statements (void)
+{
+  if (strstr (bfd_get_target (link_info.output_bfd), "aarch64") == NULL)
+    {
+      /* The arm backend needs special fields in the output hash structure.
+	 These will only be created if the output format is an arm format,
+	 hence we do not support linking and changing output formats at the
+	 same time.  Use a link followed by objcopy to change output formats.  */
+      einfo ("%F%X%P: error: Cannot change output format whilst linking AArch64 binaries.\n");
+      return;
+    }
+
+  bfd_elf64_aarch64_set_options (link_info.output_bfd, &link_info,
+				 no_enum_size_warning,
+				 no_wchar_size_warning,
+				 pic_veneer);
+
+  stub_file = lang_add_input_file ("linker stubs",
+				   lang_input_file_is_fake_enum,
+				   NULL);
+  stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
+  if (stub_file->the_bfd == NULL
+      || ! bfd_set_arch_mach (stub_file->the_bfd,
+			      bfd_get_arch (link_info.output_bfd),
+			      bfd_get_mach (link_info.output_bfd)))
+    {
+      einfo ("%X%P: can not create BFD %E\n");
+      return;
+    }
+
+  stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
+  ldlang_add_file (stub_file);
+}
+
+/* Avoid processing the fake stub_file in vercheck, stat_needed and
+   check_needed routines.  */
+
+static void (*real_func) (lang_input_statement_type *);
+
+static void aarch64_for_each_input_file_wrapper (lang_input_statement_type *l)
+{
+  if (l != stub_file)
+    (*real_func) (l);
+}
+
+static void
+aarch64_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
+{
+  real_func = func;
+  lang_for_each_input_file (&aarch64_for_each_input_file_wrapper);
+}
+
+#define lang_for_each_input_file aarch64_lang_for_each_input_file
+
+EOF
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_NO_ENUM_SIZE_WARNING	309
+#define OPTION_PIC_VENEER		310
+#define OPTION_STUBGROUP_SIZE           311
+#define OPTION_NO_WCHAR_SIZE_WARNING	312
+'
+
+PARSE_AND_LIST_SHORTOPTS=p
+
+PARSE_AND_LIST_LONGOPTS='
+  { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
+  { "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING},
+  { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER},
+  { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
+  { "no-wchar-size-warning", no_argument, NULL, OPTION_NO_WCHAR_SIZE_WARNING},
+'
+
+PARSE_AND_LIST_OPTIONS='
+  fprintf (file, _("  --no-enum-size-warning      Don'\''t warn about objects with incompatible\n"
+		   "                                enum sizes\n"));
+  fprintf (file, _("  --no-wchar-size-warning     Don'\''t warn about objects with incompatible"
+		   "                                wchar_t sizes\n"));
+  fprintf (file, _("  --pic-veneer                Always generate PIC interworking veneers\n"));
+  fprintf (file, _("\
+   --stub-group-size=N   Maximum size of a group of input sections that can be\n\
+                           handled by one stub section.  A negative value\n\
+                           locates all stubs after their branches (with a\n\
+                           group size of -N), while a positive value allows\n\
+                           two groups of input sections, one before, and one\n\
+                           after each stub section.  Values of +/-1 indicate\n\
+                           the linker should choose suitable defaults.\n"
+		   ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+    case '\'p\'':
+      /* Only here for backwards compatibility.  */
+      break;
+
+    case OPTION_NO_ENUM_SIZE_WARNING:
+      no_enum_size_warning = 1;
+      break;
+
+    case OPTION_NO_WCHAR_SIZE_WARNING:
+      no_wchar_size_warning = 1;
+      break;
+
+    case OPTION_PIC_VENEER:
+      pic_veneer = 1;
+      break;
+
+    case OPTION_STUBGROUP_SIZE:
+      {
+	const char *end;
+
+        group_size = bfd_scan_vma (optarg, &end, 0);
+        if (*end)
+	  einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
+      }
+      break;
+'
+
+# We have our own before_allocation etc. functions, but they call
+# the standard routines, so give them a different name.
+LDEMUL_BEFORE_ALLOCATION=aarch64_elf_before_allocation
+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=aarch64_elf_create_output_section_statements
+
+# Replace the elf before_parse function with our own.
+LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+
+# Call the extra arm-elf function
+LDEMUL_FINISH=gld${EMULATION_NAME}_finish
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
new file mode 100644
index 0000000..eefe05a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -0,0 +1,105 @@
+# Expect script for various AARCH64 ELF tests.
+# Copyright 2009-2012 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# Exclude non-aarch64-ELF targets.
+if { ![is_elf_format] || ![istarget "aarch64*-*-*"] } {
+    return
+}
+
+# List contains test-items with 3 items followed by 2 lists:
+# 0:name 1:ld options 2:assembler options
+# 3:filenames of assembler files 4: action and options. 5: name of output file
+
+# Actions:
+# objdump: Apply objdump options on result.  Compare with regex (last arg).
+# nm: Apply nm options on result.  Compare with regex (last arg).
+# readelf: Apply readelf options on result.  Compare with regex (last arg).
+
+set aarch64elftests {
+    {"EH Frame merge" "-Ttext 0x8000" "" {eh-frame-bar.s eh-frame-foo.s}
+	{{objdump --dwarf=frames eh-frame.d}} "eh-frame"}
+}
+
+run_ld_link_tests $aarch64elftests
+
+# Relocation Tests
+run_dump_test "weak-undefined"
+run_dump_test "emit-relocs-257"
+run_dump_test "emit-relocs-257-be"
+# 258 is tested in 257
+# 259 is tested in 257
+run_dump_test "emit-relocs-260"
+run_dump_test "emit-relocs-260-be"
+# 261 is tested by 260
+run_dump_test "emit-relocs-262"
+run_dump_test "emit-relocs-263"
+run_dump_test "emit-relocs-264"
+run_dump_test "emit-relocs-265"
+run_dump_test "emit-relocs-266"
+run_dump_test "emit-relocs-267"
+run_dump_test "emit-relocs-268"
+run_dump_test "emit-relocs-269"
+run_dump_test "emit-relocs-270"
+run_dump_test "emit-relocs-270-bad"
+run_dump_test "emit-relocs-271"
+run_dump_test "emit-relocs-272"
+run_dump_test "emit-relocs-273"
+run_dump_test "emit-relocs-274"
+run_dump_test "emit-relocs-275"
+run_dump_test "emit-relocs-276"
+run_dump_test "emit-relocs-277"
+run_dump_test "emit-relocs-278"
+run_dump_test "emit-relocs-279"
+run_dump_test "emit-relocs-279-bad"
+run_dump_test "emit-relocs-280"
+# 281 is unused
+run_dump_test "emit-relocs-282"
+run_dump_test "emit-relocs-283"
+run_dump_test "emit-relocs-284"
+run_dump_test "emit-relocs-285"
+run_dump_test "emit-relocs-286"
+run_dump_test "emit-relocs-286-bad"
+# 287-298 are not done yet
+run_dump_test "emit-relocs-299"
+# 300-310 are not done yet
+run_dump_test "emit-relocs-311"
+run_dump_test "emit-relocs-312"
+
+
+run_dump_test "limit-b"
+run_dump_test "limit-bl"
+run_dump_test "farcall-section"
+run_dump_test "farcall-back"
+run_dump_test "farcall-bl"
+run_dump_test "farcall-b"
+run_dump_test "farcall-b-none-function"
+run_dump_test "farcall-bl-none-function"
+
+run_dump_test "tls-relax-all"
+run_dump_test "tls-relax-gd-le"
+run_dump_test "tls-relax-gdesc-le"
+run_dump_test "tls-relax-gd-ie"
+run_dump_test "tls-relax-gdesc-ie"
+run_dump_test "tls-relax-ie-le"
+run_dump_test "tls-desc-ie"
+run_dump_test "tls-relax-gdesc-ie-2"
+run_dump_test "tls-relax-gdesc-le-2"
+run_dump_test "tls-relax-ie-le-2"
+run_dump_test "tls-relax-ie-le-3"
diff --git a/ld/testsuite/ld-aarch64/aarch64.ld b/ld/testsuite/ld-aarch64/aarch64.ld
new file mode 100644
index 0000000..75ee3b5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/aarch64.ld
@@ -0,0 +1,19 @@
+/* Script for ld testsuite */
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x8000); . = 0x8000;
+  .text           :
+  {
+    *(.before)
+    *(.text)
+    *(.after)
+  } =0
+  . = 0x9000;
+  .got            : { *(.got) *(.got.plt)}
+  . = 0x12340000;
+  .far : { *(.far) }
+  .ARM.attributes 0 : { *(.ARM.atttributes) }
+}
diff --git a/ld/testsuite/ld-aarch64/eh-frame-bar.s b/ld/testsuite/ld-aarch64/eh-frame-bar.s
new file mode 100644
index 0000000..a67d8e4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/eh-frame-bar.s
@@ -0,0 +1,38 @@
+__longjmp:
+ .cfi_startproc
+ .cfi_def_cfa x0, 0
+ .cfi_offset x19, 16
+ .cfi_offset x20, 16
+ .cfi_offset x21, 16
+ .cfi_offset x22, 16
+ .cfi_offset x23, 24
+ .cfi_offset x24, 24
+ .cfi_offset x25, 24
+ .cfi_offset x26, 24
+ .cfi_offset x27, 24
+ .cfi_offset x28, 32
+ .cfi_offset x29, 32
+ .cfi_offset x30, 36
+ .cfi_offset d9, 8
+# This eh frame data differs from eh-frame-bar.s here, see the comment
+# in eh-frame-foo.s
+ .cfi_offset d11, 8
+
+ ldp x19, x20, [x0, #16]
+ ldp x21, x22, [x0, #16]
+ ldp x23, x24, [x0, #24]
+ ldp x25, x26, [x0, #24]
+ ldp x27, x28, [x0, #24]
+ ldp x29, x30, [x0, #32]
+
+ ldp d8, d9, [x0, #8]
+ ldp d10, d11, [x0, #8]
+ ldp d12, d13, [x0, #8]
+ ldp d14, d15, [x0, #8]
+ ldr x5, [x0, #48]
+ mov sp, x5
+ cmp x1, #0
+ mov x0, #1
+ csel x0, x1, x0, ne
+ br x30
+ .cfi_endproc
diff --git a/ld/testsuite/ld-aarch64/eh-frame-foo.s b/ld/testsuite/ld-aarch64/eh-frame-foo.s
new file mode 100644
index 0000000..c077ef2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/eh-frame-foo.s
@@ -0,0 +1,55 @@
+__longjmp:
+ .cfi_startproc
+ .cfi_def_cfa x0, 0
+ .cfi_offset x19, 16
+ .cfi_offset x20, 16
+ .cfi_offset x21, 16
+ .cfi_offset x22, 16
+ .cfi_offset x23, 24
+ .cfi_offset x24, 24
+ .cfi_offset x25, 24
+ .cfi_offset x26, 24
+ .cfi_offset x27, 24
+ .cfi_offset x28, 32
+ .cfi_offset x29, 32
+ .cfi_offset x30, 36
+ .cfi_offset d9, 8
+
+/* This eh frame data differs from eh-frame-bar.s here.  The eh
+   frame information is identical but changes at the end.  The
+   initial identical section is long enough to overflow the
+   initial instruction buffer used in eh frame merging.  This
+   checks that merging does something sane once the initial
+   instruction buffer overflows.  */
+
+.cfi_offset d10, 8
+
+
+
+
+
+
+
+ ldp x19, x20, [x0, #16]
+ ldp x21, x22, [x0, #16]
+ ldp x23, x24, [x0, #24]
+ ldp x25, x26, [x0, #24]
+ ldp x27, x28, [x0, #24]
+ ldp x29, x30, [x0, #32]
+
+ ldp d8, d9, [x0, #8]
+ ldp d10, d11, [x0, #8]
+ ldp d12, d13, [x0, #8]
+ ldp d14, d15, [x0, #8]
+ ldr x5, [x0, #48]
+ mov sp, x5
+ cmp x1, #0
+ mov x0, #1
+ csel x0, x1, x0, ne
+
+ br x30
+ .cfi_endproc
+
+ .global _start
+_start:
+
diff --git a/ld/testsuite/ld-aarch64/eh-frame.d b/ld/testsuite/ld-aarch64/eh-frame.d
new file mode 100644
index 0000000..533381f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/eh-frame.d
@@ -0,0 +1,86 @@
+.*:     file format elf64-(little|big)aarch64
+
+Contents of the .eh_frame section:
+
+00000000 00000044 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 2
+  Data alignment factor: -4
+  Return address column: 30
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r31 ofs 0
+  DW_CFA_def_cfa: r0 ofs 0
+  DW_CFA_offset_extended_sf: r19 at cfa\+16
+  DW_CFA_offset_extended_sf: r20 at cfa\+16
+  DW_CFA_offset_extended_sf: r21 at cfa\+16
+  DW_CFA_offset_extended_sf: r22 at cfa\+16
+  DW_CFA_offset_extended_sf: r23 at cfa\+24
+  DW_CFA_offset_extended_sf: r24 at cfa\+24
+  DW_CFA_offset_extended_sf: r25 at cfa\+24
+  DW_CFA_offset_extended_sf: r26 at cfa\+24
+  DW_CFA_offset_extended_sf: r27 at cfa\+24
+  DW_CFA_offset_extended_sf: r28 at cfa\+32
+  DW_CFA_offset_extended_sf: r29 at cfa\+32
+  DW_CFA_offset_extended_sf: r30 at cfa\+36
+  DW_CFA_offset_extended_sf: r9 at cfa\+8
+  DW_CFA_offset_extended_sf: r11 at cfa\+8
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000048 00000014 0000004c FDE cie=00000000 pc=ffffffffffffff80..ffffffffffffffc0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000060 00000044 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 2
+  Data alignment factor: -4
+  Return address column: 30
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r31 ofs 0
+  DW_CFA_def_cfa: r0 ofs 0
+  DW_CFA_offset_extended_sf: r19 at cfa\+16
+  DW_CFA_offset_extended_sf: r20 at cfa\+16
+  DW_CFA_offset_extended_sf: r21 at cfa\+16
+  DW_CFA_offset_extended_sf: r22 at cfa\+16
+  DW_CFA_offset_extended_sf: r23 at cfa\+24
+  DW_CFA_offset_extended_sf: r24 at cfa\+24
+  DW_CFA_offset_extended_sf: r25 at cfa\+24
+  DW_CFA_offset_extended_sf: r26 at cfa\+24
+  DW_CFA_offset_extended_sf: r27 at cfa\+24
+  DW_CFA_offset_extended_sf: r28 at cfa\+32
+  DW_CFA_offset_extended_sf: r29 at cfa\+32
+  DW_CFA_offset_extended_sf: r30 at cfa\+36
+  DW_CFA_offset_extended_sf: r9 at cfa\+8
+  DW_CFA_offset_extended_sf: r10 at cfa\+8
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000000a8 00000014 0000004c FDE cie=00000060 pc=ffffffffffffffc0..00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-257-be.d b/ld/testsuite/ld-aarch64/emit-relocs-257-be.d
new file mode 100644
index 0000000..3f6be24
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-257-be.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-257.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234  -e0 --emit-relocs
+#notarget: aarch64-*-*
+#objdump: -dr
+#...
+ +10000:	00011012 	\.word	0x00011012
+	+10000: R_AARCH64_ABS32	tempy
+ +10004:	00000000 	\.word	0x00000000
+	+10004: R_AARCH64_ABS64	tempy2
+ +10008:	00045034 	\.word	0x00045034
+ +1000c:	1234123c 	\.word	0x1234123c
+	+1000c: R_AARCH64_ABS16	tempy3
+	+1000e: R_AARCH64_ABS16	tempy3\+0x8
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-257.d b/ld/testsuite/ld-aarch64/emit-relocs-257.d
new file mode 100644
index 0000000..0a3a7ac
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-257.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-257.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234  -e0 --emit-relocs
+#notarget: aarch64_be-*-*
+#objdump: -dr
+#...
+ +10000:	00011012 	\.word	0x00011012
+	+10000: R_AARCH64_ABS32	tempy
+ +10004:	00045034 	\.word	0x00045034
+	+10004: R_AARCH64_ABS64	tempy2
+ +10008:	00000000 	\.word	0x00000000
+ +1000c:	123c1234 	\.word	0x123c1234
+	+1000c: R_AARCH64_ABS16	tempy3
+	+1000e: R_AARCH64_ABS16	tempy3\+0x8
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-257.s b/ld/testsuite/ld-aarch64/emit-relocs-257.s
new file mode 100644
index 0000000..609ebba
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-257.s
@@ -0,0 +1,12 @@
+.comm   gempy,4,4
+.text
+
+.word	tempy
+.xword  tempy2
+.hword	tempy3
+.hword	tempy3+8
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-260-be.d b/ld/testsuite/ld-aarch64/emit-relocs-260-be.d
new file mode 100644
index 0000000..7cea3c6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-260-be.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-260.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234 --defsym _GOT_=0x10000 -e0 --emit-relocs
+#notarget: aarch64-*-*
+#objdump: -dr
+#...
+	+10000: R_AARCH64_PREL32	_GOT_
+	+10004: R_AARCH64_PREL64	_GOT_\+0x12
+ +10008:	0000000e 	\.word	0x0000000e
+ +1000c:	fff404f2 	\.word	0xfff404f2
+	+1000c: R_AARCH64_PREL16	_GOT_
+	+1000e: R_AARCH64_PREL16	_GOT_\+0x500
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-260.d b/ld/testsuite/ld-aarch64/emit-relocs-260.d
new file mode 100644
index 0000000..91c1d8a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-260.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-260.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234 --defsym _GOT_=0x10000 -e0 --emit-relocs
+#notarget: aarch64_be-*-*
+#objdump: -dr
+#...
+ +10000:	00000000 	\.word	0x00000000
+	+10000: R_AARCH64_PREL32	_GOT_
+ +10004:	0000000e 	\.word	0x0000000e
+	+10004: R_AARCH64_PREL64	_GOT_\+0x12
+ +10008:	00000000 	\.word	0x00000000
+ +1000c:	04f2fff4 	\.word	0x04f2fff4
+	+1000c: R_AARCH64_PREL16	_GOT_
+	+1000e: R_AARCH64_PREL16	_GOT_\+0x500
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-260.s b/ld/testsuite/ld-aarch64/emit-relocs-260.s
new file mode 100644
index 0000000..87aa342
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-260.s
@@ -0,0 +1,13 @@
+.comm   gempy,4,4
+.text
+
+.word	_GOT_ - .
+.xword  _GOT_ - . + 0x12
+.hword	_GOT_ - . 
+.hword	_GOT_ - . + 0x500 
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-262.d b/ld/testsuite/ld-aarch64/emit-relocs-262.d
new file mode 100644
index 0000000..c42ecb6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-262.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-262.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234 --defsym _GOT_=0x20000 -e0 --emit-relocs
+#error: .*truncated.*
+#objdump: -dr
+#...
+ +10000:	00011012 	\.word	0x00011012
+	+10000: R_AARCH64_PREL32	tempy
+ +10004:	00045034 	\.word	0x00045034
+	+10004: R_AARCH64_PREL64	tempy2
+ +10008:	00000000 	\.word	0x00000000
+ +1000c:	123c1234 	\.word	0x123c1234
+	+1000c: R_AARCH64_PREL16	tempy3
+	+1000e: R_AARCH64_PREL16	tempy3\+0x8
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-262.s b/ld/testsuite/ld-aarch64/emit-relocs-262.s
new file mode 100644
index 0000000..aa97f52
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-262.s
@@ -0,0 +1,13 @@
+.comm   gempy,4,4
+.text
+
+.word	_GOT_ - .
+.xword  _GOT_ - . + 0x12
+.hword	_GOT_ - . 
+.hword	_GOT_ - . 
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-263.d b/ld/testsuite/ld-aarch64/emit-relocs-263.d
new file mode 100644
index 0000000..a6c854d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-263.d
@@ -0,0 +1,15 @@
+#source: emit-relocs-263.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#error: .*\(.text\+0x\d+\): relocation truncated to fit: R_AARCH64_MOVW_UABS_G0 against symbol `tempy.*
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820004 	movz	x4, #0x1000
+	+10008: R_AARCH64_MOVW_UABS_G0	tempy
+ +1000c:	d28a0007 	movz	x7, #0x5000
+	+1000c: R_AARCH64_MOVW_UABS_G0	tempy2
+ +10010:	d2824691 	movz	x17, #0x1234
+	+10010: R_AARCH64_MOVW_UABS_G0	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-263.s b/ld/testsuite/ld-aarch64/emit-relocs-263.s
new file mode 100644
index 0000000..e215872
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-263.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g0:tempy
+	movz	x7, :abs_g0:tempy2
+	movz	x17, :abs_g0:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-264.d b/ld/testsuite/ld-aarch64/emit-relocs-264.d
new file mode 100644
index 0000000..1da911b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-264.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-264.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820004 	movz	x4, #0x1000
+	+10008: R_AARCH64_MOVW_UABS_G0_NC	tempy
+ +1000c:	d28a0007 	movz	x7, #0x5000
+	+1000c: R_AARCH64_MOVW_UABS_G0_NC	tempy2
+ +10010:	d2824691 	movz	x17, #0x1234
+	+10010: R_AARCH64_MOVW_UABS_G0_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-264.s b/ld/testsuite/ld-aarch64/emit-relocs-264.s
new file mode 100644
index 0000000..32a5a17
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-264.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g0_nc:tempy
+	movz	x7, :abs_g0_nc:tempy2
+	movz	x17, :abs_g0_nc:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-265.d b/ld/testsuite/ld-aarch64/emit-relocs-265.d
new file mode 100644
index 0000000..d30db5f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-265.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-265.s
+#ld: -T relocs.ld --defsym tempy=0x100011000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#error: .*\(.text\+0x\d+\): relocation truncated to fit: R_AARCH64_MOVW_UABS_G1 against symbol `tempy.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2a00024 	movz	x4, #0x1, lsl #16
+	+10008: R_AARCH64_MOVW_UABS_G1	tempy
+ +1000c:	d2a00087 	movz	x7, #0x4, lsl #16
+	+1000c: R_AARCH64_MOVW_UABS_G1	tempy2
+ +10010:	d2a00011 	movz	x17, #0x0, lsl #16
+	+10010: R_AARCH64_MOVW_UABS_G1	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-265.s b/ld/testsuite/ld-aarch64/emit-relocs-265.s
new file mode 100644
index 0000000..552a8ae
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-265.s
@@ -0,0 +1,10 @@
+.comm   gempy,4,4
+.text
+
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g1:tempy
+	movz	x7, :abs_g1:tempy2
+	movz	x17, :abs_g1:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-266.d b/ld/testsuite/ld-aarch64/emit-relocs-266.d
new file mode 100644
index 0000000..fde9090
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-266.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-266.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2a00024 	movz	x4, #0x1, lsl #16
+	+10008: R_AARCH64_MOVW_UABS_G1_NC	tempy
+ +1000c:	d2a00087 	movz	x7, #0x4, lsl #16
+	+1000c: R_AARCH64_MOVW_UABS_G1_NC	tempy2
+ +10010:	d2a00011 	movz	x17, #0x0, lsl #16
+	+10010: R_AARCH64_MOVW_UABS_G1_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-266.s b/ld/testsuite/ld-aarch64/emit-relocs-266.s
new file mode 100644
index 0000000..7c23e87
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-266.s
@@ -0,0 +1,10 @@
+.comm   gempy,4,4
+.text
+
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g1_nc:tempy
+	movz	x7, :abs_g1_nc:tempy2
+	movz	x17, :abs_g1_nc:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-267.d b/ld/testsuite/ld-aarch64/emit-relocs-267.d
new file mode 100644
index 0000000..9cc495c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-267.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-267.s
+#ld: -T relocs.ld --defsym tempy=0x63001000 --defsym tempy2=0x4500000000 --defsym tempy3=0x1234567812345  -e0 --emit-relocs
+#error: .*truncated.*tempy3.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2c00004 	movz	x4, #0x0, lsl #32
+	+10008: R_AARCH64_MOVW_UABS_G2	tempy
+ +1000c:	d2c008a7 	movz	x7, #0x45, lsl #32
+	+1000c: R_AARCH64_MOVW_UABS_G2	tempy2
+ +10010:	d2c468b1 	movz	x17, #0x2345, lsl #32
+	+10010: R_AARCH64_MOVW_UABS_G2	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-267.s b/ld/testsuite/ld-aarch64/emit-relocs-267.s
new file mode 100644
index 0000000..94a150e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-267.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g2:tempy
+	movz	x7, :abs_g2:tempy2
+	movz	x17, :abs_g2:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-268.d b/ld/testsuite/ld-aarch64/emit-relocs-268.d
new file mode 100644
index 0000000..126548b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-268.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-268.s
+#ld: -T relocs.ld --defsym tempy=0x63001000 --defsym tempy2=0x4500000000 --defsym tempy3=0x1234567812345  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2c00004 	movz	x4, #0x0, lsl #32
+	+10008: R_AARCH64_MOVW_UABS_G2_NC	tempy
+ +1000c:	d2c008a7 	movz	x7, #0x45, lsl #32
+	+1000c: R_AARCH64_MOVW_UABS_G2_NC	tempy2
+ +10010:	d2c468b1 	movz	x17, #0x2345, lsl #32
+	+10010: R_AARCH64_MOVW_UABS_G2_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-268.s b/ld/testsuite/ld-aarch64/emit-relocs-268.s
new file mode 100644
index 0000000..5928043
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-268.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g2_nc:tempy
+	movz	x7, :abs_g2_nc:tempy2
+	movz	x17, :abs_g2_nc:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-269.d b/ld/testsuite/ld-aarch64/emit-relocs-269.d
new file mode 100644
index 0000000..a911532
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-269.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-269.s
+#ld: -T relocs.ld --defsym tempy=0x6300100100100100 --defsym tempy2=0xf00df00df00df00d --defsym tempy3=0x1234567812345  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2ec6004 	movz	x4, #0x6300, lsl #48
+	+10008: R_AARCH64_MOVW_UABS_G3	tempy
+ +1000c:	d2fe01a7 	movz	x7, #0xf00d, lsl #48
+	+1000c: R_AARCH64_MOVW_UABS_G3	tempy2
+ +10010:	d2e00031 	movz	x17, #0x1, lsl #48
+	+10010: R_AARCH64_MOVW_UABS_G3	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-269.s b/ld/testsuite/ld-aarch64/emit-relocs-269.s
new file mode 100644
index 0000000..b0f11a0
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-269.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g3:tempy
+	movz	x7, :abs_g3:tempy2
+	movz	x17, :abs_g3:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-270-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-270-bad.d
new file mode 100644
index 0000000..a781a5a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-270-bad.d
@@ -0,0 +1,15 @@
+#source: emit-relocs-270.s
+#ld: -T relocs.ld --defsym tempy=0x10012 --defsym tempy2=0x45000 --defsym tempy3=-292  -e0 --emit-relocs
+#error: .*truncated.*tempy[12].*
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820244 	movz	x4, #0x1012
+	+10008: R_AARCH64_MOVW_SABS_G0	tempy
+ +1000c:	d288a007 	movz	x7, #0x4500
+	+1000c: R_AARCH64_MOVW_SABS_G0	tempy2
+ +10010:	92802471 	movn	x17, #0x123
+	+10010: R_AARCH64_MOVW_SABS_G0	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-270.d b/ld/testsuite/ld-aarch64/emit-relocs-270.d
new file mode 100644
index 0000000..6e68aec
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-270.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-270.s
+#ld: -T relocs.ld --defsym tempy=0x1012 --defsym tempy2=0x4500 --defsym tempy3=-292  -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820244 	movz	x4, #0x1012
+	+10008: R_AARCH64_MOVW_SABS_G0	tempy
+ +1000c:	d288a007 	movz	x7, #0x4500
+	+1000c: R_AARCH64_MOVW_SABS_G0	tempy2
+ +10010:	92802471 	movn	x17, #0x123
+	+10010: R_AARCH64_MOVW_SABS_G0	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-270.s b/ld/testsuite/ld-aarch64/emit-relocs-270.s
new file mode 100644
index 0000000..b508f88
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-270.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g0_s:tempy
+	movz	x7, :abs_g0_s:tempy2
+	movz	x17, :abs_g0_s:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-271.d b/ld/testsuite/ld-aarch64/emit-relocs-271.d
new file mode 100644
index 0000000..5a230c7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-271.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-271.s
+#ld: -T relocs.ld --defsym tempy=0x1012 --defsym tempy2=0x674500 --defsym tempy3=-292  -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2a00004 	movz	x4, #0x0, lsl #16
+	+10008: R_AARCH64_MOVW_SABS_G1	tempy
+ +1000c:	d2a00ce7 	movz	x7, #0x67, lsl #16
+	+1000c: R_AARCH64_MOVW_SABS_G1	tempy2
+ +10010:	92a00011 	movn	x17, #0x0, lsl #16
+	+10010: R_AARCH64_MOVW_SABS_G1	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-271.s b/ld/testsuite/ld-aarch64/emit-relocs-271.s
new file mode 100644
index 0000000..bb14fbb
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-271.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g1_s:tempy
+	movz	x7, :abs_g1_s:tempy2
+	movz	x17, :abs_g1_s:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-272.d b/ld/testsuite/ld-aarch64/emit-relocs-272.d
new file mode 100644
index 0000000..a02a52e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-272.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-272.s
+#ld: -T relocs.ld --defsym tempy=0x1012 --defsym tempy2=-12345678912345 --defsym tempy3=-292  -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2c00004 	movz	x4, #0x0, lsl #32
+	+10008: R_AARCH64_MOVW_SABS_G2	tempy
+ +1000c:	92c16747 	movn	x7, #0xb3a, lsl #32
+	+1000c: R_AARCH64_MOVW_SABS_G2	tempy2
+ +10010:	92c00011 	movn	x17, #0x0, lsl #32
+	+10010: R_AARCH64_MOVW_SABS_G2	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-272.s b/ld/testsuite/ld-aarch64/emit-relocs-272.s
new file mode 100644
index 0000000..daa625a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-272.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g2_s:tempy
+	movz	x7, :abs_g2_s:tempy2
+	movz	x17, :abs_g2_s:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-273.d b/ld/testsuite/ld-aarch64/emit-relocs-273.d
new file mode 100644
index 0000000..13ed221
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-273.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-273.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	58007fc4 	ldr	x4, 11000 <tempy>
+	+10008: R_AARCH64_LD_PREL_LO19	tempy
+ +1000c:	581a7fa7 	ldr	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_LD_PREL_LO19	tempy2
+ +10010:	58f89131 	ldr	x17, 1234 <tempy3>
+	+10010: R_AARCH64_LD_PREL_LO19	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-273.s b/ld/testsuite/ld-aarch64/emit-relocs-273.s
new file mode 100644
index 0000000..d1bad37
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-273.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     x4,tempy
+	ldr	x7,tempy2
+	ldr	x17,tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-274.d b/ld/testsuite/ld-aarch64/emit-relocs-274.d
new file mode 100644
index 0000000..f38ecbd
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-274.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-274.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	10007fc2 	adr	x2, .*
+	+10008: R_AARCH64_ADR_PREL_LO21	tempy
+ +1000c:	101a7fa7 	adr	x7, 45000 .*
+	+1000c: R_AARCH64_ADR_PREL_LO21	tempy2
+ +10010:	10f89131 	adr	x17, .*
+	+10010: R_AARCH64_ADR_PREL_LO21	tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-274.s b/ld/testsuite/ld-aarch64/emit-relocs-274.s
new file mode 100644
index 0000000..8668b7c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-274.s
@@ -0,0 +1,5 @@
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adr     x2,tempy
+        adr     x7,tempy2
+	adr	x17,tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-275.d b/ld/testsuite/ld-aarch64/emit-relocs-275.d
new file mode 100644
index 0000000..94e61a7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-275.d
@@ -0,0 +1,15 @@
+#source: emit-relocs-275.s
+#ld: -T relocs.ld --defsym tempy=0x200011000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#error: .*\(.text\+0x\d+\): relocation truncated to fit: R_AARCH64_ADR_PREL_PG_HI21 against symbol `tempy'
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b0000002 	adrp	x2, .*
+	+10008: R_AARCH64_ADR_PREL_PG_HI21	tempy
+ +1000c:	b00001a7 	adrp	x7, .*
+	+1000c: R_AARCH64_ADR_PREL_PG_HI21	tempy2
+ +10010:	b0ffff91 	adrp	x17, .*
+	+10010: R_AARCH64_ADR_PREL_PG_HI21	tempy3
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-275.s b/ld/testsuite/ld-aarch64/emit-relocs-275.s
new file mode 100644
index 0000000..92a2935
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-275.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adrp    x2,tempy
+	adrp	x7,tempy2
+	adrp	x17,tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-276.d b/ld/testsuite/ld-aarch64/emit-relocs-276.d
new file mode 100644
index 0000000..f133253
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-276.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-275.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b0000002 	adrp	x2, 11000 <tempy>
+	+10008: R_AARCH64_ADR_PREL_PG_HI21	tempy
+ +1000c:	b00001a7 	adrp	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_ADR_PREL_PG_HI21	tempy2
+ +10010:	b0ffff91 	adrp	x17, 1000 <tempy3-0x234>
+	+10010: R_AARCH64_ADR_PREL_PG_HI21	tempy3
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-276.s b/ld/testsuite/ld-aarch64/emit-relocs-276.s
new file mode 100644
index 0000000..92a2935
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-276.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adrp    x2,tempy
+	adrp	x7,tempy2
+	adrp	x17,tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-277.d b/ld/testsuite/ld-aarch64/emit-relocs-277.d
new file mode 100644
index 0000000..2145441
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-277.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-277.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	91006064 	add	x4, x3,.*
+	+10008: R_AARCH64_ADD_ABS_LO12_NC	tempy
+ +1000c:	9100e067 	add	x7, x3,.*
+	+1000c: R_AARCH64_ADD_ABS_LO12_NC	tempy2
+ +10010:	9108d071 	add	x17, x3,.*
+	+10010: R_AARCH64_ADD_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-277.s b/ld/testsuite/ld-aarch64/emit-relocs-277.s
new file mode 100644
index 0000000..efb0bf0
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-277.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        add     x4, x3, #:lo12:tempy
+	add	x7, x3, #:lo12:tempy2
+	add	x17, x3, #:lo12:tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-278.d b/ld/testsuite/ld-aarch64/emit-relocs-278.d
new file mode 100644
index 0000000..29a0095
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-278.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-278.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	3d406064 	ldr	b4, \[x3,.*
+	+10008: R_AARCH64_LDST8_ABS_LO12_NC	tempy
+ +1000c:	3d40e067 	ldr	b7, \[x3,.*
+	+1000c: R_AARCH64_LDST8_ABS_LO12_NC	tempy2
+ +10010:	3d48d071 	ldr	b17, \[x3,.*
+	+10010: R_AARCH64_LDST8_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-278.s b/ld/testsuite/ld-aarch64/emit-relocs-278.s
new file mode 100644
index 0000000..2f7f321
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-278.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     b4, [x3, #:lo12:tempy]
+	ldr	b7, [x3, #:lo12:tempy2]
+	ldr	b17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-279-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-279-bad.d
new file mode 100644
index 0000000..02b5ff6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-279-bad.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-279.s
+#ld: -T relocs.ld --defsym target=0xc000 --defsym target2=0x45678 -e0 --emit-relocs
+#error: .*truncated.*target2.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	17ffeffc 	b	c000 <target>
+	+10010: R_AARCH64_TSTBR14	target
+ +10014:	17ffefff 	b	c010 <target\+0x10>
+	+10014: R_AARCH64_TSTBR14	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-279.d b/ld/testsuite/ld-aarch64/emit-relocs-279.d
new file mode 100644
index 0000000..6980f81
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-279.d
@@ -0,0 +1,17 @@
+#source: emit-relocs-279.s
+#ld: -T relocs.ld --defsym target=0xc000 --defsym target2=0x12340 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	363dff84 	tbz	w4, #7, c000 <target>
+	+10010: R_AARCH64_TSTBR14	target
+ +10014:	b745ffe7 	tbnz	x7, #40, c010 <target\+0x10>
+	+10014: R_AARCH64_TSTBR14	target\+0x10
+ +10018:	3619194c 	tbz	w12, #3, 12340 <target2>
+	+10018: R_AARCH64_TSTBR14	target2
+ +1001c:	b7c118d1 	tbnz	x17, #56, 12334 <target.*
+	+1001c: R_AARCH64_TSTBR14	target.*
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-279.s b/ld/testsuite/ld-aarch64/emit-relocs-279.s
new file mode 100644
index 0000000..f70c78b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-279.s
@@ -0,0 +1,8 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	tbz	x4, 7, target
+	tbnz	x7, 40, target+16
+	tbz	x12, 3, target2
+	tbnz	x17, 56, target2-12
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-280.d b/ld/testsuite/ld-aarch64/emit-relocs-280.d
new file mode 100644
index 0000000..9b954ff
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-280.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-280.s
+#ld: -T relocs.ld --defsym target=0xc000 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	54fdff80 	b.eq	c000 <target>
+	+10010: R_AARCH64_CONDBR19	target
+ +10014:	54fdffe0 	b.eq	c010 <target\+0x10>
+	+10014: R_AARCH64_CONDBR19	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-280.s b/ld/testsuite/ld-aarch64/emit-relocs-280.s
new file mode 100644
index 0000000..8f5ec34
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-280.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	beq	target
+	beq	target+16
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-282.d b/ld/testsuite/ld-aarch64/emit-relocs-282.d
new file mode 100644
index 0000000..fc5764b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-282.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-282.s
+#ld: -T relocs.ld --defsym target=0xc000 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	17ffeffc 	b	c000 <target>
+	+10010: R_AARCH64_JUMP26	target
+ +10014:	17ffefff 	b	c010 <target\+0x10>
+	+10014: R_AARCH64_JUMP26	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-282.s b/ld/testsuite/ld-aarch64/emit-relocs-282.s
new file mode 100644
index 0000000..b249b6b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-282.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	b	target
+	b	target+16
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-283.d b/ld/testsuite/ld-aarch64/emit-relocs-283.d
new file mode 100644
index 0000000..708fc7c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-283.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-283.s
+#ld: -T relocs.ld --defsym target=0xc000 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	97ffeffc 	bl	c000 <target>
+	+10010: R_AARCH64_CALL26	target
+ +10014:	97ffefff 	bl	c010 <target\+0x10>
+	+10014: R_AARCH64_CALL26	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-283.s b/ld/testsuite/ld-aarch64/emit-relocs-283.s
new file mode 100644
index 0000000..9c9f509
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-283.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	bl	target
+	bl	target+16
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-284.d b/ld/testsuite/ld-aarch64/emit-relocs-284.d
new file mode 100644
index 0000000..5cb6dac
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-284.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-284.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	7d403064 	ldr	h4, \[x3,.*
+	+10008: R_AARCH64_LDST16_ABS_LO12_NC	tempy
+ +1000c:	7d407067 	ldr	h7, \[x3,.*
+	+1000c: R_AARCH64_LDST16_ABS_LO12_NC	tempy2
+ +10010:	7d446871 	ldr	h17, \[x3,.*
+	+10010: R_AARCH64_LDST16_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-284.s b/ld/testsuite/ld-aarch64/emit-relocs-284.s
new file mode 100644
index 0000000..ffd213b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-284.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     h4, [x3, #:lo12:tempy]
+	ldr	h7, [x3, #:lo12:tempy2]
+	ldr	h17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-285.d b/ld/testsuite/ld-aarch64/emit-relocs-285.d
new file mode 100644
index 0000000..8bf8270
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-285.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-285.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b9401864 	ldr	w4, \[x3,.*
+	+10008: R_AARCH64_LDST32_ABS_LO12_NC	tempy
+ +1000c:	b9403867 	ldr	w7, \[x3,.*
+	+1000c: R_AARCH64_LDST32_ABS_LO12_NC	tempy2
+ +10010:	b9423471 	ldr	w17, \[x3,.*
+	+10010: R_AARCH64_LDST32_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-285.s b/ld/testsuite/ld-aarch64/emit-relocs-285.s
new file mode 100644
index 0000000..245f8be
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-285.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     w4, [x3, #:lo12:tempy]
+	ldr	w7, [x3, #:lo12:tempy2]
+	ldr	w17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-286-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-286-bad.d
new file mode 100644
index 0000000..50cd605
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-286-bad.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-286.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#error: .*truncated.*tempy3.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	f9400c64 	ldr	x4, \[x3,.*
+	+10008: R_AARCH64_LDST64_ABS_LO12_NC	tempy
+ +1000c:	f9401c67 	ldr	x7, \[x3,.*
+	+1000c: R_AARCH64_LDST64_ABS_LO12_NC	tempy2
+ +10010:	f9411871 	ldr	x17, \[x3,.*
+	+10010: R_AARCH64_LDST64_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-286.d b/ld/testsuite/ld-aarch64/emit-relocs-286.d
new file mode 100644
index 0000000..851fa7b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-286.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-286.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1230  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	f9400c64 	ldr	x4, \[x3,.*
+	+10008: R_AARCH64_LDST64_ABS_LO12_NC	tempy
+ +1000c:	f9401c67 	ldr	x7, \[x3,.*
+	+1000c: R_AARCH64_LDST64_ABS_LO12_NC	tempy2
+ +10010:	f9411871 	ldr	x17, \[x3,.*
+	+10010: R_AARCH64_LDST64_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-286.s b/ld/testsuite/ld-aarch64/emit-relocs-286.s
new file mode 100644
index 0000000..78b508f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-286.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     x4, [x3, #:lo12:tempy]
+	ldr	x7, [x3, #:lo12:tempy2]
+	ldr	x17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-287.d b/ld/testsuite/ld-aarch64/emit-relocs-287.d
new file mode 100644
index 0000000..4d5fd43
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-287.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-287.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 --defsym _GOT_=0x10000 -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820004 	movz	x4, #0x1000
+	+10008: R_AARCH64_MOVW_PREL_G0	_GOT_
+ +1000c:	d28a0007 	movz	x7, #0x5000
+	+1000c: R_AARCH64_MOVW_PREL_G0	_GOT_
+ +10010:	d2824691 	movz	x17, #0x1234
+	+10010: R_AARCH64_MOVW_PREL_G0	_GOT_
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-287.s b/ld/testsuite/ld-aarch64/emit-relocs-287.s
new file mode 100644
index 0000000..ae9476f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-287.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :prel_g0:tempy
+	movz	x7, :prel_g0:tempy2
+	movz	x17, :prel_g0:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-299.d b/ld/testsuite/ld-aarch64/emit-relocs-299.d
new file mode 100644
index 0000000..d24b442
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-299.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-299.s
+#ld: -T relocs.ld --defsym tempy=0x11030 --defsym tempy2=0x45fa0 --defsym tempy3=0x1230  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	3dc00c64 	ldr	q4, \[x3,.*
+	+10008: R_AARCH64_LDST128_ABS_LO12_NC	tempy
+ +1000c:	3dc3e867 	ldr	q7, \[x3,.*
+	+1000c: R_AARCH64_LDST128_ABS_LO12_NC	tempy2
+ +10010:	3dc08c71 	ldr	q17, \[x3,.*
+	+10010: R_AARCH64_LDST128_ABS_LO12_NC	tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-299.s b/ld/testsuite/ld-aarch64/emit-relocs-299.s
new file mode 100644
index 0000000..b1fe6cf
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-299.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+	ldr     q4, [x3, #:lo12:tempy]
+	ldr	q7, [x3, #:lo12:tempy2]
+	ldr	q17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-311.d b/ld/testsuite/ld-aarch64/emit-relocs-311.d
new file mode 100644
index 0000000..5f1b47f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-311.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-311.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b0000002 	adrp	x2, 11000 <tempy>
+	+10008: R_AARCH64_ADR_PREL_PG_HI21	tempy
+ +1000c:	b00001a7 	adrp	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_ADR_PREL_PG_HI21	tempy2
+ +10010:	b0ffff91 	adrp	x17, 1000 <tempy3-0x234>
+	+10010: R_AARCH64_ADR_PREL_PG_HI21	tempy3
+ +10014:	90000083 	adrp	x3, 20000 <tempy[+]0xf000>
+	+10014: R_AARCH64_ADR_GOT_PAGE	gempy
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-311.s b/ld/testsuite/ld-aarch64/emit-relocs-311.s
new file mode 100644
index 0000000..182f0d4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-311.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adrp    x2,tempy
+	adrp	x7,tempy2
+	adrp	x17,tempy3
+        adrp	x3,:got:gempy
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-312.d b/ld/testsuite/ld-aarch64/emit-relocs-312.d
new file mode 100644
index 0000000..8d50d8d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-312.d
@@ -0,0 +1,19 @@
+#source: emit-relocs-312.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	58007fc4 	ldr	x4, 11000 <tempy>
+	+10008: R_AARCH64_LD_PREL_LO19	tempy
+ +1000c:	581a7fa7 	ldr	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_LD_PREL_LO19	tempy2
+ +10010:	58f89131 	ldr	x17, 1234 <tempy3>
+	+10010: R_AARCH64_LD_PREL_LO19	tempy3
+ +10014:	f9400843 	ldr	x3, \[x2.*
+	+10014: R_AARCH64_LD64_GOT_LO12_NC	jempy
+ +10018:	f9400444 	ldr	x4, \[x2.*
+	+10018: R_AARCH64_LD64_GOT_LO12_NC	gempy
+ +1001c:	f9400045 	ldr	x5, \[x2.*
+	+1001c: R_AARCH64_LD64_GOT_LO12_NC	lempy
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-312.s b/ld/testsuite/ld-aarch64/emit-relocs-312.s
new file mode 100644
index 0000000..29494ee
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-312.s
@@ -0,0 +1,13 @@
+.comm   gempy,4
+.comm	jempy,4
+.comm	lempy,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     x4,tempy
+	ldr	x7,tempy2
+	ldr	x17,tempy3
+	ldr	x3, [x2, #:got_lo12:jempy]
+	ldr	x4, [x2, #:got_lo12:gempy]
+	ldr	x5, [x2, #:got_lo12:lempy]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs1.s b/ld/testsuite/ld-aarch64/emit-relocs1.s
new file mode 100644
index 0000000..b249b6b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs1.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	b	target
+	b	target+16
diff --git a/ld/testsuite/ld-aarch64/farcall-b-none-function.d b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
new file mode 100644
index 0000000..34a6568
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
@@ -0,0 +1,5 @@
+#name: aarch64-farcall-b-none-function
+#source: farcall-b-none-function.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_JUMP26 against symbol `bar'.*
diff --git a/ld/testsuite/ld-aarch64/farcall-b-none-function.s b/ld/testsuite/ld-aarch64/farcall-b-none-function.s
new file mode 100644
index 0000000..5e5bc8d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b-none-function.s
@@ -0,0 +1,16 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b.d b/ld/testsuite/ld-aarch64/farcall-b.d
new file mode 100644
index 0000000..f3cb5ef
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b.d
@@ -0,0 +1,22 @@
+#name: aarch64-farcall-b
+#source: farcall-b.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+ +1000:	14000002 	b	1008 <__bar_veneer>
+ +1004:	d65f03c0 	ret
+0000000000001008 <__bar_veneer>:
+    1008:	90040010 	adrp	x16, 8001000 <bar>
+    100c:	91000210 	add	x16, x16, #0x0
+    1010:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+0000000008001000 <bar>:
+ 8001000:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b.s b/ld/testsuite/ld-aarch64/farcall-b.s
new file mode 100644
index 0000000..8ab3103
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b.s
@@ -0,0 +1,17 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-back.d b/ld/testsuite/ld-aarch64/farcall-back.d
new file mode 100644
index 0000000..9ff43b3
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-back.d
@@ -0,0 +1,72 @@
+#name: aarch64-farcall-back
+#source: farcall-back.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x100000000
+#notarget: aarch64_be-*-*
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+    1000:	14000412 	b	2048 <__bar1_veneer>
+    1004:	94000411 	bl	2048 <__bar1_veneer>
+    1008:	14000406 	b	2020 <__bar2_veneer>
+    100c:	94000405 	bl	2020 <__bar2_veneer>
+    1010:	14000408 	b	2030 <__bar3_veneer>
+    1014:	94000407 	bl	2030 <__bar3_veneer>
+    1018:	d65f03c0 	ret
+	...
+
+000000000000201c <_back>:
+    201c:	d65f03c0 	ret
+
+0000000000002020 <__bar2_veneer>:
+    2020:	f07ffff0 	adrp	x16, 100001000 <bar1\+0x1000>
+    2024:	91002210 	add	x16, x16, #0x8
+    2028:	d61f0200 	br	x16
+    202c:	00000000 	.inst	0x00000000 ; undefined
+
+0000000000002030 <__bar3_veneer>:
+    2030:	58000090 	ldr	x16, 2040 <__bar3_veneer\+0x10>
+    2034:	10000011 	adr	x17, 2034 <__bar3_veneer\+0x4>
+    2038:	8b110210 	add	x16, x16, x17
+    203c:	d61f0200 	br	x16
+    2040:	ffffffdc 	.word	0xffffffdc
+    2044:	00000000 	.word	0x00000000
+
+0000000000002048 <__bar1_veneer>:
+    2048:	d07ffff0 	adrp	x16, 100000000 <bar1>
+    204c:	91000210 	add	x16, x16, #0x0
+    2050:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+0000000100000000 <bar1>:
+   100000000:	d65f03c0 	ret
+   100000004:	14000805 	b	100002018 <___start_veneer>
+	...
+
+0000000100001008 <bar2>:
+   100001008:	d65f03c0 	ret
+   10000100c:	14000403 	b	100002018 <___start_veneer>
+	...
+
+0000000100002010 <bar3>:
+   100002010:	d65f03c0 	ret
+   100002014:	14000007 	b	100002030 <___back_veneer>
+
+0000000100002018 <___start_veneer>:
+   100002018:	58000090 	ldr	x16, 100002028 <___start_veneer\+0x10>
+   10000201c:	10000011 	adr	x17, 10000201c <___start_veneer\+0x4>
+   100002020:	8b110210 	add	x16, x16, x17
+   100002024:	d61f0200 	br	x16
+   100002028:	ffffefe4 	.word	0xffffefe4
+   10000202c:	fffffffe 	.word	0xfffffffe
+
+0000000100002030 <___back_veneer>:
+   100002030:	90800010 	adrp	x16, 2000 <_start\+0x1000>
+   100002034:	91007210 	add	x16, x16, #0x1c
+   100002038:	d61f0200 	br	x16
+	...
diff --git a/ld/testsuite/ld-aarch64/farcall-back.s b/ld/testsuite/ld-aarch64/farcall-back.s
new file mode 100644
index 0000000..d0a3bd5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-back.s
@@ -0,0 +1,42 @@
+	.global _start
+	.global _back
+	.global bar1
+	.global bar2
+	.global bar3
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+	.type _start, @function
+_start:
+	b	bar1
+	bl	bar1
+	b	bar2
+	bl	bar2
+	b	bar3
+	bl	bar3
+	ret
+	.space	0x1000
+	.type _back, @function
+_back:	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar1, @function
+bar1:
+	ret
+	b	_start
+
+	.space 0x1000
+	.type bar2, @function
+bar2:
+	ret
+	b	_start
+
+	.space 0x1000
+	.type bar3, @function
+bar3:
+	ret
+	b	_back
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-none-function.d b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
new file mode 100644
index 0000000..6ce9ca4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
@@ -0,0 +1,5 @@
+#name: aarch64-farcall-bl-none-function
+#source: farcall-bl-none-function.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against symbol `bar'.*
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-none-function.s b/ld/testsuite/ld-aarch64/farcall-bl-none-function.s
new file mode 100644
index 0000000..89aa85a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl-none-function.s
@@ -0,0 +1,16 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl.d b/ld/testsuite/ld-aarch64/farcall-bl.d
new file mode 100644
index 0000000..2bdd2c4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl.d
@@ -0,0 +1,23 @@
+#name: aarch64-farcall-bl
+#source: farcall-bl.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+ +1000:	94000002 	bl	1008 <__bar_veneer>
+ +1004:	d65f03c0 	ret
+
+0000000000001008 <__bar_veneer>:
+    1008:	90040010 	adrp	x16, 8001000 <bar>
+    100c:	91000210 	add	x16, x16, #0x0
+    1010:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+0000000008001000 <bar>:
+ 8001000:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl.s b/ld/testsuite/ld-aarch64/farcall-bl.s
new file mode 100644
index 0000000..432b120
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl.s
@@ -0,0 +1,17 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-section.d b/ld/testsuite/ld-aarch64/farcall-section.d
new file mode 100644
index 0000000..85775e1
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-section.d
@@ -0,0 +1,5 @@
+#name: Aarch64 farcall to symbol of type STT_SECTION
+#source: farcall-section.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001014
+#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against `.foo'
diff --git a/ld/testsuite/ld-aarch64/farcall-section.s b/ld/testsuite/ld-aarch64/farcall-section.s
new file mode 100644
index 0000000..86a070c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-section.s
@@ -0,0 +1,19 @@
+# Test to ensure that an Aarch64 call exceeding 128MB generates an error
+# if the destination is of type STT_SECTION (eg non-global symbol)
+
+	.global _start
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+
+# We will place the section .foo at 0x8001020.
+
+	.section .foo, "xa"
+
+bar:
+	ret
+
diff --git a/ld/testsuite/ld-aarch64/limit-b.d b/ld/testsuite/ld-aarch64/limit-b.d
new file mode 100644
index 0000000..95d4c8f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-b.d
@@ -0,0 +1,17 @@
+#name: aarch64-limit-b
+#source: limit-b.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8000ffc
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+    1000:	15ffffff 	b	8000ffc <bar>
+    1004:	d65f03c0 	ret
+
+Disassembly of section .foo:
+
+0000000008000ffc <bar>:
+ 8000ffc:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/limit-b.s b/ld/testsuite/ld-aarch64/limit-b.s
new file mode 100644
index 0000000..2b9f432
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-b.s
@@ -0,0 +1,19 @@
+# Test maximum encoding range of b
+
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	ret
+
+# We will place the section .foo at 0x8000ffc
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/limit-bl.d b/ld/testsuite/ld-aarch64/limit-bl.d
new file mode 100644
index 0000000..2eddeb7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-bl.d
@@ -0,0 +1,17 @@
+#name: aarch64-limit-bl
+#source: limit-bl.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8000ffc
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+    1000:	95ffffff 	bl	8000ffc <bar>
+    1004:	d65f03c0 	ret
+
+Disassembly of section .foo:
+
+0000000008000ffc <bar>:
+ 8000ffc:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/limit-bl.s b/ld/testsuite/ld-aarch64/limit-bl.s
new file mode 100644
index 0000000..72f47a5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-bl.s
@@ -0,0 +1,19 @@
+# Test maximum encoding range of bl
+
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	ret
+
+# We will place the section .foo at 0x8000ffc
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/relocs.ld b/ld/testsuite/ld-aarch64/relocs.ld
new file mode 100644
index 0000000..f42176e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/relocs.ld
@@ -0,0 +1,19 @@
+/* Script for ld testsuite */
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x8000); . = 0x10000;
+  .text           :
+  {
+    *(.before)
+    *(.text)
+    *(.after)
+  } =0
+  . = 0x20000;
+  .got            : { *(.got) *(.got.plt)}
+  . = 0x12340000;
+  .far : { *(.far) }
+  .ARM.attributes 0 : { *(.ARM.atttributes) }
+}
diff --git a/ld/testsuite/ld-aarch64/tls-desc-ie.d b/ld/testsuite/ld-aarch64/tls-desc-ie.d
new file mode 100644
index 0000000..712e39c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-desc-ie.d
@@ -0,0 +1,36 @@
+#source: tls-desc-ie.s
+#ld: -shared -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10004:	91002000 	add	x0, x0, #0x8
+ +10008:	94000016 	bl	10060 <v1\+0x10060>
+ +1000c:	d503201f 	nop
+ +10010:	90000080 	adrp	x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10014:	f9400000 	ldr	x0, \[x0\]
+ +10018:	d503201f 	nop
+ +1001c:	d503201f 	nop
+ +10020:	d53bd041 	mrs	x1, tpidr_el0
+ +10024:	8b000020 	add	x0, x1, x0
+ +10028:	d53bd042 	mrs	x2, tpidr_el0
+ +1002c:	90000080 	adrp	x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10030:	f9400000 	ldr	x0, \[x0\]
+ +10034:	8b000040 	add	x0, x2, x0
+ +10038:	b9400000 	ldr	w0, \[x0\]
+ +1003c:	0b000020 	add	w0, w1, w0
+
+Disassembly of section .plt:
+
+0000000000010040 <.plt>:
+ +10040:	a9bf7bf0 	stp	x16, x30, \[sp,#-16\]!
+ +10044:	90000090 	adrp	x16, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10048:	f9401611 	ldr	x17, \[x16,#40\]
+ +1004c:	9100a210 	add	x16, x16, #0x28
+ +10050:	d61f0220 	br	x17
+ +10054:	d503201f 	nop
+ +10058:	d503201f 	nop
+ +1005c:	d503201f 	nop
+ +10060:	90000090 	adrp	x16, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10064:	f9401a11 	ldr	x17, \[x16,#48\]
+ +10068:	9100c210 	add	x16, x16, #0x30
+ +1006c:	d61f0220 	br	x17
diff --git a/ld/testsuite/ld-aarch64/tls-desc-ie.s b/ld/testsuite/ld-aarch64/tls-desc-ie.s
new file mode 100644
index 0000000..93fd71c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-desc-ie.s
@@ -0,0 +1,32 @@
+	.global	v1
+	.global	v2
+	.section	.tdata,"awT",%progbits
+v1:
+	.word	1
+
+	.text
+
+# This GD access does not relax. It consumes a double GOT slot.
+
+	adrp	x0, :tlsgd:v2
+	add	x0, x0, :tlsgd_lo12:v2
+	bl	__tls_get_addr
+	nop
+
+# Test the combination of a TLSDESC-GD and IE access to the same
+# symbol. We expect the TLSDESC-GD to relax to IE.
+
+	adrp	x0, :tlsdesc:v1
+	ldr	x1, [x0, #:tlsdesc_lo12:v1]
+	add	x0, x0, :tlsdesc_lo12:v1
+	.tlsdesccall	v1
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+
+	mrs	x2, tpidr_el0
+	adrp	x0, :gottprel:v1
+	ldr	x0, [x0, #:gottprel_lo12:v1]
+	add	x0, x2, x0
+	ldr	w0, [x0]
+	add	w0, w1, w0
diff --git a/ld/testsuite/ld-aarch64/tls-relax-all.d b/ld/testsuite/ld-aarch64/tls-relax-all.d
new file mode 100644
index 0000000..d3db04d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-all.d
@@ -0,0 +1,39 @@
+#source: tls-relax-all.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	a9bf7bfd 	stp	x29, x30, \[sp,#-16\]!
+ +10004:	910003fd 	mov	x29, sp
+ +10008:	90000080 	adrp	x0, 20000 <ie_var\+0x1fff0>
+ +1000c:	f9400000 	ldr	x0, \[x0\]
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d53bd041 	mrs	x1, tpidr_el0
+ +1001c:	8b000020 	add	x0, x1, x0
+ +10020:	b9400001 	ldr	w1, \[x0\]
+ +10024:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10028:	f2800280 	movk	x0, #0x14
+ +1002c:	d503201f 	nop
+ +10030:	d503201f 	nop
+ +10034:	d53bd042 	mrs	x2, tpidr_el0
+ +10038:	8b000040 	add	x0, x2, x0
+ +1003c:	b9400000 	ldr	w0, \[x0\]
+ +10040:	0b000021 	add	w1, w1, w0
+ +10044:	90000080 	adrp	x0, 20000 <ie_var\+0x1fff0>
+ +10048:	f9400400 	ldr	x0, \[x0,#8\]
+ +1004c:	d53bd041 	mrs	x1, tpidr_el0
+ +10050:	8b000020 	add	x0, x1, x0
+ +10054:	b9400000 	ldr	w0, \[x0\]
+ +10058:	0b000021 	add	w1, w1, w0
+ +1005c:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10060:	f2800380 	movk	x0, #0x1c
+ +10064:	d53bd041 	mrs	x1, tpidr_el0
+ +10068:	8b000020 	add	x0, x1, x0
+ +1006c:	b9400000 	ldr	w0, \[x0\]
+ +10070:	0b000021 	add	w1, w1, w0
+ +10074:	d53bd042 	mrs	x2, tpidr_el0
+ +10078:	d2a00000 	movz	x0, #0x0, lsl #16
+ +1007c:	f2800400 	movk	x0, #0x20
+ +10080:	8b000040 	add	x0, x2, x0
+ +10084:	b9400000 	ldr	w0, \[x0\]
+ +10088:	0b000020 	add	w0, w1, w0
diff --git a/ld/testsuite/ld-aarch64/tls-relax-all.s b/ld/testsuite/ld-aarch64/tls-relax-all.s
new file mode 100644
index 0000000..1bef53d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-all.s
@@ -0,0 +1,51 @@
+	.global	gdesc_var_1
+	.global	gd_var_1
+	.section	.tdata,"awT",%progbits
+gdesc_var_1:
+	.word	1
+gdesc_var_2:
+	.word	2
+gd_var_1:
+	.word	3
+gd_var_2:
+	.word	4
+ie_var:
+	.word	5
+	.text
+	stp	x29, x30, [sp, -16]!
+	add	x29, sp, 0
+	adrp	x0, :tlsdesc:gdesc_var_1
+	ldr	x1, [x0, #:tlsdesc_lo12:gdesc_var_1]
+	add	x0, x0, :tlsdesc_lo12:gdesc_var_1
+	.tlsdesccall	gdesc_var_1
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w1, [x0]
+	adrp	x0, :tlsdesc:gdesc_var_2
+	ldr	x2, [x0, #:tlsdesc_lo12:gdesc_var_2]
+	add	x0, x0, :tlsdesc_lo12:gdesc_var_2
+	.tlsdesccall	gdesc_var_2
+	blr	x2
+	mrs	x2, tpidr_el0
+	add	x0, x2, x0
+	ldr	w0, [x0]
+	add	w1, w1, w0
+	adrp	x0, :tlsgd:gd_var_1
+	add	x0, x0, :tlsgd_lo12:gd_var_1
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
+	add	w1, w1, w0
+	adrp	x0, :tlsgd:gd_var_2
+	add	x0, x0, :tlsgd_lo12:gd_var_2
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
+	add	w1, w1, w0
+	mrs	x2, tpidr_el0
+	adrp	x0, :gottprel:ie_var
+	ldr	x0, [x0, #:gottprel_lo12:ie_var]
+	add	x0, x2, x0
+	ldr	w0, [x0]
+	add	w0, w1, w0
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-ie.d b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.d
new file mode 100644
index 0000000..a142f54
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.d
@@ -0,0 +1,9 @@
+#source: tls-relax-gd-ie.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <var\+0x20000>
+ +10004:	f9400000 	ldr	x0, \[x0\]
+ +10008:	d53bd041 	mrs	x1, tpidr_el0
+ +1000c:	8b000020 	add	x0, x1, x0
+ +10010:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-ie.s b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.s
new file mode 100644
index 0000000..88c7eec
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.s
@@ -0,0 +1,10 @@
+	.global	var
+	.section	.tdata,"awT",%progbits
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsgd:var
+	add	x0, x0, :tlsgd_lo12:var
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-le.d b/ld/testsuite/ld-aarch64/tls-relax-gd-le.d
new file mode 100644
index 0000000..b5ee39c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-le.d
@@ -0,0 +1,9 @@
+#source: tls-relax-gd-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10004:	f2800200 	movk	x0, #0x10
+ +10008:	d53bd041 	mrs	x1, tpidr_el0
+ +1000c:	8b000020 	add	x0, x1, x0
+ +10010:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-le.s b/ld/testsuite/ld-aarch64/tls-relax-gd-le.s
new file mode 100644
index 0000000..eb6fc2f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-le.s
@@ -0,0 +1,9 @@
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsgd:var
+	add	x0, x0, :tlsgd_lo12:var
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d
new file mode 100644
index 0000000..f3307ae
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d
@@ -0,0 +1,18 @@
+#source: tls-relax-gdesc-ie-2.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <var\+0x20000>
+ +10004:	d503201f 	nop
+ +10008:	f9400000 	ldr	x0, \[x0\]
+ +1000c:	d503201f 	nop
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d503201f 	nop
+ +1001c:	d503201f 	nop
+ +10020:	d503201f 	nop
+ +10024:	d503201f 	nop
+ +10028:	d503201f 	nop
+ +1002c:	d53bd041 	mrs	x1, tpidr_el0
+ +10030:	8b000020 	add	x0, x1, x0
+ +10034:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s
new file mode 100644
index 0000000..790b6c6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s
@@ -0,0 +1,24 @@
+// Test TLS Desc to TLS IE relaxation when instructions are not consecutive.
+
+	.global	var
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	nop
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	nop
+	nop
+	nop
+	add	x0, x0, :tlsdesc_lo12:var
+	nop
+	nop
+	.tlsdesccall	var
+	blr	x1
+	nop
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
+	.global	var
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d
new file mode 100644
index 0000000..691df06
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d
@@ -0,0 +1,11 @@
+#source: tls-relax-gdesc-ie.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <var\+0x20000>
+ +10004:	f9400000 	ldr	x0, \[x0\]
+ +10008:	d503201f 	nop
+ +1000c:	d503201f 	nop
+ +10010:	d53bd041 	mrs	x1, tpidr_el0
+ +10014:	8b000020 	add	x0, x1, x0
+ +10018:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
new file mode 100644
index 0000000..c20690c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
@@ -0,0 +1,13 @@
+	.global	var
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	add	x0, x0, :tlsdesc_lo12:var
+	.tlsdesccall	var
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.d
new file mode 100644
index 0000000..3c028e2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.d
@@ -0,0 +1,18 @@
+#source: tls-relax-gdesc-le-2.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10004:	d503201f 	nop
+ +10008:	d503201f 	nop
+ +1000c:	f2800200 	movk	x0, #0x10
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d503201f 	nop
+ +1001c:	d503201f 	nop
+ +10020:	d503201f 	nop
+ +10024:	d503201f 	nop
+ +10028:	d503201f 	nop
+ +1002c:	d53bd041 	mrs	x1, tpidr_el0
+ +10030:	8b000020 	add	x0, x1, x0
+ +10034:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.s
new file mode 100644
index 0000000..fb8bf66
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.s
@@ -0,0 +1,22 @@
+# Test TLS Desc to TLS LE relaxation when instructions are not consecutive.
+
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	nop
+	nop
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	nop
+	add	x0, x0, :tlsdesc_lo12:var
+	nop
+	nop
+	nop
+	.tlsdesccall	var
+	blr	x1
+	nop
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.d
new file mode 100644
index 0000000..afe0a56
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.d
@@ -0,0 +1,11 @@
+#source: tls-relax-gdesc-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10004:	f2800200 	movk	x0, #0x10
+ +10008:	d503201f 	nop
+ +1000c:	d503201f 	nop
+ +10010:	d53bd041 	mrs	x1, tpidr_el0
+ +10014:	8b000020 	add	x0, x1, x0
+ +10018:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.s
new file mode 100644
index 0000000..28ee0f6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.s
@@ -0,0 +1,12 @@
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	add	x0, x0, :tlsdesc_lo12:var
+	.tlsdesccall	var
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.d
new file mode 100644
index 0000000..2f93955
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.d
@@ -0,0 +1,17 @@
+#source: tls-relax-ie-le-2.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d53bd041 	mrs	x1, tpidr_el0
+ +10004:	d503201f 	nop
+ +10008:	d503201f 	nop
+ +1000c:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d503201f 	nop
+ +1001c:	f2800200 	movk	x0, #0x10
+ +10020:	d503201f 	nop
+ +10024:	8b000020 	add	x0, x1, x0
+ +10028:	d503201f 	nop
+ +1002c:	d503201f 	nop
+ +10030:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.s
new file mode 100644
index 0000000..98b62e2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.s
@@ -0,0 +1,20 @@
+# Test TLS IE to TLS LE relaxation when instructions are not consecutive.
+
+	.section	.tdata
+var:
+	.word	2
+	.text
+	mrs	x1, tpidr_el0
+	nop
+	nop
+	adrp	x0, :gottprel:var
+	nop
+	nop
+	nop
+	ldr	x0, [x0, #:gottprel_lo12:var]
+	nop
+	add	x0, x1, x0
+	nop
+	nop
+	ldr	w0, [x0]
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.d
new file mode 100644
index 0000000..a2fd823
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.d
@@ -0,0 +1,9 @@
+#source: tls-relax-ie-le-3.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d53bd042 	mrs	x2, tpidr_el0
+ +10004:	d2a0000f 	movz	x15, #0x0, lsl #16
+ +10008:	f280020f 	movk	x15, #0x10
+ +1000c:	8b0f004f 	add	x15, x2, x15
+ +10010:	b94001e0 	ldr	w0, \[x15\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.s
new file mode 100644
index 0000000..70e7062
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.s
@@ -0,0 +1,12 @@
+# Test TLS IE to TLS LE relaxation when using arbitrary registers.
+
+	.section	.tdata
+var:
+	.word	2
+	.text
+	mrs	x2, tpidr_el0
+	adrp	x15, :gottprel:var
+	ldr	x15, [x15, #:gottprel_lo12:var]
+	add	x15, x2, x15
+	ldr	w0, [x15]
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le.d
new file mode 100644
index 0000000..ff3b344
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le.d
@@ -0,0 +1,9 @@
+#source: tls-relax-ie-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d53bd041 	mrs	x1, tpidr_el0
+ +10004:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10008:	f2800200 	movk	x0, #0x10
+ +1000c:	8b000020 	add	x0, x1, x0
+ +10010:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le.s
new file mode 100644
index 0000000..093cda2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le.s
@@ -0,0 +1,9 @@
+	.section	.tdata
+var:
+	.word	2
+	.text
+	mrs	x1, tpidr_el0
+	adrp	x0, :gottprel:var
+	ldr	x0, [x0, #:gottprel_lo12:var]
+	add	x0, x1, x0
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/weak-undefined.d b/ld/testsuite/ld-aarch64/weak-undefined.d
new file mode 100644
index 0000000..22a9860
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/weak-undefined.d
@@ -0,0 +1,18 @@
+#source: weak-undefined.s
+#ld: -Ttext 0xF0000000 -T relocs.ld -e0 --emit-relocs
+#objdump: -d
+#...
+ +f0000000:	54000001 	b\.ne	f0000000 <main>
+ +f0000004:	54000000 	b\.eq	f0000004 <main\+0x4>
+ +f0000008:	54000002 	b\.cs	f0000008 <main\+0x8>
+ +f000000c:	54000003 	b\.cc	f000000c <main\+0xc>
+ +f0000010:	5400000c 	b\.gt	f0000010 <main\+0x10>
+ +f0000014:	5400000a 	b\.ge	f0000014 <main\+0x14>
+ +f0000018:	5400000b 	b\.lt	f0000018 <main\+0x18>
+ +f000001c:	5400000d 	b\.le	f000001c <main\+0x1c>
+ +f0000020:	d503201f 	nop
+ +f0000024:	d503201f 	nop
+ +f0000028:	58000000 	ldr	x0, f0000028 <main\+0x28>
+ +f000002c:	10000000 	adr	x0, f000002c <main\+0x2c>
+ +f0000030:	90000000 	adrp	x0, f0000000 <main>
+ +f0000034:	91000000 	add	x0, x0, #0x0
diff --git a/ld/testsuite/ld-aarch64/weak-undefined.s b/ld/testsuite/ld-aarch64/weak-undefined.s
new file mode 100644
index 0000000..692798f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/weak-undefined.s
@@ -0,0 +1,18 @@
+.text
+	.weak foo
+	.global main
+main:
+	b.ne	foo
+	b.eq	foo
+	b.cs	foo
+	b.cc	foo
+	b.gt	foo
+	b.ge	foo
+	b.lt	foo
+	b.le	foo
+	b	foo
+	bl	foo
+	ldr	x0, foo
+	adr	x0, foo
+	adrp	x0, foo
+	add	x0, x0, :lo12:foo
diff --git a/ld/testsuite/ld-elf/binutils.exp b/ld/testsuite/ld-elf/binutils.exp
index 4d91105..249fa2a 100644
--- a/ld/testsuite/ld-elf/binutils.exp
+++ b/ld/testsuite/ld-elf/binutils.exp
@@ -34,7 +34,12 @@ if { [istarget *-*-linux*aout*]
     return
 }
 
-proc binutils_test { prog_name ld_options test } {
+# The optional test_name argument provides a mechanism for the caller
+# to hardwire the test name. This is important if ld_options contains
+# absolute path names because the default test name is constructed
+# from the prog_name and ld_options and we do not want absolute paths
+# to appear in the test_name.
+proc binutils_test { prog_name ld_options test {test_name ""}} {
     global as
     global ld
     global READELF
@@ -45,7 +50,10 @@ proc binutils_test { prog_name ld_options test } {
     global link_output
 
     eval set prog \$$prog_name
-    set test_name "$prog_name $ld_options ($test)"
+
+    if { "$test_name" == "" } {
+      set test_name "$prog_name $ld_options ($test)"
+    }
 
     if { ![ld_assemble $as $srcdir/$subdir/$test.s tmpdir/$test.o ] } {
 	unresolved "$test_name"
@@ -123,7 +131,7 @@ if { ([istarget "i?86-*-elf*"]
     binutils_test objcopy "-z relro -shared" relro2
 }
 
-binutils_test strip "-T ${srcdir}/${subdir}/lma.lnk" lma
+binutils_test strip "-T ${srcdir}/${subdir}/lma.lnk" lma "strip -T lma.lnk"
 
 set tls_tests { "tdata1" "tdata2" }
 # hppa64 has its own .tbss section, with different flags.
diff --git a/ld/testsuite/ld-elf/exclude.exp b/ld/testsuite/ld-elf/exclude.exp
index 28a34ab..4c3d7ac 100644
--- a/ld/testsuite/ld-elf/exclude.exp
+++ b/ld/testsuite/ld-elf/exclude.exp
@@ -27,7 +27,7 @@ if ![is_elf_format] {
 }
 
 # No shared lib support on this target.
-if { [istarget "mcore-*-*"] } {
+if { [istarget "mcore-*-*"] || [istarget "aarch64-*-*"] } {
     return
 }
 
diff --git a/ld/testsuite/ld-elf/frame.exp b/ld/testsuite/ld-elf/frame.exp
index 66e6ac5..79de624 100644
--- a/ld/testsuite/ld-elf/frame.exp
+++ b/ld/testsuite/ld-elf/frame.exp
@@ -29,7 +29,7 @@ if ![is_elf_format] {
 }
 
 # No shared lib support on this target.
-if { [istarget "mcore-*-*"] } {
+if { [istarget "mcore-*-*"] || [istarget "aarch64*-*-*"] } {
     return
 }
 
diff --git a/ld/testsuite/ld-elf/group8a.d b/ld/testsuite/ld-elf/group8a.d
index bad4123..753eb0f 100644
--- a/ld/testsuite/ld-elf/group8a.d
+++ b/ld/testsuite/ld-elf/group8a.d
@@ -1,7 +1,7 @@
 #source: group8.s
 #ld: -r --gc-sections --entry foo
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/group8b.d b/ld/testsuite/ld-elf/group8b.d
index fb37198..107ff69 100644
--- a/ld/testsuite/ld-elf/group8b.d
+++ b/ld/testsuite/ld-elf/group8b.d
@@ -1,7 +1,7 @@
 #source: group8.s
 #ld: -r --gc-sections --entry bar
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/group9a.d b/ld/testsuite/ld-elf/group9a.d
index fd04c48..511cec7 100644
--- a/ld/testsuite/ld-elf/group9a.d
+++ b/ld/testsuite/ld-elf/group9a.d
@@ -1,7 +1,7 @@
 #source: group9.s
 #ld: -r --gc-sections --entry foo
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: alpha-*-* hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/group9b.d b/ld/testsuite/ld-elf/group9b.d
index 3f19fd6..fd5b0c2 100644
--- a/ld/testsuite/ld-elf/group9b.d
+++ b/ld/testsuite/ld-elf/group9b.d
@@ -1,7 +1,7 @@
 #source: group9.s
 #ld: -r --gc-sections --entry bar
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: alpha-*-* hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/pr12851.d b/ld/testsuite/ld-elf/pr12851.d
index fb61c5a..9160142 100644
--- a/ld/testsuite/ld-elf/pr12851.d
+++ b/ld/testsuite/ld-elf/pr12851.d
@@ -2,7 +2,7 @@
 #source: start.s
 #ld: --gc-sections
 #readelf: -s --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elf/pr12975.d b/ld/testsuite/ld-elf/pr12975.d
index b361cc2..abdb571 100644
--- a/ld/testsuite/ld-elf/pr12975.d
+++ b/ld/testsuite/ld-elf/pr12975.d
@@ -1,7 +1,7 @@
 #ld: --gc-sections -shared -version-script pr12975.t
 #readelf: -s --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elf/pr13177.d b/ld/testsuite/ld-elf/pr13177.d
index e56e865..f32e15d 100644
--- a/ld/testsuite/ld-elf/pr13177.d
+++ b/ld/testsuite/ld-elf/pr13177.d
@@ -2,7 +2,7 @@
 #ld: --gc-sections -shared
 #readelf: -s -D --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elf/pr13195.d b/ld/testsuite/ld-elf/pr13195.d
index 796102b..88c6278 100644
--- a/ld/testsuite/ld-elf/pr13195.d
+++ b/ld/testsuite/ld-elf/pr13195.d
@@ -1,7 +1,7 @@
 #ld: --gc-sections -shared -version-script pr13195.t
 #readelf: -s --wide -D
 #target: *-*-linux* *-*-gnu*
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elfvers/vers.exp b/ld/testsuite/ld-elfvers/vers.exp
index 4bea6e4..1e9ff53 100644
--- a/ld/testsuite/ld-elfvers/vers.exp
+++ b/ld/testsuite/ld-elfvers/vers.exp
@@ -47,6 +47,7 @@ if { ![istarget hppa*64*-*-hpux*]
      && ![istarget sparc*-*-elf]
      && ![istarget sparc*-*-solaris2*]
      && ![istarget sparc*-*-linux*]
+     && ![istarget aarch64*-*-linux*]
      && ![istarget arm*-*-linux*]
      && ![istarget mips*-*-linux*]
      && ![istarget alpha*-*-linux*]
diff --git a/ld/testsuite/ld-shared/shared.exp b/ld/testsuite/ld-shared/shared.exp
index 7ec304b..07fc881 100644
--- a/ld/testsuite/ld-shared/shared.exp
+++ b/ld/testsuite/ld-shared/shared.exp
@@ -57,6 +57,7 @@ if { ![istarget hppa*64*-*-hpux*] \
      && ![istarget rs6000*-*-aix*] \
      && ![istarget powerpc*-*-aix*] \
      && ![istarget s390*-*-linux*] \
+     && ![istarget aarch64*-*-linux*] \
      && ![istarget x86_64-*-linux*] } {
     return
 }
diff --git a/ld/testsuite/ld-srec/srec.exp b/ld/testsuite/ld-srec/srec.exp
index 7f13e9c..001fb2e 100644
--- a/ld/testsuite/ld-srec/srec.exp
+++ b/ld/testsuite/ld-srec/srec.exp
@@ -250,9 +250,12 @@ proc run_srec_test { test objs } {
 	setup_xfail "sh64*-*-*"
     }
 
-    if {[istarget arm*-*-*]} {
-        # ARM targets cannot convert format in the linker 
+    if {[istarget aarch64*-*-*]   || \
+        [istarget arm*-*-*]} {
+        # ARM targets cannot convert format in the linker
         # using the --oformat command line switch
+	setup_xfail "aarch64-*-*"
+	setup_xfail "aarch64_be-*-*"
 	setup_xfail "arm*-*-*"
     }
 
diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp
index a481ce7..f05d42c 100644
--- a/ld/testsuite/lib/ld-lib.exp
+++ b/ld/testsuite/lib/ld-lib.exp
@@ -1459,7 +1459,8 @@ proc check_gc_sections_available { } {
     if {![info exists gc_sections_available_saved]} {
 	# Some targets don't support gc-sections despite whatever's
 	# advertised by ld's options.
-	if {[istarget arc-*-*]
+	if {[istarget aarch64*-*-*]
+	     || [istarget arc-*-*]
 	     || [istarget d30v-*-*]
 	     || [istarget dlx-*-*]
 	     || [istarget i960-*-*]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes
  2012-07-30 14:21 [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Richard Earnshaw
                   ` (6 preceding siblings ...)
  2012-07-30 15:00 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes Yufeng Zhang
@ 2012-07-30 15:02 ` Yufeng Zhang
  2012-07-30 15:17   ` Joseph S. Myers
  7 siblings, 1 reply; 41+ messages in thread
From: Yufeng Zhang @ 2012-07-30 15:02 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1175 bytes --]

This patch adds the binutils changes of the AArch64 target support.


binutils/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * readelf.c: Add AArch64.


binutils/testsuite/ChangeLog
2012-07-30  Ian Bolton  <ian.bolton@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * objdump.exp: Add AArch64.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: aarch64-binutils.patch --]
[-- Type: text/x-patch; name=aarch64-binutils.patch, Size: 3450 bytes --]

diff --git a/binutils/readelf.c b/binutils/readelf.c
index e6f2be6..e52b9c4 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -91,6 +91,7 @@
 
 #define RELOC_MACROS_GEN_FUNC
 
+#include "elf/aarch64.h"
 #include "elf/alpha.h"
 #include "elf/arc.h"
 #include "elf/arm.h"
@@ -551,6 +552,7 @@ guess_is_rela (unsigned int e_machine)
       /* Targets that use RELA relocations.  */
     case EM_68K:
     case EM_860:
+    case EM_AARCH64:
     case EM_ADAPTEVA_EPIPHANY:
     case EM_ALPHA:
     case EM_ALTERA_NIOS2:
@@ -983,6 +985,10 @@ dump_relocations (FILE * file,
 	  rtype = NULL;
 	  break;
 
+	case EM_AARCH64:
+	  rtype = elf_aarch64_reloc_type (type);
+	  break;
+
 	case EM_M32R:
 	case EM_CYGNUS_M32R:
 	  rtype = elf_m32r_reloc_type (type);
@@ -1830,6 +1836,7 @@ get_machine_name (unsigned e_machine)
   switch (e_machine)
     {
     case EM_NONE:		return _("None");
+    case EM_AARCH64:		return "AArch64";
     case EM_M32:		return "WE32100";
     case EM_SPARC:		return "Sparc";
     case EM_SPU:		return "SPU";
@@ -9770,6 +9777,8 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_860_32.  */
     case EM_960:
       return reloc_type == 2; /* R_960_32.  */
+    case EM_AARCH64:
+      return reloc_type == 258; /* R_AARCH64_ABS32 */
     case EM_ALPHA:
       return reloc_type == 1; /* R_ALPHA_REFLONG.  */
     case EM_ARC:
@@ -9924,6 +9933,8 @@ is_32bit_pcrel_reloc (unsigned int reloc_type)
       return reloc_type == 2;  /* R_386_PC32.  */
     case EM_68K:
       return reloc_type == 4;  /* R_68K_PC32.  */
+    case EM_AARCH64:
+      return reloc_type == 261; /* R_AARCH64_PREL32 */
     case EM_ADAPTEVA_EPIPHANY:
       return reloc_type == 6;
     case EM_ALPHA:
@@ -9978,6 +9989,8 @@ is_64bit_abs_reloc (unsigned int reloc_type)
 {
   switch (elf_header.e_machine)
     {
+    case EM_AARCH64:
+      return reloc_type == 257;	/* R_AARCH64_ABS64.  */
     case EM_ALPHA:
       return reloc_type == 2; /* R_ALPHA_REFQUAD.  */
     case EM_IA_64:
@@ -10014,6 +10027,8 @@ is_64bit_pcrel_reloc (unsigned int reloc_type)
 {
   switch (elf_header.e_machine)
     {
+    case EM_AARCH64:
+      return reloc_type == 260;	/* R_AARCH64_PREL64.  */
     case EM_ALPHA:
       return reloc_type == 11; /* R_ALPHA_SREL64.  */
     case EM_IA_64:
@@ -10143,6 +10158,8 @@ is_none_reloc (unsigned int reloc_type)
     case EM_XC16X:
     case EM_C166:    /* R_XC16X_NONE.  */
       return reloc_type == 0;
+    case EM_AARCH64:
+      return reloc_type == 0 || reloc_type == 256;
     case EM_XTENSA_OLD:
     case EM_XTENSA:
       return (reloc_type == 0      /* R_XTENSA_NONE.  */
diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp
index 267bcbd..14d1860 100644
--- a/binutils/testsuite/binutils-all/objdump.exp
+++ b/binutils/testsuite/binutils-all/objdump.exp
@@ -36,7 +36,7 @@ send_user "Version [binutil_version $OBJDUMP]"
 set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"]
 
 set cpus_expected [list]
-lappend cpus_expected alpha arc arm cris
+lappend cpus_expected aarch64 alpha arc arm cris
 lappend cpus_expected d10v d30v fr30 fr500 fr550 h8 hppa i386 i860 i960 ip2022
 lappend cpus_expected m16c m32c m32r m68hc11 m68hc12 m68k m88k MCore MicroBlaze
 lappend cpus_expected mips mn10200 mn10300 ms1 msp ns32k pj powerpc pyramid

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes
  2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes Yufeng Zhang
@ 2012-07-30 15:02   ` Joseph S. Myers
  2012-07-31 18:23   ` nick clifton
  2012-08-07 17:29   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes v2 Yufeng Zhang
  2 siblings, 0 replies; 41+ messages in thread
From: Joseph S. Myers @ 2012-07-30 15:02 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

See <http://sourceware.org/ml/binutils/2010-11/msg00397.html> for details 
of the preferred way to document target assembler command-line options.  
You may not have many options now but using the approach that avoids 
duplicated text is still a good idea.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes
  2012-07-30 15:00 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes Yufeng Zhang
@ 2012-07-30 15:08   ` Joseph S. Myers
  2012-08-07 17:34     ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2 Yufeng Zhang
  0 siblings, 1 reply; 41+ messages in thread
From: Joseph S. Myers @ 2012-07-30 15:08 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

On Mon, 30 Jul 2012, Yufeng Zhang wrote:

> +aarch64*-*-linux*)
> +  MULTIARCHTUPLE=aarch64-linux-gnu
> +  NATIVE_LIB_DIRS="/usr/local/lib/$MULTIARCHTUPLE /lib/$MULTIARCHTUPLE /usr/lib/$MULTIARCHTUPLE"
> +  ;;

As I said for the GCC port, it's inappropriate for this sort of thing to 
be present unconditionally for one architecture.  Someone needs to submit 
generic binutils support for this Debian scheme, *conditional on an 
appropriate configure option*, and *after that* this port can have the 
appropriate settings to support the scheme *conditionally*.

I note you have some changes of the form:

>  # No shared lib support on this target.
> -if { [istarget "mcore-*-*"] } {
> +if { [istarget "mcore-*-*"] || [istarget "aarch64-*-*"] } {

Is it really the case that there is no shared library support for this 
port?  If not, the comments need updating.  In general, please explain, 
for each test being disabled for this target, why it is correct to disable 
it.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes
  2012-07-30 15:02 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes Yufeng Zhang
@ 2012-07-30 15:17   ` Joseph S. Myers
  2012-08-07 17:30     ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes v2 Yufeng Zhang
  0 siblings, 1 reply; 41+ messages in thread
From: Joseph S. Myers @ 2012-07-30 15:17 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

On Mon, 30 Jul 2012, Yufeng Zhang wrote:

> This patch adds the binutils changes of the AArch64 target support.

Are you sure this is adding full support to readelf?  You appear to have 
some architecture-specific PT_*, SHT_* and SHF_* values in elf/aarch64.h, 
so readelf should know how to display those - and in general such support 
is conditioned on the architecture, so even if the names and values are 
the same as for ARM, I'd expect you to need conditionals to enable the 
decoding for AArch64 as well as for ARM.  (In general I'd advise going 
through the ELF ABI and making sure that all such architecture-specific 
values from the ABI are (a) present in elf/aarch64.h and (b) properly 
displayed by readelf.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6]
  2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Joseph S. Myers
@ 2012-07-31 16:37   ` Yufeng Zhang
  0 siblings, 0 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-07-31 16:37 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Richard Earnshaw, binutils

On 07/30/12 15:54, Joseph S. Myers wrote:
> On Mon, 30 Jul 2012, Richard Earnshaw wrote:
>
>> ARM is pleased to announce a port of binutils, gas and ld to its
>> AArch64 architecture.
>
> Could you confirm the target triplets for which you have run the binutils,
> gas and ld testsuites for this port, and confirm that you have 100% clean
> test results for them (except for any failures you specifically identify
> in patch submissions), tested on both 32-bit and 64-bit hosts (since it's
> quite common for some assembler issues not to appear on both 32-bit and
> 64-bit)?

The following target triplets have been fully tested:

aarch64-none-elf
aarch64_be-none-elf
aarch64-none-linux-gnu

We have clean test results apart from one issue in the LD test 'Indirect 
symbol tests', which we are still investigating.

The testing had been done on 64-bit hosts. I'm currently running the 
testsuites on 32-bit hosts and working on fixing a few minor issues that 
have been found. I'll make sure the next patch set is fully tested on 
both 32-bit and 64-bit hosts.

Many thanks for your valuable feedback. I'll respond to your other 
comments soon; in the meantime if you have any other feedback, please do 
not hesitate to let me know.


Kind regards,
Yufeng

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes
  2012-07-30 14:47 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes Yufeng Zhang
@ 2012-07-31 18:22   ` nick clifton
  2012-07-31 19:27     ` Yufeng Zhang
  2012-08-07 17:18   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes v2 Yufeng Zhang
  1 sibling, 1 reply; 41+ messages in thread
From: nick clifton @ 2012-07-31 18:22 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

Hi Yufeng Zhang,
I had some problems with the opcodes part of this port.  Specifically:

   * A toolchain configured with --enable-targets=all 
--enable-64-bit-bfd would not build because aarch64-asm-2.c, 
aarch64-dis-2.c and aarch64-opc-2.c are not built.  I would suggest 
adding them to TARGET_LIBOPCODES_CFILES in opcodes/Makefile.am.

   * aarch64-opc.c does not build on a 32-bit host because you have 
mismatching types in a couple of the printf() statements.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes
  2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes Yufeng Zhang
  2012-07-30 15:02   ` Joseph S. Myers
@ 2012-07-31 18:23   ` nick clifton
  2012-08-07 17:29   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes v2 Yufeng Zhang
  2 siblings, 0 replies; 41+ messages in thread
From: nick clifton @ 2012-07-31 18:23 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

Hi Yufeng Zhang,

   I was not very happy with the code in tc-aarch64.c.  Specifically 
there are lots of places where functions return an integer when really 
they are returning a boolean true/false or pass/fail result.  It would 
be far more appropriate for these functions to use bfd_boolean as their 
return type.

   Even more confusing, there are some functions that return 0 to 
indicate success and 1 to indicate failure, but their name implies that 
the result would be the other way around.  For example I would expect 
code like this:

   if (my_get_expression (&inst.reloc.exp, &p, GE_OPT_PREFIX, 1))
     return FAIL;

to actually be coded like this:

   if (! my_get_expression (&inst.reloc.exp, &p, GE_OPT_PREFIX, 1))
     return FAIL;

so that is reads as "if my_get_expression failed then return FAIL".


Ideally I would very much like to see this port included in the new 2.23 
branch, so if you do not have the time to correct this behaviour then I 
will understand.  But if you *do* have the time, I would appreciate the 
effort.

Cheers
   Nick



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes
  2012-07-30 14:51 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes Yufeng Zhang
  2012-07-30 14:57   ` Joseph S. Myers
@ 2012-07-31 18:29   ` nick clifton
  2012-08-01  9:14     ` Yufeng Zhang
  2012-08-02 21:35   ` DJ Delorie
  2012-08-07 17:19   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes v2 Yufeng Zhang
  3 siblings, 1 reply; 41+ messages in thread
From: nick clifton @ 2012-07-31 18:29 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

Hi Yufeng Zhang,

   I could not build elf64-aarch.c with the current mainline binutils 
sources because the call to _bfd_dwarf2_find_nearest_line is missing a 
parameter.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes
  2012-07-31 18:22   ` nick clifton
@ 2012-07-31 19:27     ` Yufeng Zhang
  0 siblings, 0 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-07-31 19:27 UTC (permalink / raw)
  To: nick clifton; +Cc: binutils

Hi Nick,

On 07/31/12 16:45, nick clifton wrote:
> Hi Yufeng Zhang,
> I had some problems with the opcodes part of this port.  Specifically:
>
>     * A toolchain configured with --enable-targets=all
> --enable-64-bit-bfd would not build because aarch64-asm-2.c,
> aarch64-dis-2.c and aarch64-opc-2.c are not built.  I would suggest
> adding them to TARGET_LIBOPCODES_CFILES in opcodes/Makefile.am.

Many thanks for your feedback. I'll get the fix included in next updated 
patch set.

>     * aarch64-opc.c does not build on a 32-bit host because you have
> mismatching types in a couple of the printf() statements.

I also noticed this problem along with a few other issues when testing 
on the 32-bit hosts these two days. I'm working on fixing them all and 
will send the updated patch set soon.


Thanks,
Yufeng

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes
  2012-07-31 18:29   ` nick clifton
@ 2012-08-01  9:14     ` Yufeng Zhang
  0 siblings, 0 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-01  9:14 UTC (permalink / raw)
  To: nick clifton; +Cc: binutils

Hi Nick,

On 07/31/12 16:46, nick clifton wrote:
> Hi Yufeng Zhang,
>
>     I could not build elf64-aarch.c with the current mainline binutils
> sources because the call to _bfd_dwarf2_find_nearest_line is missing a
> parameter.

The patch set is based on this revision:
http://sourceware.org/ml/binutils-cvs/2012-07/msg00080.html

The later change in
http://sourceware.org/ml/binutils-cvs/2012-07/msg00089.html
added a new argument to _bfd_dwarf2_find_nearest_line and a few other 
functions.

I'll re-base the next updated patch set on the head of the mainline
binutils.


Thanks,
Yufeng

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes
  2012-07-30 14:49   ` Joseph S. Myers
@ 2012-08-01 14:59     ` Yufeng Zhang
  0 siblings, 0 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-01 14:59 UTC (permalink / raw)
  To: binutils

On 07/30/12 15:49, Joseph S. Myers wrote:
> On Mon, 30 Jul 2012, Yufeng Zhang wrote:
>
>> diff --git a/configure.ac b/configure.ac
>> index 5efb4a3..83ea5bc 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -842,6 +842,17 @@ case "${target}" in
>>       ;;
>>     *-*-vxworks*)
>>       ;;
>> +  aarch64*-*-elf* )
>> +    noconfigdirs="$noconfigdirs target-libffi target-qthreads"
>> +    libgloss_dir=aarch64
>> +    ;;
>> +  aarch64*-*-linux* )
>> +    noconfigdirs="$noconfigdirs target-libffi target-qthreads"
>> +    case ${with_newlib} in
>> +      no) noconfigdirs="$noconfigdirs target-newlib target-libgloss"
>> +    esac
>> +    libgloss_dir=aarch64
>> +    ;;
>
> This appears to be modifying the miscellaneous section of configure.ac,
> not taking account of the various cleanups I did a while back.
>
> Java is disabled in the "# Disable Java if libffi is not supported."
> section, using a whitelist of targets supported by libffi, so you don't
> need to disable it here.  I removed all references to target-qthreads on
> 2011-04-06 so you shouldn't need to handle that either.  newlib is
> disabled by default for *-*-linux* under "# Disable newlib and libgloss
> for various target OSes."; if you have a newlib port for
> aarch64*-*-linux*, then at the time you submit that port you can add
> special code like that for i[[3456789]]86-*-linux* to control whether
> newlib may be built for that target.  Finally, libgloss_dir should be set
> in the cases below "# Default libgloss CPU subdirectory.", based on the
> architecture not the OS.
>
> Thus, to the extent that this patch does things that are still relevant
> after my cleanups, (a) those things need to go in more logical places in
> configure.ac and (b) those things relate to newlib/libgloss and so would
> better be submitted with the newlib/libgloss port, to the newlib list,
> rather than as part of a binutils port to the binutils list.

Many thanks for your detailed suggestion.  The configure.ac now no 
longer needs any modification for the AArch64 port support, and I'll 
submit newlib/libgloss port related change to the newlib list.


Thanks,
Yufeng

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes
  2012-07-30 14:51 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes Yufeng Zhang
  2012-07-30 14:57   ` Joseph S. Myers
  2012-07-31 18:29   ` nick clifton
@ 2012-08-02 21:35   ` DJ Delorie
  2012-08-03 14:51     ` Yufeng Zhang
  2012-08-07 17:19   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes v2 Yufeng Zhang
  3 siblings, 1 reply; 41+ messages in thread
From: DJ Delorie @ 2012-08-02 21:35 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils


> +  if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
> +				     section, symbols, offset,
> +				     filename_ptr, functionname_ptr,
> +				     line_ptr, 0,
> +				     &elf_tdata
> +				     (abfd)->dwarf2_find_line_info))

_bfd_dwarf2_find_nearest_line has more parameters than that.

Please don't put the function name and opening paren on different
lines, it's confusing (personal preference).  Yes, I know it's a long
line, but it *looks* like there's a comma missing.

Also, there were a lot of "errors" from -Werror, I had to disable that
to do a test build.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes
  2012-08-02 21:35   ` DJ Delorie
@ 2012-08-03 14:51     ` Yufeng Zhang
  2012-08-04  8:06       ` DJ Delorie
  0 siblings, 1 reply; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-03 14:51 UTC (permalink / raw)
  To: DJ Delorie; +Cc: binutils

On 08/02/12 22:02, DJ Delorie wrote:
>
>> +  if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
>> +				     section, symbols, offset,
>> +				     filename_ptr, functionname_ptr,
>> +				     line_ptr, 0,
>> +				&elf_tdata
>> +				     (abfd)->dwarf2_find_line_info))
>
> _bfd_dwarf2_find_nearest_line has more parameters than that.

Thanks for your review.

The initial patch was prepared before the upstream change in which an 
extra parameter was added to _bfd_dwarf2_find_nearest_line and a few 
other functions.  We will resolve this and rebase the next updated patch 
set on the head of the binutils branch.

> Please don't put the function name and opening paren on different
> lines, it's confusing (personal preference).  Yes, I know it's a long
> line, but it *looks* like there's a comma missing.

Will fix it.

> Also, there were a lot of "errors" from -Werror, I had to disable that
> to do a test build.

Um, I don't see any error in my local environment with -Werror on. What 
kind of error message are you getting?


Thanks,
Yufeng

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes
  2012-08-03 14:51     ` Yufeng Zhang
@ 2012-08-04  8:06       ` DJ Delorie
  2012-08-07 17:53         ` Yufeng Zhang
  0 siblings, 1 reply; 41+ messages in thread
From: DJ Delorie @ 2012-08-04  8:06 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils


> Um, I don't see any error in my local environment with -Werror on. What 
> kind of error message are you getting?

../../binutils-src/opcodes/aarch64-dis.c:2146: error: format '%08lx' expects type 'long unsigned int', but argument 3 has type 'uint32_t'

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes v2
  2012-07-30 14:47 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes Yufeng Zhang
  2012-07-31 18:22   ` nick clifton
@ 2012-08-07 17:18   ` Yufeng Zhang
  2012-08-13 14:56     ` nick clifton
  1 sibling, 1 reply; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-07 17:18 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 3013 bytes --]

Hi,

Please find the updated patch that adds the opcodes changes of the 
AArch64 target.

The patch fixes a makefile issue as well as a few other issues found 
during the building of the opcodes on 32-bit host; some of the problems 
were mentioned in http://sourceware.org/ml/binutils/2012-07/msg00320.html


Thanks,
Yufeng


Updated change log:

include/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
             Laurent Desnogues  <laurent.desnogues@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * dis-asm.h (print_insn_aarch64): New declaration.
         (print_aarch64_disassembler_options): New declaration.
         (aarch64_symbol_is_valid): New declaration.


include/opcode/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
             Laurent Desnogues  <laurent.desnogues@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * aarch64.h: New file.


opcodes/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
             Laurent Desnogues  <laurent.desnogues@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * Makefile.am: Add AArch64.
         * Makefile.in: Regenerate.
         * aarch64-asm.c: New file.
         * aarch64-asm.h: New file.
         * aarch64-dis.c: New file.
         * aarch64-dis.h: New file.
         * aarch64-gen.c: New file.
         * aarch64-opc.c: New file.
         * aarch64-opc.h: New file.
         * aarch64-tbl.h: New file.
         * configure.in: Add AArch64.
         * configure: Regenerate.
         * disassemble.c: Add AArch64.
         * aarch64-asm-2.c: New file (automatically generated).
         * aarch64-dis-2.c: New file (automatically generated).
         * aarch64-opc-2.c: New file (automatically generated).
         * po/POTFILES.in: Regenerate.

[-- Attachment #2: aarch64-opcodes.v2.patch.bz2 --]
[-- Type: application/x-bzip, Size: 77227 bytes --]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes v2
  2012-07-30 14:51 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes Yufeng Zhang
                     ` (2 preceding siblings ...)
  2012-08-02 21:35   ` DJ Delorie
@ 2012-08-07 17:19   ` Yufeng Zhang
  2012-08-08 12:18     ` Benedikt Schroefel
  2012-08-13 14:57     ` nick clifton
  3 siblings, 2 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-07 17:19 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 3312 bytes --]

Hi,

Please find the updated patch that adds the bfd changes of the AArch64 
target support.

The patch fixes

* the empty initializer issue as mentioned in
http://sourceware.org/ml/binutils/2012-07/msg00277.html

* the missing parameter issue as mentioned in
http://sourceware.org/ml/binutils/2012-07/msg00322.html


Thanks,
Yufeng


include/elf/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
             Laurent Desnogues  <laurent.desnogues@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * aarch64.h: New file.
         * common.h (EM_res183): Rename to EM_AARCH64.
         (EM_res184): Rename to EM_ARM184.


bfd/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
             Laurent Desnogues  <laurent.desnogues@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * Makefile.am: Add AArch64 files.
         * Makefile.in: Regenerate.
         * archures.c (bfd_aarch64_arch): New declaration.
         (bfd_archures_list): Use bfd_archures_list.
         * bfd-in.h (bfd_elf64_aarch64_init_maps): New declaration.
         (bfd_aarch64_process_before_allocation): New declaration.
         (bfd_elf64_aarch64_process_before_allocation): New declaration.
         (bfd_elf64_aarch64_set_options): New declaration.
         (bfd_elf64_aarch64_add_glue_sections_to_bfd): New declaration.
         (BFD_AARCH64_SPECIAL_SYM_TYPE_MAP): New definition.
         (BFD_AARCH64_SPECIAL_SYM_TYPE_TAG): New definition.
         (BFD_AARCH64_SPECIAL_SYM_TYPE_OTHER): New definition.
         (BFD_AARCH64_SPECIAL_SYM_TYPE_ANY): New definition.
         (bfd_is_aarch64_special_symbol_name): New declaration.
         (bfd_aarch64_merge_machines): New declaration.
         (bfd_aarch64_update_notes): New declaration.
         (int bfd_aarch64_get_mach_from_notes): New declaration.
         (elf64_aarch64_setup_section_lists): New declaration.
         (elf64_aarch64_next_input_section): New declaration.
         (elf64_aarch64_size_stubs): New declaration.
         (elf64_aarch64_build_stubs): New declaration.
         * config.bfd: Add AArch64.
         * configure.in: Add AArch64.
         * configure: Regenerate.
         * cpu-aarch64.c: New file.
         * elf-bfd.h: Add AArch64.
         * bfd-in2.h: Regenerate.
         * libbfd.h: Regenerate.
         * elf64-aarch64.c: New file.
         * reloc.c: Add AArch64 relocations.
         * targets.c: Add AArch64.
         * po/SRC-POTFILES.in: Regenerate.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: aarch64-bfd.v2.patch --]
[-- Type: text/x-patch; name=aarch64-bfd.v2.patch, Size: 252107 bytes --]

diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h
new file mode 100644
index 0000000..04730b1
--- /dev/null
+++ b/include/elf/aarch64.h
@@ -0,0 +1,214 @@
+/* AArch64 ELF support for BFD.
+
+   Copyright 2009, 2010, 2011, 2012  Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of GNU Binutils.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the license, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING3. If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ELF_AARCH64_H
+#define _ELF_AARCH64_H
+
+#include "elf/reloc-macros.h"
+
+/* Processor specific program header types.  */
+#define PT_AARCH64_ARCHEXT	(PT_LOPROC + 0)
+
+/* Additional section types.  */
+#define SHT_AARCH64_ATTRIBUTES	0x70000003  /* Section holds attributes.  */
+
+/* AArch64-specific values for sh_flags.  */
+#define SHF_ENTRYSECT		0x10000000   /* Section contains an
+						entry point.  */
+#define SHF_COMDEF		0x80000000   /* Section may be multiply defined
+						in the input to a link step.  */
+
+/* Relocation types.  */
+
+START_RELOC_NUMBERS (elf_aarch64_reloc_type)
+
+/* Null relocations. */
+RELOC_NUMBER (R_AARCH64_NONE, 0) /* No reloc */
+
+FAKE_RELOC (R_AARCH64_static_min, 256)
+
+RELOC_NUMBER (R_AARCH64_NULL, 256) /* No reloc */
+
+/* Basic data relocations. */
+
+/* .xword: (S+A) */
+RELOC_NUMBER (R_AARCH64_ABS64, 257)
+
+/* .word:  (S+A) */
+RELOC_NUMBER (R_AARCH64_ABS32, 258)
+
+/* .half: (S+A) */
+RELOC_NUMBER (R_AARCH64_ABS16, 259)
+
+/* .xword: (S+A-P) */
+RELOC_NUMBER (R_AARCH64_PREL64, 260)
+
+/* .word: (S+A-P) */
+RELOC_NUMBER (R_AARCH64_PREL32, 261)
+
+/* .half:  (S+A-P) */
+RELOC_NUMBER (R_AARCH64_PREL16, 262)
+
+/* Group relocations to create a 16, 32, 48 or 64 bit
+   unsigned data or abs address inline. */
+
+/* MOV[ZK]:   ((S+A) >>  0) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G0,		263)
+
+/* MOV[ZK]:   ((S+A) >>  0) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G0_NC, 264)
+
+/* MOV[ZK]:   ((S+A) >> 16) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G1, 265)
+
+/* MOV[ZK]:   ((S+A) >> 16) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G1_NC, 266)
+
+/* MOV[ZK]:   ((S+A) >> 32) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G2, 267)
+
+/* MOV[ZK]:   ((S+A) >> 32) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G2_NC, 268)
+
+/* MOV[ZK]:   ((S+A) >> 48) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_UABS_G3, 269)
+
+/* Group relocations to create high part of a 16, 32, 48 or 64 bit
+   signed data or abs address inline. Will change instruction
+   to MOVN or MOVZ depending on sign of calculated value. */
+
+/* MOV[ZN]:   ((S+A) >>  0) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_SABS_G0, 270)
+
+/* MOV[ZN]:   ((S+A) >> 16) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_SABS_G1, 271)
+
+/* MOV[ZN]:   ((S+A) >> 32) & 0xffff */
+RELOC_NUMBER (R_AARCH64_MOVW_SABS_G2, 272)
+
+/* Relocations to generate 19, 21 and 33 bit PC-relative load/store
+   addresses: PG(x) is (x & ~0xfff). */
+
+/* LD-lit: ((S+A-P) >> 2) & 0x7ffff */
+RELOC_NUMBER (R_AARCH64_LD_PREL_LO19, 273)
+
+/* ADR:    (S+A-P) & 0x1fffff */
+RELOC_NUMBER (R_AARCH64_ADR_PREL_LO21, 274)
+
+/* ADRH:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+RELOC_NUMBER (R_AARCH64_ADR_PREL_PG_HI21, 275)
+
+/* ADRH:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+RELOC_NUMBER (R_AARCH64_ADR_PREL_PG_HI21_NC, 276)
+
+/* ADD:    (S+A) & 0xfff */
+RELOC_NUMBER (R_AARCH64_ADD_ABS_LO12_NC, 277)
+
+/* LD/ST8: (S+A) & 0xfff */
+RELOC_NUMBER (R_AARCH64_LDST8_ABS_LO12_NC, 278)
+
+/* Relocations for control-flow instructions. */
+
+/* TBZ/NZ: ((S+A-P) >> 2) & 0x3fff */
+RELOC_NUMBER (R_AARCH64_TSTBR14, 279)
+
+/* B.cond: ((S+A-P) >> 2) & 0x7ffff */
+RELOC_NUMBER (R_AARCH64_CONDBR19, 280)
+
+/* 281 unused */
+
+/* B:      ((S+A-P) >> 2) & 0x3ffffff */
+RELOC_NUMBER (R_AARCH64_JUMP26, 282)
+
+/* BL:     ((S+A-P) >> 2) & 0x3ffffff */
+RELOC_NUMBER (R_AARCH64_CALL26, 283)
+
+/* LD/ST16: (S+A) & 0xffe */
+RELOC_NUMBER (R_AARCH64_LDST16_ABS_LO12_NC, 284)
+
+/* LD/ST32: (S+A) & 0xffc */
+RELOC_NUMBER (R_AARCH64_LDST32_ABS_LO12_NC, 285)
+
+/* LD/ST64: (S+A) & 0xff8 */
+RELOC_NUMBER (R_AARCH64_LDST64_ABS_LO12_NC, 286)
+
+/* LD/ST128: (S+A) & 0xff0 */
+RELOC_NUMBER (R_AARCH64_LDST128_ABS_LO12_NC, 299)
+
+RELOC_NUMBER (R_AARCH64_ADR_GOT_PAGE, 311)
+RELOC_NUMBER (R_AARCH64_LD64_GOT_LO12_NC, 312)
+
+FAKE_RELOC (R_AARCH64_static_max, 313)
+
+FAKE_RELOC (R_AARCH64_tls_min, 512)
+RELOC_NUMBER (R_AARCH64_TLSGD_ADR_PAGE21, 513)
+RELOC_NUMBER (R_AARCH64_TLSGD_ADD_LO12_NC, 514)
+RELOC_NUMBER (R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 539)
+RELOC_NUMBER (R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 540)
+RELOC_NUMBER (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 541)
+RELOC_NUMBER (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 542)
+RELOC_NUMBER (R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 543)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G2, 544)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G1, 545)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 546)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G0, 547)
+RELOC_NUMBER (R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 548)
+RELOC_NUMBER (R_AARCH64_TLSLE_ADD_TPREL_HI12, 549)
+RELOC_NUMBER (R_AARCH64_TLSLE_ADD_TPREL_LO12, 550)
+RELOC_NUMBER (R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 551)
+FAKE_RELOC (R_AARCH64_tls_max, 552)
+
+FAKE_RELOC (R_AARCH64_tlsdesc_min, 560)
+RELOC_NUMBER (R_AARCH64_TLSDESC_LD64_PREL19, 560)
+RELOC_NUMBER (R_AARCH64_TLSDESC_ADR_PREL21, 561)
+RELOC_NUMBER (R_AARCH64_TLSDESC_ADR_PAGE, 562)
+RELOC_NUMBER (R_AARCH64_TLSDESC_LD64_LO12_NC, 563)
+RELOC_NUMBER (R_AARCH64_TLSDESC_ADD_LO12_NC, 564)
+RELOC_NUMBER (R_AARCH64_TLSDESC_OFF_G1, 565)
+RELOC_NUMBER (R_AARCH64_TLSDESC_OFF_G0_NC, 566)
+RELOC_NUMBER (R_AARCH64_TLSDESC_LDR, 567)
+RELOC_NUMBER (R_AARCH64_TLSDESC_ADD, 568)
+RELOC_NUMBER (R_AARCH64_TLSDESC_CALL, 569)
+FAKE_RELOC (R_AARCH64_tlsdesc_max, 570)
+
+/* Dynamic relocations */
+FAKE_RELOC (R_AARCH64_dyn_min, 1024)
+
+/* Copy symbol at runtime.  */
+RELOC_NUMBER (R_AARCH64_COPY, 1024)
+
+/* Create GOT entry.  */
+RELOC_NUMBER (R_AARCH64_GLOB_DAT, 1025)
+
+ /* Create PLT entry.  */
+RELOC_NUMBER (R_AARCH64_JUMP_SLOT, 1026)
+
+/* Adjust by program base.  */
+RELOC_NUMBER (R_AARCH64_RELATIVE, 1027)
+RELOC_NUMBER (R_AARCH64_TLS_DTPMOD64, 1028)
+RELOC_NUMBER (R_AARCH64_TLS_DTPREL64, 1029)
+RELOC_NUMBER (R_AARCH64_TLS_TPREL64, 1030)
+RELOC_NUMBER (R_AARCH64_TLSDESC, 1031)
+FAKE_RELOC (R_AARCH64_dyn_max, 1032)
+
+END_RELOC_NUMBERS (R_AARCH64_end)
+
+#endif /* _ELF_AARCH64_H */
diff --git a/include/elf/common.h b/include/elf/common.h
index 58e489a..1c681d5 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -287,8 +287,8 @@
 #define EM_L1OM		180	/* Intel L1OM */
 #define EM_K1OM		181	/* Intel K1OM */
 #define EM_INTEL182	182	/* Reserved by Intel */
-#define EM_res183	183	/* Reserved by ARM */
-#define EM_res184	184	/* Reserved by ARM */
+#define EM_AARCH64	183	/* ARM 64-bit architecture */
+#define EM_ARM184	184	/* Reserved by ARM */
 #define EM_AVR32	185	/* Atmel Corporation 32-bit microprocessor family */
 #define EM_STM8	186	/* STMicroeletronics STM8 8-bit microcontroller */
 #define EM_TILE64	187	/* Tilera TILE64 multicore architecture family */
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index b7271cc..49f9662 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -71,6 +71,7 @@ BFD64_LIBS_CFILES = archive64.c
 # This list is alphabetized to make it easier to keep in sync
 # with the decls and initializer in archures.c.
 ALL_MACHINES = \
+	cpu-aarch64.lo \
 	cpu-alpha.lo \
 	cpu-arc.lo \
 	cpu-arm.lo \
@@ -151,6 +152,7 @@ ALL_MACHINES = \
 	cpu-z8k.lo
 
 ALL_MACHINES_CFILES = \
+	cpu-aarch64.c \
 	cpu-alpha.c \
 	cpu-arc.c \
 	cpu-arm.c \
@@ -613,6 +615,7 @@ BFD32_BACKENDS_CFILES = \
 # elf32-ia64.c requires a 64-bit bfd_vma, and hence can not be put in
 # BFD32_BACKENDS.
 BFD64_BACKENDS = \
+	elf64-aarch64.lo \
 	aix5ppc-core.lo \
 	aout64.lo \
 	coff-alpha.lo \
@@ -651,6 +654,7 @@ BFD64_BACKENDS = \
 	vms-alpha.lo
 
 BFD64_BACKENDS_CFILES = \
+	elf64-aarch64.c \
 	aix5ppc-core.c \
 	aout64.c \
 	coff-alpha.c \
diff --git a/bfd/archures.c b/bfd/archures.c
index a23534b..3198436 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -461,6 +461,8 @@ DESCRIPTION
 .#define bfd_mach_tilepro   1
 .#define bfd_mach_tilegx    1
 .#define bfd_mach_tilegx32  2
+.  bfd_arch_aarch64,   {* AArch64  *}
+.#define bfd_mach_aarch64 0
 .  bfd_arch_last
 .  };
 */
@@ -505,6 +507,7 @@ DESCRIPTION
 .
 */
 
+extern const bfd_arch_info_type bfd_aarch64_arch;
 extern const bfd_arch_info_type bfd_alpha_arch;
 extern const bfd_arch_info_type bfd_arc_arch;
 extern const bfd_arch_info_type bfd_arm_arch;
@@ -590,6 +593,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
 #ifdef SELECT_ARCHITECTURES
     SELECT_ARCHITECTURES,
 #else
+    &bfd_aarch64_arch,
     &bfd_alpha_arch,
     &bfd_arc_arch,
     &bfd_arm_arch,
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 5300b14..a8c2db1 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -928,6 +928,32 @@ extern unsigned int _bfd_elf_ppc_at_tls_transform
 extern unsigned int _bfd_elf_ppc_at_tprel_transform
   (unsigned int, unsigned int);
 
+extern void bfd_elf64_aarch64_init_maps
+  (bfd *);
+
+void bfd_elf64_aarch64_set_options
+  (bfd *, struct bfd_link_info *, int, int, int);
+
+/* ELF AArch64 mapping symbol support.  */
+#define BFD_AARCH64_SPECIAL_SYM_TYPE_MAP	(1 << 0)
+#define BFD_AARCH64_SPECIAL_SYM_TYPE_TAG	(1 << 1)
+#define BFD_AARCH64_SPECIAL_SYM_TYPE_OTHER	(1 << 2)
+#define BFD_AARCH64_SPECIAL_SYM_TYPE_ANY	(~0)
+extern bfd_boolean bfd_is_aarch64_special_symbol_name
+  (const char * name, int type);
+
+/* AArch64 stub generation support.  Called from the linker.  */
+extern int elf64_aarch64_setup_section_lists
+  (bfd *, struct bfd_link_info *);
+extern void elf64_aarch64_next_input_section
+  (struct bfd_link_info *, struct bfd_section *);
+extern bfd_boolean elf64_aarch64_size_stubs
+  (bfd *, bfd *, struct bfd_link_info *, bfd_signed_vma,
+   struct bfd_section * (*) (const char *, struct bfd_section *),
+   void (*) (void));
+extern bfd_boolean elf64_aarch64_build_stubs
+  (struct bfd_link_info *);
+  
 /* TI COFF load page support.  */
 extern void bfd_ticoff_set_section_load_page
   (struct bfd_section *, int);
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 783d1f3..4b9ee4a 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -69,6 +69,7 @@ esac
 
 targ_cpu=`echo $targ | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
 case "${targ_cpu}" in
+aarch64*)	 targ_archs="bfd_aarch64_arch bfd_arm_arch";;
 alpha*)		 targ_archs=bfd_alpha_arch ;;
 am34*|am33_2.0*) targ_archs=bfd_mn10300_arch ;;
 arm*)		 targ_archs=bfd_arm_arch ;;
@@ -143,6 +144,26 @@ case "${targ}" in
 
 # START OF targmatch.h
 #ifdef BFD64
+  aarch64-*-elf)
+    targ_defvec=bfd_elf64_littleaarch64_vec
+    targ_selvecs="bfd_elf64_bigaarch64_vec bfd_elf32_littlearm_vec bfd_elf32_bigarm_vec"
+    want64=true
+    ;;
+  aarch64_be-*-elf)
+    targ_defvec=bfd_elf64_bigaarch64_vec
+    targ_selvecs="bfd_elf64_littleaarch64_vec bfd_elf32_bigarm_vec bfd_elf32_littlearm_vec"
+    want64=true
+    ;;
+  aarch64-*-linux*)
+    targ_defvec=bfd_elf64_littleaarch64_vec
+    targ_selvecs="bfd_elf64_bigaarch64_vec bfd_elf32_littlearm_vec bfd_elf32_bigarm_vec"
+    want64=true
+    ;;
+  aarch64_be-*-linux*)
+    targ_defvec=bfd_elf64_bigaarch64_vec
+    targ_selvecs="bfd_elf64_littleaarch64_vec bfd_elf32_bigarm_vec bfd_elf32_littlearm_vec"
+    want64=true
+    ;;
   alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
     targ_defvec=bfd_elf64_alpha_freebsd_vec
     targ_selvecs="bfd_elf64_alpha_vec ecoffalpha_little_vec"
diff --git a/bfd/configure.in b/bfd/configure.in
index 97fff61..3626173 100644
--- a/bfd/configure.in
+++ b/bfd/configure.in
@@ -832,6 +832,7 @@ do
     bfd_elf32_xtensa_be_vec)	tb="$tb xtensa-isa.lo xtensa-modules.lo elf32-xtensa.lo elf32.lo $elf" ;;
     bfd_elf64_alpha_freebsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_alpha_vec)	tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
+    bfd_elf64_bigaarch64_vec)	tb="$tb elf64-aarch64.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_big_generic_vec) 	tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_bigmips_vec) 	tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
     bfd_elf64_hppa_linux_vec)	tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;;
@@ -840,6 +841,7 @@ do
     bfd_elf64_ia64_hpux_big_vec) tb="$tb elf64-ia64.lo elfxx-ia64.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_ia64_little_vec)	tb="$tb elf64-ia64.lo elfxx-ia64.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_ia64_vms_vec)	tb="$tb elf64-ia64-vms.lo elf64-ia64.lo elfxx-ia64.lo elf64.lo vms-lib.lo vms-misc.lo $elf"; target_size=64 ;;    
+    bfd_elf64_littleaarch64_vec)tb="$tb elf64-aarch64.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_little_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
     bfd_elf64_littlemips_vec) 	tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
     bfd_elf64_mmix_vec) 	tb="$tb elf64-mmix.lo elf64.lo $elf" target_size=64 ;;
diff --git a/bfd/cpu-aarch64.c b/bfd/cpu-aarch64.c
new file mode 100644
index 0000000..8162037
--- /dev/null
+++ b/bfd/cpu-aarch64.c
@@ -0,0 +1,121 @@
+/* BFD support for AArch64.
+   Copyright 2009, 2010, 2011, 2012  Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING3. If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "libiberty.h"
+
+/* This routine is provided two arch_infos and works out which Aarch64
+   machine which would be compatible with both and returns a pointer
+   to its info structure.  */
+
+static const bfd_arch_info_type *
+compatible (const bfd_arch_info_type * a, const bfd_arch_info_type * b)
+{
+  /* If a & b are for different architecture we can do nothing.  */
+  if (a->arch != b->arch)
+    return NULL;
+
+  /* If a & b are for the same machine then all is well.  */
+  if (a->mach == b->mach)
+    return a;
+
+  /* Otherwise if either a or b is the 'default' machine
+     then it can be polymorphed into the other.  */
+  if (a->the_default)
+    return b;
+
+  if (b->the_default)
+    return a;
+
+  /* So far all newer cores are
+     supersets of previous cores.  */
+  if (a->mach < b->mach)
+    return b;
+  else if (a->mach > b->mach)
+    return a;
+
+  /* Never reached!  */
+  return NULL;
+}
+
+static struct
+{
+  unsigned int mach;
+  char *name;
+}
+processors[] =
+{
+  /* These two are example CPUs supported in GCC, once we have real
+     CPUs they will be removed.  */
+  { bfd_mach_aarch64, "example-1" },
+  { bfd_mach_aarch64, "example-2" }
+};
+
+static bfd_boolean
+scan (const struct bfd_arch_info *info, const char *string)
+{
+  int i;
+
+  /* First test for an exact match.  */
+  if (strcasecmp (string, info->printable_name) == 0)
+    return TRUE;
+
+  /* Next check for a processor name instead of an Architecture name.  */
+  for (i = sizeof (processors) / sizeof (processors[0]); i--;)
+    {
+      if (strcasecmp (string, processors[i].name) == 0)
+	break;
+    }
+
+  if (i != -1 && info->mach == processors[i].mach)
+    return TRUE;
+
+  /* Finally check for the default architecture.  */
+  if (strcasecmp (string, "aarch64") == 0)
+    return info->the_default;
+
+  return FALSE;
+}
+
+#define N(NUMBER, PRINT, DEFAULT, NEXT)				\
+  { 64, 64, 8, bfd_arch_aarch64, NUMBER,			\
+    "aarch64", PRINT, 4, DEFAULT, compatible, scan,		\
+    bfd_arch_default_fill, NEXT }
+
+const bfd_arch_info_type bfd_aarch64_arch =
+  N (0, "aarch64", TRUE, NULL);
+
+
+bfd_boolean
+bfd_is_aarch64_special_symbol_name (const char *name, int type)
+{
+  if (!name || name[0] != '$')
+    return FALSE;
+  if (name[1] == 'x' || name[1] == 'd')
+    type &= BFD_AARCH64_SPECIAL_SYM_TYPE_MAP;
+  else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
+    type &= BFD_AARCH64_SPECIAL_SYM_TYPE_TAG;
+  else
+    return FALSE;
+
+  return (type != 0 && (name[2] == 0 || name[2] == '.'));
+}
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index ff0e615..6a44912 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -402,7 +402,8 @@ struct eh_frame_hdr_info
    one line.  */
 enum elf_target_id
 {
-  ALPHA_ELF_DATA = 1,
+  AARCH64_ELF_DATA = 1,
+  ALPHA_ELF_DATA,
   ARM_ELF_DATA,
   AVR_ELF_DATA,
   BFIN_ELF_DATA,
diff --git a/bfd/elf64-aarch64.c b/bfd/elf64-aarch64.c
new file mode 100644
index 0000000..9a74b2d
--- /dev/null
+++ b/bfd/elf64-aarch64.c
@@ -0,0 +1,7009 @@
+/* ELF support for AArch64.
+   Copyright 2009, 2010, 2011, 2012  Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING3. If not,
+   see <http://www.gnu.org/licenses/>.  */
+
+/* Notes on implementation:
+
+  Thread Local Store (TLS)
+
+  Overview:
+
+  The implementation currently supports both traditional TLS and TLS
+  descriptors, but only general dynamic (GD).
+
+  For traditional TLS the assembler will present us with code
+  fragments of the form:
+
+  adrp x0, :tlsgd:foo
+                           R_AARCH64_TLSGD_ADR_PAGE21(foo)
+  add  x0, :tlsgd_lo12:foo
+                           R_AARCH64_TLSGD_ADD_LO12_NC(foo)
+  bl   __tls_get_addr
+  nop
+
+  For TLS descriptors the assembler will present us with code
+  fragments of the form:
+
+  adrp  x0, :tlsdesc:foo                      R_AARCH64_TLSDESC_ADR_PAGE(foo)
+  ldr   x1, [x0, #:tlsdesc_lo12:foo]          R_AARCH64_TLSDESC_LD64_LO12(foo)
+  add   x0, x0, #:tlsdesc_lo12:foo            R_AARCH64_TLSDESC_ADD_LO12(foo)
+  .tlsdesccall foo
+  blr   x1                                    R_AARCH64_TLSDESC_CALL(foo)
+
+  The relocations R_AARCH64_TLSGD_{ADR_PREL21,ADD_LO12_NC} against foo
+  indicate that foo is thread local and should be accessed via the
+  traditional TLS mechanims.
+
+  The relocations R_AARCH64_TLSDESC_{ADR_PAGE,LD64_LO12_NC,ADD_LO12_NC}
+  against foo indicate that 'foo' is thread local and should be accessed
+  via a TLS descriptor mechanism.
+
+  The precise instruction sequence is only relevant from the
+  perspective of linker relaxation which is currently not implemented.
+
+  The static linker must detect that 'foo' is a TLS object and
+  allocate a double GOT entry. The GOT entry must be created for both
+  global and local TLS symbols. Note that this is different to none
+  TLS local objects which do not need a GOT entry.
+
+  In the traditional TLS mechanism, the double GOT entry is used to
+  provide the tls_index structure, containing module and offset
+  entries. The static linker places the relocation R_AARCH64_TLS_DTPMOD64
+  on the module entry. The loader will subsequently fixup this
+  relocation with the module identity.
+
+  For global traditional TLS symbols the static linker places an
+  R_AARCH64_TLS_DTPREL64 relocation on the offset entry. The loader
+  will subsequently fixup the offset. For local TLS symbols the static
+  linker fixes up offset.
+
+  In the TLS descriptor mechanism the double GOT entry is used to
+  provide the descriptor. The static linker places the relocation
+  R_AARCH64_TLSDESC on the first GOT slot. The loader will
+  subsequently fix this up.
+
+  Implementation:
+
+  The handling of TLS symbols is implemented across a number of
+  different backend functions. The following is a top level view of
+  what processing is performed where.
+
+  The TLS implementation maintains state information for each TLS
+  symbol. The state information for local and global symbols is kept
+  in different places. Global symbols use generic BFD structures while
+  local symbols use backend specific structures that are allocated and
+  maintained entirely by the backend.
+
+  The flow:
+
+  aarch64_check_relocs()
+
+  This function is invoked for each relocation.
+
+  The TLS relocations R_AARCH64_TLSGD_{ADR_PREL21,ADD_LO12_NC} and
+  R_AARCH64_TLSDESC_{ADR_PAGE,LD64_LO12_NC,ADD_LO12_NC} are
+  spotted. One time creation of local symbol data structures are
+  created when the first local symbol is seen.
+
+  The reference count for a symbol is incremented.  The GOT type for
+  each symbol is marked as general dynamic.
+
+  elf64_aarch64_allocate_dynrelocs ()
+
+  For each global with positive reference count we allocate a double
+  GOT slot. For a traditional TLS symbol we allocate space for two
+  relocation entries on the GOT, for a TLS descriptor symbol we
+  allocate space for one relocation on the slot. Record the GOT offset
+  for this symbol.
+
+  elf64_aarch64_size_dynamic_sections ()
+
+  Iterate all input BFDS, look for in the local symbol data structure
+  constructed earlier for local TLS symbols and allocate them double
+  GOT slots along with space for a single GOT relocation. Update the
+  local symbol structure to record the GOT offset allocated.
+
+  elf64_aarch64_relocate_section ()
+
+  Calls elf64_aarch64_final_link_relocate ()
+
+  Emit the relevant TLS relocations against the GOT for each TLS
+  symbol. For local TLS symbols emit the GOT offset directly. The GOT
+  relocations are emitted once the first time a TLS symbol is
+  encountered. The implementation uses the LSB of the GOT offset to
+  flag that the relevant GOT relocations for a symbol have been
+  emitted. All of the TLS code that uses the GOT offset needs to take
+  care to mask out this flag bit before using the offset.
+
+  elf64_aarch64_final_link_relocate ()
+
+  Fixup the R_AARCH64_TLSGD_{ADR_PREL21, ADD_LO12_NC} relocations.
+
+ */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libiberty.h"
+#include "libbfd.h"
+#include "bfd_stdint.h"
+#include "elf-bfd.h"
+#include "bfdlink.h"
+#include "elf/aarch64.h"
+
+static bfd_reloc_status_type
+bfd_elf_aarch64_put_addend (bfd *abfd,
+			    bfd_byte *address,
+			    reloc_howto_type *howto, bfd_signed_vma addend);
+
+#define IS_AARCH64_TLS_RELOC(R_TYPE)			\
+  ((R_TYPE) == R_AARCH64_TLSGD_ADR_PAGE21		\
+   || (R_TYPE) == R_AARCH64_TLSGD_ADD_LO12_NC		\
+   || (R_TYPE) == R_AARCH64_TLSIE_MOVW_GOTTPREL_G1	\
+   || (R_TYPE) == R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC	\
+   || (R_TYPE) == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21	\
+   || (R_TYPE) == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC	\
+   || (R_TYPE) == R_AARCH64_TLSIE_LD_GOTTPREL_PREL19	\
+   || (R_TYPE) == R_AARCH64_TLSLE_ADD_TPREL_LO12	\
+   || (R_TYPE) == R_AARCH64_TLSLE_ADD_TPREL_HI12	\
+   || (R_TYPE) == R_AARCH64_TLSLE_ADD_TPREL_LO12_NC	\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G2		\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G1		\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G1_NC	\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G0		\
+   || (R_TYPE) == R_AARCH64_TLSLE_MOVW_TPREL_G0_NC	\
+   || (R_TYPE) == R_AARCH64_TLS_DTPMOD64		\
+   || (R_TYPE) == R_AARCH64_TLS_DTPREL64		\
+   || (R_TYPE) == R_AARCH64_TLS_TPREL64			\
+   || IS_AARCH64_TLSDESC_RELOC ((R_TYPE)))
+
+#define IS_AARCH64_TLSDESC_RELOC(R_TYPE)		\
+  ((R_TYPE) == R_AARCH64_TLSDESC_LD64_PREL19		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_ADR_PREL21		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_ADR_PAGE		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_ADD_LO12_NC		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_LD64_LO12_NC	\
+   || (R_TYPE) == R_AARCH64_TLSDESC_OFF_G1		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_OFF_G0_NC		\
+   || (R_TYPE) == R_AARCH64_TLSDESC_LDR			\
+   || (R_TYPE) == R_AARCH64_TLSDESC_ADD			\
+   || (R_TYPE) == R_AARCH64_TLSDESC_CALL		\
+   || (R_TYPE) == R_AARCH64_TLSDESC)
+
+#define ELIMINATE_COPY_RELOCS 0
+
+/* Return the relocation section associated with NAME.  HTAB is the
+   bfd's elf64_aarch64_link_hash_entry.  */
+#define RELOC_SECTION(HTAB, NAME) \
+  ((HTAB)->use_rel ? ".rel" NAME : ".rela" NAME)
+
+/* Return size of a relocation entry.  HTAB is the bfd's
+   elf64_aarch64_link_hash_entry.  */
+#define RELOC_SIZE(HTAB) (sizeof (Elf64_External_Rela))
+
+/* Return function to swap relocations in.  HTAB is the bfd's
+   elf64_aarch64_link_hash_entry.  */
+#define SWAP_RELOC_IN(HTAB) (bfd_elf64_swap_reloca_in)
+
+/* Return function to swap relocations out.  HTAB is the bfd's
+   elf64_aarch64_link_hash_entry.  */
+#define SWAP_RELOC_OUT(HTAB) (bfd_elf64_swap_reloca_out)
+
+/* GOT Entry size - 8 bytes.  */
+#define GOT_ENTRY_SIZE                  (8)
+#define PLT_ENTRY_SIZE                  (32)
+#define PLT_SMALL_ENTRY_SIZE            (16)
+#define PLT_TLSDESC_ENTRY_SIZE          (32)
+
+/* Take the PAGE component of an address or offset. */
+#define PG(x) ((x) & ~ 0xfff)
+#define PG_OFFSET(x) ((x) & 0xfff)
+
+/* Encoding of the nop instruction */
+#define INSN_NOP 0xd503201f
+
+#define aarch64_compute_jump_table_size(htab)		\
+  (((htab)->root.srelplt == NULL) ? 0			\
+   : (htab)->root.srelplt->reloc_count * GOT_ENTRY_SIZE)
+
+/* The first entry in a procedure linkage table looks like this
+   if the distance between the PLTGOT and the PLT is < 4GB use
+   these PLT entries. Note that the dynamic linker gets &PLTGOT[2]
+   in x16 and needs to work out PLTGOT[1] by using an address of
+   [x16,#-8].  */
+static const bfd_byte elf64_aarch64_small_plt0_entry[PLT_ENTRY_SIZE] = {
+  0xf0, 0x7b, 0xbf, 0xa9,	/* stp x16, x30, [sp, #-16]!  */
+  0x10, 0x00, 0x00, 0x90,	/* adrp x16, (GOT+16)  */
+  0x11, 0x0A, 0x40, 0xf9,	/* ldr x17, [x16, #PLT_GOT+0x10]  */
+  0x10, 0x42, 0x00, 0x91,	/* add x16, x16,#PLT_GOT+0x10   */
+  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
+   if the distance between the PLTGOT and the PLT is < 4GB use
+   these PLT entries.  */
+static const bfd_byte elf64_aarch64_small_plt_entry[PLT_SMALL_ENTRY_SIZE] = {
+  0x10, 0x00, 0x00, 0x90,	/* adrp x16, PLTGOT + n * 8  */
+  0x11, 0x02, 0x40, 0xf9,	/* ldr x17, [x16, PLTGOT + n * 8] */
+  0x10, 0x02, 0x00, 0x91,	/* add x16, x16, :lo12:PLTGOT + n * 8  */
+  0x20, 0x02, 0x1f, 0xd6,	/* br x17.  */
+};
+
+static const bfd_byte
+  elf64_aarch64_tlsdesc_small_plt_entry[PLT_TLSDESC_ENTRY_SIZE] = {
+  0xe2, 0x0f, 0xbf, 0xa9,	/* stp x2, x3, [sp, #-16]! */
+  0x02, 0x00, 0x00, 0x90,	/* adrp x2, 0 */
+  0x03, 0x00, 0x00, 0x90,	/* adrp x3, 0 */
+  0x42, 0x08, 0x40, 0xF9,	/* ldr x2, [x2, #0] */
+  0x63, 0x00, 0x00, 0x91,	/* add x3, x3, 0 */
+  0x40, 0x00, 0x1F, 0xD6,	/* br x2 */
+  0x1f, 0x20, 0x03, 0xd5,	/* nop */
+  0x1f, 0x20, 0x03, 0xd5,	/* nop */
+};
+
+#define elf_info_to_howto               elf64_aarch64_info_to_howto
+#define elf_info_to_howto_rel           elf64_aarch64_info_to_howto
+
+#define AARCH64_ELF_ABI_VERSION		0
+#define AARCH64_ELF_OS_ABI_VERSION	0
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
+#define ALL_ONES (~ (bfd_vma) 0)
+
+static reloc_howto_type elf64_aarch64_howto_none =
+  HOWTO (R_AARCH64_NONE,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_NONE",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 FALSE);		/* pcrel_offset */
+
+static reloc_howto_type elf64_aarch64_howto_dynrelocs[] = {
+
+  HOWTO (R_AARCH64_COPY,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_COPY",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_GLOB_DAT,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_GLOB_DAT",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_JUMP_SLOT,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_JUMP_SLOT",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_RELATIVE,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_RELATIVE",	/* name */
+	 TRUE,			/* partial_inplace */
+	 ALL_ONES,		/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLS_DTPMOD64,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLS_DTPMOD64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pc_reloffset */
+
+  HOWTO (R_AARCH64_TLS_DTPREL64,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLS_DTPREL64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLS_TPREL64,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLS_TPREL64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+};
+
+/* Note: code such as elf64_aarch64_reloc_type_lookup expect to use e.g.
+   R_AARCH64_PREL64 as an index into this, and find the R_AARCH64_PREL64 HOWTO
+   in that slot.  */
+
+static reloc_howto_type elf64_aarch64_howto_table[] = {
+  /* Basic data relocations. */
+
+  HOWTO (R_AARCH64_NULL,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_NULL",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* .xword: (S+A) */
+  HOWTO (R_AARCH64_ABS64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (4 = long long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ABS64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 ALL_ONES,		/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* .word: (S+A) */
+  HOWTO (R_AARCH64_ABS32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ABS32",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* .half:  (S+A) */
+  HOWTO (R_AARCH64_ABS16,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ABS16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* .xword: (S+A-P) */
+  HOWTO (R_AARCH64_PREL64,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (4 = long long) */
+	 64,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_PREL64",	/* name */
+	 FALSE,			/* partial_inplace */
+	 ALL_ONES,		/* src_mask */
+	 ALL_ONES,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* .word: (S+A-P) */
+  HOWTO (R_AARCH64_PREL32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_PREL32",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* .half: (S+A-P) */
+  HOWTO (R_AARCH64_PREL16,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_PREL16",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* Group relocations to create a 16, 32, 48 or 64 bit
+     unsigned data or abs address inline. */
+
+  /* MOVZ:   ((S+A) >>  0) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_UABS_G0,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G0",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVK:   ((S+A) >>  0) & 0xffff [no overflow check] */
+  HOWTO (R_AARCH64_MOVW_UABS_G0_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G0_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVZ:   ((S+A) >> 16) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_UABS_G1,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVK:   ((S+A) >> 16) & 0xffff [no overflow check] */
+  HOWTO (R_AARCH64_MOVW_UABS_G1_NC,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G1_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVZ:   ((S+A) >> 32) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_UABS_G2,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVK:   ((S+A) >> 32) & 0xffff [no overflow check] */
+  HOWTO (R_AARCH64_MOVW_UABS_G2_NC,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G2_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOVZ:   ((S+A) >> 48) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_UABS_G3,	/* type */
+	 48,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_UABS_G3",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* Group relocations to create high part of a 16, 32, 48 or 64 bit
+     signed data or abs address inline. Will change instruction
+     to MOVN or MOVZ depending on sign of calculated value. */
+
+  /* MOV[ZN]:   ((S+A) >>  0) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_SABS_G0,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_SABS_G0",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOV[ZN]:   ((S+A) >> 16) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_SABS_G1,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_SABS_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* MOV[ZN]:   ((S+A) >> 32) & 0xffff */
+  HOWTO (R_AARCH64_MOVW_SABS_G2,	/* type */
+	 32,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_MOVW_SABS_G2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+/* Relocations to generate 19, 21 and 33 bit PC-relative load/store
+   addresses: PG(x) is (x & ~0xfff). */
+
+  /* LD-lit: ((S+A-P) >> 2) & 0x7ffff */
+  HOWTO (R_AARCH64_LD_PREL_LO19,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LD_PREL_LO19",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x7ffff,		/* src_mask */
+	 0x7ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADR:    (S+A-P) & 0x1fffff */
+  HOWTO (R_AARCH64_ADR_PREL_LO21,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ADR_PREL_LO21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+  HOWTO (R_AARCH64_ADR_PREL_PG_HI21,	/* type */
+	 12,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ADR_PREL_PG_HI21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff [no overflow check] */
+  HOWTO (R_AARCH64_ADR_PREL_PG_HI21_NC,	/* type */
+	 12,			/* 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 */
+	 "R_AARCH64_ADR_PREL_PG_HI21_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADD:    (S+A) & 0xfff [no overflow check] */
+  HOWTO (R_AARCH64_ADD_ABS_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 10,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_ADD_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x3ffc00,		/* src_mask */
+	 0x3ffc00,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* LD/ST8:  (S+A) & 0xfff */
+  HOWTO (R_AARCH64_LDST8_ABS_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST8_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* Relocations for control-flow instructions. */
+
+  /* TBZ/NZ: ((S+A-P) >> 2) & 0x3fff */
+  HOWTO (R_AARCH64_TSTBR14,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 14,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TSTBR14",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x3fff,		/* src_mask */
+	 0x3fff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* B.cond: ((S+A-P) >> 2) & 0x7ffff */
+  HOWTO (R_AARCH64_CONDBR19,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_CONDBR19",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x7ffff,		/* src_mask */
+	 0x7ffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  EMPTY_HOWTO (281),
+
+  /* B:      ((S+A-P) >> 2) & 0x3ffffff */
+  HOWTO (R_AARCH64_JUMP26,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_JUMP26",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x3ffffff,		/* src_mask */
+	 0x3ffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* BL:     ((S+A-P) >> 2) & 0x3ffffff */
+  HOWTO (R_AARCH64_CALL26,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_CALL26",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x3ffffff,		/* src_mask */
+	 0x3ffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* LD/ST16:  (S+A) & 0xffe */
+  HOWTO (R_AARCH64_LDST16_ABS_LO12_NC,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST16_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffe,			/* src_mask */
+	 0xffe,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* LD/ST32:  (S+A) & 0xffc */
+  HOWTO (R_AARCH64_LDST32_ABS_LO12_NC,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST32_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffc,			/* src_mask */
+	 0xffc,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* LD/ST64:  (S+A) & 0xff8 */
+  HOWTO (R_AARCH64_LDST64_ABS_LO12_NC,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST64_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xff8,			/* src_mask */
+	 0xff8,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (287),
+  EMPTY_HOWTO (288),
+  EMPTY_HOWTO (289),
+  EMPTY_HOWTO (290),
+  EMPTY_HOWTO (291),
+  EMPTY_HOWTO (292),
+  EMPTY_HOWTO (293),
+  EMPTY_HOWTO (294),
+  EMPTY_HOWTO (295),
+  EMPTY_HOWTO (296),
+  EMPTY_HOWTO (297),
+  EMPTY_HOWTO (298),
+
+  /* LD/ST128:  (S+A) & 0xff0 */
+  HOWTO (R_AARCH64_LDST128_ABS_LO12_NC,	/* type */
+	 4,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LDST128_ABS_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xff0,			/* src_mask */
+	 0xff0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (300),
+  EMPTY_HOWTO (301),
+  EMPTY_HOWTO (302),
+  EMPTY_HOWTO (303),
+  EMPTY_HOWTO (304),
+  EMPTY_HOWTO (305),
+  EMPTY_HOWTO (306),
+  EMPTY_HOWTO (307),
+  EMPTY_HOWTO (308),
+  EMPTY_HOWTO (309),
+  EMPTY_HOWTO (310),
+
+  /* Get to the page for the GOT entry for the symbol
+     (G(S) - P) using an ADRP instruction.  */
+  HOWTO (R_AARCH64_ADR_GOT_PAGE,	/* type */
+	 12,			/* 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 */
+	 "R_AARCH64_ADR_GOT_PAGE",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* LD64: GOT offset G(S) & 0xff8 */
+  HOWTO (R_AARCH64_LD64_GOT_LO12_NC,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_LD64_GOT_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xff8,			/* src_mask */
+	 0xff8,			/* dst_mask */
+	 FALSE)			/* pcrel_offset */
+};
+
+static reloc_howto_type elf64_aarch64_tls_howto_table[] = {
+  EMPTY_HOWTO (512),
+
+  /* Get to the page for the GOT entry for the symbol
+     (G(S) - P) using an ADRP instruction.  */
+  HOWTO (R_AARCH64_TLSGD_ADR_PAGE21,	/* type */
+	 12,			/* 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 */
+	 "R_AARCH64_TLSGD_ADR_PAGE21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* ADD: GOT offset G(S) & 0xff8 [no overflow check] */
+  HOWTO (R_AARCH64_TLSGD_ADD_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSGD_ADD_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  EMPTY_HOWTO (515),
+  EMPTY_HOWTO (516),
+  EMPTY_HOWTO (517),
+  EMPTY_HOWTO (518),
+  EMPTY_HOWTO (519),
+  EMPTY_HOWTO (520),
+  EMPTY_HOWTO (521),
+  EMPTY_HOWTO (522),
+  EMPTY_HOWTO (523),
+  EMPTY_HOWTO (524),
+  EMPTY_HOWTO (525),
+  EMPTY_HOWTO (526),
+  EMPTY_HOWTO (527),
+  EMPTY_HOWTO (528),
+  EMPTY_HOWTO (529),
+  EMPTY_HOWTO (530),
+  EMPTY_HOWTO (531),
+  EMPTY_HOWTO (532),
+  EMPTY_HOWTO (533),
+  EMPTY_HOWTO (534),
+  EMPTY_HOWTO (535),
+  EMPTY_HOWTO (536),
+  EMPTY_HOWTO (537),
+  EMPTY_HOWTO (538),
+
+  HOWTO (R_AARCH64_TLSIE_MOVW_GOTTPREL_G1,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_MOVW_GOTTPREL_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21,	/* type */
+	 12,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xff8,			/* src_mask */
+	 0xff8,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSIE_LD_GOTTPREL_PREL19,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSIE_LD_GOTTPREL_PREL19",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1ffffc,		/* src_mask */
+	 0x1ffffc,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G2,	/* type */
+	 8,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G1,	/* type */
+	 4,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G1_NC,	/* type */
+	 4,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G1_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G0,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G0",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_MOVW_TPREL_G0_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_MOVW_TPREL_G0_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_ADD_TPREL_HI12,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_ADD_TPREL_HI12",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_ADD_TPREL_LO12,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_ADD_TPREL_LO12",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSLE_ADD_TPREL_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSLE_ADD_TPREL_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+};
+
+static reloc_howto_type elf64_aarch64_tlsdesc_howto_table[] = {
+  HOWTO (R_AARCH64_TLSDESC_LD64_PREL19,	/* 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 */
+	 "R_AARCH64_TLSDESC_LD64_PREL19",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1ffffc,		/* src_mask */
+	 0x1ffffc,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_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 */
+	 "R_AARCH64_TLSDESC_ADR_PREL21",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* Get to the page for the GOT entry for the symbol
+     (G(S) - P) using an ADRP instruction.  */
+  HOWTO (R_AARCH64_TLSDESC_ADR_PAGE,	/* type */
+	 12,			/* 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 */
+	 "R_AARCH64_TLSDESC_ADR_PAGE",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x1fffff,		/* src_mask */
+	 0x1fffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+
+  /* LD64: GOT offset G(S) & 0xfff.  */
+  HOWTO (R_AARCH64_TLSDESC_LD64_LO12_NC,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_LD64_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* ADD: GOT offset G(S) & 0xfff.  */
+  HOWTO (R_AARCH64_TLSDESC_ADD_LO12_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_ADD_LO12_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xfff,			/* src_mask */
+	 0xfff,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_OFF_G1,	/* type */
+	 4,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_OFF_G1",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_OFF_G0_NC,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_OFF_G0_NC",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffff,		/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_LDR,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_LDR",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_ADD,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_ADD",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  HOWTO (R_AARCH64_TLSDESC_CALL,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_AARCH64_TLSDESC_CALL",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+};
+
+static reloc_howto_type *
+elf64_aarch64_howto_from_type (unsigned int r_type)
+{
+  if (r_type >= R_AARCH64_static_min && r_type < R_AARCH64_static_max)
+    return &elf64_aarch64_howto_table[r_type - R_AARCH64_static_min];
+
+  if (r_type >= R_AARCH64_tls_min && r_type < R_AARCH64_tls_max)
+    return &elf64_aarch64_tls_howto_table[r_type - R_AARCH64_tls_min];
+
+  if (r_type >= R_AARCH64_tlsdesc_min && r_type < R_AARCH64_tlsdesc_max)
+    return &elf64_aarch64_tlsdesc_howto_table[r_type - R_AARCH64_tlsdesc_min];
+
+  if (r_type >= R_AARCH64_dyn_min && r_type < R_AARCH64_dyn_max)
+    return &elf64_aarch64_howto_dynrelocs[r_type - R_AARCH64_dyn_min];
+
+  switch (r_type)
+    {
+    case R_AARCH64_NONE:
+      return &elf64_aarch64_howto_none;
+
+    }
+  bfd_set_error (bfd_error_bad_value);
+  return NULL;
+}
+
+static void
+elf64_aarch64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
+			     Elf_Internal_Rela *elf_reloc)
+{
+  unsigned int r_type;
+
+  r_type = ELF64_R_TYPE (elf_reloc->r_info);
+  bfd_reloc->howto = elf64_aarch64_howto_from_type (r_type);
+}
+
+struct elf64_aarch64_reloc_map
+{
+  bfd_reloc_code_real_type bfd_reloc_val;
+  unsigned int elf_reloc_val;
+};
+
+/* All entries in this list must also be present in
+   elf64_aarch64_howto_table.  */
+static const struct elf64_aarch64_reloc_map elf64_aarch64_reloc_map[] = {
+  {BFD_RELOC_NONE, R_AARCH64_NONE},
+
+  /* Basic data relocations.  */
+  {BFD_RELOC_CTOR, R_AARCH64_ABS64},
+  {BFD_RELOC_64, R_AARCH64_ABS64},
+  {BFD_RELOC_32, R_AARCH64_ABS32},
+  {BFD_RELOC_16, R_AARCH64_ABS16},
+  {BFD_RELOC_64_PCREL, R_AARCH64_PREL64},
+  {BFD_RELOC_32_PCREL, R_AARCH64_PREL32},
+  {BFD_RELOC_16_PCREL, R_AARCH64_PREL16},
+
+  /* Group relocations to low order bits of a 16, 32, 48 or 64 bit
+     value inline.  */
+  {BFD_RELOC_AARCH64_MOVW_G0_NC, R_AARCH64_MOVW_UABS_G0_NC},
+  {BFD_RELOC_AARCH64_MOVW_G1_NC, R_AARCH64_MOVW_UABS_G1_NC},
+  {BFD_RELOC_AARCH64_MOVW_G2_NC, R_AARCH64_MOVW_UABS_G2_NC},
+
+  /* Group relocations to create high bits of a 16, 32, 48 or 64 bit
+     signed value inline.  */
+  {BFD_RELOC_AARCH64_MOVW_G0_S, R_AARCH64_MOVW_SABS_G0},
+  {BFD_RELOC_AARCH64_MOVW_G1_S, R_AARCH64_MOVW_SABS_G1},
+  {BFD_RELOC_AARCH64_MOVW_G2_S, R_AARCH64_MOVW_SABS_G2},
+
+  /* Group relocations to create high bits of a 16, 32, 48 or 64 bit
+     unsigned value inline.  */
+  {BFD_RELOC_AARCH64_MOVW_G0, R_AARCH64_MOVW_UABS_G0},
+  {BFD_RELOC_AARCH64_MOVW_G1, R_AARCH64_MOVW_UABS_G1},
+  {BFD_RELOC_AARCH64_MOVW_G2, R_AARCH64_MOVW_UABS_G2},
+  {BFD_RELOC_AARCH64_MOVW_G3, R_AARCH64_MOVW_UABS_G3},
+
+  /* Relocations to generate 19, 21 and 33 bit PC-relative load/store.  */
+  {BFD_RELOC_AARCH64_LD_LO19_PCREL, R_AARCH64_LD_PREL_LO19},
+  {BFD_RELOC_AARCH64_ADR_LO21_PCREL, R_AARCH64_ADR_PREL_LO21},
+  {BFD_RELOC_AARCH64_ADR_HI21_PCREL, R_AARCH64_ADR_PREL_PG_HI21},
+  {BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL, R_AARCH64_ADR_PREL_PG_HI21_NC},
+  {BFD_RELOC_AARCH64_ADD_LO12, R_AARCH64_ADD_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST8_LO12, R_AARCH64_LDST8_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST16_LO12, R_AARCH64_LDST16_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST32_LO12, R_AARCH64_LDST32_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST64_LO12, R_AARCH64_LDST64_ABS_LO12_NC},
+  {BFD_RELOC_AARCH64_LDST128_LO12, R_AARCH64_LDST128_ABS_LO12_NC},
+
+  /* Relocations for control-flow instructions. */
+  {BFD_RELOC_AARCH64_TSTBR14, R_AARCH64_TSTBR14},
+  {BFD_RELOC_AARCH64_BRANCH19, R_AARCH64_CONDBR19},
+  {BFD_RELOC_AARCH64_JUMP26, R_AARCH64_JUMP26},
+  {BFD_RELOC_AARCH64_CALL26, R_AARCH64_CALL26},
+
+  /* Relocations for PIC.  */
+  {BFD_RELOC_AARCH64_ADR_GOT_PAGE, R_AARCH64_ADR_GOT_PAGE},
+  {BFD_RELOC_AARCH64_LD64_GOT_LO12_NC, R_AARCH64_LD64_GOT_LO12_NC},
+
+  /* Relocations for TLS. */
+  {BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21, R_AARCH64_TLSGD_ADR_PAGE21},
+  {BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC, R_AARCH64_TLSGD_ADD_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1,
+   R_AARCH64_TLSIE_MOVW_GOTTPREL_G1},
+  {BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC,
+   R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC},
+  {BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21,
+   R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21},
+  {BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC,
+   R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19,
+   R_AARCH64_TLSIE_LD_GOTTPREL_PREL19},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2, R_AARCH64_TLSLE_MOVW_TPREL_G2},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1, R_AARCH64_TLSLE_MOVW_TPREL_G1},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC,
+   R_AARCH64_TLSLE_MOVW_TPREL_G1_NC},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0, R_AARCH64_TLSLE_MOVW_TPREL_G0},
+  {BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC,
+   R_AARCH64_TLSLE_MOVW_TPREL_G0_NC},
+  {BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12, R_AARCH64_TLSLE_ADD_TPREL_LO12},
+  {BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12, R_AARCH64_TLSLE_ADD_TPREL_HI12},
+  {BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC,
+   R_AARCH64_TLSLE_ADD_TPREL_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSDESC_LD64_PREL19, R_AARCH64_TLSDESC_LD64_PREL19},
+  {BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21, R_AARCH64_TLSDESC_ADR_PREL21},
+  {BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE, R_AARCH64_TLSDESC_ADR_PAGE},
+  {BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC, R_AARCH64_TLSDESC_ADD_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC, R_AARCH64_TLSDESC_LD64_LO12_NC},
+  {BFD_RELOC_AARCH64_TLSDESC_OFF_G1, R_AARCH64_TLSDESC_OFF_G1},
+  {BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC, R_AARCH64_TLSDESC_OFF_G0_NC},
+  {BFD_RELOC_AARCH64_TLSDESC_LDR, R_AARCH64_TLSDESC_LDR},
+  {BFD_RELOC_AARCH64_TLSDESC_ADD, R_AARCH64_TLSDESC_ADD},
+  {BFD_RELOC_AARCH64_TLSDESC_CALL, R_AARCH64_TLSDESC_CALL},
+  {BFD_RELOC_AARCH64_TLS_DTPMOD64, R_AARCH64_TLS_DTPMOD64},
+  {BFD_RELOC_AARCH64_TLS_DTPREL64, R_AARCH64_TLS_DTPREL64},
+  {BFD_RELOC_AARCH64_TLS_TPREL64, R_AARCH64_TLS_TPREL64},
+  {BFD_RELOC_AARCH64_TLSDESC, R_AARCH64_TLSDESC},
+};
+
+static reloc_howto_type *
+elf64_aarch64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+				 bfd_reloc_code_real_type code)
+{
+  unsigned int i;
+
+  for (i = 0; i < ARRAY_SIZE (elf64_aarch64_reloc_map); i++)
+    if (elf64_aarch64_reloc_map[i].bfd_reloc_val == code)
+      return elf64_aarch64_howto_from_type
+	(elf64_aarch64_reloc_map[i].elf_reloc_val);
+
+  bfd_set_error (bfd_error_bad_value);
+  return NULL;
+}
+
+static reloc_howto_type *
+elf64_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+				 const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0; i < ARRAY_SIZE (elf64_aarch64_howto_table); i++)
+    if (elf64_aarch64_howto_table[i].name != NULL
+	&& strcasecmp (elf64_aarch64_howto_table[i].name, r_name) == 0)
+      return &elf64_aarch64_howto_table[i];
+
+  return NULL;
+}
+
+#define TARGET_LITTLE_SYM               bfd_elf64_littleaarch64_vec
+#define TARGET_LITTLE_NAME              "elf64-littleaarch64"
+#define TARGET_BIG_SYM                  bfd_elf64_bigaarch64_vec
+#define TARGET_BIG_NAME                 "elf64-bigaarch64"
+
+typedef unsigned long int insn32;
+
+/* The linker script knows the section names for placement.
+   The entry_names are used to do simple name mangling on the stubs.
+   Given a function name, and its type, the stub can be found. The
+   name can be changed. The only requirement is the %s be present.  */
+#define STUB_ENTRY_NAME   "__%s_veneer"
+
+/* The name of the dynamic interpreter.  This is put in the .interp
+   section.  */
+#define ELF_DYNAMIC_INTERPRETER     "/lib/ld.so.1"
+
+#define AARCH64_MAX_FWD_BRANCH_OFFSET \
+  (((1 << 25) - 1) << 2)
+#define AARCH64_MAX_BWD_BRANCH_OFFSET \
+  (-((1 << 25) << 2))
+
+#define AARCH64_MAX_ADRP_IMM ((1 << 20) - 1)
+#define AARCH64_MIN_ADRP_IMM (-(1 << 20))
+
+static int
+aarch64_valid_for_adrp_p (bfd_vma value, bfd_vma place)
+{
+  bfd_signed_vma offset = (bfd_signed_vma) (PG (value) - PG (place)) >> 12;
+  return offset <= AARCH64_MAX_ADRP_IMM && offset >= AARCH64_MIN_ADRP_IMM;
+}
+
+static int
+aarch64_valid_branch_p (bfd_vma value, bfd_vma place)
+{
+  bfd_signed_vma offset = (bfd_signed_vma) (value - place);
+  return (offset <= AARCH64_MAX_FWD_BRANCH_OFFSET
+	  && offset >= AARCH64_MAX_BWD_BRANCH_OFFSET);
+}
+
+static const uint32_t aarch64_adrp_branch_stub [] = {
+  0x90000010,			/*	adrp	ip0, X */
+				/*		R_AARCH64_ADR_HI21_PCREL(X) */
+  0x91000210,			/*	add	ip0, ip0, :lo12:X */
+				/*		R_AARCH64_ADD_ABS_LO12_NC(X) */
+  0xd61f0200,			/*	br	ip0 */
+};
+
+static const uint32_t aarch64_long_branch_stub[] = {
+  0x58000090,			/*	ldr   ip0, 1f */
+  0x10000011,			/*	adr   ip1, #0 */
+  0x8b110210,			/*	add   ip0, ip0, ip1 */
+  0xd61f0200,			/*	br	ip0 */
+  0x00000000,			/* 1:	.xword
+				   R_AARCH64_PREL64(X) + 12
+				 */
+  0x00000000,
+};
+
+/* Section name for stubs is the associated section name plus this
+   string.  */
+#define STUB_SUFFIX ".stub"
+
+enum elf64_aarch64_stub_type
+{
+  aarch64_stub_none,
+  aarch64_stub_adrp_branch,
+  aarch64_stub_long_branch,
+};
+
+struct elf64_aarch64_stub_hash_entry
+{
+  /* Base hash table entry structure.  */
+  struct bfd_hash_entry root;
+
+
+  /* The stub section.  */
+  asection *stub_sec;
+
+  /* Offset within stub_sec of the beginning of this stub.  */
+  bfd_vma stub_offset;
+
+  /* Given the symbol's value and its section we can determine its final
+     value when building the stubs (so the stub knows where to jump).  */
+  bfd_vma target_value;
+  asection *target_section;
+
+  enum elf64_aarch64_stub_type stub_type;
+
+  /* The symbol table entry, if any, that this was derived from.  */
+  struct elf64_aarch64_link_hash_entry *h;
+
+  /* Destination symbol type */
+  unsigned char st_type;
+
+  /* Where this stub is being called from, or, in the case of combined
+     stub sections, the first input section in the group.  */
+  asection *id_sec;
+
+  /* The name for the local symbol at the start of this stub.  The
+     stub name in the hash table has to be unique; this does not, so
+     it can be friendlier.  */
+  char *output_name;
+};
+
+/* Used to build a map of a section.  This is required for mixed-endian
+   code/data.  */
+
+typedef struct elf64_elf_section_map
+{
+  bfd_vma vma;
+  char type;
+}
+elf64_aarch64_section_map;
+
+
+typedef struct _aarch64_elf_section_data
+{
+  struct bfd_elf_section_data elf;
+  unsigned int mapcount;
+  unsigned int mapsize;
+  elf64_aarch64_section_map *map;
+}
+_aarch64_elf_section_data;
+
+#define elf64_aarch64_section_data(sec) \
+  ((_aarch64_elf_section_data *) elf_section_data (sec))
+
+/* The size of the thread control block.  */
+#define TCB_SIZE	16
+
+struct elf_aarch64_local_symbol
+{
+  unsigned int got_type;
+  bfd_signed_vma got_refcount;
+  bfd_vma got_offset;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor. The
+     offset is from the end of the jump table and reserved entries
+     within the PLTGOT.
+
+     The magic value (bfd_vma) -1 indicates that an offset has not be
+     allocated.  */
+  bfd_vma tlsdesc_got_jump_table_offset;
+};
+
+struct elf_aarch64_obj_tdata
+{
+  struct elf_obj_tdata root;
+
+  /* local symbol descriptors */
+  struct elf_aarch64_local_symbol *locals;
+
+  /* Zero to warn when linking objects with incompatible enum sizes.  */
+  int no_enum_size_warning;
+
+  /* Zero to warn when linking objects with incompatible wchar_t sizes.  */
+  int no_wchar_size_warning;
+};
+
+#define elf_aarch64_tdata(bfd)				\
+  ((struct elf_aarch64_obj_tdata *) (bfd)->tdata.any)
+
+#define elf64_aarch64_locals(bfd) (elf_aarch64_tdata (bfd)->locals)
+
+#define is_aarch64_elf(bfd)				\
+  (bfd_get_flavour (bfd) == bfd_target_elf_flavour	\
+   && elf_tdata (bfd) != NULL				\
+   && elf_object_id (bfd) == AARCH64_ELF_DATA)
+
+static bfd_boolean
+elf64_aarch64_mkobject (bfd *abfd)
+{
+  return bfd_elf_allocate_object (abfd, sizeof (struct elf_aarch64_obj_tdata),
+				  AARCH64_ELF_DATA);
+}
+
+/* The AArch64 linker needs to keep track of the number of relocs that it
+   decides to copy in check_relocs for each symbol.  This is so that
+   it can discard PC relative relocs if it doesn't need them when
+   linking with -Bsymbolic.  We store the information in a field
+   extending the regular ELF linker hash table.  */
+
+/* This structure keeps track of the number of relocs we have copied
+   for a given symbol.  */
+struct elf64_aarch64_relocs_copied
+{
+  /* Next section.  */
+  struct elf64_aarch64_relocs_copied *next;
+  /* A section in dynobj.  */
+  asection *section;
+  /* Number of relocs copied in this section.  */
+  bfd_size_type count;
+  /* Number of PC-relative relocs copied in this section.  */
+  bfd_size_type pc_count;
+};
+
+#define elf64_aarch64_hash_entry(ent) \
+  ((struct elf64_aarch64_link_hash_entry *)(ent))
+
+#define GOT_UNKNOWN    0
+#define GOT_NORMAL     1
+#define GOT_TLS_GD     2
+#define GOT_TLS_IE     4
+#define GOT_TLSDESC_GD 8
+
+#define GOT_TLS_GD_ANY_P(type)	((type & GOT_TLS_GD) || (type & GOT_TLSDESC_GD))
+
+/* AArch64 ELF linker hash entry.  */
+struct elf64_aarch64_link_hash_entry
+{
+  struct elf_link_hash_entry root;
+
+  /* Track dynamic relocs copied for this symbol.  */
+  struct elf_dyn_relocs *dyn_relocs;
+
+  /* Number of PC relative relocs copied for this symbol.  */
+  struct elf64_aarch64_relocs_copied *relocs_copied;
+
+  /* Since PLT entries have variable size, we need to record the
+     index into .got.plt instead of recomputing it from the PLT
+     offset.  */
+  bfd_signed_vma plt_got_offset;
+
+  /* Bit mask representing the type of GOT entry(s) if any required by
+     this symbol.  */
+  unsigned int got_type;
+
+  /* A pointer to the most recently used stub hash entry against this
+     symbol.  */
+  struct elf64_aarch64_stub_hash_entry *stub_cache;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor.  The offset
+     is from the end of the jump table and reserved entries within the PLTGOT.
+
+     The magic value (bfd_vma) -1 indicates that an offset has not
+     be allocated.  */
+  bfd_vma tlsdesc_got_jump_table_offset;
+};
+
+static unsigned int
+elf64_aarch64_symbol_got_type (struct elf_link_hash_entry *h,
+			       bfd *abfd,
+			       unsigned long r_symndx)
+{
+  if (h)
+    return elf64_aarch64_hash_entry (h)->got_type;
+
+  if (! elf64_aarch64_locals (abfd))
+    return GOT_UNKNOWN;
+
+  return elf64_aarch64_locals (abfd)[r_symndx].got_type;
+}
+
+/* Traverse an AArch64 ELF linker hash table.  */
+#define elf64_aarch64_link_hash_traverse(table, func, info)		\
+  (elf_link_hash_traverse						\
+   (&(table)->root,							\
+    (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func),	\
+    (info)))
+
+/* Get the AArch64 elf linker hash table from a link_info structure.  */
+#define elf64_aarch64_hash_table(info)					\
+  ((struct elf64_aarch64_link_hash_table *) ((info)->hash))
+
+#define aarch64_stub_hash_lookup(table, string, create, copy)		\
+  ((struct elf64_aarch64_stub_hash_entry *)				\
+   bfd_hash_lookup ((table), (string), (create), (copy)))
+
+/* AArch64 ELF linker hash table.  */
+struct elf64_aarch64_link_hash_table
+{
+  /* The main hash table.  */
+  struct elf_link_hash_table root;
+
+  /* Nonzero to force PIC branch veneers.  */
+  int pic_veneer;
+
+  /* The number of bytes in the initial entry in the PLT.  */
+  bfd_size_type plt_header_size;
+
+  /* The number of bytes in the subsequent PLT etries.  */
+  bfd_size_type plt_entry_size;
+
+  /* Short-cuts to get to dynamic linker sections.  */
+  asection *sdynbss;
+  asection *srelbss;
+
+  /* Small local sym cache.  */
+  struct sym_cache sym_cache;
+
+  /* For convenience in allocate_dynrelocs.  */
+  bfd *obfd;
+
+  /* The amount of space used by the reserved portion of the sgotplt
+     section, plus whatever space is used by the jump slots.  */
+  bfd_vma sgotplt_jump_table_size;
+
+  /* The stub hash table.  */
+  struct bfd_hash_table stub_hash_table;
+
+  /* Linker stub bfd.  */
+  bfd *stub_bfd;
+
+  /* Linker call-backs.  */
+  asection *(*add_stub_section) (const char *, asection *);
+  void (*layout_sections_again) (void);
+
+  /* Array to keep track of which stub sections have been created, and
+     information on stub grouping.  */
+  struct map_stub
+  {
+    /* This is the section to which stubs in the group will be
+       attached.  */
+    asection *link_sec;
+    /* The stub section.  */
+    asection *stub_sec;
+  } *stub_group;
+
+  /* Assorted information used by elf64_aarch64_size_stubs.  */
+  unsigned int bfd_count;
+  int top_index;
+  asection **input_list;
+
+  /* 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
+     yet.  */
+  bfd_vma tlsdesc_plt;
+
+  /* The GOT offset for the lazy trampoline.  Communicated to the
+     loader via DT_TLSDESC_GOT.  The magic value (bfd_vma) -1
+     indicates an offset is not allocated.  */
+  bfd_vma dt_tlsdesc_got;
+};
+
+
+/* Return non-zero if the indicated VALUE has overflowed the maximum
+   range expressible by a unsigned number with the indicated number of
+   BITS.  */
+
+static bfd_reloc_status_type
+aarch64_unsigned_overflow (bfd_vma value, unsigned int bits)
+{
+  bfd_vma lim;
+  if (bits >= sizeof (bfd_vma) * 8)
+    return bfd_reloc_ok;
+  lim = (bfd_vma) 1 << bits;
+  if (value >= lim)
+    return bfd_reloc_overflow;
+  return bfd_reloc_ok;
+}
+
+
+/* Return non-zero if the indicated VALUE has overflowed the maximum
+   range expressible by an signed number with the indicated number of
+   BITS.  */
+
+static bfd_reloc_status_type
+aarch64_signed_overflow (bfd_vma value, unsigned int bits)
+{
+  bfd_signed_vma svalue = (bfd_signed_vma) value;
+  bfd_signed_vma lim;
+
+  if (bits >= sizeof (bfd_vma) * 8)
+    return bfd_reloc_ok;
+  lim = (bfd_signed_vma) 1 << (bits - 1);
+  if (svalue < -lim || svalue >= lim)
+    return bfd_reloc_overflow;
+  return bfd_reloc_ok;
+}
+
+/* Create an entry in an AArch64 ELF linker hash table.  */
+
+static struct bfd_hash_entry *
+elf64_aarch64_link_hash_newfunc (struct bfd_hash_entry *entry,
+				 struct bfd_hash_table *table,
+				 const char *string)
+{
+  struct elf64_aarch64_link_hash_entry *ret =
+    (struct elf64_aarch64_link_hash_entry *) entry;
+
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (ret == NULL)
+    ret = bfd_hash_allocate (table,
+			     sizeof (struct elf64_aarch64_link_hash_entry));
+  if (ret == NULL)
+    return (struct bfd_hash_entry *) ret;
+
+  /* Call the allocation method of the superclass.  */
+  ret = ((struct elf64_aarch64_link_hash_entry *)
+	 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+				     table, string));
+  if (ret != NULL)
+    {
+      ret->dyn_relocs = NULL;
+      ret->relocs_copied = NULL;
+      ret->got_type = GOT_UNKNOWN;
+      ret->plt_got_offset = (bfd_vma) - 1;
+      ret->stub_cache = NULL;
+      ret->tlsdesc_got_jump_table_offset = (bfd_vma) - 1;
+    }
+
+  return (struct bfd_hash_entry *) ret;
+}
+
+/* Initialize an entry in the stub hash table.  */
+
+static struct bfd_hash_entry *
+stub_hash_newfunc (struct bfd_hash_entry *entry,
+		   struct bfd_hash_table *table, const char *string)
+{
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (entry == NULL)
+    {
+      entry = bfd_hash_allocate (table,
+				 sizeof (struct
+					 elf64_aarch64_stub_hash_entry));
+      if (entry == NULL)
+	return entry;
+    }
+
+  /* Call the allocation method of the superclass.  */
+  entry = bfd_hash_newfunc (entry, table, string);
+  if (entry != NULL)
+    {
+      struct elf64_aarch64_stub_hash_entry *eh;
+
+      /* Initialize the local fields.  */
+      eh = (struct elf64_aarch64_stub_hash_entry *) entry;
+      eh->stub_sec = NULL;
+      eh->stub_offset = 0;
+      eh->target_value = 0;
+      eh->target_section = NULL;
+      eh->stub_type = aarch64_stub_none;
+      eh->h = NULL;
+      eh->id_sec = NULL;
+    }
+
+  return entry;
+}
+
+
+/* Copy the extra info we tack onto an elf_link_hash_entry.  */
+
+static void
+elf64_aarch64_copy_indirect_symbol (struct bfd_link_info *info,
+				    struct elf_link_hash_entry *dir,
+				    struct elf_link_hash_entry *ind)
+{
+  struct elf64_aarch64_link_hash_entry *edir, *eind;
+
+  edir = (struct elf64_aarch64_link_hash_entry *) dir;
+  eind = (struct elf64_aarch64_link_hash_entry *) ind;
+
+  if (eind->dyn_relocs != NULL)
+    {
+      if (edir->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;)
+	    {
+	      struct elf_dyn_relocs *q;
+
+	      for (q = edir->dyn_relocs; q != NULL; q = q->next)
+		if (q->sec == p->sec)
+		  {
+		    q->pc_count += p->pc_count;
+		    q->count += p->count;
+		    *pp = p->next;
+		    break;
+		  }
+	      if (q == NULL)
+		pp = &p->next;
+	    }
+	  *pp = edir->dyn_relocs;
+	}
+
+      edir->dyn_relocs = eind->dyn_relocs;
+      eind->dyn_relocs = NULL;
+    }
+
+  if (eind->relocs_copied != NULL)
+    {
+      if (edir->relocs_copied != NULL)
+	{
+	  struct elf64_aarch64_relocs_copied **pp;
+	  struct elf64_aarch64_relocs_copied *p;
+
+	  /* Add reloc counts against the indirect sym to the direct sym
+	     list.  Merge any entries against the same section.  */
+	  for (pp = &eind->relocs_copied; (p = *pp) != NULL;)
+	    {
+	      struct elf64_aarch64_relocs_copied *q;
+
+	      for (q = edir->relocs_copied; q != NULL; q = q->next)
+		if (q->section == p->section)
+		  {
+		    q->pc_count += p->pc_count;
+		    q->count += p->count;
+		    *pp = p->next;
+		    break;
+		  }
+	      if (q == NULL)
+		pp = &p->next;
+	    }
+	  *pp = edir->relocs_copied;
+	}
+
+      edir->relocs_copied = eind->relocs_copied;
+      eind->relocs_copied = NULL;
+    }
+
+  if (ind->root.type == bfd_link_hash_indirect)
+    {
+      /* Copy over PLT info.  */
+      if (dir->got.refcount <= 0)
+	{
+	  edir->got_type = eind->got_type;
+	  eind->got_type = GOT_UNKNOWN;
+	}
+    }
+
+  _bfd_elf_link_hash_copy_indirect (info, dir, ind);
+}
+
+/* Create an AArch64 elf linker hash table.  */
+
+static struct bfd_link_hash_table *
+elf64_aarch64_link_hash_table_create (bfd *abfd)
+{
+  struct elf64_aarch64_link_hash_table *ret;
+  bfd_size_type amt = sizeof (struct elf64_aarch64_link_hash_table);
+
+  ret = bfd_malloc (amt);
+  if (ret == NULL)
+    return NULL;
+
+  if (!_bfd_elf_link_hash_table_init
+      (&ret->root, abfd, elf64_aarch64_link_hash_newfunc,
+       sizeof (struct elf64_aarch64_link_hash_entry), AARCH64_ELF_DATA))
+    {
+      free (ret);
+      return NULL;
+    }
+
+  ret->sdynbss = NULL;
+  ret->srelbss = NULL;
+
+  ret->plt_header_size = PLT_ENTRY_SIZE;
+  ret->plt_entry_size = PLT_SMALL_ENTRY_SIZE;
+
+  ret->sym_cache.abfd = NULL;
+  ret->obfd = abfd;
+
+  ret->stub_bfd = NULL;
+  ret->add_stub_section = NULL;
+  ret->layout_sections_again = NULL;
+  ret->stub_group = NULL;
+  ret->bfd_count = 0;
+  ret->top_index = 0;
+  ret->input_list = NULL;
+  ret->tlsdesc_plt = 0;
+  ret->dt_tlsdesc_got = (bfd_vma) - 1;
+
+  if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc,
+			    sizeof (struct elf64_aarch64_stub_hash_entry)))
+    {
+      free (ret);
+      return NULL;
+    }
+
+  return &ret->root.root;
+}
+
+/* Free the derived linker hash table.  */
+
+static void
+elf64_aarch64_hash_table_free (struct bfd_link_hash_table *hash)
+{
+  struct elf64_aarch64_link_hash_table *ret
+    = (struct elf64_aarch64_link_hash_table *) hash;
+
+  bfd_hash_table_free (&ret->stub_hash_table);
+  _bfd_generic_link_hash_table_free (hash);
+}
+
+static bfd_vma
+aarch64_resolve_relocation (unsigned int r_type, bfd_vma place, bfd_vma value,
+			    bfd_vma addend, bfd_boolean weak_undef_p)
+{
+  switch (r_type)
+    {
+    case R_AARCH64_TLSDESC_CALL:
+    case R_AARCH64_NONE:
+    case R_AARCH64_NULL:
+      break;
+
+    case R_AARCH64_ADR_PREL_LO21:
+    case R_AARCH64_CONDBR19:
+    case R_AARCH64_LD_PREL_LO19:
+    case R_AARCH64_PREL16:
+    case R_AARCH64_PREL32:
+    case R_AARCH64_PREL64:
+    case R_AARCH64_TSTBR14:
+      if (weak_undef_p)
+	value = place;
+      value = value + addend - place;
+      break;
+
+    case R_AARCH64_CALL26:
+    case R_AARCH64_JUMP26:
+      value = value + addend - place;
+      break;
+
+    case R_AARCH64_ABS16:
+    case R_AARCH64_ABS32:
+    case R_AARCH64_MOVW_SABS_G0:
+    case R_AARCH64_MOVW_SABS_G1:
+    case R_AARCH64_MOVW_SABS_G2:
+    case R_AARCH64_MOVW_UABS_G0:
+    case R_AARCH64_MOVW_UABS_G0_NC:
+    case R_AARCH64_MOVW_UABS_G1:
+    case R_AARCH64_MOVW_UABS_G1_NC:
+    case R_AARCH64_MOVW_UABS_G2:
+    case R_AARCH64_MOVW_UABS_G2_NC:
+    case R_AARCH64_MOVW_UABS_G3:
+      value = value + addend;
+      break;
+
+    case R_AARCH64_ADR_PREL_PG_HI21:
+    case R_AARCH64_ADR_PREL_PG_HI21_NC:
+      if (weak_undef_p)
+	value = PG (place);
+      value = PG (value + addend) - PG (place);
+      break;
+
+    case R_AARCH64_ADR_GOT_PAGE:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+      value = PG (value + addend) - PG (place);
+      break;
+
+    case R_AARCH64_ADD_ABS_LO12_NC:
+    case R_AARCH64_LD64_GOT_LO12_NC:
+    case R_AARCH64_LDST8_ABS_LO12_NC:
+    case R_AARCH64_LDST16_ABS_LO12_NC:
+    case R_AARCH64_LDST32_ABS_LO12_NC:
+    case R_AARCH64_LDST64_ABS_LO12_NC:
+    case R_AARCH64_LDST128_ABS_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+    case R_AARCH64_TLSDESC_LDR:
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+      value = PG_OFFSET (value + addend);
+      break;
+
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+      value = (value + addend) & (bfd_vma) 0xffff0000;
+      break;
+    case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+      value = (value + addend) & (bfd_vma) 0xfff000;
+      break;
+
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+      value = (value + addend) & (bfd_vma) 0xffff;
+      break;
+
+    case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+      value = (value + addend) & ~(bfd_vma) 0xffffffff;
+      value -= place & ~(bfd_vma) 0xffffffff;
+      break;
+    }
+  return value;
+}
+
+static bfd_boolean
+aarch64_relocate (unsigned int r_type, bfd *input_bfd, asection *input_section,
+		  bfd_vma offset, bfd_vma value)
+{
+  reloc_howto_type *howto;
+  bfd_vma place;
+
+  howto = elf64_aarch64_howto_from_type (r_type);
+  place = (input_section->output_section->vma + input_section->output_offset
+	   + offset);
+  value = aarch64_resolve_relocation (r_type, place, value, 0, FALSE);
+  return bfd_elf_aarch64_put_addend (input_bfd,
+				     input_section->contents + offset,
+				     howto, value);
+}
+
+static enum elf64_aarch64_stub_type
+aarch64_select_branch_stub (bfd_vma value, bfd_vma place)
+{
+  if (aarch64_valid_for_adrp_p (value, place))
+    return aarch64_stub_adrp_branch;
+  return aarch64_stub_long_branch;
+}
+
+/* Determine the type of stub needed, if any, for a call.  */
+
+static enum elf64_aarch64_stub_type
+aarch64_type_of_stub (struct bfd_link_info *info,
+		      asection *input_sec,
+		      const Elf_Internal_Rela *rel,
+		      unsigned char st_type,
+		      struct elf64_aarch64_link_hash_entry *hash,
+		      bfd_vma destination)
+{
+  bfd_vma location;
+  bfd_signed_vma branch_offset;
+  unsigned int r_type;
+  struct elf64_aarch64_link_hash_table *globals;
+  enum elf64_aarch64_stub_type stub_type = aarch64_stub_none;
+  bfd_boolean via_plt_p;
+
+  if (st_type != STT_FUNC)
+    return stub_type;
+
+  globals = elf64_aarch64_hash_table (info);
+  via_plt_p = (globals->root.splt != NULL && hash != NULL
+	       && hash->root.plt.offset != (bfd_vma) - 1);
+
+  if (via_plt_p)
+    return stub_type;
+
+  /* Determine where the call point is.  */
+  location = (input_sec->output_offset
+	      + input_sec->output_section->vma + rel->r_offset);
+
+  branch_offset = (bfd_signed_vma) (destination - location);
+
+  r_type = ELF64_R_TYPE (rel->r_info);
+
+  /* We don't want to redirect any old unconditional jump in this way,
+     only one which is being used for a sibcall, where it is
+     acceptable for the IP0 and IP1 registers to be clobbered.  */
+  if ((r_type == R_AARCH64_CALL26 || r_type == R_AARCH64_JUMP26)
+      && (branch_offset > AARCH64_MAX_FWD_BRANCH_OFFSET
+	  || branch_offset < AARCH64_MAX_BWD_BRANCH_OFFSET))
+    {
+      stub_type = aarch64_stub_long_branch;
+    }
+
+  return stub_type;
+}
+
+/* Build a name for an entry in the stub hash table.  */
+
+static char *
+elf64_aarch64_stub_name (const asection *input_section,
+			 const asection *sym_sec,
+			 const struct elf64_aarch64_link_hash_entry *hash,
+			 const Elf_Internal_Rela *rel)
+{
+  char *stub_name;
+  bfd_size_type len;
+
+  if (hash)
+    {
+      len = 8 + 1 + strlen (hash->root.root.root.string) + 1 + 16 + 1;
+      stub_name = bfd_malloc (len);
+      if (stub_name != NULL)
+	snprintf (stub_name, len, "%08x_%s+%" BFD_VMA_FMT "x",
+		  (unsigned int) input_section->id,
+		  hash->root.root.root.string,
+		  rel->r_addend);
+    }
+  else
+    {
+      len = 8 + 1 + 8 + 1 + 8 + 1 + 16 + 1;
+      stub_name = bfd_malloc (len);
+      if (stub_name != NULL)
+	snprintf (stub_name, len, "%08x_%x:%x+%" BFD_VMA_FMT "x",
+		  (unsigned int) input_section->id,
+		  (unsigned int) sym_sec->id,
+		  (unsigned int) ELF64_R_SYM (rel->r_info),
+		  rel->r_addend);
+    }
+
+  return stub_name;
+}
+
+/* Look up an entry in the stub hash.  Stub entries are cached because
+   creating the stub name takes a bit of time.  */
+
+static struct elf64_aarch64_stub_hash_entry *
+elf64_aarch64_get_stub_entry (const asection *input_section,
+			      const asection *sym_sec,
+			      struct elf_link_hash_entry *hash,
+			      const Elf_Internal_Rela *rel,
+			      struct elf64_aarch64_link_hash_table *htab)
+{
+  struct elf64_aarch64_stub_hash_entry *stub_entry;
+  struct elf64_aarch64_link_hash_entry *h =
+    (struct elf64_aarch64_link_hash_entry *) hash;
+  const asection *id_sec;
+
+  if ((input_section->flags & SEC_CODE) == 0)
+    return NULL;
+
+  /* If this input section is part of a group of sections sharing one
+     stub section, then use the id of the first section in the group.
+     Stub names need to include a section id, as there may well be
+     more than one stub used to reach say, printf, and we need to
+     distinguish between them.  */
+  id_sec = htab->stub_group[input_section->id].link_sec;
+
+  if (h != NULL && h->stub_cache != NULL
+      && h->stub_cache->h == h && h->stub_cache->id_sec == id_sec)
+    {
+      stub_entry = h->stub_cache;
+    }
+  else
+    {
+      char *stub_name;
+
+      stub_name = elf64_aarch64_stub_name (id_sec, sym_sec, h, rel);
+      if (stub_name == NULL)
+	return NULL;
+
+      stub_entry = aarch64_stub_hash_lookup (&htab->stub_hash_table,
+					     stub_name, FALSE, FALSE);
+      if (h != NULL)
+	h->stub_cache = stub_entry;
+
+      free (stub_name);
+    }
+
+  return stub_entry;
+}
+
+/* Add a new stub entry to the stub hash.  Not all fields of the new
+   stub entry are initialised.  */
+
+static struct elf64_aarch64_stub_hash_entry *
+elf64_aarch64_add_stub (const char *stub_name,
+			asection *section,
+			struct elf64_aarch64_link_hash_table *htab)
+{
+  asection *link_sec;
+  asection *stub_sec;
+  struct elf64_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;
+    }
+
+  /* Enter this entry into the linker stub hash table.  */
+  stub_entry = aarch64_stub_hash_lookup (&htab->stub_hash_table, stub_name,
+					 TRUE, FALSE);
+  if (stub_entry == NULL)
+    {
+      (*_bfd_error_handler) (_("%s: cannot create stub entry %s"),
+			     section->owner, stub_name);
+      return NULL;
+    }
+
+  stub_entry->stub_sec = stub_sec;
+  stub_entry->stub_offset = 0;
+  stub_entry->id_sec = link_sec;
+
+  return stub_entry;
+}
+
+static bfd_boolean
+aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
+			void *in_arg ATTRIBUTE_UNUSED)
+{
+  struct elf64_aarch64_stub_hash_entry *stub_entry;
+  asection *stub_sec;
+  bfd *stub_bfd;
+  bfd_byte *loc;
+  bfd_vma sym_value;
+  unsigned int template_size;
+  const uint32_t *template;
+  unsigned int i;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf64_aarch64_stub_hash_entry *) gen_entry;
+
+  stub_sec = stub_entry->stub_sec;
+
+  /* Make a note of the offset within the stubs for this entry.  */
+  stub_entry->stub_offset = stub_sec->size;
+  loc = stub_sec->contents + stub_entry->stub_offset;
+
+  stub_bfd = stub_sec->owner;
+
+  /* This is the address of the stub destination.  */
+  sym_value = (stub_entry->target_value
+	       + stub_entry->target_section->output_offset
+	       + stub_entry->target_section->output_section->vma);
+
+  if (stub_entry->stub_type == aarch64_stub_long_branch)
+    {
+      bfd_vma place = (stub_entry->stub_offset + stub_sec->output_section->vma
+		       + stub_sec->output_offset);
+
+      /* See if we can relax the stub.  */
+      if (aarch64_valid_for_adrp_p (sym_value, place))
+	stub_entry->stub_type = aarch64_select_branch_stub (sym_value, place);
+    }
+
+  switch (stub_entry->stub_type)
+    {
+    case aarch64_stub_adrp_branch:
+      template = aarch64_adrp_branch_stub;
+      template_size = sizeof (aarch64_adrp_branch_stub);
+      break;
+    case aarch64_stub_long_branch:
+      template = aarch64_long_branch_stub;
+      template_size = sizeof (aarch64_long_branch_stub);
+      break;
+    default:
+      BFD_FAIL ();
+      return FALSE;
+    }
+
+  for (i = 0; i < (template_size / sizeof template[0]); i++)
+    {
+      bfd_putl32 (template[i], loc);
+      loc += 4;
+    }
+
+  template_size = (template_size + 7) & ~7;
+  stub_sec->size += template_size;
+
+  switch (stub_entry->stub_type)
+    {
+    case aarch64_stub_adrp_branch:
+      if (aarch64_relocate (R_AARCH64_ADR_PREL_PG_HI21, stub_bfd, stub_sec,
+			    stub_entry->stub_offset, sym_value))
+	/* The stub would not have been relaxed if the offset was out
+	   of range.  */
+	BFD_FAIL ();
+
+      _bfd_final_link_relocate
+	(elf64_aarch64_howto_from_type (R_AARCH64_ADD_ABS_LO12_NC),
+	 stub_bfd,
+	 stub_sec,
+	 stub_sec->contents,
+	 stub_entry->stub_offset + 4,
+	 sym_value,
+	 0);
+      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 (elf64_aarch64_howto_from_type
+				(R_AARCH64_PREL64), stub_bfd, stub_sec,
+				stub_sec->contents,
+				stub_entry->stub_offset + 16,
+				sym_value + 12, 0);
+      break;
+    default:
+      break;
+    }
+
+  return TRUE;
+}
+
+/* As above, but don't actually build the stub.  Just bump offset so
+   we know stub section sizes.  */
+
+static bfd_boolean
+aarch64_size_one_stub (struct bfd_hash_entry *gen_entry,
+		       void *in_arg ATTRIBUTE_UNUSED)
+{
+  struct elf64_aarch64_stub_hash_entry *stub_entry;
+  int size;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf64_aarch64_stub_hash_entry *) gen_entry;
+
+  switch (stub_entry->stub_type)
+    {
+    case aarch64_stub_adrp_branch:
+      size = sizeof (aarch64_adrp_branch_stub);
+      break;
+    case aarch64_stub_long_branch:
+      size = sizeof (aarch64_long_branch_stub);
+      break;
+    default:
+      BFD_FAIL ();
+      return FALSE;
+      break;
+    }
+
+  size = (size + 7) & ~7;
+  stub_entry->stub_sec->size += size;
+  return TRUE;
+}
+
+/* External entry points for sizing and building linker stubs.  */
+
+/* Set up various things so that we can make a list of input sections
+   for each output section included in the link.  Returns -1 on error,
+   0 when no stubs will be needed, and 1 on success.  */
+
+int
+elf64_aarch64_setup_section_lists (bfd *output_bfd,
+				   struct bfd_link_info *info)
+{
+  bfd *input_bfd;
+  unsigned int bfd_count;
+  int top_id, top_index;
+  asection *section;
+  asection **input_list, **list;
+  bfd_size_type amt;
+  struct elf64_aarch64_link_hash_table *htab =
+    elf64_aarch64_hash_table (info);
+
+  if (!is_elf_hash_table (htab))
+    return 0;
+
+  /* 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)
+    {
+      bfd_count += 1;
+      for (section = input_bfd->sections;
+	   section != NULL; section = section->next)
+	{
+	  if (top_id < section->id)
+	    top_id = section->id;
+	}
+    }
+  htab->bfd_count = bfd_count;
+
+  amt = sizeof (struct map_stub) * (top_id + 1);
+  htab->stub_group = bfd_zmalloc (amt);
+  if (htab->stub_group == NULL)
+    return -1;
+
+  /* We can't use output_bfd->section_count here to find the top output
+     section index as some sections may have been removed, and
+     _bfd_strip_section_from_output doesn't renumber the indices.  */
+  for (section = output_bfd->sections, top_index = 0;
+       section != NULL; section = section->next)
+    {
+      if (top_index < section->index)
+	top_index = section->index;
+    }
+
+  htab->top_index = top_index;
+  amt = sizeof (asection *) * (top_index + 1);
+  input_list = bfd_malloc (amt);
+  htab->input_list = input_list;
+  if (input_list == NULL)
+    return -1;
+
+  /* For sections we aren't interested in, mark their entries with a
+     value we can check later.  */
+  list = input_list + top_index;
+  do
+    *list = bfd_abs_section_ptr;
+  while (list-- != input_list);
+
+  for (section = output_bfd->sections;
+       section != NULL; section = section->next)
+    {
+      if ((section->flags & SEC_CODE) != 0)
+	input_list[section->index] = NULL;
+    }
+
+  return 1;
+}
+
+/* Used by elf64_aarch64_next_input_section and group_sections.  */
+#define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec)
+
+/* The linker repeatedly calls this function for each input section,
+   in the order that input sections are linked into output sections.
+   Build lists of input sections to determine groupings between which
+   we may insert linker stubs.  */
+
+void
+elf64_aarch64_next_input_section (struct bfd_link_info *info, asection *isec)
+{
+  struct elf64_aarch64_link_hash_table *htab =
+    elf64_aarch64_hash_table (info);
+
+  if (isec->output_section->index <= htab->top_index)
+    {
+      asection **list = htab->input_list + isec->output_section->index;
+
+      if (*list != bfd_abs_section_ptr)
+	{
+	  /* Steal the link_sec pointer for our list.  */
+	  /* This happens to make the list in reverse order,
+	     which is what we want.  */
+	  PREV_SEC (isec) = *list;
+	  *list = isec;
+	}
+    }
+}
+
+/* See whether we can group stub sections together.  Grouping stub
+   sections may result in fewer stubs.  More importantly, we need to
+   put all .init* and .fini* stubs at the beginning of the .init or
+   .fini output sections respectively, because glibc splits the
+   _init and _fini functions into multiple parts.  Putting a stub in
+   the middle of a function is not a good idea.  */
+
+static void
+group_sections (struct elf64_aarch64_link_hash_table *htab,
+		bfd_size_type stub_group_size,
+		bfd_boolean stubs_always_before_branch)
+{
+  asection **list = htab->input_list + htab->top_index;
+
+  do
+    {
+      asection *tail = *list;
+
+      if (tail == bfd_abs_section_ptr)
+	continue;
+
+      while (tail != NULL)
+	{
+	  asection *curr;
+	  asection *prev;
+	  bfd_size_type total;
+
+	  curr = tail;
+	  total = tail->size;
+	  while ((prev = PREV_SEC (curr)) != NULL
+		 && ((total += curr->output_offset - prev->output_offset)
+		     < stub_group_size))
+	    curr = prev;
+
+	  /* OK, the size from the start of CURR to the end is less
+	     than stub_group_size and thus can be handled by one stub
+	     section.  (Or the tail 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);
+	      /* Set up this stub group.  */
+	      htab->stub_group[tail->id].link_sec = curr;
+	    }
+	  while (tail != curr && (tail = prev) != 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)
+	    {
+	      total = 0;
+	      while (prev != NULL
+		     && ((total += tail->output_offset - prev->output_offset)
+			 < stub_group_size))
+		{
+		  tail = prev;
+		  prev = PREV_SEC (tail);
+		  htab->stub_group[tail->id].link_sec = curr;
+		}
+	    }
+	  tail = prev;
+	}
+    }
+  while (list-- != htab->input_list);
+
+  free (htab->input_list);
+}
+
+#undef PREV_SEC
+
+/* Determine and set the size of the stub section for a final link.
+
+   The basic idea here is to examine all the relocations looking for
+   PC-relative calls to a target that is unreachable with a "bl"
+   instruction.  */
+
+bfd_boolean
+elf64_aarch64_size_stubs (bfd *output_bfd,
+			  bfd *stub_bfd,
+			  struct bfd_link_info *info,
+			  bfd_signed_vma group_size,
+			  asection * (*add_stub_section) (const char *,
+							  asection *),
+			  void (*layout_sections_again) (void))
+{
+  bfd_size_type stub_group_size;
+  bfd_boolean stubs_always_before_branch;
+  bfd_boolean stub_changed = 0;
+  struct elf64_aarch64_link_hash_table *htab = elf64_aarch64_hash_table (info);
+
+  /* Propagate mach to stub bfd, because it may not have been
+     finalized when we created stub_bfd.  */
+  bfd_set_arch_mach (stub_bfd, bfd_get_arch (output_bfd),
+		     bfd_get_mach (output_bfd));
+
+  /* Stash our params away.  */
+  htab->stub_bfd = stub_bfd;
+  htab->add_stub_section = add_stub_section;
+  htab->layout_sections_again = layout_sections_again;
+  stubs_always_before_branch = group_size < 0;
+  if (group_size < 0)
+    stub_group_size = -group_size;
+  else
+    stub_group_size = group_size;
+
+  if (stub_group_size == 1)
+    {
+      /* Default values.  */
+      /* Aarch64 branch range is +-128MB. The value used is 1MB less. */
+      stub_group_size = 127 * 1024 * 1024;
+    }
+
+  group_sections (htab, stub_group_size, stubs_always_before_branch);
+
+  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++)
+	{
+	  Elf_Internal_Shdr *symtab_hdr;
+	  asection *section;
+	  Elf_Internal_Sym *local_syms = NULL;
+
+	  /* We'll need the symbol table in a second.  */
+	  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+	  if (symtab_hdr->sh_info == 0)
+	    continue;
+
+	  /* Walk over each section attached to the input bfd.  */
+	  for (section = input_bfd->sections;
+	       section != NULL; section = section->next)
+	    {
+	      Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
+
+	      /* If there aren't any relocs, then there's nothing more
+		 to do.  */
+	      if ((section->flags & SEC_RELOC) == 0
+		  || section->reloc_count == 0
+		  || (section->flags & SEC_CODE) == 0)
+		continue;
+
+	      /* If this section is a link-once section that will be
+		 discarded, then don't create any stubs.  */
+	      if (section->output_section == NULL
+		  || section->output_section->owner != output_bfd)
+		continue;
+
+	      /* Get the relocs.  */
+	      internal_relocs
+		= _bfd_elf_link_read_relocs (input_bfd, section, NULL,
+					     NULL, info->keep_memory);
+	      if (internal_relocs == NULL)
+		goto error_ret_free_local;
+
+	      /* Now examine each relocation.  */
+	      irela = internal_relocs;
+	      irelaend = irela + section->reloc_count;
+	      for (; irela < irelaend; irela++)
+		{
+		  unsigned int r_type, r_indx;
+		  enum elf64_aarch64_stub_type stub_type;
+		  struct elf64_aarch64_stub_hash_entry *stub_entry;
+		  asection *sym_sec;
+		  bfd_vma sym_value;
+		  bfd_vma destination;
+		  struct elf64_aarch64_link_hash_entry *hash;
+		  const char *sym_name;
+		  char *stub_name;
+		  const asection *id_sec;
+		  unsigned char st_type;
+		  bfd_size_type len;
+
+		  r_type = ELF64_R_TYPE (irela->r_info);
+		  r_indx = ELF64_R_SYM (irela->r_info);
+
+		  if (r_type >= (unsigned int) R_AARCH64_end)
+		    {
+		      bfd_set_error (bfd_error_bad_value);
+		    error_ret_free_internal:
+		      if (elf_section_data (section)->relocs == NULL)
+			free (internal_relocs);
+		      goto error_ret_free_local;
+		    }
+
+		  /* Only look for stubs on unconditional branch and
+		     branch and link instructions.  */
+		  if (r_type != (unsigned int) R_AARCH64_CALL26
+		      && r_type != (unsigned int) R_AARCH64_JUMP26)
+		    continue;
+
+		  /* Now determine the call target, its name, value,
+		     section.  */
+		  sym_sec = NULL;
+		  sym_value = 0;
+		  destination = 0;
+		  hash = NULL;
+		  sym_name = NULL;
+		  if (r_indx < symtab_hdr->sh_info)
+		    {
+		      /* It's a local symbol.  */
+		      Elf_Internal_Sym *sym;
+		      Elf_Internal_Shdr *hdr;
+
+		      if (local_syms == NULL)
+			{
+			  local_syms
+			    = (Elf_Internal_Sym *) symtab_hdr->contents;
+			  if (local_syms == NULL)
+			    local_syms
+			      = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+						      symtab_hdr->sh_info, 0,
+						      NULL, NULL, NULL);
+			  if (local_syms == NULL)
+			    goto error_ret_free_internal;
+			}
+
+		      sym = local_syms + r_indx;
+		      hdr = elf_elfsections (input_bfd)[sym->st_shndx];
+		      sym_sec = hdr->bfd_section;
+		      if (!sym_sec)
+			/* This is an undefined symbol.  It can never
+			   be resolved. */
+			continue;
+
+		      if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
+			sym_value = sym->st_value;
+		      destination = (sym_value + irela->r_addend
+				     + sym_sec->output_offset
+				     + sym_sec->output_section->vma);
+		      st_type = ELF_ST_TYPE (sym->st_info);
+		      sym_name
+			= bfd_elf_string_from_elf_section (input_bfd,
+							   symtab_hdr->sh_link,
+							   sym->st_name);
+		    }
+		  else
+		    {
+		      int e_indx;
+
+		      e_indx = r_indx - symtab_hdr->sh_info;
+		      hash = ((struct elf64_aarch64_link_hash_entry *)
+			      elf_sym_hashes (input_bfd)[e_indx]);
+
+		      while (hash->root.root.type == bfd_link_hash_indirect
+			     || hash->root.root.type == bfd_link_hash_warning)
+			hash = ((struct elf64_aarch64_link_hash_entry *)
+				hash->root.root.u.i.link);
+
+		      if (hash->root.root.type == bfd_link_hash_defined
+			  || hash->root.root.type == bfd_link_hash_defweak)
+			{
+			  struct elf64_aarch64_link_hash_table *globals =
+			    elf64_aarch64_hash_table (info);
+			  sym_sec = hash->root.root.u.def.section;
+			  sym_value = hash->root.root.u.def.value;
+			  /* For a destination in a shared library,
+			     use the PLT stub as target address to
+			     decide whether a branch stub is
+			     needed.  */
+			  if (globals->root.splt != NULL && hash != NULL
+			      && hash->root.plt.offset != (bfd_vma) - 1)
+			    {
+			      sym_sec = globals->root.splt;
+			      sym_value = hash->root.plt.offset;
+			      if (sym_sec->output_section != NULL)
+				destination = (sym_value
+					       + sym_sec->output_offset
+					       +
+					       sym_sec->output_section->vma);
+			    }
+			  else if (sym_sec->output_section != NULL)
+			    destination = (sym_value + irela->r_addend
+					   + sym_sec->output_offset
+					   + sym_sec->output_section->vma);
+			}
+		      else if (hash->root.root.type == bfd_link_hash_undefined
+			       || (hash->root.root.type
+				   == bfd_link_hash_undefweak))
+			{
+			  /* For a shared library, use the PLT stub as
+			     target address to decide whether a long
+			     branch stub is needed.
+			     For absolute code, they cannot be handled.  */
+			  struct elf64_aarch64_link_hash_table *globals =
+			    elf64_aarch64_hash_table (info);
+
+			  if (globals->root.splt != NULL && hash != NULL
+			      && hash->root.plt.offset != (bfd_vma) - 1)
+			    {
+			      sym_sec = globals->root.splt;
+			      sym_value = hash->root.plt.offset;
+			      if (sym_sec->output_section != NULL)
+				destination = (sym_value
+					       + sym_sec->output_offset
+					       +
+					       sym_sec->output_section->vma);
+			    }
+			  else
+			    continue;
+			}
+		      else
+			{
+			  bfd_set_error (bfd_error_bad_value);
+			  goto error_ret_free_internal;
+			}
+		      st_type = ELF_ST_TYPE (hash->root.type);
+		      sym_name = hash->root.root.root.string;
+		    }
+
+		  /* Determine what (if any) linker stub is needed.  */
+		  stub_type = aarch64_type_of_stub
+		    (info, section, irela, st_type, hash, destination);
+		  if (stub_type == aarch64_stub_none)
+		    continue;
+
+		  /* Support for grouping stub sections.  */
+		  id_sec = htab->stub_group[section->id].link_sec;
+
+		  /* Get the name of this stub.  */
+		  stub_name = elf64_aarch64_stub_name (id_sec, sym_sec, hash,
+						       irela);
+		  if (!stub_name)
+		    goto error_ret_free_internal;
+
+		  stub_entry =
+		    aarch64_stub_hash_lookup (&htab->stub_hash_table,
+					      stub_name, FALSE, FALSE);
+		  if (stub_entry != NULL)
+		    {
+		      /* The proper stub has already been created.  */
+		      free (stub_name);
+		      continue;
+		    }
+
+		  stub_entry = elf64_aarch64_add_stub (stub_name, section,
+						       htab);
+		  if (stub_entry == NULL)
+		    {
+		      free (stub_name);
+		      goto error_ret_free_internal;
+		    }
+
+		  stub_entry->target_value = sym_value;
+		  stub_entry->target_section = sym_sec;
+		  stub_entry->stub_type = stub_type;
+		  stub_entry->h = hash;
+		  stub_entry->st_type = st_type;
+
+		  if (sym_name == NULL)
+		    sym_name = "unnamed";
+		  len = sizeof (STUB_ENTRY_NAME) + strlen (sym_name);
+		  stub_entry->output_name = bfd_alloc (htab->stub_bfd, len);
+		  if (stub_entry->output_name == NULL)
+		    {
+		      free (stub_name);
+		      goto error_ret_free_internal;
+		    }
+
+		  snprintf (stub_entry->output_name, len, STUB_ENTRY_NAME,
+			    sym_name);
+
+		  stub_changed = TRUE;
+		}
+
+	      /* We're done with the internal relocs, free them.  */
+	      if (elf_section_data (section)->relocs == NULL)
+		free (internal_relocs);
+	    }
+	}
+
+      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);
+
+      /* Ask the linker to do its stuff.  */
+      (*htab->layout_sections_again) ();
+      stub_changed = FALSE;
+    }
+
+  return TRUE;
+
+error_ret_free_local:
+  return FALSE;
+}
+
+/* Build all the stubs associated with the current output file.  The
+   stubs are kept in a hash table attached to the main linker hash
+   table.  We also set up the .plt entries for statically linked PIC
+   functions here.  This function is called via aarch64_elf_finish in the
+   linker.  */
+
+bfd_boolean
+elf64_aarch64_build_stubs (struct bfd_link_info *info)
+{
+  asection *stub_sec;
+  struct bfd_hash_table *table;
+  struct elf64_aarch64_link_hash_table *htab;
+
+  htab = elf64_aarch64_hash_table (info);
+
+  for (stub_sec = htab->stub_bfd->sections;
+       stub_sec != NULL; stub_sec = stub_sec->next)
+    {
+      bfd_size_type size;
+
+      /* Ignore non-stub sections.  */
+      if (!strstr (stub_sec->name, STUB_SUFFIX))
+	continue;
+
+      /* Allocate memory to hold the linker stubs.  */
+      size = stub_sec->size;
+      stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
+      if (stub_sec->contents == NULL && size != 0)
+	return FALSE;
+      stub_sec->size = 0;
+    }
+
+  /* Build the stubs as directed by the stub hash table.  */
+  table = &htab->stub_hash_table;
+  bfd_hash_traverse (table, aarch64_build_one_stub, info);
+
+  return TRUE;
+}
+
+
+/* Add an entry to the code/data map for section SEC.  */
+
+static void
+elf64_aarch64_section_map_add (asection *sec, char type, bfd_vma vma)
+{
+  struct _aarch64_elf_section_data *sec_data =
+    elf64_aarch64_section_data (sec);
+  unsigned int newidx;
+
+  if (sec_data->map == NULL)
+    {
+      sec_data->map = bfd_malloc (sizeof (elf64_aarch64_section_map));
+      sec_data->mapcount = 0;
+      sec_data->mapsize = 1;
+    }
+
+  newidx = sec_data->mapcount++;
+
+  if (sec_data->mapcount > sec_data->mapsize)
+    {
+      sec_data->mapsize *= 2;
+      sec_data->map = bfd_realloc_or_free
+	(sec_data->map, sec_data->mapsize * sizeof (elf64_aarch64_section_map));
+    }
+
+  if (sec_data->map)
+    {
+      sec_data->map[newidx].vma = vma;
+      sec_data->map[newidx].type = type;
+    }
+}
+
+
+/* Initialise maps of insn/data for input BFDs.  */
+void
+bfd_elf64_aarch64_init_maps (bfd *abfd)
+{
+  Elf_Internal_Sym *isymbuf;
+  Elf_Internal_Shdr *hdr;
+  unsigned int i, localsyms;
+
+  /* Make sure that we are dealing with an AArch64 elf binary.  */
+  if (!is_aarch64_elf (abfd))
+    return;
+
+  if ((abfd->flags & DYNAMIC) != 0)
+    return;
+
+  hdr = &elf_symtab_hdr (abfd);
+  localsyms = hdr->sh_info;
+
+  /* Obtain a buffer full of symbols for this BFD. The hdr->sh_info field
+     should contain the number of local symbols, which should come before any
+     global symbols.  Mapping symbols are always local.  */
+  isymbuf = bfd_elf_get_elf_syms (abfd, hdr, localsyms, 0, NULL, NULL, NULL);
+
+  /* No internal symbols read?  Skip this BFD.  */
+  if (isymbuf == NULL)
+    return;
+
+  for (i = 0; i < localsyms; i++)
+    {
+      Elf_Internal_Sym *isym = &isymbuf[i];
+      asection *sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+      const char *name;
+
+      if (sec != NULL && ELF_ST_BIND (isym->st_info) == STB_LOCAL)
+	{
+	  name = bfd_elf_string_from_elf_section (abfd,
+						  hdr->sh_link,
+						  isym->st_name);
+
+	  if (bfd_is_aarch64_special_symbol_name
+	      (name, BFD_AARCH64_SPECIAL_SYM_TYPE_MAP))
+	    elf64_aarch64_section_map_add (sec, name[1], isym->st_value);
+	}
+    }
+}
+
+/* Set option values needed during linking.  */
+void
+bfd_elf64_aarch64_set_options (struct bfd *output_bfd,
+			       struct bfd_link_info *link_info,
+			       int no_enum_warn,
+			       int no_wchar_warn, int pic_veneer)
+{
+  struct elf64_aarch64_link_hash_table *globals;
+
+  globals = elf64_aarch64_hash_table (link_info);
+  globals->pic_veneer = pic_veneer;
+
+  BFD_ASSERT (is_aarch64_elf (output_bfd));
+  elf_aarch64_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
+  elf_aarch64_tdata (output_bfd)->no_wchar_size_warning = no_wchar_warn;
+}
+
+#define MASK(n) ((1u << (n)) - 1)
+
+/* Decode the 26-bit offset of unconditional branch.  */
+static inline uint32_t
+decode_branch_ofs_26 (uint32_t insn)
+{
+  return insn & MASK (26);
+}
+
+/* Decode the 19-bit offset of conditional branch and compare & branch.  */
+static inline uint32_t
+decode_cond_branch_ofs_19 (uint32_t insn)
+{
+  return (insn >> 5) & MASK (19);
+}
+
+/* Decode the 19-bit offset of load literal.  */
+static inline uint32_t
+decode_ld_lit_ofs_19 (uint32_t insn)
+{
+  return (insn >> 5) & MASK (19);
+}
+
+/* Decode the 14-bit offset of test & branch.  */
+static inline uint32_t
+decode_tst_branch_ofs_14 (uint32_t insn)
+{
+  return (insn >> 5) & MASK (14);
+}
+
+/* Decode the 16-bit imm of move wide.  */
+static inline uint32_t
+decode_movw_imm (uint32_t insn)
+{
+  return (insn >> 5) & MASK (16);
+}
+
+/* Decode the 21-bit imm of adr.  */
+static inline uint32_t
+decode_adr_imm (uint32_t insn)
+{
+  return ((insn >> 29) & MASK (2)) | ((insn >> 3) & (MASK (19) << 2));
+}
+
+/* Decode the 12-bit imm of add immediate.  */
+static inline uint32_t
+decode_add_imm (uint32_t insn)
+{
+  return (insn >> 10) & MASK (12);
+}
+
+
+/* Encode the 26-bit offset of unconditional branch.  */
+static inline uint32_t
+reencode_branch_ofs_26 (uint32_t insn, uint32_t ofs)
+{
+  return (insn & ~MASK (26)) | (ofs & MASK (26));
+}
+
+/* Encode the 19-bit offset of conditional branch and compare & branch.  */
+static inline uint32_t
+reencode_cond_branch_ofs_19 (uint32_t insn, uint32_t ofs)
+{
+  return (insn & ~(MASK (19) << 5)) | ((ofs & MASK (19)) << 5);
+}
+
+/* Decode the 19-bit offset of load literal.  */
+static inline uint32_t
+reencode_ld_lit_ofs_19 (uint32_t insn, uint32_t ofs)
+{
+  return (insn & ~(MASK (19) << 5)) | ((ofs & MASK (19)) << 5);
+}
+
+/* Encode the 14-bit offset of test & branch. */
+static inline uint32_t
+reencode_tst_branch_ofs_14 (uint32_t insn, uint32_t ofs)
+{
+  return (insn & ~(MASK (14) << 5)) | ((ofs & MASK (14)) << 5);
+}
+
+/* Reencode the imm field of move wide. */
+static inline uint32_t
+reencode_movw_imm (uint32_t insn, uint32_t imm)
+{
+  return (insn & ~(MASK (16) << 5)) | ((imm & MASK (16)) << 5);
+}
+
+/* Reencode the imm field of adr.  */
+static inline uint32_t
+reencode_adr_imm (uint32_t insn, uint32_t imm)
+{
+  return (insn & ~((MASK (2) << 29) | (MASK (19) << 5)))
+    | ((imm & MASK (2)) << 29) | ((imm & (MASK (19) << 2)) << 3);
+}
+
+/* Reencode the imm field of ld/st pos immediate.  */
+static inline uint32_t
+reencode_ldst_pos_imm (uint32_t insn, uint32_t imm)
+{
+  return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10);
+}
+
+/* Reencode the imm field of add immediate. */
+static inline uint32_t
+reencode_add_imm (uint32_t insn, uint32_t imm)
+{
+  return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10);
+}
+
+/* Reencode mov[zn] to movz.  */
+static inline uint32_t
+reencode_movzn_to_movz (uint32_t opcode)
+{
+  return opcode | (1 << 30);
+}
+
+/* Reencode mov[zn] to movn. */
+static inline uint32_t
+reencode_movzn_to_movn (uint32_t opcode)
+{
+  return opcode & ~(1 << 30);
+}
+
+/* Insert the addend/value into the instruction or data object being
+   relocated.  */
+static bfd_reloc_status_type
+bfd_elf_aarch64_put_addend (bfd *abfd,
+			    bfd_byte *address,
+			    reloc_howto_type *howto, bfd_signed_vma addend)
+{
+  bfd_reloc_status_type status = bfd_reloc_ok;
+  bfd_signed_vma old_addend = addend;
+  bfd_vma contents;
+  int size;
+
+  size = bfd_get_reloc_size (howto);
+  switch (size)
+    {
+    case 2:
+      contents = bfd_get_16 (abfd, address);
+      break;
+    case 4:
+      if (howto->src_mask != 0xffffffff)
+	/* Must be 32-bit instruction, always little-endian.  */
+	contents = bfd_getl32 (address);
+      else
+	/* Must be 32-bit data (endianness dependent).  */
+	contents = bfd_get_32 (abfd, address);
+      break;
+    case 8:
+      contents = bfd_get_64 (abfd, address);
+      break;
+    default:
+      abort ();
+    }
+
+  switch (howto->complain_on_overflow)
+    {
+    case complain_overflow_dont:
+      break;
+    case complain_overflow_signed:
+      status = aarch64_signed_overflow (addend,
+					howto->bitsize + howto->rightshift);
+      break;
+    case complain_overflow_unsigned:
+      status = aarch64_unsigned_overflow (addend,
+					  howto->bitsize + howto->rightshift);
+      break;
+    case complain_overflow_bitfield:
+    default:
+      abort ();
+    }
+
+  addend >>= howto->rightshift;
+
+  switch (howto->type)
+    {
+    case R_AARCH64_JUMP26:
+    case R_AARCH64_CALL26:
+      contents = reencode_branch_ofs_26 (contents, addend);
+      break;
+
+    case R_AARCH64_CONDBR19:
+      contents = reencode_cond_branch_ofs_19 (contents, addend);
+      break;
+
+    case R_AARCH64_TSTBR14:
+      contents = reencode_tst_branch_ofs_14 (contents, addend);
+      break;
+
+    case R_AARCH64_LD_PREL_LO19:
+      if (old_addend & ((1 << howto->rightshift) - 1))
+	return bfd_reloc_overflow;
+      contents = reencode_ld_lit_ofs_19 (contents, addend);
+      break;
+
+    case R_AARCH64_TLSDESC_CALL:
+      break;
+
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+    case R_AARCH64_ADR_GOT_PAGE:
+    case R_AARCH64_ADR_PREL_LO21:
+    case R_AARCH64_ADR_PREL_PG_HI21:
+    case R_AARCH64_ADR_PREL_PG_HI21_NC:
+      contents = reencode_adr_imm (contents, addend);
+      break;
+
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+    case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_ADD_ABS_LO12_NC:
+      /* Corresponds to: add rd, rn, #uimm12 to provide the low order
+         12 bits of the page offset following
+         R_AARCH64_ADR_PREL_PG_HI21 which computes the
+         (pc-relative) page base.  */
+      contents = reencode_add_imm (contents, addend);
+      break;
+
+    case R_AARCH64_LDST8_ABS_LO12_NC:
+    case R_AARCH64_LDST16_ABS_LO12_NC:
+    case R_AARCH64_LDST32_ABS_LO12_NC:
+    case R_AARCH64_LDST64_ABS_LO12_NC:
+    case R_AARCH64_LDST128_ABS_LO12_NC:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+    case R_AARCH64_LD64_GOT_LO12_NC:
+      if (old_addend & ((1 << howto->rightshift) - 1))
+	return bfd_reloc_overflow;
+      /* Used for ldr*|str* rt, [rn, #uimm12] to provide the low order
+         12 bits of the page offset following R_AARCH64_ADR_PREL_PG_HI21
+         which computes the (pc-relative) page base. */
+      contents = reencode_ldst_pos_imm (contents, addend);
+      break;
+
+      /* Group relocations to create high bits of a 16, 32, 48 or 64
+         bit signed data or abs address inline. Will change
+         instruction to MOVN or MOVZ depending on sign of calculated
+         value. */
+
+    case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+    case R_AARCH64_MOVW_SABS_G0:
+    case R_AARCH64_MOVW_SABS_G1:
+    case R_AARCH64_MOVW_SABS_G2:
+      /* NOTE: We can only come here with movz or movn. */
+      if (addend < 0)
+	{
+	  /* Force use of MOVN.  */
+	  addend = ~addend;
+	  contents = reencode_movzn_to_movn (contents);
+	}
+      else
+	{
+	  /* Force use of MOVZ.  */
+	  contents = reencode_movzn_to_movz (contents);
+	}
+      /* fall through */
+
+      /* Group relocations to create a 16, 32, 48 or 64 bit unsigned
+         data or abs address inline. */
+
+    case R_AARCH64_MOVW_UABS_G0:
+    case R_AARCH64_MOVW_UABS_G0_NC:
+    case R_AARCH64_MOVW_UABS_G1:
+    case R_AARCH64_MOVW_UABS_G1_NC:
+    case R_AARCH64_MOVW_UABS_G2:
+    case R_AARCH64_MOVW_UABS_G2_NC:
+    case R_AARCH64_MOVW_UABS_G3:
+      contents = reencode_movw_imm (contents, addend);
+      break;
+
+    default:
+      /* Repack simple data */
+      if (howto->dst_mask & (howto->dst_mask + 1))
+	return bfd_reloc_notsupported;
+
+      contents = ((contents & ~howto->dst_mask) | (addend & howto->dst_mask));
+      break;
+    }
+
+  switch (size)
+    {
+    case 2:
+      bfd_put_16 (abfd, contents, address);
+      break;
+    case 4:
+      if (howto->dst_mask != 0xffffffff)
+	/* must be 32-bit instruction, always little-endian */
+	bfd_putl32 (contents, address);
+      else
+	/* must be 32-bit data (endianness dependent) */
+	bfd_put_32 (abfd, contents, address);
+      break;
+    case 8:
+      bfd_put_64 (abfd, contents, address);
+      break;
+    default:
+      abort ();
+    }
+
+  return status;
+}
+
+static bfd_vma
+aarch64_calculate_got_entry_vma (struct elf_link_hash_entry *h,
+				 struct elf64_aarch64_link_hash_table
+				 *globals, struct bfd_link_info *info,
+				 bfd_vma value, bfd *output_bfd,
+				 bfd_boolean *unresolved_reloc_p)
+{
+  bfd_vma off = (bfd_vma) - 1;
+  asection *basegot = globals->root.sgot;
+  bfd_boolean dyn = globals->root.dynamic_sections_created;
+
+  if (h != NULL)
+    {
+      off = h->got.offset;
+      BFD_ASSERT (off != (bfd_vma) - 1);
+      if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
+	  || (info->shared
+	      && SYMBOL_REFERENCES_LOCAL (info, h))
+	  || (ELF_ST_VISIBILITY (h->other)
+	      && h->root.type == bfd_link_hash_undefweak))
+	{
+	  /* This is actually a static link, or it is a -Bsymbolic link
+	     and the symbol is defined locally.  We must initialize this
+	     entry in the global offset table.  Since the offset must
+	     always be a multiple of 8, we use the least significant bit
+	     to record whether we have initialized it already.
+	     When doing a dynamic link, we create a .rel(a).got relocation
+	     entry to initialize the value.  This is done in the
+	     finish_dynamic_symbol routine.  */
+	  if ((off & 1) != 0)
+	    off &= ~1;
+	  else
+	    {
+	      bfd_put_64 (output_bfd, value, basegot->contents + off);
+	      h->got.offset |= 1;
+	    }
+	}
+      else
+	*unresolved_reloc_p = FALSE;
+
+      off = off + basegot->output_section->vma + basegot->output_offset;
+    }
+
+  return off;
+}
+
+/* Change R_TYPE to a more efficient access model where possible,
+   return the new reloc type.  */
+
+static unsigned int
+aarch64_tls_transition_without_check (unsigned int r_type,
+				      struct elf_link_hash_entry *h)
+{
+  bfd_boolean is_local = h == NULL;
+  switch (r_type)
+    {
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+      return is_local
+	? R_AARCH64_TLSLE_MOVW_TPREL_G1 : R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21;
+
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+      return is_local
+	? R_AARCH64_TLSLE_MOVW_TPREL_G0_NC
+	: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
+
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+      return is_local ? R_AARCH64_TLSLE_MOVW_TPREL_G1 : r_type;
+
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+      return is_local ? R_AARCH64_TLSLE_MOVW_TPREL_G0_NC : r_type;
+
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_CALL:
+      /* Instructions with these relocations will become NOPs.  */
+      return R_AARCH64_NONE;
+    }
+
+  return r_type;
+}
+
+static unsigned int
+aarch64_reloc_got_type (unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case R_AARCH64_LD64_GOT_LO12_NC:
+    case R_AARCH64_ADR_GOT_PAGE:
+      return GOT_NORMAL;
+
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+      return GOT_TLS_GD;
+
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+    case R_AARCH64_TLSDESC_CALL:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+      return GOT_TLSDESC_GD;
+
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+      return GOT_TLS_IE;
+
+    case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+      return GOT_UNKNOWN;
+    }
+  return GOT_UNKNOWN;
+}
+
+static bfd_boolean
+aarch64_can_relax_tls (bfd *input_bfd,
+		       struct bfd_link_info *info,
+		       unsigned int r_type,
+		       struct elf_link_hash_entry *h,
+		       unsigned long r_symndx)
+{
+  unsigned int symbol_got_type;
+  unsigned int reloc_got_type;
+
+  if (! IS_AARCH64_TLS_RELOC (r_type))
+    return FALSE;
+
+  symbol_got_type = elf64_aarch64_symbol_got_type (h, input_bfd, r_symndx);
+  reloc_got_type = aarch64_reloc_got_type (r_type);
+
+  if (symbol_got_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (reloc_got_type))
+    return TRUE;
+
+  if (info->shared)
+    return FALSE;
+
+  if  (h && h->root.type == bfd_link_hash_undefweak)
+    return FALSE;
+
+  return TRUE;
+}
+
+static unsigned int
+aarch64_tls_transition (bfd *input_bfd,
+			struct bfd_link_info *info,
+			unsigned int r_type,
+			struct elf_link_hash_entry *h,
+			unsigned long r_symndx)
+{
+  if (! aarch64_can_relax_tls (input_bfd, info, r_type, h, r_symndx))
+    return r_type;
+
+  return aarch64_tls_transition_without_check (r_type, h);
+}
+
+/* Return the base VMA address which should be subtracted from real addresses
+   when resolving R_AARCH64_TLS_DTPREL64 relocation. */
+
+static bfd_vma
+dtpoff_base (struct bfd_link_info *info)
+{
+  /* If tls_sec is NULL, we should have signalled an error already.  */
+  BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
+  return elf_hash_table (info)->tls_sec->vma;
+}
+
+
+/* Return the base VMA address which should be subtracted from real addresses
+   when resolving R_AARCH64_TLS_GOTTPREL64 relocations.  */
+
+static bfd_vma
+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_vma base = align_power ((bfd_vma) TCB_SIZE,
+			      htab->tls_sec->alignment_power);
+  return htab->tls_sec->vma - base;
+}
+
+static bfd_vma *
+symbol_got_offset_ref (bfd *input_bfd, struct elf_link_hash_entry *h,
+		       unsigned long r_symndx)
+{
+  /* Calculate the address of the GOT entry for symbol
+     referred to in h.  */
+  if (h != NULL)
+    return &h->got.offset;
+  else
+    {
+      /* local symbol */
+      struct elf_aarch64_local_symbol *l;
+
+      l = elf64_aarch64_locals (input_bfd);
+      return &l[r_symndx].got_offset;
+    }
+}
+
+static void
+symbol_got_offset_mark (bfd *input_bfd, struct elf_link_hash_entry *h,
+			unsigned long r_symndx)
+{
+  bfd_vma *p;
+  p = symbol_got_offset_ref (input_bfd, h, r_symndx);
+  *p |= 1;
+}
+
+static int
+symbol_got_offset_mark_p (bfd *input_bfd, struct elf_link_hash_entry *h,
+			  unsigned long r_symndx)
+{
+  bfd_vma value;
+  value = * symbol_got_offset_ref (input_bfd, h, r_symndx);
+  return value & 1;
+}
+
+static bfd_vma
+symbol_got_offset (bfd *input_bfd, struct elf_link_hash_entry *h,
+		   unsigned long r_symndx)
+{
+  bfd_vma value;
+  value = * symbol_got_offset_ref (input_bfd, h, r_symndx);
+  value &= ~1;
+  return value;
+}
+
+static bfd_vma *
+symbol_tlsdesc_got_offset_ref (bfd *input_bfd, struct elf_link_hash_entry *h,
+			       unsigned long r_symndx)
+{
+  /* Calculate the address of the GOT entry for symbol
+     referred to in h.  */
+  if (h != NULL)
+    {
+      struct elf64_aarch64_link_hash_entry *eh;
+      eh = (struct elf64_aarch64_link_hash_entry *) h;
+      return &eh->tlsdesc_got_jump_table_offset;
+    }
+  else
+    {
+      /* local symbol */
+      struct elf_aarch64_local_symbol *l;
+
+      l = elf64_aarch64_locals (input_bfd);
+      return &l[r_symndx].tlsdesc_got_jump_table_offset;
+    }
+}
+
+static void
+symbol_tlsdesc_got_offset_mark (bfd *input_bfd, struct elf_link_hash_entry *h,
+				unsigned long r_symndx)
+{
+  bfd_vma *p;
+  p = symbol_tlsdesc_got_offset_ref (input_bfd, h, r_symndx);
+  *p |= 1;
+}
+
+static int
+symbol_tlsdesc_got_offset_mark_p (bfd *input_bfd,
+				  struct elf_link_hash_entry *h,
+				  unsigned long r_symndx)
+{
+  bfd_vma value;
+  value = * symbol_tlsdesc_got_offset_ref (input_bfd, h, r_symndx);
+  return value & 1;
+}
+
+static bfd_vma
+symbol_tlsdesc_got_offset (bfd *input_bfd, struct elf_link_hash_entry *h,
+			  unsigned long r_symndx)
+{
+  bfd_vma value;
+  value = * symbol_tlsdesc_got_offset_ref (input_bfd, h, r_symndx);
+  value &= ~1;
+  return value;
+}
+
+/* Perform a relocation as part of a final link.  */
+static bfd_reloc_status_type
+elf64_aarch64_final_link_relocate (reloc_howto_type *howto,
+				   bfd *input_bfd,
+				   bfd *output_bfd,
+				   asection *input_section,
+				   bfd_byte *contents,
+				   Elf_Internal_Rela *rel,
+				   bfd_vma value,
+				   struct bfd_link_info *info,
+				   asection *sym_sec,
+				   struct elf_link_hash_entry *h,
+				   bfd_boolean *unresolved_reloc_p,
+				   bfd_boolean save_addend,
+				   bfd_vma *saved_addend)
+{
+  unsigned int r_type = howto->type;
+  unsigned long r_symndx;
+  bfd_byte *hit_data = contents + rel->r_offset;
+  bfd_vma place;
+  bfd_signed_vma signed_addend;
+  struct elf64_aarch64_link_hash_table *globals;
+  bfd_boolean weak_undef_p;
+
+  globals = elf64_aarch64_hash_table (info);
+
+  BFD_ASSERT (is_aarch64_elf (input_bfd));
+
+  r_symndx = ELF64_R_SYM (rel->r_info);
+
+  /* It is possible to have linker relaxations on some TLS access
+     models.  Update our information here.  */
+  r_type = aarch64_tls_transition (input_bfd, info, r_type, h, r_symndx);
+
+  if (r_type != howto->type)
+    howto = elf64_aarch64_howto_from_type (r_type);
+
+  place = input_section->output_section->vma
+    + input_section->output_offset + rel->r_offset;
+
+  /* Get addend, accumulating the addend for consecutive relocs
+     which refer to the same offset. */
+  signed_addend = saved_addend ? *saved_addend : 0;
+  signed_addend += rel->r_addend;
+
+  weak_undef_p = (h ? h->root.type == bfd_link_hash_undefweak
+		  : bfd_is_und_section (sym_sec));
+  switch (r_type)
+    {
+    case R_AARCH64_NONE:
+    case R_AARCH64_NULL:
+    case R_AARCH64_TLSDESC_CALL:
+      *unresolved_reloc_p = FALSE;
+      return bfd_reloc_ok;
+
+    case R_AARCH64_ABS64:
+
+      /* When generating a shared object or relocatable executable, these
+         relocations are copied into the output file to be resolved at
+         run time.  */
+      if (((info->shared == TRUE) || globals->root.is_relocatable_executable)
+	  && (input_section->flags & SEC_ALLOC)
+	  && (h == NULL
+	      || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+	      || h->root.type != bfd_link_hash_undefweak))
+	{
+	  Elf_Internal_Rela outrel;
+	  bfd_byte *loc;
+	  bfd_boolean skip, relocate;
+	  asection *sreloc;
+
+	  *unresolved_reloc_p = FALSE;
+
+	  sreloc = _bfd_elf_get_dynamic_reloc_section (input_bfd,
+						       input_section, 1);
+	  if (sreloc == NULL)
+	    return bfd_reloc_notsupported;
+
+	  skip = FALSE;
+	  relocate = FALSE;
+
+	  outrel.r_addend = signed_addend;
+	  outrel.r_offset =
+	    _bfd_elf_section_offset (output_bfd, info, input_section,
+				     rel->r_offset);
+	  if (outrel.r_offset == (bfd_vma) - 1)
+	    skip = TRUE;
+	  else if (outrel.r_offset == (bfd_vma) - 2)
+	    {
+	      skip = TRUE;
+	      relocate = TRUE;
+	    }
+
+	  outrel.r_offset += (input_section->output_section->vma
+			      + input_section->output_offset);
+
+	  if (skip)
+	    memset (&outrel, 0, sizeof outrel);
+	  else if (h != NULL
+		   && h->dynindx != -1
+		   && (!info->shared || !info->symbolic || !h->def_regular))
+	    outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
+	  else
+	    {
+	      int symbol;
+
+	      /* On SVR4-ish systems, the dynamic loader cannot
+		 relocate the text and data segments independently,
+		 so the symbol does not matter.  */
+	      symbol = 0;
+	      outrel.r_info = ELF64_R_INFO (symbol, R_AARCH64_RELATIVE);
+	      outrel.r_addend += value;
+	    }
+
+	  loc = sreloc->contents + sreloc->reloc_count++ * RELOC_SIZE (htab);
+	  bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+
+	  if (sreloc->reloc_count * RELOC_SIZE (htab) > sreloc->size)
+	    {
+	      /* Sanity to check that we have previously allocated
+		 sufficient space in the relocation section for the
+		 number of relocations we actually want to emit. */
+	      abort ();
+	    }
+
+	  /* If this reloc is against an external symbol, we do not want to
+	     fiddle with the addend.  Otherwise, we need to include the symbol
+	     value so that it becomes an addend for the dynamic reloc.  */
+	  if (!relocate)
+	    return bfd_reloc_ok;
+
+	  return _bfd_final_link_relocate (howto, input_bfd, input_section,
+					   contents, rel->r_offset, value,
+					   signed_addend);
+	}
+      else
+	value += signed_addend;
+      break;
+
+    case R_AARCH64_JUMP26:
+    case R_AARCH64_CALL26:
+      {
+	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.
+	   The jump to the next instruction is optimized as a NOP.
+	   Do the same for local undefined symbols. */
+	if (weak_undef_p && ! via_plt_p)
+	  {
+	    bfd_putl32 (INSN_NOP, hit_data);
+	    return bfd_reloc_ok;
+	  }
+
+	/* If the call goes through a PLT entry, make sure to
+	   check distance to the right destination address.  */
+	if (via_plt_p)
+	  {
+	    value = (splt->output_section->vma
+		     + splt->output_offset + h->plt.offset);
+	    *unresolved_reloc_p = FALSE;
+	  }
+
+	/* If the target symbol is global and marked as a function the
+	   relocation applies a function call or a tail call.  In this
+	   situation we can veneer out of range branches.  The veneers
+	   use IP0 and IP1 hence cannot be used arbitrary out of range
+	   branches that occur within the body of a function.  */
+	if (h && h->type == STT_FUNC)
+	  {
+	    /* Check if a stub has to be inserted because the destination
+	       is too far away.  */
+	    if (! aarch64_valid_branch_p (value, place))
+	      {
+		/* The target is out of reach, so redirect the branch to
+		   the local stub for this function.  */
+		struct elf64_aarch64_stub_hash_entry *stub_entry;
+		stub_entry = elf64_aarch64_get_stub_entry (input_section,
+							   sym_sec, h,
+							   rel, globals);
+		if (stub_entry != NULL)
+		  value = (stub_entry->stub_offset
+			   + stub_entry->stub_sec->output_offset
+			   + stub_entry->stub_sec->output_section->vma);
+	      }
+	  }
+      }
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  signed_addend, weak_undef_p);
+      break;
+
+    case R_AARCH64_ABS16:
+    case R_AARCH64_ABS32:
+    case R_AARCH64_ADD_ABS_LO12_NC:
+    case R_AARCH64_ADR_PREL_LO21:
+    case R_AARCH64_ADR_PREL_PG_HI21:
+    case R_AARCH64_ADR_PREL_PG_HI21_NC:
+    case R_AARCH64_CONDBR19:
+    case R_AARCH64_LD_PREL_LO19:
+    case R_AARCH64_LDST8_ABS_LO12_NC:
+    case R_AARCH64_LDST16_ABS_LO12_NC:
+    case R_AARCH64_LDST32_ABS_LO12_NC:
+    case R_AARCH64_LDST64_ABS_LO12_NC:
+    case R_AARCH64_LDST128_ABS_LO12_NC:
+    case R_AARCH64_MOVW_SABS_G0:
+    case R_AARCH64_MOVW_SABS_G1:
+    case R_AARCH64_MOVW_SABS_G2:
+    case R_AARCH64_MOVW_UABS_G0:
+    case R_AARCH64_MOVW_UABS_G0_NC:
+    case R_AARCH64_MOVW_UABS_G1:
+    case R_AARCH64_MOVW_UABS_G1_NC:
+    case R_AARCH64_MOVW_UABS_G2:
+    case R_AARCH64_MOVW_UABS_G2_NC:
+    case R_AARCH64_MOVW_UABS_G3:
+    case R_AARCH64_PREL16:
+    case R_AARCH64_PREL32:
+    case R_AARCH64_PREL64:
+    case R_AARCH64_TSTBR14:
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  signed_addend, weak_undef_p);
+      break;
+
+    case R_AARCH64_LD64_GOT_LO12_NC:
+    case R_AARCH64_ADR_GOT_PAGE:
+      if (globals->root.sgot == NULL)
+	BFD_ASSERT (h != NULL);
+
+      if (h != NULL)
+	{
+	  value = aarch64_calculate_got_entry_vma (h, globals, info, value,
+						   output_bfd,
+						   unresolved_reloc_p);
+	  value = aarch64_resolve_relocation (r_type, place, value,
+					      0, weak_undef_p);
+	}
+      break;
+
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+      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);
+
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  0, weak_undef_p);
+      *unresolved_reloc_p = FALSE;
+      break;
+
+    case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+    case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  - tpoff_base (info), weak_undef_p);
+      *unresolved_reloc_p = FALSE;
+      break;
+
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_ADD:
+    case R_AARCH64_TLSDESC_LDR:
+      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->sgotplt_jump_table_size);
+
+      value = aarch64_resolve_relocation (r_type, place, value,
+					  0, weak_undef_p);
+      *unresolved_reloc_p = FALSE;
+      break;
+
+    default:
+      return bfd_reloc_notsupported;
+    }
+
+  if (saved_addend)
+    *saved_addend = value;
+
+  /* Only apply the final relocation in a sequence.  */
+  if (save_addend)
+    return bfd_reloc_continue;
+
+  return bfd_elf_aarch64_put_addend (input_bfd, hit_data, howto, value);
+}
+
+/* Handle TLS relaxations.  Relaxing is possible for symbols that use
+   R_AARCH64_TLSDESC_ADR_{PAGE, LD64_LO12_NC, ADD_LO12_NC} during a static
+   link.
+
+   Return bfd_reloc_ok if we're done, bfd_reloc_continue if the caller
+   is to then call final_link_relocate.  Return other values in the
+   case of error.  */
+
+static bfd_reloc_status_type
+elf64_aarch64_tls_relax (struct elf64_aarch64_link_hash_table *globals,
+			 bfd *input_bfd, bfd_byte *contents,
+			 Elf_Internal_Rela *rel, struct elf_link_hash_entry *h)
+{
+  bfd_boolean is_local = h == NULL;
+  unsigned int r_type = ELF64_R_TYPE (rel->r_info);
+  unsigned long insn;
+
+  BFD_ASSERT (globals && input_bfd && contents && rel);
+
+  switch (r_type)
+    {
+    case R_AARCH64_TLSGD_ADR_PAGE21:
+    case R_AARCH64_TLSDESC_ADR_PAGE:
+      if (is_local)
+	{
+	  /* GD->LE relaxation:
+	     adrp x0, :tlsgd:var     =>   movz x0, :tprel_g1:var
+	     or
+	     adrp x0, :tlsdesc:var   =>   movz x0, :tprel_g1:var
+	   */
+	  bfd_putl32 (0xd2a00000, contents + rel->r_offset);
+	  return bfd_reloc_continue;
+	}
+      else
+	{
+	  /* GD->IE relaxation:
+	     adrp x0, :tlsgd:var     =>   adrp x0, :gottprel:var
+	     or
+	     adrp x0, :tlsdesc:var   =>   adrp x0, :gottprel:var
+	   */
+	  insn = bfd_getl32 (contents + rel->r_offset);
+	  return bfd_reloc_continue;
+	}
+
+    case R_AARCH64_TLSDESC_LD64_LO12_NC:
+      if (is_local)
+	{
+	  /* GD->LE relaxation:
+	     ldr xd, [x0, #:tlsdesc_lo12:var]   =>   movk x0, :tprel_g0_nc:var
+	   */
+	  bfd_putl32 (0xf2800000, contents + rel->r_offset);
+	  return bfd_reloc_continue;
+	}
+      else
+	{
+	  /* GD->IE relaxation:
+	     ldr xd, [x0, #:tlsdesc_lo12:var] => ldr x0, [x0, #:gottprel_lo12:var]
+	   */
+	  insn = bfd_getl32 (contents + rel->r_offset);
+	  insn &= 0xfffffff0;
+	  bfd_putl32 (insn, contents + rel->r_offset);
+	  return bfd_reloc_continue;
+	}
+
+    case R_AARCH64_TLSGD_ADD_LO12_NC:
+      if (is_local)
+	{
+	  /* GD->LE relaxation
+	     add  x0, #:tlsgd_lo12:var  => movk x0, :tprel_g0_nc:var
+	     bl   __tls_get_addr        => mrs  x1, tpidr_el0
+	     nop                        => add  x0, x1, x0
+	   */
+
+	  /* 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 = ELF64_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+
+	  bfd_putl32 (0xf2800000, contents + rel->r_offset);
+	  bfd_putl32 (0xd53bd041, contents + rel->r_offset + 4);
+	  bfd_putl32 (0x8b000020, contents + rel->r_offset + 8);
+	  return bfd_reloc_continue;
+	}
+      else
+	{
+	  /* GD->IE relaxation
+	     ADD  x0, #:tlsgd_lo12:var  => ldr  x0, [x0, #:gottprel_lo12:var]
+	     BL   __tls_get_addr        => mrs  x1, tpidr_el0
+	       R_AARCH64_CALL26
+	     NOP                        => add  x0, x1, x0
+	   */
+
+	  BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_AARCH64_CALL26);
+
+	  /* Remove the relocation on the BL instruction.  */
+	  rel[1].r_info = ELF64_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+
+	  bfd_putl32 (0xf9400000, contents + rel->r_offset);
+
+	  /* We choose to fixup the BL and NOP instructions using the
+	     offset from the second relocation to allow flexibility in
+	     scheduling instructions between the ADD and BL.  */
+	  bfd_putl32 (0xd53bd041, contents + rel[1].r_offset);
+	  bfd_putl32 (0x8b000020, contents + rel[1].r_offset + 4);
+	  return bfd_reloc_continue;
+	}
+
+    case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    case R_AARCH64_TLSDESC_CALL:
+      /* GD->IE/LE relaxation:
+         add x0, x0, #:tlsdesc_lo12:var   =>   nop
+         blr xd                           =>   nop
+       */
+      bfd_putl32 (INSN_NOP, contents + rel->r_offset);
+      return bfd_reloc_ok;
+
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+      /* IE->LE relaxation:
+         adrp xd, :gottprel:var   =>   movz xd, :tprel_g1:var
+       */
+      if (is_local)
+	{
+	  insn = bfd_getl32 (contents + rel->r_offset);
+	  bfd_putl32 (0xd2a00000 | (insn & 0x1f), contents + rel->r_offset);
+	}
+      return bfd_reloc_continue;
+
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+      /* IE->LE relaxation:
+         ldr  xd, [xm, #:gottprel_lo12:var]   =>   movk xd, :tprel_g0_nc:var
+       */
+      if (is_local)
+	{
+	  insn = bfd_getl32 (contents + rel->r_offset);
+	  bfd_putl32 (0xf2800000 | (insn & 0x1f), contents + rel->r_offset);
+	}
+      return bfd_reloc_continue;
+
+    default:
+      return bfd_reloc_continue;
+    }
+
+  return bfd_reloc_ok;
+}
+
+/* Relocate an AArch64 ELF section.  */
+
+static bfd_boolean
+elf64_aarch64_relocate_section (bfd *output_bfd,
+				struct bfd_link_info *info,
+				bfd *input_bfd,
+				asection *input_section,
+				bfd_byte *contents,
+				Elf_Internal_Rela *relocs,
+				Elf_Internal_Sym *local_syms,
+				asection **local_sections)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  Elf_Internal_Rela *rel;
+  Elf_Internal_Rela *relend;
+  const char *name;
+  struct elf64_aarch64_link_hash_table *globals;
+  bfd_boolean save_addend = FALSE;
+  bfd_vma addend = 0;
+
+  globals = elf64_aarch64_hash_table (info);
+
+  symtab_hdr = &elf_symtab_hdr (input_bfd);
+  sym_hashes = elf_sym_hashes (input_bfd);
+
+  rel = relocs;
+  relend = relocs + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      unsigned int r_type;
+      unsigned int relaxed_r_type;
+      reloc_howto_type *howto;
+      unsigned long r_symndx;
+      Elf_Internal_Sym *sym;
+      asection *sec;
+      struct elf_link_hash_entry *h;
+      bfd_vma relocation;
+      bfd_reloc_status_type r;
+      arelent bfd_reloc;
+      char sym_type;
+      bfd_boolean unresolved_reloc = FALSE;
+      char *error_message = NULL;
+
+      r_symndx = ELF64_R_SYM (rel->r_info);
+      r_type = ELF64_R_TYPE (rel->r_info);
+
+      bfd_reloc.howto = elf64_aarch64_howto_from_type (r_type);
+      howto = bfd_reloc.howto;
+
+      h = NULL;
+      sym = NULL;
+      sec = NULL;
+
+      if (r_symndx < symtab_hdr->sh_info)
+	{
+	  sym = local_syms + r_symndx;
+	  sym_type = ELF64_ST_TYPE (sym->st_info);
+	  sec = local_sections[r_symndx];
+
+	  /* An object file might have a reference to a local
+	     undefined symbol.  This is a daft object file, but we
+	     should at least do something about it.  */
+	  if (r_type != R_AARCH64_NONE && r_type != R_AARCH64_NULL
+	      && bfd_is_und_section (sec)
+	      && ELF_ST_BIND (sym->st_info) != STB_WEAK)
+	    {
+	      if (!info->callbacks->undefined_symbol
+		  (info, bfd_elf_string_from_elf_section
+		   (input_bfd, symtab_hdr->sh_link, sym->st_name),
+		   input_bfd, input_section, rel->r_offset, TRUE))
+		return FALSE;
+	    }
+
+	  if (r_type >= R_AARCH64_dyn_max)
+	    {
+	      bfd_set_error (bfd_error_bad_value);
+	      return FALSE;
+	    }
+
+	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+	}
+      else
+	{
+	  bfd_boolean warned;
+
+	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+				   r_symndx, symtab_hdr, sym_hashes,
+				   h, sec, relocation,
+				   unresolved_reloc, warned);
+
+	  sym_type = h->type;
+	}
+
+      if (sec != NULL && discarded_section (sec))
+	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+					 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;
+	}
+
+      if (h != NULL)
+	name = h->root.root.string;
+      else
+	{
+	  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);
+	}
+
+      if (r_symndx != 0
+	  && r_type != R_AARCH64_NONE
+	  && r_type != R_AARCH64_NULL
+	  && (h == NULL
+	      || h->root.type == bfd_link_hash_defined
+	      || h->root.type == bfd_link_hash_defweak)
+	  && IS_AARCH64_TLS_RELOC (r_type) != (sym_type == STT_TLS))
+	{
+	  (*_bfd_error_handler)
+	    ((sym_type == STT_TLS
+	      ? _("%B(%A+0x%lx): %s used with TLS symbol %s")
+	      : _("%B(%A+0x%lx): %s used with non-TLS symbol %s")),
+	     input_bfd,
+	     input_section, (long) rel->r_offset, howto->name, name);
+	}
+
+
+      /* We relax only if we can see that there can be a valid transition
+         from a reloc type to another.
+         We call elf64_aarch64_final_link_relocate unless we're completely
+         done, i.e., the relaxation produced the final output we want.  */
+
+      relaxed_r_type = aarch64_tls_transition (input_bfd, info, r_type,
+					       h, r_symndx);
+      if (relaxed_r_type != r_type)
+	{
+	  r_type = relaxed_r_type;
+	  howto = elf64_aarch64_howto_from_type (r_type);
+
+	  r = elf64_aarch64_tls_relax (globals, input_bfd, contents, rel, h);
+	  unresolved_reloc = 0;
+	}
+      else
+	r = bfd_reloc_continue;
+
+      /* There may be multiple consecutive relocations for the
+         same offset.  In that case we are supposed to treat the
+         output of each relocation as the addend for the next.  */
+      if (rel + 1 < relend
+	  && rel->r_offset == rel[1].r_offset
+	  && ELF64_R_TYPE (rel[1].r_info) != R_AARCH64_NONE
+	  && ELF64_R_TYPE (rel[1].r_info) != R_AARCH64_NULL)
+	save_addend = TRUE;
+      else
+	save_addend = FALSE;
+
+      if (r == bfd_reloc_continue)
+	r = elf64_aarch64_final_link_relocate (howto, input_bfd, output_bfd,
+					       input_section, contents, rel,
+					       relocation, info, sec,
+					       h, &unresolved_reloc,
+					       save_addend, &addend);
+
+      switch (r_type)
+	{
+	case R_AARCH64_TLSGD_ADR_PAGE21:
+	case R_AARCH64_TLSGD_ADD_LO12_NC:
+	  if (! symbol_got_offset_mark_p (input_bfd, h, r_symndx))
+	    {
+	      bfd_boolean need_relocs = FALSE;
+	      bfd_byte *loc;
+	      int indx;
+	      bfd_vma off;
+
+	      off = symbol_got_offset (input_bfd, h, r_symndx);
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      need_relocs =
+		(info->shared || indx != 0) &&
+		(h == NULL
+		 || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		 || h->root.type != bfd_link_hash_undefweak);
+
+	      BFD_ASSERT (globals->root.srelgot != NULL);
+
+	      if (need_relocs)
+		{
+		  Elf_Internal_Rela rela;
+		  rela.r_info = ELF64_R_INFO (indx, R_AARCH64_TLS_DTPMOD64);
+		  rela.r_addend = 0;
+		  rela.r_offset = globals->root.sgot->output_section->vma +
+		    globals->root.sgot->output_offset + off;
+
+
+		  loc = globals->root.srelgot->contents;
+		  loc += globals->root.srelgot->reloc_count++
+		    * RELOC_SIZE (htab);
+		  bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+
+		  if (indx == 0)
+		    {
+		      bfd_put_64 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  globals->root.sgot->contents + off
+				  + GOT_ENTRY_SIZE);
+		    }
+		  else
+		    {
+		      /* This TLS symbol is global. We emit a
+			 relocation to fixup the tls offset at load
+			 time.  */
+		      rela.r_info =
+			ELF64_R_INFO (indx, R_AARCH64_TLS_DTPREL64);
+		      rela.r_addend = 0;
+		      rela.r_offset =
+			(globals->root.sgot->output_section->vma
+			 + globals->root.sgot->output_offset + off
+			 + GOT_ENTRY_SIZE);
+
+		      loc = globals->root.srelgot->contents;
+		      loc += globals->root.srelgot->reloc_count++
+			* RELOC_SIZE (globals);
+		      bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+		      bfd_put_64 (output_bfd, (bfd_vma) 0,
+				  globals->root.sgot->contents + off
+				  + GOT_ENTRY_SIZE);
+		    }
+		}
+	      else
+		{
+		  bfd_put_64 (output_bfd, (bfd_vma) 1,
+			      globals->root.sgot->contents + off);
+		  bfd_put_64 (output_bfd,
+			      relocation - dtpoff_base (info),
+			      globals->root.sgot->contents + off
+			      + GOT_ENTRY_SIZE);
+		}
+
+	      symbol_got_offset_mark (input_bfd, h, r_symndx);
+	    }
+	  break;
+
+	case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+	case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+	  if (! symbol_got_offset_mark_p (input_bfd, h, r_symndx))
+	    {
+	      bfd_boolean need_relocs = FALSE;
+	      bfd_byte *loc;
+	      int indx;
+	      bfd_vma off;
+
+	      off = symbol_got_offset (input_bfd, h, r_symndx);
+
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      need_relocs =
+		(info->shared || indx != 0) &&
+		(h == NULL
+		 || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		 || h->root.type != bfd_link_hash_undefweak);
+
+	      BFD_ASSERT (globals->root.srelgot != NULL);
+
+	      if (need_relocs)
+		{
+		  Elf_Internal_Rela rela;
+
+		  if (indx == 0)
+		    rela.r_addend = relocation - dtpoff_base (info);
+		  else
+		    rela.r_addend = 0;
+
+		  rela.r_info = ELF64_R_INFO (indx, R_AARCH64_TLS_TPREL64);
+		  rela.r_offset = globals->root.sgot->output_section->vma +
+		    globals->root.sgot->output_offset + off;
+
+		  loc = globals->root.srelgot->contents;
+		  loc += globals->root.srelgot->reloc_count++
+		    * RELOC_SIZE (htab);
+
+		  bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+
+		  bfd_put_64 (output_bfd, rela.r_addend,
+			      globals->root.sgot->contents + off);
+		}
+	      else
+		bfd_put_64 (output_bfd, relocation - tpoff_base (info),
+			    globals->root.sgot->contents + off);
+
+	      symbol_got_offset_mark (input_bfd, h, r_symndx);
+	    }
+	  break;
+
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+	case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+	  break;
+
+	case R_AARCH64_TLSDESC_ADR_PAGE:
+	case R_AARCH64_TLSDESC_LD64_LO12_NC:
+	case R_AARCH64_TLSDESC_ADD_LO12_NC:
+	  if (! symbol_tlsdesc_got_offset_mark_p (input_bfd, h, r_symndx))
+	    {
+	      bfd_boolean need_relocs = FALSE;
+	      int indx = h && h->dynindx != -1 ? h->dynindx : 0;
+	      bfd_vma off = symbol_tlsdesc_got_offset (input_bfd, h, r_symndx);
+
+	      need_relocs = (h == NULL
+			     || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+			     || h->root.type != bfd_link_hash_undefweak);
+
+	      BFD_ASSERT (globals->root.srelgot != NULL);
+	      BFD_ASSERT (globals->root.sgot != NULL);
+
+	      if (need_relocs)
+		{
+		  bfd_byte *loc;
+		  Elf_Internal_Rela rela;
+		  rela.r_info = ELF64_R_INFO (indx, R_AARCH64_TLSDESC);
+		  rela.r_addend = 0;
+		  rela.r_offset = (globals->root.sgotplt->output_section->vma
+				   + globals->root.sgotplt->output_offset
+				   + off + globals->sgotplt_jump_table_size);
+
+		  if (indx == 0)
+		    rela.r_addend = relocation - dtpoff_base (info);
+
+		  /* Allocate the next available slot in the PLT reloc
+		     section to hold our R_AARCH64_TLSDESC, the next
+		     available slot is determined from reloc_count,
+		     which we step. But note, reloc_count was
+		     artifically moved down while allocating slots for
+		     real PLT relocs such that all of the PLT relocs
+		     will fit above the initial reloc_count and the
+		     extra stuff will fit below.  */
+		  loc = globals->root.srelplt->contents;
+		  loc += globals->root.srelplt->reloc_count++
+		    * RELOC_SIZE (globals);
+
+		  bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+
+		  bfd_put_64 (output_bfd, (bfd_vma) 0,
+			      globals->root.sgotplt->contents + off +
+			      globals->sgotplt_jump_table_size);
+		  bfd_put_64 (output_bfd, (bfd_vma) 0,
+			      globals->root.sgotplt->contents + off +
+			      globals->sgotplt_jump_table_size +
+			      GOT_ENTRY_SIZE);
+		}
+
+	      symbol_tlsdesc_got_offset_mark (input_bfd, h, r_symndx);
+	    }
+	  break;
+	}
+
+      if (!save_addend)
+	addend = 0;
+
+
+      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
+         because such sections are not SEC_ALLOC and thus ld.so will
+         not process them.  */
+      if (unresolved_reloc
+	  && !((input_section->flags & SEC_DEBUGGING) != 0
+	       && h->def_dynamic)
+	  && _bfd_elf_section_offset (output_bfd, info, input_section,
+				      +rel->r_offset) != (bfd_vma) - 1)
+	{
+	  (*_bfd_error_handler)
+	    (_
+	     ("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
+	     input_bfd, input_section, (long) rel->r_offset, howto->name,
+	     h->root.root.string);
+	  return FALSE;
+	}
+
+      if (r != bfd_reloc_ok && r != bfd_reloc_continue)
+	{
+	  switch (r)
+	    {
+	    case bfd_reloc_overflow:
+	      /* If the overflowing reloc was to an undefined symbol,
+		 we have already printed one error message and there
+		 is no point complaining again.  */
+	      if ((!h ||
+		   h->root.type != bfd_link_hash_undefined)
+		  && (!((*info->callbacks->reloc_overflow)
+			(info, (h ? &h->root : NULL), name, howto->name,
+			 (bfd_vma) 0, input_bfd, input_section,
+			 rel->r_offset))))
+		return FALSE;
+	      break;
+
+	    case bfd_reloc_undefined:
+	      if (!((*info->callbacks->undefined_symbol)
+		    (info, name, input_bfd, input_section,
+		     rel->r_offset, TRUE)))
+		return FALSE;
+	      break;
+
+	    case bfd_reloc_outofrange:
+	      error_message = _("out of range");
+	      goto common_error;
+
+	    case bfd_reloc_notsupported:
+	      error_message = _("unsupported relocation");
+	      goto common_error;
+
+	    case bfd_reloc_dangerous:
+	      /* error_message should already be set.  */
+	      goto common_error;
+
+	    default:
+	      error_message = _("unknown error");
+	      /* Fall through.  */
+
+	    common_error:
+	      BFD_ASSERT (error_message != NULL);
+	      if (!((*info->callbacks->reloc_dangerous)
+		    (info, error_message, input_bfd, input_section,
+		     rel->r_offset)))
+		return FALSE;
+	      break;
+	    }
+	}
+    }
+
+  return TRUE;
+}
+
+/* Set the right machine number.  */
+
+static bfd_boolean
+elf64_aarch64_object_p (bfd *abfd)
+{
+  bfd_default_set_arch_mach (abfd, bfd_arch_aarch64, bfd_mach_aarch64);
+  return TRUE;
+}
+
+/* Function to keep AArch64 specific flags in the ELF header.  */
+
+static bfd_boolean
+elf64_aarch64_set_private_flags (bfd *abfd, flagword flags)
+{
+  if (elf_flags_init (abfd) && elf_elfheader (abfd)->e_flags != flags)
+    {
+    }
+  else
+    {
+      elf_elfheader (abfd)->e_flags = flags;
+      elf_flags_init (abfd) = TRUE;
+    }
+
+  return TRUE;
+}
+
+/* Copy backend specific data from one object module to another.  */
+
+static bfd_boolean
+elf64_aarch64_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+  flagword in_flags;
+
+  if (!is_aarch64_elf (ibfd) || !is_aarch64_elf (obfd))
+    return TRUE;
+
+  in_flags = elf_elfheader (ibfd)->e_flags;
+
+  elf_elfheader (obfd)->e_flags = in_flags;
+  elf_flags_init (obfd) = TRUE;
+
+  /* Also copy the EI_OSABI field.  */
+  elf_elfheader (obfd)->e_ident[EI_OSABI] =
+    elf_elfheader (ibfd)->e_ident[EI_OSABI];
+
+  /* Copy object attributes.  */
+  _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
+  return TRUE;
+}
+
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bfd_boolean
+elf64_aarch64_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+  flagword out_flags;
+  flagword in_flags;
+  bfd_boolean flags_compatible = TRUE;
+  asection *sec;
+
+  /* Check if we have the same endianess.  */
+  if (!_bfd_generic_verify_endian_match (ibfd, obfd))
+    return FALSE;
+
+  if (!is_aarch64_elf (ibfd) || !is_aarch64_elf (obfd))
+    return TRUE;
+
+  /* The input BFD must have had its flags initialised.  */
+  /* The following seems bogus to me -- The flags are initialized in
+     the assembler but I don't think an elf_flags_init field is
+     written into the object.  */
+  /* BFD_ASSERT (elf_flags_init (ibfd)); */
+
+  in_flags = elf_elfheader (ibfd)->e_flags;
+  out_flags = elf_elfheader (obfd)->e_flags;
+
+  if (!elf_flags_init (obfd))
+    {
+      /* If the input is the default architecture and had the default
+         flags then do not bother setting the flags for the output
+         architecture, instead allow future merges to do this.  If no
+         future merges ever set these flags then they will retain their
+         uninitialised values, which surprise surprise, correspond
+         to the default values.  */
+      if (bfd_get_arch_info (ibfd)->the_default
+	  && elf_elfheader (ibfd)->e_flags == 0)
+	return TRUE;
+
+      elf_flags_init (obfd) = TRUE;
+      elf_elfheader (obfd)->e_flags = in_flags;
+
+      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
+	  && bfd_get_arch_info (obfd)->the_default)
+	return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
+				  bfd_get_mach (ibfd));
+
+      return TRUE;
+    }
+
+  /* Identical flags must be compatible.  */
+  if (in_flags == out_flags)
+    return TRUE;
+
+  /* Check to see if the input BFD actually contains any sections.  If
+     not, its flags may not have been initialised either, but it
+     cannot actually cause any incompatiblity.  Do not short-circuit
+     dynamic objects; their section list may be emptied by
+     elf_link_add_object_symbols.
+
+     Also check to see if there are no code sections in the input.
+     In this case there is no need to check for code specific flags.
+     XXX - do we need to worry about floating-point format compatability
+     in data sections ?  */
+  if (!(ibfd->flags & DYNAMIC))
+    {
+      bfd_boolean null_input_bfd = TRUE;
+      bfd_boolean only_data_sections = TRUE;
+
+      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+	{
+	  if ((bfd_get_section_flags (ibfd, sec)
+	       & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+	      == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+	    only_data_sections = FALSE;
+
+	  null_input_bfd = FALSE;
+	  break;
+	}
+
+      if (null_input_bfd || only_data_sections)
+	return TRUE;
+    }
+
+  return flags_compatible;
+}
+
+/* Display the flags field.  */
+
+static bfd_boolean
+elf64_aarch64_print_private_bfd_data (bfd *abfd, void *ptr)
+{
+  FILE *file = (FILE *) ptr;
+  unsigned long flags;
+
+  BFD_ASSERT (abfd != NULL && ptr != NULL);
+
+  /* Print normal ELF private data.  */
+  _bfd_elf_print_private_bfd_data (abfd, ptr);
+
+  flags = elf_elfheader (abfd)->e_flags;
+  /* Ignore init flag - it may not be set, despite the flags field
+     containing valid data.  */
+
+  /* xgettext:c-format */
+  fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
+
+  if (flags)
+    fprintf (file, _("<Unrecognised flag bits set>"));
+
+  fputc ('\n', file);
+
+  return TRUE;
+}
+
+/* Update the got entry reference counts for the section being removed.  */
+
+static bfd_boolean
+elf64_aarch64_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
+			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
+			     asection *sec ATTRIBUTE_UNUSED,
+			     const Elf_Internal_Rela *
+			     relocs ATTRIBUTE_UNUSED)
+{
+  return TRUE;
+}
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+   regular object.  The current definition is in some section of the
+   dynamic object, but we're not including those sections.  We have to
+   change the definition to something the rest of the link can
+   understand.	*/
+
+static bfd_boolean
+elf64_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
+				     struct elf_link_hash_entry *h)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  asection *s;
+
+  /* If this is a function, put it in the procedure linkage table.  We
+     will fill in the contents of the procedure linkage table later,
+     when we know the address of the .got section.  */
+  if (h->type == STT_FUNC || h->needs_plt)
+    {
+      if (h->plt.refcount <= 0
+	  || SYMBOL_CALLS_LOCAL (info, h)
+	  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+	      && h->root.type == bfd_link_hash_undefweak))
+	{
+	  /* This case can occur if we saw a CALL26 reloc in
+	     an input file, but the symbol wasn't referred to
+	     by a dynamic object or all references were
+	     garbage collected. In which case we can end up
+	     resolving.  */
+	  h->plt.offset = (bfd_vma) - 1;
+	  h->needs_plt = 0;
+	}
+
+      return TRUE;
+    }
+  else
+    /* It's possible that we incorrectly decided a .plt reloc was
+       needed for an R_X86_64_PC32 reloc to a non-function sym in
+       check_relocs.  We can't decide accurately between function and
+       non-function syms in check-relocs;  Objects loaded later in
+       the link may change h->type.  So fix it now.  */
+    h->plt.offset = (bfd_vma) - 1;
+
+
+  /* If this is a weak symbol, and there is a real definition, the
+     processor independent code will have arranged for us to see the
+     real definition first, and we can just use the same value.  */
+  if (h->u.weakdef != NULL)
+    {
+      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+		  || h->u.weakdef->root.type == bfd_link_hash_defweak);
+      h->root.u.def.section = h->u.weakdef->root.u.def.section;
+      h->root.u.def.value = h->u.weakdef->root.u.def.value;
+      if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
+	h->non_got_ref = h->u.weakdef->non_got_ref;
+      return TRUE;
+    }
+
+  /* If we are creating a shared library, we must presume that the
+     only references to the symbol are via the global offset table.
+     For such cases we need not do anything here; the relocations will
+     be handled correctly by relocate_section.  */
+  if (info->shared)
+    return TRUE;
+
+  /* If there are no references to this symbol that do not use the
+     GOT, we don't need to generate a copy reloc.  */
+  if (!h->non_got_ref)
+    return TRUE;
+
+  /* If -z nocopyreloc was given, we won't generate them either.  */
+  if (info->nocopyreloc)
+    {
+      h->non_got_ref = 0;
+      return TRUE;
+    }
+
+  /* We must allocate the symbol in our .dynbss section, which will
+     become part of the .bss section of the executable.  There will be
+     an entry for this symbol in the .dynsym section.  The dynamic
+     object will contain position independent code, so all references
+     from the dynamic object to this symbol will go through the global
+     offset table.  The dynamic linker will use the .dynsym entry to
+     determine the address it must put in the global offset table, so
+     both the dynamic object and the regular object will refer to the
+     same memory location for the variable.  */
+
+  htab = elf64_aarch64_hash_table (info);
+
+  /* We must generate a R_AARCH64_COPY reloc to tell the dynamic linker
+     to copy the initial value out of the dynamic object and into the
+     runtime process image.  */
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
+    {
+      htab->srelbss->size += RELOC_SIZE (htab);
+      h->needs_copy = 1;
+    }
+
+  s = htab->sdynbss;
+
+  return _bfd_elf_adjust_dynamic_copy (h, s);
+
+}
+
+static bfd_boolean
+elf64_aarch64_allocate_local_symbols (bfd *abfd, unsigned number)
+{
+  struct elf_aarch64_local_symbol *locals;
+  locals = elf64_aarch64_locals (abfd);
+  if (locals == NULL)
+    {
+      locals = (struct elf_aarch64_local_symbol *)
+	bfd_zalloc (abfd, number * sizeof (struct elf_aarch64_local_symbol));
+      if (locals == NULL)
+	return FALSE;
+      elf64_aarch64_locals (abfd) = locals;
+    }
+  return TRUE;
+}
+
+/* Look through the relocs for a section during the first phase.  */
+
+static bfd_boolean
+elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
+			    asection *sec, const Elf_Internal_Rela *relocs)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  const Elf_Internal_Rela *rel;
+  const Elf_Internal_Rela *rel_end;
+  asection *sreloc;
+
+  struct elf64_aarch64_link_hash_table *htab;
+
+  unsigned long nsyms;
+
+  if (info->relocatable)
+    return TRUE;
+
+  BFD_ASSERT (is_aarch64_elf (abfd));
+
+  htab = elf64_aarch64_hash_table (info);
+  sreloc = NULL;
+
+  symtab_hdr = &elf_symtab_hdr (abfd);
+  sym_hashes = elf_sym_hashes (abfd);
+  nsyms = NUM_SHDR_ENTRIES (symtab_hdr);
+
+  rel_end = relocs + sec->reloc_count;
+  for (rel = relocs; rel < rel_end; rel++)
+    {
+      struct elf_link_hash_entry *h;
+      unsigned long r_symndx;
+      unsigned int r_type;
+
+      r_symndx = ELF64_R_SYM (rel->r_info);
+      r_type = ELF64_R_TYPE (rel->r_info);
+
+      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
+	{
+	  (*_bfd_error_handler) (_("%B: bad symbol index: %d"), abfd,
+				 r_symndx);
+	  return FALSE;
+	}
+
+      if (r_symndx >= nsyms
+	  /* PR 9934: It is possible to have relocations that do not
+	     refer to symbols, thus it is also possible to have an
+	     object file containing relocations but no symbol table.  */
+	  && (r_symndx > 0 || nsyms > 0))
+	{
+	  (*_bfd_error_handler) (_("%B: bad symbol index: %d"), abfd,
+				 r_symndx);
+	  return FALSE;
+	}
+
+      if (nsyms == 0 || r_symndx < symtab_hdr->sh_info)
+	h = NULL;
+      else
+	{
+	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	}
+
+      /* Could be done earlier, if h were already available.  */
+      r_type = aarch64_tls_transition (abfd, info, r_type, h, r_symndx);
+
+      switch (r_type)
+	{
+	case R_AARCH64_ABS64:
+
+	  /* We don't need to handle relocs into sections not going into
+	     the "real" output.  */
+	  if ((sec->flags & SEC_ALLOC) == 0)
+	    break;
+
+	  if (h != NULL)
+	    {
+	      if (!info->shared)
+		h->non_got_ref = 1;
+
+	      h->plt.refcount += 1;
+	      h->pointer_equality_needed = 1;
+	    }
+
+	  /* No need to do anything if we're not creating a shared
+	     object.  */
+	  if (! info->shared)
+	    break;
+
+	  {
+	    struct elf_dyn_relocs *p;
+	    struct elf_dyn_relocs **head;
+
+	    /* We must copy these reloc types into the output file.
+	       Create a reloc section in dynobj and make room for
+	       this reloc.  */
+	    if (sreloc == NULL)
+	      {
+		if (htab->root.dynobj == NULL)
+		  htab->root.dynobj = abfd;
+
+		sreloc = _bfd_elf_make_dynamic_reloc_section
+		  (sec, htab->root.dynobj, 3, abfd, /*rela? */ TRUE);
+
+		if (sreloc == NULL)
+		  return FALSE;
+	      }
+
+	    /* If this is a global symbol, we count the number of
+	       relocations we need for this symbol.  */
+	    if (h != NULL)
+	      {
+		struct elf64_aarch64_link_hash_entry *eh;
+		eh = (struct elf64_aarch64_link_hash_entry *) h;
+		head = &eh->dyn_relocs;
+	      }
+	    else
+	      {
+		/*   Track dynamic relocs needed for local syms too.
+		     We really need local syms available to do this
+		     easily.  Oh well. */
+
+		asection *s;
+		void **vpp;
+		Elf_Internal_Sym *isym;
+
+		isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+					      abfd, r_symndx);
+		if (isym == NULL)
+		  return FALSE;
+
+		s = bfd_section_from_elf_index (abfd, isym->st_shndx);
+		if (s == NULL)
+		  s = sec;
+
+		/* Beware of type punned pointers vs strict aliasing
+		   rules.  */
+		vpp = &(elf_section_data (s)->local_dynrel);
+		head = (struct elf_dyn_relocs **) vpp;
+	      }
+
+	    p = *head;
+	    if (p == NULL || p->sec != sec)
+	      {
+		bfd_size_type amt = sizeof *p;
+		p = ((struct elf_dyn_relocs *)
+		     bfd_zalloc (htab->root.dynobj, amt));
+		if (p == NULL)
+		  return FALSE;
+		p->next = *head;
+		*head = p;
+		p->sec = sec;
+	      }
+
+	    p->count += 1;
+
+	  }
+	  break;
+
+	  /* RR: We probably want to keep a consistency check that
+	     there are no dangling GOT_PAGE relocs.  */
+	case R_AARCH64_LD64_GOT_LO12_NC:
+	case R_AARCH64_ADR_GOT_PAGE:
+	case R_AARCH64_TLSGD_ADR_PAGE21:
+	case R_AARCH64_TLSGD_ADD_LO12_NC:
+	case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+	case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+	case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+	case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G2:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0:
+	case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
+	case R_AARCH64_TLSDESC_ADR_PAGE:
+	case R_AARCH64_TLSDESC_ADD_LO12_NC:
+	case R_AARCH64_TLSDESC_LD64_LO12_NC:
+	  {
+	    unsigned got_type;
+	    unsigned old_got_type;
+
+	    got_type = aarch64_reloc_got_type (r_type);
+
+	    if (h)
+	      {
+		h->got.refcount += 1;
+		old_got_type = elf64_aarch64_hash_entry (h)->got_type;
+	      }
+	    else
+	      {
+		struct elf_aarch64_local_symbol *locals;
+
+		if (!elf64_aarch64_allocate_local_symbols
+		    (abfd, symtab_hdr->sh_info))
+		  return FALSE;
+
+		locals = elf64_aarch64_locals (abfd);
+		BFD_ASSERT (r_symndx < symtab_hdr->sh_info);
+		locals[r_symndx].got_refcount += 1;
+		old_got_type = locals[r_symndx].got_type;
+	      }
+
+	    /* If a variable is accessed with both general dynamic TLS
+	       methods, two slots may be created.  */
+	    if (GOT_TLS_GD_ANY_P (old_got_type) && GOT_TLS_GD_ANY_P (got_type))
+	      got_type |= old_got_type;
+
+	    /* We will already have issued an error message if there
+	       is a TLS/non-TLS mismatch, based on the symbol type.
+	       So just combine any TLS types needed.  */
+	    if (old_got_type != GOT_UNKNOWN && old_got_type != GOT_NORMAL
+		&& got_type != GOT_NORMAL)
+	      got_type |= old_got_type;
+
+	    /* If the symbol is accessed by both IE and GD methods, we
+	       are able to relax.  Turn off the GD flag, without
+	       messing up with any other kind of TLS types that may be
+	       involved.  */
+	    if ((got_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (got_type))
+	      got_type &= ~ (GOT_TLSDESC_GD | GOT_TLS_GD);
+
+	    if (old_got_type != got_type)
+	      {
+		if (h != NULL)
+		  elf64_aarch64_hash_entry (h)->got_type = got_type;
+		else
+		  {
+		    struct elf_aarch64_local_symbol *locals;
+		    locals = elf64_aarch64_locals (abfd);
+		    BFD_ASSERT (r_symndx < symtab_hdr->sh_info);
+		    locals[r_symndx].got_type = got_type;
+		  }
+	      }
+
+	    if (htab->root.sgot == NULL)
+	      {
+		if (htab->root.dynobj == NULL)
+		  htab->root.dynobj = abfd;
+		if (!_bfd_elf_create_got_section (htab->root.dynobj, info))
+		  return FALSE;
+	      }
+	    break;
+	  }
+
+	case R_AARCH64_ADR_PREL_PG_HI21_NC:
+	case R_AARCH64_ADR_PREL_PG_HI21:
+	  if (h != NULL && info->executable)
+	    {
+	      /* If this reloc is in a read-only section, we might
+		 need a copy reloc.  We can't check reliably at this
+		 stage whether the section is read-only, as input
+		 sections have not yet been mapped to output sections.
+		 Tentatively set the flag for now, and correct in
+		 adjust_dynamic_symbol.  */
+	      h->non_got_ref = 1;
+	      h->plt.refcount += 1;
+	      h->pointer_equality_needed = 1;
+	    }
+	  /* FIXME:: RR need to handle these in shared libraries
+	     and essentially bomb out as these being non-PIC
+	     relocations in shared libraries.  */
+	  break;
+
+	case R_AARCH64_CALL26:
+	case R_AARCH64_JUMP26:
+	  /* If this is a local symbol then we resolve it
+	     directly without creating a PLT entry.  */
+	  if (h == NULL)
+	    continue;
+
+	  h->needs_plt = 1;
+	  h->plt.refcount += 1;
+	  break;
+	}
+    }
+  return TRUE;
+}
+
+/* Treat mapping symbols as special target symbols.  */
+
+static bfd_boolean
+elf64_aarch64_is_target_special_symbol (bfd *abfd ATTRIBUTE_UNUSED,
+					asymbol *sym)
+{
+  return bfd_is_aarch64_special_symbol_name (sym->name,
+					     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.  */
+
+static bfd_boolean
+aarch64_elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
+			   asection *section,
+			   asymbol **symbols,
+			   bfd_vma offset,
+			   const char **filename_ptr,
+			   const char **functionname_ptr)
+{
+  const char *filename = NULL;
+  asymbol *func = NULL;
+  bfd_vma low_func = 0;
+  asymbol **p;
+
+  for (p = symbols; *p != NULL; p++)
+    {
+      elf_symbol_type *q;
+
+      q = (elf_symbol_type *) * p;
+
+      switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
+	{
+	default:
+	  break;
+	case STT_FILE:
+	  filename = bfd_asymbol_name (&q->symbol);
+	  break;
+	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
+elf64_aarch64_find_nearest_line (bfd *abfd,
+				 asection *section,
+				 asymbol **symbols,
+				 bfd_vma offset,
+				 const char **filename_ptr,
+				 const char **functionname_ptr,
+				 unsigned int *line_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,
+				     filename_ptr, functionname_ptr,
+				     line_ptr, NULL, 0,
+				     &elf_tdata (abfd)->dwarf2_find_line_info))
+    {
+      if (!*functionname_ptr)
+	aarch64_elf_find_function (abfd, section, symbols, offset,
+				   *filename_ptr ? NULL : filename_ptr,
+				   functionname_ptr);
+
+      return TRUE;
+    }
+
+  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;
+
+  if (!aarch64_elf_find_function (abfd, section, symbols, offset,
+				  filename_ptr, functionname_ptr))
+    return FALSE;
+
+  *line_ptr = 0;
+  return TRUE;
+}
+
+static bfd_boolean
+elf64_aarch64_find_inliner_info (bfd *abfd,
+				 const char **filename_ptr,
+				 const char **functionname_ptr,
+				 unsigned int *line_ptr)
+{
+  bfd_boolean found;
+  found = _bfd_dwarf2_find_inliner_info
+    (abfd, filename_ptr,
+     functionname_ptr, line_ptr, &elf_tdata (abfd)->dwarf2_find_line_info);
+  return found;
+}
+
+
+static void
+elf64_aarch64_post_process_headers (bfd *abfd,
+				    struct bfd_link_info *link_info
+				    ATTRIBUTE_UNUSED)
+{
+  Elf_Internal_Ehdr *i_ehdrp;	/* ELF file header, internal form.  */
+
+  i_ehdrp = elf_elfheader (abfd);
+  i_ehdrp->e_ident[EI_OSABI] = 0;
+  i_ehdrp->e_ident[EI_ABIVERSION] = AARCH64_ELF_ABI_VERSION;
+}
+
+static enum elf_reloc_type_class
+elf64_aarch64_reloc_type_class (const Elf_Internal_Rela *rela)
+{
+  switch ((int) ELF64_R_TYPE (rela->r_info))
+    {
+    case R_AARCH64_RELATIVE:
+      return reloc_class_relative;
+    case R_AARCH64_JUMP_SLOT:
+      return reloc_class_plt;
+    case R_AARCH64_COPY:
+      return reloc_class_copy;
+    default:
+      return reloc_class_normal;
+    }
+}
+
+/* Set the right machine number for an AArch64 ELF file.  */
+
+static bfd_boolean
+elf64_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.  */
+
+static bfd_boolean
+elf64_aarch64_section_from_shdr (bfd *abfd,
+				 Elf_Internal_Shdr *hdr,
+				 const char *name, int shindex)
+{
+  /* There ought to be a place to keep ELF backend specific flags, but
+     at the moment there isn't one.  We just keep track of the
+     sections by their name, instead.  Fortunately, the ABI gives
+     names for all the AArch64 specific sections, so we will probably get
+     away with this.  */
+  switch (hdr->sh_type)
+    {
+    case SHT_AARCH64_ATTRIBUTES:
+      break;
+
+    default:
+      return FALSE;
+    }
+
+  if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* A structure used to record a list of sections, independently
+   of the next and prev fields in the asection structure.  */
+typedef struct section_list
+{
+  asection *sec;
+  struct section_list *next;
+  struct section_list *prev;
+}
+section_list;
+
+/* Unfortunately we need to keep a list of sections for which
+   an _aarch64_elf_section_data structure has been allocated.  This
+   is because it is possible for functions like elf64_aarch64_write_section
+   to be called on a section which has had an elf_data_structure
+   allocated for it (and so the used_by_bfd field is valid) but
+   for which the AArch64 extended version of this structure - the
+   _aarch64_elf_section_data structure - has not been allocated.  */
+static section_list *sections_with_aarch64_elf_section_data = NULL;
+
+static void
+record_section_with_aarch64_elf_section_data (asection *sec)
+{
+  struct section_list *entry;
+
+  entry = bfd_malloc (sizeof (*entry));
+  if (entry == NULL)
+    return;
+  entry->sec = sec;
+  entry->next = sections_with_aarch64_elf_section_data;
+  entry->prev = NULL;
+  if (entry->next != NULL)
+    entry->next->prev = entry;
+  sections_with_aarch64_elf_section_data = entry;
+}
+
+static struct section_list *
+find_aarch64_elf_section_entry (asection *sec)
+{
+  struct section_list *entry;
+  static struct section_list *last_entry = NULL;
+
+  /* This is a short cut for the typical case where the sections are added
+     to the sections_with_aarch64_elf_section_data list in forward order and
+     then looked up here in backwards order.  This makes a real difference
+     to the ld-srec/sec64k.exp linker test.  */
+  entry = sections_with_aarch64_elf_section_data;
+  if (last_entry != NULL)
+    {
+      if (last_entry->sec == sec)
+	entry = last_entry;
+      else if (last_entry->next != NULL && last_entry->next->sec == sec)
+	entry = last_entry->next;
+    }
+
+  for (; entry; entry = entry->next)
+    if (entry->sec == sec)
+      break;
+
+  if (entry)
+    /* Record the entry prior to this one - it is the entry we are
+       most likely to want to locate next time.  Also this way if we
+       have been called from
+       unrecord_section_with_aarch64_elf_section_data () we will not
+       be caching a pointer that is about to be freed.  */
+    last_entry = entry->prev;
+
+  return entry;
+}
+
+static void
+unrecord_section_with_aarch64_elf_section_data (asection *sec)
+{
+  struct section_list *entry;
+
+  entry = find_aarch64_elf_section_entry (sec);
+
+  if (entry)
+    {
+      if (entry->prev != NULL)
+	entry->prev->next = entry->next;
+      if (entry->next != NULL)
+	entry->next->prev = entry->prev;
+      if (entry == sections_with_aarch64_elf_section_data)
+	sections_with_aarch64_elf_section_data = entry->next;
+      free (entry);
+    }
+}
+
+
+typedef struct
+{
+  void *finfo;
+  struct bfd_link_info *info;
+  asection *sec;
+  int sec_shndx;
+  int (*func) (void *, const char *, Elf_Internal_Sym *,
+	       asection *, struct elf_link_hash_entry *);
+} output_arch_syminfo;
+
+enum map_symbol_type
+{
+  AARCH64_MAP_INSN,
+  AARCH64_MAP_DATA
+};
+
+
+/* Output a single mapping symbol.  */
+
+static bfd_boolean
+elf64_aarch64_output_map_sym (output_arch_syminfo *osi,
+			      enum map_symbol_type type, bfd_vma offset)
+{
+  static const char *names[2] = { "$x", "$d" };
+  Elf_Internal_Sym sym;
+
+  sym.st_value = (osi->sec->output_section->vma
+		  + osi->sec->output_offset + offset);
+  sym.st_size = 0;
+  sym.st_other = 0;
+  sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
+  sym.st_shndx = osi->sec_shndx;
+  return osi->func (osi->finfo, names[type], &sym, osi->sec, NULL) == 1;
+}
+
+
+
+/* Output mapping symbols for PLT entries associated with H.  */
+
+static bfd_boolean
+elf64_aarch64_output_plt_map (struct elf_link_hash_entry *h, void *inf)
+{
+  output_arch_syminfo *osi = (output_arch_syminfo *) inf;
+  bfd_vma addr;
+
+  if (h->root.type == bfd_link_hash_indirect)
+    return TRUE;
+
+  if (h->root.type == bfd_link_hash_warning)
+    /* When warning symbols are created, they **replace** the "real"
+       entry in the hash table, thus we never get to see the real
+       symbol in a hash traversal.  So look at it now.  */
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if (h->plt.offset == (bfd_vma) - 1)
+    return TRUE;
+
+  addr = h->plt.offset;
+  if (addr == 32)
+    {
+      if (!elf64_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr))
+	return FALSE;
+    }
+  return TRUE;
+}
+
+
+/* Output a single local symbol for a generated stub.  */
+
+static bfd_boolean
+elf64_aarch64_output_stub_sym (output_arch_syminfo *osi, const char *name,
+			       bfd_vma offset, bfd_vma size)
+{
+  Elf_Internal_Sym sym;
+
+  sym.st_value = (osi->sec->output_section->vma
+		  + osi->sec->output_offset + offset);
+  sym.st_size = size;
+  sym.st_other = 0;
+  sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
+  sym.st_shndx = osi->sec_shndx;
+  return osi->func (osi->finfo, name, &sym, osi->sec, NULL) == 1;
+}
+
+static bfd_boolean
+aarch64_map_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
+{
+  struct elf64_aarch64_stub_hash_entry *stub_entry;
+  asection *stub_sec;
+  bfd_vma addr;
+  char *stub_name;
+  output_arch_syminfo *osi;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf64_aarch64_stub_hash_entry *) gen_entry;
+  osi = (output_arch_syminfo *) in_arg;
+
+  stub_sec = stub_entry->stub_sec;
+
+  /* Ensure this stub is attached to the current section being
+     processed.  */
+  if (stub_sec != osi->sec)
+    return TRUE;
+
+  addr = (bfd_vma) stub_entry->stub_offset;
+
+  stub_name = stub_entry->output_name;
+
+  switch (stub_entry->stub_type)
+    {
+    case aarch64_stub_adrp_branch:
+      if (!elf64_aarch64_output_stub_sym (osi, stub_name, addr,
+					  sizeof (aarch64_adrp_branch_stub)))
+	return FALSE;
+      if (!elf64_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr))
+	return FALSE;
+      break;
+    case aarch64_stub_long_branch:
+      if (!elf64_aarch64_output_stub_sym
+	  (osi, stub_name, addr, sizeof (aarch64_long_branch_stub)))
+	return FALSE;
+      if (!elf64_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr))
+	return FALSE;
+      if (!elf64_aarch64_output_map_sym (osi, AARCH64_MAP_DATA, addr + 16))
+	return FALSE;
+      break;
+    default:
+      BFD_FAIL ();
+    }
+
+  return TRUE;
+}
+
+/* Output mapping symbols for linker generated sections.  */
+
+static bfd_boolean
+elf64_aarch64_output_arch_local_syms (bfd *output_bfd,
+				      struct bfd_link_info *info,
+				      void *finfo,
+				      int (*func) (void *, const char *,
+						   Elf_Internal_Sym *,
+						   asection *,
+						   struct elf_link_hash_entry
+						   *))
+{
+  output_arch_syminfo osi;
+  struct elf64_aarch64_link_hash_table *htab;
+
+  htab = elf64_aarch64_hash_table (info);
+
+  osi.finfo = finfo;
+  osi.info = info;
+  osi.func = func;
+
+  /* Long calls stubs.  */
+  if (htab->stub_bfd && htab->stub_bfd->sections)
+    {
+      asection *stub_sec;
+
+      for (stub_sec = htab->stub_bfd->sections;
+	   stub_sec != NULL; stub_sec = stub_sec->next)
+	{
+	  /* Ignore non-stub sections.  */
+	  if (!strstr (stub_sec->name, STUB_SUFFIX))
+	    continue;
+
+	  osi.sec = stub_sec;
+
+	  osi.sec_shndx = _bfd_elf_section_from_bfd_section
+	    (output_bfd, osi.sec->output_section);
+
+	  bfd_hash_traverse (&htab->stub_hash_table, aarch64_map_one_stub,
+			     &osi);
+	}
+    }
+
+  /* Finally, output mapping symbols for the PLT.  */
+  if (!htab->root.splt || htab->root.splt->size == 0)
+    return TRUE;
+
+  /* For now live without mapping symbols for the plt.  */
+  osi.sec_shndx = _bfd_elf_section_from_bfd_section
+    (output_bfd, htab->root.splt->output_section);
+  osi.sec = htab->root.splt;
+
+  elf_link_hash_traverse (&htab->root, elf64_aarch64_output_plt_map,
+			  (void *) &osi);
+
+  return TRUE;
+
+}
+
+/* Allocate target specific section data.  */
+
+static bfd_boolean
+elf64_aarch64_new_section_hook (bfd *abfd, asection *sec)
+{
+  if (!sec->used_by_bfd)
+    {
+      _aarch64_elf_section_data *sdata;
+      bfd_size_type amt = sizeof (*sdata);
+
+      sdata = bfd_zalloc (abfd, amt);
+      if (sdata == NULL)
+	return FALSE;
+      sec->used_by_bfd = sdata;
+    }
+
+  record_section_with_aarch64_elf_section_data (sec);
+
+  return _bfd_elf_new_section_hook (abfd, sec);
+}
+
+
+static void
+unrecord_section_via_map_over_sections (bfd *abfd ATTRIBUTE_UNUSED,
+					asection *sec,
+					void *ignore ATTRIBUTE_UNUSED)
+{
+  unrecord_section_with_aarch64_elf_section_data (sec);
+}
+
+static bfd_boolean
+elf64_aarch64_close_and_cleanup (bfd *abfd)
+{
+  if (abfd->sections)
+    bfd_map_over_sections (abfd,
+			   unrecord_section_via_map_over_sections, NULL);
+
+  return _bfd_elf_close_and_cleanup (abfd);
+}
+
+static bfd_boolean
+elf64_aarch64_bfd_free_cached_info (bfd *abfd)
+{
+  if (abfd->sections)
+    bfd_map_over_sections (abfd,
+			   unrecord_section_via_map_over_sections, NULL);
+
+  return _bfd_free_cached_info (abfd);
+}
+
+static bfd_boolean
+elf64_aarch64_is_function_type (unsigned int type)
+{
+  return type == STT_FUNC;
+}
+
+/* Create dynamic sections. This is different from the ARM backend in that
+   the got, plt, gotplt and their relocation sections are all created in the
+   standard part of the bfd elf backend.  */
+
+static bfd_boolean
+elf64_aarch64_create_dynamic_sections (bfd *dynobj,
+				       struct bfd_link_info *info)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  struct elf_link_hash_entry *h;
+
+  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
+    return FALSE;
+
+  htab = elf64_aarch64_hash_table (info);
+  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
+  if (!info->shared)
+    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
+
+  if (!htab->sdynbss || (!info->shared && !htab->srelbss))
+    abort ();
+
+  /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
+     dynobj's .got section.  We don't do this in the linker script
+     because we don't want to define the symbol if we are not creating
+     a global offset table.  */
+  h = _bfd_elf_define_linkage_sym (dynobj, info,
+				   htab->root.sgot, "_GLOBAL_OFFSET_TABLE_");
+  elf_hash_table (info)->hgot = h;
+  if (h == NULL)
+    return FALSE;
+
+  return TRUE;
+}
+
+
+/* Allocate space in .plt, .got and associated reloc sections for
+   dynamic relocs.  */
+
+static bfd_boolean
+elf64_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
+{
+  struct bfd_link_info *info;
+  struct elf64_aarch64_link_hash_table *htab;
+  struct elf64_aarch64_link_hash_entry *eh;
+  struct elf_dyn_relocs *p;
+
+  /* An example of a bfd_link_hash_indirect symbol is versioned
+     symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
+     -> __gxx_personality_v0(bfd_link_hash_defined)
+
+     There is no need to process bfd_link_hash_indirect symbols here
+     because we will also be presented with the concrete instance of
+     the symbol and elf64_aarch64_copy_indirect_symbol () will have been
+     called to copy all relevant data from the generic to the concrete
+     symbol instance.
+   */
+  if (h->root.type == bfd_link_hash_indirect)
+    return TRUE;
+
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  info = (struct bfd_link_info *) inf;
+  htab = elf64_aarch64_hash_table (info);
+
+  if (htab->root.dynamic_sections_created && h->plt.refcount > 0)
+    {
+      /* Make sure this symbol is output as a dynamic symbol.
+         Undefined weak syms won't yet be marked as dynamic.  */
+      if (h->dynindx == -1 && !h->forced_local)
+	{
+	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
+	    return FALSE;
+	}
+
+      if (info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
+	{
+	  asection *s = htab->root.splt;
+
+	  /* If this is the first .plt entry, make room for the special
+	     first entry.  */
+	  if (s->size == 0)
+	    s->size += htab->plt_header_size;
+
+	  h->plt.offset = s->size;
+
+	  /* If this symbol is not defined in a regular file, and we are
+	     not generating a shared library, then set the symbol to this
+	     location in the .plt.  This is required to make function
+	     pointers compare as equal between the normal executable and
+	     the shared library.  */
+	  if (!info->shared && !h->def_regular)
+	    {
+	      h->root.u.def.section = s;
+	      h->root.u.def.value = h->plt.offset;
+	    }
+
+	  /* Make room for this entry. For now we only create the
+	     small model PLT entries. We later need to find a way
+	     of relaxing into these from the large model PLT entries.  */
+	  s->size += PLT_SMALL_ENTRY_SIZE;
+
+	  /* We also need to make an entry in the .got.plt section, which
+	     will be placed in the .got section by the linker script.  */
+	  htab->root.sgotplt->size += GOT_ENTRY_SIZE;
+
+	  /* We also need to make an entry in the .rela.plt section.  */
+	  htab->root.srelplt->size += RELOC_SIZE (htab);
+
+	  /* We need to ensure that all GOT entries that serve the PLT
+	     are consecutive with the special GOT slots [0] [1] and
+	     [2]. Any addtional relocations, such as
+	     R_AARCH64_TLSDESC, must be placed after the PLT related
+	     entries.  We abuse the reloc_count such that during
+	     sizing we adjust reloc_count to indicate the number of
+	     PLT related reserved entries.  In subsequent phases when
+	     filling in the contents of the reloc entries, PLT related
+	     entries are placed by computing their PLT index (0
+	     .. reloc_count). While other none PLT relocs are placed
+	     at the slot indicated by reloc_count and reloc_count is
+	     updated.  */
+
+	  htab->root.srelplt->reloc_count++;
+	}
+      else
+	{
+	  h->plt.offset = (bfd_vma) - 1;
+	  h->needs_plt = 0;
+	}
+    }
+  else
+    {
+      h->plt.offset = (bfd_vma) - 1;
+      h->needs_plt = 0;
+    }
+
+  eh = (struct elf64_aarch64_link_hash_entry *) h;
+  eh->tlsdesc_got_jump_table_offset = (bfd_vma) - 1;
+
+  if (h->got.refcount > 0)
+    {
+      bfd_boolean dyn;
+      unsigned got_type = elf64_aarch64_hash_entry (h)->got_type;
+
+      h->got.offset = (bfd_vma) - 1;
+
+      dyn = htab->root.dynamic_sections_created;
+
+      /* Make sure this symbol is output as a dynamic symbol.
+         Undefined weak syms won't yet be marked as dynamic.  */
+      if (dyn && h->dynindx == -1 && !h->forced_local)
+	{
+	  if (!bfd_elf_link_record_dynamic_symbol (info, h))
+	    return FALSE;
+	}
+
+      if (got_type == GOT_UNKNOWN)
+	{
+	}
+      else if (got_type == GOT_NORMAL)
+	{
+	  h->got.offset = htab->root.sgot->size;
+	  htab->root.sgot->size += GOT_ENTRY_SIZE;
+	  if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+	       || h->root.type != bfd_link_hash_undefweak)
+	      && (info->shared
+		  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
+	    {
+	      htab->root.srelgot->size += RELOC_SIZE (htab);
+	    }
+	}
+      else
+	{
+	  int indx;
+	  if (got_type & GOT_TLSDESC_GD)
+	    {
+	      eh->tlsdesc_got_jump_table_offset =
+		(htab->root.sgotplt->size
+		 - aarch64_compute_jump_table_size (htab));
+	      htab->root.sgotplt->size += GOT_ENTRY_SIZE * 2;
+	      h->got.offset = (bfd_vma) - 2;
+	    }
+
+	  if (got_type & GOT_TLS_GD)
+	    {
+	      h->got.offset = htab->root.sgot->size;
+	      htab->root.sgot->size += GOT_ENTRY_SIZE * 2;
+	    }
+
+	  if (got_type & GOT_TLS_IE)
+	    {
+	      h->got.offset = htab->root.sgot->size;
+	      htab->root.sgot->size += GOT_ENTRY_SIZE;
+	    }
+
+	  indx = h && h->dynindx != -1 ? h->dynindx : 0;
+	  if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+	       || h->root.type != bfd_link_hash_undefweak)
+	      && (info->shared
+		  || indx != 0
+		  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
+	    {
+	      if (got_type & GOT_TLSDESC_GD)
+		{
+		  htab->root.srelplt->size += RELOC_SIZE (htab);
+		  /* Note reloc_count not incremented here!  We have
+		     already adjusted reloc_count for this relocation
+		     type.  */
+
+		  /* TLSDESC PLT is now needed, but not yet determined.  */
+		  htab->tlsdesc_plt = (bfd_vma) - 1;
+		}
+
+	      if (got_type & GOT_TLS_GD)
+		htab->root.srelgot->size += RELOC_SIZE (htab) * 2;
+
+	      if (got_type & GOT_TLS_IE)
+		htab->root.srelgot->size += RELOC_SIZE (htab);
+	    }
+	}
+    }
+  else
+    {
+      h->got.offset = (bfd_vma) - 1;
+    }
+
+  if (eh->dyn_relocs == NULL)
+    return TRUE;
+
+  /* In the shared -Bsymbolic case, discard space allocated for
+     dynamic pc-relative relocs against symbols which turn out to be
+     defined in regular objects.  For the normal shared case, discard
+     space for pc-relative relocs that have become local due to symbol
+     visibility changes.  */
+
+  if (info->shared)
+    {
+      /* Relocs that use pc_count are those that appear on a call
+         insn, or certain REL relocs that can generated via assembly.
+         We want calls to protected symbols to resolve directly to the
+         function rather than going via the plt.  If people want
+         function pointer comparisons to work as expected then they
+         should avoid writing weird assembly.  */
+      if (SYMBOL_CALLS_LOCAL (info, h))
+	{
+	  struct elf_dyn_relocs **pp;
+
+	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL;)
+	    {
+	      p->count -= p->pc_count;
+	      p->pc_count = 0;
+	      if (p->count == 0)
+		*pp = p->next;
+	      else
+		pp = &p->next;
+	    }
+	}
+
+      /* Also discard relocs on undefined weak syms with non-default
+         visibility.  */
+      if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak)
+	{
+	  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+	    eh->dyn_relocs = NULL;
+
+	  /* Make sure undefined weak symbols are output as a dynamic
+	     symbol in PIEs.  */
+	  else if (h->dynindx == -1
+		   && !h->forced_local
+		   && !bfd_elf_link_record_dynamic_symbol (info, h))
+	    return FALSE;
+	}
+
+    }
+  else if (ELIMINATE_COPY_RELOCS)
+    {
+      /* For the non-shared case, discard space for relocs against
+         symbols which turn out to need copy relocs or are not
+         dynamic.  */
+
+      if (!h->non_got_ref
+	  && ((h->def_dynamic
+	       && !h->def_regular)
+	      || (htab->root.dynamic_sections_created
+		  && (h->root.type == bfd_link_hash_undefweak
+		      || h->root.type == bfd_link_hash_undefined))))
+	{
+	  /* Make sure this symbol is output as a dynamic symbol.
+	     Undefined weak syms won't yet be marked as dynamic.  */
+	  if (h->dynindx == -1
+	      && !h->forced_local
+	      && !bfd_elf_link_record_dynamic_symbol (info, h))
+	    return FALSE;
+
+	  /* If that succeeded, we know we'll be keeping all the
+	     relocs.  */
+	  if (h->dynindx != -1)
+	    goto keep;
+	}
+
+      eh->dyn_relocs = NULL;
+
+    keep:;
+    }
+
+  /* Finally, allocate space.  */
+  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+    {
+      asection *sreloc;
+
+      sreloc = elf_section_data (p->sec)->sreloc;
+
+      BFD_ASSERT (sreloc != NULL);
+
+      sreloc->size += p->count * RELOC_SIZE (htab);
+    }
+
+  return TRUE;
+}
+
+
+
+
+/* This is the most important function of all . Innocuosly named
+   though !  */
+static bfd_boolean
+elf64_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+				     struct bfd_link_info *info)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  bfd *dynobj;
+  asection *s;
+  bfd_boolean relocs;
+  bfd *ibfd;
+
+  htab = elf64_aarch64_hash_table ((info));
+  dynobj = htab->root.dynobj;
+
+  BFD_ASSERT (dynobj != NULL);
+
+  if (htab->root.dynamic_sections_created)
+    {
+      if (info->executable)
+	{
+	  s = bfd_get_linker_section (dynobj, ".interp");
+	  if (s == NULL)
+	    abort ();
+	  s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+	}
+    }
+
+  /* Set up .got offsets for local syms, and space for local dynamic
+     relocs.  */
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+    {
+      struct elf_aarch64_local_symbol *locals = NULL;
+      Elf_Internal_Shdr *symtab_hdr;
+      asection *srel;
+      unsigned int i;
+
+      if (!is_aarch64_elf (ibfd))
+	continue;
+
+      for (s = ibfd->sections; s != NULL; s = s->next)
+	{
+	  struct elf_dyn_relocs *p;
+
+	  for (p = (struct elf_dyn_relocs *)
+	       (elf_section_data (s)->local_dynrel); p != NULL; p = p->next)
+	    {
+	      if (!bfd_is_abs_section (p->sec)
+		  && bfd_is_abs_section (p->sec->output_section))
+		{
+		  /* Input section has been discarded, either because
+		     it is a copy of a linkonce section or due to
+		     linker script /DISCARD/, so we'll be discarding
+		     the relocs too.  */
+		}
+	      else if (p->count != 0)
+		{
+		  srel = elf_section_data (p->sec)->sreloc;
+		  srel->size += p->count * RELOC_SIZE (htab);
+		  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
+		    info->flags |= DF_TEXTREL;
+		}
+	    }
+	}
+
+      locals = elf64_aarch64_locals (ibfd);
+      if (!locals)
+	continue;
+
+      symtab_hdr = &elf_symtab_hdr (ibfd);
+      srel = htab->root.srelgot;
+      for (i = 0; i < symtab_hdr->sh_info; i++)
+	{
+	  locals[i].got_offset = (bfd_vma) - 1;
+	  locals[i].tlsdesc_got_jump_table_offset = (bfd_vma) - 1;
+	  if (locals[i].got_refcount > 0)
+	    {
+	      unsigned got_type = locals[i].got_type;
+	      if (got_type & GOT_TLSDESC_GD)
+		{
+		  locals[i].tlsdesc_got_jump_table_offset =
+		    (htab->root.sgotplt->size
+		     - aarch64_compute_jump_table_size (htab));
+		  htab->root.sgotplt->size += GOT_ENTRY_SIZE * 2;
+		  locals[i].got_offset = (bfd_vma) - 2;
+		}
+
+	      if (got_type & GOT_TLS_GD)
+		{
+		  locals[i].got_offset = htab->root.sgot->size;
+		  htab->root.sgot->size += GOT_ENTRY_SIZE * 2;
+		}
+
+	      if (got_type & GOT_TLS_IE)
+		{
+		  locals[i].got_offset = htab->root.sgot->size;
+		  htab->root.sgot->size += GOT_ENTRY_SIZE;
+		}
+
+	      if (got_type == GOT_UNKNOWN)
+		{
+		}
+
+	      if (got_type == GOT_NORMAL)
+		{
+		}
+
+	      if (info->shared)
+		{
+		  if (got_type & GOT_TLSDESC_GD)
+		    {
+		      htab->root.srelplt->size += RELOC_SIZE (htab);
+		      /* Note RELOC_COUNT not incremented here! */
+		      htab->tlsdesc_plt = (bfd_vma) - 1;
+		    }
+
+		  if (got_type & GOT_TLS_GD)
+		    htab->root.srelgot->size += RELOC_SIZE (htab) * 2;
+
+		  if (got_type & GOT_TLS_IE)
+		    htab->root.srelgot->size += RELOC_SIZE (htab);
+		}
+	    }
+	  else
+	    {
+	      locals[i].got_refcount = (bfd_vma) - 1;
+	    }
+	}
+    }
+
+
+  /* Allocate global sym .plt and .got entries, and space for global
+     sym dynamic relocs.  */
+  elf_link_hash_traverse (&htab->root, elf64_aarch64_allocate_dynrelocs,
+			  info);
+
+
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     for them, it suffices to multiply the reloc count by the jump
+     slot size.  */
+
+  if (htab->root.srelplt)
+    htab->sgotplt_jump_table_size = aarch64_compute_jump_table_size (htab);
+
+  if (htab->tlsdesc_plt)
+    {
+      if (htab->root.splt->size == 0)
+	htab->root.splt->size += PLT_ENTRY_SIZE;
+
+      htab->tlsdesc_plt = htab->root.splt->size;
+      htab->root.splt->size += PLT_TLSDESC_ENTRY_SIZE;
+
+      /* If we're not using lazy TLS relocations, don't generate the
+         GOT entry required.  */
+      if (!(info->flags & DF_BIND_NOW))
+	{
+	  htab->dt_tlsdesc_got = htab->root.sgot->size;
+	  htab->root.sgot->size += GOT_ENTRY_SIZE;
+	}
+    }
+
+  /* We now have determined the sizes of the various dynamic sections.
+     Allocate memory for them.  */
+  relocs = FALSE;
+  for (s = dynobj->sections; s != NULL; s = s->next)
+    {
+      if ((s->flags & SEC_LINKER_CREATED) == 0)
+	continue;
+
+      if (s == htab->root.splt
+	  || s == htab->root.sgot
+	  || s == htab->root.sgotplt
+	  || s == htab->root.iplt
+	  || s == htab->root.igotplt || s == htab->sdynbss)
+	{
+	  /* Strip this section if we don't need it; see the
+	     comment below.  */
+	}
+      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
+	{
+	  if (s->size != 0 && s != htab->root.srelplt)
+	    relocs = TRUE;
+
+	  /* We use the reloc_count field as a counter if we need
+	     to copy relocs into the output file.  */
+	  if (s != htab->root.srelplt)
+	    s->reloc_count = 0;
+	}
+      else
+	{
+	  /* It's not one of our sections, so don't allocate space.  */
+	  continue;
+	}
+
+      if (s->size == 0)
+	{
+	  /* If we don't need this section, strip it from the
+	     output file.  This is mostly to handle .rela.bss and
+	     .rela.plt.  We must create both sections in
+	     create_dynamic_sections, because they must be created
+	     before the linker maps input sections to output
+	     sections.  The linker does that before
+	     adjust_dynamic_symbol is called, and it is that
+	     function which decides whether anything needs to go
+	     into these sections.  */
+
+	  s->flags |= SEC_EXCLUDE;
+	  continue;
+	}
+
+      if ((s->flags & SEC_HAS_CONTENTS) == 0)
+	continue;
+
+      /* Allocate memory for the section contents.  We use bfd_zalloc
+         here in case unused entries are not reclaimed before the
+         section's contents are written out.  This should not happen,
+         but this way if it does, we get a R_AARCH64_NONE reloc instead
+         of garbage.  */
+      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
+      if (s->contents == NULL)
+	return FALSE;
+    }
+
+  if (htab->root.dynamic_sections_created)
+    {
+      /* Add some entries to the .dynamic section.  We fill in the
+         values later, in elf64_aarch64_finish_dynamic_sections, but we
+         must add the entries now so that we get the correct size for
+         the .dynamic section.  The DT_DEBUG entry is filled in by the
+         dynamic linker and used by the debugger.  */
+#define add_dynamic_entry(TAG, VAL)			\
+      _bfd_elf_add_dynamic_entry (info, TAG, VAL)
+
+      if (info->executable)
+	{
+	  if (!add_dynamic_entry (DT_DEBUG, 0))
+	    return FALSE;
+	}
+
+      if (htab->root.splt->size != 0)
+	{
+	  if (!add_dynamic_entry (DT_PLTGOT, 0)
+	      || !add_dynamic_entry (DT_PLTRELSZ, 0)
+	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+	      || !add_dynamic_entry (DT_JMPREL, 0))
+	    return FALSE;
+
+	  if (htab->tlsdesc_plt
+	      && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
+		  || !add_dynamic_entry (DT_TLSDESC_GOT, 0)))
+	    return FALSE;
+	}
+
+      if (relocs)
+	{
+	  if (!add_dynamic_entry (DT_RELA, 0)
+	      || !add_dynamic_entry (DT_RELASZ, 0)
+	      || !add_dynamic_entry (DT_RELAENT, RELOC_SIZE (htab)))
+	    return FALSE;
+
+	  /* If any dynamic relocs apply to a read-only section,
+	     then we need a DT_TEXTREL entry.  */
+	  if ((info->flags & DF_TEXTREL) != 0)
+	    {
+	      if (!add_dynamic_entry (DT_TEXTREL, 0))
+		return FALSE;
+	    }
+	}
+    }
+#undef add_dynamic_entry
+
+  return TRUE;
+
+
+}
+
+static inline void
+elf64_aarch64_update_plt_entry (bfd *output_bfd,
+				unsigned int r_type,
+				bfd_byte *plt_entry, bfd_vma value)
+{
+  reloc_howto_type *howto;
+  howto = elf64_aarch64_howto_from_type (r_type);
+  bfd_elf_aarch64_put_addend (output_bfd, plt_entry, howto, value);
+}
+
+static void
+elf64_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
+				       struct elf64_aarch64_link_hash_table
+				       *htab, bfd *output_bfd)
+{
+  bfd_byte *plt_entry;
+  bfd_vma plt_index;
+  bfd_vma got_offset;
+  bfd_vma gotplt_entry_address;
+  bfd_vma plt_entry_address;
+  Elf_Internal_Rela rela;
+  bfd_byte *loc;
+
+  plt_index = (h->plt.offset - htab->plt_header_size) / htab->plt_entry_size;
+
+  /* Offset in the GOT is PLT index plus got GOT headers(3)
+     times 8.  */
+  got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
+  plt_entry = htab->root.splt->contents + h->plt.offset;
+  plt_entry_address = htab->root.splt->output_section->vma
+    + htab->root.splt->output_section->output_offset + h->plt.offset;
+  gotplt_entry_address = htab->root.sgotplt->output_section->vma +
+    htab->root.sgotplt->output_offset + got_offset;
+
+  /* Copy in the boiler-plate for the PLTn entry.  */
+  memcpy (plt_entry, elf64_aarch64_small_plt_entry, PLT_SMALL_ENTRY_SIZE);
+
+  /* Fill in the top 21 bits for this: ADRP x16, PLT_GOT + n * 8.
+     ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_ADR_PREL_PG_HI21,
+				  plt_entry,
+				  PG (gotplt_entry_address) -
+				  PG (plt_entry_address));
+
+  /* Fill in the lo12 bits for the load from the pltgot.  */
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_LDST64_ABS_LO12_NC,
+				  plt_entry + 4,
+				  PG_OFFSET (gotplt_entry_address));
+
+  /* Fill in the the lo12 bits for the add from the pltgot entry.  */
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_ADD_ABS_LO12_NC,
+				  plt_entry + 8,
+				  PG_OFFSET (gotplt_entry_address));
+
+  /* All the GOTPLT Entries are essentially initialized to PLT0.  */
+  bfd_put_64 (output_bfd,
+	      (htab->root.splt->output_section->vma
+	       + htab->root.splt->output_offset),
+	      htab->root.sgotplt->contents + got_offset);
+
+  /* Fill in the entry in the .rela.plt section.  */
+  rela.r_offset = gotplt_entry_address;
+  rela.r_info = ELF64_R_INFO (h->dynindx, R_AARCH64_JUMP_SLOT);
+  rela.r_addend = 0;
+
+  /* Compute the relocation entry to used based on PLT index and do
+     not adjust reloc_count. The reloc_count has already been adjusted
+     to account for this entry.  */
+  loc = htab->root.srelplt->contents + plt_index * RELOC_SIZE (htab);
+  bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+}
+
+/* Size sections even though they're not dynamic.  We use it to setup
+   _TLS_MODULE_BASE_, if needed.  */
+
+static bfd_boolean
+elf64_aarch64_always_size_sections (bfd *output_bfd,
+				    struct bfd_link_info *info)
+{
+  asection *tls_sec;
+
+  if (info->relocatable)
+    return TRUE;
+
+  tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_", TRUE, TRUE, FALSE);
+
+      if (tlsbase)
+	{
+	  struct bfd_link_hash_entry *h = NULL;
+	  const struct elf_backend_data *bed =
+	    get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE, bed->collect, &h)))
+	    return FALSE;
+
+	  tlsbase->type = STT_TLS;
+	  tlsbase = (struct elf_link_hash_entry *) h;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  return TRUE;
+}
+
+/* Finish up dynamic symbol handling.  We set the contents of various
+   dynamic sections here.  */
+static bfd_boolean
+elf64_aarch64_finish_dynamic_symbol (bfd *output_bfd,
+				     struct bfd_link_info *info,
+				     struct elf_link_hash_entry *h,
+				     Elf_Internal_Sym *sym)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  htab = elf64_aarch64_hash_table (info);
+
+  if (h->plt.offset != (bfd_vma) - 1)
+    {
+      /* This symbol has an entry in the procedure linkage table.  Set
+         it up.  */
+
+      if (h->dynindx == -1
+	  || htab->root.splt == NULL
+	  || htab->root.sgotplt == NULL || htab->root.srelplt == NULL)
+	abort ();
+
+      elf64_aarch64_create_small_pltn_entry (h, htab, 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.  */
+	  sym->st_shndx = SHN_UNDEF;
+	}
+    }
+
+  if (h->got.offset != (bfd_vma) - 1
+      && elf64_aarch64_hash_entry (h)->got_type == GOT_NORMAL)
+    {
+      Elf_Internal_Rela rela;
+      bfd_byte *loc;
+
+      /* This symbol has an entry in the global offset table.  Set it
+         up.  */
+      if (htab->root.sgot == NULL || htab->root.srelgot == NULL)
+	abort ();
+
+      rela.r_offset = (htab->root.sgot->output_section->vma
+		       + htab->root.sgot->output_offset
+		       + (h->got.offset & ~(bfd_vma) 1));
+
+      if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
+	{
+	  if (!h->def_regular)
+	    return FALSE;
+
+	  BFD_ASSERT ((h->got.offset & 1) != 0);
+	  rela.r_info = ELF64_R_INFO (0, R_AARCH64_RELATIVE);
+	  rela.r_addend = (h->root.u.def.value
+			   + h->root.u.def.section->output_section->vma
+			   + h->root.u.def.section->output_offset);
+	}
+      else
+	{
+	  BFD_ASSERT ((h->got.offset & 1) == 0);
+	  bfd_put_64 (output_bfd, (bfd_vma) 0,
+		      htab->root.sgot->contents + h->got.offset);
+	  rela.r_info = ELF64_R_INFO (h->dynindx, R_AARCH64_GLOB_DAT);
+	  rela.r_addend = 0;
+	}
+
+      loc = htab->root.srelgot->contents;
+      loc += htab->root.srelgot->reloc_count++ * RELOC_SIZE (htab);
+      bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+    }
+
+  if (h->needs_copy)
+    {
+      Elf_Internal_Rela rela;
+      bfd_byte *loc;
+
+      /* This symbol needs a copy reloc.  Set it up.  */
+
+      if (h->dynindx == -1
+	  || (h->root.type != bfd_link_hash_defined
+	      && h->root.type != bfd_link_hash_defweak)
+	  || htab->srelbss == NULL)
+	abort ();
+
+      rela.r_offset = (h->root.u.def.value
+		       + h->root.u.def.section->output_section->vma
+		       + h->root.u.def.section->output_offset);
+      rela.r_info = ELF64_R_INFO (h->dynindx, R_AARCH64_COPY);
+      rela.r_addend = 0;
+      loc = htab->srelbss->contents;
+      loc += htab->srelbss->reloc_count++ * RELOC_SIZE (htab);
+      bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+    }
+
+  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  SYM may
+     be NULL for local symbols.  */
+  if (sym != NULL
+      && (strcmp (h->root.root.string, "_DYNAMIC") == 0
+	  || h == elf_hash_table (info)->hgot))
+    sym->st_shndx = SHN_ABS;
+
+  return TRUE;
+}
+
+static void
+elf64_aarch64_init_small_plt0_entry (bfd *output_bfd ATTRIBUTE_UNUSED,
+				     struct elf64_aarch64_link_hash_table
+				     *htab)
+{
+  /* Fill in PLT0. Fixme:RR Note this doesn't distinguish between
+     small and large plts and at the minute just generates
+     the small PLT.  */
+
+  /* PLT0 of the small PLT looks like this -
+     stp x16, x30, [sp, #-16]!		// Save the reloc and lr on stack.
+     adrp x16, PLT_GOT + 16		// Get the page base of the GOTPLT
+     ldr  x17, [x16, #:lo12:PLT_GOT+16] // Load the address of the
+					// symbol resolver
+     add  x16, x16, #:lo12:PLT_GOT+16   // Load the lo12 bits of the
+					// GOTPLT entry for this.
+     br   x17
+   */
+  bfd_vma plt_got_base;
+  bfd_vma plt_base;
+
+
+  memcpy (htab->root.splt->contents, elf64_aarch64_small_plt0_entry,
+	  PLT_ENTRY_SIZE);
+  elf_section_data (htab->root.splt->output_section)->this_hdr.sh_entsize =
+    PLT_ENTRY_SIZE;
+
+  plt_got_base = (htab->root.sgotplt->output_section->vma
+		  + htab->root.sgotplt->output_offset);
+
+  plt_base = htab->root.splt->output_section->vma +
+    htab->root.splt->output_section->output_offset;
+
+  /* Fill in the top 21 bits for this: ADRP x16, PLT_GOT + n * 8.
+     ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_ADR_PREL_PG_HI21,
+				  htab->root.splt->contents + 4,
+				  PG (plt_got_base + 16) - PG (plt_base + 4));
+
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_LDST64_ABS_LO12_NC,
+				  htab->root.splt->contents + 8,
+				  PG_OFFSET (plt_got_base + 16));
+
+  elf64_aarch64_update_plt_entry (output_bfd, R_AARCH64_ADD_ABS_LO12_NC,
+				  htab->root.splt->contents + 12,
+				  PG_OFFSET (plt_got_base + 16));
+}
+
+static bfd_boolean
+elf64_aarch64_finish_dynamic_sections (bfd *output_bfd,
+				       struct bfd_link_info *info)
+{
+  struct elf64_aarch64_link_hash_table *htab;
+  bfd *dynobj;
+  asection *sdyn;
+
+  htab = elf64_aarch64_hash_table (info);
+  dynobj = htab->root.dynobj;
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
+
+  if (htab->root.dynamic_sections_created)
+    {
+      Elf64_External_Dyn *dyncon, *dynconend;
+
+      if (sdyn == NULL || htab->root.sgot == NULL)
+	abort ();
+
+      dyncon = (Elf64_External_Dyn *) sdyn->contents;
+      dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size);
+      for (; dyncon < dynconend; dyncon++)
+	{
+	  Elf_Internal_Dyn dyn;
+	  asection *s;
+
+	  bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
+
+	  switch (dyn.d_tag)
+	    {
+	    default:
+	      continue;
+
+	    case DT_PLTGOT:
+	      s = htab->root.sgotplt;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+	      break;
+
+	    case DT_JMPREL:
+	      dyn.d_un.d_ptr = htab->root.srelplt->output_section->vma;
+	      break;
+
+	    case DT_PLTRELSZ:
+	      s = htab->root.srelplt->output_section;
+	      dyn.d_un.d_val = s->size;
+	      break;
+
+	    case DT_RELASZ:
+	      /* The procedure linkage table relocs (DT_JMPREL) should
+		 not be included in the overall relocs (DT_RELA).
+		 Therefore, we override the DT_RELASZ entry here to
+		 make it not include the JMPREL relocs.  Since the
+		 linker script arranges for .rela.plt to follow all
+		 other relocation sections, we don't have to worry
+		 about changing the DT_RELA entry.  */
+	      if (htab->root.srelplt != NULL)
+		{
+		  s = htab->root.srelplt->output_section;
+		  dyn.d_un.d_val -= s->size;
+		}
+	      break;
+
+	    case DT_TLSDESC_PLT:
+	      s = htab->root.splt;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_plt;
+	      break;
+
+	    case DT_TLSDESC_GOT:
+	      s = htab->root.sgot;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->dt_tlsdesc_got;
+	      break;
+	    }
+
+	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
+	}
+
+    }
+
+  /* Fill in the special first entry in the procedure linkage table.  */
+  if (htab->root.splt && htab->root.splt->size > 0)
+    {
+      elf64_aarch64_init_small_plt0_entry (output_bfd, htab);
+
+      elf_section_data (htab->root.splt->output_section)->
+	this_hdr.sh_entsize = htab->plt_entry_size;
+
+
+      if (htab->tlsdesc_plt)
+	{
+	  bfd_put_64 (output_bfd, (bfd_vma) 0,
+		      htab->root.sgot->contents + htab->dt_tlsdesc_got);
+
+	  memcpy (htab->root.splt->contents + htab->tlsdesc_plt,
+		  elf64_aarch64_tlsdesc_small_plt_entry,
+		  sizeof (elf64_aarch64_tlsdesc_small_plt_entry));
+
+	  {
+	    bfd_vma adrp1_addr =
+	      htab->root.splt->output_section->vma
+	      + htab->root.splt->output_offset + htab->tlsdesc_plt + 4;
+
+	    bfd_vma adrp2_addr =
+	      htab->root.splt->output_section->vma
+	      + htab->root.splt->output_offset + htab->tlsdesc_plt + 8;
+
+	    bfd_vma got_addr =
+	      htab->root.sgot->output_section->vma
+	      + htab->root.sgot->output_offset;
+
+	    bfd_vma pltgot_addr =
+	      htab->root.sgotplt->output_section->vma
+	      + htab->root.sgotplt->output_offset;
+
+	    bfd_vma dt_tlsdesc_got = got_addr + htab->dt_tlsdesc_got;
+	    bfd_vma opcode;
+
+	    /* adrp x2, DT_TLSDESC_GOT */
+	    opcode = bfd_get_32 (output_bfd,
+				 htab->root.splt->contents
+				 + htab->tlsdesc_plt + 4);
+	    opcode = reencode_adr_imm
+	      (opcode, (PG (dt_tlsdesc_got) - PG (adrp1_addr)) >> 12);
+	    bfd_put_32 (output_bfd, opcode,
+			htab->root.splt->contents + htab->tlsdesc_plt + 4);
+
+	    /* adrp x3, 0 */
+	    opcode = bfd_get_32 (output_bfd,
+				 htab->root.splt->contents
+				 + htab->tlsdesc_plt + 8);
+	    opcode = reencode_adr_imm
+	      (opcode, (PG (pltgot_addr) - PG (adrp2_addr)) >> 12);
+	    bfd_put_32 (output_bfd, opcode,
+			htab->root.splt->contents + htab->tlsdesc_plt + 8);
+
+	    /* ldr x2, [x2, #0] */
+	    opcode = bfd_get_32 (output_bfd,
+				 htab->root.splt->contents
+				 + htab->tlsdesc_plt + 12);
+	    opcode = reencode_ldst_pos_imm (opcode,
+					    PG_OFFSET (dt_tlsdesc_got) >> 3);
+	    bfd_put_32 (output_bfd, opcode,
+			htab->root.splt->contents + htab->tlsdesc_plt + 12);
+
+	    /* add x3, x3, 0 */
+	    opcode = bfd_get_32 (output_bfd,
+				 htab->root.splt->contents
+				 + htab->tlsdesc_plt + 16);
+	    opcode = reencode_add_imm (opcode, PG_OFFSET (pltgot_addr));
+	    bfd_put_32 (output_bfd, opcode,
+			htab->root.splt->contents + htab->tlsdesc_plt + 16);
+	  }
+	}
+    }
+
+  if (htab->root.sgotplt)
+    {
+      if (bfd_is_abs_section (htab->root.sgotplt->output_section))
+	{
+	  (*_bfd_error_handler)
+	    (_("discarded output section: `%A'"), htab->root.sgotplt);
+	  return FALSE;
+	}
+
+      /* Fill in the first three entries in the global offset table.  */
+      if (htab->root.sgotplt->size > 0)
+	{
+	  /* Set the first entry in the global offset table to the address of
+	     the dynamic section.  */
+	  if (sdyn == NULL)
+	    bfd_put_64 (output_bfd, (bfd_vma) 0,
+			htab->root.sgotplt->contents);
+	  else
+	    bfd_put_64 (output_bfd,
+			sdyn->output_section->vma + sdyn->output_offset,
+			htab->root.sgotplt->contents);
+	  /* Write GOT[1] and GOT[2], needed for the dynamic linker.  */
+	  bfd_put_64 (output_bfd,
+		      (bfd_vma) 0,
+		      htab->root.sgotplt->contents + GOT_ENTRY_SIZE);
+	  bfd_put_64 (output_bfd,
+		      (bfd_vma) 0,
+		      htab->root.sgotplt->contents + GOT_ENTRY_SIZE * 2);
+	}
+
+      elf_section_data (htab->root.sgotplt->output_section)->
+	this_hdr.sh_entsize = GOT_ENTRY_SIZE;
+    }
+
+  if (htab->root.sgot && htab->root.sgot->size > 0)
+    elf_section_data (htab->root.sgot->output_section)->this_hdr.sh_entsize
+      = GOT_ENTRY_SIZE;
+
+  return TRUE;
+}
+
+/* Return address for Ith PLT stub in section PLT, for relocation REL
+   or (bfd_vma) -1 if it should not be included.  */
+
+static bfd_vma
+elf64_aarch64_plt_sym_val (bfd_vma i, const asection *plt,
+			   const arelent *rel ATTRIBUTE_UNUSED)
+{
+  return plt->vma + PLT_ENTRY_SIZE + i * PLT_SMALL_ENTRY_SIZE;
+}
+
+
+/* We use this so we can override certain functions
+   (though currently we don't).  */
+
+const struct elf_size_info elf64_aarch64_size_info = {
+  sizeof (Elf64_External_Ehdr),
+  sizeof (Elf64_External_Phdr),
+  sizeof (Elf64_External_Shdr),
+  sizeof (Elf64_External_Rel),
+  sizeof (Elf64_External_Rela),
+  sizeof (Elf64_External_Sym),
+  sizeof (Elf64_External_Dyn),
+  sizeof (Elf_External_Note),
+  4,				/* hash-table entry size.  */
+  1,				/* internal relocs per external relocs.  */
+  64,				/* arch_size.  */
+  3,				/* log_file_align.  */
+  ELFCLASS64, EV_CURRENT,
+  bfd_elf64_write_out_phdrs,
+  bfd_elf64_write_shdrs_and_ehdr,
+  bfd_elf64_checksum_contents,
+  bfd_elf64_write_relocs,
+  bfd_elf64_swap_symbol_in,
+  bfd_elf64_swap_symbol_out,
+  bfd_elf64_slurp_reloc_table,
+  bfd_elf64_slurp_symbol_table,
+  bfd_elf64_swap_dyn_in,
+  bfd_elf64_swap_dyn_out,
+  bfd_elf64_swap_reloc_in,
+  bfd_elf64_swap_reloc_out,
+  bfd_elf64_swap_reloca_in,
+  bfd_elf64_swap_reloca_out
+};
+
+#define ELF_ARCH			bfd_arch_aarch64
+#define ELF_MACHINE_CODE		EM_AARCH64
+#define ELF_MAXPAGESIZE			0x10000
+#define ELF_MINPAGESIZE			0x1000
+#define ELF_COMMONPAGESIZE		0x1000
+
+#define bfd_elf64_close_and_cleanup             \
+  elf64_aarch64_close_and_cleanup
+
+#define bfd_elf64_bfd_copy_private_bfd_data	\
+  elf64_aarch64_copy_private_bfd_data
+
+#define bfd_elf64_bfd_free_cached_info          \
+  elf64_aarch64_bfd_free_cached_info
+
+#define bfd_elf64_bfd_is_target_special_symbol	\
+  elf64_aarch64_is_target_special_symbol
+
+#define bfd_elf64_bfd_link_hash_table_create    \
+  elf64_aarch64_link_hash_table_create
+
+#define bfd_elf64_bfd_link_hash_table_free      \
+  elf64_aarch64_hash_table_free
+
+#define bfd_elf64_bfd_merge_private_bfd_data	\
+  elf64_aarch64_merge_private_bfd_data
+
+#define bfd_elf64_bfd_print_private_bfd_data	\
+  elf64_aarch64_print_private_bfd_data
+
+#define bfd_elf64_bfd_reloc_type_lookup		\
+  elf64_aarch64_reloc_type_lookup
+
+#define bfd_elf64_bfd_reloc_name_lookup		\
+  elf64_aarch64_reloc_name_lookup
+
+#define bfd_elf64_bfd_set_private_flags		\
+  elf64_aarch64_set_private_flags
+
+#define bfd_elf64_find_inliner_info		\
+  elf64_aarch64_find_inliner_info
+
+#define bfd_elf64_find_nearest_line		\
+  elf64_aarch64_find_nearest_line
+
+#define bfd_elf64_mkobject			\
+  elf64_aarch64_mkobject
+
+#define bfd_elf64_new_section_hook		\
+  elf64_aarch64_new_section_hook
+
+#define elf_backend_adjust_dynamic_symbol	\
+  elf64_aarch64_adjust_dynamic_symbol
+
+#define elf_backend_always_size_sections	\
+  elf64_aarch64_always_size_sections
+
+#define elf_backend_check_relocs		\
+  elf64_aarch64_check_relocs
+
+#define elf_backend_copy_indirect_symbol	\
+  elf64_aarch64_copy_indirect_symbol
+
+/* Create .dynbss, and .rela.bss sections in DYNOBJ, and set up shortcuts
+   to them in our hash.  */
+#define elf_backend_create_dynamic_sections	\
+  elf64_aarch64_create_dynamic_sections
+
+#define elf_backend_init_index_section		\
+  _bfd_elf_init_2_index_sections
+
+#define elf_backend_is_function_type		\
+  elf64_aarch64_is_function_type
+
+#define elf_backend_finish_dynamic_sections	\
+  elf64_aarch64_finish_dynamic_sections
+
+#define elf_backend_finish_dynamic_symbol	\
+  elf64_aarch64_finish_dynamic_symbol
+
+#define elf_backend_gc_sweep_hook		\
+  elf64_aarch64_gc_sweep_hook
+
+#define elf_backend_object_p			\
+  elf64_aarch64_object_p
+
+#define elf_backend_output_arch_local_syms      \
+  elf64_aarch64_output_arch_local_syms
+
+#define elf_backend_plt_sym_val			\
+  elf64_aarch64_plt_sym_val
+
+#define elf_backend_post_process_headers	\
+  elf64_aarch64_post_process_headers
+
+#define elf_backend_relocate_section		\
+  elf64_aarch64_relocate_section
+
+#define elf_backend_reloc_type_class		\
+  elf64_aarch64_reloc_type_class
+
+#define elf_backend_section_flags		\
+  elf64_aarch64_section_flags
+
+#define elf_backend_section_from_shdr		\
+  elf64_aarch64_section_from_shdr
+
+#define elf_backend_size_dynamic_sections	\
+  elf64_aarch64_size_dynamic_sections
+
+#define elf_backend_size_info			\
+  elf64_aarch64_size_info
+
+#define elf_backend_can_refcount       1
+#define elf_backend_can_gc_sections    0
+#define elf_backend_plt_readonly       1
+#define elf_backend_want_got_plt       1
+#define elf_backend_want_plt_sym       0
+#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_got_header_size (GOT_ENTRY_SIZE * 3)
+
+#undef  elf_backend_obj_attrs_section
+#define elf_backend_obj_attrs_section		".ARM.attributes"
+
+#include "elf64-target.h"
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 19c1f96..47d052d 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -5884,6 +5884,278 @@ ENUMDOC
   the dynamic object into the runtime process image.
 
 ENUM
+  BFD_RELOC_AARCH64_ADD_LO12
+ENUMDOC
+  AArch64 ADD immediate instruction, holding bits 0 to 11 of the address.
+  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_ADR_GOT_PAGE
+ENUMDOC
+  Get to the page base of the global offset table entry for a symbol as
+  part of an ADRP instruction using a 21 bit PC relative value.Used in
+  conjunction with BFD_RELOC_AARCH64_LD64_GOT_LO12_NC.
+ENUM
+  BFD_RELOC_AARCH64_ADR_HI21_PCREL
+ENUMDOC
+  AArch64 ADRP instruction, with bits 12 to 32 of a pc-relative page
+  offset, giving a 4KB aligned page base address.
+ENUM
+  BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL
+ENUMDOC
+  AArch64 ADRP instruction, with bits 12 to 32 of a pc-relative page
+  offset, giving a 4KB aligned page base address, but with no overflow
+  checking.
+ENUM
+  BFD_RELOC_AARCH64_ADR_LO21_PCREL
+ENUMDOC
+  AArch64 ADR instruction, holding a simple 21 bit pc-relative byte offset.
+ENUM
+  BFD_RELOC_AARCH64_BRANCH19
+ENUMDOC
+  AArch64 19 bit pc-relative conditional branch and compare & branch.
+  The lowest two bits must be zero and are not stored in the instruction,
+  giving a 21 bit signed byte offset.
+ENUM
+  BFD_RELOC_AARCH64_CALL26
+ENUMDOC
+  AArch64 26 bit pc-relative unconditional branch and link.
+  The lowest two bits must be zero and are not stored in the instruction,
+  giving a 28 bit signed byte offset.
+ENUM
+  BFD_RELOC_AARCH64_GAS_INTERNAL_FIXUP
+ENUMDOC
+  AArch64 pseudo relocation code to be used internally by the AArch64
+  assembler and not (currently) written to any object files.
+ENUM
+  BFD_RELOC_AARCH64_JUMP26
+ENUMDOC
+  AArch64 26 bit pc-relative unconditional branch.
+  The lowest two bits must be zero and are not stored in the instruction,
+  giving a 28 bit signed byte offset.
+ENUM
+  BFD_RELOC_AARCH64_LD_LO19_PCREL
+ENUMDOC
+  AArch64 Load Literal instruction, holding a 19 bit pc-relative word
+  offset.  The lowest two bits must be zero and are not stored in the
+  instruction, giving a 21 bit signed byte offset.
+ENUM
+  BFD_RELOC_AARCH64_LD64_GOT_LO12_NC
+ENUMDOC
+  Unsigned 12 bit byte offset for 64 bit load/store from the page of
+  the GOT entry for this symbol.  Used in conjunction with
+  BFD_RELOC_AARCH64_ADR_GOTPAGE.
+ENUM
+  BFD_RELOC_AARCH64_LDST_LO12
+ENUMDOC
+  AArch64 unspecified load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST8_LO12
+ENUMDOC
+  AArch64 8-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST16_LO12
+ENUMDOC
+  AArch64 16-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST32_LO12
+ENUMDOC
+  AArch64 32-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST64_LO12
+ENUMDOC
+  AArch64 64-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_LDST128_LO12
+ENUMDOC
+  AArch64 128-bit load/store instruction, holding bits 0 to 11 of the
+  address.  Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G0
+ENUMDOC
+  AArch64 MOV[NZK] instruction with most significant bits 0 to 15
+  of an unsigned address/value.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G0_S
+ENUMDOC
+  AArch64 MOV[NZ] instruction with most significant bits 0 to 15
+  of a signed value.  Changes instruction to MOVZ or MOVN depending on the
+  value's sign.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G0_NC
+ENUMDOC
+  AArch64 MOV[NZK] instruction with less significant bits 0 to 15 of
+  an address/value.  No overflow checking.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G1
+ENUMDOC
+  AArch64 MOV[NZK] instruction with most significant bits 16 to 31
+  of an unsigned address/value.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G1_NC
+ENUMDOC
+  AArch64 MOV[NZK] instruction with less significant bits 16 to 31
+  of an address/value.  No overflow checking.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G1_S
+ENUMDOC
+  AArch64 MOV[NZ] instruction with most significant bits 16 to 31
+  of a signed value.  Changes instruction to MOVZ or MOVN depending on the
+  value's sign.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G2
+ENUMDOC
+  AArch64 MOV[NZK] instruction with most significant bits 32 to 47
+  of an unsigned address/value.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G2_NC
+ENUMDOC
+  AArch64 MOV[NZK] instruction with less significant bits 32 to 47
+  of an address/value.  No overflow checking.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G2_S
+ENUMDOC
+  AArch64 MOV[NZ] instruction with most significant bits 32 to 47
+  of a signed value.  Changes instruction to MOVZ or MOVN depending on the
+  value's sign.
+ENUM
+  BFD_RELOC_AARCH64_MOVW_G3
+ENUMDOC
+  AArch64 MOV[NZK] instruction with most signficant bits 48 to 64
+  of a signed or unsigned address/value.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC
+ENUMDOC
+  AArch64 TLS relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_ADD
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_CALL
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_LD64_PREL19
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_LDR
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSDESC_OFF_G1
+ENUMDOC
+  AArch64 TLS DESC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC
+ENUMDOC
+  Unsigned 12 bit byte offset to global offset table entry for a symbols
+  tls_index structure.  Used in conjunction with
+  BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21.
+ENUM
+  BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21
+ENUMDOC
+  Get to the page base of the global offset table entry for a symbols
+  tls_index structure as part of an adrp instruction using a 21 bit PC
+  relative value.  Used in conjunction with
+  BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1
+ENUMDOC
+  AArch64 TLS INITIAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
+ENUMDOC
+  AArch64 TLS LOCAL EXEC relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLS_DTPMOD64
+ENUMDOC
+  AArch64 TLS relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLS_DTPREL64
+ENUMDOC
+  AArch64 TLS relocation.
+ENUM
+  BFD_RELOC_AARCH64_TLS_TPREL64
+ENUMDOC
+  AArch64 TLS relocation.
+ENUM
+  BFD_RELOC_AARCH64_TSTBR14
+ENUMDOC
+  AArch64 14 bit pc-relative test bit and branch.
+  The lowest two bits must be zero and are not stored in the instruction,
+  giving a 16 bit signed byte offset.
+
+ENUM
   BFD_RELOC_TILEPRO_COPY
 ENUMX
   BFD_RELOC_TILEPRO_GLOB_DAT
@@ -6043,7 +6315,6 @@ ENUMX
   BFD_RELOC_TILEPRO_IMM16_X1_TLS_LE_HA
 ENUMDOC
   Tilera TILEPro Relocations.
-
 ENUM
   BFD_RELOC_TILEGX_HW0
 ENUMX
@@ -6236,7 +6507,6 @@ ENUMX
   BFD_RELOC_TILEGX_IMM8_Y1_TLS_ADD
 ENUMDOC
   Tilera TILE-Gx Relocations.
-
 ENUM
   BFD_RELOC_EPIPHANY_SIMM8
 ENUMDOC
diff --git a/bfd/targets.c b/bfd/targets.c
index ce1cf35..fa206d2 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -730,6 +730,7 @@ extern const bfd_target bfd_elf64_alpha_freebsd_vec;
 extern const bfd_target bfd_elf64_alpha_vec;
 extern const bfd_target bfd_elf64_big_generic_vec;
 extern const bfd_target bfd_elf64_bigmips_vec;
+extern const bfd_target bfd_elf64_bigaarch64_vec;
 extern const bfd_target bfd_elf64_hppa_linux_vec;
 extern const bfd_target bfd_elf64_hppa_vec;
 extern const bfd_target bfd_elf64_ia64_big_vec;
@@ -738,6 +739,7 @@ extern const bfd_target bfd_elf64_ia64_little_vec;
 extern const bfd_target bfd_elf64_ia64_vms_vec;
 extern const bfd_target bfd_elf64_little_generic_vec;
 extern const bfd_target bfd_elf64_littlemips_vec;
+extern const bfd_target bfd_elf64_littleaarch64_vec;
 extern const bfd_target bfd_elf64_mmix_vec;
 extern const bfd_target bfd_elf64_powerpc_vec;
 extern const bfd_target bfd_elf64_powerpcle_vec;
@@ -1105,6 +1107,7 @@ static const bfd_target * const _bfd_target_vector[] =
 	&bfd_elf64_alpha_vec,
 	&bfd_elf64_big_generic_vec,
 	&bfd_elf64_bigmips_vec,
+	&bfd_elf64_bigaarch64_vec,
 	&bfd_elf64_hppa_linux_vec,
 	&bfd_elf64_hppa_vec,
 	&bfd_elf64_ia64_big_vec,
@@ -1113,6 +1116,7 @@ static const bfd_target * const _bfd_target_vector[] =
 	&bfd_elf64_ia64_vms_vec,
 	&bfd_elf64_little_generic_vec,
 	&bfd_elf64_littlemips_vec,
+	&bfd_elf64_littleaarch64_vec,
 	&bfd_elf64_mmix_vec,
 	&bfd_elf64_powerpc_vec,
 	&bfd_elf64_powerpcle_vec,

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes v2
  2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes Yufeng Zhang
  2012-07-30 15:02   ` Joseph S. Myers
  2012-07-31 18:23   ` nick clifton
@ 2012-08-07 17:29   ` Yufeng Zhang
  2012-08-13 14:58     ` nick clifton
  2 siblings, 1 reply; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-07 17:29 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 7400 bytes --]

Hi,

Here is the updated patch that adds the AArch64 gas port.

The patch

* improves the gas manual following the suggestion in
http://sourceware.org/ml/binutils/2012-07/msg00280.html

* refactors and cleans up the tc-aarch64.c file (particularly on the 
function return types) as suggested in
http://sourceware.org/ml/binutils/2012-07/msg00321.html


Thanks,
Yufeng


Updated change log:

gas/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
             Laurent Desnogues  <laurent.desnogues@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * Makefile.am: Add AArch64.
         * Makefile.in: Regenerate.
         * config/tc-aarch64.c: New file.
         * config/tc-aarch64.h: New file.
         * configure.tgt: Add AArch64.
         * doc/Makefile.am: Add AArch64.
         * doc/Makefile.in: Regenerate.
         * doc/all.texi: Add AArch64.
         * doc/as.texinfo: Add AArch64.
         * doc/c-aarch64.texi: New file.
         * po/POTFILES.in: Regenerate.


gas/testsuite/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
             Laurent Desnogues  <laurent.desnogues@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * gas/aarch64/aarch64.exp: New file.
         * gas/aarch64/addsub.d: New file.
         * gas/aarch64/addsub.s: New file.
         * gas/aarch64/advsimd-across.d: New file.
         * gas/aarch64/advsimd-across.s: New file.
         * gas/aarch64/advsimd-misc.d: New file.
         * gas/aarch64/advsimd-misc.s: New file.
         * gas/aarch64/advsisd-copy.d: New file.
         * gas/aarch64/advsisd-copy.s: New file.
         * gas/aarch64/advsisd-misc.d: New file.
         * gas/aarch64/advsisd-misc.s: New file.
         * gas/aarch64/alias.d: New file.
         * gas/aarch64/alias.s: New file.
         * gas/aarch64/bitfield-alias.d: New file.
         * gas/aarch64/bitfield-alias.s: New file.
         * gas/aarch64/bitfield-bfm.d: New file.
         * gas/aarch64/bitfield-bfm.s: New file.
         * gas/aarch64/bitfield-dump: New file.
         * gas/aarch64/bitfield-no-aliases.d: New file.
         * gas/aarch64/crypto.d: New file.
         * gas/aarch64/crypto.s: New file.
         * gas/aarch64/diagnostic.d: New file.
         * gas/aarch64/diagnostic.l: New file.
         * gas/aarch64/diagnostic.s: New file.
         * gas/aarch64/floatdp2.d: New file.
         * gas/aarch64/floatdp2.s: New file.
         * gas/aarch64/fp_cvt_int.d: New file.
         * gas/aarch64/fp_cvt_int.s: New file.
         * gas/aarch64/illegal-2.d: New file.
         * gas/aarch64/illegal-2.l: New file.
         * gas/aarch64/illegal-2.s: New file.
         * gas/aarch64/illegal.d: New file.
         * gas/aarch64/illegal.l: New file.
         * gas/aarch64/illegal.s: New file.
         * gas/aarch64/inst-directive.d: New file.
         * gas/aarch64/inst-directive.s: New file.
         * gas/aarch64/int-insns.d: New file.
         * gas/aarch64/int-insns.s: New file.
         * gas/aarch64/ldst-exclusive.d: New file.
         * gas/aarch64/ldst-exclusive.s: New file.
         * gas/aarch64/ldst-reg-imm-post-ind.d: New file.
         * gas/aarch64/ldst-reg-imm-post-ind.s: New file.
         * gas/aarch64/ldst-reg-imm-pre-ind.d: New file.
         * gas/aarch64/ldst-reg-imm-pre-ind.s: New file.
         * gas/aarch64/ldst-reg-pair.d: New file.
         * gas/aarch64/ldst-reg-pair.s: New file.
         * gas/aarch64/ldst-reg-reg-offset.d: New file.
         * gas/aarch64/ldst-reg-reg-offset.s: New file.
         * gas/aarch64/ldst-reg-uns-imm.d: New file.
         * gas/aarch64/ldst-reg-uns-imm.s: New file.
         * gas/aarch64/ldst-reg-unscaled-imm.d: New file.
         * gas/aarch64/ldst-reg-unscaled-imm.s: New file.
         * gas/aarch64/legacy_reg_names.d: New file.
         * gas/aarch64/legacy_reg_names.l: New file.
         * gas/aarch64/legacy_reg_names.s: New file.
         * gas/aarch64/mapmisc.d: New file.
         * gas/aarch64/mapmisc.dat: New file.
         * gas/aarch64/mapmisc.s: New file.
         * gas/aarch64/mapping.d: New file.
         * gas/aarch64/mapping.s: New file.
         * gas/aarch64/mapping2.d: New file.
         * gas/aarch64/mapping2.s: New file.
         * gas/aarch64/mapping3.d: New file.
         * gas/aarch64/mapping3.s: New file.
         * gas/aarch64/mapping4.d: New file.
         * gas/aarch64/mapping4.s: New file.
         * gas/aarch64/mov-no-aliases.d: New file.
         * gas/aarch64/mov.d: New file.
         * gas/aarch64/mov.s: New file.
         * gas/aarch64/movi.d: New file.
         * gas/aarch64/movi.s: New file.
         * gas/aarch64/msr.d: New file.
         * gas/aarch64/msr.s: New file.
         * gas/aarch64/neon-fp-cvt-int.d: New file.
         * gas/aarch64/neon-fp-cvt-int.s: New file.
         * gas/aarch64/neon-frint.d: New file.
         * gas/aarch64/neon-frint.s: New file.
         * gas/aarch64/neon-ins.d: New file.
         * gas/aarch64/neon-ins.s: New file.
         * gas/aarch64/neon-not.d: New file.
         * gas/aarch64/neon-not.s: New file.
         * gas/aarch64/neon-vfp-reglist-post.d: New file.
         * gas/aarch64/neon-vfp-reglist-post.s: New file.
         * gas/aarch64/neon-vfp-reglist.d: New file.
         * gas/aarch64/neon-vfp-reglist.s: New file.
         * gas/aarch64/no-aliases.d: New file.
         * gas/aarch64/optional.d: New file.
         * gas/aarch64/optional.s: New file.
         * gas/aarch64/programmer-friendly.d: New file.
         * gas/aarch64/programmer-friendly.s: New file.
         * gas/aarch64/reloc-data.d: New file.
         * gas/aarch64/reloc-data.s: New file.
         * gas/aarch64/reloc-insn.d: New file.
         * gas/aarch64/reloc-insn.s: New file.
         * gas/aarch64/shifted.d: New file.
         * gas/aarch64/shifted.s: New file.
         * gas/aarch64/symbol.d: New file.
         * gas/aarch64/symbol.s: New file.
         * gas/aarch64/sysreg-1.d: New file.
         * gas/aarch64/sysreg-1.s: New file.
         * gas/aarch64/sysreg.d: New file.
         * gas/aarch64/sysreg.s: New file.
         * gas/aarch64/system.d: New file.
         * gas/aarch64/system.s: New file.
         * gas/aarch64/tlbi_op.d: New file.
         * gas/aarch64/tlbi_op.s: New file.
         * gas/aarch64/tls.d: New file.
         * gas/aarch64/tls.s: New file.
         * gas/aarch64/verbose-error.d: New file.
         * gas/aarch64/verbose-error.l: New file.
         * gas/aarch64/verbose-error.s: New file.

[-- Attachment #2: aarch64-gas.v2.patch.bz2 --]
[-- Type: application/x-bzip, Size: 207707 bytes --]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes v2
  2012-07-30 15:17   ` Joseph S. Myers
@ 2012-08-07 17:30     ` Yufeng Zhang
  2012-08-13 15:02       ` nick clifton
  0 siblings, 1 reply; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-07 17:30 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 2762 bytes --]

Hi,

On 07/30/12 16:16, Joseph S. Myers wrote:
> On Mon, 30 Jul 2012, Yufeng Zhang wrote:
>
>> This patch adds the binutils changes of the AArch64 target support.
>
> Are you sure this is adding full support to readelf?  You appear to have
> some architecture-specific PT_*, SHT_* and SHF_* values in elf/aarch64.h,
> so readelf should know how to display those - and in general such support
> is conditioned on the architecture, so even if the names and values are
> the same as for ARM, I'd expect you to need conditionals to enable the
> decoding for AArch64 as well as for ARM.  (In general I'd advise going
> through the ELF ABI and making sure that all such architecture-specific
> values from the ABI are (a) present in elf/aarch64.h and (b) properly
> displayed by readelf.)

Thank you for your reviewing.

Please find the attached updated patch which has an improved 
implementation of the AArch64-port readelf.


Thanks,
Yufeng


Updated change log:

binutils/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
             Laurent Desnogues  <laurent.desnogues@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * readelf.c (guess_is_rela): Handle EM_AARCH64.
         (get_machine_name): Likewise.
         (get_aarch64_segment_type): New function.
         (get_segment_type): Handle EM_AARCH64 by calling the new function.
         (get_aarch64_section_type_name): New function.
         (get_section_type_name): Handle EM_AARCH64 by calling the new 
function.
         (is_32bit_abs_reloc): Handle EM_AARCH64.
         (is_32bit_pcrel_reloc): Likewise.
         (is_64bit_abs_reloc): Likewise.
         (is_64bit_pcrel_reloc): Likewise.
         (is_none_reloc): Likewise.

binutils/testsuite/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
             Laurent Desnogues  <laurent.desnogues@arm.com>
             Jim MacArthur  <jim.macarthur@arm.com>
             Marcus Shawcroft  <marcus.shawcroft@arm.com>
             Nigel Stephens  <nigel.stephens@arm.com>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
             Richard Earnshaw  <rearnsha@arm.com>
             Sofiane Naci  <sofiane.naci@arm.com>
             Tejas Belagod  <tejas.belagod@arm.com>
             Yufeng Zhang  <yufeng.zhang@arm.com>

         * objdump.exp: Add AArch64.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: aarch64-binutils.v2.patch --]
[-- Type: text/x-patch; name=aarch64-binutils.v2.patch, Size: 4902 bytes --]

diff --git a/binutils/readelf.c b/binutils/readelf.c
index e6f2be6..5423c7f 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -91,6 +91,7 @@
 
 #define RELOC_MACROS_GEN_FUNC
 
+#include "elf/aarch64.h"
 #include "elf/alpha.h"
 #include "elf/arc.h"
 #include "elf/arm.h"
@@ -551,6 +552,7 @@ guess_is_rela (unsigned int e_machine)
       /* Targets that use RELA relocations.  */
     case EM_68K:
     case EM_860:
+    case EM_AARCH64:
     case EM_ADAPTEVA_EPIPHANY:
     case EM_ALPHA:
     case EM_ALTERA_NIOS2:
@@ -983,6 +985,10 @@ dump_relocations (FILE * file,
 	  rtype = NULL;
 	  break;
 
+	case EM_AARCH64:
+	  rtype = elf_aarch64_reloc_type (type);
+	  break;
+
 	case EM_M32R:
 	case EM_CYGNUS_M32R:
 	  rtype = elf_m32r_reloc_type (type);
@@ -1830,6 +1836,7 @@ get_machine_name (unsigned e_machine)
   switch (e_machine)
     {
     case EM_NONE:		return _("None");
+    case EM_AARCH64:		return "AArch64";
     case EM_M32:		return "WE32100";
     case EM_SPARC:		return "Sparc";
     case EM_SPU:		return "SPU";
@@ -2695,6 +2702,20 @@ get_osabi_name (unsigned int osabi)
 }
 
 static const char *
+get_aarch64_segment_type (unsigned long type)
+{
+  switch (type)
+    {
+    case PT_AARCH64_ARCHEXT:
+      return "AARCH64_ARCHEXT";
+    default:
+      break;
+    }
+
+  return NULL;
+}
+
+static const char *
 get_arm_segment_type (unsigned long type)
 {
   switch (type)
@@ -2816,6 +2837,9 @@ get_segment_type (unsigned long p_type)
 
 	  switch (elf_header.e_machine)
 	    {
+	    case EM_AARCH64:
+	      result = get_aarch64_segment_type (p_type);
+	      break;
 	    case EM_ARM:
 	      result = get_arm_segment_type (p_type);
 	      break;
@@ -2977,6 +3001,19 @@ get_x86_64_section_type_name (unsigned int sh_type)
 }
 
 static const char *
+get_aarch64_section_type_name (unsigned int sh_type)
+{
+  switch (sh_type)
+    {
+    case SHT_AARCH64_ATTRIBUTES:
+      return "AARCH64_ATTRIBUTES";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+static const char *
 get_arm_section_type_name (unsigned int sh_type)
 {
   switch (sh_type)
@@ -3075,6 +3112,9 @@ get_section_type_name (unsigned int sh_type)
 	    case EM_K1OM:
 	      result = get_x86_64_section_type_name (sh_type);
 	      break;
+	    case EM_AARCH64:
+	      result = get_aarch64_section_type_name (sh_type);
+	      break;
 	    case EM_ARM:
 	      result = get_arm_section_type_name (sh_type);
 	      break;
@@ -9770,6 +9810,8 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_860_32.  */
     case EM_960:
       return reloc_type == 2; /* R_960_32.  */
+    case EM_AARCH64:
+      return reloc_type == 258; /* R_AARCH64_ABS32 */
     case EM_ALPHA:
       return reloc_type == 1; /* R_ALPHA_REFLONG.  */
     case EM_ARC:
@@ -9924,6 +9966,8 @@ is_32bit_pcrel_reloc (unsigned int reloc_type)
       return reloc_type == 2;  /* R_386_PC32.  */
     case EM_68K:
       return reloc_type == 4;  /* R_68K_PC32.  */
+    case EM_AARCH64:
+      return reloc_type == 261; /* R_AARCH64_PREL32 */
     case EM_ADAPTEVA_EPIPHANY:
       return reloc_type == 6;
     case EM_ALPHA:
@@ -9978,6 +10022,8 @@ is_64bit_abs_reloc (unsigned int reloc_type)
 {
   switch (elf_header.e_machine)
     {
+    case EM_AARCH64:
+      return reloc_type == 257;	/* R_AARCH64_ABS64.  */
     case EM_ALPHA:
       return reloc_type == 2; /* R_ALPHA_REFQUAD.  */
     case EM_IA_64:
@@ -10014,6 +10060,8 @@ is_64bit_pcrel_reloc (unsigned int reloc_type)
 {
   switch (elf_header.e_machine)
     {
+    case EM_AARCH64:
+      return reloc_type == 260;	/* R_AARCH64_PREL64.  */
     case EM_ALPHA:
       return reloc_type == 11; /* R_ALPHA_SREL64.  */
     case EM_IA_64:
@@ -10143,6 +10191,8 @@ is_none_reloc (unsigned int reloc_type)
     case EM_XC16X:
     case EM_C166:    /* R_XC16X_NONE.  */
       return reloc_type == 0;
+    case EM_AARCH64:
+      return reloc_type == 0 || reloc_type == 256;
     case EM_XTENSA_OLD:
     case EM_XTENSA:
       return (reloc_type == 0      /* R_XTENSA_NONE.  */
diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp
index 267bcbd..14d1860 100644
--- a/binutils/testsuite/binutils-all/objdump.exp
+++ b/binutils/testsuite/binutils-all/objdump.exp
@@ -36,7 +36,7 @@ send_user "Version [binutil_version $OBJDUMP]"
 set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"]
 
 set cpus_expected [list]
-lappend cpus_expected alpha arc arm cris
+lappend cpus_expected aarch64 alpha arc arm cris
 lappend cpus_expected d10v d30v fr30 fr500 fr550 h8 hppa i386 i860 i960 ip2022
 lappend cpus_expected m16c m32c m32r m68hc11 m68hc12 m68k m88k MCore MicroBlaze
 lappend cpus_expected mips mn10200 mn10300 ms1 msp ns32k pj powerpc pyramid

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2
  2012-07-30 15:08   ` Joseph S. Myers
@ 2012-08-07 17:34     ` Yufeng Zhang
  2012-08-09 17:37       ` nick clifton
  2012-08-13 14:58       ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2 nick clifton
  0 siblings, 2 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-07 17:34 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 10323 bytes --]

Hi,

Please find the updated patch in the attachment.

On 07/30/12 16:08, Joseph S. Myers wrote:
> On Mon, 30 Jul 2012, Yufeng Zhang wrote:
>
>> +aarch64*-*-linux*)
>> +  MULTIARCHTUPLE=aarch64-linux-gnu
>> +  NATIVE_LIB_DIRS="/usr/local/lib/$MULTIARCHTUPLE /lib/$MULTIARCHTUPLE /usr/lib/$MULTIARCHTUPLE"
>> +  ;;
>
> As I said for the GCC port, it's inappropriate for this sort of thing to
> be present unconditionally for one architecture.  Someone needs to submit
> generic binutils support for this Debian scheme, *conditional on an
> appropriate configure option*, and *after that* this port can have the
> appropriate settings to support the scheme *conditionally*.

This change has been withdrawn; the AArch64 port now uses the default 
NATIVE_LIB_DIRS.


> I note you have some changes of the form:
>
>>   # No shared lib support on this target.
>> -if { [istarget "mcore-*-*"] } {
>> +if { [istarget "mcore-*-*"] || [istarget "aarch64-*-*"] } {
>
> Is it really the case that there is no shared library support for this
> port?  If not, the comments need updating.

Thanks for pointing this out.  The change to ld-elf/exclude.exp and 
ld-elf/frame.exp is no longer necessary and has been removed from the 
re-submitted patch.


> In general, please explain,
> for each test being disabled for this target, why it is correct to disable
> it.

The following tests have been disabled for the AArch64 port as 
--gc-sections is not supported yet:

          * ld-elf/group8a.d
          * ld-elf/group8b.d
          * ld-elf/group9a.d
          * ld-elf/group9b.d
          * ld-elf/pr12851.d
          * ld-elf/pr12975.d
          * ld-elf/pr13177.d
          * ld-elf/pr13195.d
          * ld-elfvers/vers.exp: Add AArch64.
          * ld-shared/shared.exp: Add AArch64.
          * ld-srec/srec.exp: Add AArch64.
          * lib/ld-lib.exp: Add AArch64.

ld-srec/srec.exp has been disabled as well since SREC is not supported.


Thanks,
Yufeng


Updated change log:

ld/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
              Laurent Desnogues  <laurent.desnogues@arm.com>
              Jim MacArthur  <jim.macarthur@arm.com>
              Marcus Shawcroft  <marcus.shawcroft@arm.com>
              Nigel Stephens  <nigel.stephens@arm.com>
              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
              Richard Earnshaw  <rearnsha@arm.com>
              Sofiane Naci  <sofiane.naci@arm.com>
              Tejas Belagod  <tejas.belagod@arm.com>
              Yufeng Zhang  <yufeng.zhang@arm.com>

          * Makefile.am: Add AArch64.
          * Makefile.in: Regenerate.
          * configure.tgt: Add AArch64.
          * emulparams/aarch64elf.sh: New file.
          * emulparams/aarch64elfb.sh: New file.
          * emulparams/aarch64linux.sh: New file.
          * emulparams/aarch64linuxb.sh: New file.
          * emultempl/aarch64elf.em: New file.


ld/testsuite/ChangeLog
2012-08-07  Ian Bolton  <ian.bolton@arm.com>
              Laurent Desnogues  <laurent.desnogues@arm.com>
              Jim MacArthur  <jim.macarthur@arm.com>
              Marcus Shawcroft  <marcus.shawcroft@arm.com>
              Nigel Stephens  <nigel.stephens@arm.com>
              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
              Richard Earnshaw  <rearnsha@arm.com>
              Sofiane Naci  <sofiane.naci@arm.com>
              Tejas Belagod  <tejas.belagod@arm.com>
              Yufeng Zhang  <yufeng.zhang@arm.com>

          * ld-aarch64/aarch64-elf.exp: New file.
          * ld-aarch64/aarch64.ld: New file.
          * ld-aarch64/eh-frame-bar.s: New file.
          * ld-aarch64/eh-frame-foo.s: New file.
          * ld-aarch64/eh-frame.d: New file.
          * ld-aarch64/emit-relocs-257-be.d: New file.
          * ld-aarch64/emit-relocs-257.d: New file.
          * ld-aarch64/emit-relocs-257.s: New file.
          * ld-aarch64/emit-relocs-260-be.d: New file.
          * ld-aarch64/emit-relocs-260.d: New file.
          * ld-aarch64/emit-relocs-260.s: New file.
          * ld-aarch64/emit-relocs-262.d: New file.
          * ld-aarch64/emit-relocs-262.s: New file.
          * ld-aarch64/emit-relocs-263.d: New file.
          * ld-aarch64/emit-relocs-263.s: New file.
          * ld-aarch64/emit-relocs-264.d: New file.
          * ld-aarch64/emit-relocs-264.s: New file.
          * ld-aarch64/emit-relocs-265.d: New file.
          * ld-aarch64/emit-relocs-265.s: New file.
          * ld-aarch64/emit-relocs-266.d: New file.
          * ld-aarch64/emit-relocs-266.s: New file.
          * ld-aarch64/emit-relocs-267.d: New file.
          * ld-aarch64/emit-relocs-267.s: New file.
          * ld-aarch64/emit-relocs-268.d: New file.
          * ld-aarch64/emit-relocs-268.s: New file.
          * ld-aarch64/emit-relocs-269.d: New file.
          * ld-aarch64/emit-relocs-269.s: New file.
          * ld-aarch64/emit-relocs-270-bad.d: New file.
          * ld-aarch64/emit-relocs-270.d: New file.
          * ld-aarch64/emit-relocs-270.s: New file.
          * ld-aarch64/emit-relocs-271.d: New file.
          * ld-aarch64/emit-relocs-271.s: New file.
          * ld-aarch64/emit-relocs-272.d: New file.
          * ld-aarch64/emit-relocs-272.s: New file.
          * ld-aarch64/emit-relocs-273.d: New file.
          * ld-aarch64/emit-relocs-273.s: New file.
          * ld-aarch64/emit-relocs-274.d: New file.
          * ld-aarch64/emit-relocs-274.s: New file.
          * ld-aarch64/emit-relocs-275.d: New file.
          * ld-aarch64/emit-relocs-275.s: New file.
          * ld-aarch64/emit-relocs-276.d: New file.
          * ld-aarch64/emit-relocs-276.s: New file.
          * ld-aarch64/emit-relocs-277.d: New file.
          * ld-aarch64/emit-relocs-277.s: New file.
          * ld-aarch64/emit-relocs-278.d: New file.
          * ld-aarch64/emit-relocs-278.s: New file.
          * ld-aarch64/emit-relocs-279-bad.d: New file.
          * ld-aarch64/emit-relocs-279.d: New file.
          * ld-aarch64/emit-relocs-279.s: New file.
          * ld-aarch64/emit-relocs-280.d: New file.
          * ld-aarch64/emit-relocs-280.s: New file.
          * ld-aarch64/emit-relocs-282.d: New file.
          * ld-aarch64/emit-relocs-282.s: New file.
          * ld-aarch64/emit-relocs-283.d: New file.
          * ld-aarch64/emit-relocs-283.s: New file.
          * ld-aarch64/emit-relocs-284.d: New file.
          * ld-aarch64/emit-relocs-284.s: New file.
          * ld-aarch64/emit-relocs-285.d: New file.
          * ld-aarch64/emit-relocs-285.s: New file.
          * ld-aarch64/emit-relocs-286-bad.d: New file.
          * ld-aarch64/emit-relocs-286.d: New file.
          * ld-aarch64/emit-relocs-286.s: New file.
          * ld-aarch64/emit-relocs-287.d: New file.
          * ld-aarch64/emit-relocs-287.s: New file.
          * ld-aarch64/emit-relocs-299.d: New file.
          * ld-aarch64/emit-relocs-299.s: New file.
          * ld-aarch64/emit-relocs-311.d: New file.
          * ld-aarch64/emit-relocs-311.s: New file.
          * ld-aarch64/emit-relocs-312.d: New file.
          * ld-aarch64/emit-relocs-312.s: New file.
          * ld-aarch64/emit-relocs1.s: New file.
          * ld-aarch64/farcall-b-none-function.d: New file.
          * ld-aarch64/farcall-b-none-function.s: New file.
          * ld-aarch64/farcall-b.d: New file.
          * ld-aarch64/farcall-b.s: New file.
          * ld-aarch64/farcall-back.d: New file.
          * ld-aarch64/farcall-back.s: New file.
          * ld-aarch64/farcall-bl-none-function.d: New file.
          * ld-aarch64/farcall-bl-none-function.s: New file.
          * ld-aarch64/farcall-bl.d: New file.
          * ld-aarch64/farcall-bl.s: New file.
          * ld-aarch64/farcall-section.d: New file.
          * ld-aarch64/farcall-section.s: New file.
          * ld-aarch64/limit-b.d: New file.
          * ld-aarch64/limit-b.s: New file.
          * ld-aarch64/limit-bl.d: New file.
          * ld-aarch64/limit-bl.s: New file.
          * ld-aarch64/relocs.ld: New file.
          * ld-aarch64/tls-desc-ie.d: New file.
          * ld-aarch64/tls-desc-ie.s: New file.
          * ld-aarch64/tls-relax-all.d: New file.
          * ld-aarch64/tls-relax-all.s: New file.
          * ld-aarch64/tls-relax-gd-ie.d: New file.
          * ld-aarch64/tls-relax-gd-ie.s: New file.
          * ld-aarch64/tls-relax-gd-le.d: New file.
          * ld-aarch64/tls-relax-gd-le.s: New file.
          * ld-aarch64/tls-relax-gdesc-ie-2.d: New file.
          * ld-aarch64/tls-relax-gdesc-ie-2.s: New file.
          * ld-aarch64/tls-relax-gdesc-ie.d: New file.
          * ld-aarch64/tls-relax-gdesc-ie.s: New file.
          * ld-aarch64/tls-relax-gdesc-le-2.d: New file.
          * ld-aarch64/tls-relax-gdesc-le-2.s: New file.
          * ld-aarch64/tls-relax-gdesc-le.d: New file.
          * ld-aarch64/tls-relax-gdesc-le.s: New file.
          * ld-aarch64/tls-relax-ie-le-2.d: New file.
          * ld-aarch64/tls-relax-ie-le-2.s: New file.
          * ld-aarch64/tls-relax-ie-le-3.d: New file.
          * ld-aarch64/tls-relax-ie-le-3.s: New file.
          * ld-aarch64/tls-relax-ie-le.d: New file.
          * ld-aarch64/tls-relax-ie-le.s: New file.
          * ld-aarch64/weak-undefined.d: New file.
          * ld-aarch64/weak-undefined.s: New file.
          * ld-elf/binutils.exp (binutils_test): Add optional parameter
          'test_name'; change to construct 'test_name' from the 'prog_name'
          and 'ld_options' only when "$test_name" == "".
          * ld-elf/group8a.d (#notarget): Add AArch64.
          * ld-elf/group8b.d (#notarget): Add AArch64.
          * ld-elf/group9a.d (#notarget): Add AArch64.
          * ld-elf/group9b.d (#notarget): Add AArch64.
          * ld-elf/pr12851.d (#notarget): Add AArch64.
          * ld-elf/pr12975.d (#notarget): Add AArch64.
          * ld-elf/pr13177.d (#notarget): Add AArch64.
          * ld-elf/pr13195.d (#notarget): Add AArch64.
          * ld-elfvers/vers.exp: Add AArch64.
          * ld-shared/shared.exp: Add AArch64.
          * ld-srec/srec.exp: Add AArch64.
          * lib/ld-lib.exp: Add AArch64.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: aarch64-ld.v2.patch --]
[-- Type: text/x-patch; name=aarch64-ld.v2.patch, Size: 102515 bytes --]

diff --git a/ld/Makefile.am b/ld/Makefile.am
index f35ba4b..8ee8655 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -127,6 +127,10 @@ BFDLIB = ../bfd/libbfd.la
 LIBIBERTY = ../libiberty/libiberty.a
 
 ALL_EMULATION_SOURCES = \
+	eaarch64elf.c \
+	eaarch64elfb.c \
+	eaarch64linux.c \
+	eaarch64linuxb.c \
 	eaix5ppc.c \
 	eaix5rs6.c \
 	eaixppc.c \
@@ -1719,6 +1723,22 @@ ens32knbsd.c:	$(srcdir)/emulparams/ns32knbsd.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/netbsd.em \
   $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} ns32knbsd "$(tdir_ns32knbsd)"
+eaarch64elf.c: $(srcdir)/emulparams/aarch64elf.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64elf "$(tdir_aarch64elf)"
+eaarch64elfb.c: $(srcdir)/emulparams/aarch64elfb.sh $(srcdir)/emulparams/aarch64elf.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64elfb "$(tdir_aarch64elfb)"
+eaarch64linux.c: $(srcdir)/emulparams/aarch64linux.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64linux "$(tdir_aarch64linux)"
+eaarch64linuxb.c: $(srcdir)/emulparams/aarch64linuxb.sh $(srcdir)/emulparams/aarch64linux.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64linuxb "$(tdir_aarch64linuxb)"
 eor32.c: $(srcdir)/emulparams/or32.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/or32.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} or32 "$(tdir_or32)"
diff --git a/ld/configure.tgt b/ld/configure.tgt
index e58f4b8..0075dce 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -27,6 +27,14 @@ targ64_extra_libpath=
 # architecture variants should be kept together even if their names
 # break the alpha sorting.
 case "${targ}" in
+aarch64_be-*-elf)	targ_emul=aarch64elfb
+			targ_extra_emuls="aarch64elf armelfb armelf" ;;
+aarch64-*-elf)		targ_emul=aarch64elf
+			targ_extra_emuls="aarch64elfb armelf armelfb" ;;
+aarch64_be-*-linux*)	targ_emul=aarch64linuxb
+			targ_extra_emuls="aarch64linux aarch64elfb aarch64elf armelfb_linux_eabi armelf_linux_eabi armelfb armelf" ;;
+aarch64-*-linux*)	targ_emul=aarch64linux
+			targ_extra_emuls="aarch64linuxb aarch64elf aarch64elfb armelf_linux_eabi armelfb_linux_eabi armelf armelfb" ;;
 alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
 		        targ_emul=elf64alpha_fbsd
 			targ_extra_emuls="elf64alpha alpha"
diff --git a/ld/emulparams/aarch64elf.sh b/ld/emulparams/aarch64elf.sh
new file mode 100644
index 0000000..d72e5f7
--- /dev/null
+++ b/ld/emulparams/aarch64elf.sh
@@ -0,0 +1,35 @@
+ARCH=aarch64
+MACHINE=
+NOP=0
+
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf64-littleaarch64"
+BIG_OUTPUT_FORMAT="elf64-bigaarch64"
+LITTLE_OUTPUT_FORMAT="elf64-littleaarch64"
+NO_REL_RELOCS=yes
+
+TEMPLATE_NAME=elf32
+EXTRA_EM_FILE=aarch64elf
+
+GENERATE_SHLIB_SCRIPT=yes
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+
+ENTRY=_start
+EMBEDDED=yes
+SEPARATE_GOTPLT=24
+TEXT_START_ADDR=0x00400000
+
+DATA_START_SYMBOLS='__data_start = . ;';
+
+# AArch64 does not support .s* sections.
+NO_SMALL_DATA=yes
+
+OTHER_BSS_SYMBOLS='__bss_start__ = .;'
+OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
+OTHER_END_SYMBOLS='__end__ = . ;'
+
+OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
+ATTRS_SECTIONS='.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }'
+
+# This sets the stack to the top of the simulator memory (2^19 bytes).
+STACK_ADDR=0x80000
diff --git a/ld/emulparams/aarch64elfb.sh b/ld/emulparams/aarch64elfb.sh
new file mode 100644
index 0000000..7a3ff97
--- /dev/null
+++ b/ld/emulparams/aarch64elfb.sh
@@ -0,0 +1,2 @@
+. ${srcdir}/emulparams/aarch64elf.sh
+OUTPUT_FORMAT="elf64-bigaarch64"
diff --git a/ld/emulparams/aarch64linux.sh b/ld/emulparams/aarch64linux.sh
new file mode 100644
index 0000000..a5a2500
--- /dev/null
+++ b/ld/emulparams/aarch64linux.sh
@@ -0,0 +1,36 @@
+ARCH=aarch64
+MACHINE=
+NOP=0
+
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf64-littleaarch64"
+BIG_OUTPUT_FORMAT="elf64-bigaarch64"
+LITTLE_OUTPUT_FORMAT="elf64-littleaarch64"
+NO_REL_RELOCS=yes
+
+TEMPLATE_NAME=elf32
+EXTRA_EM_FILE=aarch64elf
+
+GENERATE_SHLIB_SCRIPT=yes
+GENERATE_PIE_SCRIPT=yes
+
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
+SEPARATE_GOTPLT=24
+IREL_IN_PLT=
+
+TEXT_START_ADDR=0x400000
+
+DATA_START_SYMBOLS='PROVIDE (__data_start = .);';
+
+# AArch64 does not support .s* sections.
+NO_SMALL_DATA=yes
+
+OTHER_BSS_SYMBOLS='__bss_start__ = .;'
+OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
+OTHER_END_SYMBOLS='__end__ = . ;'
+
+OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
+ATTRS_SECTIONS='.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }'
+# Ensure each PLT entry is aligned to a cache line.
+PLT=".plt          ${RELOCATING-0} : ALIGN(16) { *(.plt)${IREL_IN_PLT+ *(.iplt)} }"
diff --git a/ld/emulparams/aarch64linuxb.sh b/ld/emulparams/aarch64linuxb.sh
new file mode 100644
index 0000000..2bdf602
--- /dev/null
+++ b/ld/emulparams/aarch64linuxb.sh
@@ -0,0 +1,2 @@
+. ${srcdir}/emulparams/aarch64linux.sh
+OUTPUT_FORMAT="elf64-bigaarch64"
diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em
new file mode 100644
index 0000000..4c03ffd
--- /dev/null
+++ b/ld/emultempl/aarch64elf.em
@@ -0,0 +1,415 @@
+# This shell script emits a C file. -*- C -*-
+#   Copyright 2009-2012  Free Software Foundation, Inc.
+#   Contributed by ARM Ltd.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not,
+# see <http://www.gnu.org/licenses/>.
+#
+
+# This file is sourced from elf32.em, and defines extra aarch64-elf
+# specific routines.
+#
+fragment <<EOF
+
+#include "ldctor.h"
+#include "elf/aarch64.h"
+
+static int no_enum_size_warning = 0;
+static int no_wchar_size_warning = 0;
+static int pic_veneer = 0;
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+#ifndef TARGET_			/* I.e., if not generic.  */
+  ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+  input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
+  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
+}
+
+static void
+aarch64_elf_before_allocation (void)
+{
+  /* We should be able to set the size of the interworking stub section.  We
+     can't do it until later if we have dynamic sections, though.  */
+  if (! elf_hash_table (&link_info)->dynamic_sections_created)
+    {
+      /* Here we rummage through the found bfds to collect information.  */
+      LANG_FOR_EACH_INPUT_STATEMENT (is)
+	{
+          /* Initialise mapping tables for code/data.  */
+          bfd_elf64_aarch64_init_maps (is->the_bfd);
+	}
+    }
+
+  /* Call the standard elf routine.  */
+  gld${EMULATION_NAME}_before_allocation ();
+}
+
+/* Fake input file for stubs.  */
+static lang_input_statement_type *stub_file;
+
+/* Whether we need to call gldarm_layout_sections_again.  */
+static int need_laying_out = 0;
+
+/* Maximum size of a group of input sections that can be handled by
+   one stub section.  A value of +/-1 indicates the bfd back-end
+   should use a suitable default size.  */
+static bfd_signed_vma group_size = 1;
+
+struct hook_stub_info
+{
+  lang_statement_list_type add;
+  asection *input_section;
+};
+
+/* Traverse the linker tree to find the spot where the stub goes.  */
+
+static bfd_boolean
+hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
+{
+  lang_statement_union_type *l;
+  bfd_boolean ret;
+
+  for (; (l = *lp) != NULL; lp = &l->header.next)
+    {
+      switch (l->header.type)
+	{
+	case lang_constructors_statement_enum:
+	  ret = hook_in_stub (info, &constructor_list.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_output_section_statement_enum:
+	  ret = hook_in_stub (info,
+			      &l->output_section_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_wild_statement_enum:
+	  ret = hook_in_stub (info, &l->wild_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_group_statement_enum:
+	  ret = hook_in_stub (info, &l->group_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_input_section_enum:
+	  if (l->input_section.section == info->input_section)
+	    {
+	      /* We've found our section.  Insert the stub immediately
+		 after its associated input section.  */
+	      *(info->add.tail) = l->header.next;
+	      l->header.next = info->add.head;
+	      return TRUE;
+	    }
+	  break;
+
+	case lang_data_statement_enum:
+	case lang_reloc_statement_enum:
+	case lang_object_symbols_statement_enum:
+	case lang_output_statement_enum:
+	case lang_target_statement_enum:
+	case lang_input_statement_enum:
+	case lang_assignment_statement_enum:
+	case lang_padding_statement_enum:
+	case lang_address_statement_enum:
+	case lang_fill_statement_enum:
+	  break;
+
+	default:
+	  FAIL ();
+	  break;
+	}
+    }
+  return FALSE;
+}
+
+
+/* Call-back for elf64_aarch64_size_stubs.  */
+
+/* Create a new stub section, and arrange for it to be linked
+   immediately after INPUT_SECTION.  */
+
+static asection *
+elf64_aarch64_add_stub_section (const char *stub_sec_name,
+				asection *input_section)
+{
+  asection *stub_sec;
+  flagword flags;
+  asection *output_section;
+  const char *secname;
+  lang_output_section_statement_type *os;
+  struct hook_stub_info info;
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+  stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
+						 stub_sec_name, flags);
+  if (stub_sec == NULL)
+    goto err_ret;
+
+  bfd_set_section_alignment (stub_file->the_bfd, stub_sec, 3);
+
+  output_section = input_section->output_section;
+  secname = bfd_get_section_name (output_section->owner, output_section);
+  os = lang_output_section_find (secname);
+
+  info.input_section = input_section;
+  lang_list_init (&info.add);
+  lang_add_section (&info.add, stub_sec, NULL, os);
+
+  if (info.add.head == NULL)
+    goto err_ret;
+
+  if (hook_in_stub (&info, &os->children.head))
+    return stub_sec;
+
+ err_ret:
+  einfo ("%X%P: can not make stub section: %E\n");
+  return NULL;
+}
+
+/* Another call-back for elf_arm_size_stubs.  */
+
+static void
+gldaarch64_layout_sections_again (void)
+{
+  /* If we have changed sizes of the stub sections, then we need
+     to recalculate all the section offsets.  This may mean we need to
+     add even more stubs.  */
+  gld${EMULATION_NAME}_map_segments (TRUE);
+  need_laying_out = -1;
+}
+
+static void
+build_section_lists (lang_statement_union_type *statement)
+{
+  if (statement->header.type == lang_input_section_enum)
+    {
+      asection *i = statement->input_section.section;
+
+      if (!((lang_input_statement_type *) i->owner->usrdata)->flags.just_syms
+	  && (i->flags & SEC_EXCLUDE) == 0
+	  && i->output_section != NULL
+	  && i->output_section->owner == link_info.output_bfd)
+	elf64_aarch64_next_input_section (& link_info, i);
+    }
+}
+
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+  /* bfd_elf32_discard_info just plays with debugging sections,
+     ie. doesn't affect any code, so we can delay resizing the
+     sections.  It's likely we'll resize everything in the process of
+     adding stubs.  */
+  if (bfd_elf_discard_info (link_info.output_bfd, & link_info))
+    need_laying_out = 1;
+
+  /* If generating a relocatable output file, then we don't
+     have to examine the relocs.  */
+  if (stub_file != NULL && !link_info.relocatable)
+    {
+      int ret = elf64_aarch64_setup_section_lists (link_info.output_bfd,
+						   & link_info);
+
+      if (ret != 0)
+	{
+	  if (ret < 0)
+	    {
+	      einfo ("%X%P: could not compute sections lists for stub generation: %E\n");
+	      return;
+	    }
+
+	  lang_for_each_statement (build_section_lists);
+
+	  /* Call into the BFD backend to do the real work.  */
+	  if (! elf64_aarch64_size_stubs (link_info.output_bfd,
+					  stub_file->the_bfd,
+					  & link_info,
+					  group_size,
+					  & elf64_aarch64_add_stub_section,
+					  & gldaarch64_layout_sections_again))
+	    {
+	      einfo ("%X%P: cannot size stub section: %E\n");
+	      return;
+	    }
+	}
+    }
+
+  if (need_laying_out != -1)
+    gld${EMULATION_NAME}_map_segments (need_laying_out);
+}
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+  if (! link_info.relocatable)
+    {
+      /* Now build the linker stubs.  */
+      if (stub_file->the_bfd->sections != NULL)
+	{
+	  if (! elf64_aarch64_build_stubs (& link_info))
+	    einfo ("%X%P: can not build stubs: %E\n");
+	}
+    }
+
+  finish_default ();
+}
+
+/* This is a convenient point to tell BFD about target specific flags.
+   After the output has been created, but before inputs are read.  */
+static void
+aarch64_elf_create_output_section_statements (void)
+{
+  if (strstr (bfd_get_target (link_info.output_bfd), "aarch64") == NULL)
+    {
+      /* The arm backend needs special fields in the output hash structure.
+	 These will only be created if the output format is an arm format,
+	 hence we do not support linking and changing output formats at the
+	 same time.  Use a link followed by objcopy to change output formats.  */
+      einfo ("%F%X%P: error: Cannot change output format whilst linking AArch64 binaries.\n");
+      return;
+    }
+
+  bfd_elf64_aarch64_set_options (link_info.output_bfd, &link_info,
+				 no_enum_size_warning,
+				 no_wchar_size_warning,
+				 pic_veneer);
+
+  stub_file = lang_add_input_file ("linker stubs",
+				   lang_input_file_is_fake_enum,
+				   NULL);
+  stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
+  if (stub_file->the_bfd == NULL
+      || ! bfd_set_arch_mach (stub_file->the_bfd,
+			      bfd_get_arch (link_info.output_bfd),
+			      bfd_get_mach (link_info.output_bfd)))
+    {
+      einfo ("%X%P: can not create BFD %E\n");
+      return;
+    }
+
+  stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
+  ldlang_add_file (stub_file);
+}
+
+/* Avoid processing the fake stub_file in vercheck, stat_needed and
+   check_needed routines.  */
+
+static void (*real_func) (lang_input_statement_type *);
+
+static void aarch64_for_each_input_file_wrapper (lang_input_statement_type *l)
+{
+  if (l != stub_file)
+    (*real_func) (l);
+}
+
+static void
+aarch64_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
+{
+  real_func = func;
+  lang_for_each_input_file (&aarch64_for_each_input_file_wrapper);
+}
+
+#define lang_for_each_input_file aarch64_lang_for_each_input_file
+
+EOF
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_NO_ENUM_SIZE_WARNING	309
+#define OPTION_PIC_VENEER		310
+#define OPTION_STUBGROUP_SIZE           311
+#define OPTION_NO_WCHAR_SIZE_WARNING	312
+'
+
+PARSE_AND_LIST_SHORTOPTS=p
+
+PARSE_AND_LIST_LONGOPTS='
+  { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
+  { "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING},
+  { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER},
+  { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
+  { "no-wchar-size-warning", no_argument, NULL, OPTION_NO_WCHAR_SIZE_WARNING},
+'
+
+PARSE_AND_LIST_OPTIONS='
+  fprintf (file, _("  --no-enum-size-warning      Don'\''t warn about objects with incompatible\n"
+		   "                                enum sizes\n"));
+  fprintf (file, _("  --no-wchar-size-warning     Don'\''t warn about objects with incompatible"
+		   "                                wchar_t sizes\n"));
+  fprintf (file, _("  --pic-veneer                Always generate PIC interworking veneers\n"));
+  fprintf (file, _("\
+   --stub-group-size=N   Maximum size of a group of input sections that can be\n\
+                           handled by one stub section.  A negative value\n\
+                           locates all stubs after their branches (with a\n\
+                           group size of -N), while a positive value allows\n\
+                           two groups of input sections, one before, and one\n\
+                           after each stub section.  Values of +/-1 indicate\n\
+                           the linker should choose suitable defaults.\n"
+		   ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+    case '\'p\'':
+      /* Only here for backwards compatibility.  */
+      break;
+
+    case OPTION_NO_ENUM_SIZE_WARNING:
+      no_enum_size_warning = 1;
+      break;
+
+    case OPTION_NO_WCHAR_SIZE_WARNING:
+      no_wchar_size_warning = 1;
+      break;
+
+    case OPTION_PIC_VENEER:
+      pic_veneer = 1;
+      break;
+
+    case OPTION_STUBGROUP_SIZE:
+      {
+	const char *end;
+
+        group_size = bfd_scan_vma (optarg, &end, 0);
+        if (*end)
+	  einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
+      }
+      break;
+'
+
+# We have our own before_allocation etc. functions, but they call
+# the standard routines, so give them a different name.
+LDEMUL_BEFORE_ALLOCATION=aarch64_elf_before_allocation
+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=aarch64_elf_create_output_section_statements
+
+# Replace the elf before_parse function with our own.
+LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+
+# Call the extra arm-elf function
+LDEMUL_FINISH=gld${EMULATION_NAME}_finish
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
new file mode 100644
index 0000000..eefe05a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -0,0 +1,105 @@
+# Expect script for various AARCH64 ELF tests.
+# Copyright 2009-2012 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# Exclude non-aarch64-ELF targets.
+if { ![is_elf_format] || ![istarget "aarch64*-*-*"] } {
+    return
+}
+
+# List contains test-items with 3 items followed by 2 lists:
+# 0:name 1:ld options 2:assembler options
+# 3:filenames of assembler files 4: action and options. 5: name of output file
+
+# Actions:
+# objdump: Apply objdump options on result.  Compare with regex (last arg).
+# nm: Apply nm options on result.  Compare with regex (last arg).
+# readelf: Apply readelf options on result.  Compare with regex (last arg).
+
+set aarch64elftests {
+    {"EH Frame merge" "-Ttext 0x8000" "" {eh-frame-bar.s eh-frame-foo.s}
+	{{objdump --dwarf=frames eh-frame.d}} "eh-frame"}
+}
+
+run_ld_link_tests $aarch64elftests
+
+# Relocation Tests
+run_dump_test "weak-undefined"
+run_dump_test "emit-relocs-257"
+run_dump_test "emit-relocs-257-be"
+# 258 is tested in 257
+# 259 is tested in 257
+run_dump_test "emit-relocs-260"
+run_dump_test "emit-relocs-260-be"
+# 261 is tested by 260
+run_dump_test "emit-relocs-262"
+run_dump_test "emit-relocs-263"
+run_dump_test "emit-relocs-264"
+run_dump_test "emit-relocs-265"
+run_dump_test "emit-relocs-266"
+run_dump_test "emit-relocs-267"
+run_dump_test "emit-relocs-268"
+run_dump_test "emit-relocs-269"
+run_dump_test "emit-relocs-270"
+run_dump_test "emit-relocs-270-bad"
+run_dump_test "emit-relocs-271"
+run_dump_test "emit-relocs-272"
+run_dump_test "emit-relocs-273"
+run_dump_test "emit-relocs-274"
+run_dump_test "emit-relocs-275"
+run_dump_test "emit-relocs-276"
+run_dump_test "emit-relocs-277"
+run_dump_test "emit-relocs-278"
+run_dump_test "emit-relocs-279"
+run_dump_test "emit-relocs-279-bad"
+run_dump_test "emit-relocs-280"
+# 281 is unused
+run_dump_test "emit-relocs-282"
+run_dump_test "emit-relocs-283"
+run_dump_test "emit-relocs-284"
+run_dump_test "emit-relocs-285"
+run_dump_test "emit-relocs-286"
+run_dump_test "emit-relocs-286-bad"
+# 287-298 are not done yet
+run_dump_test "emit-relocs-299"
+# 300-310 are not done yet
+run_dump_test "emit-relocs-311"
+run_dump_test "emit-relocs-312"
+
+
+run_dump_test "limit-b"
+run_dump_test "limit-bl"
+run_dump_test "farcall-section"
+run_dump_test "farcall-back"
+run_dump_test "farcall-bl"
+run_dump_test "farcall-b"
+run_dump_test "farcall-b-none-function"
+run_dump_test "farcall-bl-none-function"
+
+run_dump_test "tls-relax-all"
+run_dump_test "tls-relax-gd-le"
+run_dump_test "tls-relax-gdesc-le"
+run_dump_test "tls-relax-gd-ie"
+run_dump_test "tls-relax-gdesc-ie"
+run_dump_test "tls-relax-ie-le"
+run_dump_test "tls-desc-ie"
+run_dump_test "tls-relax-gdesc-ie-2"
+run_dump_test "tls-relax-gdesc-le-2"
+run_dump_test "tls-relax-ie-le-2"
+run_dump_test "tls-relax-ie-le-3"
diff --git a/ld/testsuite/ld-aarch64/aarch64.ld b/ld/testsuite/ld-aarch64/aarch64.ld
new file mode 100644
index 0000000..75ee3b5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/aarch64.ld
@@ -0,0 +1,19 @@
+/* Script for ld testsuite */
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x8000); . = 0x8000;
+  .text           :
+  {
+    *(.before)
+    *(.text)
+    *(.after)
+  } =0
+  . = 0x9000;
+  .got            : { *(.got) *(.got.plt)}
+  . = 0x12340000;
+  .far : { *(.far) }
+  .ARM.attributes 0 : { *(.ARM.atttributes) }
+}
diff --git a/ld/testsuite/ld-aarch64/eh-frame-bar.s b/ld/testsuite/ld-aarch64/eh-frame-bar.s
new file mode 100644
index 0000000..a67d8e4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/eh-frame-bar.s
@@ -0,0 +1,38 @@
+__longjmp:
+ .cfi_startproc
+ .cfi_def_cfa x0, 0
+ .cfi_offset x19, 16
+ .cfi_offset x20, 16
+ .cfi_offset x21, 16
+ .cfi_offset x22, 16
+ .cfi_offset x23, 24
+ .cfi_offset x24, 24
+ .cfi_offset x25, 24
+ .cfi_offset x26, 24
+ .cfi_offset x27, 24
+ .cfi_offset x28, 32
+ .cfi_offset x29, 32
+ .cfi_offset x30, 36
+ .cfi_offset d9, 8
+# This eh frame data differs from eh-frame-bar.s here, see the comment
+# in eh-frame-foo.s
+ .cfi_offset d11, 8
+
+ ldp x19, x20, [x0, #16]
+ ldp x21, x22, [x0, #16]
+ ldp x23, x24, [x0, #24]
+ ldp x25, x26, [x0, #24]
+ ldp x27, x28, [x0, #24]
+ ldp x29, x30, [x0, #32]
+
+ ldp d8, d9, [x0, #8]
+ ldp d10, d11, [x0, #8]
+ ldp d12, d13, [x0, #8]
+ ldp d14, d15, [x0, #8]
+ ldr x5, [x0, #48]
+ mov sp, x5
+ cmp x1, #0
+ mov x0, #1
+ csel x0, x1, x0, ne
+ br x30
+ .cfi_endproc
diff --git a/ld/testsuite/ld-aarch64/eh-frame-foo.s b/ld/testsuite/ld-aarch64/eh-frame-foo.s
new file mode 100644
index 0000000..c077ef2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/eh-frame-foo.s
@@ -0,0 +1,55 @@
+__longjmp:
+ .cfi_startproc
+ .cfi_def_cfa x0, 0
+ .cfi_offset x19, 16
+ .cfi_offset x20, 16
+ .cfi_offset x21, 16
+ .cfi_offset x22, 16
+ .cfi_offset x23, 24
+ .cfi_offset x24, 24
+ .cfi_offset x25, 24
+ .cfi_offset x26, 24
+ .cfi_offset x27, 24
+ .cfi_offset x28, 32
+ .cfi_offset x29, 32
+ .cfi_offset x30, 36
+ .cfi_offset d9, 8
+
+/* This eh frame data differs from eh-frame-bar.s here.  The eh
+   frame information is identical but changes at the end.  The
+   initial identical section is long enough to overflow the
+   initial instruction buffer used in eh frame merging.  This
+   checks that merging does something sane once the initial
+   instruction buffer overflows.  */
+
+.cfi_offset d10, 8
+
+
+
+
+
+
+
+ ldp x19, x20, [x0, #16]
+ ldp x21, x22, [x0, #16]
+ ldp x23, x24, [x0, #24]
+ ldp x25, x26, [x0, #24]
+ ldp x27, x28, [x0, #24]
+ ldp x29, x30, [x0, #32]
+
+ ldp d8, d9, [x0, #8]
+ ldp d10, d11, [x0, #8]
+ ldp d12, d13, [x0, #8]
+ ldp d14, d15, [x0, #8]
+ ldr x5, [x0, #48]
+ mov sp, x5
+ cmp x1, #0
+ mov x0, #1
+ csel x0, x1, x0, ne
+
+ br x30
+ .cfi_endproc
+
+ .global _start
+_start:
+
diff --git a/ld/testsuite/ld-aarch64/eh-frame.d b/ld/testsuite/ld-aarch64/eh-frame.d
new file mode 100644
index 0000000..88e9988
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/eh-frame.d
@@ -0,0 +1,86 @@
+.*:     file format elf64-(little|big)aarch64
+
+Contents of the .eh_frame section:
+
+00000000 00000044 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 2
+  Data alignment factor: -4
+  Return address column: 30
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r31 ofs 0
+  DW_CFA_def_cfa: r0 ofs 0
+  DW_CFA_offset_extended_sf: r19 at cfa\+16
+  DW_CFA_offset_extended_sf: r20 at cfa\+16
+  DW_CFA_offset_extended_sf: r21 at cfa\+16
+  DW_CFA_offset_extended_sf: r22 at cfa\+16
+  DW_CFA_offset_extended_sf: r23 at cfa\+24
+  DW_CFA_offset_extended_sf: r24 at cfa\+24
+  DW_CFA_offset_extended_sf: r25 at cfa\+24
+  DW_CFA_offset_extended_sf: r26 at cfa\+24
+  DW_CFA_offset_extended_sf: r27 at cfa\+24
+  DW_CFA_offset_extended_sf: r28 at cfa\+32
+  DW_CFA_offset_extended_sf: r29 at cfa\+32
+  DW_CFA_offset_extended_sf: r30 at cfa\+36
+  DW_CFA_offset_extended_sf: r9 at cfa\+8
+  DW_CFA_offset_extended_sf: r11 at cfa\+8
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000048 00000014 0000004c FDE cie=00000000 pc=f*ffffff80..f*ffffffc0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000060 00000044 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 2
+  Data alignment factor: -4
+  Return address column: 30
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r31 ofs 0
+  DW_CFA_def_cfa: r0 ofs 0
+  DW_CFA_offset_extended_sf: r19 at cfa\+16
+  DW_CFA_offset_extended_sf: r20 at cfa\+16
+  DW_CFA_offset_extended_sf: r21 at cfa\+16
+  DW_CFA_offset_extended_sf: r22 at cfa\+16
+  DW_CFA_offset_extended_sf: r23 at cfa\+24
+  DW_CFA_offset_extended_sf: r24 at cfa\+24
+  DW_CFA_offset_extended_sf: r25 at cfa\+24
+  DW_CFA_offset_extended_sf: r26 at cfa\+24
+  DW_CFA_offset_extended_sf: r27 at cfa\+24
+  DW_CFA_offset_extended_sf: r28 at cfa\+32
+  DW_CFA_offset_extended_sf: r29 at cfa\+32
+  DW_CFA_offset_extended_sf: r30 at cfa\+36
+  DW_CFA_offset_extended_sf: r9 at cfa\+8
+  DW_CFA_offset_extended_sf: r10 at cfa\+8
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000000a8 00000014 0000004c FDE cie=00000060 pc=f*ffffffc0..00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-257-be.d b/ld/testsuite/ld-aarch64/emit-relocs-257-be.d
new file mode 100644
index 0000000..3f6be24
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-257-be.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-257.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234  -e0 --emit-relocs
+#notarget: aarch64-*-*
+#objdump: -dr
+#...
+ +10000:	00011012 	\.word	0x00011012
+	+10000: R_AARCH64_ABS32	tempy
+ +10004:	00000000 	\.word	0x00000000
+	+10004: R_AARCH64_ABS64	tempy2
+ +10008:	00045034 	\.word	0x00045034
+ +1000c:	1234123c 	\.word	0x1234123c
+	+1000c: R_AARCH64_ABS16	tempy3
+	+1000e: R_AARCH64_ABS16	tempy3\+0x8
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-257.d b/ld/testsuite/ld-aarch64/emit-relocs-257.d
new file mode 100644
index 0000000..0a3a7ac
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-257.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-257.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234  -e0 --emit-relocs
+#notarget: aarch64_be-*-*
+#objdump: -dr
+#...
+ +10000:	00011012 	\.word	0x00011012
+	+10000: R_AARCH64_ABS32	tempy
+ +10004:	00045034 	\.word	0x00045034
+	+10004: R_AARCH64_ABS64	tempy2
+ +10008:	00000000 	\.word	0x00000000
+ +1000c:	123c1234 	\.word	0x123c1234
+	+1000c: R_AARCH64_ABS16	tempy3
+	+1000e: R_AARCH64_ABS16	tempy3\+0x8
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-257.s b/ld/testsuite/ld-aarch64/emit-relocs-257.s
new file mode 100644
index 0000000..609ebba
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-257.s
@@ -0,0 +1,12 @@
+.comm   gempy,4,4
+.text
+
+.word	tempy
+.xword  tempy2
+.hword	tempy3
+.hword	tempy3+8
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-260-be.d b/ld/testsuite/ld-aarch64/emit-relocs-260-be.d
new file mode 100644
index 0000000..7cea3c6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-260-be.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-260.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234 --defsym _GOT_=0x10000 -e0 --emit-relocs
+#notarget: aarch64-*-*
+#objdump: -dr
+#...
+	+10000: R_AARCH64_PREL32	_GOT_
+	+10004: R_AARCH64_PREL64	_GOT_\+0x12
+ +10008:	0000000e 	\.word	0x0000000e
+ +1000c:	fff404f2 	\.word	0xfff404f2
+	+1000c: R_AARCH64_PREL16	_GOT_
+	+1000e: R_AARCH64_PREL16	_GOT_\+0x500
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-260.d b/ld/testsuite/ld-aarch64/emit-relocs-260.d
new file mode 100644
index 0000000..91c1d8a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-260.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-260.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234 --defsym _GOT_=0x10000 -e0 --emit-relocs
+#notarget: aarch64_be-*-*
+#objdump: -dr
+#...
+ +10000:	00000000 	\.word	0x00000000
+	+10000: R_AARCH64_PREL32	_GOT_
+ +10004:	0000000e 	\.word	0x0000000e
+	+10004: R_AARCH64_PREL64	_GOT_\+0x12
+ +10008:	00000000 	\.word	0x00000000
+ +1000c:	04f2fff4 	\.word	0x04f2fff4
+	+1000c: R_AARCH64_PREL16	_GOT_
+	+1000e: R_AARCH64_PREL16	_GOT_\+0x500
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-260.s b/ld/testsuite/ld-aarch64/emit-relocs-260.s
new file mode 100644
index 0000000..87aa342
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-260.s
@@ -0,0 +1,13 @@
+.comm   gempy,4,4
+.text
+
+.word	_GOT_ - .
+.xword  _GOT_ - . + 0x12
+.hword	_GOT_ - . 
+.hword	_GOT_ - . + 0x500 
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-262.d b/ld/testsuite/ld-aarch64/emit-relocs-262.d
new file mode 100644
index 0000000..c42ecb6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-262.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-262.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234 --defsym _GOT_=0x20000 -e0 --emit-relocs
+#error: .*truncated.*
+#objdump: -dr
+#...
+ +10000:	00011012 	\.word	0x00011012
+	+10000: R_AARCH64_PREL32	tempy
+ +10004:	00045034 	\.word	0x00045034
+	+10004: R_AARCH64_PREL64	tempy2
+ +10008:	00000000 	\.word	0x00000000
+ +1000c:	123c1234 	\.word	0x123c1234
+	+1000c: R_AARCH64_PREL16	tempy3
+	+1000e: R_AARCH64_PREL16	tempy3\+0x8
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-262.s b/ld/testsuite/ld-aarch64/emit-relocs-262.s
new file mode 100644
index 0000000..aa97f52
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-262.s
@@ -0,0 +1,13 @@
+.comm   gempy,4,4
+.text
+
+.word	_GOT_ - .
+.xword  _GOT_ - . + 0x12
+.hword	_GOT_ - . 
+.hword	_GOT_ - . 
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-263.d b/ld/testsuite/ld-aarch64/emit-relocs-263.d
new file mode 100644
index 0000000..a6c854d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-263.d
@@ -0,0 +1,15 @@
+#source: emit-relocs-263.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#error: .*\(.text\+0x\d+\): relocation truncated to fit: R_AARCH64_MOVW_UABS_G0 against symbol `tempy.*
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820004 	movz	x4, #0x1000
+	+10008: R_AARCH64_MOVW_UABS_G0	tempy
+ +1000c:	d28a0007 	movz	x7, #0x5000
+	+1000c: R_AARCH64_MOVW_UABS_G0	tempy2
+ +10010:	d2824691 	movz	x17, #0x1234
+	+10010: R_AARCH64_MOVW_UABS_G0	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-263.s b/ld/testsuite/ld-aarch64/emit-relocs-263.s
new file mode 100644
index 0000000..e215872
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-263.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g0:tempy
+	movz	x7, :abs_g0:tempy2
+	movz	x17, :abs_g0:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-264.d b/ld/testsuite/ld-aarch64/emit-relocs-264.d
new file mode 100644
index 0000000..1da911b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-264.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-264.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820004 	movz	x4, #0x1000
+	+10008: R_AARCH64_MOVW_UABS_G0_NC	tempy
+ +1000c:	d28a0007 	movz	x7, #0x5000
+	+1000c: R_AARCH64_MOVW_UABS_G0_NC	tempy2
+ +10010:	d2824691 	movz	x17, #0x1234
+	+10010: R_AARCH64_MOVW_UABS_G0_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-264.s b/ld/testsuite/ld-aarch64/emit-relocs-264.s
new file mode 100644
index 0000000..32a5a17
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-264.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g0_nc:tempy
+	movz	x7, :abs_g0_nc:tempy2
+	movz	x17, :abs_g0_nc:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-265.d b/ld/testsuite/ld-aarch64/emit-relocs-265.d
new file mode 100644
index 0000000..d30db5f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-265.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-265.s
+#ld: -T relocs.ld --defsym tempy=0x100011000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#error: .*\(.text\+0x\d+\): relocation truncated to fit: R_AARCH64_MOVW_UABS_G1 against symbol `tempy.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2a00024 	movz	x4, #0x1, lsl #16
+	+10008: R_AARCH64_MOVW_UABS_G1	tempy
+ +1000c:	d2a00087 	movz	x7, #0x4, lsl #16
+	+1000c: R_AARCH64_MOVW_UABS_G1	tempy2
+ +10010:	d2a00011 	movz	x17, #0x0, lsl #16
+	+10010: R_AARCH64_MOVW_UABS_G1	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-265.s b/ld/testsuite/ld-aarch64/emit-relocs-265.s
new file mode 100644
index 0000000..552a8ae
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-265.s
@@ -0,0 +1,10 @@
+.comm   gempy,4,4
+.text
+
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g1:tempy
+	movz	x7, :abs_g1:tempy2
+	movz	x17, :abs_g1:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-266.d b/ld/testsuite/ld-aarch64/emit-relocs-266.d
new file mode 100644
index 0000000..fde9090
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-266.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-266.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2a00024 	movz	x4, #0x1, lsl #16
+	+10008: R_AARCH64_MOVW_UABS_G1_NC	tempy
+ +1000c:	d2a00087 	movz	x7, #0x4, lsl #16
+	+1000c: R_AARCH64_MOVW_UABS_G1_NC	tempy2
+ +10010:	d2a00011 	movz	x17, #0x0, lsl #16
+	+10010: R_AARCH64_MOVW_UABS_G1_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-266.s b/ld/testsuite/ld-aarch64/emit-relocs-266.s
new file mode 100644
index 0000000..7c23e87
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-266.s
@@ -0,0 +1,10 @@
+.comm   gempy,4,4
+.text
+
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g1_nc:tempy
+	movz	x7, :abs_g1_nc:tempy2
+	movz	x17, :abs_g1_nc:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-267.d b/ld/testsuite/ld-aarch64/emit-relocs-267.d
new file mode 100644
index 0000000..9cc495c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-267.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-267.s
+#ld: -T relocs.ld --defsym tempy=0x63001000 --defsym tempy2=0x4500000000 --defsym tempy3=0x1234567812345  -e0 --emit-relocs
+#error: .*truncated.*tempy3.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2c00004 	movz	x4, #0x0, lsl #32
+	+10008: R_AARCH64_MOVW_UABS_G2	tempy
+ +1000c:	d2c008a7 	movz	x7, #0x45, lsl #32
+	+1000c: R_AARCH64_MOVW_UABS_G2	tempy2
+ +10010:	d2c468b1 	movz	x17, #0x2345, lsl #32
+	+10010: R_AARCH64_MOVW_UABS_G2	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-267.s b/ld/testsuite/ld-aarch64/emit-relocs-267.s
new file mode 100644
index 0000000..94a150e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-267.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g2:tempy
+	movz	x7, :abs_g2:tempy2
+	movz	x17, :abs_g2:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-268.d b/ld/testsuite/ld-aarch64/emit-relocs-268.d
new file mode 100644
index 0000000..126548b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-268.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-268.s
+#ld: -T relocs.ld --defsym tempy=0x63001000 --defsym tempy2=0x4500000000 --defsym tempy3=0x1234567812345  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2c00004 	movz	x4, #0x0, lsl #32
+	+10008: R_AARCH64_MOVW_UABS_G2_NC	tempy
+ +1000c:	d2c008a7 	movz	x7, #0x45, lsl #32
+	+1000c: R_AARCH64_MOVW_UABS_G2_NC	tempy2
+ +10010:	d2c468b1 	movz	x17, #0x2345, lsl #32
+	+10010: R_AARCH64_MOVW_UABS_G2_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-268.s b/ld/testsuite/ld-aarch64/emit-relocs-268.s
new file mode 100644
index 0000000..5928043
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-268.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g2_nc:tempy
+	movz	x7, :abs_g2_nc:tempy2
+	movz	x17, :abs_g2_nc:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-269.d b/ld/testsuite/ld-aarch64/emit-relocs-269.d
new file mode 100644
index 0000000..a911532
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-269.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-269.s
+#ld: -T relocs.ld --defsym tempy=0x6300100100100100 --defsym tempy2=0xf00df00df00df00d --defsym tempy3=0x1234567812345  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2ec6004 	movz	x4, #0x6300, lsl #48
+	+10008: R_AARCH64_MOVW_UABS_G3	tempy
+ +1000c:	d2fe01a7 	movz	x7, #0xf00d, lsl #48
+	+1000c: R_AARCH64_MOVW_UABS_G3	tempy2
+ +10010:	d2e00031 	movz	x17, #0x1, lsl #48
+	+10010: R_AARCH64_MOVW_UABS_G3	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-269.s b/ld/testsuite/ld-aarch64/emit-relocs-269.s
new file mode 100644
index 0000000..b0f11a0
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-269.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g3:tempy
+	movz	x7, :abs_g3:tempy2
+	movz	x17, :abs_g3:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-270-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-270-bad.d
new file mode 100644
index 0000000..a781a5a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-270-bad.d
@@ -0,0 +1,15 @@
+#source: emit-relocs-270.s
+#ld: -T relocs.ld --defsym tempy=0x10012 --defsym tempy2=0x45000 --defsym tempy3=-292  -e0 --emit-relocs
+#error: .*truncated.*tempy[12].*
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820244 	movz	x4, #0x1012
+	+10008: R_AARCH64_MOVW_SABS_G0	tempy
+ +1000c:	d288a007 	movz	x7, #0x4500
+	+1000c: R_AARCH64_MOVW_SABS_G0	tempy2
+ +10010:	92802471 	movn	x17, #0x123
+	+10010: R_AARCH64_MOVW_SABS_G0	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-270.d b/ld/testsuite/ld-aarch64/emit-relocs-270.d
new file mode 100644
index 0000000..6e68aec
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-270.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-270.s
+#ld: -T relocs.ld --defsym tempy=0x1012 --defsym tempy2=0x4500 --defsym tempy3=-292  -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820244 	movz	x4, #0x1012
+	+10008: R_AARCH64_MOVW_SABS_G0	tempy
+ +1000c:	d288a007 	movz	x7, #0x4500
+	+1000c: R_AARCH64_MOVW_SABS_G0	tempy2
+ +10010:	92802471 	movn	x17, #0x123
+	+10010: R_AARCH64_MOVW_SABS_G0	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-270.s b/ld/testsuite/ld-aarch64/emit-relocs-270.s
new file mode 100644
index 0000000..b508f88
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-270.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g0_s:tempy
+	movz	x7, :abs_g0_s:tempy2
+	movz	x17, :abs_g0_s:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-271.d b/ld/testsuite/ld-aarch64/emit-relocs-271.d
new file mode 100644
index 0000000..5a230c7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-271.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-271.s
+#ld: -T relocs.ld --defsym tempy=0x1012 --defsym tempy2=0x674500 --defsym tempy3=-292  -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2a00004 	movz	x4, #0x0, lsl #16
+	+10008: R_AARCH64_MOVW_SABS_G1	tempy
+ +1000c:	d2a00ce7 	movz	x7, #0x67, lsl #16
+	+1000c: R_AARCH64_MOVW_SABS_G1	tempy2
+ +10010:	92a00011 	movn	x17, #0x0, lsl #16
+	+10010: R_AARCH64_MOVW_SABS_G1	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-271.s b/ld/testsuite/ld-aarch64/emit-relocs-271.s
new file mode 100644
index 0000000..bb14fbb
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-271.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g1_s:tempy
+	movz	x7, :abs_g1_s:tempy2
+	movz	x17, :abs_g1_s:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-272.d b/ld/testsuite/ld-aarch64/emit-relocs-272.d
new file mode 100644
index 0000000..a02a52e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-272.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-272.s
+#ld: -T relocs.ld --defsym tempy=0x1012 --defsym tempy2=-12345678912345 --defsym tempy3=-292  -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2c00004 	movz	x4, #0x0, lsl #32
+	+10008: R_AARCH64_MOVW_SABS_G2	tempy
+ +1000c:	92c16747 	movn	x7, #0xb3a, lsl #32
+	+1000c: R_AARCH64_MOVW_SABS_G2	tempy2
+ +10010:	92c00011 	movn	x17, #0x0, lsl #32
+	+10010: R_AARCH64_MOVW_SABS_G2	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-272.s b/ld/testsuite/ld-aarch64/emit-relocs-272.s
new file mode 100644
index 0000000..daa625a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-272.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g2_s:tempy
+	movz	x7, :abs_g2_s:tempy2
+	movz	x17, :abs_g2_s:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-273.d b/ld/testsuite/ld-aarch64/emit-relocs-273.d
new file mode 100644
index 0000000..13ed221
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-273.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-273.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	58007fc4 	ldr	x4, 11000 <tempy>
+	+10008: R_AARCH64_LD_PREL_LO19	tempy
+ +1000c:	581a7fa7 	ldr	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_LD_PREL_LO19	tempy2
+ +10010:	58f89131 	ldr	x17, 1234 <tempy3>
+	+10010: R_AARCH64_LD_PREL_LO19	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-273.s b/ld/testsuite/ld-aarch64/emit-relocs-273.s
new file mode 100644
index 0000000..d1bad37
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-273.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     x4,tempy
+	ldr	x7,tempy2
+	ldr	x17,tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-274.d b/ld/testsuite/ld-aarch64/emit-relocs-274.d
new file mode 100644
index 0000000..f38ecbd
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-274.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-274.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	10007fc2 	adr	x2, .*
+	+10008: R_AARCH64_ADR_PREL_LO21	tempy
+ +1000c:	101a7fa7 	adr	x7, 45000 .*
+	+1000c: R_AARCH64_ADR_PREL_LO21	tempy2
+ +10010:	10f89131 	adr	x17, .*
+	+10010: R_AARCH64_ADR_PREL_LO21	tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-274.s b/ld/testsuite/ld-aarch64/emit-relocs-274.s
new file mode 100644
index 0000000..8668b7c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-274.s
@@ -0,0 +1,5 @@
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adr     x2,tempy
+        adr     x7,tempy2
+	adr	x17,tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-275.d b/ld/testsuite/ld-aarch64/emit-relocs-275.d
new file mode 100644
index 0000000..94e61a7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-275.d
@@ -0,0 +1,15 @@
+#source: emit-relocs-275.s
+#ld: -T relocs.ld --defsym tempy=0x200011000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#error: .*\(.text\+0x\d+\): relocation truncated to fit: R_AARCH64_ADR_PREL_PG_HI21 against symbol `tempy'
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b0000002 	adrp	x2, .*
+	+10008: R_AARCH64_ADR_PREL_PG_HI21	tempy
+ +1000c:	b00001a7 	adrp	x7, .*
+	+1000c: R_AARCH64_ADR_PREL_PG_HI21	tempy2
+ +10010:	b0ffff91 	adrp	x17, .*
+	+10010: R_AARCH64_ADR_PREL_PG_HI21	tempy3
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-275.s b/ld/testsuite/ld-aarch64/emit-relocs-275.s
new file mode 100644
index 0000000..92a2935
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-275.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adrp    x2,tempy
+	adrp	x7,tempy2
+	adrp	x17,tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-276.d b/ld/testsuite/ld-aarch64/emit-relocs-276.d
new file mode 100644
index 0000000..f133253
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-276.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-275.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b0000002 	adrp	x2, 11000 <tempy>
+	+10008: R_AARCH64_ADR_PREL_PG_HI21	tempy
+ +1000c:	b00001a7 	adrp	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_ADR_PREL_PG_HI21	tempy2
+ +10010:	b0ffff91 	adrp	x17, 1000 <tempy3-0x234>
+	+10010: R_AARCH64_ADR_PREL_PG_HI21	tempy3
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-276.s b/ld/testsuite/ld-aarch64/emit-relocs-276.s
new file mode 100644
index 0000000..92a2935
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-276.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adrp    x2,tempy
+	adrp	x7,tempy2
+	adrp	x17,tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-277.d b/ld/testsuite/ld-aarch64/emit-relocs-277.d
new file mode 100644
index 0000000..2145441
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-277.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-277.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	91006064 	add	x4, x3,.*
+	+10008: R_AARCH64_ADD_ABS_LO12_NC	tempy
+ +1000c:	9100e067 	add	x7, x3,.*
+	+1000c: R_AARCH64_ADD_ABS_LO12_NC	tempy2
+ +10010:	9108d071 	add	x17, x3,.*
+	+10010: R_AARCH64_ADD_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-277.s b/ld/testsuite/ld-aarch64/emit-relocs-277.s
new file mode 100644
index 0000000..efb0bf0
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-277.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        add     x4, x3, #:lo12:tempy
+	add	x7, x3, #:lo12:tempy2
+	add	x17, x3, #:lo12:tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-278.d b/ld/testsuite/ld-aarch64/emit-relocs-278.d
new file mode 100644
index 0000000..29a0095
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-278.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-278.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	3d406064 	ldr	b4, \[x3,.*
+	+10008: R_AARCH64_LDST8_ABS_LO12_NC	tempy
+ +1000c:	3d40e067 	ldr	b7, \[x3,.*
+	+1000c: R_AARCH64_LDST8_ABS_LO12_NC	tempy2
+ +10010:	3d48d071 	ldr	b17, \[x3,.*
+	+10010: R_AARCH64_LDST8_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-278.s b/ld/testsuite/ld-aarch64/emit-relocs-278.s
new file mode 100644
index 0000000..2f7f321
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-278.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     b4, [x3, #:lo12:tempy]
+	ldr	b7, [x3, #:lo12:tempy2]
+	ldr	b17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-279-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-279-bad.d
new file mode 100644
index 0000000..02b5ff6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-279-bad.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-279.s
+#ld: -T relocs.ld --defsym target=0xc000 --defsym target2=0x45678 -e0 --emit-relocs
+#error: .*truncated.*target2.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	17ffeffc 	b	c000 <target>
+	+10010: R_AARCH64_TSTBR14	target
+ +10014:	17ffefff 	b	c010 <target\+0x10>
+	+10014: R_AARCH64_TSTBR14	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-279.d b/ld/testsuite/ld-aarch64/emit-relocs-279.d
new file mode 100644
index 0000000..6980f81
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-279.d
@@ -0,0 +1,17 @@
+#source: emit-relocs-279.s
+#ld: -T relocs.ld --defsym target=0xc000 --defsym target2=0x12340 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	363dff84 	tbz	w4, #7, c000 <target>
+	+10010: R_AARCH64_TSTBR14	target
+ +10014:	b745ffe7 	tbnz	x7, #40, c010 <target\+0x10>
+	+10014: R_AARCH64_TSTBR14	target\+0x10
+ +10018:	3619194c 	tbz	w12, #3, 12340 <target2>
+	+10018: R_AARCH64_TSTBR14	target2
+ +1001c:	b7c118d1 	tbnz	x17, #56, 12334 <target.*
+	+1001c: R_AARCH64_TSTBR14	target.*
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-279.s b/ld/testsuite/ld-aarch64/emit-relocs-279.s
new file mode 100644
index 0000000..f70c78b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-279.s
@@ -0,0 +1,8 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	tbz	x4, 7, target
+	tbnz	x7, 40, target+16
+	tbz	x12, 3, target2
+	tbnz	x17, 56, target2-12
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-280.d b/ld/testsuite/ld-aarch64/emit-relocs-280.d
new file mode 100644
index 0000000..9b954ff
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-280.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-280.s
+#ld: -T relocs.ld --defsym target=0xc000 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	54fdff80 	b.eq	c000 <target>
+	+10010: R_AARCH64_CONDBR19	target
+ +10014:	54fdffe0 	b.eq	c010 <target\+0x10>
+	+10014: R_AARCH64_CONDBR19	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-280.s b/ld/testsuite/ld-aarch64/emit-relocs-280.s
new file mode 100644
index 0000000..8f5ec34
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-280.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	beq	target
+	beq	target+16
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-282.d b/ld/testsuite/ld-aarch64/emit-relocs-282.d
new file mode 100644
index 0000000..fc5764b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-282.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-282.s
+#ld: -T relocs.ld --defsym target=0xc000 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	17ffeffc 	b	c000 <target>
+	+10010: R_AARCH64_JUMP26	target
+ +10014:	17ffefff 	b	c010 <target\+0x10>
+	+10014: R_AARCH64_JUMP26	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-282.s b/ld/testsuite/ld-aarch64/emit-relocs-282.s
new file mode 100644
index 0000000..b249b6b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-282.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	b	target
+	b	target+16
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-283.d b/ld/testsuite/ld-aarch64/emit-relocs-283.d
new file mode 100644
index 0000000..708fc7c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-283.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-283.s
+#ld: -T relocs.ld --defsym target=0xc000 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	97ffeffc 	bl	c000 <target>
+	+10010: R_AARCH64_CALL26	target
+ +10014:	97ffefff 	bl	c010 <target\+0x10>
+	+10014: R_AARCH64_CALL26	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-283.s b/ld/testsuite/ld-aarch64/emit-relocs-283.s
new file mode 100644
index 0000000..9c9f509
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-283.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	bl	target
+	bl	target+16
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-284.d b/ld/testsuite/ld-aarch64/emit-relocs-284.d
new file mode 100644
index 0000000..5cb6dac
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-284.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-284.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	7d403064 	ldr	h4, \[x3,.*
+	+10008: R_AARCH64_LDST16_ABS_LO12_NC	tempy
+ +1000c:	7d407067 	ldr	h7, \[x3,.*
+	+1000c: R_AARCH64_LDST16_ABS_LO12_NC	tempy2
+ +10010:	7d446871 	ldr	h17, \[x3,.*
+	+10010: R_AARCH64_LDST16_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-284.s b/ld/testsuite/ld-aarch64/emit-relocs-284.s
new file mode 100644
index 0000000..ffd213b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-284.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     h4, [x3, #:lo12:tempy]
+	ldr	h7, [x3, #:lo12:tempy2]
+	ldr	h17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-285.d b/ld/testsuite/ld-aarch64/emit-relocs-285.d
new file mode 100644
index 0000000..8bf8270
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-285.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-285.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b9401864 	ldr	w4, \[x3,.*
+	+10008: R_AARCH64_LDST32_ABS_LO12_NC	tempy
+ +1000c:	b9403867 	ldr	w7, \[x3,.*
+	+1000c: R_AARCH64_LDST32_ABS_LO12_NC	tempy2
+ +10010:	b9423471 	ldr	w17, \[x3,.*
+	+10010: R_AARCH64_LDST32_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-285.s b/ld/testsuite/ld-aarch64/emit-relocs-285.s
new file mode 100644
index 0000000..245f8be
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-285.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     w4, [x3, #:lo12:tempy]
+	ldr	w7, [x3, #:lo12:tempy2]
+	ldr	w17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-286-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-286-bad.d
new file mode 100644
index 0000000..50cd605
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-286-bad.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-286.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#error: .*truncated.*tempy3.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	f9400c64 	ldr	x4, \[x3,.*
+	+10008: R_AARCH64_LDST64_ABS_LO12_NC	tempy
+ +1000c:	f9401c67 	ldr	x7, \[x3,.*
+	+1000c: R_AARCH64_LDST64_ABS_LO12_NC	tempy2
+ +10010:	f9411871 	ldr	x17, \[x3,.*
+	+10010: R_AARCH64_LDST64_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-286.d b/ld/testsuite/ld-aarch64/emit-relocs-286.d
new file mode 100644
index 0000000..851fa7b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-286.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-286.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1230  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	f9400c64 	ldr	x4, \[x3,.*
+	+10008: R_AARCH64_LDST64_ABS_LO12_NC	tempy
+ +1000c:	f9401c67 	ldr	x7, \[x3,.*
+	+1000c: R_AARCH64_LDST64_ABS_LO12_NC	tempy2
+ +10010:	f9411871 	ldr	x17, \[x3,.*
+	+10010: R_AARCH64_LDST64_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-286.s b/ld/testsuite/ld-aarch64/emit-relocs-286.s
new file mode 100644
index 0000000..78b508f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-286.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     x4, [x3, #:lo12:tempy]
+	ldr	x7, [x3, #:lo12:tempy2]
+	ldr	x17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-287.d b/ld/testsuite/ld-aarch64/emit-relocs-287.d
new file mode 100644
index 0000000..4d5fd43
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-287.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-287.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 --defsym _GOT_=0x10000 -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820004 	movz	x4, #0x1000
+	+10008: R_AARCH64_MOVW_PREL_G0	_GOT_
+ +1000c:	d28a0007 	movz	x7, #0x5000
+	+1000c: R_AARCH64_MOVW_PREL_G0	_GOT_
+ +10010:	d2824691 	movz	x17, #0x1234
+	+10010: R_AARCH64_MOVW_PREL_G0	_GOT_
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-287.s b/ld/testsuite/ld-aarch64/emit-relocs-287.s
new file mode 100644
index 0000000..ae9476f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-287.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :prel_g0:tempy
+	movz	x7, :prel_g0:tempy2
+	movz	x17, :prel_g0:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-299.d b/ld/testsuite/ld-aarch64/emit-relocs-299.d
new file mode 100644
index 0000000..d24b442
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-299.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-299.s
+#ld: -T relocs.ld --defsym tempy=0x11030 --defsym tempy2=0x45fa0 --defsym tempy3=0x1230  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	3dc00c64 	ldr	q4, \[x3,.*
+	+10008: R_AARCH64_LDST128_ABS_LO12_NC	tempy
+ +1000c:	3dc3e867 	ldr	q7, \[x3,.*
+	+1000c: R_AARCH64_LDST128_ABS_LO12_NC	tempy2
+ +10010:	3dc08c71 	ldr	q17, \[x3,.*
+	+10010: R_AARCH64_LDST128_ABS_LO12_NC	tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-299.s b/ld/testsuite/ld-aarch64/emit-relocs-299.s
new file mode 100644
index 0000000..b1fe6cf
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-299.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+	ldr     q4, [x3, #:lo12:tempy]
+	ldr	q7, [x3, #:lo12:tempy2]
+	ldr	q17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-311.d b/ld/testsuite/ld-aarch64/emit-relocs-311.d
new file mode 100644
index 0000000..5f1b47f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-311.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-311.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b0000002 	adrp	x2, 11000 <tempy>
+	+10008: R_AARCH64_ADR_PREL_PG_HI21	tempy
+ +1000c:	b00001a7 	adrp	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_ADR_PREL_PG_HI21	tempy2
+ +10010:	b0ffff91 	adrp	x17, 1000 <tempy3-0x234>
+	+10010: R_AARCH64_ADR_PREL_PG_HI21	tempy3
+ +10014:	90000083 	adrp	x3, 20000 <tempy[+]0xf000>
+	+10014: R_AARCH64_ADR_GOT_PAGE	gempy
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-311.s b/ld/testsuite/ld-aarch64/emit-relocs-311.s
new file mode 100644
index 0000000..182f0d4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-311.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adrp    x2,tempy
+	adrp	x7,tempy2
+	adrp	x17,tempy3
+        adrp	x3,:got:gempy
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-312.d b/ld/testsuite/ld-aarch64/emit-relocs-312.d
new file mode 100644
index 0000000..8d50d8d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-312.d
@@ -0,0 +1,19 @@
+#source: emit-relocs-312.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	58007fc4 	ldr	x4, 11000 <tempy>
+	+10008: R_AARCH64_LD_PREL_LO19	tempy
+ +1000c:	581a7fa7 	ldr	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_LD_PREL_LO19	tempy2
+ +10010:	58f89131 	ldr	x17, 1234 <tempy3>
+	+10010: R_AARCH64_LD_PREL_LO19	tempy3
+ +10014:	f9400843 	ldr	x3, \[x2.*
+	+10014: R_AARCH64_LD64_GOT_LO12_NC	jempy
+ +10018:	f9400444 	ldr	x4, \[x2.*
+	+10018: R_AARCH64_LD64_GOT_LO12_NC	gempy
+ +1001c:	f9400045 	ldr	x5, \[x2.*
+	+1001c: R_AARCH64_LD64_GOT_LO12_NC	lempy
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-312.s b/ld/testsuite/ld-aarch64/emit-relocs-312.s
new file mode 100644
index 0000000..29494ee
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-312.s
@@ -0,0 +1,13 @@
+.comm   gempy,4
+.comm	jempy,4
+.comm	lempy,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     x4,tempy
+	ldr	x7,tempy2
+	ldr	x17,tempy3
+	ldr	x3, [x2, #:got_lo12:jempy]
+	ldr	x4, [x2, #:got_lo12:gempy]
+	ldr	x5, [x2, #:got_lo12:lempy]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs1.s b/ld/testsuite/ld-aarch64/emit-relocs1.s
new file mode 100644
index 0000000..b249b6b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs1.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	b	target
+	b	target+16
diff --git a/ld/testsuite/ld-aarch64/farcall-b-none-function.d b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
new file mode 100644
index 0000000..34a6568
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
@@ -0,0 +1,5 @@
+#name: aarch64-farcall-b-none-function
+#source: farcall-b-none-function.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_JUMP26 against symbol `bar'.*
diff --git a/ld/testsuite/ld-aarch64/farcall-b-none-function.s b/ld/testsuite/ld-aarch64/farcall-b-none-function.s
new file mode 100644
index 0000000..5e5bc8d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b-none-function.s
@@ -0,0 +1,16 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b.d b/ld/testsuite/ld-aarch64/farcall-b.d
new file mode 100644
index 0000000..f3cb5ef
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b.d
@@ -0,0 +1,22 @@
+#name: aarch64-farcall-b
+#source: farcall-b.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+ +1000:	14000002 	b	1008 <__bar_veneer>
+ +1004:	d65f03c0 	ret
+0000000000001008 <__bar_veneer>:
+    1008:	90040010 	adrp	x16, 8001000 <bar>
+    100c:	91000210 	add	x16, x16, #0x0
+    1010:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+0000000008001000 <bar>:
+ 8001000:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b.s b/ld/testsuite/ld-aarch64/farcall-b.s
new file mode 100644
index 0000000..8ab3103
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b.s
@@ -0,0 +1,17 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-back.d b/ld/testsuite/ld-aarch64/farcall-back.d
new file mode 100644
index 0000000..9ff43b3
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-back.d
@@ -0,0 +1,72 @@
+#name: aarch64-farcall-back
+#source: farcall-back.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x100000000
+#notarget: aarch64_be-*-*
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+    1000:	14000412 	b	2048 <__bar1_veneer>
+    1004:	94000411 	bl	2048 <__bar1_veneer>
+    1008:	14000406 	b	2020 <__bar2_veneer>
+    100c:	94000405 	bl	2020 <__bar2_veneer>
+    1010:	14000408 	b	2030 <__bar3_veneer>
+    1014:	94000407 	bl	2030 <__bar3_veneer>
+    1018:	d65f03c0 	ret
+	...
+
+000000000000201c <_back>:
+    201c:	d65f03c0 	ret
+
+0000000000002020 <__bar2_veneer>:
+    2020:	f07ffff0 	adrp	x16, 100001000 <bar1\+0x1000>
+    2024:	91002210 	add	x16, x16, #0x8
+    2028:	d61f0200 	br	x16
+    202c:	00000000 	.inst	0x00000000 ; undefined
+
+0000000000002030 <__bar3_veneer>:
+    2030:	58000090 	ldr	x16, 2040 <__bar3_veneer\+0x10>
+    2034:	10000011 	adr	x17, 2034 <__bar3_veneer\+0x4>
+    2038:	8b110210 	add	x16, x16, x17
+    203c:	d61f0200 	br	x16
+    2040:	ffffffdc 	.word	0xffffffdc
+    2044:	00000000 	.word	0x00000000
+
+0000000000002048 <__bar1_veneer>:
+    2048:	d07ffff0 	adrp	x16, 100000000 <bar1>
+    204c:	91000210 	add	x16, x16, #0x0
+    2050:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+0000000100000000 <bar1>:
+   100000000:	d65f03c0 	ret
+   100000004:	14000805 	b	100002018 <___start_veneer>
+	...
+
+0000000100001008 <bar2>:
+   100001008:	d65f03c0 	ret
+   10000100c:	14000403 	b	100002018 <___start_veneer>
+	...
+
+0000000100002010 <bar3>:
+   100002010:	d65f03c0 	ret
+   100002014:	14000007 	b	100002030 <___back_veneer>
+
+0000000100002018 <___start_veneer>:
+   100002018:	58000090 	ldr	x16, 100002028 <___start_veneer\+0x10>
+   10000201c:	10000011 	adr	x17, 10000201c <___start_veneer\+0x4>
+   100002020:	8b110210 	add	x16, x16, x17
+   100002024:	d61f0200 	br	x16
+   100002028:	ffffefe4 	.word	0xffffefe4
+   10000202c:	fffffffe 	.word	0xfffffffe
+
+0000000100002030 <___back_veneer>:
+   100002030:	90800010 	adrp	x16, 2000 <_start\+0x1000>
+   100002034:	91007210 	add	x16, x16, #0x1c
+   100002038:	d61f0200 	br	x16
+	...
diff --git a/ld/testsuite/ld-aarch64/farcall-back.s b/ld/testsuite/ld-aarch64/farcall-back.s
new file mode 100644
index 0000000..d0a3bd5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-back.s
@@ -0,0 +1,42 @@
+	.global _start
+	.global _back
+	.global bar1
+	.global bar2
+	.global bar3
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+	.type _start, @function
+_start:
+	b	bar1
+	bl	bar1
+	b	bar2
+	bl	bar2
+	b	bar3
+	bl	bar3
+	ret
+	.space	0x1000
+	.type _back, @function
+_back:	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar1, @function
+bar1:
+	ret
+	b	_start
+
+	.space 0x1000
+	.type bar2, @function
+bar2:
+	ret
+	b	_start
+
+	.space 0x1000
+	.type bar3, @function
+bar3:
+	ret
+	b	_back
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-none-function.d b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
new file mode 100644
index 0000000..6ce9ca4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
@@ -0,0 +1,5 @@
+#name: aarch64-farcall-bl-none-function
+#source: farcall-bl-none-function.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against symbol `bar'.*
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-none-function.s b/ld/testsuite/ld-aarch64/farcall-bl-none-function.s
new file mode 100644
index 0000000..89aa85a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl-none-function.s
@@ -0,0 +1,16 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl.d b/ld/testsuite/ld-aarch64/farcall-bl.d
new file mode 100644
index 0000000..2bdd2c4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl.d
@@ -0,0 +1,23 @@
+#name: aarch64-farcall-bl
+#source: farcall-bl.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+ +1000:	94000002 	bl	1008 <__bar_veneer>
+ +1004:	d65f03c0 	ret
+
+0000000000001008 <__bar_veneer>:
+    1008:	90040010 	adrp	x16, 8001000 <bar>
+    100c:	91000210 	add	x16, x16, #0x0
+    1010:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+0000000008001000 <bar>:
+ 8001000:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl.s b/ld/testsuite/ld-aarch64/farcall-bl.s
new file mode 100644
index 0000000..432b120
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl.s
@@ -0,0 +1,17 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-section.d b/ld/testsuite/ld-aarch64/farcall-section.d
new file mode 100644
index 0000000..85775e1
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-section.d
@@ -0,0 +1,5 @@
+#name: Aarch64 farcall to symbol of type STT_SECTION
+#source: farcall-section.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001014
+#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against `.foo'
diff --git a/ld/testsuite/ld-aarch64/farcall-section.s b/ld/testsuite/ld-aarch64/farcall-section.s
new file mode 100644
index 0000000..86a070c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-section.s
@@ -0,0 +1,19 @@
+# Test to ensure that an Aarch64 call exceeding 128MB generates an error
+# if the destination is of type STT_SECTION (eg non-global symbol)
+
+	.global _start
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+
+# We will place the section .foo at 0x8001020.
+
+	.section .foo, "xa"
+
+bar:
+	ret
+
diff --git a/ld/testsuite/ld-aarch64/limit-b.d b/ld/testsuite/ld-aarch64/limit-b.d
new file mode 100644
index 0000000..95d4c8f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-b.d
@@ -0,0 +1,17 @@
+#name: aarch64-limit-b
+#source: limit-b.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8000ffc
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+    1000:	15ffffff 	b	8000ffc <bar>
+    1004:	d65f03c0 	ret
+
+Disassembly of section .foo:
+
+0000000008000ffc <bar>:
+ 8000ffc:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/limit-b.s b/ld/testsuite/ld-aarch64/limit-b.s
new file mode 100644
index 0000000..2b9f432
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-b.s
@@ -0,0 +1,19 @@
+# Test maximum encoding range of b
+
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	ret
+
+# We will place the section .foo at 0x8000ffc
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/limit-bl.d b/ld/testsuite/ld-aarch64/limit-bl.d
new file mode 100644
index 0000000..2eddeb7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-bl.d
@@ -0,0 +1,17 @@
+#name: aarch64-limit-bl
+#source: limit-bl.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8000ffc
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+    1000:	95ffffff 	bl	8000ffc <bar>
+    1004:	d65f03c0 	ret
+
+Disassembly of section .foo:
+
+0000000008000ffc <bar>:
+ 8000ffc:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/limit-bl.s b/ld/testsuite/ld-aarch64/limit-bl.s
new file mode 100644
index 0000000..72f47a5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-bl.s
@@ -0,0 +1,19 @@
+# Test maximum encoding range of bl
+
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	ret
+
+# We will place the section .foo at 0x8000ffc
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/relocs.ld b/ld/testsuite/ld-aarch64/relocs.ld
new file mode 100644
index 0000000..f42176e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/relocs.ld
@@ -0,0 +1,19 @@
+/* Script for ld testsuite */
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x8000); . = 0x10000;
+  .text           :
+  {
+    *(.before)
+    *(.text)
+    *(.after)
+  } =0
+  . = 0x20000;
+  .got            : { *(.got) *(.got.plt)}
+  . = 0x12340000;
+  .far : { *(.far) }
+  .ARM.attributes 0 : { *(.ARM.atttributes) }
+}
diff --git a/ld/testsuite/ld-aarch64/tls-desc-ie.d b/ld/testsuite/ld-aarch64/tls-desc-ie.d
new file mode 100644
index 0000000..712e39c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-desc-ie.d
@@ -0,0 +1,36 @@
+#source: tls-desc-ie.s
+#ld: -shared -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10004:	91002000 	add	x0, x0, #0x8
+ +10008:	94000016 	bl	10060 <v1\+0x10060>
+ +1000c:	d503201f 	nop
+ +10010:	90000080 	adrp	x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10014:	f9400000 	ldr	x0, \[x0\]
+ +10018:	d503201f 	nop
+ +1001c:	d503201f 	nop
+ +10020:	d53bd041 	mrs	x1, tpidr_el0
+ +10024:	8b000020 	add	x0, x1, x0
+ +10028:	d53bd042 	mrs	x2, tpidr_el0
+ +1002c:	90000080 	adrp	x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10030:	f9400000 	ldr	x0, \[x0\]
+ +10034:	8b000040 	add	x0, x2, x0
+ +10038:	b9400000 	ldr	w0, \[x0\]
+ +1003c:	0b000020 	add	w0, w1, w0
+
+Disassembly of section .plt:
+
+0000000000010040 <.plt>:
+ +10040:	a9bf7bf0 	stp	x16, x30, \[sp,#-16\]!
+ +10044:	90000090 	adrp	x16, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10048:	f9401611 	ldr	x17, \[x16,#40\]
+ +1004c:	9100a210 	add	x16, x16, #0x28
+ +10050:	d61f0220 	br	x17
+ +10054:	d503201f 	nop
+ +10058:	d503201f 	nop
+ +1005c:	d503201f 	nop
+ +10060:	90000090 	adrp	x16, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10064:	f9401a11 	ldr	x17, \[x16,#48\]
+ +10068:	9100c210 	add	x16, x16, #0x30
+ +1006c:	d61f0220 	br	x17
diff --git a/ld/testsuite/ld-aarch64/tls-desc-ie.s b/ld/testsuite/ld-aarch64/tls-desc-ie.s
new file mode 100644
index 0000000..93fd71c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-desc-ie.s
@@ -0,0 +1,32 @@
+	.global	v1
+	.global	v2
+	.section	.tdata,"awT",%progbits
+v1:
+	.word	1
+
+	.text
+
+# This GD access does not relax. It consumes a double GOT slot.
+
+	adrp	x0, :tlsgd:v2
+	add	x0, x0, :tlsgd_lo12:v2
+	bl	__tls_get_addr
+	nop
+
+# Test the combination of a TLSDESC-GD and IE access to the same
+# symbol. We expect the TLSDESC-GD to relax to IE.
+
+	adrp	x0, :tlsdesc:v1
+	ldr	x1, [x0, #:tlsdesc_lo12:v1]
+	add	x0, x0, :tlsdesc_lo12:v1
+	.tlsdesccall	v1
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+
+	mrs	x2, tpidr_el0
+	adrp	x0, :gottprel:v1
+	ldr	x0, [x0, #:gottprel_lo12:v1]
+	add	x0, x2, x0
+	ldr	w0, [x0]
+	add	w0, w1, w0
diff --git a/ld/testsuite/ld-aarch64/tls-relax-all.d b/ld/testsuite/ld-aarch64/tls-relax-all.d
new file mode 100644
index 0000000..d3db04d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-all.d
@@ -0,0 +1,39 @@
+#source: tls-relax-all.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	a9bf7bfd 	stp	x29, x30, \[sp,#-16\]!
+ +10004:	910003fd 	mov	x29, sp
+ +10008:	90000080 	adrp	x0, 20000 <ie_var\+0x1fff0>
+ +1000c:	f9400000 	ldr	x0, \[x0\]
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d53bd041 	mrs	x1, tpidr_el0
+ +1001c:	8b000020 	add	x0, x1, x0
+ +10020:	b9400001 	ldr	w1, \[x0\]
+ +10024:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10028:	f2800280 	movk	x0, #0x14
+ +1002c:	d503201f 	nop
+ +10030:	d503201f 	nop
+ +10034:	d53bd042 	mrs	x2, tpidr_el0
+ +10038:	8b000040 	add	x0, x2, x0
+ +1003c:	b9400000 	ldr	w0, \[x0\]
+ +10040:	0b000021 	add	w1, w1, w0
+ +10044:	90000080 	adrp	x0, 20000 <ie_var\+0x1fff0>
+ +10048:	f9400400 	ldr	x0, \[x0,#8\]
+ +1004c:	d53bd041 	mrs	x1, tpidr_el0
+ +10050:	8b000020 	add	x0, x1, x0
+ +10054:	b9400000 	ldr	w0, \[x0\]
+ +10058:	0b000021 	add	w1, w1, w0
+ +1005c:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10060:	f2800380 	movk	x0, #0x1c
+ +10064:	d53bd041 	mrs	x1, tpidr_el0
+ +10068:	8b000020 	add	x0, x1, x0
+ +1006c:	b9400000 	ldr	w0, \[x0\]
+ +10070:	0b000021 	add	w1, w1, w0
+ +10074:	d53bd042 	mrs	x2, tpidr_el0
+ +10078:	d2a00000 	movz	x0, #0x0, lsl #16
+ +1007c:	f2800400 	movk	x0, #0x20
+ +10080:	8b000040 	add	x0, x2, x0
+ +10084:	b9400000 	ldr	w0, \[x0\]
+ +10088:	0b000020 	add	w0, w1, w0
diff --git a/ld/testsuite/ld-aarch64/tls-relax-all.s b/ld/testsuite/ld-aarch64/tls-relax-all.s
new file mode 100644
index 0000000..1bef53d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-all.s
@@ -0,0 +1,51 @@
+	.global	gdesc_var_1
+	.global	gd_var_1
+	.section	.tdata,"awT",%progbits
+gdesc_var_1:
+	.word	1
+gdesc_var_2:
+	.word	2
+gd_var_1:
+	.word	3
+gd_var_2:
+	.word	4
+ie_var:
+	.word	5
+	.text
+	stp	x29, x30, [sp, -16]!
+	add	x29, sp, 0
+	adrp	x0, :tlsdesc:gdesc_var_1
+	ldr	x1, [x0, #:tlsdesc_lo12:gdesc_var_1]
+	add	x0, x0, :tlsdesc_lo12:gdesc_var_1
+	.tlsdesccall	gdesc_var_1
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w1, [x0]
+	adrp	x0, :tlsdesc:gdesc_var_2
+	ldr	x2, [x0, #:tlsdesc_lo12:gdesc_var_2]
+	add	x0, x0, :tlsdesc_lo12:gdesc_var_2
+	.tlsdesccall	gdesc_var_2
+	blr	x2
+	mrs	x2, tpidr_el0
+	add	x0, x2, x0
+	ldr	w0, [x0]
+	add	w1, w1, w0
+	adrp	x0, :tlsgd:gd_var_1
+	add	x0, x0, :tlsgd_lo12:gd_var_1
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
+	add	w1, w1, w0
+	adrp	x0, :tlsgd:gd_var_2
+	add	x0, x0, :tlsgd_lo12:gd_var_2
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
+	add	w1, w1, w0
+	mrs	x2, tpidr_el0
+	adrp	x0, :gottprel:ie_var
+	ldr	x0, [x0, #:gottprel_lo12:ie_var]
+	add	x0, x2, x0
+	ldr	w0, [x0]
+	add	w0, w1, w0
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-ie.d b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.d
new file mode 100644
index 0000000..a142f54
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.d
@@ -0,0 +1,9 @@
+#source: tls-relax-gd-ie.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <var\+0x20000>
+ +10004:	f9400000 	ldr	x0, \[x0\]
+ +10008:	d53bd041 	mrs	x1, tpidr_el0
+ +1000c:	8b000020 	add	x0, x1, x0
+ +10010:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-ie.s b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.s
new file mode 100644
index 0000000..88c7eec
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.s
@@ -0,0 +1,10 @@
+	.global	var
+	.section	.tdata,"awT",%progbits
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsgd:var
+	add	x0, x0, :tlsgd_lo12:var
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-le.d b/ld/testsuite/ld-aarch64/tls-relax-gd-le.d
new file mode 100644
index 0000000..b5ee39c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-le.d
@@ -0,0 +1,9 @@
+#source: tls-relax-gd-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10004:	f2800200 	movk	x0, #0x10
+ +10008:	d53bd041 	mrs	x1, tpidr_el0
+ +1000c:	8b000020 	add	x0, x1, x0
+ +10010:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-le.s b/ld/testsuite/ld-aarch64/tls-relax-gd-le.s
new file mode 100644
index 0000000..eb6fc2f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-le.s
@@ -0,0 +1,9 @@
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsgd:var
+	add	x0, x0, :tlsgd_lo12:var
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d
new file mode 100644
index 0000000..f3307ae
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d
@@ -0,0 +1,18 @@
+#source: tls-relax-gdesc-ie-2.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <var\+0x20000>
+ +10004:	d503201f 	nop
+ +10008:	f9400000 	ldr	x0, \[x0\]
+ +1000c:	d503201f 	nop
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d503201f 	nop
+ +1001c:	d503201f 	nop
+ +10020:	d503201f 	nop
+ +10024:	d503201f 	nop
+ +10028:	d503201f 	nop
+ +1002c:	d53bd041 	mrs	x1, tpidr_el0
+ +10030:	8b000020 	add	x0, x1, x0
+ +10034:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s
new file mode 100644
index 0000000..790b6c6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s
@@ -0,0 +1,24 @@
+// Test TLS Desc to TLS IE relaxation when instructions are not consecutive.
+
+	.global	var
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	nop
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	nop
+	nop
+	nop
+	add	x0, x0, :tlsdesc_lo12:var
+	nop
+	nop
+	.tlsdesccall	var
+	blr	x1
+	nop
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
+	.global	var
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d
new file mode 100644
index 0000000..691df06
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d
@@ -0,0 +1,11 @@
+#source: tls-relax-gdesc-ie.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <var\+0x20000>
+ +10004:	f9400000 	ldr	x0, \[x0\]
+ +10008:	d503201f 	nop
+ +1000c:	d503201f 	nop
+ +10010:	d53bd041 	mrs	x1, tpidr_el0
+ +10014:	8b000020 	add	x0, x1, x0
+ +10018:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
new file mode 100644
index 0000000..c20690c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
@@ -0,0 +1,13 @@
+	.global	var
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	add	x0, x0, :tlsdesc_lo12:var
+	.tlsdesccall	var
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.d
new file mode 100644
index 0000000..3c028e2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.d
@@ -0,0 +1,18 @@
+#source: tls-relax-gdesc-le-2.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10004:	d503201f 	nop
+ +10008:	d503201f 	nop
+ +1000c:	f2800200 	movk	x0, #0x10
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d503201f 	nop
+ +1001c:	d503201f 	nop
+ +10020:	d503201f 	nop
+ +10024:	d503201f 	nop
+ +10028:	d503201f 	nop
+ +1002c:	d53bd041 	mrs	x1, tpidr_el0
+ +10030:	8b000020 	add	x0, x1, x0
+ +10034:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.s
new file mode 100644
index 0000000..fb8bf66
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.s
@@ -0,0 +1,22 @@
+# Test TLS Desc to TLS LE relaxation when instructions are not consecutive.
+
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	nop
+	nop
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	nop
+	add	x0, x0, :tlsdesc_lo12:var
+	nop
+	nop
+	nop
+	.tlsdesccall	var
+	blr	x1
+	nop
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.d
new file mode 100644
index 0000000..afe0a56
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.d
@@ -0,0 +1,11 @@
+#source: tls-relax-gdesc-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10004:	f2800200 	movk	x0, #0x10
+ +10008:	d503201f 	nop
+ +1000c:	d503201f 	nop
+ +10010:	d53bd041 	mrs	x1, tpidr_el0
+ +10014:	8b000020 	add	x0, x1, x0
+ +10018:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.s
new file mode 100644
index 0000000..28ee0f6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.s
@@ -0,0 +1,12 @@
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	add	x0, x0, :tlsdesc_lo12:var
+	.tlsdesccall	var
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.d
new file mode 100644
index 0000000..2f93955
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.d
@@ -0,0 +1,17 @@
+#source: tls-relax-ie-le-2.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d53bd041 	mrs	x1, tpidr_el0
+ +10004:	d503201f 	nop
+ +10008:	d503201f 	nop
+ +1000c:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d503201f 	nop
+ +1001c:	f2800200 	movk	x0, #0x10
+ +10020:	d503201f 	nop
+ +10024:	8b000020 	add	x0, x1, x0
+ +10028:	d503201f 	nop
+ +1002c:	d503201f 	nop
+ +10030:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.s
new file mode 100644
index 0000000..98b62e2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.s
@@ -0,0 +1,20 @@
+# Test TLS IE to TLS LE relaxation when instructions are not consecutive.
+
+	.section	.tdata
+var:
+	.word	2
+	.text
+	mrs	x1, tpidr_el0
+	nop
+	nop
+	adrp	x0, :gottprel:var
+	nop
+	nop
+	nop
+	ldr	x0, [x0, #:gottprel_lo12:var]
+	nop
+	add	x0, x1, x0
+	nop
+	nop
+	ldr	w0, [x0]
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.d
new file mode 100644
index 0000000..a2fd823
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.d
@@ -0,0 +1,9 @@
+#source: tls-relax-ie-le-3.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d53bd042 	mrs	x2, tpidr_el0
+ +10004:	d2a0000f 	movz	x15, #0x0, lsl #16
+ +10008:	f280020f 	movk	x15, #0x10
+ +1000c:	8b0f004f 	add	x15, x2, x15
+ +10010:	b94001e0 	ldr	w0, \[x15\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.s
new file mode 100644
index 0000000..70e7062
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.s
@@ -0,0 +1,12 @@
+# Test TLS IE to TLS LE relaxation when using arbitrary registers.
+
+	.section	.tdata
+var:
+	.word	2
+	.text
+	mrs	x2, tpidr_el0
+	adrp	x15, :gottprel:var
+	ldr	x15, [x15, #:gottprel_lo12:var]
+	add	x15, x2, x15
+	ldr	w0, [x15]
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le.d
new file mode 100644
index 0000000..ff3b344
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le.d
@@ -0,0 +1,9 @@
+#source: tls-relax-ie-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d53bd041 	mrs	x1, tpidr_el0
+ +10004:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10008:	f2800200 	movk	x0, #0x10
+ +1000c:	8b000020 	add	x0, x1, x0
+ +10010:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le.s
new file mode 100644
index 0000000..093cda2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le.s
@@ -0,0 +1,9 @@
+	.section	.tdata
+var:
+	.word	2
+	.text
+	mrs	x1, tpidr_el0
+	adrp	x0, :gottprel:var
+	ldr	x0, [x0, #:gottprel_lo12:var]
+	add	x0, x1, x0
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/weak-undefined.d b/ld/testsuite/ld-aarch64/weak-undefined.d
new file mode 100644
index 0000000..22a9860
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/weak-undefined.d
@@ -0,0 +1,18 @@
+#source: weak-undefined.s
+#ld: -Ttext 0xF0000000 -T relocs.ld -e0 --emit-relocs
+#objdump: -d
+#...
+ +f0000000:	54000001 	b\.ne	f0000000 <main>
+ +f0000004:	54000000 	b\.eq	f0000004 <main\+0x4>
+ +f0000008:	54000002 	b\.cs	f0000008 <main\+0x8>
+ +f000000c:	54000003 	b\.cc	f000000c <main\+0xc>
+ +f0000010:	5400000c 	b\.gt	f0000010 <main\+0x10>
+ +f0000014:	5400000a 	b\.ge	f0000014 <main\+0x14>
+ +f0000018:	5400000b 	b\.lt	f0000018 <main\+0x18>
+ +f000001c:	5400000d 	b\.le	f000001c <main\+0x1c>
+ +f0000020:	d503201f 	nop
+ +f0000024:	d503201f 	nop
+ +f0000028:	58000000 	ldr	x0, f0000028 <main\+0x28>
+ +f000002c:	10000000 	adr	x0, f000002c <main\+0x2c>
+ +f0000030:	90000000 	adrp	x0, f0000000 <main>
+ +f0000034:	91000000 	add	x0, x0, #0x0
diff --git a/ld/testsuite/ld-aarch64/weak-undefined.s b/ld/testsuite/ld-aarch64/weak-undefined.s
new file mode 100644
index 0000000..692798f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/weak-undefined.s
@@ -0,0 +1,18 @@
+.text
+	.weak foo
+	.global main
+main:
+	b.ne	foo
+	b.eq	foo
+	b.cs	foo
+	b.cc	foo
+	b.gt	foo
+	b.ge	foo
+	b.lt	foo
+	b.le	foo
+	b	foo
+	bl	foo
+	ldr	x0, foo
+	adr	x0, foo
+	adrp	x0, foo
+	add	x0, x0, :lo12:foo
diff --git a/ld/testsuite/ld-elf/binutils.exp b/ld/testsuite/ld-elf/binutils.exp
index 4d91105..249fa2a 100644
--- a/ld/testsuite/ld-elf/binutils.exp
+++ b/ld/testsuite/ld-elf/binutils.exp
@@ -34,7 +34,12 @@ if { [istarget *-*-linux*aout*]
     return
 }
 
-proc binutils_test { prog_name ld_options test } {
+# The optional test_name argument provides a mechanism for the caller
+# to hardwire the test name. This is important if ld_options contains
+# absolute path names because the default test name is constructed
+# from the prog_name and ld_options and we do not want absolute paths
+# to appear in the test_name.
+proc binutils_test { prog_name ld_options test {test_name ""}} {
     global as
     global ld
     global READELF
@@ -45,7 +50,10 @@ proc binutils_test { prog_name ld_options test } {
     global link_output
 
     eval set prog \$$prog_name
-    set test_name "$prog_name $ld_options ($test)"
+
+    if { "$test_name" == "" } {
+      set test_name "$prog_name $ld_options ($test)"
+    }
 
     if { ![ld_assemble $as $srcdir/$subdir/$test.s tmpdir/$test.o ] } {
 	unresolved "$test_name"
@@ -123,7 +131,7 @@ if { ([istarget "i?86-*-elf*"]
     binutils_test objcopy "-z relro -shared" relro2
 }
 
-binutils_test strip "-T ${srcdir}/${subdir}/lma.lnk" lma
+binutils_test strip "-T ${srcdir}/${subdir}/lma.lnk" lma "strip -T lma.lnk"
 
 set tls_tests { "tdata1" "tdata2" }
 # hppa64 has its own .tbss section, with different flags.
diff --git a/ld/testsuite/ld-elf/group8a.d b/ld/testsuite/ld-elf/group8a.d
index bad4123..753eb0f 100644
--- a/ld/testsuite/ld-elf/group8a.d
+++ b/ld/testsuite/ld-elf/group8a.d
@@ -1,7 +1,7 @@
 #source: group8.s
 #ld: -r --gc-sections --entry foo
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/group8b.d b/ld/testsuite/ld-elf/group8b.d
index fb37198..107ff69 100644
--- a/ld/testsuite/ld-elf/group8b.d
+++ b/ld/testsuite/ld-elf/group8b.d
@@ -1,7 +1,7 @@
 #source: group8.s
 #ld: -r --gc-sections --entry bar
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/group9a.d b/ld/testsuite/ld-elf/group9a.d
index fd04c48..511cec7 100644
--- a/ld/testsuite/ld-elf/group9a.d
+++ b/ld/testsuite/ld-elf/group9a.d
@@ -1,7 +1,7 @@
 #source: group9.s
 #ld: -r --gc-sections --entry foo
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: alpha-*-* hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/group9b.d b/ld/testsuite/ld-elf/group9b.d
index 3f19fd6..fd5b0c2 100644
--- a/ld/testsuite/ld-elf/group9b.d
+++ b/ld/testsuite/ld-elf/group9b.d
@@ -1,7 +1,7 @@
 #source: group9.s
 #ld: -r --gc-sections --entry bar
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: alpha-*-* hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/pr12851.d b/ld/testsuite/ld-elf/pr12851.d
index fb61c5a..9160142 100644
--- a/ld/testsuite/ld-elf/pr12851.d
+++ b/ld/testsuite/ld-elf/pr12851.d
@@ -2,7 +2,7 @@
 #source: start.s
 #ld: --gc-sections
 #readelf: -s --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elf/pr12975.d b/ld/testsuite/ld-elf/pr12975.d
index b361cc2..abdb571 100644
--- a/ld/testsuite/ld-elf/pr12975.d
+++ b/ld/testsuite/ld-elf/pr12975.d
@@ -1,7 +1,7 @@
 #ld: --gc-sections -shared -version-script pr12975.t
 #readelf: -s --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elf/pr13177.d b/ld/testsuite/ld-elf/pr13177.d
index e56e865..f32e15d 100644
--- a/ld/testsuite/ld-elf/pr13177.d
+++ b/ld/testsuite/ld-elf/pr13177.d
@@ -2,7 +2,7 @@
 #ld: --gc-sections -shared
 #readelf: -s -D --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elf/pr13195.d b/ld/testsuite/ld-elf/pr13195.d
index 796102b..88c6278 100644
--- a/ld/testsuite/ld-elf/pr13195.d
+++ b/ld/testsuite/ld-elf/pr13195.d
@@ -1,7 +1,7 @@
 #ld: --gc-sections -shared -version-script pr13195.t
 #readelf: -s --wide -D
 #target: *-*-linux* *-*-gnu*
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elfvers/vers.exp b/ld/testsuite/ld-elfvers/vers.exp
index 4bea6e4..1e9ff53 100644
--- a/ld/testsuite/ld-elfvers/vers.exp
+++ b/ld/testsuite/ld-elfvers/vers.exp
@@ -47,6 +47,7 @@ if { ![istarget hppa*64*-*-hpux*]
      && ![istarget sparc*-*-elf]
      && ![istarget sparc*-*-solaris2*]
      && ![istarget sparc*-*-linux*]
+     && ![istarget aarch64*-*-linux*]
      && ![istarget arm*-*-linux*]
      && ![istarget mips*-*-linux*]
      && ![istarget alpha*-*-linux*]
diff --git a/ld/testsuite/ld-shared/shared.exp b/ld/testsuite/ld-shared/shared.exp
index 7ec304b..07fc881 100644
--- a/ld/testsuite/ld-shared/shared.exp
+++ b/ld/testsuite/ld-shared/shared.exp
@@ -57,6 +57,7 @@ if { ![istarget hppa*64*-*-hpux*] \
      && ![istarget rs6000*-*-aix*] \
      && ![istarget powerpc*-*-aix*] \
      && ![istarget s390*-*-linux*] \
+     && ![istarget aarch64*-*-linux*] \
      && ![istarget x86_64-*-linux*] } {
     return
 }
diff --git a/ld/testsuite/ld-srec/srec.exp b/ld/testsuite/ld-srec/srec.exp
index 7f13e9c..001fb2e 100644
--- a/ld/testsuite/ld-srec/srec.exp
+++ b/ld/testsuite/ld-srec/srec.exp
@@ -250,9 +250,12 @@ proc run_srec_test { test objs } {
 	setup_xfail "sh64*-*-*"
     }
 
-    if {[istarget arm*-*-*]} {
-        # ARM targets cannot convert format in the linker 
+    if {[istarget aarch64*-*-*]   || \
+        [istarget arm*-*-*]} {
+        # ARM targets cannot convert format in the linker
         # using the --oformat command line switch
+	setup_xfail "aarch64-*-*"
+	setup_xfail "aarch64_be-*-*"
 	setup_xfail "arm*-*-*"
     }
 
diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp
index a481ce7..f05d42c 100644
--- a/ld/testsuite/lib/ld-lib.exp
+++ b/ld/testsuite/lib/ld-lib.exp
@@ -1459,7 +1459,8 @@ proc check_gc_sections_available { } {
     if {![info exists gc_sections_available_saved]} {
 	# Some targets don't support gc-sections despite whatever's
 	# advertised by ld's options.
-	if {[istarget arc-*-*]
+	if {[istarget aarch64*-*-*]
+	     || [istarget arc-*-*]
 	     || [istarget d30v-*-*]
 	     || [istarget dlx-*-*]
 	     || [istarget i960-*-*]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes
  2012-07-30 14:28 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes Yufeng Zhang
  2012-07-30 14:49   ` Joseph S. Myers
@ 2012-08-07 17:39   ` Yufeng Zhang
  1 sibling, 0 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-07 17:39 UTC (permalink / raw)
  To: binutils

On 07/30/12 15:28, Yufeng Zhang wrote:
> This patch adds the top level configury changes for the AArch64 target
> support.

This patch has been withdrawn following JosephM's suggestion in 
http://sourceware.org/ml/binutils/2012-07/msg00273.html.

The AArch64 port no longer requires any toplevel configury change; the 
newlib/libgloss-related changes will be submitted to the newlib list later.


Thanks,
Yufeng

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes
  2012-08-04  8:06       ` DJ Delorie
@ 2012-08-07 17:53         ` Yufeng Zhang
  0 siblings, 0 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-07 17:53 UTC (permalink / raw)
  To: DJ Delorie; +Cc: binutils

On 08/04/12 01:29, DJ Delorie wrote:
>
>> Um, I don't see any error in my local environment with -Werror on. What
>> kind of error message are you getting?
>
> ../../binutils-src/opcodes/aarch64-dis.c:2146: error: format '%08lx' expects type 'long unsigned int', but argument 3 has type 'uint32_t'

Many thanks.  The issue has now been fixed in the updated patch.  See 
http://sourceware.org/ml/binutils/2012-08/msg00140.html.


Thanks,
Yufeng

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes v2
  2012-08-07 17:19   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes v2 Yufeng Zhang
@ 2012-08-08 12:18     ` Benedikt Schroefel
  2012-08-08 12:20       ` Richard Earnshaw
  2012-08-13 14:57     ` nick clifton
  1 sibling, 1 reply; 41+ messages in thread
From: Benedikt Schroefel @ 2012-08-08 12:18 UTC (permalink / raw)
  To: binutils

Yufeng Zhang <Yufeng.Zhang <at> arm.com> writes:

> 
> Hi,
> 
> Please find the updated patch that adds the bfd changes of the AArch64 
> target support.
> 
> The patch fixes
> 
> * the empty initializer issue as mentioned in
> http://sourceware.org/ml/binutils/2012-07/msg00277.html
> 
> * the missing parameter issue as mentioned in
> http://sourceware.org/ml/binutils/2012-07/msg00322.html
> 
> Thanks,
> Yufeng
> 

Hello Yufeng,

it seems that the patch 3/6 fails with the latest binutils
(http://ftp.gnu.org/gnu/binutils/binutils-2.22.tar.gz):

user@linux:~/armv8/binutils$ patch -p 1 --dry-run < patch/aarch64_3_6_v2.patch

creates the following error messages:

Hunk #1 FAILED at 461.
Hunk #2 succeeded at 484 (offset -21 lines).
Hunk #3 succeeded at 565 (offset -26 lines).
1 out of 3 hunks FAILED -- saving rejects to file bfd/archures.c.rej

Hunk #1 succeeded at 813 (offset -19 lines).
Hunk #2 FAILED at 841.
1 out of 2 hunks FAILED -- saving rejects to file bfd/configure.in.rej

Hunk #1 succeeded at 5619 (offset -265 lines).
Hunk #2 succeeded at 6022 with fuzz 1 (offset -293 lines).
Hunk #3 FAILED at 6507.
1 out of 3 hunks FAILED -- saving rejects to file bfd/reloc.c.rej

Which binutils version have you used to create the patch? Maybe 2.22 isn't the
right one for this patch.

Thank you very much
regards

Benedikt



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes v2
  2012-08-08 12:18     ` Benedikt Schroefel
@ 2012-08-08 12:20       ` Richard Earnshaw
  0 siblings, 0 replies; 41+ messages in thread
From: Richard Earnshaw @ 2012-08-08 12:20 UTC (permalink / raw)
  To: Benedikt Schroefel; +Cc: binutils

On 08/08/12 10:56, Benedikt Schroefel wrote:
> Yufeng Zhang <Yufeng.Zhang <at> arm.com> writes:
> 
>>
>> Hi,
>>
>> Please find the updated patch that adds the bfd changes of the AArch64 
>> target support.
>>
>> The patch fixes
>>
>> * the empty initializer issue as mentioned in
>> http://sourceware.org/ml/binutils/2012-07/msg00277.html
>>
>> * the missing parameter issue as mentioned in
>> http://sourceware.org/ml/binutils/2012-07/msg00322.html
>>
>> Thanks,
>> Yufeng
>>
> 
> Hello Yufeng,
> 
> it seems that the patch 3/6 fails with the latest binutils
> (http://ftp.gnu.org/gnu/binutils/binutils-2.22.tar.gz):
> 

This patch is against the development version of binutils (CVS trunk).
You can't expect it to work against a 10-month old version without rework.


R.

> user@linux:~/armv8/binutils$ patch -p 1 --dry-run < patch/aarch64_3_6_v2.patch
> 
> creates the following error messages:
> 
> Hunk #1 FAILED at 461.
> Hunk #2 succeeded at 484 (offset -21 lines).
> Hunk #3 succeeded at 565 (offset -26 lines).
> 1 out of 3 hunks FAILED -- saving rejects to file bfd/archures.c.rej
> 
> Hunk #1 succeeded at 813 (offset -19 lines).
> Hunk #2 FAILED at 841.
> 1 out of 2 hunks FAILED -- saving rejects to file bfd/configure.in.rej
> 
> Hunk #1 succeeded at 5619 (offset -265 lines).
> Hunk #2 succeeded at 6022 with fuzz 1 (offset -293 lines).
> Hunk #3 FAILED at 6507.
> 1 out of 3 hunks FAILED -- saving rejects to file bfd/reloc.c.rej
> 
> Which binutils version have you used to create the patch? Maybe 2.22 isn't the
> right one for this patch.
> 
> Thank you very much
> regards
> 
> Benedikt
> 
> 
> 
> 
> 
> 




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6]
  2012-07-30 14:30 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Jan Beulich
@ 2012-08-09 14:50   ` Richard Earnshaw
  0 siblings, 0 replies; 41+ messages in thread
From: Richard Earnshaw @ 2012-08-09 14:50 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Yufeng Zhang, binutils

On 30/07/12 15:31, Jan Beulich wrote:
>>>> On 30.07.12 at 16:21, Richard Earnshaw <rearnsha@arm.com> wrote:
>> ARM is pleased to announce a port of binutils, gas and ld to its
>> AArch64 architecture.
>>
>> Please note that while these tools have been used to build a large
>> body of software, they cannot yet be considered complete.  We believe
>> that the code is now in a state where it is worth starting the process
>> of a public review.
> 
> Since it was just yesterday that I looked at arm.com, and there
> still was no public documentation available - where would that be
> found (as it would be needed in order to do a meaningful review)?
> 
> Thanks, Jan
> 
> 
> 
> 

The documentation is gradually being published, but it will take some
time before the full v8 specification is made public.

The assembly language, as supported by GAS, is documented in:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.genc010197a/index.html

You may need to register to gain access to the document.

The encoding information isn't covered in that document; you'll just
have to trust us that we've got that bit right :-)

R.



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2
  2012-08-07 17:34     ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2 Yufeng Zhang
@ 2012-08-09 17:37       ` nick clifton
  2012-08-09 21:32         ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v3 Yufeng Zhang
  2012-08-13 14:58       ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2 nick clifton
  1 sibling, 1 reply; 41+ messages in thread
From: nick clifton @ 2012-08-09 17:37 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: Joseph S. Myers, binutils

Hi Yufeng,

   There is one minor problem with the ld patch:

--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -127,6 +127,10 @@ BFDLIB = ../bfd/libbfd.la
  LIBIBERTY = ../libiberty/libiberty.a

  ALL_EMULATION_SOURCES = \
+	eaarch64elf.c \
+	eaarch64elfb.c \
+	eaarch64linux.c \
+	eaarch64linuxb.c \
  	eaix5ppc.c \
  	eaix5rs6.c \
  	eaixppc.c \


64-bit source files should be added to the ALL_64_EMULATION_SOURCES list 
not the ALL_EMULATION_SOURCES list.  If you build a toolchain configured 
with --enable-targets=all, but *not* configured with --enable-64-bit-bfd 
you will see why this is important.

Otherwise the patches (all of them) look good to me.  If there are no 
other problems raised over the next few days I plan on approving them on 
Monday.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v3
  2012-08-09 17:37       ` nick clifton
@ 2012-08-09 21:32         ` Yufeng Zhang
  0 siblings, 0 replies; 41+ messages in thread
From: Yufeng Zhang @ 2012-08-09 21:32 UTC (permalink / raw)
  To: nick clifton; +Cc: Joseph S. Myers, binutils

[-- Attachment #1: Type: text/plain, Size: 994 bytes --]

On 08/09/12 15:48, nick clifton wrote:
> Hi Yufeng,
>
>     There is one minor problem with the ld patch:
>
> --- a/ld/Makefile.am
> +++ b/ld/Makefile.am
> @@ -127,6 +127,10 @@ BFDLIB = ../bfd/libbfd.la
>    LIBIBERTY = ../libiberty/libiberty.a
>
>    ALL_EMULATION_SOURCES = \
> +	eaarch64elf.c \
> +	eaarch64elfb.c \
> +	eaarch64linux.c \
> +	eaarch64linuxb.c \
>    	eaix5ppc.c \
>    	eaix5rs6.c \
>    	eaixppc.c \
>
>
> 64-bit source files should be added to the ALL_64_EMULATION_SOURCES list
> not the ALL_EMULATION_SOURCES list.  If you build a toolchain configured
> with --enable-targets=all, but *not* configured with --enable-64-bit-bfd
> you will see why this is important.

Thanks for pointing this out.  Please find the updated patch in the 
attachment.

> Otherwise the patches (all of them) look good to me.  If there are no
> other problems raised over the next few days I plan on approving them on
> Monday.

Thanks!


Kind regards,
Yufeng

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: aarch64-ld.v3.patch --]
[-- Type: text/x-patch; name=aarch64-ld.v3.patch, Size: 102554 bytes --]

diff --git a/ld/Makefile.am b/ld/Makefile.am
index f35ba4b..4c692ea 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -465,6 +465,10 @@ ALL_EMULATION_SOURCES = \
 ALL_EMULATIONS = $(ALL_EMULATION_SOURCES:.c=.@OBJEXT@)
 
 ALL_64_EMULATION_SOURCES = \
+	eaarch64elf.c \
+	eaarch64elfb.c \
+	eaarch64linux.c \
+	eaarch64linuxb.c \
 	eelf32_x86_64.c \
 	eelf32_x86_64_nacl.c \
 	eelf64_aix.c \
@@ -1719,6 +1723,22 @@ ens32knbsd.c:	$(srcdir)/emulparams/ns32knbsd.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/netbsd.em \
   $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} ns32knbsd "$(tdir_ns32knbsd)"
+eaarch64elf.c: $(srcdir)/emulparams/aarch64elf.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64elf "$(tdir_aarch64elf)"
+eaarch64elfb.c: $(srcdir)/emulparams/aarch64elfb.sh $(srcdir)/emulparams/aarch64elf.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64elfb "$(tdir_aarch64elfb)"
+eaarch64linux.c: $(srcdir)/emulparams/aarch64linux.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64linux "$(tdir_aarch64linux)"
+eaarch64linuxb.c: $(srcdir)/emulparams/aarch64linuxb.sh $(srcdir)/emulparams/aarch64linux.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/aarch64elf.em \
+  $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} aarch64linuxb "$(tdir_aarch64linuxb)"
 eor32.c: $(srcdir)/emulparams/or32.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/or32.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} or32 "$(tdir_or32)"
diff --git a/ld/configure.tgt b/ld/configure.tgt
index e58f4b8..72bc5bc 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -27,6 +27,14 @@ targ64_extra_libpath=
 # architecture variants should be kept together even if their names
 # break the alpha sorting.
 case "${targ}" in
+aarch64_be-*-elf)	targ_emul=aarch64elfb
+			targ_extra_emuls="aarch64elf armelfb armelf" ;;
+aarch64-*-elf)		targ_emul=aarch64elf
+			targ_extra_emuls="aarch64elfb armelf armelfb" ;;
+aarch64_be-*-linux*)	targ_emul=aarch64linuxb
+			targ_extra_emuls="aarch64linux aarch64elfb aarch64elf armelfb_linux_eabi armelf_linux_eabi armelfb armelf" ;;
+aarch64-*-linux*)	targ_emul=aarch64linux
+			targ_extra_emuls="aarch64linuxb aarch64elf aarch64elfb armelf_linux_eabi armelfb_linux_eabi armelf armelfb" ;;
 alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
 		        targ_emul=elf64alpha_fbsd
 			targ_extra_emuls="elf64alpha alpha"
diff --git a/ld/emulparams/aarch64elf.sh b/ld/emulparams/aarch64elf.sh
new file mode 100644
index 0000000..d72e5f7
--- /dev/null
+++ b/ld/emulparams/aarch64elf.sh
@@ -0,0 +1,35 @@
+ARCH=aarch64
+MACHINE=
+NOP=0
+
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf64-littleaarch64"
+BIG_OUTPUT_FORMAT="elf64-bigaarch64"
+LITTLE_OUTPUT_FORMAT="elf64-littleaarch64"
+NO_REL_RELOCS=yes
+
+TEMPLATE_NAME=elf32
+EXTRA_EM_FILE=aarch64elf
+
+GENERATE_SHLIB_SCRIPT=yes
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+
+ENTRY=_start
+EMBEDDED=yes
+SEPARATE_GOTPLT=24
+TEXT_START_ADDR=0x00400000
+
+DATA_START_SYMBOLS='__data_start = . ;';
+
+# AArch64 does not support .s* sections.
+NO_SMALL_DATA=yes
+
+OTHER_BSS_SYMBOLS='__bss_start__ = .;'
+OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
+OTHER_END_SYMBOLS='__end__ = . ;'
+
+OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
+ATTRS_SECTIONS='.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }'
+
+# This sets the stack to the top of the simulator memory (2^19 bytes).
+STACK_ADDR=0x80000
diff --git a/ld/emulparams/aarch64elfb.sh b/ld/emulparams/aarch64elfb.sh
new file mode 100644
index 0000000..7a3ff97
--- /dev/null
+++ b/ld/emulparams/aarch64elfb.sh
@@ -0,0 +1,2 @@
+. ${srcdir}/emulparams/aarch64elf.sh
+OUTPUT_FORMAT="elf64-bigaarch64"
diff --git a/ld/emulparams/aarch64linux.sh b/ld/emulparams/aarch64linux.sh
new file mode 100644
index 0000000..a5a2500
--- /dev/null
+++ b/ld/emulparams/aarch64linux.sh
@@ -0,0 +1,36 @@
+ARCH=aarch64
+MACHINE=
+NOP=0
+
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf64-littleaarch64"
+BIG_OUTPUT_FORMAT="elf64-bigaarch64"
+LITTLE_OUTPUT_FORMAT="elf64-littleaarch64"
+NO_REL_RELOCS=yes
+
+TEMPLATE_NAME=elf32
+EXTRA_EM_FILE=aarch64elf
+
+GENERATE_SHLIB_SCRIPT=yes
+GENERATE_PIE_SCRIPT=yes
+
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
+SEPARATE_GOTPLT=24
+IREL_IN_PLT=
+
+TEXT_START_ADDR=0x400000
+
+DATA_START_SYMBOLS='PROVIDE (__data_start = .);';
+
+# AArch64 does not support .s* sections.
+NO_SMALL_DATA=yes
+
+OTHER_BSS_SYMBOLS='__bss_start__ = .;'
+OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;'
+OTHER_END_SYMBOLS='__end__ = . ;'
+
+OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
+ATTRS_SECTIONS='.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }'
+# Ensure each PLT entry is aligned to a cache line.
+PLT=".plt          ${RELOCATING-0} : ALIGN(16) { *(.plt)${IREL_IN_PLT+ *(.iplt)} }"
diff --git a/ld/emulparams/aarch64linuxb.sh b/ld/emulparams/aarch64linuxb.sh
new file mode 100644
index 0000000..2bdf602
--- /dev/null
+++ b/ld/emulparams/aarch64linuxb.sh
@@ -0,0 +1,2 @@
+. ${srcdir}/emulparams/aarch64linux.sh
+OUTPUT_FORMAT="elf64-bigaarch64"
diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em
new file mode 100644
index 0000000..4c03ffd
--- /dev/null
+++ b/ld/emultempl/aarch64elf.em
@@ -0,0 +1,415 @@
+# This shell script emits a C file. -*- C -*-
+#   Copyright 2009-2012  Free Software Foundation, Inc.
+#   Contributed by ARM Ltd.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not,
+# see <http://www.gnu.org/licenses/>.
+#
+
+# This file is sourced from elf32.em, and defines extra aarch64-elf
+# specific routines.
+#
+fragment <<EOF
+
+#include "ldctor.h"
+#include "elf/aarch64.h"
+
+static int no_enum_size_warning = 0;
+static int no_wchar_size_warning = 0;
+static int pic_veneer = 0;
+
+static void
+gld${EMULATION_NAME}_before_parse (void)
+{
+#ifndef TARGET_			/* I.e., if not generic.  */
+  ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
+#endif /* not TARGET_ */
+  input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
+  config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
+}
+
+static void
+aarch64_elf_before_allocation (void)
+{
+  /* We should be able to set the size of the interworking stub section.  We
+     can't do it until later if we have dynamic sections, though.  */
+  if (! elf_hash_table (&link_info)->dynamic_sections_created)
+    {
+      /* Here we rummage through the found bfds to collect information.  */
+      LANG_FOR_EACH_INPUT_STATEMENT (is)
+	{
+          /* Initialise mapping tables for code/data.  */
+          bfd_elf64_aarch64_init_maps (is->the_bfd);
+	}
+    }
+
+  /* Call the standard elf routine.  */
+  gld${EMULATION_NAME}_before_allocation ();
+}
+
+/* Fake input file for stubs.  */
+static lang_input_statement_type *stub_file;
+
+/* Whether we need to call gldarm_layout_sections_again.  */
+static int need_laying_out = 0;
+
+/* Maximum size of a group of input sections that can be handled by
+   one stub section.  A value of +/-1 indicates the bfd back-end
+   should use a suitable default size.  */
+static bfd_signed_vma group_size = 1;
+
+struct hook_stub_info
+{
+  lang_statement_list_type add;
+  asection *input_section;
+};
+
+/* Traverse the linker tree to find the spot where the stub goes.  */
+
+static bfd_boolean
+hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
+{
+  lang_statement_union_type *l;
+  bfd_boolean ret;
+
+  for (; (l = *lp) != NULL; lp = &l->header.next)
+    {
+      switch (l->header.type)
+	{
+	case lang_constructors_statement_enum:
+	  ret = hook_in_stub (info, &constructor_list.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_output_section_statement_enum:
+	  ret = hook_in_stub (info,
+			      &l->output_section_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_wild_statement_enum:
+	  ret = hook_in_stub (info, &l->wild_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_group_statement_enum:
+	  ret = hook_in_stub (info, &l->group_statement.children.head);
+	  if (ret)
+	    return ret;
+	  break;
+
+	case lang_input_section_enum:
+	  if (l->input_section.section == info->input_section)
+	    {
+	      /* We've found our section.  Insert the stub immediately
+		 after its associated input section.  */
+	      *(info->add.tail) = l->header.next;
+	      l->header.next = info->add.head;
+	      return TRUE;
+	    }
+	  break;
+
+	case lang_data_statement_enum:
+	case lang_reloc_statement_enum:
+	case lang_object_symbols_statement_enum:
+	case lang_output_statement_enum:
+	case lang_target_statement_enum:
+	case lang_input_statement_enum:
+	case lang_assignment_statement_enum:
+	case lang_padding_statement_enum:
+	case lang_address_statement_enum:
+	case lang_fill_statement_enum:
+	  break;
+
+	default:
+	  FAIL ();
+	  break;
+	}
+    }
+  return FALSE;
+}
+
+
+/* Call-back for elf64_aarch64_size_stubs.  */
+
+/* Create a new stub section, and arrange for it to be linked
+   immediately after INPUT_SECTION.  */
+
+static asection *
+elf64_aarch64_add_stub_section (const char *stub_sec_name,
+				asection *input_section)
+{
+  asection *stub_sec;
+  flagword flags;
+  asection *output_section;
+  const char *secname;
+  lang_output_section_statement_type *os;
+  struct hook_stub_info info;
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
+	   | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+  stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
+						 stub_sec_name, flags);
+  if (stub_sec == NULL)
+    goto err_ret;
+
+  bfd_set_section_alignment (stub_file->the_bfd, stub_sec, 3);
+
+  output_section = input_section->output_section;
+  secname = bfd_get_section_name (output_section->owner, output_section);
+  os = lang_output_section_find (secname);
+
+  info.input_section = input_section;
+  lang_list_init (&info.add);
+  lang_add_section (&info.add, stub_sec, NULL, os);
+
+  if (info.add.head == NULL)
+    goto err_ret;
+
+  if (hook_in_stub (&info, &os->children.head))
+    return stub_sec;
+
+ err_ret:
+  einfo ("%X%P: can not make stub section: %E\n");
+  return NULL;
+}
+
+/* Another call-back for elf_arm_size_stubs.  */
+
+static void
+gldaarch64_layout_sections_again (void)
+{
+  /* If we have changed sizes of the stub sections, then we need
+     to recalculate all the section offsets.  This may mean we need to
+     add even more stubs.  */
+  gld${EMULATION_NAME}_map_segments (TRUE);
+  need_laying_out = -1;
+}
+
+static void
+build_section_lists (lang_statement_union_type *statement)
+{
+  if (statement->header.type == lang_input_section_enum)
+    {
+      asection *i = statement->input_section.section;
+
+      if (!((lang_input_statement_type *) i->owner->usrdata)->flags.just_syms
+	  && (i->flags & SEC_EXCLUDE) == 0
+	  && i->output_section != NULL
+	  && i->output_section->owner == link_info.output_bfd)
+	elf64_aarch64_next_input_section (& link_info, i);
+    }
+}
+
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+  /* bfd_elf32_discard_info just plays with debugging sections,
+     ie. doesn't affect any code, so we can delay resizing the
+     sections.  It's likely we'll resize everything in the process of
+     adding stubs.  */
+  if (bfd_elf_discard_info (link_info.output_bfd, & link_info))
+    need_laying_out = 1;
+
+  /* If generating a relocatable output file, then we don't
+     have to examine the relocs.  */
+  if (stub_file != NULL && !link_info.relocatable)
+    {
+      int ret = elf64_aarch64_setup_section_lists (link_info.output_bfd,
+						   & link_info);
+
+      if (ret != 0)
+	{
+	  if (ret < 0)
+	    {
+	      einfo ("%X%P: could not compute sections lists for stub generation: %E\n");
+	      return;
+	    }
+
+	  lang_for_each_statement (build_section_lists);
+
+	  /* Call into the BFD backend to do the real work.  */
+	  if (! elf64_aarch64_size_stubs (link_info.output_bfd,
+					  stub_file->the_bfd,
+					  & link_info,
+					  group_size,
+					  & elf64_aarch64_add_stub_section,
+					  & gldaarch64_layout_sections_again))
+	    {
+	      einfo ("%X%P: cannot size stub section: %E\n");
+	      return;
+	    }
+	}
+    }
+
+  if (need_laying_out != -1)
+    gld${EMULATION_NAME}_map_segments (need_laying_out);
+}
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+  if (! link_info.relocatable)
+    {
+      /* Now build the linker stubs.  */
+      if (stub_file->the_bfd->sections != NULL)
+	{
+	  if (! elf64_aarch64_build_stubs (& link_info))
+	    einfo ("%X%P: can not build stubs: %E\n");
+	}
+    }
+
+  finish_default ();
+}
+
+/* This is a convenient point to tell BFD about target specific flags.
+   After the output has been created, but before inputs are read.  */
+static void
+aarch64_elf_create_output_section_statements (void)
+{
+  if (strstr (bfd_get_target (link_info.output_bfd), "aarch64") == NULL)
+    {
+      /* The arm backend needs special fields in the output hash structure.
+	 These will only be created if the output format is an arm format,
+	 hence we do not support linking and changing output formats at the
+	 same time.  Use a link followed by objcopy to change output formats.  */
+      einfo ("%F%X%P: error: Cannot change output format whilst linking AArch64 binaries.\n");
+      return;
+    }
+
+  bfd_elf64_aarch64_set_options (link_info.output_bfd, &link_info,
+				 no_enum_size_warning,
+				 no_wchar_size_warning,
+				 pic_veneer);
+
+  stub_file = lang_add_input_file ("linker stubs",
+				   lang_input_file_is_fake_enum,
+				   NULL);
+  stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
+  if (stub_file->the_bfd == NULL
+      || ! bfd_set_arch_mach (stub_file->the_bfd,
+			      bfd_get_arch (link_info.output_bfd),
+			      bfd_get_mach (link_info.output_bfd)))
+    {
+      einfo ("%X%P: can not create BFD %E\n");
+      return;
+    }
+
+  stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
+  ldlang_add_file (stub_file);
+}
+
+/* Avoid processing the fake stub_file in vercheck, stat_needed and
+   check_needed routines.  */
+
+static void (*real_func) (lang_input_statement_type *);
+
+static void aarch64_for_each_input_file_wrapper (lang_input_statement_type *l)
+{
+  if (l != stub_file)
+    (*real_func) (l);
+}
+
+static void
+aarch64_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
+{
+  real_func = func;
+  lang_for_each_input_file (&aarch64_for_each_input_file_wrapper);
+}
+
+#define lang_for_each_input_file aarch64_lang_for_each_input_file
+
+EOF
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_NO_ENUM_SIZE_WARNING	309
+#define OPTION_PIC_VENEER		310
+#define OPTION_STUBGROUP_SIZE           311
+#define OPTION_NO_WCHAR_SIZE_WARNING	312
+'
+
+PARSE_AND_LIST_SHORTOPTS=p
+
+PARSE_AND_LIST_LONGOPTS='
+  { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
+  { "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING},
+  { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER},
+  { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
+  { "no-wchar-size-warning", no_argument, NULL, OPTION_NO_WCHAR_SIZE_WARNING},
+'
+
+PARSE_AND_LIST_OPTIONS='
+  fprintf (file, _("  --no-enum-size-warning      Don'\''t warn about objects with incompatible\n"
+		   "                                enum sizes\n"));
+  fprintf (file, _("  --no-wchar-size-warning     Don'\''t warn about objects with incompatible"
+		   "                                wchar_t sizes\n"));
+  fprintf (file, _("  --pic-veneer                Always generate PIC interworking veneers\n"));
+  fprintf (file, _("\
+   --stub-group-size=N   Maximum size of a group of input sections that can be\n\
+                           handled by one stub section.  A negative value\n\
+                           locates all stubs after their branches (with a\n\
+                           group size of -N), while a positive value allows\n\
+                           two groups of input sections, one before, and one\n\
+                           after each stub section.  Values of +/-1 indicate\n\
+                           the linker should choose suitable defaults.\n"
+		   ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+    case '\'p\'':
+      /* Only here for backwards compatibility.  */
+      break;
+
+    case OPTION_NO_ENUM_SIZE_WARNING:
+      no_enum_size_warning = 1;
+      break;
+
+    case OPTION_NO_WCHAR_SIZE_WARNING:
+      no_wchar_size_warning = 1;
+      break;
+
+    case OPTION_PIC_VENEER:
+      pic_veneer = 1;
+      break;
+
+    case OPTION_STUBGROUP_SIZE:
+      {
+	const char *end;
+
+        group_size = bfd_scan_vma (optarg, &end, 0);
+        if (*end)
+	  einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
+      }
+      break;
+'
+
+# We have our own before_allocation etc. functions, but they call
+# the standard routines, so give them a different name.
+LDEMUL_BEFORE_ALLOCATION=aarch64_elf_before_allocation
+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
+LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=aarch64_elf_create_output_section_statements
+
+# Replace the elf before_parse function with our own.
+LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+
+# Call the extra arm-elf function
+LDEMUL_FINISH=gld${EMULATION_NAME}_finish
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
new file mode 100644
index 0000000..eefe05a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -0,0 +1,105 @@
+# Expect script for various AARCH64 ELF tests.
+# Copyright 2009-2012 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# Exclude non-aarch64-ELF targets.
+if { ![is_elf_format] || ![istarget "aarch64*-*-*"] } {
+    return
+}
+
+# List contains test-items with 3 items followed by 2 lists:
+# 0:name 1:ld options 2:assembler options
+# 3:filenames of assembler files 4: action and options. 5: name of output file
+
+# Actions:
+# objdump: Apply objdump options on result.  Compare with regex (last arg).
+# nm: Apply nm options on result.  Compare with regex (last arg).
+# readelf: Apply readelf options on result.  Compare with regex (last arg).
+
+set aarch64elftests {
+    {"EH Frame merge" "-Ttext 0x8000" "" {eh-frame-bar.s eh-frame-foo.s}
+	{{objdump --dwarf=frames eh-frame.d}} "eh-frame"}
+}
+
+run_ld_link_tests $aarch64elftests
+
+# Relocation Tests
+run_dump_test "weak-undefined"
+run_dump_test "emit-relocs-257"
+run_dump_test "emit-relocs-257-be"
+# 258 is tested in 257
+# 259 is tested in 257
+run_dump_test "emit-relocs-260"
+run_dump_test "emit-relocs-260-be"
+# 261 is tested by 260
+run_dump_test "emit-relocs-262"
+run_dump_test "emit-relocs-263"
+run_dump_test "emit-relocs-264"
+run_dump_test "emit-relocs-265"
+run_dump_test "emit-relocs-266"
+run_dump_test "emit-relocs-267"
+run_dump_test "emit-relocs-268"
+run_dump_test "emit-relocs-269"
+run_dump_test "emit-relocs-270"
+run_dump_test "emit-relocs-270-bad"
+run_dump_test "emit-relocs-271"
+run_dump_test "emit-relocs-272"
+run_dump_test "emit-relocs-273"
+run_dump_test "emit-relocs-274"
+run_dump_test "emit-relocs-275"
+run_dump_test "emit-relocs-276"
+run_dump_test "emit-relocs-277"
+run_dump_test "emit-relocs-278"
+run_dump_test "emit-relocs-279"
+run_dump_test "emit-relocs-279-bad"
+run_dump_test "emit-relocs-280"
+# 281 is unused
+run_dump_test "emit-relocs-282"
+run_dump_test "emit-relocs-283"
+run_dump_test "emit-relocs-284"
+run_dump_test "emit-relocs-285"
+run_dump_test "emit-relocs-286"
+run_dump_test "emit-relocs-286-bad"
+# 287-298 are not done yet
+run_dump_test "emit-relocs-299"
+# 300-310 are not done yet
+run_dump_test "emit-relocs-311"
+run_dump_test "emit-relocs-312"
+
+
+run_dump_test "limit-b"
+run_dump_test "limit-bl"
+run_dump_test "farcall-section"
+run_dump_test "farcall-back"
+run_dump_test "farcall-bl"
+run_dump_test "farcall-b"
+run_dump_test "farcall-b-none-function"
+run_dump_test "farcall-bl-none-function"
+
+run_dump_test "tls-relax-all"
+run_dump_test "tls-relax-gd-le"
+run_dump_test "tls-relax-gdesc-le"
+run_dump_test "tls-relax-gd-ie"
+run_dump_test "tls-relax-gdesc-ie"
+run_dump_test "tls-relax-ie-le"
+run_dump_test "tls-desc-ie"
+run_dump_test "tls-relax-gdesc-ie-2"
+run_dump_test "tls-relax-gdesc-le-2"
+run_dump_test "tls-relax-ie-le-2"
+run_dump_test "tls-relax-ie-le-3"
diff --git a/ld/testsuite/ld-aarch64/aarch64.ld b/ld/testsuite/ld-aarch64/aarch64.ld
new file mode 100644
index 0000000..75ee3b5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/aarch64.ld
@@ -0,0 +1,19 @@
+/* Script for ld testsuite */
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x8000); . = 0x8000;
+  .text           :
+  {
+    *(.before)
+    *(.text)
+    *(.after)
+  } =0
+  . = 0x9000;
+  .got            : { *(.got) *(.got.plt)}
+  . = 0x12340000;
+  .far : { *(.far) }
+  .ARM.attributes 0 : { *(.ARM.atttributes) }
+}
diff --git a/ld/testsuite/ld-aarch64/eh-frame-bar.s b/ld/testsuite/ld-aarch64/eh-frame-bar.s
new file mode 100644
index 0000000..a67d8e4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/eh-frame-bar.s
@@ -0,0 +1,38 @@
+__longjmp:
+ .cfi_startproc
+ .cfi_def_cfa x0, 0
+ .cfi_offset x19, 16
+ .cfi_offset x20, 16
+ .cfi_offset x21, 16
+ .cfi_offset x22, 16
+ .cfi_offset x23, 24
+ .cfi_offset x24, 24
+ .cfi_offset x25, 24
+ .cfi_offset x26, 24
+ .cfi_offset x27, 24
+ .cfi_offset x28, 32
+ .cfi_offset x29, 32
+ .cfi_offset x30, 36
+ .cfi_offset d9, 8
+# This eh frame data differs from eh-frame-bar.s here, see the comment
+# in eh-frame-foo.s
+ .cfi_offset d11, 8
+
+ ldp x19, x20, [x0, #16]
+ ldp x21, x22, [x0, #16]
+ ldp x23, x24, [x0, #24]
+ ldp x25, x26, [x0, #24]
+ ldp x27, x28, [x0, #24]
+ ldp x29, x30, [x0, #32]
+
+ ldp d8, d9, [x0, #8]
+ ldp d10, d11, [x0, #8]
+ ldp d12, d13, [x0, #8]
+ ldp d14, d15, [x0, #8]
+ ldr x5, [x0, #48]
+ mov sp, x5
+ cmp x1, #0
+ mov x0, #1
+ csel x0, x1, x0, ne
+ br x30
+ .cfi_endproc
diff --git a/ld/testsuite/ld-aarch64/eh-frame-foo.s b/ld/testsuite/ld-aarch64/eh-frame-foo.s
new file mode 100644
index 0000000..c077ef2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/eh-frame-foo.s
@@ -0,0 +1,55 @@
+__longjmp:
+ .cfi_startproc
+ .cfi_def_cfa x0, 0
+ .cfi_offset x19, 16
+ .cfi_offset x20, 16
+ .cfi_offset x21, 16
+ .cfi_offset x22, 16
+ .cfi_offset x23, 24
+ .cfi_offset x24, 24
+ .cfi_offset x25, 24
+ .cfi_offset x26, 24
+ .cfi_offset x27, 24
+ .cfi_offset x28, 32
+ .cfi_offset x29, 32
+ .cfi_offset x30, 36
+ .cfi_offset d9, 8
+
+/* This eh frame data differs from eh-frame-bar.s here.  The eh
+   frame information is identical but changes at the end.  The
+   initial identical section is long enough to overflow the
+   initial instruction buffer used in eh frame merging.  This
+   checks that merging does something sane once the initial
+   instruction buffer overflows.  */
+
+.cfi_offset d10, 8
+
+
+
+
+
+
+
+ ldp x19, x20, [x0, #16]
+ ldp x21, x22, [x0, #16]
+ ldp x23, x24, [x0, #24]
+ ldp x25, x26, [x0, #24]
+ ldp x27, x28, [x0, #24]
+ ldp x29, x30, [x0, #32]
+
+ ldp d8, d9, [x0, #8]
+ ldp d10, d11, [x0, #8]
+ ldp d12, d13, [x0, #8]
+ ldp d14, d15, [x0, #8]
+ ldr x5, [x0, #48]
+ mov sp, x5
+ cmp x1, #0
+ mov x0, #1
+ csel x0, x1, x0, ne
+
+ br x30
+ .cfi_endproc
+
+ .global _start
+_start:
+
diff --git a/ld/testsuite/ld-aarch64/eh-frame.d b/ld/testsuite/ld-aarch64/eh-frame.d
new file mode 100644
index 0000000..88e9988
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/eh-frame.d
@@ -0,0 +1,86 @@
+.*:     file format elf64-(little|big)aarch64
+
+Contents of the .eh_frame section:
+
+00000000 00000044 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 2
+  Data alignment factor: -4
+  Return address column: 30
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r31 ofs 0
+  DW_CFA_def_cfa: r0 ofs 0
+  DW_CFA_offset_extended_sf: r19 at cfa\+16
+  DW_CFA_offset_extended_sf: r20 at cfa\+16
+  DW_CFA_offset_extended_sf: r21 at cfa\+16
+  DW_CFA_offset_extended_sf: r22 at cfa\+16
+  DW_CFA_offset_extended_sf: r23 at cfa\+24
+  DW_CFA_offset_extended_sf: r24 at cfa\+24
+  DW_CFA_offset_extended_sf: r25 at cfa\+24
+  DW_CFA_offset_extended_sf: r26 at cfa\+24
+  DW_CFA_offset_extended_sf: r27 at cfa\+24
+  DW_CFA_offset_extended_sf: r28 at cfa\+32
+  DW_CFA_offset_extended_sf: r29 at cfa\+32
+  DW_CFA_offset_extended_sf: r30 at cfa\+36
+  DW_CFA_offset_extended_sf: r9 at cfa\+8
+  DW_CFA_offset_extended_sf: r11 at cfa\+8
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000048 00000014 0000004c FDE cie=00000000 pc=f*ffffff80..f*ffffffc0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000060 00000044 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 2
+  Data alignment factor: -4
+  Return address column: 30
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r31 ofs 0
+  DW_CFA_def_cfa: r0 ofs 0
+  DW_CFA_offset_extended_sf: r19 at cfa\+16
+  DW_CFA_offset_extended_sf: r20 at cfa\+16
+  DW_CFA_offset_extended_sf: r21 at cfa\+16
+  DW_CFA_offset_extended_sf: r22 at cfa\+16
+  DW_CFA_offset_extended_sf: r23 at cfa\+24
+  DW_CFA_offset_extended_sf: r24 at cfa\+24
+  DW_CFA_offset_extended_sf: r25 at cfa\+24
+  DW_CFA_offset_extended_sf: r26 at cfa\+24
+  DW_CFA_offset_extended_sf: r27 at cfa\+24
+  DW_CFA_offset_extended_sf: r28 at cfa\+32
+  DW_CFA_offset_extended_sf: r29 at cfa\+32
+  DW_CFA_offset_extended_sf: r30 at cfa\+36
+  DW_CFA_offset_extended_sf: r9 at cfa\+8
+  DW_CFA_offset_extended_sf: r10 at cfa\+8
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000000a8 00000014 0000004c FDE cie=00000060 pc=f*ffffffc0..00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-257-be.d b/ld/testsuite/ld-aarch64/emit-relocs-257-be.d
new file mode 100644
index 0000000..3f6be24
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-257-be.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-257.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234  -e0 --emit-relocs
+#notarget: aarch64-*-*
+#objdump: -dr
+#...
+ +10000:	00011012 	\.word	0x00011012
+	+10000: R_AARCH64_ABS32	tempy
+ +10004:	00000000 	\.word	0x00000000
+	+10004: R_AARCH64_ABS64	tempy2
+ +10008:	00045034 	\.word	0x00045034
+ +1000c:	1234123c 	\.word	0x1234123c
+	+1000c: R_AARCH64_ABS16	tempy3
+	+1000e: R_AARCH64_ABS16	tempy3\+0x8
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-257.d b/ld/testsuite/ld-aarch64/emit-relocs-257.d
new file mode 100644
index 0000000..0a3a7ac
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-257.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-257.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234  -e0 --emit-relocs
+#notarget: aarch64_be-*-*
+#objdump: -dr
+#...
+ +10000:	00011012 	\.word	0x00011012
+	+10000: R_AARCH64_ABS32	tempy
+ +10004:	00045034 	\.word	0x00045034
+	+10004: R_AARCH64_ABS64	tempy2
+ +10008:	00000000 	\.word	0x00000000
+ +1000c:	123c1234 	\.word	0x123c1234
+	+1000c: R_AARCH64_ABS16	tempy3
+	+1000e: R_AARCH64_ABS16	tempy3\+0x8
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-257.s b/ld/testsuite/ld-aarch64/emit-relocs-257.s
new file mode 100644
index 0000000..609ebba
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-257.s
@@ -0,0 +1,12 @@
+.comm   gempy,4,4
+.text
+
+.word	tempy
+.xword  tempy2
+.hword	tempy3
+.hword	tempy3+8
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-260-be.d b/ld/testsuite/ld-aarch64/emit-relocs-260-be.d
new file mode 100644
index 0000000..7cea3c6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-260-be.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-260.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234 --defsym _GOT_=0x10000 -e0 --emit-relocs
+#notarget: aarch64-*-*
+#objdump: -dr
+#...
+	+10000: R_AARCH64_PREL32	_GOT_
+	+10004: R_AARCH64_PREL64	_GOT_\+0x12
+ +10008:	0000000e 	\.word	0x0000000e
+ +1000c:	fff404f2 	\.word	0xfff404f2
+	+1000c: R_AARCH64_PREL16	_GOT_
+	+1000e: R_AARCH64_PREL16	_GOT_\+0x500
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-260.d b/ld/testsuite/ld-aarch64/emit-relocs-260.d
new file mode 100644
index 0000000..91c1d8a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-260.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-260.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234 --defsym _GOT_=0x10000 -e0 --emit-relocs
+#notarget: aarch64_be-*-*
+#objdump: -dr
+#...
+ +10000:	00000000 	\.word	0x00000000
+	+10000: R_AARCH64_PREL32	_GOT_
+ +10004:	0000000e 	\.word	0x0000000e
+	+10004: R_AARCH64_PREL64	_GOT_\+0x12
+ +10008:	00000000 	\.word	0x00000000
+ +1000c:	04f2fff4 	\.word	0x04f2fff4
+	+1000c: R_AARCH64_PREL16	_GOT_
+	+1000e: R_AARCH64_PREL16	_GOT_\+0x500
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-260.s b/ld/testsuite/ld-aarch64/emit-relocs-260.s
new file mode 100644
index 0000000..87aa342
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-260.s
@@ -0,0 +1,13 @@
+.comm   gempy,4,4
+.text
+
+.word	_GOT_ - .
+.xword  _GOT_ - . + 0x12
+.hword	_GOT_ - . 
+.hword	_GOT_ - . + 0x500 
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-262.d b/ld/testsuite/ld-aarch64/emit-relocs-262.d
new file mode 100644
index 0000000..c42ecb6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-262.d
@@ -0,0 +1,16 @@
+#source: emit-relocs-262.s
+#ld: -T relocs.ld --defsym tempy=0x11012 --defsym tempy2=0x45034 --defsym tempy3=0x1234 --defsym _GOT_=0x20000 -e0 --emit-relocs
+#error: .*truncated.*
+#objdump: -dr
+#...
+ +10000:	00011012 	\.word	0x00011012
+	+10000: R_AARCH64_PREL32	tempy
+ +10004:	00045034 	\.word	0x00045034
+	+10004: R_AARCH64_PREL64	tempy2
+ +10008:	00000000 	\.word	0x00000000
+ +1000c:	123c1234 	\.word	0x123c1234
+	+1000c: R_AARCH64_PREL16	tempy3
+	+1000e: R_AARCH64_PREL16	tempy3\+0x8
+ +10010:	8a000000 	and	x0, x0, x0
+ +10014:	92400000 	and	x0, x0, #0x1
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-262.s b/ld/testsuite/ld-aarch64/emit-relocs-262.s
new file mode 100644
index 0000000..aa97f52
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-262.s
@@ -0,0 +1,13 @@
+.comm   gempy,4,4
+.text
+
+.word	_GOT_ - .
+.xword  _GOT_ - . + 0x12
+.hword	_GOT_ - . 
+.hword	_GOT_ - . 
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-263.d b/ld/testsuite/ld-aarch64/emit-relocs-263.d
new file mode 100644
index 0000000..a6c854d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-263.d
@@ -0,0 +1,15 @@
+#source: emit-relocs-263.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#error: .*\(.text\+0x\d+\): relocation truncated to fit: R_AARCH64_MOVW_UABS_G0 against symbol `tempy.*
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820004 	movz	x4, #0x1000
+	+10008: R_AARCH64_MOVW_UABS_G0	tempy
+ +1000c:	d28a0007 	movz	x7, #0x5000
+	+1000c: R_AARCH64_MOVW_UABS_G0	tempy2
+ +10010:	d2824691 	movz	x17, #0x1234
+	+10010: R_AARCH64_MOVW_UABS_G0	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-263.s b/ld/testsuite/ld-aarch64/emit-relocs-263.s
new file mode 100644
index 0000000..e215872
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-263.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g0:tempy
+	movz	x7, :abs_g0:tempy2
+	movz	x17, :abs_g0:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-264.d b/ld/testsuite/ld-aarch64/emit-relocs-264.d
new file mode 100644
index 0000000..1da911b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-264.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-264.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820004 	movz	x4, #0x1000
+	+10008: R_AARCH64_MOVW_UABS_G0_NC	tempy
+ +1000c:	d28a0007 	movz	x7, #0x5000
+	+1000c: R_AARCH64_MOVW_UABS_G0_NC	tempy2
+ +10010:	d2824691 	movz	x17, #0x1234
+	+10010: R_AARCH64_MOVW_UABS_G0_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-264.s b/ld/testsuite/ld-aarch64/emit-relocs-264.s
new file mode 100644
index 0000000..32a5a17
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-264.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g0_nc:tempy
+	movz	x7, :abs_g0_nc:tempy2
+	movz	x17, :abs_g0_nc:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-265.d b/ld/testsuite/ld-aarch64/emit-relocs-265.d
new file mode 100644
index 0000000..d30db5f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-265.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-265.s
+#ld: -T relocs.ld --defsym tempy=0x100011000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#error: .*\(.text\+0x\d+\): relocation truncated to fit: R_AARCH64_MOVW_UABS_G1 against symbol `tempy.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2a00024 	movz	x4, #0x1, lsl #16
+	+10008: R_AARCH64_MOVW_UABS_G1	tempy
+ +1000c:	d2a00087 	movz	x7, #0x4, lsl #16
+	+1000c: R_AARCH64_MOVW_UABS_G1	tempy2
+ +10010:	d2a00011 	movz	x17, #0x0, lsl #16
+	+10010: R_AARCH64_MOVW_UABS_G1	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-265.s b/ld/testsuite/ld-aarch64/emit-relocs-265.s
new file mode 100644
index 0000000..552a8ae
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-265.s
@@ -0,0 +1,10 @@
+.comm   gempy,4,4
+.text
+
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g1:tempy
+	movz	x7, :abs_g1:tempy2
+	movz	x17, :abs_g1:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-266.d b/ld/testsuite/ld-aarch64/emit-relocs-266.d
new file mode 100644
index 0000000..fde9090
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-266.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-266.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2a00024 	movz	x4, #0x1, lsl #16
+	+10008: R_AARCH64_MOVW_UABS_G1_NC	tempy
+ +1000c:	d2a00087 	movz	x7, #0x4, lsl #16
+	+1000c: R_AARCH64_MOVW_UABS_G1_NC	tempy2
+ +10010:	d2a00011 	movz	x17, #0x0, lsl #16
+	+10010: R_AARCH64_MOVW_UABS_G1_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-266.s b/ld/testsuite/ld-aarch64/emit-relocs-266.s
new file mode 100644
index 0000000..7c23e87
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-266.s
@@ -0,0 +1,10 @@
+.comm   gempy,4,4
+.text
+
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g1_nc:tempy
+	movz	x7, :abs_g1_nc:tempy2
+	movz	x17, :abs_g1_nc:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-267.d b/ld/testsuite/ld-aarch64/emit-relocs-267.d
new file mode 100644
index 0000000..9cc495c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-267.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-267.s
+#ld: -T relocs.ld --defsym tempy=0x63001000 --defsym tempy2=0x4500000000 --defsym tempy3=0x1234567812345  -e0 --emit-relocs
+#error: .*truncated.*tempy3.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2c00004 	movz	x4, #0x0, lsl #32
+	+10008: R_AARCH64_MOVW_UABS_G2	tempy
+ +1000c:	d2c008a7 	movz	x7, #0x45, lsl #32
+	+1000c: R_AARCH64_MOVW_UABS_G2	tempy2
+ +10010:	d2c468b1 	movz	x17, #0x2345, lsl #32
+	+10010: R_AARCH64_MOVW_UABS_G2	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-267.s b/ld/testsuite/ld-aarch64/emit-relocs-267.s
new file mode 100644
index 0000000..94a150e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-267.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g2:tempy
+	movz	x7, :abs_g2:tempy2
+	movz	x17, :abs_g2:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-268.d b/ld/testsuite/ld-aarch64/emit-relocs-268.d
new file mode 100644
index 0000000..126548b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-268.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-268.s
+#ld: -T relocs.ld --defsym tempy=0x63001000 --defsym tempy2=0x4500000000 --defsym tempy3=0x1234567812345  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2c00004 	movz	x4, #0x0, lsl #32
+	+10008: R_AARCH64_MOVW_UABS_G2_NC	tempy
+ +1000c:	d2c008a7 	movz	x7, #0x45, lsl #32
+	+1000c: R_AARCH64_MOVW_UABS_G2_NC	tempy2
+ +10010:	d2c468b1 	movz	x17, #0x2345, lsl #32
+	+10010: R_AARCH64_MOVW_UABS_G2_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-268.s b/ld/testsuite/ld-aarch64/emit-relocs-268.s
new file mode 100644
index 0000000..5928043
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-268.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g2_nc:tempy
+	movz	x7, :abs_g2_nc:tempy2
+	movz	x17, :abs_g2_nc:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-269.d b/ld/testsuite/ld-aarch64/emit-relocs-269.d
new file mode 100644
index 0000000..a911532
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-269.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-269.s
+#ld: -T relocs.ld --defsym tempy=0x6300100100100100 --defsym tempy2=0xf00df00df00df00d --defsym tempy3=0x1234567812345  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2ec6004 	movz	x4, #0x6300, lsl #48
+	+10008: R_AARCH64_MOVW_UABS_G3	tempy
+ +1000c:	d2fe01a7 	movz	x7, #0xf00d, lsl #48
+	+1000c: R_AARCH64_MOVW_UABS_G3	tempy2
+ +10010:	d2e00031 	movz	x17, #0x1, lsl #48
+	+10010: R_AARCH64_MOVW_UABS_G3	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-269.s b/ld/testsuite/ld-aarch64/emit-relocs-269.s
new file mode 100644
index 0000000..b0f11a0
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-269.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g3:tempy
+	movz	x7, :abs_g3:tempy2
+	movz	x17, :abs_g3:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-270-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-270-bad.d
new file mode 100644
index 0000000..a781a5a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-270-bad.d
@@ -0,0 +1,15 @@
+#source: emit-relocs-270.s
+#ld: -T relocs.ld --defsym tempy=0x10012 --defsym tempy2=0x45000 --defsym tempy3=-292  -e0 --emit-relocs
+#error: .*truncated.*tempy[12].*
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820244 	movz	x4, #0x1012
+	+10008: R_AARCH64_MOVW_SABS_G0	tempy
+ +1000c:	d288a007 	movz	x7, #0x4500
+	+1000c: R_AARCH64_MOVW_SABS_G0	tempy2
+ +10010:	92802471 	movn	x17, #0x123
+	+10010: R_AARCH64_MOVW_SABS_G0	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-270.d b/ld/testsuite/ld-aarch64/emit-relocs-270.d
new file mode 100644
index 0000000..6e68aec
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-270.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-270.s
+#ld: -T relocs.ld --defsym tempy=0x1012 --defsym tempy2=0x4500 --defsym tempy3=-292  -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820244 	movz	x4, #0x1012
+	+10008: R_AARCH64_MOVW_SABS_G0	tempy
+ +1000c:	d288a007 	movz	x7, #0x4500
+	+1000c: R_AARCH64_MOVW_SABS_G0	tempy2
+ +10010:	92802471 	movn	x17, #0x123
+	+10010: R_AARCH64_MOVW_SABS_G0	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-270.s b/ld/testsuite/ld-aarch64/emit-relocs-270.s
new file mode 100644
index 0000000..b508f88
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-270.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g0_s:tempy
+	movz	x7, :abs_g0_s:tempy2
+	movz	x17, :abs_g0_s:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-271.d b/ld/testsuite/ld-aarch64/emit-relocs-271.d
new file mode 100644
index 0000000..5a230c7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-271.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-271.s
+#ld: -T relocs.ld --defsym tempy=0x1012 --defsym tempy2=0x674500 --defsym tempy3=-292  -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2a00004 	movz	x4, #0x0, lsl #16
+	+10008: R_AARCH64_MOVW_SABS_G1	tempy
+ +1000c:	d2a00ce7 	movz	x7, #0x67, lsl #16
+	+1000c: R_AARCH64_MOVW_SABS_G1	tempy2
+ +10010:	92a00011 	movn	x17, #0x0, lsl #16
+	+10010: R_AARCH64_MOVW_SABS_G1	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-271.s b/ld/testsuite/ld-aarch64/emit-relocs-271.s
new file mode 100644
index 0000000..bb14fbb
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-271.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g1_s:tempy
+	movz	x7, :abs_g1_s:tempy2
+	movz	x17, :abs_g1_s:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-272.d b/ld/testsuite/ld-aarch64/emit-relocs-272.d
new file mode 100644
index 0000000..a02a52e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-272.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-272.s
+#ld: -T relocs.ld --defsym tempy=0x1012 --defsym tempy2=-12345678912345 --defsym tempy3=-292  -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2c00004 	movz	x4, #0x0, lsl #32
+	+10008: R_AARCH64_MOVW_SABS_G2	tempy
+ +1000c:	92c16747 	movn	x7, #0xb3a, lsl #32
+	+1000c: R_AARCH64_MOVW_SABS_G2	tempy2
+ +10010:	92c00011 	movn	x17, #0x0, lsl #32
+	+10010: R_AARCH64_MOVW_SABS_G2	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-272.s b/ld/testsuite/ld-aarch64/emit-relocs-272.s
new file mode 100644
index 0000000..daa625a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-272.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :abs_g2_s:tempy
+	movz	x7, :abs_g2_s:tempy2
+	movz	x17, :abs_g2_s:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-273.d b/ld/testsuite/ld-aarch64/emit-relocs-273.d
new file mode 100644
index 0000000..13ed221
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-273.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-273.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	58007fc4 	ldr	x4, 11000 <tempy>
+	+10008: R_AARCH64_LD_PREL_LO19	tempy
+ +1000c:	581a7fa7 	ldr	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_LD_PREL_LO19	tempy2
+ +10010:	58f89131 	ldr	x17, 1234 <tempy3>
+	+10010: R_AARCH64_LD_PREL_LO19	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-273.s b/ld/testsuite/ld-aarch64/emit-relocs-273.s
new file mode 100644
index 0000000..d1bad37
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-273.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     x4,tempy
+	ldr	x7,tempy2
+	ldr	x17,tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-274.d b/ld/testsuite/ld-aarch64/emit-relocs-274.d
new file mode 100644
index 0000000..f38ecbd
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-274.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-274.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	10007fc2 	adr	x2, .*
+	+10008: R_AARCH64_ADR_PREL_LO21	tempy
+ +1000c:	101a7fa7 	adr	x7, 45000 .*
+	+1000c: R_AARCH64_ADR_PREL_LO21	tempy2
+ +10010:	10f89131 	adr	x17, .*
+	+10010: R_AARCH64_ADR_PREL_LO21	tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-274.s b/ld/testsuite/ld-aarch64/emit-relocs-274.s
new file mode 100644
index 0000000..8668b7c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-274.s
@@ -0,0 +1,5 @@
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adr     x2,tempy
+        adr     x7,tempy2
+	adr	x17,tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-275.d b/ld/testsuite/ld-aarch64/emit-relocs-275.d
new file mode 100644
index 0000000..94e61a7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-275.d
@@ -0,0 +1,15 @@
+#source: emit-relocs-275.s
+#ld: -T relocs.ld --defsym tempy=0x200011000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#error: .*\(.text\+0x\d+\): relocation truncated to fit: R_AARCH64_ADR_PREL_PG_HI21 against symbol `tempy'
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b0000002 	adrp	x2, .*
+	+10008: R_AARCH64_ADR_PREL_PG_HI21	tempy
+ +1000c:	b00001a7 	adrp	x7, .*
+	+1000c: R_AARCH64_ADR_PREL_PG_HI21	tempy2
+ +10010:	b0ffff91 	adrp	x17, .*
+	+10010: R_AARCH64_ADR_PREL_PG_HI21	tempy3
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-275.s b/ld/testsuite/ld-aarch64/emit-relocs-275.s
new file mode 100644
index 0000000..92a2935
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-275.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adrp    x2,tempy
+	adrp	x7,tempy2
+	adrp	x17,tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-276.d b/ld/testsuite/ld-aarch64/emit-relocs-276.d
new file mode 100644
index 0000000..f133253
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-276.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-275.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b0000002 	adrp	x2, 11000 <tempy>
+	+10008: R_AARCH64_ADR_PREL_PG_HI21	tempy
+ +1000c:	b00001a7 	adrp	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_ADR_PREL_PG_HI21	tempy2
+ +10010:	b0ffff91 	adrp	x17, 1000 <tempy3-0x234>
+	+10010: R_AARCH64_ADR_PREL_PG_HI21	tempy3
+
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-276.s b/ld/testsuite/ld-aarch64/emit-relocs-276.s
new file mode 100644
index 0000000..92a2935
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-276.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adrp    x2,tempy
+	adrp	x7,tempy2
+	adrp	x17,tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-277.d b/ld/testsuite/ld-aarch64/emit-relocs-277.d
new file mode 100644
index 0000000..2145441
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-277.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-277.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	91006064 	add	x4, x3,.*
+	+10008: R_AARCH64_ADD_ABS_LO12_NC	tempy
+ +1000c:	9100e067 	add	x7, x3,.*
+	+1000c: R_AARCH64_ADD_ABS_LO12_NC	tempy2
+ +10010:	9108d071 	add	x17, x3,.*
+	+10010: R_AARCH64_ADD_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-277.s b/ld/testsuite/ld-aarch64/emit-relocs-277.s
new file mode 100644
index 0000000..efb0bf0
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-277.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        add     x4, x3, #:lo12:tempy
+	add	x7, x3, #:lo12:tempy2
+	add	x17, x3, #:lo12:tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-278.d b/ld/testsuite/ld-aarch64/emit-relocs-278.d
new file mode 100644
index 0000000..29a0095
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-278.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-278.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	3d406064 	ldr	b4, \[x3,.*
+	+10008: R_AARCH64_LDST8_ABS_LO12_NC	tempy
+ +1000c:	3d40e067 	ldr	b7, \[x3,.*
+	+1000c: R_AARCH64_LDST8_ABS_LO12_NC	tempy2
+ +10010:	3d48d071 	ldr	b17, \[x3,.*
+	+10010: R_AARCH64_LDST8_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-278.s b/ld/testsuite/ld-aarch64/emit-relocs-278.s
new file mode 100644
index 0000000..2f7f321
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-278.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     b4, [x3, #:lo12:tempy]
+	ldr	b7, [x3, #:lo12:tempy2]
+	ldr	b17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-279-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-279-bad.d
new file mode 100644
index 0000000..02b5ff6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-279-bad.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-279.s
+#ld: -T relocs.ld --defsym target=0xc000 --defsym target2=0x45678 -e0 --emit-relocs
+#error: .*truncated.*target2.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	17ffeffc 	b	c000 <target>
+	+10010: R_AARCH64_TSTBR14	target
+ +10014:	17ffefff 	b	c010 <target\+0x10>
+	+10014: R_AARCH64_TSTBR14	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-279.d b/ld/testsuite/ld-aarch64/emit-relocs-279.d
new file mode 100644
index 0000000..6980f81
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-279.d
@@ -0,0 +1,17 @@
+#source: emit-relocs-279.s
+#ld: -T relocs.ld --defsym target=0xc000 --defsym target2=0x12340 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	363dff84 	tbz	w4, #7, c000 <target>
+	+10010: R_AARCH64_TSTBR14	target
+ +10014:	b745ffe7 	tbnz	x7, #40, c010 <target\+0x10>
+	+10014: R_AARCH64_TSTBR14	target\+0x10
+ +10018:	3619194c 	tbz	w12, #3, 12340 <target2>
+	+10018: R_AARCH64_TSTBR14	target2
+ +1001c:	b7c118d1 	tbnz	x17, #56, 12334 <target.*
+	+1001c: R_AARCH64_TSTBR14	target.*
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-279.s b/ld/testsuite/ld-aarch64/emit-relocs-279.s
new file mode 100644
index 0000000..f70c78b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-279.s
@@ -0,0 +1,8 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	tbz	x4, 7, target
+	tbnz	x7, 40, target+16
+	tbz	x12, 3, target2
+	tbnz	x17, 56, target2-12
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-280.d b/ld/testsuite/ld-aarch64/emit-relocs-280.d
new file mode 100644
index 0000000..9b954ff
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-280.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-280.s
+#ld: -T relocs.ld --defsym target=0xc000 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	54fdff80 	b.eq	c000 <target>
+	+10010: R_AARCH64_CONDBR19	target
+ +10014:	54fdffe0 	b.eq	c010 <target\+0x10>
+	+10014: R_AARCH64_CONDBR19	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-280.s b/ld/testsuite/ld-aarch64/emit-relocs-280.s
new file mode 100644
index 0000000..8f5ec34
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-280.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	beq	target
+	beq	target+16
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-282.d b/ld/testsuite/ld-aarch64/emit-relocs-282.d
new file mode 100644
index 0000000..fc5764b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-282.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-282.s
+#ld: -T relocs.ld --defsym target=0xc000 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	17ffeffc 	b	c000 <target>
+	+10010: R_AARCH64_JUMP26	target
+ +10014:	17ffefff 	b	c010 <target\+0x10>
+	+10014: R_AARCH64_JUMP26	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-282.s b/ld/testsuite/ld-aarch64/emit-relocs-282.s
new file mode 100644
index 0000000..b249b6b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-282.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	b	target
+	b	target+16
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-283.d b/ld/testsuite/ld-aarch64/emit-relocs-283.d
new file mode 100644
index 0000000..708fc7c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-283.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-283.s
+#ld: -T relocs.ld --defsym target=0xc000 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	.*
+ +10004:	8a000000 	and	.*
+ +10008:	8a000000 	and	.*
+ +1000c:	8a000000 	and	.*
+ +10010:	97ffeffc 	bl	c000 <target>
+	+10010: R_AARCH64_CALL26	target
+ +10014:	97ffefff 	bl	c010 <target\+0x10>
+	+10014: R_AARCH64_CALL26	target\+0x10
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-283.s b/ld/testsuite/ld-aarch64/emit-relocs-283.s
new file mode 100644
index 0000000..9c9f509
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-283.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	bl	target
+	bl	target+16
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-284.d b/ld/testsuite/ld-aarch64/emit-relocs-284.d
new file mode 100644
index 0000000..5cb6dac
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-284.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-284.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	7d403064 	ldr	h4, \[x3,.*
+	+10008: R_AARCH64_LDST16_ABS_LO12_NC	tempy
+ +1000c:	7d407067 	ldr	h7, \[x3,.*
+	+1000c: R_AARCH64_LDST16_ABS_LO12_NC	tempy2
+ +10010:	7d446871 	ldr	h17, \[x3,.*
+	+10010: R_AARCH64_LDST16_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-284.s b/ld/testsuite/ld-aarch64/emit-relocs-284.s
new file mode 100644
index 0000000..ffd213b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-284.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     h4, [x3, #:lo12:tempy]
+	ldr	h7, [x3, #:lo12:tempy2]
+	ldr	h17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-285.d b/ld/testsuite/ld-aarch64/emit-relocs-285.d
new file mode 100644
index 0000000..8bf8270
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-285.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-285.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b9401864 	ldr	w4, \[x3,.*
+	+10008: R_AARCH64_LDST32_ABS_LO12_NC	tempy
+ +1000c:	b9403867 	ldr	w7, \[x3,.*
+	+1000c: R_AARCH64_LDST32_ABS_LO12_NC	tempy2
+ +10010:	b9423471 	ldr	w17, \[x3,.*
+	+10010: R_AARCH64_LDST32_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-285.s b/ld/testsuite/ld-aarch64/emit-relocs-285.s
new file mode 100644
index 0000000..245f8be
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-285.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     w4, [x3, #:lo12:tempy]
+	ldr	w7, [x3, #:lo12:tempy2]
+	ldr	w17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-286-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-286-bad.d
new file mode 100644
index 0000000..50cd605
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-286-bad.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-286.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1234  -e0 --emit-relocs
+#error: .*truncated.*tempy3.*
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	f9400c64 	ldr	x4, \[x3,.*
+	+10008: R_AARCH64_LDST64_ABS_LO12_NC	tempy
+ +1000c:	f9401c67 	ldr	x7, \[x3,.*
+	+1000c: R_AARCH64_LDST64_ABS_LO12_NC	tempy2
+ +10010:	f9411871 	ldr	x17, \[x3,.*
+	+10010: R_AARCH64_LDST64_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-286.d b/ld/testsuite/ld-aarch64/emit-relocs-286.d
new file mode 100644
index 0000000..851fa7b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-286.d
@@ -0,0 +1,13 @@
+#source: emit-relocs-286.s
+#ld: -T relocs.ld --defsym tempy=0x11018 --defsym tempy2=0x45038 --defsym tempy3=0x1230  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	f9400c64 	ldr	x4, \[x3,.*
+	+10008: R_AARCH64_LDST64_ABS_LO12_NC	tempy
+ +1000c:	f9401c67 	ldr	x7, \[x3,.*
+	+1000c: R_AARCH64_LDST64_ABS_LO12_NC	tempy2
+ +10010:	f9411871 	ldr	x17, \[x3,.*
+	+10010: R_AARCH64_LDST64_ABS_LO12_NC	tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-286.s b/ld/testsuite/ld-aarch64/emit-relocs-286.s
new file mode 100644
index 0000000..78b508f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-286.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     x4, [x3, #:lo12:tempy]
+	ldr	x7, [x3, #:lo12:tempy2]
+	ldr	x17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-287.d b/ld/testsuite/ld-aarch64/emit-relocs-287.d
new file mode 100644
index 0000000..4d5fd43
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-287.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-287.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 --defsym _GOT_=0x10000 -e0 --emit-relocs
+#objdump: -dr
+
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	d2820004 	movz	x4, #0x1000
+	+10008: R_AARCH64_MOVW_PREL_G0	_GOT_
+ +1000c:	d28a0007 	movz	x7, #0x5000
+	+1000c: R_AARCH64_MOVW_PREL_G0	_GOT_
+ +10010:	d2824691 	movz	x17, #0x1234
+	+10010: R_AARCH64_MOVW_PREL_G0	_GOT_
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-287.s b/ld/testsuite/ld-aarch64/emit-relocs-287.s
new file mode 100644
index 0000000..ae9476f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-287.s
@@ -0,0 +1,9 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        movz	x4, :prel_g0:tempy
+	movz	x7, :prel_g0:tempy2
+	movz	x17, :prel_g0:tempy3
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-299.d b/ld/testsuite/ld-aarch64/emit-relocs-299.d
new file mode 100644
index 0000000..d24b442
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-299.d
@@ -0,0 +1,12 @@
+#source: emit-relocs-299.s
+#ld: -T relocs.ld --defsym tempy=0x11030 --defsym tempy2=0x45fa0 --defsym tempy3=0x1230  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	3dc00c64 	ldr	q4, \[x3,.*
+	+10008: R_AARCH64_LDST128_ABS_LO12_NC	tempy
+ +1000c:	3dc3e867 	ldr	q7, \[x3,.*
+	+1000c: R_AARCH64_LDST128_ABS_LO12_NC	tempy2
+ +10010:	3dc08c71 	ldr	q17, \[x3,.*
+	+10010: R_AARCH64_LDST128_ABS_LO12_NC	tempy3
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-299.s b/ld/testsuite/ld-aarch64/emit-relocs-299.s
new file mode 100644
index 0000000..b1fe6cf
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-299.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+	ldr     q4, [x3, #:lo12:tempy]
+	ldr	q7, [x3, #:lo12:tempy2]
+	ldr	q17, [x3, #:lo12:tempy3]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-311.d b/ld/testsuite/ld-aarch64/emit-relocs-311.d
new file mode 100644
index 0000000..5f1b47f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-311.d
@@ -0,0 +1,14 @@
+#source: emit-relocs-311.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234 -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	b0000002 	adrp	x2, 11000 <tempy>
+	+10008: R_AARCH64_ADR_PREL_PG_HI21	tempy
+ +1000c:	b00001a7 	adrp	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_ADR_PREL_PG_HI21	tempy2
+ +10010:	b0ffff91 	adrp	x17, 1000 <tempy3-0x234>
+	+10010: R_AARCH64_ADR_PREL_PG_HI21	tempy3
+ +10014:	90000083 	adrp	x3, 20000 <tempy[+]0xf000>
+	+10014: R_AARCH64_ADR_GOT_PAGE	gempy
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-311.s b/ld/testsuite/ld-aarch64/emit-relocs-311.s
new file mode 100644
index 0000000..182f0d4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-311.s
@@ -0,0 +1,8 @@
+.comm   gempy,4,4
+.text
+	and	x0,x0,x0
+	and	x0,x0,#1
+	adrp    x2,tempy
+	adrp	x7,tempy2
+	adrp	x17,tempy3
+        adrp	x3,:got:gempy
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-312.d b/ld/testsuite/ld-aarch64/emit-relocs-312.d
new file mode 100644
index 0000000..8d50d8d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-312.d
@@ -0,0 +1,19 @@
+#source: emit-relocs-312.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 --emit-relocs
+#objdump: -dr
+#...
+ +10000:	8a000000 	and	x0, x0, x0
+ +10004:	92400000 	and	x0, x0, #0x1
+ +10008:	58007fc4 	ldr	x4, 11000 <tempy>
+	+10008: R_AARCH64_LD_PREL_LO19	tempy
+ +1000c:	581a7fa7 	ldr	x7, 45000 <tempy2>
+	+1000c: R_AARCH64_LD_PREL_LO19	tempy2
+ +10010:	58f89131 	ldr	x17, 1234 <tempy3>
+	+10010: R_AARCH64_LD_PREL_LO19	tempy3
+ +10014:	f9400843 	ldr	x3, \[x2.*
+	+10014: R_AARCH64_LD64_GOT_LO12_NC	jempy
+ +10018:	f9400444 	ldr	x4, \[x2.*
+	+10018: R_AARCH64_LD64_GOT_LO12_NC	gempy
+ +1001c:	f9400045 	ldr	x5, \[x2.*
+	+1001c: R_AARCH64_LD64_GOT_LO12_NC	lempy
+
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-312.s b/ld/testsuite/ld-aarch64/emit-relocs-312.s
new file mode 100644
index 0000000..29494ee
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-312.s
@@ -0,0 +1,13 @@
+.comm   gempy,4
+.comm	jempy,4
+.comm	lempy,4
+.text
+
+	and	x0,x0,x0
+	and	x0,x0,#0x1
+        ldr     x4,tempy
+	ldr	x7,tempy2
+	ldr	x17,tempy3
+	ldr	x3, [x2, #:got_lo12:jempy]
+	ldr	x4, [x2, #:got_lo12:gempy]
+	ldr	x5, [x2, #:got_lo12:lempy]
diff --git a/ld/testsuite/ld-aarch64/emit-relocs1.s b/ld/testsuite/ld-aarch64/emit-relocs1.s
new file mode 100644
index 0000000..b249b6b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs1.s
@@ -0,0 +1,6 @@
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	and	x0,x0,x0
+	b	target
+	b	target+16
diff --git a/ld/testsuite/ld-aarch64/farcall-b-none-function.d b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
new file mode 100644
index 0000000..34a6568
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b-none-function.d
@@ -0,0 +1,5 @@
+#name: aarch64-farcall-b-none-function
+#source: farcall-b-none-function.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_JUMP26 against symbol `bar'.*
diff --git a/ld/testsuite/ld-aarch64/farcall-b-none-function.s b/ld/testsuite/ld-aarch64/farcall-b-none-function.s
new file mode 100644
index 0000000..5e5bc8d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b-none-function.s
@@ -0,0 +1,16 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b.d b/ld/testsuite/ld-aarch64/farcall-b.d
new file mode 100644
index 0000000..f3cb5ef
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b.d
@@ -0,0 +1,22 @@
+#name: aarch64-farcall-b
+#source: farcall-b.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+ +1000:	14000002 	b	1008 <__bar_veneer>
+ +1004:	d65f03c0 	ret
+0000000000001008 <__bar_veneer>:
+    1008:	90040010 	adrp	x16, 8001000 <bar>
+    100c:	91000210 	add	x16, x16, #0x0
+    1010:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+0000000008001000 <bar>:
+ 8001000:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b.s b/ld/testsuite/ld-aarch64/farcall-b.s
new file mode 100644
index 0000000..8ab3103
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-b.s
@@ -0,0 +1,17 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-back.d b/ld/testsuite/ld-aarch64/farcall-back.d
new file mode 100644
index 0000000..9ff43b3
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-back.d
@@ -0,0 +1,72 @@
+#name: aarch64-farcall-back
+#source: farcall-back.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x100000000
+#notarget: aarch64_be-*-*
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+    1000:	14000412 	b	2048 <__bar1_veneer>
+    1004:	94000411 	bl	2048 <__bar1_veneer>
+    1008:	14000406 	b	2020 <__bar2_veneer>
+    100c:	94000405 	bl	2020 <__bar2_veneer>
+    1010:	14000408 	b	2030 <__bar3_veneer>
+    1014:	94000407 	bl	2030 <__bar3_veneer>
+    1018:	d65f03c0 	ret
+	...
+
+000000000000201c <_back>:
+    201c:	d65f03c0 	ret
+
+0000000000002020 <__bar2_veneer>:
+    2020:	f07ffff0 	adrp	x16, 100001000 <bar1\+0x1000>
+    2024:	91002210 	add	x16, x16, #0x8
+    2028:	d61f0200 	br	x16
+    202c:	00000000 	.inst	0x00000000 ; undefined
+
+0000000000002030 <__bar3_veneer>:
+    2030:	58000090 	ldr	x16, 2040 <__bar3_veneer\+0x10>
+    2034:	10000011 	adr	x17, 2034 <__bar3_veneer\+0x4>
+    2038:	8b110210 	add	x16, x16, x17
+    203c:	d61f0200 	br	x16
+    2040:	ffffffdc 	.word	0xffffffdc
+    2044:	00000000 	.word	0x00000000
+
+0000000000002048 <__bar1_veneer>:
+    2048:	d07ffff0 	adrp	x16, 100000000 <bar1>
+    204c:	91000210 	add	x16, x16, #0x0
+    2050:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+0000000100000000 <bar1>:
+   100000000:	d65f03c0 	ret
+   100000004:	14000805 	b	100002018 <___start_veneer>
+	...
+
+0000000100001008 <bar2>:
+   100001008:	d65f03c0 	ret
+   10000100c:	14000403 	b	100002018 <___start_veneer>
+	...
+
+0000000100002010 <bar3>:
+   100002010:	d65f03c0 	ret
+   100002014:	14000007 	b	100002030 <___back_veneer>
+
+0000000100002018 <___start_veneer>:
+   100002018:	58000090 	ldr	x16, 100002028 <___start_veneer\+0x10>
+   10000201c:	10000011 	adr	x17, 10000201c <___start_veneer\+0x4>
+   100002020:	8b110210 	add	x16, x16, x17
+   100002024:	d61f0200 	br	x16
+   100002028:	ffffefe4 	.word	0xffffefe4
+   10000202c:	fffffffe 	.word	0xfffffffe
+
+0000000100002030 <___back_veneer>:
+   100002030:	90800010 	adrp	x16, 2000 <_start\+0x1000>
+   100002034:	91007210 	add	x16, x16, #0x1c
+   100002038:	d61f0200 	br	x16
+	...
diff --git a/ld/testsuite/ld-aarch64/farcall-back.s b/ld/testsuite/ld-aarch64/farcall-back.s
new file mode 100644
index 0000000..d0a3bd5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-back.s
@@ -0,0 +1,42 @@
+	.global _start
+	.global _back
+	.global bar1
+	.global bar2
+	.global bar3
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+	.type _start, @function
+_start:
+	b	bar1
+	bl	bar1
+	b	bar2
+	bl	bar2
+	b	bar3
+	bl	bar3
+	ret
+	.space	0x1000
+	.type _back, @function
+_back:	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar1, @function
+bar1:
+	ret
+	b	_start
+
+	.space 0x1000
+	.type bar2, @function
+bar2:
+	ret
+	b	_start
+
+	.space 0x1000
+	.type bar3, @function
+bar3:
+	ret
+	b	_back
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-none-function.d b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
new file mode 100644
index 0000000..6ce9ca4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl-none-function.d
@@ -0,0 +1,5 @@
+#name: aarch64-farcall-bl-none-function
+#source: farcall-bl-none-function.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against symbol `bar'.*
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-none-function.s b/ld/testsuite/ld-aarch64/farcall-bl-none-function.s
new file mode 100644
index 0000000..89aa85a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl-none-function.s
@@ -0,0 +1,16 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl.d b/ld/testsuite/ld-aarch64/farcall-bl.d
new file mode 100644
index 0000000..2bdd2c4
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl.d
@@ -0,0 +1,23 @@
+#name: aarch64-farcall-bl
+#source: farcall-bl.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+ +1000:	94000002 	bl	1008 <__bar_veneer>
+ +1004:	d65f03c0 	ret
+
+0000000000001008 <__bar_veneer>:
+    1008:	90040010 	adrp	x16, 8001000 <bar>
+    100c:	91000210 	add	x16, x16, #0x0
+    1010:	d61f0200 	br	x16
+	...
+
+Disassembly of section .foo:
+
+0000000008001000 <bar>:
+ 8001000:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl.s b/ld/testsuite/ld-aarch64/farcall-bl.s
new file mode 100644
index 0000000..432b120
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-bl.s
@@ -0,0 +1,17 @@
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	ret
+
+# We will place the section .foo at 0x8001000.
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/farcall-section.d b/ld/testsuite/ld-aarch64/farcall-section.d
new file mode 100644
index 0000000..85775e1
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-section.d
@@ -0,0 +1,5 @@
+#name: Aarch64 farcall to symbol of type STT_SECTION
+#source: farcall-section.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001014
+#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against `.foo'
diff --git a/ld/testsuite/ld-aarch64/farcall-section.s b/ld/testsuite/ld-aarch64/farcall-section.s
new file mode 100644
index 0000000..86a070c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/farcall-section.s
@@ -0,0 +1,19 @@
+# Test to ensure that an Aarch64 call exceeding 128MB generates an error
+# if the destination is of type STT_SECTION (eg non-global symbol)
+
+	.global _start
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+
+# We will place the section .foo at 0x8001020.
+
+	.section .foo, "xa"
+
+bar:
+	ret
+
diff --git a/ld/testsuite/ld-aarch64/limit-b.d b/ld/testsuite/ld-aarch64/limit-b.d
new file mode 100644
index 0000000..95d4c8f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-b.d
@@ -0,0 +1,17 @@
+#name: aarch64-limit-b
+#source: limit-b.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8000ffc
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+    1000:	15ffffff 	b	8000ffc <bar>
+    1004:	d65f03c0 	ret
+
+Disassembly of section .foo:
+
+0000000008000ffc <bar>:
+ 8000ffc:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/limit-b.s b/ld/testsuite/ld-aarch64/limit-b.s
new file mode 100644
index 0000000..2b9f432
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-b.s
@@ -0,0 +1,19 @@
+# Test maximum encoding range of b
+
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	b bar
+	ret
+
+# We will place the section .foo at 0x8000ffc
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/limit-bl.d b/ld/testsuite/ld-aarch64/limit-bl.d
new file mode 100644
index 0000000..2eddeb7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-bl.d
@@ -0,0 +1,17 @@
+#name: aarch64-limit-bl
+#source: limit-bl.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8000ffc
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+0000000000001000 <_start>:
+    1000:	95ffffff 	bl	8000ffc <bar>
+    1004:	d65f03c0 	ret
+
+Disassembly of section .foo:
+
+0000000008000ffc <bar>:
+ 8000ffc:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/limit-bl.s b/ld/testsuite/ld-aarch64/limit-bl.s
new file mode 100644
index 0000000..72f47a5
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/limit-bl.s
@@ -0,0 +1,19 @@
+# Test maximum encoding range of bl
+
+	.global _start
+	.global bar
+
+# We will place the section .text at 0x1000.
+
+	.text
+
+_start:
+	bl bar
+	ret
+
+# We will place the section .foo at 0x8000ffc
+
+	.section .foo, "xa"
+	.type bar, @function
+bar:
+	ret
diff --git a/ld/testsuite/ld-aarch64/relocs.ld b/ld/testsuite/ld-aarch64/relocs.ld
new file mode 100644
index 0000000..f42176e
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/relocs.ld
@@ -0,0 +1,19 @@
+/* Script for ld testsuite */
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x8000); . = 0x10000;
+  .text           :
+  {
+    *(.before)
+    *(.text)
+    *(.after)
+  } =0
+  . = 0x20000;
+  .got            : { *(.got) *(.got.plt)}
+  . = 0x12340000;
+  .far : { *(.far) }
+  .ARM.attributes 0 : { *(.ARM.atttributes) }
+}
diff --git a/ld/testsuite/ld-aarch64/tls-desc-ie.d b/ld/testsuite/ld-aarch64/tls-desc-ie.d
new file mode 100644
index 0000000..712e39c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-desc-ie.d
@@ -0,0 +1,36 @@
+#source: tls-desc-ie.s
+#ld: -shared -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10004:	91002000 	add	x0, x0, #0x8
+ +10008:	94000016 	bl	10060 <v1\+0x10060>
+ +1000c:	d503201f 	nop
+ +10010:	90000080 	adrp	x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10014:	f9400000 	ldr	x0, \[x0\]
+ +10018:	d503201f 	nop
+ +1001c:	d503201f 	nop
+ +10020:	d53bd041 	mrs	x1, tpidr_el0
+ +10024:	8b000020 	add	x0, x1, x0
+ +10028:	d53bd042 	mrs	x2, tpidr_el0
+ +1002c:	90000080 	adrp	x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10030:	f9400000 	ldr	x0, \[x0\]
+ +10034:	8b000040 	add	x0, x2, x0
+ +10038:	b9400000 	ldr	w0, \[x0\]
+ +1003c:	0b000020 	add	w0, w1, w0
+
+Disassembly of section .plt:
+
+0000000000010040 <.plt>:
+ +10040:	a9bf7bf0 	stp	x16, x30, \[sp,#-16\]!
+ +10044:	90000090 	adrp	x16, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10048:	f9401611 	ldr	x17, \[x16,#40\]
+ +1004c:	9100a210 	add	x16, x16, #0x28
+ +10050:	d61f0220 	br	x17
+ +10054:	d503201f 	nop
+ +10058:	d503201f 	nop
+ +1005c:	d503201f 	nop
+ +10060:	90000090 	adrp	x16, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10064:	f9401a11 	ldr	x17, \[x16,#48\]
+ +10068:	9100c210 	add	x16, x16, #0x30
+ +1006c:	d61f0220 	br	x17
diff --git a/ld/testsuite/ld-aarch64/tls-desc-ie.s b/ld/testsuite/ld-aarch64/tls-desc-ie.s
new file mode 100644
index 0000000..93fd71c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-desc-ie.s
@@ -0,0 +1,32 @@
+	.global	v1
+	.global	v2
+	.section	.tdata,"awT",%progbits
+v1:
+	.word	1
+
+	.text
+
+# This GD access does not relax. It consumes a double GOT slot.
+
+	adrp	x0, :tlsgd:v2
+	add	x0, x0, :tlsgd_lo12:v2
+	bl	__tls_get_addr
+	nop
+
+# Test the combination of a TLSDESC-GD and IE access to the same
+# symbol. We expect the TLSDESC-GD to relax to IE.
+
+	adrp	x0, :tlsdesc:v1
+	ldr	x1, [x0, #:tlsdesc_lo12:v1]
+	add	x0, x0, :tlsdesc_lo12:v1
+	.tlsdesccall	v1
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+
+	mrs	x2, tpidr_el0
+	adrp	x0, :gottprel:v1
+	ldr	x0, [x0, #:gottprel_lo12:v1]
+	add	x0, x2, x0
+	ldr	w0, [x0]
+	add	w0, w1, w0
diff --git a/ld/testsuite/ld-aarch64/tls-relax-all.d b/ld/testsuite/ld-aarch64/tls-relax-all.d
new file mode 100644
index 0000000..d3db04d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-all.d
@@ -0,0 +1,39 @@
+#source: tls-relax-all.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	a9bf7bfd 	stp	x29, x30, \[sp,#-16\]!
+ +10004:	910003fd 	mov	x29, sp
+ +10008:	90000080 	adrp	x0, 20000 <ie_var\+0x1fff0>
+ +1000c:	f9400000 	ldr	x0, \[x0\]
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d53bd041 	mrs	x1, tpidr_el0
+ +1001c:	8b000020 	add	x0, x1, x0
+ +10020:	b9400001 	ldr	w1, \[x0\]
+ +10024:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10028:	f2800280 	movk	x0, #0x14
+ +1002c:	d503201f 	nop
+ +10030:	d503201f 	nop
+ +10034:	d53bd042 	mrs	x2, tpidr_el0
+ +10038:	8b000040 	add	x0, x2, x0
+ +1003c:	b9400000 	ldr	w0, \[x0\]
+ +10040:	0b000021 	add	w1, w1, w0
+ +10044:	90000080 	adrp	x0, 20000 <ie_var\+0x1fff0>
+ +10048:	f9400400 	ldr	x0, \[x0,#8\]
+ +1004c:	d53bd041 	mrs	x1, tpidr_el0
+ +10050:	8b000020 	add	x0, x1, x0
+ +10054:	b9400000 	ldr	w0, \[x0\]
+ +10058:	0b000021 	add	w1, w1, w0
+ +1005c:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10060:	f2800380 	movk	x0, #0x1c
+ +10064:	d53bd041 	mrs	x1, tpidr_el0
+ +10068:	8b000020 	add	x0, x1, x0
+ +1006c:	b9400000 	ldr	w0, \[x0\]
+ +10070:	0b000021 	add	w1, w1, w0
+ +10074:	d53bd042 	mrs	x2, tpidr_el0
+ +10078:	d2a00000 	movz	x0, #0x0, lsl #16
+ +1007c:	f2800400 	movk	x0, #0x20
+ +10080:	8b000040 	add	x0, x2, x0
+ +10084:	b9400000 	ldr	w0, \[x0\]
+ +10088:	0b000020 	add	w0, w1, w0
diff --git a/ld/testsuite/ld-aarch64/tls-relax-all.s b/ld/testsuite/ld-aarch64/tls-relax-all.s
new file mode 100644
index 0000000..1bef53d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-all.s
@@ -0,0 +1,51 @@
+	.global	gdesc_var_1
+	.global	gd_var_1
+	.section	.tdata,"awT",%progbits
+gdesc_var_1:
+	.word	1
+gdesc_var_2:
+	.word	2
+gd_var_1:
+	.word	3
+gd_var_2:
+	.word	4
+ie_var:
+	.word	5
+	.text
+	stp	x29, x30, [sp, -16]!
+	add	x29, sp, 0
+	adrp	x0, :tlsdesc:gdesc_var_1
+	ldr	x1, [x0, #:tlsdesc_lo12:gdesc_var_1]
+	add	x0, x0, :tlsdesc_lo12:gdesc_var_1
+	.tlsdesccall	gdesc_var_1
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w1, [x0]
+	adrp	x0, :tlsdesc:gdesc_var_2
+	ldr	x2, [x0, #:tlsdesc_lo12:gdesc_var_2]
+	add	x0, x0, :tlsdesc_lo12:gdesc_var_2
+	.tlsdesccall	gdesc_var_2
+	blr	x2
+	mrs	x2, tpidr_el0
+	add	x0, x2, x0
+	ldr	w0, [x0]
+	add	w1, w1, w0
+	adrp	x0, :tlsgd:gd_var_1
+	add	x0, x0, :tlsgd_lo12:gd_var_1
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
+	add	w1, w1, w0
+	adrp	x0, :tlsgd:gd_var_2
+	add	x0, x0, :tlsgd_lo12:gd_var_2
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
+	add	w1, w1, w0
+	mrs	x2, tpidr_el0
+	adrp	x0, :gottprel:ie_var
+	ldr	x0, [x0, #:gottprel_lo12:ie_var]
+	add	x0, x2, x0
+	ldr	w0, [x0]
+	add	w0, w1, w0
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-ie.d b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.d
new file mode 100644
index 0000000..a142f54
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.d
@@ -0,0 +1,9 @@
+#source: tls-relax-gd-ie.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <var\+0x20000>
+ +10004:	f9400000 	ldr	x0, \[x0\]
+ +10008:	d53bd041 	mrs	x1, tpidr_el0
+ +1000c:	8b000020 	add	x0, x1, x0
+ +10010:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-ie.s b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.s
new file mode 100644
index 0000000..88c7eec
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-ie.s
@@ -0,0 +1,10 @@
+	.global	var
+	.section	.tdata,"awT",%progbits
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsgd:var
+	add	x0, x0, :tlsgd_lo12:var
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-le.d b/ld/testsuite/ld-aarch64/tls-relax-gd-le.d
new file mode 100644
index 0000000..b5ee39c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-le.d
@@ -0,0 +1,9 @@
+#source: tls-relax-gd-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10004:	f2800200 	movk	x0, #0x10
+ +10008:	d53bd041 	mrs	x1, tpidr_el0
+ +1000c:	8b000020 	add	x0, x1, x0
+ +10010:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-le.s b/ld/testsuite/ld-aarch64/tls-relax-gd-le.s
new file mode 100644
index 0000000..eb6fc2f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-le.s
@@ -0,0 +1,9 @@
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsgd:var
+	add	x0, x0, :tlsgd_lo12:var
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d
new file mode 100644
index 0000000..f3307ae
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.d
@@ -0,0 +1,18 @@
+#source: tls-relax-gdesc-ie-2.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <var\+0x20000>
+ +10004:	d503201f 	nop
+ +10008:	f9400000 	ldr	x0, \[x0\]
+ +1000c:	d503201f 	nop
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d503201f 	nop
+ +1001c:	d503201f 	nop
+ +10020:	d503201f 	nop
+ +10024:	d503201f 	nop
+ +10028:	d503201f 	nop
+ +1002c:	d53bd041 	mrs	x1, tpidr_el0
+ +10030:	8b000020 	add	x0, x1, x0
+ +10034:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s
new file mode 100644
index 0000000..790b6c6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie-2.s
@@ -0,0 +1,24 @@
+// Test TLS Desc to TLS IE relaxation when instructions are not consecutive.
+
+	.global	var
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	nop
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	nop
+	nop
+	nop
+	add	x0, x0, :tlsdesc_lo12:var
+	nop
+	nop
+	.tlsdesccall	var
+	blr	x1
+	nop
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
+	.global	var
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d
new file mode 100644
index 0000000..691df06
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.d
@@ -0,0 +1,11 @@
+#source: tls-relax-gdesc-ie.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	90000080 	adrp	x0, 20000 <var\+0x20000>
+ +10004:	f9400000 	ldr	x0, \[x0\]
+ +10008:	d503201f 	nop
+ +1000c:	d503201f 	nop
+ +10010:	d53bd041 	mrs	x1, tpidr_el0
+ +10014:	8b000020 	add	x0, x1, x0
+ +10018:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
new file mode 100644
index 0000000..c20690c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
@@ -0,0 +1,13 @@
+	.global	var
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	add	x0, x0, :tlsdesc_lo12:var
+	.tlsdesccall	var
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.d
new file mode 100644
index 0000000..3c028e2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.d
@@ -0,0 +1,18 @@
+#source: tls-relax-gdesc-le-2.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10004:	d503201f 	nop
+ +10008:	d503201f 	nop
+ +1000c:	f2800200 	movk	x0, #0x10
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d503201f 	nop
+ +1001c:	d503201f 	nop
+ +10020:	d503201f 	nop
+ +10024:	d503201f 	nop
+ +10028:	d503201f 	nop
+ +1002c:	d53bd041 	mrs	x1, tpidr_el0
+ +10030:	8b000020 	add	x0, x1, x0
+ +10034:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.s
new file mode 100644
index 0000000..fb8bf66
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le-2.s
@@ -0,0 +1,22 @@
+# Test TLS Desc to TLS LE relaxation when instructions are not consecutive.
+
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	nop
+	nop
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	nop
+	add	x0, x0, :tlsdesc_lo12:var
+	nop
+	nop
+	nop
+	.tlsdesccall	var
+	blr	x1
+	nop
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.d b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.d
new file mode 100644
index 0000000..afe0a56
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.d
@@ -0,0 +1,11 @@
+#source: tls-relax-gdesc-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10004:	f2800200 	movk	x0, #0x10
+ +10008:	d503201f 	nop
+ +1000c:	d503201f 	nop
+ +10010:	d53bd041 	mrs	x1, tpidr_el0
+ +10014:	8b000020 	add	x0, x1, x0
+ +10018:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.s
new file mode 100644
index 0000000..28ee0f6
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-le.s
@@ -0,0 +1,12 @@
+	.section	.tdata
+var:
+	.word	2
+	.text
+	adrp	x0, :tlsdesc:var
+	ldr	x1, [x0, #:tlsdesc_lo12:var]
+	add	x0, x0, :tlsdesc_lo12:var
+	.tlsdesccall	var
+	blr	x1
+	mrs	x1, tpidr_el0
+	add	x0, x1, x0
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.d
new file mode 100644
index 0000000..2f93955
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.d
@@ -0,0 +1,17 @@
+#source: tls-relax-ie-le-2.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d53bd041 	mrs	x1, tpidr_el0
+ +10004:	d503201f 	nop
+ +10008:	d503201f 	nop
+ +1000c:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10010:	d503201f 	nop
+ +10014:	d503201f 	nop
+ +10018:	d503201f 	nop
+ +1001c:	f2800200 	movk	x0, #0x10
+ +10020:	d503201f 	nop
+ +10024:	8b000020 	add	x0, x1, x0
+ +10028:	d503201f 	nop
+ +1002c:	d503201f 	nop
+ +10030:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.s
new file mode 100644
index 0000000..98b62e2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-2.s
@@ -0,0 +1,20 @@
+# Test TLS IE to TLS LE relaxation when instructions are not consecutive.
+
+	.section	.tdata
+var:
+	.word	2
+	.text
+	mrs	x1, tpidr_el0
+	nop
+	nop
+	adrp	x0, :gottprel:var
+	nop
+	nop
+	nop
+	ldr	x0, [x0, #:gottprel_lo12:var]
+	nop
+	add	x0, x1, x0
+	nop
+	nop
+	ldr	w0, [x0]
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.d
new file mode 100644
index 0000000..a2fd823
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.d
@@ -0,0 +1,9 @@
+#source: tls-relax-ie-le-3.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d53bd042 	mrs	x2, tpidr_el0
+ +10004:	d2a0000f 	movz	x15, #0x0, lsl #16
+ +10008:	f280020f 	movk	x15, #0x10
+ +1000c:	8b0f004f 	add	x15, x2, x15
+ +10010:	b94001e0 	ldr	w0, \[x15\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.s
new file mode 100644
index 0000000..70e7062
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le-3.s
@@ -0,0 +1,12 @@
+# Test TLS IE to TLS LE relaxation when using arbitrary registers.
+
+	.section	.tdata
+var:
+	.word	2
+	.text
+	mrs	x2, tpidr_el0
+	adrp	x15, :gottprel:var
+	ldr	x15, [x15, #:gottprel_lo12:var]
+	add	x15, x2, x15
+	ldr	w0, [x15]
+	.section	.tdata
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le.d b/ld/testsuite/ld-aarch64/tls-relax-ie-le.d
new file mode 100644
index 0000000..ff3b344
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le.d
@@ -0,0 +1,9 @@
+#source: tls-relax-ie-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	d53bd041 	mrs	x1, tpidr_el0
+ +10004:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10008:	f2800200 	movk	x0, #0x10
+ +1000c:	8b000020 	add	x0, x1, x0
+ +10010:	b9400000 	ldr	w0, \[x0\]
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ie-le.s b/ld/testsuite/ld-aarch64/tls-relax-ie-le.s
new file mode 100644
index 0000000..093cda2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ie-le.s
@@ -0,0 +1,9 @@
+	.section	.tdata
+var:
+	.word	2
+	.text
+	mrs	x1, tpidr_el0
+	adrp	x0, :gottprel:var
+	ldr	x0, [x0, #:gottprel_lo12:var]
+	add	x0, x1, x0
+	ldr	w0, [x0]
diff --git a/ld/testsuite/ld-aarch64/weak-undefined.d b/ld/testsuite/ld-aarch64/weak-undefined.d
new file mode 100644
index 0000000..22a9860
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/weak-undefined.d
@@ -0,0 +1,18 @@
+#source: weak-undefined.s
+#ld: -Ttext 0xF0000000 -T relocs.ld -e0 --emit-relocs
+#objdump: -d
+#...
+ +f0000000:	54000001 	b\.ne	f0000000 <main>
+ +f0000004:	54000000 	b\.eq	f0000004 <main\+0x4>
+ +f0000008:	54000002 	b\.cs	f0000008 <main\+0x8>
+ +f000000c:	54000003 	b\.cc	f000000c <main\+0xc>
+ +f0000010:	5400000c 	b\.gt	f0000010 <main\+0x10>
+ +f0000014:	5400000a 	b\.ge	f0000014 <main\+0x14>
+ +f0000018:	5400000b 	b\.lt	f0000018 <main\+0x18>
+ +f000001c:	5400000d 	b\.le	f000001c <main\+0x1c>
+ +f0000020:	d503201f 	nop
+ +f0000024:	d503201f 	nop
+ +f0000028:	58000000 	ldr	x0, f0000028 <main\+0x28>
+ +f000002c:	10000000 	adr	x0, f000002c <main\+0x2c>
+ +f0000030:	90000000 	adrp	x0, f0000000 <main>
+ +f0000034:	91000000 	add	x0, x0, #0x0
diff --git a/ld/testsuite/ld-aarch64/weak-undefined.s b/ld/testsuite/ld-aarch64/weak-undefined.s
new file mode 100644
index 0000000..692798f
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/weak-undefined.s
@@ -0,0 +1,18 @@
+.text
+	.weak foo
+	.global main
+main:
+	b.ne	foo
+	b.eq	foo
+	b.cs	foo
+	b.cc	foo
+	b.gt	foo
+	b.ge	foo
+	b.lt	foo
+	b.le	foo
+	b	foo
+	bl	foo
+	ldr	x0, foo
+	adr	x0, foo
+	adrp	x0, foo
+	add	x0, x0, :lo12:foo
diff --git a/ld/testsuite/ld-elf/binutils.exp b/ld/testsuite/ld-elf/binutils.exp
index 4d91105..249fa2a 100644
--- a/ld/testsuite/ld-elf/binutils.exp
+++ b/ld/testsuite/ld-elf/binutils.exp
@@ -34,7 +34,12 @@ if { [istarget *-*-linux*aout*]
     return
 }
 
-proc binutils_test { prog_name ld_options test } {
+# The optional test_name argument provides a mechanism for the caller
+# to hardwire the test name. This is important if ld_options contains
+# absolute path names because the default test name is constructed
+# from the prog_name and ld_options and we do not want absolute paths
+# to appear in the test_name.
+proc binutils_test { prog_name ld_options test {test_name ""}} {
     global as
     global ld
     global READELF
@@ -45,7 +50,10 @@ proc binutils_test { prog_name ld_options test } {
     global link_output
 
     eval set prog \$$prog_name
-    set test_name "$prog_name $ld_options ($test)"
+
+    if { "$test_name" == "" } {
+      set test_name "$prog_name $ld_options ($test)"
+    }
 
     if { ![ld_assemble $as $srcdir/$subdir/$test.s tmpdir/$test.o ] } {
 	unresolved "$test_name"
@@ -123,7 +131,7 @@ if { ([istarget "i?86-*-elf*"]
     binutils_test objcopy "-z relro -shared" relro2
 }
 
-binutils_test strip "-T ${srcdir}/${subdir}/lma.lnk" lma
+binutils_test strip "-T ${srcdir}/${subdir}/lma.lnk" lma "strip -T lma.lnk"
 
 set tls_tests { "tdata1" "tdata2" }
 # hppa64 has its own .tbss section, with different flags.
diff --git a/ld/testsuite/ld-elf/group8a.d b/ld/testsuite/ld-elf/group8a.d
index bad4123..753eb0f 100644
--- a/ld/testsuite/ld-elf/group8a.d
+++ b/ld/testsuite/ld-elf/group8a.d
@@ -1,7 +1,7 @@
 #source: group8.s
 #ld: -r --gc-sections --entry foo
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/group8b.d b/ld/testsuite/ld-elf/group8b.d
index fb37198..107ff69 100644
--- a/ld/testsuite/ld-elf/group8b.d
+++ b/ld/testsuite/ld-elf/group8b.d
@@ -1,7 +1,7 @@
 #source: group8.s
 #ld: -r --gc-sections --entry bar
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/group9a.d b/ld/testsuite/ld-elf/group9a.d
index fd04c48..511cec7 100644
--- a/ld/testsuite/ld-elf/group9a.d
+++ b/ld/testsuite/ld-elf/group9a.d
@@ -1,7 +1,7 @@
 #source: group9.s
 #ld: -r --gc-sections --entry foo
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: alpha-*-* hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/group9b.d b/ld/testsuite/ld-elf/group9b.d
index 3f19fd6..fd5b0c2 100644
--- a/ld/testsuite/ld-elf/group9b.d
+++ b/ld/testsuite/ld-elf/group9b.d
@@ -1,7 +1,7 @@
 #source: group9.s
 #ld: -r --gc-sections --entry bar
 #readelf: -g --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: alpha-*-* hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 #xfail: cr16-*-* crx-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
diff --git a/ld/testsuite/ld-elf/pr12851.d b/ld/testsuite/ld-elf/pr12851.d
index fb61c5a..9160142 100644
--- a/ld/testsuite/ld-elf/pr12851.d
+++ b/ld/testsuite/ld-elf/pr12851.d
@@ -2,7 +2,7 @@
 #source: start.s
 #ld: --gc-sections
 #readelf: -s --wide
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elf/pr12975.d b/ld/testsuite/ld-elf/pr12975.d
index b361cc2..abdb571 100644
--- a/ld/testsuite/ld-elf/pr12975.d
+++ b/ld/testsuite/ld-elf/pr12975.d
@@ -1,7 +1,7 @@
 #ld: --gc-sections -shared -version-script pr12975.t
 #readelf: -s --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elf/pr13177.d b/ld/testsuite/ld-elf/pr13177.d
index e56e865..f32e15d 100644
--- a/ld/testsuite/ld-elf/pr13177.d
+++ b/ld/testsuite/ld-elf/pr13177.d
@@ -2,7 +2,7 @@
 #ld: --gc-sections -shared
 #readelf: -s -D --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elf/pr13195.d b/ld/testsuite/ld-elf/pr13195.d
index 796102b..88c6278 100644
--- a/ld/testsuite/ld-elf/pr13195.d
+++ b/ld/testsuite/ld-elf/pr13195.d
@@ -1,7 +1,7 @@
 #ld: --gc-sections -shared -version-script pr13195.t
 #readelf: -s --wide -D
 #target: *-*-linux* *-*-gnu*
-#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
+#notarget: aarch64*-*-* arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-*
 #notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
diff --git a/ld/testsuite/ld-elfvers/vers.exp b/ld/testsuite/ld-elfvers/vers.exp
index 4bea6e4..1e9ff53 100644
--- a/ld/testsuite/ld-elfvers/vers.exp
+++ b/ld/testsuite/ld-elfvers/vers.exp
@@ -47,6 +47,7 @@ if { ![istarget hppa*64*-*-hpux*]
      && ![istarget sparc*-*-elf]
      && ![istarget sparc*-*-solaris2*]
      && ![istarget sparc*-*-linux*]
+     && ![istarget aarch64*-*-linux*]
      && ![istarget arm*-*-linux*]
      && ![istarget mips*-*-linux*]
      && ![istarget alpha*-*-linux*]
diff --git a/ld/testsuite/ld-shared/shared.exp b/ld/testsuite/ld-shared/shared.exp
index 7ec304b..07fc881 100644
--- a/ld/testsuite/ld-shared/shared.exp
+++ b/ld/testsuite/ld-shared/shared.exp
@@ -57,6 +57,7 @@ if { ![istarget hppa*64*-*-hpux*] \
      && ![istarget rs6000*-*-aix*] \
      && ![istarget powerpc*-*-aix*] \
      && ![istarget s390*-*-linux*] \
+     && ![istarget aarch64*-*-linux*] \
      && ![istarget x86_64-*-linux*] } {
     return
 }
diff --git a/ld/testsuite/ld-srec/srec.exp b/ld/testsuite/ld-srec/srec.exp
index 7f13e9c..001fb2e 100644
--- a/ld/testsuite/ld-srec/srec.exp
+++ b/ld/testsuite/ld-srec/srec.exp
@@ -250,9 +250,12 @@ proc run_srec_test { test objs } {
 	setup_xfail "sh64*-*-*"
     }
 
-    if {[istarget arm*-*-*]} {
-        # ARM targets cannot convert format in the linker 
+    if {[istarget aarch64*-*-*]   || \
+        [istarget arm*-*-*]} {
+        # ARM targets cannot convert format in the linker
         # using the --oformat command line switch
+	setup_xfail "aarch64-*-*"
+	setup_xfail "aarch64_be-*-*"
 	setup_xfail "arm*-*-*"
     }
 
diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp
index a481ce7..f05d42c 100644
--- a/ld/testsuite/lib/ld-lib.exp
+++ b/ld/testsuite/lib/ld-lib.exp
@@ -1459,7 +1459,8 @@ proc check_gc_sections_available { } {
     if {![info exists gc_sections_available_saved]} {
 	# Some targets don't support gc-sections despite whatever's
 	# advertised by ld's options.
-	if {[istarget arc-*-*]
+	if {[istarget aarch64*-*-*]
+	     || [istarget arc-*-*]
 	     || [istarget d30v-*-*]
 	     || [istarget dlx-*-*]
 	     || [istarget i960-*-*]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes v2
  2012-08-07 17:18   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes v2 Yufeng Zhang
@ 2012-08-13 14:56     ` nick clifton
  0 siblings, 0 replies; 41+ messages in thread
From: nick clifton @ 2012-08-13 14:56 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

Hi Yufeng,

> include/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>              Laurent Desnogues  <laurent.desnogues@arm.com>
>              Jim MacArthur  <jim.macarthur@arm.com>
>              Marcus Shawcroft  <marcus.shawcroft@arm.com>
>              Nigel Stephens  <nigel.stephens@arm.com>
>              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>              Richard Earnshaw  <rearnsha@arm.com>
>              Sofiane Naci  <sofiane.naci@arm.com>
>              Tejas Belagod  <tejas.belagod@arm.com>
>              Yufeng Zhang  <yufeng.zhang@arm.com>
>
>          * dis-asm.h (print_insn_aarch64): New declaration.
>          (print_aarch64_disassembler_options): New declaration.
>          (aarch64_symbol_is_valid): New declaration.
>
>
> include/opcode/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>              Laurent Desnogues  <laurent.desnogues@arm.com>
>              Jim MacArthur  <jim.macarthur@arm.com>
>              Marcus Shawcroft  <marcus.shawcroft@arm.com>
>              Nigel Stephens  <nigel.stephens@arm.com>
>              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>              Richard Earnshaw  <rearnsha@arm.com>
>              Sofiane Naci  <sofiane.naci@arm.com>
>              Tejas Belagod  <tejas.belagod@arm.com>
>              Yufeng Zhang  <yufeng.zhang@arm.com>
>
>          * aarch64.h: New file.
>
>
> opcodes/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>              Laurent Desnogues  <laurent.desnogues@arm.com>
>              Jim MacArthur  <jim.macarthur@arm.com>
>              Marcus Shawcroft  <marcus.shawcroft@arm.com>
>              Nigel Stephens  <nigel.stephens@arm.com>
>              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>              Richard Earnshaw  <rearnsha@arm.com>
>              Sofiane Naci  <sofiane.naci@arm.com>
>              Tejas Belagod  <tejas.belagod@arm.com>
>              Yufeng Zhang  <yufeng.zhang@arm.com>
>
>          * Makefile.am: Add AArch64.
>          * Makefile.in: Regenerate.
>          * aarch64-asm.c: New file.
>          * aarch64-asm.h: New file.
>          * aarch64-dis.c: New file.
>          * aarch64-dis.h: New file.
>          * aarch64-gen.c: New file.
>          * aarch64-opc.c: New file.
>          * aarch64-opc.h: New file.
>          * aarch64-tbl.h: New file.
>          * configure.in: Add AArch64.
>          * configure: Regenerate.
>          * disassemble.c: Add AArch64.
>          * aarch64-asm-2.c: New file (automatically generated).
>          * aarch64-dis-2.c: New file (automatically generated).
>          * aarch64-opc-2.c: New file (automatically generated).
>          * po/POTFILES.in: Regenerate.

Approved and applied.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes v2
  2012-08-07 17:19   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes v2 Yufeng Zhang
  2012-08-08 12:18     ` Benedikt Schroefel
@ 2012-08-13 14:57     ` nick clifton
  1 sibling, 0 replies; 41+ messages in thread
From: nick clifton @ 2012-08-13 14:57 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

Hi Yufeng,

> include/elf/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>              Laurent Desnogues  <laurent.desnogues@arm.com>
>              Jim MacArthur  <jim.macarthur@arm.com>
>              Marcus Shawcroft  <marcus.shawcroft@arm.com>
>              Nigel Stephens  <nigel.stephens@arm.com>
>              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>              Richard Earnshaw  <rearnsha@arm.com>
>              Sofiane Naci  <sofiane.naci@arm.com>
>              Tejas Belagod  <tejas.belagod@arm.com>
>              Yufeng Zhang  <yufeng.zhang@arm.com>
>
>          * aarch64.h: New file.
>          * common.h (EM_res183): Rename to EM_AARCH64.
>          (EM_res184): Rename to EM_ARM184.
>
>
> bfd/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>              Laurent Desnogues  <laurent.desnogues@arm.com>
>              Jim MacArthur  <jim.macarthur@arm.com>
>              Marcus Shawcroft  <marcus.shawcroft@arm.com>
>              Nigel Stephens  <nigel.stephens@arm.com>
>              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>              Richard Earnshaw  <rearnsha@arm.com>
>              Sofiane Naci  <sofiane.naci@arm.com>
>              Tejas Belagod  <tejas.belagod@arm.com>
>              Yufeng Zhang  <yufeng.zhang@arm.com>
>
>          * Makefile.am: Add AArch64 files.
>          * Makefile.in: Regenerate.
>          * archures.c (bfd_aarch64_arch): New declaration.
>          (bfd_archures_list): Use bfd_archures_list.
>          * bfd-in.h (bfd_elf64_aarch64_init_maps): New declaration.
>          (bfd_aarch64_process_before_allocation): New declaration.
>          (bfd_elf64_aarch64_process_before_allocation): New declaration.
>          (bfd_elf64_aarch64_set_options): New declaration.
>          (bfd_elf64_aarch64_add_glue_sections_to_bfd): New declaration.
>          (BFD_AARCH64_SPECIAL_SYM_TYPE_MAP): New definition.
>          (BFD_AARCH64_SPECIAL_SYM_TYPE_TAG): New definition.
>          (BFD_AARCH64_SPECIAL_SYM_TYPE_OTHER): New definition.
>          (BFD_AARCH64_SPECIAL_SYM_TYPE_ANY): New definition.
>          (bfd_is_aarch64_special_symbol_name): New declaration.
>          (bfd_aarch64_merge_machines): New declaration.
>          (bfd_aarch64_update_notes): New declaration.
>          (int bfd_aarch64_get_mach_from_notes): New declaration.
>          (elf64_aarch64_setup_section_lists): New declaration.
>          (elf64_aarch64_next_input_section): New declaration.
>          (elf64_aarch64_size_stubs): New declaration.
>          (elf64_aarch64_build_stubs): New declaration.
>          * config.bfd: Add AArch64.
>          * configure.in: Add AArch64.
>          * configure: Regenerate.
>          * cpu-aarch64.c: New file.
>          * elf-bfd.h: Add AArch64.
>          * bfd-in2.h: Regenerate.
>          * libbfd.h: Regenerate.
>          * elf64-aarch64.c: New file.
>          * reloc.c: Add AArch64 relocations.
>          * targets.c: Add AArch64.
>          * po/SRC-POTFILES.in: Regenerate.

Approved and applied.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes v2
  2012-08-07 17:29   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes v2 Yufeng Zhang
@ 2012-08-13 14:58     ` nick clifton
  0 siblings, 0 replies; 41+ messages in thread
From: nick clifton @ 2012-08-13 14:58 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils

Hi Yufeng,

> gas/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>              Laurent Desnogues  <laurent.desnogues@arm.com>
>              Jim MacArthur  <jim.macarthur@arm.com>
>              Marcus Shawcroft  <marcus.shawcroft@arm.com>
>              Nigel Stephens  <nigel.stephens@arm.com>
>              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>              Richard Earnshaw  <rearnsha@arm.com>
>              Sofiane Naci  <sofiane.naci@arm.com>
>              Tejas Belagod  <tejas.belagod@arm.com>
>              Yufeng Zhang  <yufeng.zhang@arm.com>
>
>          * Makefile.am: Add AArch64.
>          * Makefile.in: Regenerate.
>          * config/tc-aarch64.c: New file.
>          * config/tc-aarch64.h: New file.
>          * configure.tgt: Add AArch64.
>          * doc/Makefile.am: Add AArch64.
>          * doc/Makefile.in: Regenerate.
>          * doc/all.texi: Add AArch64.
>          * doc/as.texinfo: Add AArch64.
>          * doc/c-aarch64.texi: New file.
>          * po/POTFILES.in: Regenerate.
>
>
> gas/testsuite/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>              Laurent Desnogues  <laurent.desnogues@arm.com>
>              Jim MacArthur  <jim.macarthur@arm.com>
>              Marcus Shawcroft  <marcus.shawcroft@arm.com>
>              Nigel Stephens  <nigel.stephens@arm.com>
>              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>              Richard Earnshaw  <rearnsha@arm.com>
>              Sofiane Naci  <sofiane.naci@arm.com>
>              Tejas Belagod  <tejas.belagod@arm.com>
>              Yufeng Zhang  <yufeng.zhang@arm.com>
>
>          * gas/aarch64/aarch64.exp: New file.
>          * gas/aarch64/addsub.d: New file.
>          * gas/aarch64/addsub.s: New file.
>          * gas/aarch64/advsimd-across.d: New file.
>          * gas/aarch64/advsimd-across.s: New file.
>          * gas/aarch64/advsimd-misc.d: New file.
>          * gas/aarch64/advsimd-misc.s: New file.
>          * gas/aarch64/advsisd-copy.d: New file.
>          * gas/aarch64/advsisd-copy.s: New file.
>          * gas/aarch64/advsisd-misc.d: New file.
>          * gas/aarch64/advsisd-misc.s: New file.
>          * gas/aarch64/alias.d: New file.
>          * gas/aarch64/alias.s: New file.
>          * gas/aarch64/bitfield-alias.d: New file.
>          * gas/aarch64/bitfield-alias.s: New file.
>          * gas/aarch64/bitfield-bfm.d: New file.
>          * gas/aarch64/bitfield-bfm.s: New file.
>          * gas/aarch64/bitfield-dump: New file.
>          * gas/aarch64/bitfield-no-aliases.d: New file.
>          * gas/aarch64/crypto.d: New file.
>          * gas/aarch64/crypto.s: New file.
>          * gas/aarch64/diagnostic.d: New file.
>          * gas/aarch64/diagnostic.l: New file.
>          * gas/aarch64/diagnostic.s: New file.
>          * gas/aarch64/floatdp2.d: New file.
>          * gas/aarch64/floatdp2.s: New file.
>          * gas/aarch64/fp_cvt_int.d: New file.
>          * gas/aarch64/fp_cvt_int.s: New file.
>          * gas/aarch64/illegal-2.d: New file.
>          * gas/aarch64/illegal-2.l: New file.
>          * gas/aarch64/illegal-2.s: New file.
>          * gas/aarch64/illegal.d: New file.
>          * gas/aarch64/illegal.l: New file.
>          * gas/aarch64/illegal.s: New file.
>          * gas/aarch64/inst-directive.d: New file.
>          * gas/aarch64/inst-directive.s: New file.
>          * gas/aarch64/int-insns.d: New file.
>          * gas/aarch64/int-insns.s: New file.
>          * gas/aarch64/ldst-exclusive.d: New file.
>          * gas/aarch64/ldst-exclusive.s: New file.
>          * gas/aarch64/ldst-reg-imm-post-ind.d: New file.
>          * gas/aarch64/ldst-reg-imm-post-ind.s: New file.
>          * gas/aarch64/ldst-reg-imm-pre-ind.d: New file.
>          * gas/aarch64/ldst-reg-imm-pre-ind.s: New file.
>          * gas/aarch64/ldst-reg-pair.d: New file.
>          * gas/aarch64/ldst-reg-pair.s: New file.
>          * gas/aarch64/ldst-reg-reg-offset.d: New file.
>          * gas/aarch64/ldst-reg-reg-offset.s: New file.
>          * gas/aarch64/ldst-reg-uns-imm.d: New file.
>          * gas/aarch64/ldst-reg-uns-imm.s: New file.
>          * gas/aarch64/ldst-reg-unscaled-imm.d: New file.
>          * gas/aarch64/ldst-reg-unscaled-imm.s: New file.
>          * gas/aarch64/legacy_reg_names.d: New file.
>          * gas/aarch64/legacy_reg_names.l: New file.
>          * gas/aarch64/legacy_reg_names.s: New file.
>          * gas/aarch64/mapmisc.d: New file.
>          * gas/aarch64/mapmisc.dat: New file.
>          * gas/aarch64/mapmisc.s: New file.
>          * gas/aarch64/mapping.d: New file.
>          * gas/aarch64/mapping.s: New file.
>          * gas/aarch64/mapping2.d: New file.
>          * gas/aarch64/mapping2.s: New file.
>          * gas/aarch64/mapping3.d: New file.
>          * gas/aarch64/mapping3.s: New file.
>          * gas/aarch64/mapping4.d: New file.
>          * gas/aarch64/mapping4.s: New file.
>          * gas/aarch64/mov-no-aliases.d: New file.
>          * gas/aarch64/mov.d: New file.
>          * gas/aarch64/mov.s: New file.
>          * gas/aarch64/movi.d: New file.
>          * gas/aarch64/movi.s: New file.
>          * gas/aarch64/msr.d: New file.
>          * gas/aarch64/msr.s: New file.
>          * gas/aarch64/neon-fp-cvt-int.d: New file.
>          * gas/aarch64/neon-fp-cvt-int.s: New file.
>          * gas/aarch64/neon-frint.d: New file.
>          * gas/aarch64/neon-frint.s: New file.
>          * gas/aarch64/neon-ins.d: New file.
>          * gas/aarch64/neon-ins.s: New file.
>          * gas/aarch64/neon-not.d: New file.
>          * gas/aarch64/neon-not.s: New file.
>          * gas/aarch64/neon-vfp-reglist-post.d: New file.
>          * gas/aarch64/neon-vfp-reglist-post.s: New file.
>          * gas/aarch64/neon-vfp-reglist.d: New file.
>          * gas/aarch64/neon-vfp-reglist.s: New file.
>          * gas/aarch64/no-aliases.d: New file.
>          * gas/aarch64/optional.d: New file.
>          * gas/aarch64/optional.s: New file.
>          * gas/aarch64/programmer-friendly.d: New file.
>          * gas/aarch64/programmer-friendly.s: New file.
>          * gas/aarch64/reloc-data.d: New file.
>          * gas/aarch64/reloc-data.s: New file.
>          * gas/aarch64/reloc-insn.d: New file.
>          * gas/aarch64/reloc-insn.s: New file.
>          * gas/aarch64/shifted.d: New file.
>          * gas/aarch64/shifted.s: New file.
>          * gas/aarch64/symbol.d: New file.
>          * gas/aarch64/symbol.s: New file.
>          * gas/aarch64/sysreg-1.d: New file.
>          * gas/aarch64/sysreg-1.s: New file.
>          * gas/aarch64/sysreg.d: New file.
>          * gas/aarch64/sysreg.s: New file.
>          * gas/aarch64/system.d: New file.
>          * gas/aarch64/system.s: New file.
>          * gas/aarch64/tlbi_op.d: New file.
>          * gas/aarch64/tlbi_op.s: New file.
>          * gas/aarch64/tls.d: New file.
>          * gas/aarch64/tls.s: New file.
>          * gas/aarch64/verbose-error.d: New file.
>          * gas/aarch64/verbose-error.l: New file.
>          * gas/aarch64/verbose-error.s: New file.

Approved and applied.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2
  2012-08-07 17:34     ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2 Yufeng Zhang
  2012-08-09 17:37       ` nick clifton
@ 2012-08-13 14:58       ` nick clifton
  1 sibling, 0 replies; 41+ messages in thread
From: nick clifton @ 2012-08-13 14:58 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: Joseph S. Myers, binutils

Hi Yufeng,

> ld/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>               Laurent Desnogues  <laurent.desnogues@arm.com>
>               Jim MacArthur  <jim.macarthur@arm.com>
>               Marcus Shawcroft  <marcus.shawcroft@arm.com>
>               Nigel Stephens  <nigel.stephens@arm.com>
>               Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>               Richard Earnshaw  <rearnsha@arm.com>
>               Sofiane Naci  <sofiane.naci@arm.com>
>               Tejas Belagod  <tejas.belagod@arm.com>
>               Yufeng Zhang  <yufeng.zhang@arm.com>
>
>           * Makefile.am: Add AArch64.
>           * Makefile.in: Regenerate.
>           * configure.tgt: Add AArch64.
>           * emulparams/aarch64elf.sh: New file.
>           * emulparams/aarch64elfb.sh: New file.
>           * emulparams/aarch64linux.sh: New file.
>           * emulparams/aarch64linuxb.sh: New file.
>           * emultempl/aarch64elf.em: New file.
>
>
> ld/testsuite/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>               Laurent Desnogues  <laurent.desnogues@arm.com>
>               Jim MacArthur  <jim.macarthur@arm.com>
>               Marcus Shawcroft  <marcus.shawcroft@arm.com>
>               Nigel Stephens  <nigel.stephens@arm.com>
>               Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>               Richard Earnshaw  <rearnsha@arm.com>
>               Sofiane Naci  <sofiane.naci@arm.com>
>               Tejas Belagod  <tejas.belagod@arm.com>
>               Yufeng Zhang  <yufeng.zhang@arm.com>
>
>           * ld-aarch64/aarch64-elf.exp: New file.
>           * ld-aarch64/aarch64.ld: New file.
>           * ld-aarch64/eh-frame-bar.s: New file.
>           * ld-aarch64/eh-frame-foo.s: New file.
>           * ld-aarch64/eh-frame.d: New file.
>           * ld-aarch64/emit-relocs-257-be.d: New file.
>           * ld-aarch64/emit-relocs-257.d: New file.
>           * ld-aarch64/emit-relocs-257.s: New file.
>           * ld-aarch64/emit-relocs-260-be.d: New file.
>           * ld-aarch64/emit-relocs-260.d: New file.
>           * ld-aarch64/emit-relocs-260.s: New file.
>           * ld-aarch64/emit-relocs-262.d: New file.
>           * ld-aarch64/emit-relocs-262.s: New file.
>           * ld-aarch64/emit-relocs-263.d: New file.
>           * ld-aarch64/emit-relocs-263.s: New file.
>           * ld-aarch64/emit-relocs-264.d: New file.
>           * ld-aarch64/emit-relocs-264.s: New file.
>           * ld-aarch64/emit-relocs-265.d: New file.
>           * ld-aarch64/emit-relocs-265.s: New file.
>           * ld-aarch64/emit-relocs-266.d: New file.
>           * ld-aarch64/emit-relocs-266.s: New file.
>           * ld-aarch64/emit-relocs-267.d: New file.
>           * ld-aarch64/emit-relocs-267.s: New file.
>           * ld-aarch64/emit-relocs-268.d: New file.
>           * ld-aarch64/emit-relocs-268.s: New file.
>           * ld-aarch64/emit-relocs-269.d: New file.
>           * ld-aarch64/emit-relocs-269.s: New file.
>           * ld-aarch64/emit-relocs-270-bad.d: New file.
>           * ld-aarch64/emit-relocs-270.d: New file.
>           * ld-aarch64/emit-relocs-270.s: New file.
>           * ld-aarch64/emit-relocs-271.d: New file.
>           * ld-aarch64/emit-relocs-271.s: New file.
>           * ld-aarch64/emit-relocs-272.d: New file.
>           * ld-aarch64/emit-relocs-272.s: New file.
>           * ld-aarch64/emit-relocs-273.d: New file.
>           * ld-aarch64/emit-relocs-273.s: New file.
>           * ld-aarch64/emit-relocs-274.d: New file.
>           * ld-aarch64/emit-relocs-274.s: New file.
>           * ld-aarch64/emit-relocs-275.d: New file.
>           * ld-aarch64/emit-relocs-275.s: New file.
>           * ld-aarch64/emit-relocs-276.d: New file.
>           * ld-aarch64/emit-relocs-276.s: New file.
>           * ld-aarch64/emit-relocs-277.d: New file.
>           * ld-aarch64/emit-relocs-277.s: New file.
>           * ld-aarch64/emit-relocs-278.d: New file.
>           * ld-aarch64/emit-relocs-278.s: New file.
>           * ld-aarch64/emit-relocs-279-bad.d: New file.
>           * ld-aarch64/emit-relocs-279.d: New file.
>           * ld-aarch64/emit-relocs-279.s: New file.
>           * ld-aarch64/emit-relocs-280.d: New file.
>           * ld-aarch64/emit-relocs-280.s: New file.
>           * ld-aarch64/emit-relocs-282.d: New file.
>           * ld-aarch64/emit-relocs-282.s: New file.
>           * ld-aarch64/emit-relocs-283.d: New file.
>           * ld-aarch64/emit-relocs-283.s: New file.
>           * ld-aarch64/emit-relocs-284.d: New file.
>           * ld-aarch64/emit-relocs-284.s: New file.
>           * ld-aarch64/emit-relocs-285.d: New file.
>           * ld-aarch64/emit-relocs-285.s: New file.
>           * ld-aarch64/emit-relocs-286-bad.d: New file.
>           * ld-aarch64/emit-relocs-286.d: New file.
>           * ld-aarch64/emit-relocs-286.s: New file.
>           * ld-aarch64/emit-relocs-287.d: New file.
>           * ld-aarch64/emit-relocs-287.s: New file.
>           * ld-aarch64/emit-relocs-299.d: New file.
>           * ld-aarch64/emit-relocs-299.s: New file.
>           * ld-aarch64/emit-relocs-311.d: New file.
>           * ld-aarch64/emit-relocs-311.s: New file.
>           * ld-aarch64/emit-relocs-312.d: New file.
>           * ld-aarch64/emit-relocs-312.s: New file.
>           * ld-aarch64/emit-relocs1.s: New file.
>           * ld-aarch64/farcall-b-none-function.d: New file.
>           * ld-aarch64/farcall-b-none-function.s: New file.
>           * ld-aarch64/farcall-b.d: New file.
>           * ld-aarch64/farcall-b.s: New file.
>           * ld-aarch64/farcall-back.d: New file.
>           * ld-aarch64/farcall-back.s: New file.
>           * ld-aarch64/farcall-bl-none-function.d: New file.
>           * ld-aarch64/farcall-bl-none-function.s: New file.
>           * ld-aarch64/farcall-bl.d: New file.
>           * ld-aarch64/farcall-bl.s: New file.
>           * ld-aarch64/farcall-section.d: New file.
>           * ld-aarch64/farcall-section.s: New file.
>           * ld-aarch64/limit-b.d: New file.
>           * ld-aarch64/limit-b.s: New file.
>           * ld-aarch64/limit-bl.d: New file.
>           * ld-aarch64/limit-bl.s: New file.
>           * ld-aarch64/relocs.ld: New file.
>           * ld-aarch64/tls-desc-ie.d: New file.
>           * ld-aarch64/tls-desc-ie.s: New file.
>           * ld-aarch64/tls-relax-all.d: New file.
>           * ld-aarch64/tls-relax-all.s: New file.
>           * ld-aarch64/tls-relax-gd-ie.d: New file.
>           * ld-aarch64/tls-relax-gd-ie.s: New file.
>           * ld-aarch64/tls-relax-gd-le.d: New file.
>           * ld-aarch64/tls-relax-gd-le.s: New file.
>           * ld-aarch64/tls-relax-gdesc-ie-2.d: New file.
>           * ld-aarch64/tls-relax-gdesc-ie-2.s: New file.
>           * ld-aarch64/tls-relax-gdesc-ie.d: New file.
>           * ld-aarch64/tls-relax-gdesc-ie.s: New file.
>           * ld-aarch64/tls-relax-gdesc-le-2.d: New file.
>           * ld-aarch64/tls-relax-gdesc-le-2.s: New file.
>           * ld-aarch64/tls-relax-gdesc-le.d: New file.
>           * ld-aarch64/tls-relax-gdesc-le.s: New file.
>           * ld-aarch64/tls-relax-ie-le-2.d: New file.
>           * ld-aarch64/tls-relax-ie-le-2.s: New file.
>           * ld-aarch64/tls-relax-ie-le-3.d: New file.
>           * ld-aarch64/tls-relax-ie-le-3.s: New file.
>           * ld-aarch64/tls-relax-ie-le.d: New file.
>           * ld-aarch64/tls-relax-ie-le.s: New file.
>           * ld-aarch64/weak-undefined.d: New file.
>           * ld-aarch64/weak-undefined.s: New file.
>           * ld-elf/binutils.exp (binutils_test): Add optional parameter
>           'test_name'; change to construct 'test_name' from the 'prog_name'
>           and 'ld_options' only when "$test_name" == "".
>           * ld-elf/group8a.d (#notarget): Add AArch64.
>           * ld-elf/group8b.d (#notarget): Add AArch64.
>           * ld-elf/group9a.d (#notarget): Add AArch64.
>           * ld-elf/group9b.d (#notarget): Add AArch64.
>           * ld-elf/pr12851.d (#notarget): Add AArch64.
>           * ld-elf/pr12975.d (#notarget): Add AArch64.
>           * ld-elf/pr13177.d (#notarget): Add AArch64.
>           * ld-elf/pr13195.d (#notarget): Add AArch64.
>           * ld-elfvers/vers.exp: Add AArch64.
>           * ld-shared/shared.exp: Add AArch64.
>           * ld-srec/srec.exp: Add AArch64.
>           * lib/ld-lib.exp: Add AArch64.

Approved and applied.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes v2
  2012-08-07 17:30     ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes v2 Yufeng Zhang
@ 2012-08-13 15:02       ` nick clifton
  0 siblings, 0 replies; 41+ messages in thread
From: nick clifton @ 2012-08-13 15:02 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: Joseph S. Myers, binutils

Hi Yufeng,

> binutils/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>              Laurent Desnogues  <laurent.desnogues@arm.com>
>              Jim MacArthur  <jim.macarthur@arm.com>
>              Marcus Shawcroft  <marcus.shawcroft@arm.com>
>              Nigel Stephens  <nigel.stephens@arm.com>
>              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>              Richard Earnshaw  <rearnsha@arm.com>
>              Sofiane Naci  <sofiane.naci@arm.com>
>              Tejas Belagod  <tejas.belagod@arm.com>
>              Yufeng Zhang  <yufeng.zhang@arm.com>
>
>          * readelf.c (guess_is_rela): Handle EM_AARCH64.
>          (get_machine_name): Likewise.
>          (get_aarch64_segment_type): New function.
>          (get_segment_type): Handle EM_AARCH64 by calling the new function.
>          (get_aarch64_section_type_name): New function.
>          (get_section_type_name): Handle EM_AARCH64 by calling the new
> function.
>          (is_32bit_abs_reloc): Handle EM_AARCH64.
>          (is_32bit_pcrel_reloc): Likewise.
>          (is_64bit_abs_reloc): Likewise.
>          (is_64bit_pcrel_reloc): Likewise.
>          (is_none_reloc): Likewise.
>
> binutils/testsuite/ChangeLog
> 2012-08-07  Ian Bolton  <ian.bolton@arm.com>
>              Laurent Desnogues  <laurent.desnogues@arm.com>
>              Jim MacArthur  <jim.macarthur@arm.com>
>              Marcus Shawcroft  <marcus.shawcroft@arm.com>
>              Nigel Stephens  <nigel.stephens@arm.com>
>              Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
>              Richard Earnshaw  <rearnsha@arm.com>
>              Sofiane Naci  <sofiane.naci@arm.com>
>              Tejas Belagod  <tejas.belagod@arm.com>
>              Yufeng Zhang  <yufeng.zhang@arm.com>
>
>          * objdump.exp: Add AArch64.

Approved and applied.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2012-08-13 14:58 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-30 14:21 [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Richard Earnshaw
2012-07-30 14:28 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [1/6] Toplevel configury changes Yufeng Zhang
2012-07-30 14:49   ` Joseph S. Myers
2012-08-01 14:59     ` Yufeng Zhang
2012-08-07 17:39   ` Yufeng Zhang
2012-07-30 14:30 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Jan Beulich
2012-08-09 14:50   ` Richard Earnshaw
2012-07-30 14:47 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes Yufeng Zhang
2012-07-31 18:22   ` nick clifton
2012-07-31 19:27     ` Yufeng Zhang
2012-08-07 17:18   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [2/6] opcodes changes v2 Yufeng Zhang
2012-08-13 14:56     ` nick clifton
2012-07-30 14:51 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes Yufeng Zhang
2012-07-30 14:57   ` Joseph S. Myers
2012-07-31 18:29   ` nick clifton
2012-08-01  9:14     ` Yufeng Zhang
2012-08-02 21:35   ` DJ Delorie
2012-08-03 14:51     ` Yufeng Zhang
2012-08-04  8:06       ` DJ Delorie
2012-08-07 17:53         ` Yufeng Zhang
2012-08-07 17:19   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [3/6] bfd changes v2 Yufeng Zhang
2012-08-08 12:18     ` Benedikt Schroefel
2012-08-08 12:20       ` Richard Earnshaw
2012-08-13 14:57     ` nick clifton
2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes Yufeng Zhang
2012-07-30 15:02   ` Joseph S. Myers
2012-07-31 18:23   ` nick clifton
2012-08-07 17:29   ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [4/6] gas changes v2 Yufeng Zhang
2012-08-13 14:58     ` nick clifton
2012-07-30 14:54 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [0/6] Joseph S. Myers
2012-07-31 16:37   ` Yufeng Zhang
2012-07-30 15:00 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes Yufeng Zhang
2012-07-30 15:08   ` Joseph S. Myers
2012-08-07 17:34     ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2 Yufeng Zhang
2012-08-09 17:37       ` nick clifton
2012-08-09 21:32         ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v3 Yufeng Zhang
2012-08-13 14:58       ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [5/6] ld changes v2 nick clifton
2012-07-30 15:02 ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes Yufeng Zhang
2012-07-30 15:17   ` Joseph S. Myers
2012-08-07 17:30     ` [AArch64] Binutils/gas/ld port for ARM's new 64-bit architecture, AArch64 [6/6] binutils changes v2 Yufeng Zhang
2012-08-13 15:02       ` nick clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).