[lld] r215544 - [AArch64] Initial ELF/AArch64 Support

Chad Rosier mcrosier at codeaurora.org
Wed Aug 13 06:16:38 PDT 2014


Author: mcrosier
Date: Wed Aug 13 08:16:38 2014
New Revision: 215544

URL: http://llvm.org/viewvc/llvm-project?rev=215544&view=rev
Log:
[AArch64] Initial ELF/AArch64 Support

This patch adds the initial ELF/AArch64 support to lld. Only a basic "Hello
World" app has been successfully tested for both dynamic and static compiling.

Differential Revision: http://reviews.llvm.org/D4778
Patch by Daniel Stewart <stewartd at codeaurora.org>!

Added:
    lld/trunk/lib/ReaderWriter/ELF/AArch64/
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
    lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile
    lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst
    lld/trunk/test/elf/AArch64/
    lld/trunk/test/elf/AArch64/Inputs/
    lld/trunk/test/elf/AArch64/Inputs/fn.c
    lld/trunk/test/elf/AArch64/Inputs/fn.o
    lld/trunk/test/elf/AArch64/Inputs/initfini-option.c
    lld/trunk/test/elf/AArch64/Inputs/initfini-option.o
    lld/trunk/test/elf/AArch64/Inputs/initfini.c
    lld/trunk/test/elf/AArch64/Inputs/initfini.o
    lld/trunk/test/elf/AArch64/Inputs/main.c
    lld/trunk/test/elf/AArch64/Inputs/main.o
    lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c
    lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o
    lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o
    lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s
    lld/trunk/test/elf/AArch64/defsym.test
    lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test
    lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test
    lld/trunk/test/elf/AArch64/initfini-alignment.test
    lld/trunk/test/elf/AArch64/initfini-option.test
    lld/trunk/test/elf/AArch64/initfini.test
Modified:
    lld/trunk/docs/open_projects.rst
    lld/trunk/include/lld/Core/Reference.h
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/ReaderWriter/ELF/Atoms.h
    lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/ELF/ELFFile.h
    lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/ELF/Makefile
    lld/trunk/lib/ReaderWriter/ELF/Targets.h
    lld/trunk/tools/lld/Makefile
    lld/trunk/unittests/DriverTests/Makefile

Modified: lld/trunk/docs/open_projects.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/open_projects.rst?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/docs/open_projects.rst (original)
+++ lld/trunk/docs/open_projects.rst Wed Aug 13 08:16:38 2014
@@ -7,6 +7,7 @@ Open Projects
 .. include:: ../lib/Core/TODO.txt
 .. include:: ../lib/Driver/TODO.rst
 .. include:: ../lib/ReaderWriter/ELF/X86_64/TODO.rst
+.. include:: ../lib/ReaderWriter/ELF/AArch64/TODO.rst
 .. include:: ../tools/lld/TODO.txt
 
 Documentation TODOs

Modified: lld/trunk/include/lld/Core/Reference.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Reference.h?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Reference.h (original)
+++ lld/trunk/include/lld/Core/Reference.h Wed Aug 13 08:16:38 2014
@@ -64,7 +64,8 @@ public:
     ARM     = 3,
     PowerPC = 4,
     Hexagon = 5,
-    Mips    = 6
+    Mips    = 6,
+    AArch64 = 7
   };
 
   KindArch kindArch() const { return (KindArch)_kindArch; }

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Wed Aug 13 08:16:38 2014
@@ -204,6 +204,10 @@ getArchType(const llvm::Triple &triple,
     if (value == "elf32ltsmip")
       return llvm::Triple::mipsel;
     return llvm::None;
+  case llvm::Triple::aarch64:
+    if (value == "aarch64linux")
+      return llvm::Triple::aarch64;
+    return llvm::None;
   default:
     return llvm::None;
   }

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,69 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h ---------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef AARCH64_DYNAMIC_LIBRARY_WRITER_H
+#define AARCH64_DYNAMIC_LIBRARY_WRITER_H
+
+#include "DynamicLibraryWriter.h"
+#include "AArch64LinkingContext.h"
+
+namespace lld {
+namespace elf {
+
+template <class ELFT>
+class AArch64DynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
+public:
+  AArch64DynamicLibraryWriter(AArch64LinkingContext &context,
+                              AArch64TargetLayout<ELFT> &layout);
+
+protected:
+  // Add any runtime files and their atoms to the output
+  virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &);
+
+  virtual void finalizeDefaultAtomValues() {
+    return DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues();
+  }
+
+  virtual void addDefaultAtoms() {
+    return DynamicLibraryWriter<ELFT>::addDefaultAtoms();
+  }
+
+private:
+  class GOTFile : public SimpleFile {
+  public:
+    GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {}
+    llvm::BumpPtrAllocator _alloc;
+  };
+
+  std::unique_ptr<GOTFile> _gotFile;
+  AArch64LinkingContext &_context;
+  AArch64TargetLayout<ELFT> &_AArch64Layout;
+};
+
+template <class ELFT>
+AArch64DynamicLibraryWriter<ELFT>::AArch64DynamicLibraryWriter(
+    AArch64LinkingContext &context, AArch64TargetLayout<ELFT> &layout)
+    : DynamicLibraryWriter<ELFT>(context, layout),
+      _gotFile(new GOTFile(context)), _context(context),
+      _AArch64Layout(layout) {}
+
+template <class ELFT>
+bool AArch64DynamicLibraryWriter<ELFT>::createImplicitFiles(
+    std::vector<std::unique_ptr<File>> &result) {
+  DynamicLibraryWriter<ELFT>::createImplicitFiles(result);
+  _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile));
+  _gotFile->addAtom(*new (_gotFile->_alloc) TLSGETADDRAtom(*_gotFile));
+  _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile));
+  result.push_back(std::move(_gotFile));
+  return true;
+}
+
+} // namespace elf
+} // namespace lld
+
+#endif

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,69 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h -------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef AARCH64_EXECUTABLE_WRITER_H
+#define AARCH64_EXECUTABLE_WRITER_H
+
+#include "ExecutableWriter.h"
+#include "AArch64LinkingContext.h"
+
+namespace lld {
+namespace elf {
+
+template <class ELFT>
+class AArch64ExecutableWriter : public ExecutableWriter<ELFT> {
+public:
+  AArch64ExecutableWriter(AArch64LinkingContext &context,
+                          AArch64TargetLayout<ELFT> &layout);
+
+protected:
+  // Add any runtime files and their atoms to the output
+  bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
+
+  void finalizeDefaultAtomValues() override {
+    return ExecutableWriter<ELFT>::finalizeDefaultAtomValues();
+  }
+
+  void addDefaultAtoms() override{
+    return ExecutableWriter<ELFT>::addDefaultAtoms();
+  }
+
+private:
+  class GOTFile : public SimpleFile {
+  public:
+    GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {}
+    llvm::BumpPtrAllocator _alloc;
+  };
+
+  std::unique_ptr<GOTFile> _gotFile;
+  AArch64LinkingContext &_context;
+  AArch64TargetLayout<ELFT> &_AArch64Layout;
+};
+
+template <class ELFT>
+AArch64ExecutableWriter<ELFT>::AArch64ExecutableWriter(
+    AArch64LinkingContext &context, AArch64TargetLayout<ELFT> &layout)
+    : ExecutableWriter<ELFT>(context, layout), _gotFile(new GOTFile(context)),
+      _context(context), _AArch64Layout(layout) {}
+
+template <class ELFT>
+bool AArch64ExecutableWriter<ELFT>::createImplicitFiles(
+    std::vector<std::unique_ptr<File>> &result) {
+  ExecutableWriter<ELFT>::createImplicitFiles(result);
+  _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile));
+  _gotFile->addAtom(*new (_gotFile->_alloc) TLSGETADDRAtom(*_gotFile));
+  if (_context.isDynamic())
+    _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile));
+  result.push_back(std::move(_gotFile));
+  return true;
+}
+
+} // namespace elf
+} // namespace lld
+
+#endif

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp Wed Aug 13 08:16:38 2014
@@ -0,0 +1,112 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp -------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64LinkingContext.h"
+
+#include "lld/Core/File.h"
+#include "lld/Core/Instrumentation.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringSwitch.h"
+
+#include "Atoms.h"
+#include "AArch64RelocationPass.h"
+
+using namespace lld;
+using namespace lld::elf;
+
+using llvm::makeArrayRef;
+
+namespace {
+using namespace llvm::ELF;
+
+const uint8_t AArch64InitFiniAtomContent[8] = {0};
+
+// AArch64InitFini Atom
+class AArch64InitAtom : public InitFiniAtom {
+public:
+  AArch64InitAtom(const File &f, StringRef function)
+      : InitFiniAtom(f, ".init_array") {
+#ifndef NDEBUG
+    _name = "__init_fn_";
+    _name += function;
+#endif
+  }
+  ArrayRef<uint8_t> rawContent() const override {
+    return makeArrayRef(AArch64InitFiniAtomContent);
+  }
+  Alignment alignment() const override { return Alignment(3); }
+};
+
+class AArch64FiniAtom : public InitFiniAtom {
+public:
+  AArch64FiniAtom(const File &f, StringRef function)
+      : InitFiniAtom(f, ".fini_array") {
+#ifndef NDEBUG
+    _name = "__fini_fn_";
+    _name += function;
+#endif
+  }
+  ArrayRef<uint8_t> rawContent() const override {
+    return makeArrayRef(AArch64InitFiniAtomContent);
+  }
+
+  Alignment alignment() const override { return Alignment(3); }
+};
+
+class AArch64InitFiniFile : public SimpleFile {
+public:
+  AArch64InitFiniFile(const ELFLinkingContext &context)
+      : SimpleFile("command line option -init/-fini"), _ordinal(0) {}
+
+  void addInitFunction(StringRef name) {
+    Atom *initFunctionAtom = new (_allocator) SimpleUndefinedAtom(*this, name);
+    AArch64InitAtom *initAtom = (new (_allocator) AArch64InitAtom(*this, name));
+    initAtom->addReferenceELF_AArch64(llvm::ELF::R_AARCH64_ABS64, 0,
+                                      initFunctionAtom, 0);
+    initAtom->setOrdinal(_ordinal++);
+    addAtom(*initFunctionAtom);
+    addAtom(*initAtom);
+  }
+
+  void addFiniFunction(StringRef name) {
+    Atom *finiFunctionAtom = new (_allocator) SimpleUndefinedAtom(*this, name);
+    AArch64FiniAtom *finiAtom = (new (_allocator) AArch64FiniAtom(*this, name));
+    finiAtom->addReferenceELF_AArch64(llvm::ELF::R_AARCH64_ABS64, 0,
+                                      finiFunctionAtom, 0);
+    finiAtom->setOrdinal(_ordinal++);
+    addAtom(*finiFunctionAtom);
+    addAtom(*finiAtom);
+  }
+
+private:
+  llvm::BumpPtrAllocator _allocator;
+  uint64_t _ordinal;
+};
+
+} // end anon namespace
+
+void elf::AArch64LinkingContext::addPasses(PassManager &pm) {
+  auto pass = createAArch64RelocationPass(*this);
+  if (pass)
+    pm.add(std::move(pass));
+  ELFLinkingContext::addPasses(pm);
+}
+
+void elf::AArch64LinkingContext::createInternalFiles(
+    std::vector<std::unique_ptr<File>> &result) const {
+  ELFLinkingContext::createInternalFiles(result);
+  std::unique_ptr<AArch64InitFiniFile> initFiniFile(
+      new AArch64InitFiniFile(*this));
+  for (auto ai : initFunctions())
+    initFiniFile->addInitFunction(ai);
+  for (auto ai : finiFunctions())
+    initFiniFile->addFiniFunction(ai);
+  result.push_back(std::move(initFiniFile));
+}

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,95 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h ---------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_LINKING_CONTEXT_H
+#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_LINKING_CONTEXT_H
+
+#include "AArch64TargetHandler.h"
+
+#include "lld/ReaderWriter/ELFLinkingContext.h"
+
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/ELF.h"
+
+namespace lld {
+namespace elf {
+
+enum {
+  /// \brief The offset to add operation for a R_AARCH64_ADR_GOT_PAGE
+  ADD_AARCH64_GOTRELINDEX = 0xE000,
+};
+
+class AArch64LinkingContext final : public ELFLinkingContext {
+public:
+  AArch64LinkingContext(llvm::Triple triple)
+      : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
+                                      new AArch64TargetHandler(*this))) {}
+
+  void addPasses(PassManager &) override;
+
+  uint64_t getBaseAddress() const override {
+    if (_baseAddress == 0)
+      return 0x400000;
+    return _baseAddress;
+  }
+
+  bool isDynamicRelocation(const DefinedAtom &,
+                           const Reference &r) const override {
+    if (r.kindNamespace() != Reference::KindNamespace::ELF)
+      return false;
+    assert(r.kindArch() == Reference::KindArch::AArch64);
+    switch (r.kindValue()) {
+    case llvm::ELF::R_AARCH64_COPY:
+    case llvm::ELF::R_AARCH64_GLOB_DAT:
+    case llvm::ELF::R_AARCH64_RELATIVE:
+    case llvm::ELF::R_AARCH64_TLS_DTPREL64:
+    case llvm::ELF::R_AARCH64_TLS_DTPMOD64:
+    case llvm::ELF::R_AARCH64_TLS_TPREL64:
+    case llvm::ELF::R_AARCH64_TLSDESC:
+    case llvm::ELF::R_AARCH64_IRELATIVE:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  bool isPLTRelocation(const DefinedAtom &,
+                               const Reference &r) const override {
+    if (r.kindNamespace() != Reference::KindNamespace::ELF)
+      return false;
+    assert(r.kindArch() == Reference::KindArch::AArch64);
+    switch (r.kindValue()) {
+    case llvm::ELF::R_AARCH64_JUMP_SLOT:
+    case llvm::ELF::R_AARCH64_IRELATIVE:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  bool isRelativeReloc(const Reference &r) const override {
+    if (r.kindNamespace() != Reference::KindNamespace::ELF)
+      return false;
+    assert(r.kindArch() == Reference::KindArch::AArch64);
+    switch (r.kindValue()) {
+    case llvm::ELF::R_AARCH64_IRELATIVE:
+    case llvm::ELF::R_AARCH64_RELATIVE:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  /// \brief Create Internal files for Init/Fini
+  void createInternalFiles(std::vector<std::unique_ptr<File>> &) const override;
+};
+} // end namespace elf
+} // end namespace lld
+
+#endif

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp Wed Aug 13 08:16:38 2014
@@ -0,0 +1,490 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp ----------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64TargetHandler.h"
+#include "AArch64LinkingContext.h"
+#include "llvm/Support/Debug.h"
+
+using namespace lld;
+using namespace elf;
+
+#define PAGE(X) ((X) & ~0x0FFFL)
+
+/// \brief R_AARCH64_ABS64 - word64: S + A
+static void relocR_AARCH64_ABS64(uint8_t *location, uint64_t P, uint64_t S,
+                                 int64_t A) {
+  int64_t result = (int64_t)S + A;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: 0x" << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::ulittle64_t *>(location) =
+      result |
+      (int64_t) * reinterpret_cast<llvm::support::little64_t *>(location);
+}
+
+/// \brief R_AARCH64_PREL32 - word32: S + A - P
+static void relocR_AARCH64_PREL32(uint8_t *location, uint64_t P, uint64_t S,
+                                  int64_t A) {
+  int32_t result = (int32_t)((S + A) - P);
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result +
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_ABS32 - word32:  S + A
+static void relocR_AARCH64_ABS32(uint8_t *location, uint64_t P, uint64_t S,
+                                 int64_t A) {
+  int32_t result = (int32_t)(S + A);
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: 0x" << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::ulittle32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_ADR_PREL_PG_HI21 - Page(S+A) - Page(P)
+static void relocR_AARCH64_ADR_PREL_PG_HI21(uint8_t *location, uint64_t P,
+                                            uint64_t S, int64_t A) {
+  uint64_t result = (PAGE(S + A) - PAGE(P));
+  result = result >> 12;
+  uint32_t immlo = result & 0x3;
+  uint32_t immhi = result & 0x1FFFFC;
+  immlo = immlo << 29;
+  immhi = immhi << 3;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
+                  llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      immlo | immhi |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+  // TODO: Make sure this is correct!
+}
+
+/// \brief R_AARCH64_ADR_PREL_LO21 - S + A - P
+static void relocR_AARCH64_ADR_PREL_LO21(uint8_t *location, uint64_t P,
+                                         uint64_t S, int64_t A) {
+  uint64_t result = (S + A) - P;
+  uint32_t immlo = result & 0x3;
+  uint32_t immhi = result & 0x1FFFFC;
+  immlo = immlo << 29;
+  immhi = immhi << 3;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
+                  llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      immlo | immhi |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+  // TODO: Make sure this is correct!
+}
+
+/// \brief R_AARCH64_ADD_ABS_LO12_NC
+static void relocR_AARCH64_ADD_ABS_LO12_NC(uint8_t *location, uint64_t P,
+                                           uint64_t S, int64_t A) {
+  int32_t result = (int32_t)((S + A) & 0xFFF);
+  result <<= 10;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+static void relocJump26(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
+  int32_t result = (int32_t)((S + A) - P);
+  result &= 0x0FFFFFFC;
+  result >>= 2;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_CONDBR19
+static void relocR_AARCH64_CONDBR19(uint8_t *location, uint64_t P, uint64_t S,
+                                    int64_t A) {
+  int32_t result = (int32_t)((S + A) - P);
+  result &= 0x01FFFFC;
+  result <<= 3;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST8_ABS_LO12_NC - S + A
+static void relocR_AARCH64_LDST8_ABS_LO12_NC(uint8_t *location, uint64_t P,
+                                             uint64_t S, int64_t A) {
+  int32_t result = (int32_t)((S + A) & 0xFFF);
+  result <<= 10;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST16_ABS_LO12_NC
+static void relocR_AARCH64_LDST16_ABS_LO12_NC(uint8_t *location, uint64_t P,
+                                              uint64_t S, int64_t A) {
+  int32_t result = (int32_t)(S + A);
+  result &= 0x0FFC;
+  result <<= 9;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST32_ABS_LO12_NC
+static void relocR_AARCH64_LDST32_ABS_LO12_NC(uint8_t *location, uint64_t P,
+                                              uint64_t S, int64_t A) {
+  int32_t result = (int32_t)(S + A);
+  result &= 0x0FFC;
+  result <<= 8;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST64_ABS_LO12_NC
+static void relocR_AARCH64_LDST64_ABS_LO12_NC(uint8_t *location, uint64_t P,
+                                              uint64_t S, int64_t A) {
+  int32_t result = (int32_t)(S + A);
+  result &= 0x0FF8;
+  result <<= 7;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST128_ABS_LO12_NC
+static void relocR_AARCH64_LDST128_ABS_LO12_NC(uint8_t *location, uint64_t P,
+                                               uint64_t S, int64_t A) {
+  int32_t result = (int32_t)(S + A);
+  result &= 0x0FF8;
+  result <<= 6;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+static void relocR_AARCH64_ADR_GOT_PAGE(uint8_t *location, uint64_t P,
+                                        uint64_t S, int64_t A) {
+  uint64_t result = PAGE(S + A) - PAGE(P);
+  result >>= 12;
+  uint32_t immlo = result & 0x3;
+  uint32_t immhi = result & 0x1FFFFC;
+  immlo = immlo << 29;
+  immhi = immhi << 3;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
+                  llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      immlo | immhi |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+// R_AARCH64_LD64_GOT_LO12_NC
+static void relocR_AARCH64_LD64_GOT_LO12_NC(uint8_t *location, uint64_t P,
+                                            uint64_t S, int64_t A) {
+  int32_t result = S + A;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  result &= 0xFF8;
+  result <<= 7;
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+// ADD_AARCH64_GOTRELINDEX
+static void relocADD_AARCH64_GOTRELINDEX(uint8_t *location, uint64_t P,
+                                         uint64_t S, int64_t A) {
+  int32_t result = S + A;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  result &= 0xFFF;
+  result <<= 10;
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+// R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
+static void relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(uint8_t *location,
+                                                     uint64_t P, uint64_t S,
+                                                     int64_t A) {
+  int64_t result = PAGE(S + A) - PAGE(P);
+  result >>= 12;
+  uint32_t immlo = result & 0x3;
+  uint32_t immhi = result & 0x1FFFFC;
+  immlo = immlo << 29;
+  immhi = immhi << 3;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
+                  llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      immlo | immhi |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+// R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
+static void relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(uint8_t *location,
+                                                       uint64_t P, uint64_t S,
+                                                       int64_t A) {
+  int32_t result = S + A;
+  result &= 0xFF8;
+  result <<= 7;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_TLSLE_ADD_TPREL_HI12
+static void relocR_AARCH64_TLSLE_ADD_TPREL_HI12(uint8_t *location, uint64_t P,
+                                                uint64_t S, int64_t A) {
+  int32_t result = S + A;
+  result &= 0x0FFF000;
+  result >>= 2;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
+static void relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(uint8_t *location,
+                                                   uint64_t P, uint64_t S,
+                                                   int64_t A) {
+  int32_t result = S + A;
+  result &= 0x0FFF;
+  result <<= 10;
+  DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+                  llvm::dbgs() << " S: " << Twine::utohexstr(S);
+                  llvm::dbgs() << " A: " << Twine::utohexstr(A);
+                  llvm::dbgs() << " P: " << Twine::utohexstr(P);
+                  llvm::dbgs() << " result: " << Twine::utohexstr(result)
+                               << "\n");
+  *reinterpret_cast<llvm::support::little32_t *>(location) =
+      result |
+      (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+int64_t
+AArch64TargetRelocationHandler::relocAddend(const Reference &ref) const {
+  if (ref.kindNamespace() != Reference::KindNamespace::ELF)
+    return false;
+  assert(ref.kindArch() == Reference::KindArch::AArch64);
+  switch (ref.kindValue()) {
+  case R_AARCH64_PREL32:
+    return 4;
+  default:
+    return 0;
+  }
+  return 0;
+}
+
+std::error_code AArch64TargetRelocationHandler::applyRelocation(
+    ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
+    const Reference &ref) const {
+  uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
+  uint8_t *location = atomContent + ref.offsetInAtom();
+  uint64_t targetVAddress = writer.addressOfAtom(ref.target());
+  uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
+
+  if (ref.kindNamespace() != Reference::KindNamespace::ELF)
+    return std::error_code();
+  assert(ref.kindArch() == Reference::KindArch::AArch64);
+  switch (ref.kindValue()) {
+  case R_AARCH64_NONE:
+    break;
+  case R_AARCH64_ABS64:
+    relocR_AARCH64_ABS64(location, relocVAddress, targetVAddress, ref.addend());
+    break;
+  case R_AARCH64_PREL32:
+    relocR_AARCH64_PREL32(location, relocVAddress, targetVAddress,
+                          ref.addend());
+    break;
+  case R_AARCH64_ABS32:
+    relocR_AARCH64_ABS32(location, relocVAddress, targetVAddress, ref.addend());
+    break;
+  // Runtime only relocations. Ignore here.
+  case R_AARCH64_RELATIVE:
+  case R_AARCH64_IRELATIVE:
+  case R_AARCH64_JUMP_SLOT:
+  case R_AARCH64_GLOB_DAT:
+    break;
+  case R_AARCH64_ADR_PREL_PG_HI21:
+    relocR_AARCH64_ADR_PREL_PG_HI21(location, relocVAddress, targetVAddress,
+                                    ref.addend());
+    break;
+  case R_AARCH64_ADR_PREL_LO21:
+    relocR_AARCH64_ADR_PREL_LO21(location, relocVAddress, targetVAddress,
+                                 ref.addend());
+    break;
+  case R_AARCH64_ADD_ABS_LO12_NC:
+    relocR_AARCH64_ADD_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+                                   ref.addend());
+    break;
+  case R_AARCH64_CALL26:
+  case R_AARCH64_JUMP26:
+    relocJump26(location, relocVAddress, targetVAddress, ref.addend());
+    break;
+  case R_AARCH64_CONDBR19:
+    relocR_AARCH64_CONDBR19(location, relocVAddress, targetVAddress,
+                            ref.addend());
+    break;
+  case R_AARCH64_ADR_GOT_PAGE:
+    relocR_AARCH64_ADR_GOT_PAGE(location, relocVAddress, targetVAddress,
+                                ref.addend());
+    break;
+  case R_AARCH64_LD64_GOT_LO12_NC:
+    relocR_AARCH64_LD64_GOT_LO12_NC(location, relocVAddress, targetVAddress,
+                                    ref.addend());
+    break;
+  case R_AARCH64_LDST8_ABS_LO12_NC:
+    relocR_AARCH64_LDST8_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+                                     ref.addend());
+    break;
+  case R_AARCH64_LDST16_ABS_LO12_NC:
+    relocR_AARCH64_LDST16_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+                                      ref.addend());
+    break;
+  case R_AARCH64_LDST32_ABS_LO12_NC:
+    relocR_AARCH64_LDST32_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+                                      ref.addend());
+    break;
+  case R_AARCH64_LDST64_ABS_LO12_NC:
+    relocR_AARCH64_LDST64_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+                                      ref.addend());
+    break;
+  case R_AARCH64_LDST128_ABS_LO12_NC:
+    relocR_AARCH64_LDST128_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+                                       ref.addend());
+    break;
+  case ADD_AARCH64_GOTRELINDEX:
+    relocADD_AARCH64_GOTRELINDEX(location, relocVAddress, targetVAddress,
+                                 ref.addend());
+    break;
+  case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+    relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(location, relocVAddress,
+                                             targetVAddress, ref.addend());
+    break;
+  case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+    relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(location, relocVAddress,
+                                               targetVAddress, ref.addend());
+    break;
+  case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+    relocR_AARCH64_TLSLE_ADD_TPREL_HI12(location, relocVAddress, targetVAddress,
+                                        ref.addend());
+    break;
+  case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+    relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(location, relocVAddress,
+                                           targetVAddress, ref.addend());
+    break;
+  default: {
+    std::string str;
+    llvm::raw_string_ostream s(str);
+    s << "Unhandled relocation: " << atom._atom->file().path() << ":"
+      << atom._atom->name() << "@" << ref.offsetInAtom() << " "
+      << "#" << ref.kindValue();
+    s.flush();
+    llvm_unreachable(str.c_str());
+  }
+  }
+
+  return std::error_code();
+}

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,44 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h ------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef AARCH64_RELOCATION_HANDLER_H
+#define AARCH64_RELOCATION_HANDLER_H
+
+#include "AArch64TargetHandler.h"
+
+namespace lld {
+namespace elf {
+typedef llvm::object::ELFType<llvm::support::little, 2, true> AArch64ELFType;
+
+template <class ELFT> class AArch64TargetLayout;
+
+class AArch64TargetRelocationHandler final
+    : public TargetRelocationHandler<AArch64ELFType> {
+public:
+  AArch64TargetRelocationHandler(AArch64TargetLayout<AArch64ELFType> &layout)
+      : _tlsSize(0), _AArch64Layout(layout) {}
+
+  std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
+                                  const lld::AtomLayout &,
+                                  const Reference &) const override;
+
+  virtual int64_t relocAddend(const Reference &) const;
+
+  static const Registry::KindStrings kindStrings[];
+
+private:
+  // Cached size of the TLS segment.
+  mutable uint64_t _tlsSize;
+  AArch64TargetLayout<AArch64ELFType> &_AArch64Layout;
+};
+
+} // end namespace elf
+} // end namespace lld
+
+#endif // AArch64_RELOCATION_HANDLER_H

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp Wed Aug 13 08:16:38 2014
@@ -0,0 +1,535 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp -------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the relocation processing pass for AArch64. This includes
+///   GOT and PLT entries, TLS, COPY, and ifunc.
+///
+/// This also includes additional behavior that gnu-ld and gold implement but
+/// which is not specified anywhere.
+///
+//===----------------------------------------------------------------------===//
+
+#include "AArch64RelocationPass.h"
+
+#include "lld/Core/Simple.h"
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "Atoms.h"
+#include "AArch64LinkingContext.h"
+#include "llvm/Support/Debug.h"
+
+using namespace lld;
+using namespace lld::elf;
+using namespace llvm::ELF;
+
+namespace {
+// .got values
+const uint8_t AArch64GotAtomContent[8] = {0};
+
+// .plt value (entry 0)
+const uint8_t AArch64Plt0AtomContent[32] = {
+    0xf0, 0x7b, 0xbf,
+    0xa9, // stp	x16, x30, [sp,#-16]!
+    0x10, 0x00, 0x00,
+    0x90, // adrp	x16, Page(eh_frame)
+    0x11, 0x02, 0x40,
+    0xf9, // ldr	x17, [x16,#offset]
+    0x10, 0x02, 0x00,
+    0x91, // add	x16, x16, #offset
+    0x20, 0x02, 0x1f,
+    0xd6, // br	x17
+    0x1f, 0x20, 0x03,
+    0xd5, // nop
+    0x1f, 0x20, 0x03,
+    0xd5, // nop
+    0x1f, 0x20, 0x03,
+    0xd5 // nop
+};
+
+// .plt values (other entries)
+const uint8_t AArch64PltAtomContent[16] = {
+    0x10, 0x00, 0x00,
+    0x90, // adrp x16, PAGE(<GLOBAL_OFFSET_TABLE>)
+    0x11, 0x02, 0x40,
+    0xf9, // ldr x17, [x16,#offset]
+    0x10, 0x02, 0x00,
+    0x91, // add x16, x16, #offset
+    0x20, 0x02, 0x1f,
+    0xd6 // br x17
+};
+
+/// \brief Atoms that are used by AArch64 dynamic linking
+class AArch64GOTAtom : public GOTAtom {
+public:
+  AArch64GOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
+
+  ArrayRef<uint8_t> rawContent() const override {
+    return ArrayRef<uint8_t>(AArch64GotAtomContent, 8);
+  }
+};
+
+class AArch64PLT0Atom : public PLT0Atom {
+public:
+  AArch64PLT0Atom(const File &f) : PLT0Atom(f) {
+#ifndef NDEBUG
+    _name = ".PLT0";
+#endif
+  }
+  ArrayRef<uint8_t> rawContent() const override {
+    return ArrayRef<uint8_t>(AArch64Plt0AtomContent, 32);
+  }
+};
+
+class AArch64PLTAtom : public PLTAtom {
+public:
+  AArch64PLTAtom(const File &f, StringRef secName) : PLTAtom(f, secName) {}
+
+  ArrayRef<uint8_t> rawContent() const override {
+    return ArrayRef<uint8_t>(AArch64PltAtomContent, 16);
+  }
+};
+
+class ELFPassFile : public SimpleFile {
+public:
+  ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") {
+    setOrdinal(eti.getNextOrdinalAndIncrement());
+  }
+
+  llvm::BumpPtrAllocator _alloc;
+};
+
+/// \brief CRTP base for handling relocations.
+template <class Derived> class AArch64RelocationPass : public Pass {
+  /// \brief Handle a specific reference.
+  void handleReference(const DefinedAtom &atom, const Reference &ref) {
+    DEBUG_WITH_TYPE(
+        "AArch64", llvm::dbgs()
+                       << "\t" << __func__ << "()"
+                       << ":   Name of Defined Atom: " << atom.name().str();
+        llvm::dbgs() << "   kindValue: " << ref.kindValue() << "\n");
+    if (ref.kindNamespace() != Reference::KindNamespace::ELF)
+      return;
+    assert(ref.kindArch() == Reference::KindArch::AArch64);
+    switch (ref.kindValue()) {
+    case R_AARCH64_ABS32:
+    case R_AARCH64_ABS16:
+    case R_AARCH64_ABS64:
+    case R_AARCH64_PREL16:
+    case R_AARCH64_PREL32:
+    case R_AARCH64_PREL64:
+      static_cast<Derived *>(this)->handlePlain(ref);
+      break;
+    case R_AARCH64_GOTREL32:
+    case R_AARCH64_GOTREL64:
+      static_cast<Derived *>(this)->handleGOT(ref);
+      break;
+    case R_AARCH64_ADR_PREL_PG_HI21:
+      static_cast<Derived *>(this)->handlePlain(ref);
+      break;
+    case R_AARCH64_LDST8_ABS_LO12_NC:
+    case R_AARCH64_LDST16_ABS_LO12_NC:
+    case R_AARCH64_LDST32_ABS_LO12_NC:
+    case R_AARCH64_LDST64_ABS_LO12_NC:
+    case R_AARCH64_LDST128_ABS_LO12_NC:
+      static_cast<Derived *>(this)->handlePlain(ref);
+      break;
+    case R_AARCH64_ADD_ABS_LO12_NC:
+      static_cast<Derived *>(this)->handlePlain(ref);
+      break;
+    case R_AARCH64_CALL26:
+    case R_AARCH64_JUMP26:
+    case R_AARCH64_CONDBR19:
+      static_cast<Derived *>(this)->handlePlain(ref);
+      break;
+    case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+      static_cast<Derived *>(this)->handlePlain(ref);
+      break;
+    case R_AARCH64_ADR_GOT_PAGE:
+    case R_AARCH64_LD64_GOT_LO12_NC:
+    case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+    case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+      static_cast<Derived *>(this)->handleGOT(ref);
+      break;
+    default:
+      llvm_unreachable("Unhandled type in handleReference");
+    }
+  }
+
+protected:
+  /// \brief get the PLT entry for a given IFUNC Atom.
+  ///
+  /// If the entry does not exist. Both the GOT and PLT entry is created.
+  const PLTAtom *getIFUNCPLTEntry(const DefinedAtom *da) {
+    auto plt = _pltMap.find(da);
+    if (plt != _pltMap.end())
+      return plt->second;
+    auto ga = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+    ga->addReferenceELF_AArch64(R_AARCH64_IRELATIVE, 0, da, 0);
+    auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
+    pa->addReferenceELF_AArch64(R_AARCH64_PREL32, 2, ga, -4);
+#ifndef NDEBUG
+    ga->_name = "__got_ifunc_";
+    ga->_name += da->name();
+    pa->_name = "__plt_ifunc_";
+    pa->_name += da->name();
+#endif
+    _gotMap[da] = ga;
+    _pltMap[da] = pa;
+    _gotVector.push_back(ga);
+    _pltVector.push_back(pa);
+    return pa;
+  }
+
+  /// \brief Redirect the call to the PLT stub for the target IFUNC.
+  ///
+  /// This create a PLT and GOT entry for the IFUNC if one does not exist. The
+  /// GOT entry and a IRELATIVE relocation to the original target resolver.
+  std::error_code handleIFUNC(const Reference &ref) {
+    auto target = dyn_cast_or_null<const DefinedAtom>(ref.target());
+    if (target && target->contentType() == DefinedAtom::typeResolver)
+      const_cast<Reference &>(ref).setTarget(getIFUNCPLTEntry(target));
+    return std::error_code();
+  }
+
+  /// \brief Create a GOT entry for the TP offset of a TLS atom.
+  const GOTAtom *getGOTTPOFF(const Atom *atom) {
+    auto got = _gotMap.find(atom);
+    if (got == _gotMap.end()) {
+      auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
+      g->addReferenceELF_AArch64(R_AARCH64_GOTREL64, 0, atom, 0);
+#ifndef NDEBUG
+      g->_name = "__got_tls_";
+      g->_name += atom->name();
+#endif
+      _gotMap[atom] = g;
+      _gotVector.push_back(g);
+      return g;
+    }
+    return got->second;
+  }
+
+  /// \brief Create a TPOFF64 GOT entry and change the relocation to a PC32 to
+  /// the GOT.
+  void handleGOTTPOFF(const Reference &ref) {
+    const_cast<Reference &>(ref).setTarget(getGOTTPOFF(ref.target()));
+    const_cast<Reference &>(ref).setKindValue(R_AARCH64_PREL32);
+  }
+
+  /// \brief Create a GOT entry containing 0.
+  const GOTAtom *getNullGOT() {
+    if (!_null) {
+      _null = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+#ifndef NDEBUG
+      _null->_name = "__got_null";
+#endif
+    }
+    return _null;
+  }
+
+  const GOTAtom *getGOT(const DefinedAtom *da) {
+    auto got = _gotMap.find(da);
+    if (got == _gotMap.end()) {
+      auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
+      g->addReferenceELF_AArch64(R_AARCH64_ABS64, 0, da, 0);
+#ifndef NDEBUG
+      g->_name = "__got_";
+      g->_name += da->name();
+#endif
+      _gotMap[da] = g;
+      _gotVector.push_back(g);
+      return g;
+    }
+    return got->second;
+  }
+
+public:
+  AArch64RelocationPass(const ELFLinkingContext &ctx)
+      : _file(ctx), _ctx(ctx), _null(nullptr), _PLT0(nullptr), _got0(nullptr),
+        _got1(nullptr) {}
+
+  /// \brief Do the pass.
+  ///
+  /// The goal here is to first process each reference individually. Each call
+  /// to handleReference may modify the reference itself and/or create new
+  /// atoms which must be stored in one of the maps below.
+  ///
+  /// After all references are handled, the atoms created during that are all
+  /// added to mf.
+  void perform(std::unique_ptr<MutableFile> &mf) override {
+    ScopedTask task(getDefaultDomain(), "AArch64 GOT/PLT Pass");
+    DEBUG_WITH_TYPE(
+        "AArch64", llvm::dbgs() << "Undefined Atoms"
+                                << "\n";
+        for (const auto &atom
+             : mf->undefined()) {
+          llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
+        } llvm::dbgs()
+            << "Shared Library Atoms"
+            << "\n";
+        for (const auto &atom
+             : mf->sharedLibrary()) {
+          llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
+        } llvm::dbgs()
+            << "Absolute Atoms"
+            << "\n";
+        for (const auto &atom
+             : mf->absolute()) {
+          llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
+        }
+            // Process all references.
+            llvm::dbgs()
+            << "Defined Atoms"
+            << "\n");
+    for (const auto &atom : mf->defined()) {
+      for (const auto &ref : *atom) {
+        handleReference(*atom, *ref);
+      }
+    }
+
+    // Add all created atoms to the link.
+    uint64_t ordinal = 0;
+    if (_PLT0) {
+      _PLT0->setOrdinal(ordinal++);
+      mf->addAtom(*_PLT0);
+    }
+    for (auto &plt : _pltVector) {
+      plt->setOrdinal(ordinal++);
+      mf->addAtom(*plt);
+    }
+    if (_null) {
+      _null->setOrdinal(ordinal++);
+      mf->addAtom(*_null);
+    }
+    if (_PLT0) {
+      _got0->setOrdinal(ordinal++);
+      _got1->setOrdinal(ordinal++);
+      mf->addAtom(*_got0);
+      mf->addAtom(*_got1);
+    }
+    for (auto &got : _gotVector) {
+      got->setOrdinal(ordinal++);
+      mf->addAtom(*got);
+    }
+    for (auto obj : _objectVector) {
+      obj->setOrdinal(ordinal++);
+      mf->addAtom(*obj);
+    }
+  }
+
+protected:
+  /// \brief Owner of all the Atoms created by this pass.
+  ELFPassFile _file;
+  const ELFLinkingContext &_ctx;
+
+  /// \brief Map Atoms to their GOT entries.
+  llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
+
+  /// \brief Map Atoms to their PLT entries.
+  llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
+
+  /// \brief Map Atoms to their Object entries.
+  llvm::DenseMap<const Atom *, ObjectAtom *> _objectMap;
+
+  /// \brief the list of GOT/PLT atoms
+  std::vector<GOTAtom *> _gotVector;
+  std::vector<PLTAtom *> _pltVector;
+  std::vector<ObjectAtom *> _objectVector;
+
+  /// \brief GOT entry that is always 0. Used for undefined weaks.
+  GOTAtom *_null;
+
+  /// \brief The got and plt entries for .PLT0. This is used to call into the
+  /// dynamic linker for symbol resolution.
+  /// @{
+  PLT0Atom *_PLT0;
+  GOTAtom *_got0;
+  GOTAtom *_got1;
+  /// @}
+};
+
+/// This implements the static relocation model. Meaning GOT and PLT entries are
+/// not created for references that can be directly resolved. These are
+/// converted to a direct relocation. For entries that do require a GOT or PLT
+/// entry, that entry is statically bound.
+///
+/// TLS always assumes module 1 and attempts to remove indirection.
+class AArch64StaticRelocationPass final
+    : public AArch64RelocationPass<AArch64StaticRelocationPass> {
+public:
+  AArch64StaticRelocationPass(const elf::AArch64LinkingContext &ctx)
+      : AArch64RelocationPass(ctx) {}
+
+  std::error_code handlePlain(const Reference &ref) { return handleIFUNC(ref); }
+
+  std::error_code handlePLT32(const Reference &ref) {
+    // __tls_get_addr is handled elsewhere.
+    if (ref.target() && ref.target()->name() == "__tls_get_addr") {
+      const_cast<Reference &>(ref).setKindValue(R_AARCH64_NONE);
+      return std::error_code();
+    }
+    // Static code doesn't need PLTs.
+    const_cast<Reference &>(ref).setKindValue(R_AARCH64_PREL32);
+    // Handle IFUNC.
+    if (const DefinedAtom *da =
+            dyn_cast_or_null<const DefinedAtom>(ref.target()))
+      if (da->contentType() == DefinedAtom::typeResolver)
+        return handleIFUNC(ref);
+    return std::error_code();
+  }
+
+  std::error_code handleGOT(const Reference &ref) {
+    if (isa<UndefinedAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getNullGOT());
+    else if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getGOT(da));
+    return std::error_code();
+  }
+};
+
+class AArch64DynamicRelocationPass final
+    : public AArch64RelocationPass<AArch64DynamicRelocationPass> {
+public:
+  AArch64DynamicRelocationPass(const elf::AArch64LinkingContext &ctx)
+      : AArch64RelocationPass(ctx) {}
+
+  const PLT0Atom *getPLT0() {
+    if (_PLT0)
+      return _PLT0;
+    // Fill in the null entry.
+    getNullGOT();
+    _PLT0 = new (_file._alloc) AArch64PLT0Atom(_file);
+    _got0 = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+    _got1 = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+    _PLT0->addReferenceELF_AArch64(R_AARCH64_ADR_GOT_PAGE, 4, _got0, 0);
+    _PLT0->addReferenceELF_AArch64(R_AARCH64_LD64_GOT_LO12_NC, 8, _got1, 0);
+    _PLT0->addReferenceELF_AArch64(ADD_AARCH64_GOTRELINDEX, 12, _got1, 0);
+#ifndef NDEBUG
+    _got0->_name = "__got0";
+    _got1->_name = "__got1";
+#endif
+    return _PLT0;
+  }
+
+  const PLTAtom *getPLTEntry(const Atom *a) {
+    auto plt = _pltMap.find(a);
+    if (plt != _pltMap.end())
+      return plt->second;
+    auto ga = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+    ga->addReferenceELF_AArch64(R_AARCH64_JUMP_SLOT, 0, a, 0);
+    auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
+    pa->addReferenceELF_AArch64(R_AARCH64_ADR_GOT_PAGE, 0, ga, 0);
+    pa->addReferenceELF_AArch64(R_AARCH64_LD64_GOT_LO12_NC, 4, ga, 0);
+    pa->addReferenceELF_AArch64(ADD_AARCH64_GOTRELINDEX, 8, ga, 0);
+    pa->addReferenceELF_AArch64(R_AARCH64_NONE, 12, getPLT0(), 0);
+    // Set the starting address of the got entry to the first instruction in
+    // the plt0 entry.
+    ga->addReferenceELF_AArch64(R_AARCH64_ABS32, 0, pa, 0);
+#ifndef NDEBUG
+    ga->_name = "__got_";
+    ga->_name += a->name();
+    pa->_name = "__plt_";
+    pa->_name += a->name();
+#endif
+    _gotMap[a] = ga;
+    _pltMap[a] = pa;
+    _gotVector.push_back(ga);
+    _pltVector.push_back(pa);
+    return pa;
+  }
+
+  const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a) {
+    auto obj = _objectMap.find(a);
+    if (obj != _objectMap.end())
+      return obj->second;
+
+    auto oa = new (_file._alloc) ObjectAtom(_file);
+    // This needs to point to the atom that we just created.
+    oa->addReferenceELF_AArch64(R_AARCH64_COPY, 0, oa, 0);
+
+    oa->_name = a->name();
+    oa->_size = a->size();
+
+    _objectMap[a] = oa;
+    _objectVector.push_back(oa);
+    return oa;
+  }
+
+  std::error_code handlePlain(const Reference &ref) {
+    if (!ref.target())
+      return std::error_code();
+    if (auto sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
+      if (sla->type() == SharedLibraryAtom::Type::Data)
+        const_cast<Reference &>(ref).setTarget(getObjectEntry(sla));
+      else if (sla->type() == SharedLibraryAtom::Type::Code)
+        const_cast<Reference &>(ref).setTarget(getPLTEntry(sla));
+    } else
+      return handleIFUNC(ref);
+    return std::error_code();
+  }
+
+  std::error_code handlePLT32(const Reference &ref) {
+    // Turn this into a PC32 to the PLT entry.
+    const_cast<Reference &>(ref).setKindValue(R_AARCH64_PREL32);
+    // Handle IFUNC.
+    if (const DefinedAtom *da =
+            dyn_cast_or_null<const DefinedAtom>(ref.target()))
+      if (da->contentType() == DefinedAtom::typeResolver)
+        return handleIFUNC(ref);
+    if (isa<const SharedLibraryAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target()));
+    return std::error_code();
+  }
+
+  const GOTAtom *getSharedGOT(const SharedLibraryAtom *sla) {
+    auto got = _gotMap.find(sla);
+    if (got == _gotMap.end()) {
+      auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got.dyn");
+      g->addReferenceELF_AArch64(R_AARCH64_GLOB_DAT, 0, sla, 0);
+#ifndef NDEBUG
+      g->_name = "__got_";
+      g->_name += sla->name();
+#endif
+      _gotMap[sla] = g;
+      _gotVector.push_back(g);
+      return g;
+    }
+    return got->second;
+  }
+
+  std::error_code handleGOT(const Reference &ref) {
+    if (isa<UndefinedAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getNullGOT());
+    else if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getGOT(da));
+    else if (const auto sla = dyn_cast<const SharedLibraryAtom>(ref.target()))
+      const_cast<Reference &>(ref).setTarget(getSharedGOT(sla));
+    return std::error_code();
+  }
+};
+} // end anon namespace
+
+std::unique_ptr<Pass>
+lld::elf::createAArch64RelocationPass(const AArch64LinkingContext &ctx) {
+  switch (ctx.getOutputELFType()) {
+  case llvm::ELF::ET_EXEC:
+    if (ctx.isDynamic())
+      return std::unique_ptr<Pass>(new AArch64DynamicRelocationPass(ctx));
+    else
+      return std::unique_ptr<Pass>(new AArch64StaticRelocationPass(ctx));
+  case llvm::ELF::ET_DYN:
+    return std::unique_ptr<Pass>(new AArch64DynamicRelocationPass(ctx));
+  case llvm::ELF::ET_REL:
+    return std::unique_ptr<Pass>();
+  default:
+    llvm_unreachable("Unhandled output file type");
+  }
+}

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,32 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h ---------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Declares the relocation processing pass for x86-64. This includes
+///   GOT and PLT entries, TLS, COPY, and ifunc.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_RELOCATION_PASS_H
+#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_RELOCATION_PASS_H
+
+#include <memory>
+
+namespace lld {
+class Pass;
+namespace elf {
+class AArch64LinkingContext;
+
+/// \brief Create AArch64 relocation pass for the given linking context.
+std::unique_ptr<Pass>
+createAArch64RelocationPass(const AArch64LinkingContext &);
+}
+}
+
+#endif

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,10 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64Target.h -----------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64LinkingContext.h"

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp Wed Aug 13 08:16:38 2014
@@ -0,0 +1,129 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp --------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Atoms.h"
+#include "AArch64ExecutableWriter.h"
+#include "AArch64DynamicLibraryWriter.h"
+#include "AArch64TargetHandler.h"
+#include "AArch64LinkingContext.h"
+
+using namespace lld;
+using namespace elf;
+
+AArch64TargetHandler::AArch64TargetHandler(AArch64LinkingContext &context)
+    : DefaultTargetHandler(context), _context(context),
+      _AArch64TargetLayout(new AArch64TargetLayout<AArch64ELFType>(context)),
+      _AArch64RelocationHandler(
+          new AArch64TargetRelocationHandler(*_AArch64TargetLayout.get())) {}
+
+void AArch64TargetHandler::registerRelocationNames(Registry &registry) {
+  registry.addKindTable(Reference::KindNamespace::ELF,
+                        Reference::KindArch::AArch64, kindStrings);
+}
+
+std::unique_ptr<Writer> AArch64TargetHandler::getWriter() {
+  switch (this->_context.getOutputELFType()) {
+  case llvm::ELF::ET_EXEC:
+    return std::unique_ptr<Writer>(new AArch64ExecutableWriter<AArch64ELFType>(
+        _context, *_AArch64TargetLayout.get()));
+  case llvm::ELF::ET_DYN:
+    return std::unique_ptr<Writer>(
+        new AArch64DynamicLibraryWriter<AArch64ELFType>(
+            _context, *_AArch64TargetLayout.get()));
+  case llvm::ELF::ET_REL:
+    llvm_unreachable("TODO: support -r mode");
+  default:
+    llvm_unreachable("unsupported output type");
+  }
+}
+
+const Registry::KindStrings AArch64TargetHandler::kindStrings[] = {
+    LLD_KIND_STRING_ENTRY(R_AARCH64_NONE),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_ABS64),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_ABS32),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_ABS16),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_PREL64),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_PREL32),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_PREL16),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G0),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G0_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G1),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G1_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G2),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G2_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G3),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_SABS_G0),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_SABS_G1),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_SABS_G2),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_LD_PREL_LO19),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_ADR_PREL_LO21),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_ADR_PREL_PG_HI21),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_ADD_ABS_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_LDST8_ABS_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TSTBR14),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_CONDBR19),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_JUMP26),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_CALL26),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_LDST16_ABS_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_LDST32_ABS_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_LDST64_ABS_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_LDST128_ABS_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_ADR_GOT_PAGE),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_LD64_GOT_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G2),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G1),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G0),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_ADD_DTPREL_HI12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_ADD_DTPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST8_DTPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST16_DTPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST32_DTPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST64_DTPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G2),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G1),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G0),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_ADD_TPREL_HI12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_ADD_TPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST8_TPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST16_TPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST32_TPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST64_TPREL_LO12),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC_ADR_PAGE),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC_LD64_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC_ADD_LO12_NC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC_CALL),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_COPY),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_GLOB_DAT),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_JUMP_SLOT),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_RELATIVE),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLS_DTPREL64),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLS_DTPMOD64),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLS_TPREL64),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC),
+    LLD_KIND_STRING_ENTRY(R_AARCH64_IRELATIVE),
+    LLD_KIND_STRING_END};

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,57 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h ----------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_TARGET_HANDLER_H
+#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_TARGET_HANDLER_H
+
+#include "DefaultTargetHandler.h"
+#include "ELFFile.h"
+#include "AArch64RelocationHandler.h"
+#include "TargetLayout.h"
+
+#include "lld/Core/Simple.h"
+
+namespace lld {
+namespace elf {
+typedef llvm::object::ELFType<llvm::support::little, 2, true> AArch64ELFType;
+class AArch64LinkingContext;
+
+template <class ELFT> class AArch64TargetLayout : public TargetLayout<ELFT> {
+public:
+  AArch64TargetLayout(AArch64LinkingContext &context)
+      : TargetLayout<ELFT>(context) {}
+};
+
+class AArch64TargetHandler final : public DefaultTargetHandler<AArch64ELFType> {
+public:
+  AArch64TargetHandler(AArch64LinkingContext &context);
+
+  AArch64TargetLayout<AArch64ELFType> &getTargetLayout() override {
+    return *(_AArch64TargetLayout.get());
+  }
+
+  void registerRelocationNames(Registry &registry) override;
+
+  const AArch64TargetRelocationHandler &getRelocationHandler() const override {
+    return *(_AArch64RelocationHandler.get());
+  }
+
+  std::unique_ptr<Writer> getWriter() override;
+
+private:
+  static const Registry::KindStrings kindStrings[];
+  AArch64LinkingContext &_context;
+  std::unique_ptr<AArch64TargetLayout<AArch64ELFType>> _AArch64TargetLayout;
+  std::unique_ptr<AArch64TargetRelocationHandler> _AArch64RelocationHandler;
+};
+
+} // end namespace elf
+} // end namespace lld
+
+#endif

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt Wed Aug 13 08:16:38 2014
@@ -0,0 +1,10 @@
+add_lld_library(lldAArch64ELFTarget
+  AArch64LinkingContext.cpp
+  AArch64TargetHandler.cpp
+  AArch64RelocationHandler.cpp
+  AArch64RelocationPass.cpp
+  )
+
+target_link_libraries(lldAArch64ELFTarget
+  lldCore
+  )

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile Wed Aug 13 08:16:38 2014
@@ -0,0 +1,15 @@
+##===- lld/lib/ReaderWriter/ELF/AArch64/Makefile ----------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLD_LEVEL := ../../../..
+LIBRARYNAME := lldAArch64ELFTarget
+USEDLIBS = lldCore.a
+CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF/AArch64 -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
+
+include $(LLD_LEVEL)/Makefile

Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst Wed Aug 13 08:16:38 2014
@@ -0,0 +1,15 @@
+ELF AArch64
+~~~~~~~~~~
+
+Unimplemented Features
+######################
+
+* Just about everything!
+
+Unimplemented Relocations
+#########################
+
+All of these relocations are defined in:
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
+
+

Modified: lld/trunk/lib/ReaderWriter/ELF/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Atoms.h?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Atoms.h Wed Aug 13 08:16:38 2014
@@ -679,6 +679,11 @@ public:
                             Reference::Addend a) {
     this->addReferenceELF(Reference::KindArch::Mips, relocType, off, t, a);
   }
+
+  void addReferenceELF_AArch64(uint16_t relocType, uint64_t off, const Atom *t,
+                               Reference::Addend a) {
+    this->addReferenceELF(Reference::KindArch::AArch64, relocType, off, t, a);
+  }
 };
 
 /// \brief Atom which represents an object for which a COPY relocation will be

Modified: lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt (original)
+++ lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt Wed Aug 13 08:16:38 2014
@@ -13,6 +13,7 @@ target_link_libraries(lldELF
   lldReaderWriter
   lldX86ELFTarget
   lldX86_64ELFTarget
+  lldAArch64ELFTarget
   )
 
 include_directories(.)

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFFile.h?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFFile.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFFile.h Wed Aug 13 08:16:38 2014
@@ -452,6 +452,8 @@ template <class ELFT> Reference::KindArc
     return Reference::KindArch::Hexagon;
   case llvm::ELF::EM_MIPS:
     return Reference::KindArch::Mips;
+  case llvm::ELF::EM_AARCH64:
+    return Reference::KindArch::AArch64;
   }
   llvm_unreachable("unsupported e_machine value");
 }

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp Wed Aug 13 08:16:38 2014
@@ -87,6 +87,8 @@ uint16_t ELFLinkingContext::getOutputMac
     return llvm::ELF::EM_MIPS;
   case llvm::Triple::ppc:
     return llvm::ELF::EM_PPC;
+  case llvm::Triple::aarch64:
+    return llvm::ELF::EM_AARCH64;
   default:
     llvm_unreachable("Unhandled arch");
   }
@@ -147,6 +149,9 @@ ELFLinkingContext::create(llvm::Triple t
   case llvm::Triple::ppc:
     return std::unique_ptr<ELFLinkingContext>(
         new lld::elf::PPCLinkingContext(triple));
+  case llvm::Triple::aarch64:
+    return std::unique_ptr<ELFLinkingContext>(
+        new lld::elf::AArch64LinkingContext(triple));
   default:
     return nullptr;
   }

Modified: lld/trunk/lib/ReaderWriter/ELF/Makefile
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Makefile?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Makefile (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Makefile Wed Aug 13 08:16:38 2014
@@ -10,12 +10,12 @@
 LLD_LEVEL := ../../..
 LIBRARYNAME := lldELF
 USEDLIBS = lldHexagonELFTarget.a lldPPCELFTarget.a lldMipsELFTarget.a \
-           lldX86ELFTarget.a lldX86_64ELFTarget.a \
+           lldX86ELFTarget.a lldX86_64ELFTarget.a lldAArch64ELFTarget.a \
            lldReaderWriter.a lldPasses.a
 
 CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
 
 # these link against this lib
-PARALLEL_DIRS := Hexagon PPC X86 X86_64 Mips
+PARALLEL_DIRS := Hexagon PPC X86 X86_64 Mips AArch64
 
 include $(LLD_LEVEL)/Makefile

Modified: lld/trunk/lib/ReaderWriter/ELF/Targets.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Targets.h?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Targets.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Targets.h Wed Aug 13 08:16:38 2014
@@ -15,5 +15,6 @@
 #include "PPC/PPCTarget.h"
 #include "X86/X86Target.h"
 #include "X86_64/X86_64Target.h"
+#include "AArch64/AArch64Target.h"
 
 #endif

Added: lld/trunk/test/elf/AArch64/Inputs/fn.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/fn.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/fn.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/fn.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1,4 @@
+int fn()
+{
+  return 0;
+}

Added: lld/trunk/test/elf/AArch64/Inputs/fn.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/fn.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/fn.o (added) and lld/trunk/test/elf/AArch64/Inputs/fn.o Wed Aug 13 08:16:38 2014 differ

Added: lld/trunk/test/elf/AArch64/Inputs/initfini-option.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/initfini-option.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/initfini-option.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/initfini-option.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void init() {
+ printf("%s\n", __FUNCTION__);
+}
+
+void fini() {
+ printf("%s\n", __FUNCTION__);
+}
+
+int main() {
+}

Added: lld/trunk/test/elf/AArch64/Inputs/initfini-option.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/initfini-option.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/initfini-option.o (added) and lld/trunk/test/elf/AArch64/Inputs/initfini-option.o Wed Aug 13 08:16:38 2014 differ

Added: lld/trunk/test/elf/AArch64/Inputs/initfini.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/initfini.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/initfini.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/initfini.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+void  __attribute__ ((constructor)) constructor() {
+ printf("%s\n", __FUNCTION__);
+}
+
+void __attribute__ ((destructor)) destructor() {
+ printf("%s\n", __FUNCTION__);
+}
+
+int main() {
+  return 0;
+}

Added: lld/trunk/test/elf/AArch64/Inputs/initfini.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/initfini.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/initfini.o (added) and lld/trunk/test/elf/AArch64/Inputs/initfini.o Wed Aug 13 08:16:38 2014 differ

Added: lld/trunk/test/elf/AArch64/Inputs/main.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/main.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/main.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/main.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1,4 @@
+int main() {
+  fn();
+  return 0;
+}

Added: lld/trunk/test/elf/AArch64/Inputs/main.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/main.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/main.o (added) and lld/trunk/test/elf/AArch64/Inputs/main.o Wed Aug 13 08:16:38 2014 differ

Added: lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1 @@
+int c = 10;

Added: lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o (added) and lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o Wed Aug 13 08:16:38 2014 differ

Added: lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o (added) and lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o Wed Aug 13 08:16:38 2014 differ

Added: lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s (added)
+++ lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s Wed Aug 13 08:16:38 2014
@@ -0,0 +1,3 @@
+.text
+.data
+.word .text

Added: lld/trunk/test/elf/AArch64/defsym.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/defsym.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/defsym.test (added)
+++ lld/trunk/test/elf/AArch64/defsym.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,22 @@
+RUN: lld -flavor gnu -target aarch64--linux-gnu --defsym=main=fn \
+RUN: --noinhibit-exec %p/Inputs/fn.o -o %t
+RUN: llvm-readobj -symbols %t | FileCheck %s
+
+CHECK: Symbol {
+CHECK:   Name: main (1)
+CHECK:   Value: 0x4001A4
+CHECK:   Size: 0
+CHECK:   Binding: Global (0x1)
+CHECK:   Type: Function (0x2)
+CHECK:   Other: 0
+CHECK:   Section: .text (0x5)
+CHECK: }
+CHECK: Symbol {
+CHECK:   Name: fn (6)
+CHECK:   Value: 0x4001A4
+CHECK:   Size: 8
+CHECK:   Binding: Global (0x1)
+CHECK:   Type: Function (0x2)
+CHECK:   Other: 0
+CHECK:   Section: .text (0x5)
+CHECK: }

Added: lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test (added)
+++ lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,9 @@
+# This tests that lld is not ignoring zero sized sections
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/zerosizedsection.o  \
+RUN: --noinhibit-exec --output-filetype=yaml -o %t
+RUN: FileCheck %s < %t
+
+CHECK:    references:
+CHECK:      - kind:            layout-after
+CHECK:        offset:          0
+CHECK:        target:          L000

Added: lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test (added)
+++ lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,5 @@
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/no-interp-section.o \
+RUN:  -o %t -shared
+RUN: llvm-objdump -section-headers %t | FileCheck %s
+
+CHECK-NOT: .interp

Added: lld/trunk/test/elf/AArch64/initfini-alignment.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/initfini-alignment.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/initfini-alignment.test (added)
+++ lld/trunk/test/elf/AArch64/initfini-alignment.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,12 @@
+# This tests the functionality that lld is able to create
+# init_array/fini_array sections in the output ELF with the
+# right alignment
+
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/initfini-option.o  \
+RUN: -init init -fini fini --noinhibit-exec -o %t
+RUN: llvm-readobj -s %t | FileCheck %s
+
+CHECK:    Name: .init_array
+CHECK:    AddressAlignment: 8
+CHECK:    Name: .fini_array
+CHECK:    AddressAlignment: 8

Added: lld/trunk/test/elf/AArch64/initfini-option.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/initfini-option.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/initfini-option.test (added)
+++ lld/trunk/test/elf/AArch64/initfini-option.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,21 @@
+# This tests the functionality that lld is able to create
+# init_array/fini_array sections in the output ELF. This
+# corresponds to the the .init_array/.fini_array sections
+# in the output ELF.
+
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/initfini-option.o  \
+RUN: -init init -fini fini --noinhibit-exec --output-filetype=yaml -static -o %t
+RUN: FileCheck %s < %t
+
+CHECK:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECK:    section-name:    .init_array
+CHECK:    references:
+CHECK:      - kind:            R_AARCH64_ABS64
+CHECK:        offset:          0
+CHECK:        target:          init
+CHECK:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECK:    section-name:    .fini_array
+CHECK:    references:
+CHECK:      - kind:            R_AARCH64_ABS64
+CHECK:        offset:          0
+CHECK:        target:          fini

Added: lld/trunk/test/elf/AArch64/initfini.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/initfini.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/initfini.test (added)
+++ lld/trunk/test/elf/AArch64/initfini.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,23 @@
+# This tests the functionality that lld is able to read
+# init_array/fini_array sections in the input ELF. This
+# corresponds to the the .init_array/.fini_array sections
+# in the output ELF.
+
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/initfini.o  \
+RUN: --noinhibit-exec --output-filetype=yaml -o %t
+RUN: FileCheck %s < %t
+
+CHECK:    type:            data
+CHECK:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECK:    section-name:    .init_array
+CHECK:    references:
+CHECK:      - kind:            R_AARCH64_ABS64
+CHECK:        offset:          0
+CHECK:        target:          constructor
+CHECK:    type:            data
+CHECK:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECK:    section-name:    .fini_array
+CHECK:    references:
+CHECK:      - kind:            R_AARCH64_ABS64
+CHECK:        offset:          0
+CHECK:        target:          destructor

Modified: lld/trunk/tools/lld/Makefile
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld/Makefile?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/tools/lld/Makefile (original)
+++ lld/trunk/tools/lld/Makefile Wed Aug 13 08:16:38 2014
@@ -23,6 +23,7 @@ USEDLIBS = lldDriver.a \
            lldELF.a lldMachO.a lldPasses.a lldPECOFF.a lldYAML.a \
            lldReaderWriter.a lldCore.a lldNative.a \
            lldHexagonELFTarget.a lldPPCELFTarget.a lldMipsELFTarget.a \
-           lldX86ELFTarget.a lldX86_64ELFTarget.a LLVMOption.a
+           lldX86ELFTarget.a lldX86_64ELFTarget.a lldAArch64ELFTarget.a \
+           LLVMOption.a
 
 include $(LLD_LEVEL)/Makefile

Modified: lld/trunk/unittests/DriverTests/Makefile
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/Makefile?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/Makefile (original)
+++ lld/trunk/unittests/DriverTests/Makefile Wed Aug 13 08:16:38 2014
@@ -15,5 +15,5 @@ USEDLIBS = lldDriver.a \
            lldHexagonELFTarget.a lldPPCELFTarget.a lldMipsELFTarget.a \
            lldX86ELFTarget.a lldX86_64ELFTarget.a lldYAML.a \
            LLVMObject.a LLVMMCParser.a LLVMMC.a LLVMBitReader.a \
-           LLVMCore.a LLVMOption.a LLVMSupport.a
+           LLVMCore.a LLVMOption.a LLVMSupport.a lldAArch64ELFTarget.a
 include $(LLD_LEVEL)/unittests/Makefile





More information about the llvm-commits mailing list