public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [gold] First patch for aarch64 backend
@ 2014-06-25 23:47 Jing Yu
  2014-07-01 21:55 ` Cary Coutant
  2014-07-01 22:15 ` Yufeng Zhang
  0 siblings, 2 replies; 8+ messages in thread
From: Jing Yu @ 2014-06-25 23:47 UTC (permalink / raw)
  To: binutils; +Cc: Han Shen, Doug Kwan, Cary Coutant

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

Hi,

We start to work on gold aarch64 backend. Here is the first patch.
This patch is just a skeleton which almost does nothing.
The change that enables gold for aarch64 in top level configure was
removed from this patch.

Tested:
1) On x86_64,
${binutils}/configure --build=x86_64-unknown-linux-gnu
--host=x86_64-unknown-linux-gnu --target=x86_64-unknown-linux-gnu
--enable-plugins --disable-multilib --disable-nls --enable-threads
--enable-gold=default --enable-targets=all
$make all-gold

Also built with -O1 and -O0.

2) On aarch64,
gcc version 4.8.2 (Ubuntu/Linaro 4.8.2-19ubuntu1)
$ ../binutils-gdb/configure --enable-plugins --disable-multilib
--disable-nls --enable-threads --enable-gold=default
--enable-targets=all
$make all-gold
Also built with -O1 and -O0.

The generated native gold/ld-new is able to read hello.o and libc.so.

Thanks,
Jing

[-- Attachment #2: gold_aarch64_0.patch --]
[-- Type: text/x-patch, Size: 59339 bytes --]

diff --git a/elfcpp/aarch64.h b/elfcpp/aarch64.h
new file mode 100644
index 0000000..09bc498
--- /dev/null
+++ b/elfcpp/aarch64.h
@@ -0,0 +1,183 @@
+// aarch64.h -- ELF definitions specific to AARCH64  -*- C++ -*-
+
+// Copyright (C) 2012-2014 Free Software Foundation, Inc.
+// Written by Jing Yu (jingyu@google.com)
+
+// This file is part of elfcpp.
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public License
+// as published by the Free Software Foundation; either version 2, or
+// (at your option) any later version.
+
+// In addition to the permissions in the GNU Library General Public
+// License, the Free Software Foundation gives you unlimited
+// permission to link the compiled version of this file into
+// combinations with other programs, and to distribute those
+// combinations without any restriction coming from the use of this
+// file.  (The Library Public License restrictions do apply in other
+// respects; for example, they cover modification of the file, and
+/// distribution when not linked into a combined executable.)
+
+// 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
+// Library General Public License for more details.
+
+// You should have received a copy of the GNU Library 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.
+
+#ifndef ELFCPP_AARCH64_H
+#define ELFCPP_AARCH64_H
+
+namespace elfcpp
+{
+
+// The relocation type information is taken from:
+//
+//   ELF for the ARM 64-bit Architecture (AArch64)
+//   Document number: ARM IHI 0056B, current through AArch64 ABI release 1.0
+//   Date of Issue: 22nd May, 2013
+//
+
+enum
+{
+  // Null relocation codes
+  R_AARCH64_NONE = 0,		// None
+  withdrawn = 256,		// Treat as R_AARCH64_NONE
+
+  // Static relocations
+  R_AARCH64_ABS64 = 257,	// S + A
+  R_AARCH64_ABS32 = 258,	// S + A
+  R_AARCH64_ABS16 = 259,	// S + A
+  R_AARCH64_PREL64 = 260,	// S + A - P
+  R_AARCH64_PREL32 = 261,	// S + A - P
+  R_AARCH64_PREL16 = 262,	// S + A - P
+  R_AARCH64_MOVW_UABS_G0 = 263,		// S + A
+  R_AARCH64_MOVW_UABS_G0_NC = 264,	// S + A
+  R_AARCH64_MOVW_UABS_G1 = 265,		// S + A
+  R_AARCH64_MOVW_UABS_G1_NC = 266,	// S + A
+  R_AARCH64_MOVW_UABS_G2 = 267,		// S + A
+  R_AARCH64_MOVW_UABS_G2_NC = 268,	// S + A
+  R_AARCH64_MOVW_UABS_G3 = 269,		// S + A
+  R_AARCH64_MOVW_SABS_G0 = 270,		// S + A
+  R_AARCH64_MOVW_SABS_G1 = 271,		// S + A
+  R_AARCH64_MOVW_SABS_G2 = 272,		// S + A
+  R_AARCH64_LD_PREL_LO19 = 273,		// S + A - P
+  R_AARCH64_ADR_PREL_LO21 = 274,	// S + A - P
+  R_AARCH64_ADR_PREL_PG_HI21 = 275,	// Page(S+A) - Page(P)
+  R_AARCH64_ADR_PREL_PG_HI21_NC = 276,	// Page(S+A) - Page(P)
+  R_AARCH64_ADD_ABS_LO12_NC = 277,	// S + A
+  R_AARCH64_LDST8_ABS_LO12_NC = 278,	// S + A
+  R_AARCH64_TSTBR14 = 279,		// S + A - P
+  R_AARCH64_CONDBR19 = 280,		// S + A - P
+  R_AARCH64_JUMP26 = 282,		// S + A - P
+  R_AARCH64_CALL26 = 283,		// S + A - P
+  R_AARCH64_LDST16_ABS_LO12_NC = 284,	// S + A
+  R_AARCH64_LDST32_ABS_LO12_NC = 285,	// S + A
+  R_AARCH64_LDST64_ABS_LO12_NC = 286,	// S + A
+  R_AARCH64_MOVW_PREL_G0 = 287,		// S + A - P
+  R_AARCH64_MOVW_PREL_G0_NC = 288,	// S + A - P
+  R_AARCH64_MOVW_PREL_G1 = 289,		// S + A - P
+  R_AARCH64_MOVW_PREL_G1_NC = 290,	// S + A - P
+  R_AARCH64_MOVW_PREL_G2 = 291,		// S + A - P
+  R_AARCH64_MOVW_PREL_G2_NC = 292,	// S + A - P
+  R_AARCH64_MOVW_PREL_G3 = 293,		// S + A - P
+  R_AARCH64_LDST128_ABS_LO12_NC = 299,	// S + A
+  R_AARCH64_MOVW_GOTOFF_G0 = 300,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G0_NC = 301,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G1 = 302,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G1_NC = 303,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G2 = 304,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G2_NC = 305,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G3 = 306,	// G(GDAT(S+A))-GOT
+  R_AARCH64_GOTREL64 = 307,		// S + A - GOT
+  R_AARCH64_GOTREL32 = 308,		// S + A - GOT
+  R_AARCH64_GOT_LD_PREL19 = 309,	// G(GDAT(S+A))-P
+  R_AARCH64_LD64_GOTOFF_LO15 = 310,	// G(GDAT(S+A))-GOT
+  R_AARCH64_ADR_GOT_PAGE = 311,		// Page(G(GDAT(S+A)))-Page(P)
+  R_AARCH64_LD64_GOT_LO12_NC = 312,	// G(GDAT(S+A))
+  R_AARCH64_LD64_GOTPAGE_LO15 = 313,	// G(GDAT(S+A))-Page(GOT)
+
+  // Relocations for thread-local storage
+  R_AARCH64_TLSGD_ADR_PREL21 = 512,		// G(GTLSIDX(S,A)) - P
+  R_AARCH64_TLSGD_ADR_PAGE21 = 513,		// Page(G(GTLSIDX(S,A)))-Page(P)
+  R_AARCH64_TLSGD_ADD_LO12_NC = 514,		// G(GTLSICX(S,A))
+  R_AARCH64_TLSGD_MOVW_G1 = 515,		// G(GTLSIDX(S,A)) - GOT
+  R_AARCH64_TLSGD_MOVW_G0_NC = 516,		// G(GTLSIDX(S,A)) - GOT
+
+  R_AARCH64_TLSLD_ADR_PREL21 = 517,		// G(GLDM(S)) - P
+  R_AARCH64_TLSLD_ADR_PAGE21 = 518,		// Page(G(GLDM(S))) - Page(P)
+  R_AARCH64_TLSLD_ADD_LO12_NC = 519,		// G(GLDM(S))
+  R_AARCH64_TLSLD_MOVW_G1 = 520,		// G(GLDM(S)) - GOT
+  R_AARCH64_TLSLD_MOVW_G0_NC = 521,		// G(GLDM(S)) - GOT
+  R_AARCH64_TLSLD_LD_PREL19 = 522,		// G(GLDM(S)) - P
+  R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 523,		// DTPREL(S+A)
+  R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 524,		// DTPREL(S+A)
+  R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 525,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 526,		// DTPREL(S+A)
+  R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 527,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 528,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 529,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 530,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 531,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 532,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 533,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 534,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 535,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 536,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 537,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 538,	// DTPREL(S+A)
+  R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 539,	// G(GTPREL(S+A)) - GOT
+  R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 540,	// G(GTPREL(S+A)) - GOT
+  R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541,	// Page(G(GTPREL(S+A)))-Page(P)
+  R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542,	// G(GTPREL(S+A))
+  R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 543,	// G(GTPREL(S+A)) - P
+  R_AARCH64_TLSLE_MOVW_TPREL_G2 = 544,		// TPREL(S+A)
+  R_AARCH64_TLSLE_MOVW_TPREL_G1 = 545,		// TPREL(S+A)
+  R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 546,	// TPREL(S+A)
+  R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547,		// TPREL(S+A)
+  R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 548,	// TPREL(S+A)
+  R_AARCH64_TLSLE_ADD_TPREL_HI12 = 549,		// TPREL(S+A)
+  R_AARCH64_TLSLE_ADD_TPREL_LO12 = 550,		// TPREL(S+A)
+  R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 551,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 552,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 553,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 554,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LSDT16_TPREL_LO12_NC = 555,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 556,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 557,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 558,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 559,	// TPREL(S+A)
+  R_AARCH64_TLSDESC_LD_PREL19 = 560,	// G(GTLSDESC(S+A)) - P
+  R_AARCH64_TLSDESC_ADR_PREL21 = 561,	// G(GTLSDESC(S+A)) - P
+  R_AARCH64_TLSDESC_ADR_PAGE21 = 562,	// Page(G(GTLSDESC(S+A)))-Page(P)
+  R_AARCH64_TLSDESC_LD64_LO12 = 563,	// G(GTLSDESC(S+A))
+  R_AARCH64_TLSDESC_ADD_LO12 = 564,	// G(GTLSDESC(S+A))
+  R_AARCH64_TLSDESC_OFF_G1 = 565,	// G(GTLSDESC(S+A)) - GOT
+  R_AARCH64_TLSDESC_OFF_G0_NC = 566,	// G(GTLSDESC(S+A)) - GOT
+  R_AARCH64_TLSDESC_LDR = 567,		// None
+  R_AARCH64_TLSDESC_ADD = 568,		// None
+  R_AARCH64_TLSDESC_CALL = 569,		// None
+  R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 570,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 571,	// TPREL(S+A)
+  R_AARCH64_TLSLD_LDST128_DTPREL_LO12 = 572,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC = 573,	// DTPREL(S+A)
+
+  // Dynamic relocations
+  R_AARCH64_COPY = 1024,
+  R_AARCH64_GLOB_DAT = 1025,		// S + A
+  R_AARCH64_JUMP_SLOT = 1026,		// S + A
+  R_AARCH64_RELATIVE = 1027,		// Delta(S) + A
+  R_AARCH64_TLS_DTPREL64 = 1028,	// DTPREL(S+A)
+  R_AARCH64_TLS_DTPMOD64 = 1029,	// LDM(S)
+  R_AARCH64_TLS_TPREL64 = 1030,		// TPREL(S+A)
+  R_AARCH64_TLSDESC = 1031,		// TLSDESC(S+A)
+  R_AARCH64_IRELATIVE = 1032,		// Indirect(Delta(S) + A)
+};
+
+} // End namespace elfcpp.
+
+#endif // !defined(ELFCPP_AARCH64_H)
diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h
index 561b54a..8e8e675 100644
--- a/elfcpp/elfcpp.h
+++ b/elfcpp/elfcpp.h
@@ -268,6 +268,7 @@ enum EM
   EM_UNICORE = 110,
   EM_ALTERA_NIOS2 = 113,
   EM_CRX = 114,
+  EM_AARCH64 = 183,
   EM_TILEGX = 191,
   // The Morph MT.
   EM_MT = 0x2530,
@@ -406,6 +407,9 @@ enum SHT
   // Section contains miscellaneous options.
   SHT_MIPS_OPTIONS = 0x7000000d,
 
+  // AARCH64-specific section type.
+  SHT_AARCH64_ATTRIBUTES = 0x70000003,
+
   // Link editor is to sort the entries in this section based on the
   // address specified in the associated symbol table entry.
   SHT_ORDERED = 0x7fffffff
@@ -490,7 +494,11 @@ enum PT
   // Runtime procedure table.
   PT_MIPS_RTPROC = 0x70000001,
   // .MIPS.options section.
-  PT_MIPS_OPTIONS = 0x70000002
+  PT_MIPS_OPTIONS = 0x70000002,
+  // Platform architecture compatibility information
+  PT_AARCH64_ARCHEXT = 0x70000000,
+  // Exception unwind tables
+  PT_AARCH64_UNWIND = 0x70000001
 };
 
 // The valid bit flags found in the Phdr p_flags field.
diff --git a/gold/Makefile.am b/gold/Makefile.am
index dd05e82..17ba4b4 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -164,11 +164,12 @@ EXTRA_DIST = yyscript.c yyscript.h
 
 TARGETSOURCES = \
 	i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc tilegx.cc \
-	mips.cc
+	mips.cc aarch64.cc
 
 ALL_TARGETOBJS = \
 	i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \
-	arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) mips.$(OBJEXT)
+	arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) \
+	mips.$(OBJEXT) aarch64.$(OBJEXT)
 
 libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES)
 libgold_a_LIBADD = $(LIBOBJS)
diff --git a/gold/Makefile.in b/gold/Makefile.in
index 39a3952..e8d9efb 100644
--- a/gold/Makefile.in
+++ b/gold/Makefile.in
@@ -533,11 +533,12 @@ DEFFILES = arm-reloc.def
 EXTRA_DIST = yyscript.c yyscript.h
 TARGETSOURCES = \
 	i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc tilegx.cc \
-	mips.cc
+	mips.cc aarch64.cc
 
 ALL_TARGETOBJS = \
 	i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \
-	arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) mips.$(OBJEXT)
+	arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) \
+	mips.$(OBJEXT) aarch64.$(OBJEXT)
 
 libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES)
 libgold_a_LIBADD = $(LIBOBJS)
diff --git a/gold/aarch64.cc b/gold/aarch64.cc
new file mode 100644
index 0000000..5e863e1
--- /dev/null
+++ b/gold/aarch64.cc
@@ -0,0 +1,1447 @@
+// aarch64.cc -- aarch64 target support for gold.
+
+// Copyright (C) 2006-2014 Free Software Foundation, Inc.
+// Written by Jing Yu <jingyu@google.com>.
+
+// This file is part of gold.
+
+// 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.
+
+#include "gold.h"
+
+#include <cstring>
+
+#include "elfcpp.h"
+#include "dwarf.h"
+#include "parameters.h"
+#include "reloc.h"
+#include "aarch64.h"
+#include "object.h"
+#include "symtab.h"
+#include "layout.h"
+#include "output.h"
+#include "copy-relocs.h"
+#include "target.h"
+#include "target-reloc.h"
+#include "target-select.h"
+#include "tls.h"
+#include "freebsd.h"
+#include "nacl.h"
+#include "gc.h"
+#include "icf.h"
+
+// The first three .got.plt entries are reserved.
+const int32_t AARCH64_GOTPLT_RESERVE_COUNT = 3;
+
+namespace
+{
+
+using namespace gold;
+
+template<int size, bool big_endian>
+class Output_data_plt_aarch64;
+
+template<int size, bool big_endian>
+class Output_data_plt_aarch64_standard;
+
+template<int size, bool big_endian>
+class Target_aarch64;
+
+// Output_data_got_aarch64 class.
+
+template<int size, bool big_endian>
+class Output_data_got_aarch64 : public Output_data_got<size, big_endian>
+{
+ public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
+  Output_data_got_aarch64(Symbol_table* symtab, Layout* layout)
+    : Output_data_got<size, big_endian>(), layout_(layout)
+  { }
+
+ protected:
+  // Write out the GOT table.
+  void
+  do_write(Output_file* of) {
+    // The first entry in the GOT is the address of the .dynamic section.
+    gold_assert(this->data_size() >= size / 8);
+    Output_section* dynamic = this->layout_->dynamic_section();
+    Valtype dynamic_addr = dynamic == NULL ? 0 : dynamic->address();
+    this->replace_constant(0, dynamic_addr);
+    Output_data_got<size, big_endian>::do_write(of);
+  }
+
+ private:
+  // A pointer to the Layout class, so that we can find the .dynamic
+  // section when we write out the GOT section.
+  Layout* layout_;
+};
+
+// The aarch64 target class.
+// See the ABI at
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
+template<int size, bool big_endian>
+class Target_aarch64 : public Sized_target<size, big_endian>
+{
+ public:
+  typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
+      Reloc_section;
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+
+  Target_aarch64(const Target::Target_info* info = &aarch64_info)
+    : Sized_target<size, big_endian>(info),
+      got_(NULL), plt_(NULL), got_plt_(NULL),
+      global_offset_table_(NULL), rela_dyn_(NULL),
+      copy_relocs_(elfcpp::R_AARCH64_COPY)
+  { }
+
+  // Scan the relocations to determine unreferenced sections for
+  // garbage collection.
+  void
+  gc_process_relocs(Symbol_table* symtab,
+		    Layout* layout,
+		    Sized_relobj_file<size, big_endian>* object,
+		    unsigned int data_shndx,
+		    unsigned int sh_type,
+		    const unsigned char* prelocs,
+		    size_t reloc_count,
+		    Output_section* output_section,
+		    bool needs_special_offset_handling,
+		    size_t local_symbol_count,
+		    const unsigned char* plocal_symbols);
+
+  // Scan the relocations to look for symbol adjustments.
+  void
+  scan_relocs(Symbol_table* symtab,
+	      Layout* layout,
+	      Sized_relobj_file<size, big_endian>* object,
+	      unsigned int data_shndx,
+	      unsigned int sh_type,
+	      const unsigned char* prelocs,
+	      size_t reloc_count,
+	      Output_section* output_section,
+	      bool needs_special_offset_handling,
+	      size_t local_symbol_count,
+	      const unsigned char* plocal_symbols);
+
+  // Finalize the sections.
+  void
+  do_finalize_sections(Layout*, const Input_objects*, Symbol_table*);
+
+  // Relocate a section.
+  void
+  relocate_section(const Relocate_info<size, big_endian>*,
+		   unsigned int sh_type,
+		   const unsigned char* prelocs,
+		   size_t reloc_count,
+		   Output_section* output_section,
+		   bool needs_special_offset_handling,
+		   unsigned char* view,
+		   typename elfcpp::Elf_types<size>::Elf_Addr view_address,
+		   section_size_type view_size,
+		   const Reloc_symbol_changes*);
+
+  // Scan the relocs during a relocatable link.
+  void
+  scan_relocatable_relocs(Symbol_table* symtab,
+			  Layout* layout,
+			  Sized_relobj_file<size, big_endian>* object,
+			  unsigned int data_shndx,
+			  unsigned int sh_type,
+			  const unsigned char* prelocs,
+			  size_t reloc_count,
+			  Output_section* output_section,
+			  bool needs_special_offset_handling,
+			  size_t local_symbol_count,
+			  const unsigned char* plocal_symbols,
+			  Relocatable_relocs*);
+
+  // Relocate a section during a relocatable link.
+  void
+  relocate_relocs(
+      const Relocate_info<size, big_endian>*,
+      unsigned int sh_type,
+      const unsigned char* prelocs,
+      size_t reloc_count,
+      Output_section* output_section,
+      typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
+      const Relocatable_relocs*,
+      unsigned char* view,
+      typename elfcpp::Elf_types<size>::Elf_Addr view_address,
+      section_size_type view_size,
+      unsigned char* reloc_view,
+      section_size_type reloc_view_size);
+
+  // Return the number of entries in the PLT.
+  unsigned int
+  plt_entry_count() const;
+
+  //Return the offset of the first non-reserved PLT entry.
+  unsigned int
+  first_plt_entry_offset() const;
+
+  // Return the size of each PLT entry.
+  unsigned int
+  plt_entry_size() const;
+
+ private:
+  // The class which scans relocations.
+  class Scan
+  {
+  public:
+    Scan()
+      : issued_non_pic_error_(false)
+    { }
+
+    static inline int
+    get_reference_flags(unsigned int r_type);
+
+    inline void
+    local(Symbol_table* symtab, Layout* layout, Target_aarch64* target,
+	  Sized_relobj_file<size, big_endian>* object,
+	  unsigned int data_shndx,
+	  Output_section* output_section,
+	  const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
+	  const elfcpp::Sym<size, big_endian>& lsym,
+	  bool is_discarded);
+
+    inline void
+    global(Symbol_table* symtab, Layout* layout, Target_aarch64* target,
+	   Sized_relobj_file<size, big_endian>* object,
+	   unsigned int data_shndx,
+	   Output_section* output_section,
+	   const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
+	   Symbol* gsym);
+
+    inline bool
+    local_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
+                                        Target_aarch64<size, big_endian>* ,
+                                        Sized_relobj_file<size, big_endian>* ,
+                                        unsigned int ,
+                                        Output_section* ,
+                                        const elfcpp::Rela<size, big_endian>& ,
+                                        unsigned int r_type,
+                                        const elfcpp::Sym<size, big_endian>&);
+
+    inline bool
+    global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
+                                         Target_aarch64<size, big_endian>* ,
+                                         Sized_relobj_file<size, big_endian>* ,
+                                         unsigned int ,
+                                         Output_section* ,
+                                         const elfcpp::Rela<size, big_endian>& ,
+                                         unsigned int r_type,
+                                         Symbol* gsym);
+
+  private:
+    static void
+    unsupported_reloc_local(Sized_relobj_file<size, big_endian>*,
+			    unsigned int r_type);
+
+    static void
+    unsupported_reloc_global(Sized_relobj_file<size, big_endian>*,
+			     unsigned int r_type, Symbol*);
+
+    inline bool
+    possible_function_pointer_reloc(unsigned int r_type);
+
+    void
+    check_non_pic(Relobj*, unsigned int r_type);
+
+    // Whether we have issued an error about a non-PIC compilation.
+    bool issued_non_pic_error_;
+  };
+
+  // The class which implements relocation.
+  class Relocate
+  {
+   public:
+    Relocate()
+    { }
+
+    ~Relocate()
+    { }
+
+    // Do a relocation.  Return false if the caller should not issue
+    // any warnings about this relocation.
+    inline bool
+    relocate(const Relocate_info<size, big_endian>*, Target_aarch64*,
+	     Output_section*,
+	     size_t relnum, const elfcpp::Rela<size, big_endian>&,
+	     unsigned int r_type, const Sized_symbol<size>*,
+	     const Symbol_value<size>*,
+	     unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
+	     section_size_type);
+
+  };
+
+  // A class which returns the size required for a relocation type,
+  // used while scanning relocs during a relocatable link.
+  class Relocatable_size_for_reloc
+  {
+   public:
+    unsigned int
+    get_size_for_reloc(unsigned int, Relobj*);
+  };
+
+  // Adjust TLS relocation type based on the options and whether this
+  // is a local symbol.
+  static tls::Tls_optimization
+  optimize_tls_reloc(bool is_final, int r_type);
+
+  // Get the GOT section, creating it if necessary.
+  Output_data_got_aarch64<size, big_endian>*
+  got_section(Symbol_table*, Layout*);
+
+  // Get the GOT PLT section.
+  Output_data_space*
+  got_plt_section() const
+  {
+    gold_assert(this->got_plt_ != NULL);
+    return this->got_plt_;
+  }
+
+  // Create the PLT section.
+  void
+  make_plt_section(Symbol_table* symtab, Layout* layout);
+
+  // Create a PLT entry for a global symbol.
+  void
+  make_plt_entry(Symbol_table*, Layout*, Symbol*);
+
+  // Get the PLT section.
+  Output_data_plt_aarch64<size, big_endian>*
+  plt_section() const
+  {
+    gold_assert(this->plt_ != NULL);
+    return this->plt_;
+  }
+
+  // Get the dynamic reloc section, creating it if necessary.
+  Reloc_section*
+  rela_dyn_section(Layout*);
+
+  // Add a potential copy relocation.
+  void
+  copy_reloc(Symbol_table* symtab, Layout* layout,
+	     Sized_relobj_file<size, big_endian>* object,
+	     unsigned int shndx, Output_section* output_section,
+	     Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
+  {
+    this->copy_relocs_.copy_reloc(symtab, layout,
+				  symtab->get_sized_symbol<size>(sym),
+				  object, shndx, output_section,
+				  reloc, this->rela_dyn_section(layout));
+  }
+
+  // Information about this specific target which we pass to the
+  // general Target structure.
+  static const Target::Target_info aarch64_info;
+
+  // The types of GOT entries needed for this platform.
+  // These values are exposed to the ABI in an incremental link.
+  // Do not renumber existing values without changing the version
+  // number of the .gnu_incremental_inputs section.
+  enum Got_type
+  {
+    GOT_TYPE_STANDARD = 0,      // GOT entry for a regular symbol
+    GOT_TYPE_TLS_OFFSET = 1,    // GOT entry for TLS offset
+    GOT_TYPE_TLS_PAIR = 2,      // GOT entry for TLS module/offset pair
+    GOT_TYPE_TLS_DESC = 3       // GOT entry for TLS_DESC pair
+  };
+
+  // The GOT section.
+  Output_data_got_aarch64<size, big_endian>* got_;
+  // The PLT section.
+  Output_data_plt_aarch64<size, big_endian>* plt_;
+  // The GOT PLT section.
+  Output_data_space* got_plt_;
+  // The _GLOBAL_OFFSET_TABLE_ symbol.
+  Symbol* global_offset_table_;
+  // The dynamic reloc section.
+  Reloc_section* rela_dyn_;
+  // Relocs saved to avoid a COPY reloc.
+  Copy_relocs<elfcpp::SHT_RELA, size, big_endian> copy_relocs_;
+};
+
+template<>
+const Target::Target_info Target_aarch64<64, false>::aarch64_info =
+{
+  64,			// size
+  false,		// is_big_endian
+  elfcpp::EM_AARCH64,	// machine_code
+  false,		// has_make_symbol
+  false,		// has_resolve
+  false,		// has_code_fill
+  true,			// is_default_stack_executable
+  false,		// can_icf_inline_merge_sections
+  '\0',			// wrap_char
+  "/lib/ld.so.1",	// program interpreter
+  0x400000,		// default_text_segment_address
+  0x1000,		// abi_pagesize (overridable by -z max-page-size)
+  0x1000,		// common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
+  elfcpp::SHN_UNDEF,	// small_common_shndx
+  elfcpp::SHN_UNDEF,	// large_common_shndx
+  0,			// small_common_section_flags
+  0,			// large_common_section_flags
+  NULL,			// attributes_section
+  NULL,			// attributes_vendor
+  "_start"		// entry_symbol_name
+};
+
+template<>
+const Target::Target_info Target_aarch64<32, false>::aarch64_info =
+{
+  32,			// size
+  false,		// is_big_endian
+  elfcpp::EM_AARCH64,	// machine_code
+  false,		// has_make_symbol
+  false,		// has_resolve
+  false,		// has_code_fill
+  true,			// is_default_stack_executable
+  false,		// can_icf_inline_merge_sections
+  '\0',			// wrap_char
+  "/lib/ld.so.1",	// program interpreter
+  0x400000,		// default_text_segment_address
+  0x1000,		// abi_pagesize (overridable by -z max-page-size)
+  0x1000,		// common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
+  elfcpp::SHN_UNDEF,	// small_common_shndx
+  elfcpp::SHN_UNDEF,	// large_common_shndx
+  0,			// small_common_section_flags
+  0,			// large_common_section_flags
+  NULL,			// attributes_section
+  NULL,			// attributes_vendor
+  "_start"		// entry_symbol_name
+};
+
+template<>
+const Target::Target_info Target_aarch64<64, true>::aarch64_info =
+{
+  64,			// size
+  true,			// is_big_endian
+  elfcpp::EM_AARCH64,	// machine_code
+  false,		// has_make_symbol
+  false,		// has_resolve
+  false,		// has_code_fill
+  true,			// is_default_stack_executable
+  false,		// can_icf_inline_merge_sections
+  '\0',			// wrap_char
+  "/lib/ld.so.1",	// program interpreter
+  0x400000,		// default_text_segment_address
+  0x1000,		// abi_pagesize (overridable by -z max-page-size)
+  0x1000,		// common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
+  elfcpp::SHN_UNDEF,	// small_common_shndx
+  elfcpp::SHN_UNDEF,	// large_common_shndx
+  0,			// small_common_section_flags
+  0,			// large_common_section_flags
+  NULL,			// attributes_section
+  NULL,			// attributes_vendor
+  "_start"		// entry_symbol_name
+};
+
+template<>
+const Target::Target_info Target_aarch64<32, true>::aarch64_info =
+{
+  32,			// size
+  true,			// is_big_endian
+  elfcpp::EM_AARCH64,	// machine_code
+  false,		// has_make_symbol
+  false,		// has_resolve
+  false,		// has_code_fill
+  true,			// is_default_stack_executable
+  false,		// can_icf_inline_merge_sections
+  '\0',			// wrap_char
+  "/lib/ld.so.1",	// program interpreter
+  0x400000,		// default_text_segment_address
+  0x1000,		// abi_pagesize (overridable by -z max-page-size)
+  0x1000,		// common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
+  elfcpp::SHN_UNDEF,	// small_common_shndx
+  elfcpp::SHN_UNDEF,	// large_common_shndx
+  0,			// small_common_section_flags
+  0,			// large_common_section_flags
+  NULL,			// attributes_section
+  NULL,			// attributes_vendor
+  "_start"		// entry_symbol_name
+};
+
+// Get the GOT section, creating it if necessary.
+
+template<int size, bool big_endian>
+Output_data_got_aarch64<size, big_endian>*
+Target_aarch64<size, big_endian>::got_section(Symbol_table* symtab,
+                                              Layout* layout)
+{
+  if (this->got_ == NULL)
+    {
+      gold_assert(symtab != NULL && layout != NULL);
+
+      // When using -z now, we can treat .got.plt as a relro section.
+      // Without -z now, it is modified after program startup by lazy
+      // PLT relocations.
+      bool is_got_plt_relro = parameters->options().now();
+      Output_section_order got_order = (is_got_plt_relro
+					? ORDER_RELRO
+					: ORDER_RELRO_LAST);
+      Output_section_order got_plt_order = (is_got_plt_relro
+					    ? ORDER_RELRO
+					    : ORDER_NON_RELRO_FIRST);
+
+      // Layout of .got and .got.plt sections.
+      // .got[0] &_DYNAMIC                          <-_GLOBAL_OFFSET_TABLE_
+      // ...
+      // .gotplt[0] reserved for ld.so (&linkmap)   <--DT_PLTGOT
+      // .gotplt[1] reserved for ld.so (resolver)
+      // .gotplt[2] reserved
+
+      // Generate .got section.
+      this->got_ = new Output_data_got_aarch64<size, big_endian>(symtab,
+                                                                 layout);
+      layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
+                                      (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
+                                      this->got_, got_order, true);
+      // The first word of GOT is reserved for the address of .dynamic.
+      // We put 0 here now. The value will be replaced later in
+      // Output_data_got_aarch64::do_write.
+      this->got_->add_constant(0);
+
+      // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT.
+      // _GLOBAL_OFFSET_TABLE_ value points to the start of the .got section,
+      // even if there is a .got.plt section.
+      this->global_offset_table_ =
+        symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
+                                      Symbol_table::PREDEFINED,
+                                      this->got_,
+                                      0, 0, elfcpp::STT_OBJECT,
+                                      elfcpp::STB_LOCAL,
+                                      elfcpp::STV_HIDDEN, 0,
+                                      false, false);
+
+      // Generate .got.plt section.
+      this->got_plt_ = new Output_data_space(size / 8, "** GOT PLT");
+      layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
+                                      (elfcpp::SHF_ALLOC
+                                       | elfcpp::SHF_WRITE),
+                                      this->got_plt_, got_plt_order,
+                                      is_got_plt_relro);
+
+      // The first three entries are reserved.
+      this->got_plt_->set_current_data_size
+          (AARCH64_GOTPLT_RESERVE_COUNT * (size / 8));
+
+      if (!is_got_plt_relro)
+        {
+          // Those bytes can go into the relro segment.
+          layout->increase_relro
+              (AARCH64_GOTPLT_RESERVE_COUNT * (size / 8));
+        }
+
+    }
+  return this->got_;
+}
+
+// Get the dynamic reloc section, creating it if necessary.
+
+template<int size, bool big_endian>
+typename Target_aarch64<size, big_endian>::Reloc_section*
+Target_aarch64<size, big_endian>::rela_dyn_section(Layout* layout)
+{
+  if (this->rela_dyn_ == NULL)
+    {
+      gold_assert(layout != NULL);
+      this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
+      layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
+				      elfcpp::SHF_ALLOC, this->rela_dyn_,
+				      ORDER_DYNAMIC_RELOCS, false);
+    }
+  return this->rela_dyn_;
+}
+
+// A class to handle the PLT data.
+// This is an abstract base class that handles most of the linker details
+// but does not know the actual contents of PLT entries.  The derived
+// classes below fill in those details.
+
+template<int size, bool big_endian>
+class Output_data_plt_aarch64 : public Output_section_data
+{
+ public:
+  typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
+      Reloc_section;
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+
+  Output_data_plt_aarch64(Layout* layout,
+                          uint64_t addralign,
+                          Output_data_space* got_plt)
+    : Output_section_data(addralign),
+      got_plt_(got_plt),
+      count_(0)
+  { this->init(layout); }
+
+  // Initialize the PLT section.
+  void
+  init(Layout* layout);
+
+  // Add an entry to the PLT.
+  void
+  add_entry(Symbol* gsym);
+
+  // Return the .rela.plt section data.
+  Reloc_section*
+  rela_plt()
+  { return this->rel_; }
+
+  // Return the number of PLT entries.
+  unsigned int
+  entry_count() const
+  { return this->count_; }
+
+  // Return the offset of the first non-reserved PLT entry.
+  unsigned int
+  first_plt_entry_offset()
+  { return this->do_first_plt_entry_offset(); }
+
+  // Return the size of a PLT entry.
+  unsigned int
+  get_plt_entry_size() const
+  { return this->do_get_plt_entry_size(); }
+
+ protected:
+  // Fill in the first PLT entry.
+  void
+  fill_first_plt_entry(unsigned char* pov,
+		       Address got_address,
+		       Address plt_address)
+  { this->do_fill_first_plt_entry(pov, got_address, plt_address); }
+
+  // Fill in a normal PLT entry.
+  void
+  fill_plt_entry(unsigned char* pov,
+		 Address got_address,
+		 Address plt_address,
+		 unsigned int got_offset,
+		 unsigned int plt_offset)
+  {
+    this->do_fill_plt_entry(pov, got_address, plt_address,
+			    got_offset, plt_offset);
+  }
+
+  virtual unsigned int
+  do_first_plt_entry_offset() const = 0;
+
+  virtual unsigned int
+  do_get_plt_entry_size() const = 0;
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+			  Address got_addr,
+			  Address plt_addr) = 0;
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+		    Address got_address,
+		    Address plt_address,
+		    unsigned int got_offset,
+		    unsigned int plt_offset) = 0;
+
+  void
+  do_adjust_output_section(Output_section* os);
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** PLT")); }
+
+ private:
+  // Set the final size.
+  void
+  set_final_data_size();
+
+  // Write out the PLT data.
+  void
+  do_write(Output_file*);
+
+  // The reloc section.
+  Reloc_section* rel_;
+  // The .got section.
+  Output_data_got_aarch64<size, big_endian>* got_;
+  // The .got.plt section.
+  Output_data_space* got_plt_;
+  // The number of PLT entries.
+  unsigned int count_;
+};
+
+// Initialize the PLT section.
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::init(Layout* layout)
+{
+  this->rel_ = new Reloc_section(false);
+  layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
+				  elfcpp::SHF_ALLOC, this->rel_,
+				  ORDER_DYNAMIC_PLT_RELOCS, false);
+}
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::do_adjust_output_section(
+    Output_section* os)
+{
+  os->set_entsize(this->get_plt_entry_size());
+}
+
+// Add an entry to the PLT.
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::add_entry(Symbol* gsym)
+{
+  gold_assert(!gsym->has_plt_offset());
+  //TODO
+}
+
+// Set the final size.
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::set_final_data_size()
+{
+  this->set_data_size(this->first_plt_entry_offset()
+                      + this->count * this->get_plt_entry_size());
+}
+
+template<int size, bool big_endian>
+class Output_data_plt_aarch64_standard :
+  public Output_data_plt_aarch64<size, big_endian>
+{
+ public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+  Output_data_plt_aarch64_standard(Layout* layout, Output_data_space* got_plt)
+    : Output_data_plt_aarch64<size, big_endian>(layout,
+                                                size == 32 ? 4 : 8,
+                                                got_plt)
+  { }
+
+ protected:
+  // Return the offset of the first non-reserved PLT entry.
+  virtual unsigned int
+  do_first_plt_entry_offset() const
+  { return this->first_plt_entry_size; }
+
+  // Return the size of a PLT entry
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return this->plt_entry_size; }
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                          Address got_address,
+                          Address plt_address);
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+                    Address got_address,
+                    Address plt_address,
+                    unsigned int got_offset,
+                    unsigned int plt_offset);
+
+ private:
+  // The size of the first plt entry size.
+  static const int first_plt_entry_size = 32;
+  // The size of the plt entry size.
+  static const int plt_entry_size = 16;
+  // Template for the first PLT entry.
+  static const uint32_t first_plt_entry[first_plt_entry_size / 4];
+  // Template for subsequent PLT entries.
+  static const uint32_t plt_entry[plt_entry_size / 4];
+};
+
+// The first entry in the PLT for an executable.
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<32, false>::
+    first_plt_entry[first_plt_entry_size / 4] =
+{
+  0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
+  0x90000010,	/* adrp x16, PLT_GOT+16  */
+  0xb9400A11,	/* ldr w17, [x16, #PLT_GOT+0x8]  */
+  0x11002210,	/* add w16, w16,#PLT_GOT+0x8   */
+  0xd61f0220,	/* br x17  */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<32, true>::
+    first_plt_entry[first_plt_entry_size / 4] =
+{
+  0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
+  0x90000010,	/* adrp x16, PLT_GOT+16  */
+  0xb9400A11,	/* ldr w17, [x16, #PLT_GOT+0x8]  */
+  0x11002210,	/* add w16, w16,#PLT_GOT+0x8   */
+  0xd61f0220,	/* br x17  */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<64, false>::
+    first_plt_entry[first_plt_entry_size / 4] =
+{
+  0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
+  0x90000010,	/* adrp x16, PLT_GOT+16  */
+  0xf9400A11,	/* ldr x17, [x16, #PLT_GOT+0x10]  */
+  0x91004210,	/* add x16, x16,#PLT_GOT+0x10   */
+  0xd61f0220,	/* br x17  */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<64, true>::
+    first_plt_entry[first_plt_entry_size / 4] =
+{
+  0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
+  0x90000010,	/* adrp x16, PLT_GOT+16  */
+  0xf9400A11,	/* ldr x17, [x16, #PLT_GOT+0x10]  */
+  0x91004210,	/* add x16, x16,#PLT_GOT+0x10   */
+  0xd61f0220,	/* br x17  */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<32, false>::
+    plt_entry[plt_entry_size / 4] =
+{
+  0x90000010,	/* adrp x16, PLTGOT + n * 8  */
+  0xb9400211,	/* ldr w17, [w16, PLTGOT + n * 8] */
+  0x11000210,	/* add w16, w16, :lo12:PLTGOT + n * 4  */
+  0xd61f0220,	/* br x17.  */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<32, true>::
+    plt_entry[plt_entry_size / 4] =
+{
+  0x90000010,	/* adrp x16, PLTGOT + n * 8  */
+  0xb9400211,	/* ldr w17, [w16, PLTGOT + n * 8] */
+  0x11000210,	/* add w16, w16, :lo12:PLTGOT + n * 4  */
+  0xd61f0220,	/* br x17.  */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<64, false>::
+    plt_entry[plt_entry_size / 4] =
+{
+  0x90000010,	/* adrp x16, PLTGOT + n * 8  */
+  0xf9400211,	/* ldr x17, [x16, PLTGOT + n * 8] */
+  0x91000210,	/* add x16, x16, :lo12:PLTGOT + n * 4  */
+  0xd61f0220,	/* br x17.  */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<64, true>::
+    plt_entry[plt_entry_size / 4] =
+{
+  0x90000010,	/* adrp x16, PLTGOT + n * 8  */
+  0xf9400211,	/* ldr x17, [x16, PLTGOT + n * 8] */
+  0x91000210,	/* add x16, x16, :lo12:PLTGOT + n * 4  */
+  0xd61f0220,	/* br x17.  */
+};
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64_standard<size, big_endian>::do_fill_first_plt_entry(
+    unsigned char* pov,
+    Address /* got_address */,
+    Address /* plt_address */)
+{
+  // PLT0 of the small PLT looks like this in ELF64 -
+  // 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
+  // PLT0 will be slightly different in ELF32 due to different got entry
+  // size.
+  memcpy(pov, this->first_plt_entry, this->first_plt_entry_size);
+  // TODO
+}
+
+// Subsequent entries in the PLT for an executable.
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64_standard<size, big_endian>::do_fill_plt_entry(
+    unsigned char* pov,
+    Address /* got_address*/,
+    Address /* plt_address */,
+    unsigned int /* got_offset */,
+    unsigned int /* plt_offset */)
+{
+  memcpy(pov, this->plt_entry, this->plt_entry_size);
+  //TODO
+}
+
+// Write out the PLT.  This uses the hand-coded instructions above,
+// and adjusts them as needed.  This is specified by the AMD64 ABI.
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::do_write(Output_file* of)
+{
+  const off_t offset = this->offset();
+  const section_size_type oview_size =
+    convert_to_section_size_type(this->data_size());
+  unsigned char* const oview = of->get_output_view(offset, oview_size);
+
+  const off_t got_file_offset = this->got_plt_->offset();
+  const section_size_type got_size =
+    convert_to_section_size_type(this->got_plt_->data_size());
+  unsigned char* const got_view = of->get_output_view(got_file_offset,
+						      got_size);
+
+  unsigned char* pov = oview;
+
+  // The base address of the .plt section.
+  typename elfcpp::Elf_types<size>::Elf_Addr plt_address = this->address();
+  // The base address of the .got section.
+  typename elfcpp::Elf_types<size>::Elf_Addr got_base = this->got_->address();
+  // The base address of the PLT portion of the .got section.
+  typename elfcpp::Elf_types<size>::Elf_Addr got_address
+    = this->got_plt_->address();
+
+  this->fill_first_plt_entry(pov, got_address, plt_address);
+  pov += this->first_plt_entry_offset();
+
+  // The first three entries in .got.plt are reserved.
+  unsigned char* got_pov = got_view;
+  memset(got_pov, 0, size / 8 * AARCH64_GOTPLT_RESERVE_COUNT);
+  got_pov += (size / 8) * AARCH64_GOTPLT_RESERVE_COUNT;
+
+  unsigned int plt_offset = this->first_plt_entry_offset();
+  unsigned int got_offset = (size / 8) * AARCH64_GOTPLT_RESERVE_COUNT;
+  const unsigned int count = this->count_;
+  for (unsigned int plt_index = 0;
+       plt_index < count;
+       ++plt_index,
+	 pov += this->get_plt_entry_size(),
+	 got_pov += size / 8,
+	 plt_offset += this->get_plt_entry_size(),
+	 got_offset += size / 8)
+    {
+      // Set and adjust the PLT entry itself.
+      this->fill_plt_entry(pov, got_address, plt_address,
+                           got_offset, plt_offset);
+
+      // Set the entry in the GOT.
+      elfcpp::Swap<size, big_endian>::writeval(got_pov,
+          plt_address + plt_offset);
+    }
+
+  gold_assert(static_cast<section_size_type>(pov - oview) == oview_size);
+  gold_assert(static_cast<section_size_type>(got_pov - got_view) == got_size);
+
+  of->write_output_view(offset, oview_size, oview);
+  of->write_output_view(got_file_offset, got_size, got_view);
+}
+
+// Return the number of entries in the PLT.
+
+template<int size, bool big_endian>
+unsigned int
+Target_aarch64<size, big_endian>::plt_entry_count() const
+{
+  if (this->plt_ == NULL)
+    return 0;
+  return this->plt_->entry_count();
+}
+
+// Return the offset of the first non-reserved PLT entry.
+
+template<int size, bool big_endian>
+unsigned int
+Target_aarch64<size, big_endian>::first_plt_entry_offset() const
+{
+  return this->plt_->first_plt_entry_offset();
+}
+
+// Return the size of each PLT entry.
+
+template<int size, bool big_endian>
+unsigned int
+Target_aarch64<size, big_endian>::plt_entry_size() const
+{
+  return this->plt_->get_plt_entry_size();
+}
+
+// Optimize the TLS relocation type based on what we know about the
+// symbol.  IS_FINAL is true if the final address of this symbol is
+// known at link time.
+
+template<int size, bool big_endian>
+tls::Tls_optimization
+Target_aarch64<size, big_endian>::optimize_tls_reloc(bool /* is_final */,
+                                                     int /* r_type */)
+{
+  //TODO
+  return tls::TLSOPT_NONE;
+}
+
+// Get the Reference_flags for a particular relocation.
+template<int size, bool big_endian>
+int
+Target_aarch64<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case elfcpp::R_AARCH64_NONE:
+      // No symbol reference.
+      return 0;
+    //TODO
+    default:
+      // Not expected. We will give an error later.
+    return 0;
+    }
+}
+
+// Returns true if this relocation type could be that of a function pointer.
+
+template<int size, bool big_endian>
+inline bool
+Target_aarch64<size, big_endian>::Scan::possible_function_pointer_reloc(
+  unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case elfcpp::R_AARCH64_ABS64:
+    //TODO
+      {
+        return true;
+      }
+    }
+  return false;
+}
+
+// For safe ICF, scan a relocation for a local symbol to check if it
+// corresponds to a function pointer being taken.  In that case mark
+// the function whose pointer was taken as not foldable.
+
+template<int size, bool big_endian>
+inline bool
+Target_aarch64<size, big_endian>::Scan::local_reloc_may_be_function_pointer(
+  Symbol_table* ,
+  Layout* ,
+  Target_aarch64<size, big_endian>* ,
+  Sized_relobj_file<size, big_endian>* ,
+  unsigned int ,
+  Output_section* ,
+  const elfcpp::Rela<size, big_endian>& ,
+  unsigned int r_type,
+  const elfcpp::Sym<size, big_endian>&)
+{
+  // When building a shared library, do not fold any local symbols as it is
+  // not possible to distinguish pointer taken versus a call by looking at
+  // the relocation types.
+  return (parameters->options().shared()
+          || possible_function_pointer_reloc(r_type));
+}
+
+// For safe ICF, scan a relocation for a global symbol to check if it
+// corresponds to a function pointer being taken.  In that case mark
+// the function whose pointer was taken as not foldable.
+
+template<int size, bool big_endian>
+inline bool
+Target_aarch64<size, big_endian>::Scan::global_reloc_may_be_function_pointer(
+  Symbol_table* ,
+  Layout* ,
+  Target_aarch64<size, big_endian>* ,
+  Sized_relobj_file<size, big_endian>* ,
+  unsigned int ,
+  Output_section* ,
+  const elfcpp::Rela<size, big_endian>& ,
+  unsigned int r_type,
+  Symbol* gsym)
+{
+  // When building a shared library, do not fold symbols whose visibility
+  // is hidden, internal or protected.
+  return ((parameters->options().shared()
+           && (gsym->visibility() == elfcpp::STV_INTERNAL
+               || gsym->visibility() == elfcpp::STV_PROTECTED
+               || gsym->visibility() == elfcpp::STV_HIDDEN))
+          || possible_function_pointer_reloc(r_type));
+}
+
+// Report an unsupported relocation against a local symbol.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::Scan::unsupported_reloc_local(
+     Sized_relobj_file<size, big_endian>* object,
+     unsigned int r_type)
+{
+  gold_error(_("%s: unsupported reloc %u against local symbol"),
+	     object->name().c_str(), r_type);
+}
+
+// We are about to emit a dynamic relocation of type R_TYPE.  If the
+// dynamic linker does not support it, issue an error.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::Scan::check_non_pic(Relobj* object,
+                                                      unsigned int r_type)
+{
+  gold_assert(r_type != elfcpp::R_AARCH64_NONE);
+
+  switch (r_type)
+    {
+    // These are the relocation types supported by glibc for AARCH64.
+    case elfcpp::R_AARCH64_NONE:
+    case elfcpp::R_AARCH64_COPY:
+    case elfcpp::R_AARCH64_GLOB_DAT:
+    case elfcpp::R_AARCH64_JUMP_SLOT:
+    case elfcpp::R_AARCH64_RELATIVE:
+    case elfcpp::R_AARCH64_TLS_DTPREL64:
+    case elfcpp::R_AARCH64_TLS_DTPMOD64:
+    case elfcpp::R_AARCH64_TLS_TPREL64:
+    case elfcpp::R_AARCH64_TLSDESC:
+    case elfcpp::R_AARCH64_IRELATIVE:
+    case elfcpp::R_AARCH64_ABS32:
+    case elfcpp::R_AARCH64_ABS64:
+      return;
+
+    default:
+      break;
+    }
+
+  // This prevents us from issuing more than one error per reloc
+  // section. But we can still wind up issuing more than one
+  // error per object file.
+  if (this->issued_non_pic_error_)
+    return;
+  gold_assert(parameters->options().output_is_position_independent());
+  object->error(_("requires unsupported dynamic reloc; "
+                  "recompile with -fPIC"));
+  this->issued_non_pic_error_ = true;
+  return;
+}
+
+// Scan a relocation for a local symbol.
+
+template<int size, bool big_endian>
+inline void
+Target_aarch64<size, big_endian>::Scan::local(
+    Symbol_table* /* symtab */,
+    Layout* /* layout */,
+    Target_aarch64<size, big_endian>* /* target */,
+    Sized_relobj_file<size, big_endian>* /* object */,
+    unsigned int /* data_shndx */,
+    Output_section* /* output_section */,
+    const elfcpp::Rela<size, big_endian>& /* reloc */,
+    unsigned int r_type,
+    const elfcpp::Sym<size, big_endian>& /* lsym */,
+    bool is_discarded)
+{
+  if (is_discarded)
+    return;
+
+  switch (r_type)
+    {
+    case elfcpp::R_AARCH64_NONE:
+      break;
+
+      //TODO
+    }
+}
+
+
+// Report an unsupported relocation against a global symbol.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::Scan::unsupported_reloc_global(
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int r_type,
+    Symbol* gsym)
+{
+  gold_error(_("%s: unsupported reloc %u against global symbol %s"),
+	     object->name().c_str(), r_type, gsym->demangled_name().c_str());
+}
+
+template<int size, bool big_endian>
+inline void
+Target_aarch64<size, big_endian>::Scan::global(
+    Symbol_table* /* symtab */,
+    Layout* /* layout */,
+    Target_aarch64<size, big_endian>* /* target */,
+    Sized_relobj_file<size, big_endian>* /* object */,
+    unsigned int /* data_shndx */,
+    Output_section* /* output_section */,
+    const elfcpp::Rela<size, big_endian>& /* reloc */,
+    unsigned int /* r_type */,
+    Symbol* /* gsym */)
+{
+  //TODO
+  return;
+}
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::gc_process_relocs(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_symbols)
+{
+  if (sh_type == elfcpp::SHT_REL)
+    {
+      return;
+    }
+
+  gold::gc_process_relocs<size, big_endian,
+                          Target_aarch64<size, big_endian>,
+                          elfcpp::SHT_RELA,
+                          typename Target_aarch64<size, big_endian>::Scan,
+                          typename Target_aarch64<size, big_endian>::Relocatable_size_for_reloc>(
+    symtab,
+    layout,
+    this,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_symbols);
+}
+
+// Scan relocations for a section.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::scan_relocs(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_symbols)
+{
+  if (sh_type == elfcpp::SHT_REL)
+    {
+      gold_error(_("%s: unsupported REL reloc section"),
+		 object->name().c_str());
+      return;
+    }
+
+  gold::scan_relocs<size, big_endian, Target_aarch64<size, big_endian>,
+                    elfcpp::SHT_RELA,
+                    typename Target_aarch64<size, big_endian>::Scan>(
+    symtab,
+    layout,
+    this,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_symbols);
+}
+
+// Finalize the sections.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::do_finalize_sections(
+    Layout* /* layout */,
+    const Input_objects*,
+    Symbol_table* /* symtab */)
+{
+  //TODO
+  return;
+}
+
+// Perform a relocation.
+
+template<int size, bool big_endian>
+inline bool
+Target_aarch64<size, big_endian>::Relocate::relocate(
+    const Relocate_info<size, big_endian>* /* relinfo */,
+    Target_aarch64<size, big_endian>* /* target */,
+    Output_section* ,
+    size_t /* relnum */,
+    const elfcpp::Rela<size, big_endian>& /* rela */,
+    unsigned int /* r_type */,
+    const Sized_symbol<size>* /* gsym */,
+    const Symbol_value<size>* /* psymval */,
+    unsigned char* /* view */,
+    typename elfcpp::Elf_types<size>::Elf_Addr /* address */,
+    section_size_type /* view_size */)
+{
+  //TODO
+  return true;
+}
+
+// Relocate section data.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::relocate_section(
+    const Relocate_info<size, big_endian>* /* relinfo */,
+    unsigned int sh_type,
+    const unsigned char* /* prelocs */,
+    size_t /* reloc_count */,
+    Output_section* /* output_section */,
+    bool /*needs_special_offset_handling */,
+    unsigned char* /* view */,
+    typename elfcpp::Elf_types<size>::Elf_Addr /* address */,
+    section_size_type /* view_size */,
+    const Reloc_symbol_changes* /* reloc_symbol_changes */)
+{
+  //TODO
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+}
+
+// Return the size of a relocation while scanning during a relocatable
+// link.
+
+template<int size, bool big_endian>
+unsigned int
+Target_aarch64<size, big_endian>::Relocatable_size_for_reloc::
+get_size_for_reloc(
+    unsigned int ,
+    Relobj* )
+{
+  // We will never support SHT_REL relocations.
+  gold_unreachable();
+  return 0;
+}
+
+// Scan the relocs during a relocatable link.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::scan_relocatable_relocs(
+    Symbol_table* /* symtab */,
+    Layout* /* layout */,
+    Sized_relobj_file<size, big_endian>* /* object */,
+    unsigned int /* data_shndx */,
+    unsigned int sh_type,
+    const unsigned char* /* prelocs */,
+    size_t /* reloc_count */,
+    Output_section* /* output_section */,
+    bool /* needs_special_offset_handling */,
+    size_t /* local_symbol_count */,
+    const unsigned char* /* plocal_symbols */,
+    Relocatable_relocs* /* rr */)
+{
+  //TODO
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+}
+
+// Relocate a section during a relocatable link.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::relocate_relocs(
+    const Relocate_info<size, big_endian>* /* relinfo */,
+    unsigned int sh_type,
+    const unsigned char* /* prelocs */,
+    size_t /* reloc_count */,
+    Output_section* /* output_section */,
+    typename elfcpp::Elf_types<size>::Elf_Off /* offset_in_output_section */,
+    const Relocatable_relocs* /* rr */,
+    unsigned char* /* view */,
+    typename elfcpp::Elf_types<size>::Elf_Addr /* view_address */,
+    section_size_type /* view_size */,
+    unsigned char* /* reloc_view */,
+    section_size_type /* reloc_view_size */)
+{
+  //TODO
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+}
+
+
+// The selector for aarch64 object files.
+
+template<int size, bool big_endian>
+class Target_selector_aarch64 : public Target_selector
+{
+ public:
+  Target_selector_aarch64()
+    : Target_selector(elfcpp::EM_AARCH64, size, big_endian,
+                      (size == 64
+                       ? (big_endian ? "elf64-bigaarch64"
+                                     : "elf64-littleaarch64")
+                       : (big_endian ? "elf32-bigaarch64"
+                                     : "elf32-littleaarch64")),
+                      (size == 64
+                       ? (big_endian ? "aarch64_elf64_be_vec"
+                                     : "aarch64_elf64_le_vec")
+                       : (big_endian ? "aarch64_elf32_be_vec"
+                                     : "aarch64_elf32_le_vec")))
+  { }
+
+  virtual Target*
+  do_instantiate_target()
+  { return new Target_aarch64<size, big_endian>(); }
+};
+
+Target_selector_aarch64<32, true> target_selector_aarch64elf32b;
+Target_selector_aarch64<32, false> target_selector_aarch64elf32;
+Target_selector_aarch64<64, true> target_selector_aarch64elfb;
+Target_selector_aarch64<64, false> target_selector_aarch64elf;
+
+
+} // End anonymous namespace.
diff --git a/gold/configure b/gold/configure
index 9880635..7d7b849 100755
--- a/gold/configure
+++ b/gold/configure
@@ -698,6 +698,8 @@ DEFAULT_TARGET_I386_FALSE
 DEFAULT_TARGET_I386_TRUE
 DEFAULT_TARGET_ARM_FALSE
 DEFAULT_TARGET_ARM_TRUE
+DEFAULT_TARGET_AARCH64_FALSE
+DEFAULT_TARGET_AARCH64_TRUE
 PLUGINS_FALSE
 PLUGINS_TRUE
 THREADS_FALSE
@@ -3433,6 +3435,14 @@ for targ in $target $canon_targets; do
 	default_big_endian=$targ_big_endian
 	default_osabi=$targ_osabi
 
+	 if test "$targ_obj" = "aarch64"; then
+  DEFAULT_TARGET_AARCH64_TRUE=
+  DEFAULT_TARGET_AARCH64_FALSE='#'
+else
+  DEFAULT_TARGET_AARCH64_TRUE='#'
+  DEFAULT_TARGET_AARCH64_FALSE=
+fi
+
 	 if test "$targ_obj" = "arm"; then
   DEFAULT_TARGET_ARM_TRUE=
   DEFAULT_TARGET_ARM_FALSE='#'
@@ -7777,6 +7787,10 @@ if test -z "${PLUGINS_TRUE}" && test -z "${PLUGINS_FALSE}"; then
   as_fn_error "conditional \"PLUGINS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${DEFAULT_TARGET_AARCH64_TRUE}" && test -z "${DEFAULT_TARGET_AARCH64_FALSE}"; then
+  as_fn_error "conditional \"DEFAULT_TARGET_AARCH64\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${DEFAULT_TARGET_ARM_TRUE}" && test -z "${DEFAULT_TARGET_ARM_FALSE}"; then
   as_fn_error "conditional \"DEFAULT_TARGET_ARM\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/gold/configure.ac b/gold/configure.ac
index 14ecd72..0478011 100644
--- a/gold/configure.ac
+++ b/gold/configure.ac
@@ -199,6 +199,7 @@ for targ in $target $canon_targets; do
 	default_big_endian=$targ_big_endian
 	default_osabi=$targ_osabi
 
+	AM_CONDITIONAL(DEFAULT_TARGET_AARCH64, test "$targ_obj" = "aarch64")
 	AM_CONDITIONAL(DEFAULT_TARGET_ARM, test "$targ_obj" = "arm")
 	AM_CONDITIONAL(DEFAULT_TARGET_I386, test "$targ_obj" = "i386")
 	AM_CONDITIONAL(DEFAULT_TARGET_POWERPC, test "$targ_obj" = "powerpc")
diff --git a/gold/configure.tgt b/gold/configure.tgt
index 93d622d..eaf164b 100644
--- a/gold/configure.tgt
+++ b/gold/configure.tgt
@@ -144,6 +144,14 @@ arm*-*-*)
  targ_big_endian=false
  targ_extra_big_endian=true
  ;;
+aarch64-*)
+ targ_obj=aarch64
+ targ_machine=EM_AARCH64
+ targ_size=64
+ targ_extra_size=32
+ targ_big_endian=false
+ targ_extra_big_endian=true
+ ;;
 mips*el*-*-*|mips*le*-*-*)
  targ_obj=mips
  targ_machine=EM_MIPS_RS3_LE

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

* Re: [gold] First patch for aarch64 backend
  2014-06-25 23:47 [gold] First patch for aarch64 backend Jing Yu
@ 2014-07-01 21:55 ` Cary Coutant
  2014-07-01 22:15 ` Yufeng Zhang
  1 sibling, 0 replies; 8+ messages in thread
From: Cary Coutant @ 2014-07-01 21:55 UTC (permalink / raw)
  To: Jing Yu; +Cc: Binutils, Han Shen, Doug Kwan

> We start to work on gold aarch64 backend. Here is the first patch.
> This patch is just a skeleton which almost does nothing.
> The change that enables gold for aarch64 in top level configure was
> removed from this patch.

Please prepare ChangeLog entries (one for elfcpp/ and one for gold/).

In gold/aarch64.cc:

+ // Copyright (C) 2006-2014 Free Software Foundation, Inc.

This being a new file, it should just read "2014".

Otherwise, this is OK.

Thanks!

-cary

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

* Re: [gold] First patch for aarch64 backend
  2014-06-25 23:47 [gold] First patch for aarch64 backend Jing Yu
  2014-07-01 21:55 ` Cary Coutant
@ 2014-07-01 22:15 ` Yufeng Zhang
  2014-07-01 23:06   ` Jing Yu
  1 sibling, 1 reply; 8+ messages in thread
From: Yufeng Zhang @ 2014-07-01 22:15 UTC (permalink / raw)
  To: Jing Yu; +Cc: binutils, Han Shen, Doug Kwan, Cary Coutant

On 26 June 2014 00:46, Jing Yu <jingyu@google.com> wrote:
>
> Hi,
>
> We start to work on gold aarch64 backend. Here is the first patch.
> This patch is just a skeleton which almost does nothing.
> The change that enables gold for aarch64 in top level configure was
> removed from this patch.
>
> Tested:
> 1) On x86_64,
> ${binutils}/configure --build=x86_64-unknown-linux-gnu
> --host=x86_64-unknown-linux-gnu --target=x86_64-unknown-linux-gnu
> --enable-plugins --disable-multilib --disable-nls --enable-threads
> --enable-gold=default --enable-targets=all
> $make all-gold
>
> Also built with -O1 and -O0.
>
> 2) On aarch64,
> gcc version 4.8.2 (Ubuntu/Linaro 4.8.2-19ubuntu1)
> $ ../binutils-gdb/configure --enable-plugins --disable-multilib
> --disable-nls --enable-threads --enable-gold=default
> --enable-targets=all
> $make all-gold
> Also built with -O1 and -O0.
>
> The generated native gold/ld-new is able to read hello.o and libc.so.
>
> Thanks,
> Jing
>
> diff --git a/elfcpp/aarch64.h b/elfcpp/aarch64.h
> new file mode 100644
> index 0000000..09bc498
> --- /dev/null
> +++ b/elfcpp/aarch64.h
> @@ -0,0 +1,183 @@
> +// aarch64.h -- ELF definitions specific to AARCH64  -*- C++ -*-
> +
> +// Copyright (C) 2012-2014 Free Software Foundation, Inc.
> +// Written by Jing Yu (jingyu@google.com)
> +
> +// This file is part of elfcpp.
> +
> +// This program is free software; you can redistribute it and/or
> +// modify it under the terms of the GNU Library General Public License
> +// as published by the Free Software Foundation; either version 2, or
> +// (at your option) any later version.
> +
> +// In addition to the permissions in the GNU Library General Public
> +// License, the Free Software Foundation gives you unlimited
> +// permission to link the compiled version of this file into
> +// combinations with other programs, and to distribute those
> +// combinations without any restriction coming from the use of this
> +// file.  (The Library Public License restrictions do apply in other
> +// respects; for example, they cover modification of the file, and
> +/// distribution when not linked into a combined executable.)
> +
> +// 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
> +// Library General Public License for more details.
> +
> +// You should have received a copy of the GNU Library 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.
> +
> +#ifndef ELFCPP_AARCH64_H
> +#define ELFCPP_AARCH64_H
> +
> +namespace elfcpp
> +{
> +
> +// The relocation type information is taken from:
> +//
> +//   ELF for the ARM 64-bit Architecture (AArch64)
> +//   Document number: ARM IHI 0056B, current through AArch64 ABI release 1.0
> +//   Date of Issue: 22nd May, 2013
> +//

Is there a particular reason that you didn’t choose the ABI release
1.1 which has the support for ELF32, including the ELF32 relocation
codes?

> +
> +enum
> +{
> +  // Null relocation codes
> +  R_AARCH64_NONE = 0, // None
> +  withdrawn = 256, // Treat as R_AARCH64_NONE
> +
> +  // Static relocations
> +  R_AARCH64_ABS64 = 257, // S + A
> +  R_AARCH64_ABS32 = 258, // S + A
> +  R_AARCH64_ABS16 = 259, // S + A
> +  R_AARCH64_PREL64 = 260, // S + A - P
> +  R_AARCH64_PREL32 = 261, // S + A - P
> +  R_AARCH64_PREL16 = 262, // S + A - P
> +  R_AARCH64_MOVW_UABS_G0 = 263, // S + A
> +  R_AARCH64_MOVW_UABS_G0_NC = 264, // S + A
> +  R_AARCH64_MOVW_UABS_G1 = 265, // S + A

[snip]

> diff --git a/gold/configure.tgt b/gold/configure.tgt
> index 93d622d..eaf164b 100644
> --- a/gold/configure.tgt
> +++ b/gold/configure.tgt
> @@ -144,6 +144,14 @@ arm*-*-*)
>   targ_big_endian=false
>   targ_extra_big_endian=true
>   ;;
> +aarch64-*)

I think you'll need aarch64*-* in order to support targ_extra_size=32
and targ_extra_big_endian=true.

Yufeng

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

* Re: [gold] First patch for aarch64 backend
  2014-07-01 22:15 ` Yufeng Zhang
@ 2014-07-01 23:06   ` Jing Yu
  2014-07-01 23:09     ` Andrew Pinski
  0 siblings, 1 reply; 8+ messages in thread
From: Jing Yu @ 2014-07-01 23:06 UTC (permalink / raw)
  To: Yufeng Zhang; +Cc: binutils, Han Shen, Doug Kwan, Cary Coutant

On Tue, Jul 1, 2014 at 3:15 PM, Yufeng Zhang <yufengzhangdev@gmail.com> wrote:
> On 26 June 2014 00:46, Jing Yu <jingyu@google.com> wrote:
>>
>> Hi,
>>
>> We start to work on gold aarch64 backend. Here is the first patch.
>> This patch is just a skeleton which almost does nothing.
>> The change that enables gold for aarch64 in top level configure was
>> removed from this patch.
>>
>> Tested:
>> 1) On x86_64,
>> ${binutils}/configure --build=x86_64-unknown-linux-gnu
>> --host=x86_64-unknown-linux-gnu --target=x86_64-unknown-linux-gnu
>> --enable-plugins --disable-multilib --disable-nls --enable-threads
>> --enable-gold=default --enable-targets=all
>> $make all-gold
>>
>> Also built with -O1 and -O0.
>>
>> 2) On aarch64,
>> gcc version 4.8.2 (Ubuntu/Linaro 4.8.2-19ubuntu1)
>> $ ../binutils-gdb/configure --enable-plugins --disable-multilib
>> --disable-nls --enable-threads --enable-gold=default
>> --enable-targets=all
>> $make all-gold
>> Also built with -O1 and -O0.
>>
>> The generated native gold/ld-new is able to read hello.o and libc.so.
>>
>> Thanks,
>> Jing
>>
>> diff --git a/elfcpp/aarch64.h b/elfcpp/aarch64.h
>> new file mode 100644
>> index 0000000..09bc498
>> --- /dev/null
>> +++ b/elfcpp/aarch64.h
>> @@ -0,0 +1,183 @@
>> +// aarch64.h -- ELF definitions specific to AARCH64  -*- C++ -*-
>> +
>> +// Copyright (C) 2012-2014 Free Software Foundation, Inc.
>> +// Written by Jing Yu (jingyu@google.com)
>> +
>> +// This file is part of elfcpp.
>> +
>> +// This program is free software; you can redistribute it and/or
>> +// modify it under the terms of the GNU Library General Public License
>> +// as published by the Free Software Foundation; either version 2, or
>> +// (at your option) any later version.
>> +
>> +// In addition to the permissions in the GNU Library General Public
>> +// License, the Free Software Foundation gives you unlimited
>> +// permission to link the compiled version of this file into
>> +// combinations with other programs, and to distribute those
>> +// combinations without any restriction coming from the use of this
>> +// file.  (The Library Public License restrictions do apply in other
>> +// respects; for example, they cover modification of the file, and
>> +/// distribution when not linked into a combined executable.)
>> +
>> +// 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
>> +// Library General Public License for more details.
>> +
>> +// You should have received a copy of the GNU Library 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.
>> +
>> +#ifndef ELFCPP_AARCH64_H
>> +#define ELFCPP_AARCH64_H
>> +
>> +namespace elfcpp
>> +{
>> +
>> +// The relocation type information is taken from:
>> +//
>> +//   ELF for the ARM 64-bit Architecture (AArch64)
>> +//   Document number: ARM IHI 0056B, current through AArch64 ABI release 1.0
>> +//   Date of Issue: 22nd May, 2013
>> +//
>
> Is there a particular reason that you didn’t choose the ABI release
> 1.1 which has the support for ELF32, including the ELF32 relocation
> codes?
>
We don't have a plan to support ELF32 in anytime soon.
The document that describes ELF32 relocations is a beta proposal.

>> +
>> +enum
>> +{
>> +  // Null relocation codes
>> +  R_AARCH64_NONE = 0, // None
>> +  withdrawn = 256, // Treat as R_AARCH64_NONE
>> +
>> +  // Static relocations
>> +  R_AARCH64_ABS64 = 257, // S + A
>> +  R_AARCH64_ABS32 = 258, // S + A
>> +  R_AARCH64_ABS16 = 259, // S + A
>> +  R_AARCH64_PREL64 = 260, // S + A - P
>> +  R_AARCH64_PREL32 = 261, // S + A - P
>> +  R_AARCH64_PREL16 = 262, // S + A - P
>> +  R_AARCH64_MOVW_UABS_G0 = 263, // S + A
>> +  R_AARCH64_MOVW_UABS_G0_NC = 264, // S + A
>> +  R_AARCH64_MOVW_UABS_G1 = 265, // S + A
>
> [snip]
>
>> diff --git a/gold/configure.tgt b/gold/configure.tgt
>> index 93d622d..eaf164b 100644
>> --- a/gold/configure.tgt
>> +++ b/gold/configure.tgt
>> @@ -144,6 +144,14 @@ arm*-*-*)
>>   targ_big_endian=false
>>   targ_extra_big_endian=true
>>   ;;
>> +aarch64-*)
>
> I think you'll need aarch64*-* in order to support targ_extra_size=32
> and targ_extra_big_endian=true.
>
Will do. Thanks!
Jing

> Yufeng

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

* Re: [gold] First patch for aarch64 backend
  2014-07-01 23:06   ` Jing Yu
@ 2014-07-01 23:09     ` Andrew Pinski
  2014-07-01 23:14       ` Andrew Pinski
  2014-07-01 23:21       ` Jing Yu
  0 siblings, 2 replies; 8+ messages in thread
From: Andrew Pinski @ 2014-07-01 23:09 UTC (permalink / raw)
  To: Jing Yu; +Cc: Yufeng Zhang, binutils, Han Shen, Doug Kwan, Cary Coutant

On Tue, Jul 1, 2014 at 4:06 PM, Jing Yu <jingyu@google.com> wrote:
> On Tue, Jul 1, 2014 at 3:15 PM, Yufeng Zhang <yufengzhangdev@gmail.com> wrote:
>> On 26 June 2014 00:46, Jing Yu <jingyu@google.com> wrote:
>>>
>>> Hi,
>>>
>>> We start to work on gold aarch64 backend. Here is the first patch.
>>> This patch is just a skeleton which almost does nothing.
>>> The change that enables gold for aarch64 in top level configure was
>>> removed from this patch.
>>>
>>> Tested:
>>> 1) On x86_64,
>>> ${binutils}/configure --build=x86_64-unknown-linux-gnu
>>> --host=x86_64-unknown-linux-gnu --target=x86_64-unknown-linux-gnu
>>> --enable-plugins --disable-multilib --disable-nls --enable-threads
>>> --enable-gold=default --enable-targets=all
>>> $make all-gold
>>>
>>> Also built with -O1 and -O0.
>>>
>>> 2) On aarch64,
>>> gcc version 4.8.2 (Ubuntu/Linaro 4.8.2-19ubuntu1)
>>> $ ../binutils-gdb/configure --enable-plugins --disable-multilib
>>> --disable-nls --enable-threads --enable-gold=default
>>> --enable-targets=all
>>> $make all-gold
>>> Also built with -O1 and -O0.
>>>
>>> The generated native gold/ld-new is able to read hello.o and libc.so.
>>>
>>> Thanks,
>>> Jing
>>>
>>> diff --git a/elfcpp/aarch64.h b/elfcpp/aarch64.h
>>> new file mode 100644
>>> index 0000000..09bc498
>>> --- /dev/null
>>> +++ b/elfcpp/aarch64.h
>>> @@ -0,0 +1,183 @@
>>> +// aarch64.h -- ELF definitions specific to AARCH64  -*- C++ -*-
>>> +
>>> +// Copyright (C) 2012-2014 Free Software Foundation, Inc.
>>> +// Written by Jing Yu (jingyu@google.com)
>>> +
>>> +// This file is part of elfcpp.
>>> +
>>> +// This program is free software; you can redistribute it and/or
>>> +// modify it under the terms of the GNU Library General Public License
>>> +// as published by the Free Software Foundation; either version 2, or
>>> +// (at your option) any later version.
>>> +
>>> +// In addition to the permissions in the GNU Library General Public
>>> +// License, the Free Software Foundation gives you unlimited
>>> +// permission to link the compiled version of this file into
>>> +// combinations with other programs, and to distribute those
>>> +// combinations without any restriction coming from the use of this
>>> +// file.  (The Library Public License restrictions do apply in other
>>> +// respects; for example, they cover modification of the file, and
>>> +/// distribution when not linked into a combined executable.)
>>> +
>>> +// 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
>>> +// Library General Public License for more details.
>>> +
>>> +// You should have received a copy of the GNU Library 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.
>>> +
>>> +#ifndef ELFCPP_AARCH64_H
>>> +#define ELFCPP_AARCH64_H
>>> +
>>> +namespace elfcpp
>>> +{
>>> +
>>> +// The relocation type information is taken from:
>>> +//
>>> +//   ELF for the ARM 64-bit Architecture (AArch64)
>>> +//   Document number: ARM IHI 0056B, current through AArch64 ABI release 1.0
>>> +//   Date of Issue: 22nd May, 2013
>>> +//
>>
>> Is there a particular reason that you didn’t choose the ABI release
>> 1.1 which has the support for ELF32, including the ELF32 relocation
>> codes?
>>
> We don't have a plan to support ELF32 in anytime soon.
> The document that describes ELF32 relocations is a beta proposal.ELF_PLATFORM

Why not?  The Linux kernel support for ILP32 is in review right now.
And I will be submitting the glibc support right after the kernel
support goes in.

They are only beta because ARM does not want to commit to them until
an implementation is upstream.  Yes it is a catch 22 though.

Thanks,
Andrew Pinski


>
>>> +
>>> +enum
>>> +{
>>> +  // Null relocation codes
>>> +  R_AARCH64_NONE = 0, // None
>>> +  withdrawn = 256, // Treat as R_AARCH64_NONE
>>> +
>>> +  // Static relocations
>>> +  R_AARCH64_ABS64 = 257, // S + A
>>> +  R_AARCH64_ABS32 = 258, // S + A
>>> +  R_AARCH64_ABS16 = 259, // S + A
>>> +  R_AARCH64_PREL64 = 260, // S + A - P
>>> +  R_AARCH64_PREL32 = 261, // S + A - P
>>> +  R_AARCH64_PREL16 = 262, // S + A - P
>>> +  R_AARCH64_MOVW_UABS_G0 = 263, // S + A
>>> +  R_AARCH64_MOVW_UABS_G0_NC = 264, // S + A
>>> +  R_AARCH64_MOVW_UABS_G1 = 265, // S + A
>>
>> [snip]
>>
>>> diff --git a/gold/configure.tgt b/gold/configure.tgt
>>> index 93d622d..eaf164b 100644
>>> --- a/gold/configure.tgt
>>> +++ b/gold/configure.tgt
>>> @@ -144,6 +144,14 @@ arm*-*-*)
>>>   targ_big_endian=false
>>>   targ_extra_big_endian=true
>>>   ;;
>>> +aarch64-*)
>>
>> I think you'll need aarch64*-* in order to support targ_extra_size=32
>> and targ_extra_big_endian=true.
>>
> Will do. Thanks!
> Jing
>
>> Yufeng

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

* Re: [gold] First patch for aarch64 backend
  2014-07-01 23:09     ` Andrew Pinski
@ 2014-07-01 23:14       ` Andrew Pinski
  2014-07-01 23:21       ` Jing Yu
  1 sibling, 0 replies; 8+ messages in thread
From: Andrew Pinski @ 2014-07-01 23:14 UTC (permalink / raw)
  To: Jing Yu; +Cc: Yufeng Zhang, binutils, Han Shen, Doug Kwan, Cary Coutant

On Tue, Jul 1, 2014 at 4:09 PM, Andrew Pinski <pinskia@gmail.com> wrote:
> On Tue, Jul 1, 2014 at 4:06 PM, Jing Yu <jingyu@google.com> wrote:
>> On Tue, Jul 1, 2014 at 3:15 PM, Yufeng Zhang <yufengzhangdev@gmail.com> wrote:
>>> On 26 June 2014 00:46, Jing Yu <jingyu@google.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> We start to work on gold aarch64 backend. Here is the first patch.
>>>> This patch is just a skeleton which almost does nothing.
>>>> The change that enables gold for aarch64 in top level configure was
>>>> removed from this patch.
>>>>
>>>> Tested:
>>>> 1) On x86_64,
>>>> ${binutils}/configure --build=x86_64-unknown-linux-gnu
>>>> --host=x86_64-unknown-linux-gnu --target=x86_64-unknown-linux-gnu
>>>> --enable-plugins --disable-multilib --disable-nls --enable-threads
>>>> --enable-gold=default --enable-targets=all
>>>> $make all-gold
>>>>
>>>> Also built with -O1 and -O0.
>>>>
>>>> 2) On aarch64,
>>>> gcc version 4.8.2 (Ubuntu/Linaro 4.8.2-19ubuntu1)
>>>> $ ../binutils-gdb/configure --enable-plugins --disable-multilib
>>>> --disable-nls --enable-threads --enable-gold=default
>>>> --enable-targets=all
>>>> $make all-gold
>>>> Also built with -O1 and -O0.
>>>>
>>>> The generated native gold/ld-new is able to read hello.o and libc.so.
>>>>
>>>> Thanks,
>>>> Jing
>>>>
>>>> diff --git a/elfcpp/aarch64.h b/elfcpp/aarch64.h
>>>> new file mode 100644
>>>> index 0000000..09bc498
>>>> --- /dev/null
>>>> +++ b/elfcpp/aarch64.h
>>>> @@ -0,0 +1,183 @@
>>>> +// aarch64.h -- ELF definitions specific to AARCH64  -*- C++ -*-
>>>> +
>>>> +// Copyright (C) 2012-2014 Free Software Foundation, Inc.
>>>> +// Written by Jing Yu (jingyu@google.com)
>>>> +
>>>> +// This file is part of elfcpp.
>>>> +
>>>> +// This program is free software; you can redistribute it and/or
>>>> +// modify it under the terms of the GNU Library General Public License
>>>> +// as published by the Free Software Foundation; either version 2, or
>>>> +// (at your option) any later version.
>>>> +
>>>> +// In addition to the permissions in the GNU Library General Public
>>>> +// License, the Free Software Foundation gives you unlimited
>>>> +// permission to link the compiled version of this file into
>>>> +// combinations with other programs, and to distribute those
>>>> +// combinations without any restriction coming from the use of this
>>>> +// file.  (The Library Public License restrictions do apply in other
>>>> +// respects; for example, they cover modification of the file, and
>>>> +/// distribution when not linked into a combined executable.)
>>>> +
>>>> +// 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
>>>> +// Library General Public License for more details.
>>>> +
>>>> +// You should have received a copy of the GNU Library 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.
>>>> +
>>>> +#ifndef ELFCPP_AARCH64_H
>>>> +#define ELFCPP_AARCH64_H
>>>> +
>>>> +namespace elfcpp
>>>> +{
>>>> +
>>>> +// The relocation type information is taken from:
>>>> +//
>>>> +//   ELF for the ARM 64-bit Architecture (AArch64)
>>>> +//   Document number: ARM IHI 0056B, current through AArch64 ABI release 1.0
>>>> +//   Date of Issue: 22nd May, 2013
>>>> +//
>>>
>>> Is there a particular reason that you didn’t choose the ABI release
>>> 1.1 which has the support for ELF32, including the ELF32 relocation
>>> codes?
>>>
>> We don't have a plan to support ELF32 in anytime soon.
>> The document that describes ELF32 relocations is a beta proposal.ELF_PLATFORM
>
> Why not?  The Linux kernel support for ILP32 is in review right now.
> And I will be submitting the glibc support right after the kernel
> support goes in.
>
> They are only beta because ARM does not want to commit to them until
> an implementation is upstream.  Yes it is a catch 22 though.


In fact I think Android should be looking into support ILP32 also.  It
would make better sense for them.

Thanks,
Andrew Pinski

>
> Thanks,
> Andrew Pinski
>
>
>>
>>>> +
>>>> +enum
>>>> +{
>>>> +  // Null relocation codes
>>>> +  R_AARCH64_NONE = 0, // None
>>>> +  withdrawn = 256, // Treat as R_AARCH64_NONE
>>>> +
>>>> +  // Static relocations
>>>> +  R_AARCH64_ABS64 = 257, // S + A
>>>> +  R_AARCH64_ABS32 = 258, // S + A
>>>> +  R_AARCH64_ABS16 = 259, // S + A
>>>> +  R_AARCH64_PREL64 = 260, // S + A - P
>>>> +  R_AARCH64_PREL32 = 261, // S + A - P
>>>> +  R_AARCH64_PREL16 = 262, // S + A - P
>>>> +  R_AARCH64_MOVW_UABS_G0 = 263, // S + A
>>>> +  R_AARCH64_MOVW_UABS_G0_NC = 264, // S + A
>>>> +  R_AARCH64_MOVW_UABS_G1 = 265, // S + A
>>>
>>> [snip]
>>>
>>>> diff --git a/gold/configure.tgt b/gold/configure.tgt
>>>> index 93d622d..eaf164b 100644
>>>> --- a/gold/configure.tgt
>>>> +++ b/gold/configure.tgt
>>>> @@ -144,6 +144,14 @@ arm*-*-*)
>>>>   targ_big_endian=false
>>>>   targ_extra_big_endian=true
>>>>   ;;
>>>> +aarch64-*)
>>>
>>> I think you'll need aarch64*-* in order to support targ_extra_size=32
>>> and targ_extra_big_endian=true.
>>>
>> Will do. Thanks!
>> Jing
>>
>>> Yufeng

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

* Re: [gold] First patch for aarch64 backend
  2014-07-01 23:09     ` Andrew Pinski
  2014-07-01 23:14       ` Andrew Pinski
@ 2014-07-01 23:21       ` Jing Yu
  2014-07-02 23:26         ` Cary Coutant
  1 sibling, 1 reply; 8+ messages in thread
From: Jing Yu @ 2014-07-01 23:21 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: Yufeng Zhang, binutils, Han Shen, Doug Kwan, Cary Coutant

Yes, ILP32 support may be interesting for ChromeOS and Android.

Given the limited resources, our team have to focus on 64bit now and
leave ILP32 for other developers who are interested to contribute.
We will try our best to consider ILP32 varieties when implementing LP64.

Thanks,
Jing

On Tue, Jul 1, 2014 at 4:09 PM, Andrew Pinski <pinskia@gmail.com> wrote:
> On Tue, Jul 1, 2014 at 4:06 PM, Jing Yu <jingyu@google.com> wrote:
>> On Tue, Jul 1, 2014 at 3:15 PM, Yufeng Zhang <yufengzhangdev@gmail.com> wrote:
>>> On 26 June 2014 00:46, Jing Yu <jingyu@google.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> We start to work on gold aarch64 backend. Here is the first patch.
>>>> This patch is just a skeleton which almost does nothing.
>>>> The change that enables gold for aarch64 in top level configure was
>>>> removed from this patch.
>>>>
>>>> Tested:
>>>> 1) On x86_64,
>>>> ${binutils}/configure --build=x86_64-unknown-linux-gnu
>>>> --host=x86_64-unknown-linux-gnu --target=x86_64-unknown-linux-gnu
>>>> --enable-plugins --disable-multilib --disable-nls --enable-threads
>>>> --enable-gold=default --enable-targets=all
>>>> $make all-gold
>>>>
>>>> Also built with -O1 and -O0.
>>>>
>>>> 2) On aarch64,
>>>> gcc version 4.8.2 (Ubuntu/Linaro 4.8.2-19ubuntu1)
>>>> $ ../binutils-gdb/configure --enable-plugins --disable-multilib
>>>> --disable-nls --enable-threads --enable-gold=default
>>>> --enable-targets=all
>>>> $make all-gold
>>>> Also built with -O1 and -O0.
>>>>
>>>> The generated native gold/ld-new is able to read hello.o and libc.so.
>>>>
>>>> Thanks,
>>>> Jing
>>>>
>>>> diff --git a/elfcpp/aarch64.h b/elfcpp/aarch64.h
>>>> new file mode 100644
>>>> index 0000000..09bc498
>>>> --- /dev/null
>>>> +++ b/elfcpp/aarch64.h
>>>> @@ -0,0 +1,183 @@
>>>> +// aarch64.h -- ELF definitions specific to AARCH64  -*- C++ -*-
>>>> +
>>>> +// Copyright (C) 2012-2014 Free Software Foundation, Inc.
>>>> +// Written by Jing Yu (jingyu@google.com)
>>>> +
>>>> +// This file is part of elfcpp.
>>>> +
>>>> +// This program is free software; you can redistribute it and/or
>>>> +// modify it under the terms of the GNU Library General Public License
>>>> +// as published by the Free Software Foundation; either version 2, or
>>>> +// (at your option) any later version.
>>>> +
>>>> +// In addition to the permissions in the GNU Library General Public
>>>> +// License, the Free Software Foundation gives you unlimited
>>>> +// permission to link the compiled version of this file into
>>>> +// combinations with other programs, and to distribute those
>>>> +// combinations without any restriction coming from the use of this
>>>> +// file.  (The Library Public License restrictions do apply in other
>>>> +// respects; for example, they cover modification of the file, and
>>>> +/// distribution when not linked into a combined executable.)
>>>> +
>>>> +// 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
>>>> +// Library General Public License for more details.
>>>> +
>>>> +// You should have received a copy of the GNU Library 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.
>>>> +
>>>> +#ifndef ELFCPP_AARCH64_H
>>>> +#define ELFCPP_AARCH64_H
>>>> +
>>>> +namespace elfcpp
>>>> +{
>>>> +
>>>> +// The relocation type information is taken from:
>>>> +//
>>>> +//   ELF for the ARM 64-bit Architecture (AArch64)
>>>> +//   Document number: ARM IHI 0056B, current through AArch64 ABI release 1.0
>>>> +//   Date of Issue: 22nd May, 2013
>>>> +//
>>>
>>> Is there a particular reason that you didn’t choose the ABI release
>>> 1.1 which has the support for ELF32, including the ELF32 relocation
>>> codes?
>>>
>> We don't have a plan to support ELF32 in anytime soon.
>> The document that describes ELF32 relocations is a beta proposal.ELF_PLATFORM
>
> Why not?  The Linux kernel support for ILP32 is in review right now.
> And I will be submitting the glibc support right after the kernel
> support goes in.
>
> They are only beta because ARM does not want to commit to them until
> an implementation is upstream.  Yes it is a catch 22 though.
>
> Thanks,
> Andrew Pinski
>
>
>>
>>>> +
>>>> +enum
>>>> +{
>>>> +  // Null relocation codes
>>>> +  R_AARCH64_NONE = 0, // None
>>>> +  withdrawn = 256, // Treat as R_AARCH64_NONE
>>>> +
>>>> +  // Static relocations
>>>> +  R_AARCH64_ABS64 = 257, // S + A
>>>> +  R_AARCH64_ABS32 = 258, // S + A
>>>> +  R_AARCH64_ABS16 = 259, // S + A
>>>> +  R_AARCH64_PREL64 = 260, // S + A - P
>>>> +  R_AARCH64_PREL32 = 261, // S + A - P
>>>> +  R_AARCH64_PREL16 = 262, // S + A - P
>>>> +  R_AARCH64_MOVW_UABS_G0 = 263, // S + A
>>>> +  R_AARCH64_MOVW_UABS_G0_NC = 264, // S + A
>>>> +  R_AARCH64_MOVW_UABS_G1 = 265, // S + A
>>>
>>> [snip]
>>>
>>>> diff --git a/gold/configure.tgt b/gold/configure.tgt
>>>> index 93d622d..eaf164b 100644
>>>> --- a/gold/configure.tgt
>>>> +++ b/gold/configure.tgt
>>>> @@ -144,6 +144,14 @@ arm*-*-*)
>>>>   targ_big_endian=false
>>>>   targ_extra_big_endian=true
>>>>   ;;
>>>> +aarch64-*)
>>>
>>> I think you'll need aarch64*-* in order to support targ_extra_size=32
>>> and targ_extra_big_endian=true.
>>>
>> Will do. Thanks!
>> Jing
>>
>>> Yufeng

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

* Re: [gold] First patch for aarch64 backend
  2014-07-01 23:21       ` Jing Yu
@ 2014-07-02 23:26         ` Cary Coutant
  0 siblings, 0 replies; 8+ messages in thread
From: Cary Coutant @ 2014-07-02 23:26 UTC (permalink / raw)
  To: Jing Yu; +Cc: Andrew Pinski, Yufeng Zhang, binutils, Han Shen, Doug Kwan

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

I've committed the attached patch on your behalf. Thanks, and looking
forward to more aarch64 patches!

-cary

2014-07-02  Jing Yu  <jingyu@google.com>

    Initial patch to enable gold aarch64 backend.

    This patch is just a skeleton which almost does nothing.
    It does not support ILP32 now.

    gold/ChangeLog:
        * aarch64.cc: New file
        * Makefile.am (TARGETSOURCES): Add aarch64.cc
        (ALL_TARGETOBJS): Add aarch64.$(OBJEXT)
        * Makefile.in: Regenerate.
        * configure.tgt: Add entries for aarch64*.
        * configure.ac:  Likewise.
        * configure: Likewise.

    elfcpp/ChangeLog:
        * aarch64.h: New file. New enums for aarch64-elf64 relocations.
        * elfcpp.h (EM_AARCH64, SHT_AARCH64_ATTRIBUTES, PT_AARCH64_ARCHEXT,
        PT_AARCH64_UNWIND): New enum constant.

[-- Attachment #2: gold_aarch64.patch1 --]
[-- Type: application/octet-stream, Size: 57938 bytes --]

commit eb9ebea8c93102ae44ca856b3a0ae7c7be883ea7
Author: Jing Yu <jingyu@google.com>
Date:   Wed Jul 2 10:54:53 2014 -0700

    Initial patch to enable gold aarch64 backend.
    
    This patch is just a skeleton which almost does nothing.
    It does not support ILP32 now.
    
    gold/ChangeLog:
    	* aarch64.cc: New file
    	* Makefile.am (TARGETSOURCES): Add aarch64.cc
    	(ALL_TARGETOBJS): Add aarch64.$(OBJEXT)
    	* Makefile.in: Regenerate.
    	* configure.tgt: Add entries for aarch64*.
    	* configure.ac:  Likewise.
    	* configure: Likewise.
    
    elfcpp/ChangeLog:
    	* aarch64.h: New file. New enums for aarch64-elf64 relocations.
    	* elfcpp.h (EM_AARCH64, SHT_AARCH64_ATTRIBUTES, PT_AARCH64_ARCHEXT,
    	PT_AARCH64_UNWIND): New enum constant.

diff --git a/elfcpp/aarch64.h b/elfcpp/aarch64.h
new file mode 100644
index 0000000..4d1898f
--- /dev/null
+++ b/elfcpp/aarch64.h
@@ -0,0 +1,183 @@
+// aarch64.h -- ELF definitions specific to AARCH64  -*- C++ -*-
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+// Written by Jing Yu (jingyu@google.com)
+
+// This file is part of elfcpp.
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public License
+// as published by the Free Software Foundation; either version 2, or
+// (at your option) any later version.
+
+// In addition to the permissions in the GNU Library General Public
+// License, the Free Software Foundation gives you unlimited
+// permission to link the compiled version of this file into
+// combinations with other programs, and to distribute those
+// combinations without any restriction coming from the use of this
+// file.  (The Library Public License restrictions do apply in other
+// respects; for example, they cover modification of the file, and
+/// distribution when not linked into a combined executable.)
+
+// 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
+// Library General Public License for more details.
+
+// You should have received a copy of the GNU Library 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.
+
+#ifndef ELFCPP_AARCH64_H
+#define ELFCPP_AARCH64_H
+
+namespace elfcpp
+{
+
+// The relocation type information is taken from:
+//
+//   ELF for the ARM 64-bit Architecture (AArch64)
+//   Document number: ARM IHI 0056B, current through AArch64 ABI release 1.0
+//   Date of Issue: 22nd May, 2013
+//
+
+enum
+{
+  // Null relocation codes
+  R_AARCH64_NONE = 0,		// None
+  withdrawn = 256,		// Treat as R_AARCH64_NONE
+
+  // Static relocations
+  R_AARCH64_ABS64 = 257,	// S + A
+  R_AARCH64_ABS32 = 258,	// S + A
+  R_AARCH64_ABS16 = 259,	// S + A
+  R_AARCH64_PREL64 = 260,	// S + A - P
+  R_AARCH64_PREL32 = 261,	// S + A - P
+  R_AARCH64_PREL16 = 262,	// S + A - P
+  R_AARCH64_MOVW_UABS_G0 = 263,		// S + A
+  R_AARCH64_MOVW_UABS_G0_NC = 264,	// S + A
+  R_AARCH64_MOVW_UABS_G1 = 265,		// S + A
+  R_AARCH64_MOVW_UABS_G1_NC = 266,	// S + A
+  R_AARCH64_MOVW_UABS_G2 = 267,		// S + A
+  R_AARCH64_MOVW_UABS_G2_NC = 268,	// S + A
+  R_AARCH64_MOVW_UABS_G3 = 269,		// S + A
+  R_AARCH64_MOVW_SABS_G0 = 270,		// S + A
+  R_AARCH64_MOVW_SABS_G1 = 271,		// S + A
+  R_AARCH64_MOVW_SABS_G2 = 272,		// S + A
+  R_AARCH64_LD_PREL_LO19 = 273,		// S + A - P
+  R_AARCH64_ADR_PREL_LO21 = 274,	// S + A - P
+  R_AARCH64_ADR_PREL_PG_HI21 = 275,	// Page(S+A) - Page(P)
+  R_AARCH64_ADR_PREL_PG_HI21_NC = 276,	// Page(S+A) - Page(P)
+  R_AARCH64_ADD_ABS_LO12_NC = 277,	// S + A
+  R_AARCH64_LDST8_ABS_LO12_NC = 278,	// S + A
+  R_AARCH64_TSTBR14 = 279,		// S + A - P
+  R_AARCH64_CONDBR19 = 280,		// S + A - P
+  R_AARCH64_JUMP26 = 282,		// S + A - P
+  R_AARCH64_CALL26 = 283,		// S + A - P
+  R_AARCH64_LDST16_ABS_LO12_NC = 284,	// S + A
+  R_AARCH64_LDST32_ABS_LO12_NC = 285,	// S + A
+  R_AARCH64_LDST64_ABS_LO12_NC = 286,	// S + A
+  R_AARCH64_MOVW_PREL_G0 = 287,		// S + A - P
+  R_AARCH64_MOVW_PREL_G0_NC = 288,	// S + A - P
+  R_AARCH64_MOVW_PREL_G1 = 289,		// S + A - P
+  R_AARCH64_MOVW_PREL_G1_NC = 290,	// S + A - P
+  R_AARCH64_MOVW_PREL_G2 = 291,		// S + A - P
+  R_AARCH64_MOVW_PREL_G2_NC = 292,	// S + A - P
+  R_AARCH64_MOVW_PREL_G3 = 293,		// S + A - P
+  R_AARCH64_LDST128_ABS_LO12_NC = 299,	// S + A
+  R_AARCH64_MOVW_GOTOFF_G0 = 300,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G0_NC = 301,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G1 = 302,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G1_NC = 303,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G2 = 304,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G2_NC = 305,	// G(GDAT(S+A))-GOT
+  R_AARCH64_MOVW_GOTOFF_G3 = 306,	// G(GDAT(S+A))-GOT
+  R_AARCH64_GOTREL64 = 307,		// S + A - GOT
+  R_AARCH64_GOTREL32 = 308,		// S + A - GOT
+  R_AARCH64_GOT_LD_PREL19 = 309,	// G(GDAT(S+A))-P
+  R_AARCH64_LD64_GOTOFF_LO15 = 310,	// G(GDAT(S+A))-GOT
+  R_AARCH64_ADR_GOT_PAGE = 311,		// Page(G(GDAT(S+A)))-Page(P)
+  R_AARCH64_LD64_GOT_LO12_NC = 312,	// G(GDAT(S+A))
+  R_AARCH64_LD64_GOTPAGE_LO15 = 313,	// G(GDAT(S+A))-Page(GOT)
+
+  // Relocations for thread-local storage
+  R_AARCH64_TLSGD_ADR_PREL21 = 512,		// G(GTLSIDX(S,A)) - P
+  R_AARCH64_TLSGD_ADR_PAGE21 = 513,		// Page(G(GTLSIDX(S,A)))-Page(P)
+  R_AARCH64_TLSGD_ADD_LO12_NC = 514,		// G(GTLSICX(S,A))
+  R_AARCH64_TLSGD_MOVW_G1 = 515,		// G(GTLSIDX(S,A)) - GOT
+  R_AARCH64_TLSGD_MOVW_G0_NC = 516,		// G(GTLSIDX(S,A)) - GOT
+
+  R_AARCH64_TLSLD_ADR_PREL21 = 517,		// G(GLDM(S)) - P
+  R_AARCH64_TLSLD_ADR_PAGE21 = 518,		// Page(G(GLDM(S))) - Page(P)
+  R_AARCH64_TLSLD_ADD_LO12_NC = 519,		// G(GLDM(S))
+  R_AARCH64_TLSLD_MOVW_G1 = 520,		// G(GLDM(S)) - GOT
+  R_AARCH64_TLSLD_MOVW_G0_NC = 521,		// G(GLDM(S)) - GOT
+  R_AARCH64_TLSLD_LD_PREL19 = 522,		// G(GLDM(S)) - P
+  R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 523,		// DTPREL(S+A)
+  R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 524,		// DTPREL(S+A)
+  R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 525,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 526,		// DTPREL(S+A)
+  R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 527,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 528,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 529,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 530,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 531,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 532,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 533,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 534,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 535,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 536,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 537,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 538,	// DTPREL(S+A)
+  R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 539,	// G(GTPREL(S+A)) - GOT
+  R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 540,	// G(GTPREL(S+A)) - GOT
+  R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541,	// Page(G(GTPREL(S+A)))-Page(P)
+  R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542,	// G(GTPREL(S+A))
+  R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 543,	// G(GTPREL(S+A)) - P
+  R_AARCH64_TLSLE_MOVW_TPREL_G2 = 544,		// TPREL(S+A)
+  R_AARCH64_TLSLE_MOVW_TPREL_G1 = 545,		// TPREL(S+A)
+  R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 546,	// TPREL(S+A)
+  R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547,		// TPREL(S+A)
+  R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 548,	// TPREL(S+A)
+  R_AARCH64_TLSLE_ADD_TPREL_HI12 = 549,		// TPREL(S+A)
+  R_AARCH64_TLSLE_ADD_TPREL_LO12 = 550,		// TPREL(S+A)
+  R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 551,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 552,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 553,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 554,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LSDT16_TPREL_LO12_NC = 555,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 556,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 557,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 558,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 559,	// TPREL(S+A)
+  R_AARCH64_TLSDESC_LD_PREL19 = 560,	// G(GTLSDESC(S+A)) - P
+  R_AARCH64_TLSDESC_ADR_PREL21 = 561,	// G(GTLSDESC(S+A)) - P
+  R_AARCH64_TLSDESC_ADR_PAGE21 = 562,	// Page(G(GTLSDESC(S+A)))-Page(P)
+  R_AARCH64_TLSDESC_LD64_LO12 = 563,	// G(GTLSDESC(S+A))
+  R_AARCH64_TLSDESC_ADD_LO12 = 564,	// G(GTLSDESC(S+A))
+  R_AARCH64_TLSDESC_OFF_G1 = 565,	// G(GTLSDESC(S+A)) - GOT
+  R_AARCH64_TLSDESC_OFF_G0_NC = 566,	// G(GTLSDESC(S+A)) - GOT
+  R_AARCH64_TLSDESC_LDR = 567,		// None
+  R_AARCH64_TLSDESC_ADD = 568,		// None
+  R_AARCH64_TLSDESC_CALL = 569,		// None
+  R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 570,	// TPREL(S+A)
+  R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 571,	// TPREL(S+A)
+  R_AARCH64_TLSLD_LDST128_DTPREL_LO12 = 572,	// DTPREL(S+A)
+  R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC = 573,	// DTPREL(S+A)
+
+  // Dynamic relocations
+  R_AARCH64_COPY = 1024,
+  R_AARCH64_GLOB_DAT = 1025,		// S + A
+  R_AARCH64_JUMP_SLOT = 1026,		// S + A
+  R_AARCH64_RELATIVE = 1027,		// Delta(S) + A
+  R_AARCH64_TLS_DTPREL64 = 1028,	// DTPREL(S+A)
+  R_AARCH64_TLS_DTPMOD64 = 1029,	// LDM(S)
+  R_AARCH64_TLS_TPREL64 = 1030,		// TPREL(S+A)
+  R_AARCH64_TLSDESC = 1031,		// TLSDESC(S+A)
+  R_AARCH64_IRELATIVE = 1032,		// Indirect(Delta(S) + A)
+};
+
+} // End namespace elfcpp.
+
+#endif // !defined(ELFCPP_AARCH64_H)
diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h
index 561b54a..8e8e675 100644
--- a/elfcpp/elfcpp.h
+++ b/elfcpp/elfcpp.h
@@ -268,6 +268,7 @@ enum EM
   EM_UNICORE = 110,
   EM_ALTERA_NIOS2 = 113,
   EM_CRX = 114,
+  EM_AARCH64 = 183,
   EM_TILEGX = 191,
   // The Morph MT.
   EM_MT = 0x2530,
@@ -406,6 +407,9 @@ enum SHT
   // Section contains miscellaneous options.
   SHT_MIPS_OPTIONS = 0x7000000d,
 
+  // AARCH64-specific section type.
+  SHT_AARCH64_ATTRIBUTES = 0x70000003,
+
   // Link editor is to sort the entries in this section based on the
   // address specified in the associated symbol table entry.
   SHT_ORDERED = 0x7fffffff
@@ -490,7 +494,11 @@ enum PT
   // Runtime procedure table.
   PT_MIPS_RTPROC = 0x70000001,
   // .MIPS.options section.
-  PT_MIPS_OPTIONS = 0x70000002
+  PT_MIPS_OPTIONS = 0x70000002,
+  // Platform architecture compatibility information
+  PT_AARCH64_ARCHEXT = 0x70000000,
+  // Exception unwind tables
+  PT_AARCH64_UNWIND = 0x70000001
 };
 
 // The valid bit flags found in the Phdr p_flags field.
diff --git a/gold/Makefile.am b/gold/Makefile.am
index dd05e82..17ba4b4 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -164,11 +164,12 @@ EXTRA_DIST = yyscript.c yyscript.h
 
 TARGETSOURCES = \
 	i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc tilegx.cc \
-	mips.cc
+	mips.cc aarch64.cc
 
 ALL_TARGETOBJS = \
 	i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \
-	arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) mips.$(OBJEXT)
+	arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) tilegx.$(OBJEXT) \
+	mips.$(OBJEXT) aarch64.$(OBJEXT)
 
 libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES)
 libgold_a_LIBADD = $(LIBOBJS)
diff --git a/gold/aarch64.cc b/gold/aarch64.cc
new file mode 100644
index 0000000..17fe031
--- /dev/null
+++ b/gold/aarch64.cc
@@ -0,0 +1,1447 @@
+// aarch64.cc -- aarch64 target support for gold.
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+// Written by Jing Yu <jingyu@google.com>.
+
+// This file is part of gold.
+
+// 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.
+
+#include "gold.h"
+
+#include <cstring>
+
+#include "elfcpp.h"
+#include "dwarf.h"
+#include "parameters.h"
+#include "reloc.h"
+#include "aarch64.h"
+#include "object.h"
+#include "symtab.h"
+#include "layout.h"
+#include "output.h"
+#include "copy-relocs.h"
+#include "target.h"
+#include "target-reloc.h"
+#include "target-select.h"
+#include "tls.h"
+#include "freebsd.h"
+#include "nacl.h"
+#include "gc.h"
+#include "icf.h"
+
+// The first three .got.plt entries are reserved.
+const int32_t AARCH64_GOTPLT_RESERVE_COUNT = 3;
+
+namespace
+{
+
+using namespace gold;
+
+template<int size, bool big_endian>
+class Output_data_plt_aarch64;
+
+template<int size, bool big_endian>
+class Output_data_plt_aarch64_standard;
+
+template<int size, bool big_endian>
+class Target_aarch64;
+
+// Output_data_got_aarch64 class.
+
+template<int size, bool big_endian>
+class Output_data_got_aarch64 : public Output_data_got<size, big_endian>
+{
+ public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
+  Output_data_got_aarch64(Symbol_table* symtab, Layout* layout)
+    : Output_data_got<size, big_endian>(), layout_(layout)
+  { }
+
+ protected:
+  // Write out the GOT table.
+  void
+  do_write(Output_file* of) {
+    // The first entry in the GOT is the address of the .dynamic section.
+    gold_assert(this->data_size() >= size / 8);
+    Output_section* dynamic = this->layout_->dynamic_section();
+    Valtype dynamic_addr = dynamic == NULL ? 0 : dynamic->address();
+    this->replace_constant(0, dynamic_addr);
+    Output_data_got<size, big_endian>::do_write(of);
+  }
+
+ private:
+  // A pointer to the Layout class, so that we can find the .dynamic
+  // section when we write out the GOT section.
+  Layout* layout_;
+};
+
+// The aarch64 target class.
+// See the ABI at
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
+template<int size, bool big_endian>
+class Target_aarch64 : public Sized_target<size, big_endian>
+{
+ public:
+  typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
+      Reloc_section;
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+
+  Target_aarch64(const Target::Target_info* info = &aarch64_info)
+    : Sized_target<size, big_endian>(info),
+      got_(NULL), plt_(NULL), got_plt_(NULL),
+      global_offset_table_(NULL), rela_dyn_(NULL),
+      copy_relocs_(elfcpp::R_AARCH64_COPY)
+  { }
+
+  // Scan the relocations to determine unreferenced sections for
+  // garbage collection.
+  void
+  gc_process_relocs(Symbol_table* symtab,
+		    Layout* layout,
+		    Sized_relobj_file<size, big_endian>* object,
+		    unsigned int data_shndx,
+		    unsigned int sh_type,
+		    const unsigned char* prelocs,
+		    size_t reloc_count,
+		    Output_section* output_section,
+		    bool needs_special_offset_handling,
+		    size_t local_symbol_count,
+		    const unsigned char* plocal_symbols);
+
+  // Scan the relocations to look for symbol adjustments.
+  void
+  scan_relocs(Symbol_table* symtab,
+	      Layout* layout,
+	      Sized_relobj_file<size, big_endian>* object,
+	      unsigned int data_shndx,
+	      unsigned int sh_type,
+	      const unsigned char* prelocs,
+	      size_t reloc_count,
+	      Output_section* output_section,
+	      bool needs_special_offset_handling,
+	      size_t local_symbol_count,
+	      const unsigned char* plocal_symbols);
+
+  // Finalize the sections.
+  void
+  do_finalize_sections(Layout*, const Input_objects*, Symbol_table*);
+
+  // Relocate a section.
+  void
+  relocate_section(const Relocate_info<size, big_endian>*,
+		   unsigned int sh_type,
+		   const unsigned char* prelocs,
+		   size_t reloc_count,
+		   Output_section* output_section,
+		   bool needs_special_offset_handling,
+		   unsigned char* view,
+		   typename elfcpp::Elf_types<size>::Elf_Addr view_address,
+		   section_size_type view_size,
+		   const Reloc_symbol_changes*);
+
+  // Scan the relocs during a relocatable link.
+  void
+  scan_relocatable_relocs(Symbol_table* symtab,
+			  Layout* layout,
+			  Sized_relobj_file<size, big_endian>* object,
+			  unsigned int data_shndx,
+			  unsigned int sh_type,
+			  const unsigned char* prelocs,
+			  size_t reloc_count,
+			  Output_section* output_section,
+			  bool needs_special_offset_handling,
+			  size_t local_symbol_count,
+			  const unsigned char* plocal_symbols,
+			  Relocatable_relocs*);
+
+  // Relocate a section during a relocatable link.
+  void
+  relocate_relocs(
+      const Relocate_info<size, big_endian>*,
+      unsigned int sh_type,
+      const unsigned char* prelocs,
+      size_t reloc_count,
+      Output_section* output_section,
+      typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
+      const Relocatable_relocs*,
+      unsigned char* view,
+      typename elfcpp::Elf_types<size>::Elf_Addr view_address,
+      section_size_type view_size,
+      unsigned char* reloc_view,
+      section_size_type reloc_view_size);
+
+  // Return the number of entries in the PLT.
+  unsigned int
+  plt_entry_count() const;
+
+  //Return the offset of the first non-reserved PLT entry.
+  unsigned int
+  first_plt_entry_offset() const;
+
+  // Return the size of each PLT entry.
+  unsigned int
+  plt_entry_size() const;
+
+ private:
+  // The class which scans relocations.
+  class Scan
+  {
+  public:
+    Scan()
+      : issued_non_pic_error_(false)
+    { }
+
+    static inline int
+    get_reference_flags(unsigned int r_type);
+
+    inline void
+    local(Symbol_table* symtab, Layout* layout, Target_aarch64* target,
+	  Sized_relobj_file<size, big_endian>* object,
+	  unsigned int data_shndx,
+	  Output_section* output_section,
+	  const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
+	  const elfcpp::Sym<size, big_endian>& lsym,
+	  bool is_discarded);
+
+    inline void
+    global(Symbol_table* symtab, Layout* layout, Target_aarch64* target,
+	   Sized_relobj_file<size, big_endian>* object,
+	   unsigned int data_shndx,
+	   Output_section* output_section,
+	   const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
+	   Symbol* gsym);
+
+    inline bool
+    local_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
+                                        Target_aarch64<size, big_endian>* ,
+                                        Sized_relobj_file<size, big_endian>* ,
+                                        unsigned int ,
+                                        Output_section* ,
+                                        const elfcpp::Rela<size, big_endian>& ,
+                                        unsigned int r_type,
+                                        const elfcpp::Sym<size, big_endian>&);
+
+    inline bool
+    global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
+                                         Target_aarch64<size, big_endian>* ,
+                                         Sized_relobj_file<size, big_endian>* ,
+                                         unsigned int ,
+                                         Output_section* ,
+                                         const elfcpp::Rela<size, big_endian>& ,
+                                         unsigned int r_type,
+                                         Symbol* gsym);
+
+  private:
+    static void
+    unsupported_reloc_local(Sized_relobj_file<size, big_endian>*,
+			    unsigned int r_type);
+
+    static void
+    unsupported_reloc_global(Sized_relobj_file<size, big_endian>*,
+			     unsigned int r_type, Symbol*);
+
+    inline bool
+    possible_function_pointer_reloc(unsigned int r_type);
+
+    void
+    check_non_pic(Relobj*, unsigned int r_type);
+
+    // Whether we have issued an error about a non-PIC compilation.
+    bool issued_non_pic_error_;
+  };
+
+  // The class which implements relocation.
+  class Relocate
+  {
+   public:
+    Relocate()
+    { }
+
+    ~Relocate()
+    { }
+
+    // Do a relocation.  Return false if the caller should not issue
+    // any warnings about this relocation.
+    inline bool
+    relocate(const Relocate_info<size, big_endian>*, Target_aarch64*,
+	     Output_section*,
+	     size_t relnum, const elfcpp::Rela<size, big_endian>&,
+	     unsigned int r_type, const Sized_symbol<size>*,
+	     const Symbol_value<size>*,
+	     unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
+	     section_size_type);
+
+  };
+
+  // A class which returns the size required for a relocation type,
+  // used while scanning relocs during a relocatable link.
+  class Relocatable_size_for_reloc
+  {
+   public:
+    unsigned int
+    get_size_for_reloc(unsigned int, Relobj*);
+  };
+
+  // Adjust TLS relocation type based on the options and whether this
+  // is a local symbol.
+  static tls::Tls_optimization
+  optimize_tls_reloc(bool is_final, int r_type);
+
+  // Get the GOT section, creating it if necessary.
+  Output_data_got_aarch64<size, big_endian>*
+  got_section(Symbol_table*, Layout*);
+
+  // Get the GOT PLT section.
+  Output_data_space*
+  got_plt_section() const
+  {
+    gold_assert(this->got_plt_ != NULL);
+    return this->got_plt_;
+  }
+
+  // Create the PLT section.
+  void
+  make_plt_section(Symbol_table* symtab, Layout* layout);
+
+  // Create a PLT entry for a global symbol.
+  void
+  make_plt_entry(Symbol_table*, Layout*, Symbol*);
+
+  // Get the PLT section.
+  Output_data_plt_aarch64<size, big_endian>*
+  plt_section() const
+  {
+    gold_assert(this->plt_ != NULL);
+    return this->plt_;
+  }
+
+  // Get the dynamic reloc section, creating it if necessary.
+  Reloc_section*
+  rela_dyn_section(Layout*);
+
+  // Add a potential copy relocation.
+  void
+  copy_reloc(Symbol_table* symtab, Layout* layout,
+	     Sized_relobj_file<size, big_endian>* object,
+	     unsigned int shndx, Output_section* output_section,
+	     Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
+  {
+    this->copy_relocs_.copy_reloc(symtab, layout,
+				  symtab->get_sized_symbol<size>(sym),
+				  object, shndx, output_section,
+				  reloc, this->rela_dyn_section(layout));
+  }
+
+  // Information about this specific target which we pass to the
+  // general Target structure.
+  static const Target::Target_info aarch64_info;
+
+  // The types of GOT entries needed for this platform.
+  // These values are exposed to the ABI in an incremental link.
+  // Do not renumber existing values without changing the version
+  // number of the .gnu_incremental_inputs section.
+  enum Got_type
+  {
+    GOT_TYPE_STANDARD = 0,      // GOT entry for a regular symbol
+    GOT_TYPE_TLS_OFFSET = 1,    // GOT entry for TLS offset
+    GOT_TYPE_TLS_PAIR = 2,      // GOT entry for TLS module/offset pair
+    GOT_TYPE_TLS_DESC = 3       // GOT entry for TLS_DESC pair
+  };
+
+  // The GOT section.
+  Output_data_got_aarch64<size, big_endian>* got_;
+  // The PLT section.
+  Output_data_plt_aarch64<size, big_endian>* plt_;
+  // The GOT PLT section.
+  Output_data_space* got_plt_;
+  // The _GLOBAL_OFFSET_TABLE_ symbol.
+  Symbol* global_offset_table_;
+  // The dynamic reloc section.
+  Reloc_section* rela_dyn_;
+  // Relocs saved to avoid a COPY reloc.
+  Copy_relocs<elfcpp::SHT_RELA, size, big_endian> copy_relocs_;
+};
+
+template<>
+const Target::Target_info Target_aarch64<64, false>::aarch64_info =
+{
+  64,			// size
+  false,		// is_big_endian
+  elfcpp::EM_AARCH64,	// machine_code
+  false,		// has_make_symbol
+  false,		// has_resolve
+  false,		// has_code_fill
+  true,			// is_default_stack_executable
+  false,		// can_icf_inline_merge_sections
+  '\0',			// wrap_char
+  "/lib/ld.so.1",	// program interpreter
+  0x400000,		// default_text_segment_address
+  0x1000,		// abi_pagesize (overridable by -z max-page-size)
+  0x1000,		// common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
+  elfcpp::SHN_UNDEF,	// small_common_shndx
+  elfcpp::SHN_UNDEF,	// large_common_shndx
+  0,			// small_common_section_flags
+  0,			// large_common_section_flags
+  NULL,			// attributes_section
+  NULL,			// attributes_vendor
+  "_start"		// entry_symbol_name
+};
+
+template<>
+const Target::Target_info Target_aarch64<32, false>::aarch64_info =
+{
+  32,			// size
+  false,		// is_big_endian
+  elfcpp::EM_AARCH64,	// machine_code
+  false,		// has_make_symbol
+  false,		// has_resolve
+  false,		// has_code_fill
+  true,			// is_default_stack_executable
+  false,		// can_icf_inline_merge_sections
+  '\0',			// wrap_char
+  "/lib/ld.so.1",	// program interpreter
+  0x400000,		// default_text_segment_address
+  0x1000,		// abi_pagesize (overridable by -z max-page-size)
+  0x1000,		// common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
+  elfcpp::SHN_UNDEF,	// small_common_shndx
+  elfcpp::SHN_UNDEF,	// large_common_shndx
+  0,			// small_common_section_flags
+  0,			// large_common_section_flags
+  NULL,			// attributes_section
+  NULL,			// attributes_vendor
+  "_start"		// entry_symbol_name
+};
+
+template<>
+const Target::Target_info Target_aarch64<64, true>::aarch64_info =
+{
+  64,			// size
+  true,			// is_big_endian
+  elfcpp::EM_AARCH64,	// machine_code
+  false,		// has_make_symbol
+  false,		// has_resolve
+  false,		// has_code_fill
+  true,			// is_default_stack_executable
+  false,		// can_icf_inline_merge_sections
+  '\0',			// wrap_char
+  "/lib/ld.so.1",	// program interpreter
+  0x400000,		// default_text_segment_address
+  0x1000,		// abi_pagesize (overridable by -z max-page-size)
+  0x1000,		// common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
+  elfcpp::SHN_UNDEF,	// small_common_shndx
+  elfcpp::SHN_UNDEF,	// large_common_shndx
+  0,			// small_common_section_flags
+  0,			// large_common_section_flags
+  NULL,			// attributes_section
+  NULL,			// attributes_vendor
+  "_start"		// entry_symbol_name
+};
+
+template<>
+const Target::Target_info Target_aarch64<32, true>::aarch64_info =
+{
+  32,			// size
+  true,			// is_big_endian
+  elfcpp::EM_AARCH64,	// machine_code
+  false,		// has_make_symbol
+  false,		// has_resolve
+  false,		// has_code_fill
+  true,			// is_default_stack_executable
+  false,		// can_icf_inline_merge_sections
+  '\0',			// wrap_char
+  "/lib/ld.so.1",	// program interpreter
+  0x400000,		// default_text_segment_address
+  0x1000,		// abi_pagesize (overridable by -z max-page-size)
+  0x1000,		// common_pagesize (overridable by -z common-page-size)
+  false,                // isolate_execinstr
+  0,                    // rosegment_gap
+  elfcpp::SHN_UNDEF,	// small_common_shndx
+  elfcpp::SHN_UNDEF,	// large_common_shndx
+  0,			// small_common_section_flags
+  0,			// large_common_section_flags
+  NULL,			// attributes_section
+  NULL,			// attributes_vendor
+  "_start"		// entry_symbol_name
+};
+
+// Get the GOT section, creating it if necessary.
+
+template<int size, bool big_endian>
+Output_data_got_aarch64<size, big_endian>*
+Target_aarch64<size, big_endian>::got_section(Symbol_table* symtab,
+                                              Layout* layout)
+{
+  if (this->got_ == NULL)
+    {
+      gold_assert(symtab != NULL && layout != NULL);
+
+      // When using -z now, we can treat .got.plt as a relro section.
+      // Without -z now, it is modified after program startup by lazy
+      // PLT relocations.
+      bool is_got_plt_relro = parameters->options().now();
+      Output_section_order got_order = (is_got_plt_relro
+					? ORDER_RELRO
+					: ORDER_RELRO_LAST);
+      Output_section_order got_plt_order = (is_got_plt_relro
+					    ? ORDER_RELRO
+					    : ORDER_NON_RELRO_FIRST);
+
+      // Layout of .got and .got.plt sections.
+      // .got[0] &_DYNAMIC                          <-_GLOBAL_OFFSET_TABLE_
+      // ...
+      // .gotplt[0] reserved for ld.so (&linkmap)   <--DT_PLTGOT
+      // .gotplt[1] reserved for ld.so (resolver)
+      // .gotplt[2] reserved
+
+      // Generate .got section.
+      this->got_ = new Output_data_got_aarch64<size, big_endian>(symtab,
+                                                                 layout);
+      layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
+                                      (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
+                                      this->got_, got_order, true);
+      // The first word of GOT is reserved for the address of .dynamic.
+      // We put 0 here now. The value will be replaced later in
+      // Output_data_got_aarch64::do_write.
+      this->got_->add_constant(0);
+
+      // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT.
+      // _GLOBAL_OFFSET_TABLE_ value points to the start of the .got section,
+      // even if there is a .got.plt section.
+      this->global_offset_table_ =
+        symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
+                                      Symbol_table::PREDEFINED,
+                                      this->got_,
+                                      0, 0, elfcpp::STT_OBJECT,
+                                      elfcpp::STB_LOCAL,
+                                      elfcpp::STV_HIDDEN, 0,
+                                      false, false);
+
+      // Generate .got.plt section.
+      this->got_plt_ = new Output_data_space(size / 8, "** GOT PLT");
+      layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
+                                      (elfcpp::SHF_ALLOC
+                                       | elfcpp::SHF_WRITE),
+                                      this->got_plt_, got_plt_order,
+                                      is_got_plt_relro);
+
+      // The first three entries are reserved.
+      this->got_plt_->set_current_data_size
+          (AARCH64_GOTPLT_RESERVE_COUNT * (size / 8));
+
+      if (!is_got_plt_relro)
+        {
+          // Those bytes can go into the relro segment.
+          layout->increase_relro
+              (AARCH64_GOTPLT_RESERVE_COUNT * (size / 8));
+        }
+
+    }
+  return this->got_;
+}
+
+// Get the dynamic reloc section, creating it if necessary.
+
+template<int size, bool big_endian>
+typename Target_aarch64<size, big_endian>::Reloc_section*
+Target_aarch64<size, big_endian>::rela_dyn_section(Layout* layout)
+{
+  if (this->rela_dyn_ == NULL)
+    {
+      gold_assert(layout != NULL);
+      this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
+      layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
+				      elfcpp::SHF_ALLOC, this->rela_dyn_,
+				      ORDER_DYNAMIC_RELOCS, false);
+    }
+  return this->rela_dyn_;
+}
+
+// A class to handle the PLT data.
+// This is an abstract base class that handles most of the linker details
+// but does not know the actual contents of PLT entries.  The derived
+// classes below fill in those details.
+
+template<int size, bool big_endian>
+class Output_data_plt_aarch64 : public Output_section_data
+{
+ public:
+  typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
+      Reloc_section;
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+
+  Output_data_plt_aarch64(Layout* layout,
+                          uint64_t addralign,
+                          Output_data_space* got_plt)
+    : Output_section_data(addralign),
+      got_plt_(got_plt),
+      count_(0)
+  { this->init(layout); }
+
+  // Initialize the PLT section.
+  void
+  init(Layout* layout);
+
+  // Add an entry to the PLT.
+  void
+  add_entry(Symbol* gsym);
+
+  // Return the .rela.plt section data.
+  Reloc_section*
+  rela_plt()
+  { return this->rel_; }
+
+  // Return the number of PLT entries.
+  unsigned int
+  entry_count() const
+  { return this->count_; }
+
+  // Return the offset of the first non-reserved PLT entry.
+  unsigned int
+  first_plt_entry_offset()
+  { return this->do_first_plt_entry_offset(); }
+
+  // Return the size of a PLT entry.
+  unsigned int
+  get_plt_entry_size() const
+  { return this->do_get_plt_entry_size(); }
+
+ protected:
+  // Fill in the first PLT entry.
+  void
+  fill_first_plt_entry(unsigned char* pov,
+		       Address got_address,
+		       Address plt_address)
+  { this->do_fill_first_plt_entry(pov, got_address, plt_address); }
+
+  // Fill in a normal PLT entry.
+  void
+  fill_plt_entry(unsigned char* pov,
+		 Address got_address,
+		 Address plt_address,
+		 unsigned int got_offset,
+		 unsigned int plt_offset)
+  {
+    this->do_fill_plt_entry(pov, got_address, plt_address,
+			    got_offset, plt_offset);
+  }
+
+  virtual unsigned int
+  do_first_plt_entry_offset() const = 0;
+
+  virtual unsigned int
+  do_get_plt_entry_size() const = 0;
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+			  Address got_addr,
+			  Address plt_addr) = 0;
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+		    Address got_address,
+		    Address plt_address,
+		    unsigned int got_offset,
+		    unsigned int plt_offset) = 0;
+
+  void
+  do_adjust_output_section(Output_section* os);
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** PLT")); }
+
+ private:
+  // Set the final size.
+  void
+  set_final_data_size();
+
+  // Write out the PLT data.
+  void
+  do_write(Output_file*);
+
+  // The reloc section.
+  Reloc_section* rel_;
+  // The .got section.
+  Output_data_got_aarch64<size, big_endian>* got_;
+  // The .got.plt section.
+  Output_data_space* got_plt_;
+  // The number of PLT entries.
+  unsigned int count_;
+};
+
+// Initialize the PLT section.
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::init(Layout* layout)
+{
+  this->rel_ = new Reloc_section(false);
+  layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
+				  elfcpp::SHF_ALLOC, this->rel_,
+				  ORDER_DYNAMIC_PLT_RELOCS, false);
+}
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::do_adjust_output_section(
+    Output_section* os)
+{
+  os->set_entsize(this->get_plt_entry_size());
+}
+
+// Add an entry to the PLT.
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::add_entry(Symbol* gsym)
+{
+  gold_assert(!gsym->has_plt_offset());
+  //TODO
+}
+
+// Set the final size.
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::set_final_data_size()
+{
+  this->set_data_size(this->first_plt_entry_offset()
+                      + this->count * this->get_plt_entry_size());
+}
+
+template<int size, bool big_endian>
+class Output_data_plt_aarch64_standard :
+  public Output_data_plt_aarch64<size, big_endian>
+{
+ public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+  Output_data_plt_aarch64_standard(Layout* layout, Output_data_space* got_plt)
+    : Output_data_plt_aarch64<size, big_endian>(layout,
+                                                size == 32 ? 4 : 8,
+                                                got_plt)
+  { }
+
+ protected:
+  // Return the offset of the first non-reserved PLT entry.
+  virtual unsigned int
+  do_first_plt_entry_offset() const
+  { return this->first_plt_entry_size; }
+
+  // Return the size of a PLT entry
+  virtual unsigned int
+  do_get_plt_entry_size() const
+  { return this->plt_entry_size; }
+
+  virtual void
+  do_fill_first_plt_entry(unsigned char* pov,
+                          Address got_address,
+                          Address plt_address);
+
+  virtual void
+  do_fill_plt_entry(unsigned char* pov,
+                    Address got_address,
+                    Address plt_address,
+                    unsigned int got_offset,
+                    unsigned int plt_offset);
+
+ private:
+  // The size of the first plt entry size.
+  static const int first_plt_entry_size = 32;
+  // The size of the plt entry size.
+  static const int plt_entry_size = 16;
+  // Template for the first PLT entry.
+  static const uint32_t first_plt_entry[first_plt_entry_size / 4];
+  // Template for subsequent PLT entries.
+  static const uint32_t plt_entry[plt_entry_size / 4];
+};
+
+// The first entry in the PLT for an executable.
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<32, false>::
+    first_plt_entry[first_plt_entry_size / 4] =
+{
+  0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
+  0x90000010,	/* adrp x16, PLT_GOT+0x8  */
+  0xb9400A11,	/* ldr w17, [x16, #PLT_GOT+0x8]  */
+  0x11002210,	/* add w16, w16,#PLT_GOT+0x8   */
+  0xd61f0220,	/* br x17  */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<32, true>::
+    first_plt_entry[first_plt_entry_size / 4] =
+{
+  0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
+  0x90000010,	/* adrp x16, PLT_GOT+0x8  */
+  0xb9400A11,	/* ldr w17, [x16, #PLT_GOT+0x8]  */
+  0x11002210,	/* add w16, w16,#PLT_GOT+0x8   */
+  0xd61f0220,	/* br x17  */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<64, false>::
+    first_plt_entry[first_plt_entry_size / 4] =
+{
+  0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
+  0x90000010,	/* adrp x16, PLT_GOT+16  */
+  0xf9400A11,	/* ldr x17, [x16, #PLT_GOT+0x10]  */
+  0x91004210,	/* add x16, x16,#PLT_GOT+0x10   */
+  0xd61f0220,	/* br x17  */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<64, true>::
+    first_plt_entry[first_plt_entry_size / 4] =
+{
+  0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
+  0x90000010,	/* adrp x16, PLT_GOT+16  */
+  0xf9400A11,	/* ldr x17, [x16, #PLT_GOT+0x10]  */
+  0x91004210,	/* add x16, x16,#PLT_GOT+0x10   */
+  0xd61f0220,	/* br x17  */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+  0xd503201f,	/* nop */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<32, false>::
+    plt_entry[plt_entry_size / 4] =
+{
+  0x90000010,	/* adrp x16, PLTGOT + n * 4  */
+  0xb9400211,	/* ldr w17, [w16, PLTGOT + n * 4] */
+  0x11000210,	/* add w16, w16, :lo12:PLTGOT + n * 4  */
+  0xd61f0220,	/* br x17.  */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<32, true>::
+    plt_entry[plt_entry_size / 4] =
+{
+  0x90000010,	/* adrp x16, PLTGOT + n * 4  */
+  0xb9400211,	/* ldr w17, [w16, PLTGOT + n * 4] */
+  0x11000210,	/* add w16, w16, :lo12:PLTGOT + n * 4  */
+  0xd61f0220,	/* br x17.  */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<64, false>::
+    plt_entry[plt_entry_size / 4] =
+{
+  0x90000010,	/* adrp x16, PLTGOT + n * 8  */
+  0xf9400211,	/* ldr x17, [x16, PLTGOT + n * 8] */
+  0x91000210,	/* add x16, x16, :lo12:PLTGOT + n * 8  */
+  0xd61f0220,	/* br x17.  */
+};
+
+template<>
+const uint32_t
+Output_data_plt_aarch64_standard<64, true>::
+    plt_entry[plt_entry_size / 4] =
+{
+  0x90000010,	/* adrp x16, PLTGOT + n * 8  */
+  0xf9400211,	/* ldr x17, [x16, PLTGOT + n * 8] */
+  0x91000210,	/* add x16, x16, :lo12:PLTGOT + n * 8  */
+  0xd61f0220,	/* br x17.  */
+};
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64_standard<size, big_endian>::do_fill_first_plt_entry(
+    unsigned char* pov,
+    Address /* got_address */,
+    Address /* plt_address */)
+{
+  // PLT0 of the small PLT looks like this in ELF64 -
+  // 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
+  // PLT0 will be slightly different in ELF32 due to different got entry
+  // size.
+  memcpy(pov, this->first_plt_entry, this->first_plt_entry_size);
+  // TODO
+}
+
+// Subsequent entries in the PLT for an executable.
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64_standard<size, big_endian>::do_fill_plt_entry(
+    unsigned char* pov,
+    Address /* got_address*/,
+    Address /* plt_address */,
+    unsigned int /* got_offset */,
+    unsigned int /* plt_offset */)
+{
+  memcpy(pov, this->plt_entry, this->plt_entry_size);
+  //TODO
+}
+
+// Write out the PLT.  This uses the hand-coded instructions above,
+// and adjusts them as needed.  This is specified by the AMD64 ABI.
+
+template<int size, bool big_endian>
+void
+Output_data_plt_aarch64<size, big_endian>::do_write(Output_file* of)
+{
+  const off_t offset = this->offset();
+  const section_size_type oview_size =
+    convert_to_section_size_type(this->data_size());
+  unsigned char* const oview = of->get_output_view(offset, oview_size);
+
+  const off_t got_file_offset = this->got_plt_->offset();
+  const section_size_type got_size =
+    convert_to_section_size_type(this->got_plt_->data_size());
+  unsigned char* const got_view = of->get_output_view(got_file_offset,
+						      got_size);
+
+  unsigned char* pov = oview;
+
+  // The base address of the .plt section.
+  typename elfcpp::Elf_types<size>::Elf_Addr plt_address = this->address();
+  // The base address of the .got section.
+  typename elfcpp::Elf_types<size>::Elf_Addr got_base = this->got_->address();
+  // The base address of the PLT portion of the .got section.
+  typename elfcpp::Elf_types<size>::Elf_Addr got_address
+    = this->got_plt_->address();
+
+  this->fill_first_plt_entry(pov, got_address, plt_address);
+  pov += this->first_plt_entry_offset();
+
+  // The first three entries in .got.plt are reserved.
+  unsigned char* got_pov = got_view;
+  memset(got_pov, 0, size / 8 * AARCH64_GOTPLT_RESERVE_COUNT);
+  got_pov += (size / 8) * AARCH64_GOTPLT_RESERVE_COUNT;
+
+  unsigned int plt_offset = this->first_plt_entry_offset();
+  unsigned int got_offset = (size / 8) * AARCH64_GOTPLT_RESERVE_COUNT;
+  const unsigned int count = this->count_;
+  for (unsigned int plt_index = 0;
+       plt_index < count;
+       ++plt_index,
+	 pov += this->get_plt_entry_size(),
+	 got_pov += size / 8,
+	 plt_offset += this->get_plt_entry_size(),
+	 got_offset += size / 8)
+    {
+      // Set and adjust the PLT entry itself.
+      this->fill_plt_entry(pov, got_address, plt_address,
+                           got_offset, plt_offset);
+
+      // Set the entry in the GOT.
+      elfcpp::Swap<size, big_endian>::writeval(got_pov,
+          plt_address + plt_offset);
+    }
+
+  gold_assert(static_cast<section_size_type>(pov - oview) == oview_size);
+  gold_assert(static_cast<section_size_type>(got_pov - got_view) == got_size);
+
+  of->write_output_view(offset, oview_size, oview);
+  of->write_output_view(got_file_offset, got_size, got_view);
+}
+
+// Return the number of entries in the PLT.
+
+template<int size, bool big_endian>
+unsigned int
+Target_aarch64<size, big_endian>::plt_entry_count() const
+{
+  if (this->plt_ == NULL)
+    return 0;
+  return this->plt_->entry_count();
+}
+
+// Return the offset of the first non-reserved PLT entry.
+
+template<int size, bool big_endian>
+unsigned int
+Target_aarch64<size, big_endian>::first_plt_entry_offset() const
+{
+  return this->plt_->first_plt_entry_offset();
+}
+
+// Return the size of each PLT entry.
+
+template<int size, bool big_endian>
+unsigned int
+Target_aarch64<size, big_endian>::plt_entry_size() const
+{
+  return this->plt_->get_plt_entry_size();
+}
+
+// Optimize the TLS relocation type based on what we know about the
+// symbol.  IS_FINAL is true if the final address of this symbol is
+// known at link time.
+
+template<int size, bool big_endian>
+tls::Tls_optimization
+Target_aarch64<size, big_endian>::optimize_tls_reloc(bool /* is_final */,
+                                                     int /* r_type */)
+{
+  //TODO
+  return tls::TLSOPT_NONE;
+}
+
+// Get the Reference_flags for a particular relocation.
+template<int size, bool big_endian>
+int
+Target_aarch64<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case elfcpp::R_AARCH64_NONE:
+      // No symbol reference.
+      return 0;
+    //TODO
+    default:
+      // Not expected. We will give an error later.
+    return 0;
+    }
+}
+
+// Returns true if this relocation type could be that of a function pointer.
+
+template<int size, bool big_endian>
+inline bool
+Target_aarch64<size, big_endian>::Scan::possible_function_pointer_reloc(
+  unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case elfcpp::R_AARCH64_ABS64:
+    //TODO
+      {
+        return true;
+      }
+    }
+  return false;
+}
+
+// For safe ICF, scan a relocation for a local symbol to check if it
+// corresponds to a function pointer being taken.  In that case mark
+// the function whose pointer was taken as not foldable.
+
+template<int size, bool big_endian>
+inline bool
+Target_aarch64<size, big_endian>::Scan::local_reloc_may_be_function_pointer(
+  Symbol_table* ,
+  Layout* ,
+  Target_aarch64<size, big_endian>* ,
+  Sized_relobj_file<size, big_endian>* ,
+  unsigned int ,
+  Output_section* ,
+  const elfcpp::Rela<size, big_endian>& ,
+  unsigned int r_type,
+  const elfcpp::Sym<size, big_endian>&)
+{
+  // When building a shared library, do not fold any local symbols as it is
+  // not possible to distinguish pointer taken versus a call by looking at
+  // the relocation types.
+  return (parameters->options().shared()
+          || possible_function_pointer_reloc(r_type));
+}
+
+// For safe ICF, scan a relocation for a global symbol to check if it
+// corresponds to a function pointer being taken.  In that case mark
+// the function whose pointer was taken as not foldable.
+
+template<int size, bool big_endian>
+inline bool
+Target_aarch64<size, big_endian>::Scan::global_reloc_may_be_function_pointer(
+  Symbol_table* ,
+  Layout* ,
+  Target_aarch64<size, big_endian>* ,
+  Sized_relobj_file<size, big_endian>* ,
+  unsigned int ,
+  Output_section* ,
+  const elfcpp::Rela<size, big_endian>& ,
+  unsigned int r_type,
+  Symbol* gsym)
+{
+  // When building a shared library, do not fold symbols whose visibility
+  // is hidden, internal or protected.
+  return ((parameters->options().shared()
+           && (gsym->visibility() == elfcpp::STV_INTERNAL
+               || gsym->visibility() == elfcpp::STV_PROTECTED
+               || gsym->visibility() == elfcpp::STV_HIDDEN))
+          || possible_function_pointer_reloc(r_type));
+}
+
+// Report an unsupported relocation against a local symbol.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::Scan::unsupported_reloc_local(
+     Sized_relobj_file<size, big_endian>* object,
+     unsigned int r_type)
+{
+  gold_error(_("%s: unsupported reloc %u against local symbol"),
+	     object->name().c_str(), r_type);
+}
+
+// We are about to emit a dynamic relocation of type R_TYPE.  If the
+// dynamic linker does not support it, issue an error.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::Scan::check_non_pic(Relobj* object,
+                                                      unsigned int r_type)
+{
+  gold_assert(r_type != elfcpp::R_AARCH64_NONE);
+
+  switch (r_type)
+    {
+    // These are the relocation types supported by glibc for AARCH64.
+    case elfcpp::R_AARCH64_NONE:
+    case elfcpp::R_AARCH64_COPY:
+    case elfcpp::R_AARCH64_GLOB_DAT:
+    case elfcpp::R_AARCH64_JUMP_SLOT:
+    case elfcpp::R_AARCH64_RELATIVE:
+    case elfcpp::R_AARCH64_TLS_DTPREL64:
+    case elfcpp::R_AARCH64_TLS_DTPMOD64:
+    case elfcpp::R_AARCH64_TLS_TPREL64:
+    case elfcpp::R_AARCH64_TLSDESC:
+    case elfcpp::R_AARCH64_IRELATIVE:
+    case elfcpp::R_AARCH64_ABS32:
+    case elfcpp::R_AARCH64_ABS64:
+      return;
+
+    default:
+      break;
+    }
+
+  // This prevents us from issuing more than one error per reloc
+  // section. But we can still wind up issuing more than one
+  // error per object file.
+  if (this->issued_non_pic_error_)
+    return;
+  gold_assert(parameters->options().output_is_position_independent());
+  object->error(_("requires unsupported dynamic reloc; "
+                  "recompile with -fPIC"));
+  this->issued_non_pic_error_ = true;
+  return;
+}
+
+// Scan a relocation for a local symbol.
+
+template<int size, bool big_endian>
+inline void
+Target_aarch64<size, big_endian>::Scan::local(
+    Symbol_table* /* symtab */,
+    Layout* /* layout */,
+    Target_aarch64<size, big_endian>* /* target */,
+    Sized_relobj_file<size, big_endian>* /* object */,
+    unsigned int /* data_shndx */,
+    Output_section* /* output_section */,
+    const elfcpp::Rela<size, big_endian>& /* reloc */,
+    unsigned int r_type,
+    const elfcpp::Sym<size, big_endian>& /* lsym */,
+    bool is_discarded)
+{
+  if (is_discarded)
+    return;
+
+  switch (r_type)
+    {
+    case elfcpp::R_AARCH64_NONE:
+      break;
+
+      //TODO
+    }
+}
+
+
+// Report an unsupported relocation against a global symbol.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::Scan::unsupported_reloc_global(
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int r_type,
+    Symbol* gsym)
+{
+  gold_error(_("%s: unsupported reloc %u against global symbol %s"),
+	     object->name().c_str(), r_type, gsym->demangled_name().c_str());
+}
+
+template<int size, bool big_endian>
+inline void
+Target_aarch64<size, big_endian>::Scan::global(
+    Symbol_table* /* symtab */,
+    Layout* /* layout */,
+    Target_aarch64<size, big_endian>* /* target */,
+    Sized_relobj_file<size, big_endian>* /* object */,
+    unsigned int /* data_shndx */,
+    Output_section* /* output_section */,
+    const elfcpp::Rela<size, big_endian>& /* reloc */,
+    unsigned int /* r_type */,
+    Symbol* /* gsym */)
+{
+  //TODO
+  return;
+}
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::gc_process_relocs(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_symbols)
+{
+  if (sh_type == elfcpp::SHT_REL)
+    {
+      return;
+    }
+
+  gold::gc_process_relocs<size, big_endian,
+                          Target_aarch64<size, big_endian>,
+                          elfcpp::SHT_RELA,
+                          typename Target_aarch64<size, big_endian>::Scan,
+                          typename Target_aarch64<size, big_endian>::Relocatable_size_for_reloc>(
+    symtab,
+    layout,
+    this,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_symbols);
+}
+
+// Scan relocations for a section.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::scan_relocs(
+    Symbol_table* symtab,
+    Layout* layout,
+    Sized_relobj_file<size, big_endian>* object,
+    unsigned int data_shndx,
+    unsigned int sh_type,
+    const unsigned char* prelocs,
+    size_t reloc_count,
+    Output_section* output_section,
+    bool needs_special_offset_handling,
+    size_t local_symbol_count,
+    const unsigned char* plocal_symbols)
+{
+  if (sh_type == elfcpp::SHT_REL)
+    {
+      gold_error(_("%s: unsupported REL reloc section"),
+		 object->name().c_str());
+      return;
+    }
+
+  gold::scan_relocs<size, big_endian, Target_aarch64<size, big_endian>,
+                    elfcpp::SHT_RELA,
+                    typename Target_aarch64<size, big_endian>::Scan>(
+    symtab,
+    layout,
+    this,
+    object,
+    data_shndx,
+    prelocs,
+    reloc_count,
+    output_section,
+    needs_special_offset_handling,
+    local_symbol_count,
+    plocal_symbols);
+}
+
+// Finalize the sections.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::do_finalize_sections(
+    Layout* /* layout */,
+    const Input_objects*,
+    Symbol_table* /* symtab */)
+{
+  //TODO
+  return;
+}
+
+// Perform a relocation.
+
+template<int size, bool big_endian>
+inline bool
+Target_aarch64<size, big_endian>::Relocate::relocate(
+    const Relocate_info<size, big_endian>* /* relinfo */,
+    Target_aarch64<size, big_endian>* /* target */,
+    Output_section* ,
+    size_t /* relnum */,
+    const elfcpp::Rela<size, big_endian>& /* rela */,
+    unsigned int /* r_type */,
+    const Sized_symbol<size>* /* gsym */,
+    const Symbol_value<size>* /* psymval */,
+    unsigned char* /* view */,
+    typename elfcpp::Elf_types<size>::Elf_Addr /* address */,
+    section_size_type /* view_size */)
+{
+  //TODO
+  return true;
+}
+
+// Relocate section data.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::relocate_section(
+    const Relocate_info<size, big_endian>* /* relinfo */,
+    unsigned int sh_type,
+    const unsigned char* /* prelocs */,
+    size_t /* reloc_count */,
+    Output_section* /* output_section */,
+    bool /*needs_special_offset_handling */,
+    unsigned char* /* view */,
+    typename elfcpp::Elf_types<size>::Elf_Addr /* address */,
+    section_size_type /* view_size */,
+    const Reloc_symbol_changes* /* reloc_symbol_changes */)
+{
+  //TODO
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+}
+
+// Return the size of a relocation while scanning during a relocatable
+// link.
+
+template<int size, bool big_endian>
+unsigned int
+Target_aarch64<size, big_endian>::Relocatable_size_for_reloc::
+get_size_for_reloc(
+    unsigned int ,
+    Relobj* )
+{
+  // We will never support SHT_REL relocations.
+  gold_unreachable();
+  return 0;
+}
+
+// Scan the relocs during a relocatable link.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::scan_relocatable_relocs(
+    Symbol_table* /* symtab */,
+    Layout* /* layout */,
+    Sized_relobj_file<size, big_endian>* /* object */,
+    unsigned int /* data_shndx */,
+    unsigned int sh_type,
+    const unsigned char* /* prelocs */,
+    size_t /* reloc_count */,
+    Output_section* /* output_section */,
+    bool /* needs_special_offset_handling */,
+    size_t /* local_symbol_count */,
+    const unsigned char* /* plocal_symbols */,
+    Relocatable_relocs* /* rr */)
+{
+  //TODO
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+}
+
+// Relocate a section during a relocatable link.
+
+template<int size, bool big_endian>
+void
+Target_aarch64<size, big_endian>::relocate_relocs(
+    const Relocate_info<size, big_endian>* /* relinfo */,
+    unsigned int sh_type,
+    const unsigned char* /* prelocs */,
+    size_t /* reloc_count */,
+    Output_section* /* output_section */,
+    typename elfcpp::Elf_types<size>::Elf_Off /* offset_in_output_section */,
+    const Relocatable_relocs* /* rr */,
+    unsigned char* /* view */,
+    typename elfcpp::Elf_types<size>::Elf_Addr /* view_address */,
+    section_size_type /* view_size */,
+    unsigned char* /* reloc_view */,
+    section_size_type /* reloc_view_size */)
+{
+  //TODO
+  gold_assert(sh_type == elfcpp::SHT_RELA);
+}
+
+
+// The selector for aarch64 object files.
+
+template<int size, bool big_endian>
+class Target_selector_aarch64 : public Target_selector
+{
+ public:
+  Target_selector_aarch64()
+    : Target_selector(elfcpp::EM_AARCH64, size, big_endian,
+                      (size == 64
+                       ? (big_endian ? "elf64-bigaarch64"
+                                     : "elf64-littleaarch64")
+                       : (big_endian ? "elf32-bigaarch64"
+                                     : "elf32-littleaarch64")),
+                      (size == 64
+                       ? (big_endian ? "aarch64_elf64_be_vec"
+                                     : "aarch64_elf64_le_vec")
+                       : (big_endian ? "aarch64_elf32_be_vec"
+                                     : "aarch64_elf32_le_vec")))
+  { }
+
+  virtual Target*
+  do_instantiate_target()
+  { return new Target_aarch64<size, big_endian>(); }
+};
+
+Target_selector_aarch64<32, true> target_selector_aarch64elf32b;
+Target_selector_aarch64<32, false> target_selector_aarch64elf32;
+Target_selector_aarch64<64, true> target_selector_aarch64elfb;
+Target_selector_aarch64<64, false> target_selector_aarch64elf;
+
+
+} // End anonymous namespace.
diff --git a/gold/configure.ac b/gold/configure.ac
index 14ecd72..0478011 100644
--- a/gold/configure.ac
+++ b/gold/configure.ac
@@ -199,6 +199,7 @@ for targ in $target $canon_targets; do
 	default_big_endian=$targ_big_endian
 	default_osabi=$targ_osabi
 
+	AM_CONDITIONAL(DEFAULT_TARGET_AARCH64, test "$targ_obj" = "aarch64")
 	AM_CONDITIONAL(DEFAULT_TARGET_ARM, test "$targ_obj" = "arm")
 	AM_CONDITIONAL(DEFAULT_TARGET_I386, test "$targ_obj" = "i386")
 	AM_CONDITIONAL(DEFAULT_TARGET_POWERPC, test "$targ_obj" = "powerpc")
diff --git a/gold/configure.tgt b/gold/configure.tgt
index 93d622d..9a75070 100644
--- a/gold/configure.tgt
+++ b/gold/configure.tgt
@@ -144,6 +144,14 @@ arm*-*-*)
  targ_big_endian=false
  targ_extra_big_endian=true
  ;;
+aarch64*-*)
+ targ_obj=aarch64
+ targ_machine=EM_AARCH64
+ targ_size=64
+ targ_extra_size=32
+ targ_big_endian=false
+ targ_extra_big_endian=true
+ ;;
 mips*el*-*-*|mips*le*-*-*)
  targ_obj=mips
  targ_machine=EM_MIPS_RS3_LE

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

end of thread, other threads:[~2014-07-02 23:26 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-25 23:47 [gold] First patch for aarch64 backend Jing Yu
2014-07-01 21:55 ` Cary Coutant
2014-07-01 22:15 ` Yufeng Zhang
2014-07-01 23:06   ` Jing Yu
2014-07-01 23:09     ` Andrew Pinski
2014-07-01 23:14       ` Andrew Pinski
2014-07-01 23:21       ` Jing Yu
2014-07-02 23:26         ` Cary Coutant

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).