[lld] r217469 - [mach-o] Add support for arm64 (AAarch64)

Nick Kledzik kledzik at apple.com
Tue Sep 9 16:53:00 PDT 2014


Author: kledzik
Date: Tue Sep  9 18:52:59 2014
New Revision: 217469

URL: http://llvm.org/viewvc/llvm-project?rev=217469&view=rev
Log:
[mach-o] Add support for arm64 (AAarch64)

Most of the changes are in the new file ArchHandler_arm64.cpp.  But a few
things had to be fixed to support 16KB pages (instead of 4KB) which iOS arm64
requires.  In addition the StubInfo struct had to be expanded because
arm64 uses two instruction (ADRP/LDR) to load a global which requires two
relocations.  The other mach-o arches just needed one relocation.

Added:
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
    lld/trunk/test/mach-o/hello-world-arm64.yaml
    lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml
    lld/trunk/test/mach-o/parse-text-relocs-arm64.yaml
Modified:
    lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
    lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
    lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp

Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Tue Sep  9 18:52:59 2014
@@ -43,6 +43,7 @@ public:
     arch_armv6,
     arch_armv7,
     arch_armv7s,
+    arch_arm64,
   };
 
   enum class OS {

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp Tue Sep  9 18:52:59 2014
@@ -42,6 +42,8 @@ std::unique_ptr<mach_o::ArchHandler> Arc
   case MachOLinkingContext::arch_armv7:
   case MachOLinkingContext::arch_armv7s:
     return create_arm();
+  case MachOLinkingContext::arch_arm64:
+    return create_arm64();
   default:
     llvm_unreachable("Unknown arch");
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h Tue Sep  9 18:52:59 2014
@@ -174,6 +174,13 @@ public:
     int32_t             addend;
   };
 
+  struct OptionalRefInfo {
+    bool                used;
+    uint16_t            kind;
+    uint32_t            offset;
+    int32_t             addend;
+  };
+
   /// Table of architecture specific information for creating stubs.
   struct StubInfo {
     const char*     binderSymbolName;
@@ -185,16 +192,19 @@ public:
     uint32_t        stubSize;
     uint8_t         stubBytes[16];
     ReferenceInfo   stubReferenceToLP;
-    
+    OptionalRefInfo optStubReferenceToLP;
+
     uint32_t        stubHelperSize;
     uint8_t         stubHelperBytes[16];
     ReferenceInfo   stubHelperReferenceToImm;
     ReferenceInfo   stubHelperReferenceToHelperCommon;
-    
+
     uint32_t        stubHelperCommonSize;
     uint8_t         stubHelperCommonBytes[36];
     ReferenceInfo   stubHelperCommonReferenceToCache;
+    OptionalRefInfo optStubHelperCommonReferenceToCache;
     ReferenceInfo   stubHelperCommonReferenceToBinder;
+    OptionalRefInfo optStubHelperCommonReferenceToBinder;
   };
 
   virtual const StubInfo &stubInfo() = 0;
@@ -205,6 +215,7 @@ protected:
   static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
   static std::unique_ptr<mach_o::ArchHandler> create_x86();
   static std::unique_ptr<mach_o::ArchHandler> create_arm();
+  static std::unique_ptr<mach_o::ArchHandler> create_arm64();
 
   // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
   typedef uint16_t RelocPattern;

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Tue Sep  9 18:52:59 2014
@@ -208,6 +208,7 @@ const ArchHandler::StubInfo ArchHandler_
     0x00, 0xF0, 0x9C, 0xE5,       // 	ldr pc, [ip]
     0x00, 0x00, 0x00, 0x00 },     // 	.long L_foo$lazy_ptr - (L1$scv + 8)
   { Reference::KindArch::ARM, delta32, 12, 0 },
+  { false, 0, 0, 0 },
   
   // Stub Helper size and code
   12,
@@ -232,7 +233,9 @@ const ArchHandler::StubInfo ArchHandler_
     0x00, 0x00, 0x00, 0x00,       // L1: .long fFastStubGOTAtom - (helper+16)
     0x00, 0x00, 0x00, 0x00 },     // L2: .long dyld_stub_binder - (helper+28)
   { Reference::KindArch::ARM, delta32, 28, 0xC },
-  { Reference::KindArch::ARM, delta32, 32, 0x04 }
+  { false, 0, 0, 0 },
+  { Reference::KindArch::ARM, delta32, 32, 0x04 },
+  { false, 0, 0, 0 }
 };
 
 const ArchHandler::StubInfo &ArchHandler_arm::stubInfo() {

Added: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp?rev=217469&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp Tue Sep  9 18:52:59 2014
@@ -0,0 +1,727 @@
+//===- lib/FileFormat/MachO/ArchHandler_arm64.cpp -------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ArchHandler.h"
+#include "Atoms.h"
+#include "MachONormalizedFileBinaryUtils.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm::MachO;
+using namespace lld::mach_o::normalized;
+
+namespace lld {
+namespace mach_o {
+
+class ArchHandler_arm64 : public ArchHandler {
+public:
+  ArchHandler_arm64();
+  virtual ~ArchHandler_arm64();
+
+  const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
+
+  Reference::KindArch kindArch() override {
+    return Reference::KindArch::AArch64;
+  }
+
+  /// Used by GOTPass to locate GOT References
+  bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override {
+    if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+      return false;
+    assert(ref.kindArch() == Reference::KindArch::AArch64);
+    switch (ref.kindValue()) {
+    case gotPage21:
+    case gotOffset12:
+      canBypassGOT = true;
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  /// Used by GOTPass to update GOT References.
+  void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override {
+    // If GOT slot was instanciated, transform:
+    //   gotPage21/gotOffset12 -> page21/offset12scale8
+    // If GOT slot optimized away, transform:
+    //   gotPage21/gotOffset12 -> page21/addOffset12
+    assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
+    assert(ref->kindArch() == Reference::KindArch::AArch64);
+    switch (ref->kindValue()) {
+    case gotPage21:
+      const_cast<Reference *>(ref)->setKindValue(page21);
+      break;
+    case gotOffset12:
+      const_cast<Reference *>(ref)->setKindValue(targetNowGOT ?
+                                                 offset12scale8 : addOffset12);
+      break;
+    default:
+      llvm_unreachable("Not a GOT reference");
+    }
+  }
+
+  const StubInfo &stubInfo() override { return _sStubInfo; }
+
+  bool isCallSite(const Reference &) override;
+  bool isPointer(const Reference &) override;
+  bool isPairedReloc(const normalized::Relocation &) override;
+  std::error_code getReferenceInfo(const normalized::Relocation &reloc,
+                                   const DefinedAtom *inAtom,
+                                   uint32_t offsetInAtom,
+                                   uint64_t fixupAddress, bool swap,
+                                   FindAtomBySectionAndAddress atomFromAddress,
+                                   FindAtomBySymbolIndex atomFromSymbolIndex,
+                                   Reference::KindValue *kind,
+                                   const lld::Atom **target,
+                                   Reference::Addend *addend) override;
+  std::error_code
+      getPairReferenceInfo(const normalized::Relocation &reloc1,
+                           const normalized::Relocation &reloc2,
+                           const DefinedAtom *inAtom,
+                           uint32_t offsetInAtom,
+                           uint64_t fixupAddress, bool swap,
+                           FindAtomBySectionAndAddress atomFromAddress,
+                           FindAtomBySymbolIndex atomFromSymbolIndex,
+                           Reference::KindValue *kind,
+                           const lld::Atom **target,
+                           Reference::Addend *addend) override;
+
+  virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
+    return (atom->contentType() == DefinedAtom::typeCString);
+  }
+
+  void generateAtomContent(const DefinedAtom &atom, bool relocatable,
+                           FindAddressForAtom findAddress,
+                           uint8_t *atomContentBuffer) override;
+
+  void appendSectionRelocations(const DefinedAtom &atom,
+                                uint64_t atomSectionOffset,
+                                const Reference &ref,
+                                FindSymbolIndexForAtom symbolIndexForAtom,
+                                FindSectionIndexForAtom sectionIndexForAtom,
+                                FindAddressForAtom addressForAtom,
+                                normalized::Relocations &relocs) override;
+
+private:
+  static const Registry::KindStrings _sKindStrings[];
+  static const StubInfo _sStubInfo;
+
+  enum Arm64_Kinds : Reference::KindValue {
+    invalid,               /// for error condition
+
+    // Kinds found in mach-o .o files:
+    branch26,              /// ex: bl   _foo
+    page21,                /// ex: adrp x1, _foo at PAGE
+    offset12,              /// ex: ldrb w0, [x1, _foo at PAGEOFF]
+    offset12scale2,        /// ex: ldrs w0, [x1, _foo at PAGEOFF]
+    offset12scale4,        /// ex: ldr  w0, [x1, _foo at PAGEOFF]
+    offset12scale8,        /// ex: ldr  x0, [x1, _foo at PAGEOFF]
+    offset12scale16,       /// ex: ldr  q0, [x1, _foo at PAGEOFF]
+    gotPage21,             /// ex: adrp x1, _foo at GOTPAGE
+    gotOffset12,           /// ex: ldr  w0, [x1, _foo at GOTPAGEOFF]
+    tlvPage21,             /// ex: adrp x1, _foo at TLVPAGE
+    tlvOffset12,           /// ex: ldr  w0, [x1, _foo at TLVPAGEOFF]
+
+    pointer64,             /// ex: .quad _foo
+    delta64,               /// ex: .quad _foo - .
+    delta32,               /// ex: .long _foo - .
+    pointer64ToGOT,        /// ex: .quad _foo at GOT
+    delta32ToGOT,          /// ex: .long _foo at GOT - .
+
+    // Kinds introduced by Passes:
+    addOffset12,           /// Location contains LDR to change into ADD.
+    lazyPointer,           /// Location contains a lazy pointer.
+    lazyImmediateLocation, /// Location contains immediate value used in stub.
+  };
+
+  void applyFixupFinal(const Reference &ref, uint8_t *location,
+                       uint64_t fixupAddress, uint64_t targetAddress,
+                       uint64_t inAtomAddress);
+
+  void applyFixupRelocatable(const Reference &ref, uint8_t *location,
+                             uint64_t fixupAddress, uint64_t targetAddress,
+                             uint64_t inAtomAddress);
+
+  // Utility functions for inspecting/updating instructions.
+  static uint32_t setDisplacementInBranch26(uint32_t instr, int32_t disp);
+  static uint32_t setDisplacementInADRP(uint32_t instr, int64_t disp);
+  static Arm64_Kinds offset12KindFromInstruction(uint32_t instr);
+  static uint32_t setImm12(uint32_t instr, uint32_t offset);
+
+  const bool _swap;
+};
+
+ArchHandler_arm64::ArchHandler_arm64()
+  : _swap(!MachOLinkingContext::isHostEndian(MachOLinkingContext::arch_arm64)) {
+}
+
+ArchHandler_arm64::~ArchHandler_arm64() {}
+
+const Registry::KindStrings ArchHandler_arm64::_sKindStrings[] = {
+  LLD_KIND_STRING_ENTRY(invalid),
+  LLD_KIND_STRING_ENTRY(branch26),
+  LLD_KIND_STRING_ENTRY(page21),
+  LLD_KIND_STRING_ENTRY(offset12),
+  LLD_KIND_STRING_ENTRY(offset12scale2),
+  LLD_KIND_STRING_ENTRY(offset12scale4),
+  LLD_KIND_STRING_ENTRY(offset12scale8),
+  LLD_KIND_STRING_ENTRY(offset12scale16),
+  LLD_KIND_STRING_ENTRY(gotPage21),
+  LLD_KIND_STRING_ENTRY(gotOffset12),
+  LLD_KIND_STRING_ENTRY(tlvPage21),
+  LLD_KIND_STRING_ENTRY(tlvOffset12),
+  LLD_KIND_STRING_ENTRY(pointer64),
+  LLD_KIND_STRING_ENTRY(delta64),
+  LLD_KIND_STRING_ENTRY(delta32),
+  LLD_KIND_STRING_ENTRY(pointer64ToGOT),
+  LLD_KIND_STRING_ENTRY(delta32ToGOT),
+
+  LLD_KIND_STRING_ENTRY(addOffset12),
+  LLD_KIND_STRING_ENTRY(lazyPointer),
+  LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
+  LLD_KIND_STRING_ENTRY(pointer64),
+
+  LLD_KIND_STRING_END
+};
+
+const ArchHandler::StubInfo ArchHandler_arm64::_sStubInfo = {
+  "dyld_stub_binder",
+
+  // Lazy pointer references
+  { Reference::KindArch::AArch64, pointer64, 0, 0 },
+  { Reference::KindArch::AArch64, lazyPointer, 0, 0 },
+
+  // GOT pointer to dyld_stub_binder
+  { Reference::KindArch::AArch64, pointer64, 0, 0 },
+
+  // arm64 code alignment 2^2
+  2,
+
+  // Stub size and code
+  12,
+  { 0x10, 0x00, 0x00, 0x90,   // ADRP  X16, lazy_pointer at page
+    0x10, 0x02, 0x40, 0xF9,   // LDR   X16, [X16, lazy_pointer at pageoff]
+    0x00, 0x02, 0x1F, 0xD6 }, // BR    X16
+  { Reference::KindArch::AArch64, page21, 0, 0 },
+  { true,                         offset12scale8, 4, 0 },
+
+  // Stub Helper size and code
+  12,
+  { 0x50, 0x00, 0x00, 0x18,   //      LDR   W16, L0
+    0x00, 0x00, 0x00, 0x14,   //      LDR   B  helperhelper
+    0x00, 0x00, 0x00, 0x00 }, // L0: .long 0
+  { Reference::KindArch::AArch64, lazyImmediateLocation, 8, 0 },
+  { Reference::KindArch::AArch64, branch26, 4, 0 },
+
+  // Stub Helper-Common size and code
+  24,
+  { 0x11, 0x00, 0x00, 0x90,   //  ADRP  X17, dyld_ImageLoaderCache at page
+    0x31, 0x02, 0x00, 0x91,   //  ADD   X17, X17, dyld_ImageLoaderCache at pageoff
+    0xF0, 0x47, 0xBF, 0xA9,   //  STP   X16/X17, [SP, #-16]!
+    0x10, 0x00, 0x00, 0x90,   //  ADRP  X16, _fast_lazy_bind at page
+    0x10, 0x02, 0x40, 0xF9,   //  LDR   X16, [X16,_fast_lazy_bind at pageoff]
+    0x00, 0x02, 0x1F, 0xD6 }, //  BR    X16
+  { Reference::KindArch::AArch64, page21,   0, 0 },
+  { true,                         offset12, 4, 0 },
+  { Reference::KindArch::AArch64, page21,   12, 0 },
+  { true,                         offset12scale8, 16, 0 }
+};
+
+bool ArchHandler_arm64::isCallSite(const Reference &ref) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return false;
+  assert(ref.kindArch() == Reference::KindArch::AArch64);
+  return (ref.kindValue() == branch26);
+}
+
+bool ArchHandler_arm64::isPointer(const Reference &ref) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return false;
+  assert(ref.kindArch() == Reference::KindArch::AArch64);
+  Reference::KindValue kind = ref.kindValue();
+  return (kind == pointer64);
+}
+
+bool ArchHandler_arm64::isPairedReloc(const Relocation &r) {
+  return ((r.type == ARM64_RELOC_ADDEND) || (r.type == ARM64_RELOC_SUBTRACTOR));
+}
+
+uint32_t ArchHandler_arm64::setDisplacementInBranch26(uint32_t instr,
+                                                      int32_t displacement) {
+  assert((displacement <= 134217727) && (displacement > (-134217728)) &&
+         "arm64 branch out of range");
+  return (instr & 0xFC000000) | ((uint32_t)(displacement >> 2) & 0x03FFFFFF);
+}
+
+uint32_t ArchHandler_arm64::setDisplacementInADRP(uint32_t instruction,
+                                                  int64_t displacement) {
+  assert((displacement <= 0x100000000LL) && (displacement > (-0x100000000LL)) &&
+         "arm64 ADRP out of range");
+  assert(((instruction & 0x9F000000) == 0x90000000) &&
+         "reloc not on ADRP instruction");
+  uint32_t immhi = (displacement >> 9) & (0x00FFFFE0);
+  uint32_t immlo = (displacement << 17) & (0x60000000);
+  return (instruction & 0x9F00001F) | immlo | immhi;
+}
+
+ArchHandler_arm64::Arm64_Kinds
+ArchHandler_arm64::offset12KindFromInstruction(uint32_t instruction) {
+  if (instruction & 0x08000000) {
+    switch ((instruction >> 30) & 0x3) {
+    case 0:
+      if ((instruction & 0x04800000) == 0x04800000)
+        return offset12scale16;
+      return offset12;
+    case 1:
+      return offset12scale2;
+    case 2:
+      return offset12scale4;
+    case 3:
+      return offset12scale8;
+    }
+  }
+  return offset12;
+}
+
+uint32_t ArchHandler_arm64::setImm12(uint32_t instruction, uint32_t offset) {
+  assert(((offset & 0xFFFFF000) == 0) && "imm12 offset out of range");
+  uint32_t imm12 = offset << 10;
+  return (instruction & 0xFFC003FF) | imm12;
+}
+
+std::error_code ArchHandler_arm64::getReferenceInfo(
+    const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom,
+    uint64_t fixupAddress, bool swap,
+    FindAtomBySectionAndAddress atomFromAddress,
+    FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
+    const lld::Atom **target, Reference::Addend *addend) {
+  typedef std::error_code E;
+  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
+  switch (relocPattern(reloc)) {
+  case ARM64_RELOC_BRANCH26           | rPcRel | rExtern | rLength4:
+    // ex: bl _foo
+    *kind = branch26;
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  case ARM64_RELOC_PAGE21             | rPcRel | rExtern | rLength4:
+    // ex: adrp x1, _foo at PAGE
+    *kind = page21;
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  case ARM64_RELOC_PAGEOFF12                   | rExtern | rLength4:
+    // ex: ldr x0, [x1, _foo at PAGEOFF]
+    *kind = offset12KindFromInstruction(readS32(swap, fixupContent));
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  case ARM64_RELOC_GOT_LOAD_PAGE21    | rPcRel | rExtern | rLength4:
+    // ex: adrp x1, _foo at GOTPAGE
+    *kind = gotPage21;
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  case ARM64_RELOC_GOT_LOAD_PAGEOFF12          | rExtern | rLength4:
+    // ex: ldr x0, [x1, _foo at GOTPAGEOFF]
+    *kind = gotOffset12;
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  case ARM64_RELOC_TLVP_LOAD_PAGE21   | rPcRel | rExtern | rLength4:
+    // ex: adrp x1, _foo at TLVPAGE
+    *kind = tlvPage21;
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  case ARM64_RELOC_TLVP_LOAD_PAGEOFF12         | rExtern | rLength4:
+    // ex: ldr x0, [x1, _foo at TLVPAGEOFF]
+    *kind = tlvOffset12;
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  case X86_64_RELOC_UNSIGNED                   | rExtern | rLength8:
+    // ex: .quad _foo + N
+    *kind = pointer64;
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = readS64(swap, fixupContent);
+    return std::error_code();
+  case ARM64_RELOC_POINTER_TO_GOT              | rExtern | rLength8:
+    // ex: .quad _foo at GOT
+    *kind = pointer64ToGOT;
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  case ARM64_RELOC_POINTER_TO_GOT     | rPcRel | rExtern | rLength4:
+    // ex: .long _foo at GOT - .
+    *kind = delta32ToGOT;
+    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  default:
+    return make_dynamic_error_code(Twine("unsupported arm relocation type"));
+  }
+}
+
+std::error_code ArchHandler_arm64::getPairReferenceInfo(
+    const normalized::Relocation &reloc1, const normalized::Relocation &reloc2,
+    const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress,
+    bool swap, FindAtomBySectionAndAddress atomFromAddress,
+    FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
+    const lld::Atom **target, Reference::Addend *addend) {
+  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
+  const uint32_t *cont32 = reinterpret_cast<const uint32_t *>(fixupContent);
+  switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
+  case ((ARM64_RELOC_ADDEND                                | rLength4) << 16 |
+         ARM64_RELOC_BRANCH26           | rPcRel | rExtern | rLength4):
+    // ex: bl _foo+8
+    *kind = branch26;
+    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
+      return ec;
+    *addend = reloc1.symbol;
+    return std::error_code();
+  case ((ARM64_RELOC_ADDEND                                | rLength4) << 16 |
+         ARM64_RELOC_PAGE21             | rPcRel | rExtern | rLength4):
+    // ex: adrp x1, _foo at PAGE
+    *kind = page21;
+    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
+      return ec;
+    *addend = reloc1.symbol;
+    return std::error_code();
+  case ((ARM64_RELOC_ADDEND                                | rLength4) << 16 |
+         ARM64_RELOC_PAGEOFF12                   | rExtern | rLength4):
+    // ex: ldr w0, [x1, _foo at PAGEOFF]
+    *kind = offset12KindFromInstruction(*cont32);
+    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
+      return ec;
+    *addend = reloc1.symbol;
+    return std::error_code();
+  case ((ARM64_RELOC_SUBTRACTOR                  | rExtern | rLength8) << 16 |
+         ARM64_RELOC_UNSIGNED                    | rExtern | rLength8):
+    // ex: .quad _foo - .
+    *kind = delta64;
+    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
+      return ec;
+    *addend = readS64(swap, fixupContent) + offsetInAtom;
+    return std::error_code();
+  case ((ARM64_RELOC_SUBTRACTOR                  | rExtern | rLength4) << 16 |
+         ARM64_RELOC_UNSIGNED                    | rExtern | rLength4):
+    // ex: .quad _foo - .
+    *kind = delta32;
+    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
+      return ec;
+    *addend = readS32(swap, fixupContent) + offsetInAtom;
+    return std::error_code();
+  default:
+    return make_dynamic_error_code(Twine("unsupported arm64 relocation pair"));
+  }
+}
+
+void ArchHandler_arm64::generateAtomContent(const DefinedAtom &atom,
+                                            bool relocatable,
+                                            FindAddressForAtom findAddress,
+                                            uint8_t *atomContentBuffer) {
+  // Copy raw bytes.
+  memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
+  // Apply fix-ups.
+  for (const Reference *ref : atom) {
+    uint32_t offset = ref->offsetInAtom();
+    const Atom *target = ref->target();
+    uint64_t targetAddress = 0;
+    if (isa<DefinedAtom>(target))
+      targetAddress = findAddress(*target);
+    uint64_t atomAddress = findAddress(atom);
+    uint64_t fixupAddress = atomAddress + offset;
+    if (relocatable) {
+      applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
+                            targetAddress, atomAddress);
+    } else {
+      applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
+                      targetAddress, atomAddress);
+    }
+  }
+}
+
+void ArchHandler_arm64::applyFixupFinal(const Reference &ref, uint8_t *location,
+                                        uint64_t fixupAddress,
+                                        uint64_t targetAddress,
+                                        uint64_t inAtomAddress) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return;
+  assert(ref.kindArch() == Reference::KindArch::AArch64);
+  int32_t *loc32 = reinterpret_cast<int32_t *>(location);
+  uint64_t *loc64 = reinterpret_cast<uint64_t *>(location);
+  int32_t displacement;
+  uint32_t instruction;
+  uint32_t value32;
+  switch (static_cast<Arm64_Kinds>(ref.kindValue())) {
+  case branch26:
+    displacement = (targetAddress - fixupAddress) + ref.addend();
+    value32 = setDisplacementInBranch26(*loc32, displacement);
+    write32(*loc32, _swap, value32);
+    return;
+  case page21:
+  case gotPage21:
+  case tlvPage21:
+    displacement =
+        ((targetAddress + ref.addend()) & (-4096)) - (fixupAddress & (-4096));
+    value32 = setDisplacementInADRP(*loc32, displacement);
+    write32(*loc32, _swap, value32);
+    return;
+  case offset12:
+  case gotOffset12:
+  case tlvOffset12:
+    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
+    value32 = setImm12(*loc32, displacement);
+    write32(*loc32, _swap, value32);
+    return;
+  case offset12scale2:
+    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
+    assert(((displacement & 0x1) == 0) &&
+           "scaled imm12 not accessing 2-byte aligneds");
+    value32 = setImm12(*loc32, displacement >> 1);
+    write32(*loc32, _swap, value32);
+    return;
+  case offset12scale4:
+    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
+    assert(((displacement & 0x3) == 0) &&
+           "scaled imm12 not accessing 4-byte aligned");
+    value32 = setImm12(*loc32, displacement >> 2);
+    write32(*loc32, _swap, value32);
+    return;
+  case offset12scale8:
+    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
+    assert(((displacement & 0x7) == 0) &&
+           "scaled imm12 not accessing 8-byte aligned");
+    value32 = setImm12(*loc32, displacement >> 3);
+    write32(*loc32, _swap, value32);
+    return;
+  case offset12scale16:
+    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
+    assert(((displacement & 0xF) == 0) &&
+           "scaled imm12 not accessing 16-byte aligned");
+    value32 = setImm12(*loc32, displacement >> 4);
+    write32(*loc32, _swap, value32);
+    return;
+  case addOffset12:
+    instruction = read32(_swap, *loc32);
+    assert(((instruction & 0xFFC00000) == 0xF9400000) &&
+           "GOT reloc is not an LDR instruction");
+    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
+    value32 = 0x91000000 | (instruction & 0x000003FF);
+    instruction = setImm12(value32, displacement);
+    write32(*loc32, _swap, instruction);
+    return;
+  case pointer64:
+  case pointer64ToGOT:
+    write64(*loc64, _swap, targetAddress + ref.addend());
+    return;
+  case delta64:
+    write64(*loc64, _swap, (targetAddress - fixupAddress) + ref.addend());
+    return;
+  case delta32:
+  case delta32ToGOT:
+    write32(*loc32, _swap, (targetAddress - fixupAddress) + ref.addend());
+    return;
+  case lazyPointer:
+  case lazyImmediateLocation:
+    // Do nothing
+    return;
+  case invalid:
+    // Fall into llvm_unreachable().
+    break;
+  }
+  llvm_unreachable("invalid arm64 Reference Kind");
+}
+
+void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
+                                              uint8_t *location,
+                                              uint64_t fixupAddress,
+                                              uint64_t targetAddress,
+                                              uint64_t inAtomAddress) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return;
+  assert(ref.kindArch() == Reference::KindArch::AArch64);
+  int32_t *loc32 = reinterpret_cast<int32_t *>(location);
+  uint64_t *loc64 = reinterpret_cast<uint64_t *>(location);
+  uint32_t value32;
+  switch (static_cast<Arm64_Kinds>(ref.kindValue())) {
+  case branch26:
+    value32 = setDisplacementInBranch26(*loc32, 0);
+    write32(*loc32, _swap, value32);
+    return;
+  case page21:
+  case gotPage21:
+  case tlvPage21:
+    value32 = setDisplacementInADRP(*loc32, 0);
+    write32(*loc32, _swap, value32);
+    return;
+  case offset12:
+  case offset12scale2:
+  case offset12scale4:
+  case offset12scale8:
+  case offset12scale16:
+  case gotOffset12:
+  case tlvOffset12:
+    value32 = setImm12(*loc32, 0);
+    write32(*loc32, _swap, value32);
+    return;
+  case pointer64:
+    write64(*loc64, _swap, ref.addend());
+    return;
+  case delta64:
+    write64(*loc64, _swap, ref.addend() + inAtomAddress - fixupAddress);
+    return;
+  case delta32:
+    write32(*loc32, _swap, ref.addend() + inAtomAddress - fixupAddress);
+    return;
+  case pointer64ToGOT:
+    write64(*loc64, _swap, 0);
+    return;
+  case delta32ToGOT:
+    write32(*loc32, _swap, -fixupAddress);
+    return;
+  case addOffset12:
+    llvm_unreachable("lazy reference kind implies GOT pass was run");
+  case lazyPointer:
+  case lazyImmediateLocation:
+    llvm_unreachable("lazy reference kind implies Stubs pass was run");
+  case invalid:
+    // Fall into llvm_unreachable().
+    break;
+  }
+  llvm_unreachable("unknown arm64 Reference Kind");
+}
+
+void ArchHandler_arm64::appendSectionRelocations(
+    const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref,
+    FindSymbolIndexForAtom symbolIndexForAtom,
+    FindSectionIndexForAtom sectionIndexForAtom,
+    FindAddressForAtom addressForAtom, normalized::Relocations &relocs) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return;
+  assert(ref.kindArch() == Reference::KindArch::AArch64);
+  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
+  switch (static_cast<Arm64_Kinds>(ref.kindValue())) {
+  case branch26:
+    if (ref.addend()) {
+      appendReloc(relocs, sectionOffset, ref.addend(), 0,
+                  ARM64_RELOC_ADDEND | rLength4);
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4);
+     } else {
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4);
+    }
+    return;
+  case page21:
+    if (ref.addend()) {
+      appendReloc(relocs, sectionOffset, ref.addend(), 0,
+                  ARM64_RELOC_ADDEND | rLength4);
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4);
+     } else {
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4);
+    }
+    return;
+  case offset12:
+  case offset12scale2:
+  case offset12scale4:
+  case offset12scale8:
+  case offset12scale16:
+    if (ref.addend()) {
+      appendReloc(relocs, sectionOffset, ref.addend(), 0,
+                  ARM64_RELOC_ADDEND | rLength4);
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_PAGEOFF12  | rExtern | rLength4);
+     } else {
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_PAGEOFF12 | rExtern | rLength4);
+    }
+    return;
+  case gotPage21:
+    assert(ref.addend() == 0);
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_GOT_LOAD_PAGE21 | rPcRel | rExtern | rLength4);
+    return;
+  case gotOffset12:
+    assert(ref.addend() == 0);
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_GOT_LOAD_PAGEOFF12 | rExtern | rLength4);
+    return;
+  case tlvPage21:
+    assert(ref.addend() == 0);
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_TLVP_LOAD_PAGE21 | rPcRel | rExtern | rLength4);
+    return;
+  case tlvOffset12:
+    assert(ref.addend() == 0);
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4);
+    return;
+  case pointer64:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  X86_64_RELOC_UNSIGNED | rExtern | rLength8);
+    return;
+  case delta64:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+                ARM64_RELOC_SUBTRACTOR | rExtern | rLength8);
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                ARM64_RELOC_UNSIGNED  | rExtern | rLength8);
+    return;
+  case delta32:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+                ARM64_RELOC_SUBTRACTOR | rExtern | rLength4 );
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                ARM64_RELOC_UNSIGNED   | rExtern | rLength4 );
+    return;
+  case pointer64ToGOT:
+    assert(ref.addend() == 0);
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_POINTER_TO_GOT | rExtern | rLength8);
+    return;
+  case delta32ToGOT:
+    assert(ref.addend() == 0);
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_POINTER_TO_GOT | rPcRel | rExtern | rLength4);
+    return;
+  case addOffset12:
+    llvm_unreachable("lazy reference kind implies GOT pass was run");
+  case lazyPointer:
+  case lazyImmediateLocation:
+    llvm_unreachable("lazy reference kind implies Stubs pass was run");
+  case invalid:
+    // Fall into llvm_unreachable().
+    break;
+  }
+  llvm_unreachable("unknown arm64 Reference Kind");
+}
+
+std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm64() {
+  return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm64());
+}
+
+} // namespace mach_o
+} // namespace lld

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp Tue Sep  9 18:52:59 2014
@@ -170,6 +170,7 @@ const ArchHandler::StubInfo ArchHandler_
   6, 
   { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 },       // jmp *lazyPointer
   { Reference::KindArch::x86, abs32, 2, 0 },
+  { false, 0, 0, 0 },
   
   // Stub Helper size and code
   10,
@@ -184,7 +185,9 @@ const ArchHandler::StubInfo ArchHandler_
     0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,         // jmp *_fast_lazy_bind
     0x90 },                                     // nop
   { Reference::KindArch::x86, abs32, 1, 0 },
-  { Reference::KindArch::x86, abs32, 7, 0 }
+  { false, 0, 0, 0 },
+  { Reference::KindArch::x86, abs32, 7, 0 },
+  { false, 0, 0, 0 }
 };
 
 bool ArchHandler_x86::isCallSite(const Reference &ref) {

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Tue Sep  9 18:52:59 2014
@@ -185,6 +185,7 @@ const ArchHandler::StubInfo ArchHandler_
   6, 
   { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 },       // jmp *lazyPointer
   { Reference::KindArch::x86_64, ripRel32, 2, 0 },
+  { false, 0, 0, 0 },
   
   // Stub Helper size and code
   10,
@@ -200,7 +201,9 @@ const ArchHandler::StubInfo ArchHandler_
     0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,         // jmp *binder(%rip)
     0x90 },                                     // nop
   { Reference::KindArch::x86_64, ripRel32, 3, 0 },
-  { Reference::KindArch::x86_64, ripRel32, 11, 0 }
+  { false, 0, 0, 0 },
+  { Reference::KindArch::x86_64, ripRel32, 11, 0 },
+  { false, 0, 0, 0 }
   
 };
 

Modified: lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt (original)
+++ lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt Tue Sep  9 18:52:59 2014
@@ -1,6 +1,7 @@
 add_lld_library(lldMachO
   ArchHandler.cpp
   ArchHandler_arm.cpp
+  ArchHandler_arm64.cpp
   ArchHandler_x86.cpp
   ArchHandler_x86_64.cpp
   GOTPass.cpp

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Tue Sep  9 18:52:59 2014
@@ -79,6 +79,7 @@ MachOLinkingContext::ArchInfo MachOLinki
   { "armv6",  arch_armv6,  true,  CPU_TYPE_ARM,     CPU_SUBTYPE_ARM_V6 },
   { "armv7",  arch_armv7,  true,  CPU_TYPE_ARM,     CPU_SUBTYPE_ARM_V7 },
   { "armv7s", arch_armv7s, true,  CPU_TYPE_ARM,     CPU_SUBTYPE_ARM_V7S },
+  { "arm64",  arch_arm64,  true,  CPU_TYPE_ARM64,   CPU_SUBTYPE_ARM64_ALL },
   { "",       arch_unknown,false, 0,                0 }
 };
 
@@ -194,6 +195,10 @@ void MachOLinkingContext::configure(Head
   default:
     break;
   }
+
+  // Set default segment page sizes based on arch.
+  if (arch == arch_arm64)
+    _pageSize = 4*4096;
 }
 
 uint32_t MachOLinkingContext::getCPUType() const {
@@ -264,10 +269,17 @@ bool MachOLinkingContext::needsStubsPass
 }
 
 bool MachOLinkingContext::needsGOTPass() const {
-  // Only x86_64 uses GOT pass but not in -r mode.
-  if (_arch != arch_x86_64)
+  // GOT pass not used in -r mode.
+  if (_outputMachOType == MH_OBJECT)
     return false;
-  return (_outputMachOType != MH_OBJECT);
+  // Only some arches use GOT pass.
+  switch (_arch) {
+    case arch_x86_64:
+    case arch_arm64:
+      return true;
+    default:
+      return false;
+  }
 }
 
 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h Tue Sep  9 18:52:59 2014
@@ -236,6 +236,7 @@ struct NormalizedFile {
   Hex32                       sdkVersion;
 
   // Maps to load commands with LINKEDIT content (final linked images only).
+  Hex32                       pageSize;
   std::vector<RebaseLocation> rebasingInfo;
   std::vector<BindLocation>   bindingInfo;
   std::vector<BindLocation>   weakBindingInfo;

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp Tue Sep  9 18:52:59 2014
@@ -470,16 +470,21 @@ void MachOFileLayout::buildFileOffsets()
   // Assign sections to segments.
   for (const Section &s : _file.sections) {
     _sectInfo[&s] = t2;
+    bool foundSegment = false;
     for (const Segment &sg : _file.segments) {
-      if ((s.address >= sg.address)
+      if (sg.name.equals(s.segmentName)) {
+        if ((s.address >= sg.address)
                         && (s.address+s.content.size() <= sg.address+sg.size)) {
-        if (!sg.name.equals(s.segmentName)) {
-          _ec = make_error_code(llvm::errc::executable_format_error);
-          return;
+          _segInfo[&sg].sections.push_back(&s);
+          foundSegment = true;
+          break;
         }
-        _segInfo[&sg].sections.push_back(&s);
       }
     }
+    if (!foundSegment) {
+      _ec = make_error_code(llvm::errc::executable_format_error);
+      return;
+    }
   }
 
   // Assign file offsets.
@@ -507,9 +512,10 @@ void MachOFileLayout::buildFileOffsets()
                   << ", fileOffset=" << fileOffset << "\n");
     }
 
-    // FIXME: 4096 should be inferred from segments in normalized file.
-    _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize, 4096);
-    fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize, 4096);
+    _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize,
+                                                      _file.pageSize);
+    fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize,
+                                          _file.pageSize);
     _addressOfLinkEdit = sg.address + sg.size;
   }
   _startOfLinkEdit = fileOffset;
@@ -638,15 +644,16 @@ std::error_code MachOFileLayout::writeSe
     lc = reinterpret_cast<uint8_t*>(next);
   }
   // Add implicit __LINKEDIT segment
+  size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
   typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
   cmd->cmd = T::LC;
   cmd->cmdsize = sizeof(typename T::command);
   uint8_t *next = lc + cmd->cmdsize;
   setString16("__LINKEDIT", cmd->segname);
   cmd->vmaddr   = _addressOfLinkEdit;
-  cmd->vmsize   = _endOfLinkEdit - _startOfLinkEdit;
+  cmd->vmsize   = llvm::RoundUpToAlignment(linkeditSize, _file.pageSize);
   cmd->fileoff  = _startOfLinkEdit;
-  cmd->filesize = _endOfLinkEdit - _startOfLinkEdit;
+  cmd->filesize = linkeditSize;
   cmd->maxprot  = VM_PROT_READ;
   cmd->initprot = VM_PROT_READ;
   cmd->nsects   = 0;
@@ -823,6 +830,8 @@ void MachOFileLayout::writeSectionConten
     // Copy all section content to output buffer.
     if (s.type == llvm::MachO::S_ZEROFILL)
       continue;
+    if (s.content.empty())
+      continue;
     uint32_t offset = _sectInfo[&s].fileOffset;
     uint8_t *p = &_buffer[offset];
     memcpy(p, &s.content[0], s.content.size());
@@ -1262,7 +1271,6 @@ std::error_code MachOFileLayout::writeBi
 }
 
 
-
 /// Takes in-memory normalized view and writes a mach-o object file.
 std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
   MachOFileLayout layout(file);

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Tue Sep  9 18:52:59 2014
@@ -1149,6 +1149,7 @@ normalizedFromAtoms(const lld::File &ato
   normFile.fileType = context.outputMachOType();
   normFile.flags = util.fileFlags();
   normFile.installName = context.installName();
+  normFile.pageSize = context.pageSize();
   util.addDependentDylibs(atomFile, normFile);
   util.copySegmentInfo(normFile);
   util.copySectionInfo(normFile);

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Tue Sep  9 18:52:59 2014
@@ -285,6 +285,12 @@ std::error_code processSymboledSection(D
               Atom::Scope rScope = atomScope(rhs->scope);
               if (lScope != rScope)
                 return lScope < rScope;
+              // If same address and scope, see if one might be better as
+              // the alias.
+              bool lPrivate = (lhs->name.front() == 'l');
+              bool rPrivate = (rhs->name.front() == 'l');
+              if (lPrivate != rPrivate)
+                return lPrivate;
               // If same address and scope, sort by name.
               return lhs->name < rhs->name;
             });
@@ -315,8 +321,15 @@ std::error_code processSymboledSection(D
   const Symbol *lastSym = nullptr;
   for (const Symbol *sym : symbols) {
     if (lastSym != nullptr) {
-      atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
-                     lastSym->desc, atomScope(lastSym->scope), sym->value, copyRefs);
+      // Ignore any assembler added "ltmpNNN" symbol at start of section
+      // if there is another symbol at the start.
+      if ((lastSym->value != sym->value)
+          || lastSym->value != section.address
+          || !lastSym->name.startswith("ltmp")) {
+        atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
+                       lastSym->desc, atomScope(lastSym->scope), sym->value,
+                       copyRefs);
+      }
     }
     lastSym = sym;
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp Tue Sep  9 18:52:59 2014
@@ -129,6 +129,7 @@ struct ScalarEnumerationTraits<lld::Mach
     io.enumCase(value, "armv6",  lld::MachOLinkingContext::arch_armv6);
     io.enumCase(value, "armv7",  lld::MachOLinkingContext::arch_armv7);
     io.enumCase(value, "armv7s", lld::MachOLinkingContext::arch_armv7s);
+    io.enumCase(value, "arm64",  lld::MachOLinkingContext::arch_arm64);
   }
 };
 
@@ -400,6 +401,30 @@ struct ScalarEnumerationTraits<Relocatio
       io.enumCase(value, "ARM_RELOC_HALF_SECTDIFF",
                                   llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
       break;
+    case lld::MachOLinkingContext::arch_arm64:
+      io.enumCase(value, "ARM64_RELOC_UNSIGNED",
+                                  llvm::MachO::ARM64_RELOC_UNSIGNED);
+      io.enumCase(value, "ARM64_RELOC_SUBTRACTOR",
+                                  llvm::MachO::ARM64_RELOC_SUBTRACTOR);
+      io.enumCase(value, "ARM64_RELOC_BRANCH26",
+                                  llvm::MachO::ARM64_RELOC_BRANCH26);
+      io.enumCase(value, "ARM64_RELOC_PAGE21",
+                                  llvm::MachO::ARM64_RELOC_PAGE21);
+      io.enumCase(value, "ARM64_RELOC_PAGEOFF12",
+                                  llvm::MachO::ARM64_RELOC_PAGEOFF12);
+      io.enumCase(value, "ARM64_RELOC_GOT_LOAD_PAGE21",
+                                  llvm::MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
+      io.enumCase(value, "ARM64_RELOC_GOT_LOAD_PAGEOFF12",
+                                  llvm::MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
+      io.enumCase(value, "ARM64_RELOC_POINTER_TO_GOT",
+                                  llvm::MachO::ARM64_RELOC_POINTER_TO_GOT);
+      io.enumCase(value, "ARM64_RELOC_TLVP_LOAD_PAGE21",
+                                  llvm::MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
+      io.enumCase(value, "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
+                                  llvm::MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
+      io.enumCase(value, "ARM64_RELOC_ADDEND",
+                                  llvm::MachO::ARM64_RELOC_ADDEND);
+      break;
     default:
       llvm_unreachable("unknown architecture");
     }
@@ -646,6 +671,7 @@ struct MappingTraits<NormalizedFile> {
     io.mapOptional("local-symbols",    file.localSymbols);
     io.mapOptional("global-symbols",   file.globalSymbols);
     io.mapOptional("undefined-symbols",file.undefinedSymbols);
+    io.mapOptional("page-size",        file.pageSize,       Hex32(4096));
     io.mapOptional("rebasings",        file.rebasingInfo);
     io.mapOptional("bindings",         file.bindingInfo);
     io.mapOptional("weak-bindings",    file.weakBindingInfo);

Modified: lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp?rev=217469&r1=217468&r2=217469&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp Tue Sep  9 18:52:59 2014
@@ -321,6 +321,8 @@ private:
                                               StubHelperAtom(_file, _stubInfo);
    
     addReference(stub, _stubInfo.stubReferenceToLP, lp);
+    addOptReference(stub, _stubInfo.stubReferenceToLP,
+                    _stubInfo.optStubReferenceToLP, lp);
     addReference(lp, _stubInfo.lazyPointerReferenceToHelper, helper);
     addReference(lp, _stubInfo.lazyPointerReferenceToFinal, &target);
     addReference(helper, _stubInfo.stubHelperReferenceToImm, helper);
@@ -334,14 +336,25 @@ private:
     return stub;
   }
  
-  void addReference(SimpleDefinedAtom* atom, 
+  void addReference(SimpleDefinedAtom* atom,
                     const ArchHandler::ReferenceInfo &refInfo,
                     const lld::Atom* target) {
     atom->addReference(Reference::KindNamespace::mach_o,
                       refInfo.arch, refInfo.kind, refInfo.offset,
                       target, refInfo.addend);
   }
-  
+
+   void addOptReference(SimpleDefinedAtom* atom,
+                    const ArchHandler::ReferenceInfo &refInfo,
+                    const ArchHandler::OptionalRefInfo &optRef,
+                    const lld::Atom* target) {
+      if (!optRef.used)
+        return;
+    atom->addReference(Reference::KindNamespace::mach_o,
+                      refInfo.arch, optRef.kind, optRef.offset,
+                      target, optRef.addend);
+  }
+
   const DefinedAtom* helperCommon() {
     if ( !_helperCommonAtom ) {
       // Lazily create common helper code and data.
@@ -352,11 +365,19 @@ private:
       _helperBinderNLPAtom = new (_file.allocator()) 
                                   NonLazyPointerAtom(_file, _context.is64Bit());
       addReference(_helperCommonAtom, 
-                   _stubInfo.stubHelperCommonReferenceToCache, 
+                   _stubInfo.stubHelperCommonReferenceToCache,
                    _helperCacheNLPAtom);
-      addReference(_helperCommonAtom, 
-                   _stubInfo.stubHelperCommonReferenceToBinder, 
+      addOptReference(_helperCommonAtom,
+                      _stubInfo.stubHelperCommonReferenceToCache,
+                      _stubInfo.optStubHelperCommonReferenceToCache,
+                      _helperCacheNLPAtom);
+      addReference(_helperCommonAtom,
+                   _stubInfo.stubHelperCommonReferenceToBinder,
                    _helperBinderNLPAtom);
+      addOptReference(_helperCommonAtom,
+                      _stubInfo.stubHelperCommonReferenceToBinder,
+                      _stubInfo.optStubHelperCommonReferenceToBinder,
+                      _helperBinderNLPAtom);
     }
     return _helperCommonAtom;
   }

Added: lld/trunk/test/mach-o/hello-world-arm64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/hello-world-arm64.yaml?rev=217469&view=auto
==============================================================================
--- lld/trunk/test/mach-o/hello-world-arm64.yaml (added)
+++ lld/trunk/test/mach-o/hello-world-arm64.yaml Tue Sep  9 18:52:59 2014
@@ -0,0 +1,104 @@
+# RUN: lld -flavor darwin -arch arm64 -ios_version_min 7.0 %s -o %t  && \
+# RUN: llvm-nm -m -n %t | FileCheck %s
+#
+# Test that arm64 hello-world can be linked into a mach-o executable
+#
+
+--- !mach-o
+arch:            arm64
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    alignment:       2
+    address:         0x0000000000000000
+    content:         [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
+                       0x08, 0x00, 0x00, 0x90, 0x08, 0x01, 0x40, 0xF9,
+                       0x00, 0x01, 0x40, 0xF9, 0x01, 0x00, 0x00, 0x90,
+                       0x21, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x94,
+                       0x00, 0x00, 0x80, 0x52, 0xFD, 0x7B, 0xC1, 0xA8,
+                       0xC0, 0x03, 0x5F, 0xD6 ]
+    relocations:
+      - offset:          0x0000001C
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          5
+      - offset:          0x00000018
+        type:            ARM64_RELOC_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          1
+      - offset:          0x00000014
+        type:            ARM64_RELOC_PAGE21
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x0000000C
+        type:            ARM64_RELOC_GOT_LOAD_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000008
+        type:            ARM64_RELOC_GOT_LOAD_PAGE21
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          4
+  - segment:         __TEXT
+    section:         __cstring
+    type:            S_CSTRING_LITERALS
+    attributes:      [  ]
+    address:         0x000000000000002C
+    content:         [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
+local-symbols:
+  - name:            ltmp0
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000000
+  - name:            l_.str
+    type:            N_SECT
+    sect:            2
+    value:           0x000000000000002C
+  - name:            ltmp1
+    type:            N_SECT
+    sect:            2
+    value:           0x000000000000002C
+global-symbols:
+  - name:            _main
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+undefined-symbols:
+  - name:            ___stdoutp
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            _fprintf
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+...
+
+--- !mach-o
+arch:            arm64
+file-type:       MH_DYLIB
+install-name:    /usr/lib/libSystem.B.dylib
+exports:
+  - name:            _fprintf
+  - name:            ___stdoutp
+  - name:            dyld_stub_binder
+...
+
+# CHECK:	{{[0-9a-f]+}} (__TEXT,__text) external _main
+# CHECK:	(undefined) external ___stdoutp (from libSystem)
+# CHECK:	(undefined) external _fprintf (from libSystem)
+# CHECK:	(undefined) external dyld_stub_binder (from libSystem)

Added: lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml?rev=217469&view=auto
==============================================================================
--- lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml (added)
+++ lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml Tue Sep  9 18:52:59 2014
@@ -0,0 +1,191 @@
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s \
+# RUN:  && lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
+#
+# Test parsing and writing of arm64 data relocations.
+#
+# The first step tests if the supplied mach-o file is parsed into the correct
+# set of references.  The second step verifies relocations can be round-tripped
+# by writing to a new .o file, then parsing that file which should result in
+# the same references.
+#
+#_test:
+
+
+--- !mach-o
+arch:            arm64
+file-type:       MH_OBJECT
+flags:           [  ]
+has-UUID:        false
+OS:              unknown
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS ]
+    address:         0x0000000000000000
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    alignment:       3
+    address:         0x0000000000000000
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                       0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                       0xD0, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0xFF, 0xFF,
+                       0xC8, 0xFF, 0xFF, 0xFF ]
+    relocations:
+      - offset:          0x00000038
+        type:            ARM64_RELOC_POINTER_TO_GOT
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          3
+      - offset:          0x00000034
+        type:            ARM64_RELOC_SUBTRACTOR
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000034
+        type:            ARM64_RELOC_UNSIGNED
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+      - offset:          0x00000030
+        type:            ARM64_RELOC_SUBTRACTOR
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000030
+        type:            ARM64_RELOC_UNSIGNED
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+      - offset:          0x00000028
+        type:            ARM64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000028
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+      - offset:          0x00000020
+        type:            ARM64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000020
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+      - offset:          0x00000018
+        type:            ARM64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000018
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+      - offset:          0x00000010
+        type:            ARM64_RELOC_POINTER_TO_GOT
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+      - offset:          0x00000008
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+      - offset:          0x00000000
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+local-symbols:
+  - name:            ltmp0
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000000
+  - name:            ltmp1
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000000
+  - name:            _v1
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000000
+undefined-symbols:
+  - name:            _foo
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+...
+
+# CHECK: defined-atoms:
+# CHECK:   - name:            _v1
+# CHECK:     type:            data
+# CHECK:     content:         [ 00, 00, 00, 00, 00, 00, 00, 00, 08, 00, 00, 00,
+# CHECK:                        00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
+# CHECK:                        00, 00, 00, 00, 00, 00, 00, 00, E0, FF, FF, FF,
+# CHECK:                        FF, FF, FF, FF, DC, FF, FF, FF, FF, FF, FF, FF,
+# CHECK:                        D0, FF, FF, FF, CE, FF, FF, FF, C8, FF, FF, FF ]
+# CHECK:     references:
+# CHECK:       - kind:            pointer64
+# CHECK:         offset:          0
+# CHECK:         target:          _foo
+# CHECK-NOT:     addend:
+# CHECK:       - kind:            pointer64
+# CHECK:         offset:          8
+# CHECK:         target:          _foo
+# CHECK:         addend:          8
+# CHECK:       - kind:            pointer64ToGOT
+# CHECK:         offset:          16
+# CHECK:         target:          _foo
+# CHECK-NOT:     addend:
+# CHECK:       - kind:            delta64
+# CHECK:         offset:          24
+# CHECK:         target:          _foo
+# CHECK:         addend:          24
+# CHECK:       - kind:            delta64
+# CHECK:         offset:          32
+# CHECK:         target:          _foo
+# CHECK-NOT:     addend:
+# CHECK:       - kind:            delta64
+# CHECK:         offset:          40
+# CHECK:         target:          _foo
+# CHECK:         addend:          4
+# CHECK:       - kind:            delta32
+# CHECK:         offset:          48
+# CHECK:         target:          _foo
+# CHECK-NOT:     addend:
+# CHECK:       - kind:            delta32
+# CHECK:         offset:          52
+# CHECK:         target:          _foo
+# CHECK:         addend:          2
+# CHECK:       - kind:            delta32ToGOT
+# CHECK:         offset:          56
+# CHECK:         target:          _foo
+# CHECK-NOT:     addend:
+# CHECK: undefined-atoms:
+# CHECK:   - name:            _foo

Added: lld/trunk/test/mach-o/parse-text-relocs-arm64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-text-relocs-arm64.yaml?rev=217469&view=auto
==============================================================================
--- lld/trunk/test/mach-o/parse-text-relocs-arm64.yaml (added)
+++ lld/trunk/test/mach-o/parse-text-relocs-arm64.yaml Tue Sep  9 18:52:59 2014
@@ -0,0 +1,237 @@
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s \
+# RUN:  && lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
+#
+# Test parsing and writing of arm64 text relocations.
+#
+# The first step tests if the supplied mach-o file is parsed into the correct
+# set of references.  The second step verifies relocations can be round-tripped
+# by writing to a new .o file, then parsing that file which should result in
+# the same references.
+#
+#_test:
+
+
+--- !mach-o
+arch:            arm64
+file-type:       MH_OBJECT
+flags:           [  ]
+has-UUID:        false
+OS:              unknown
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    address:         0x0000000000000000
+    content:         [ 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x94,
+                       0x01, 0x00, 0x00, 0x90, 0x20, 0x00, 0x40, 0x39,
+                       0x20, 0x00, 0x40, 0x79, 0x20, 0x00, 0x40, 0xB9,
+                       0x20, 0x00, 0x40, 0xF9, 0x20, 0x00, 0xC0, 0x3D,
+                       0x01, 0x00, 0x00, 0x90, 0x20, 0x00, 0x40, 0xB9,
+                       0x01, 0x00, 0x00, 0x90, 0x20, 0x00, 0x40, 0xF9,
+                       0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x40, 0xF9 ]
+    relocations:
+      - offset:          0x00000034
+        type:            ARM64_RELOC_TLVP_LOAD_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          5
+      - offset:          0x00000030
+        type:            ARM64_RELOC_TLVP_LOAD_PAGE21
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          5
+      - offset:          0x0000002C
+        type:            ARM64_RELOC_GOT_LOAD_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          6
+      - offset:          0x00000028
+        type:            ARM64_RELOC_GOT_LOAD_PAGE21
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          6
+      - offset:          0x00000024
+        type:            ARM64_RELOC_ADDEND
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          16
+      - offset:          0x00000024
+        type:            ARM64_RELOC_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000020
+        type:            ARM64_RELOC_ADDEND
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          16
+      - offset:          0x00000020
+        type:            ARM64_RELOC_PAGE21
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          2
+      - offset:          0x0000001C
+        type:            ARM64_RELOC_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000018
+        type:            ARM64_RELOC_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000014
+        type:            ARM64_RELOC_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000010
+        type:            ARM64_RELOC_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x0000000C
+        type:            ARM64_RELOC_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000008
+        type:            ARM64_RELOC_PAGE21
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          2
+      - offset:          0x00000004
+        type:            ARM64_RELOC_ADDEND
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          8
+      - offset:          0x00000004
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          4
+      - offset:          0x00000000
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          4
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    alignment:       2
+    address:         0x0000000000000038
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+local-symbols:
+  - name:            ltmp0
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000000
+  - name:            _func
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000000
+  - name:            _v1
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000038
+  - name:            ltmp1
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000038
+undefined-symbols:
+  - name:            _foo
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            _tlv
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            _v2
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+...
+
+# CHECK: defined-atoms:
+# CHECK:   - name:            _v1
+# CHECK:     type:            data
+# CHECK:     content:         [ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
+# CHECK:                        00, 00, 00, 00 ]
+# CHECK:   - name:            _func
+# CHECK:     content:         [ 00, 00, 00, 94, 00, 00, 00, 94, 01, 00, 00, 90,
+# CHECK:                        20, 00, 40, 39, 20, 00, 40, 79, 20, 00, 40, B9,
+# CHECK:                        20, 00, 40, F9, 20, 00, C0, 3D, 01, 00, 00, 90,
+# CHECK:                        20, 00, 40, B9, 01, 00, 00, 90, 20, 00, 40, F9,
+# CHECK:                        00, 00, 00, 90, 00, 00, 40, F9 ]
+# CHECK:     references:
+# CHECK:       - kind:            branch26
+# CHECK:         offset:          0
+# CHECK:         target:          _foo
+# CHECK:       - kind:            branch26
+# CHECK:         offset:          4
+# CHECK:         target:          _foo
+# CHECK:         addend:          8
+# CHECK:       - kind:            page21
+# CHECK:         offset:          8
+# CHECK:         target:          _v1
+# CHECK:       - kind:            offset12
+# CHECK:         offset:          12
+# CHECK:         target:          _v1
+# CHECK:       - kind:            offset12scale2
+# CHECK:         offset:          16
+# CHECK:         target:          _v1
+# CHECK:       - kind:            offset12scale4
+# CHECK:         offset:          20
+# CHECK:         target:          _v1
+# CHECK:       - kind:            offset12scale8
+# CHECK:         offset:          24
+# CHECK:         target:          _v1
+# CHECK:       - kind:            offset12scale16
+# CHECK:         offset:          28
+# CHECK:         target:          _v1
+# CHECK:       - kind:            page21
+# CHECK:         offset:          32
+# CHECK:         target:          _v1
+# CHECK:         addend:          16
+# CHECK:       - kind:            offset12scale4
+# CHECK:         offset:          36
+# CHECK:         target:          _v1
+# CHECK:         addend:          16
+# CHECK:       - kind:            gotPage21
+# CHECK:         offset:          40
+# CHECK:         target:          _v2
+# CHECK:       - kind:            gotOffset12
+# CHECK:         offset:          44
+# CHECK:         target:          _v2
+# CHECK:       - kind:            tlvPage21
+# CHECK:         offset:          48
+# CHECK:         target:          _tlv
+# CHECK:       - kind:            tlvOffset12
+# CHECK:         offset:          52
+# CHECK:         target:          _tlv
+# CHECK: undefined-atoms:
+# CHECK:   - name:            _foo
+# CHECK:   - name:            _tlv
+# CHECK:   - name:            _v2
+





More information about the llvm-commits mailing list