[lld] r212306 - [mach-o] Add parsing of arm/thumb relocations

Nick Kledzik kledzik at apple.com
Thu Jul 3 17:11:09 PDT 2014


Author: kledzik
Date: Thu Jul  3 19:11:09 2014
New Revision: 212306

URL: http://llvm.org/viewvc/llvm-project?rev=212306&view=rev
Log:
[mach-o] Add parsing of arm/thumb relocations

This converts the very complicated mach-o arm
relocations into the simple Reference Kinds in lld.

The next patch will use the internal Reference kinds
to fix up arm/thumb code.

Added:
    lld/trunk/test/mach-o/parse-arm-relocs.yaml
Modified:
    lld/trunk/lib/ReaderWriter/MachO/Atoms.h
    lld/trunk/lib/ReaderWriter/MachO/File.h
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp
    lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h

Modified: lld/trunk/lib/ReaderWriter/MachO/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/Atoms.h?rev=212306&r1=212305&r2=212306&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/Atoms.h Thu Jul  3 19:11:09 2014
@@ -17,10 +17,10 @@ namespace mach_o {
 class MachODefinedAtom : public SimpleDefinedAtom {
 public:
   MachODefinedAtom(const File &f, const StringRef name, Scope scope,
-                   ContentType type, Merge merge,
+                   ContentType type, Merge merge, bool thumb,
                    const ArrayRef<uint8_t> content)
       : SimpleDefinedAtom(f), _name(name), _content(content),
-        _contentType(type), _scope(scope), _merge(merge) {}
+        _contentType(type), _scope(scope), _merge(merge), _thumb(thumb) {}
 
   // Constructor for zero-fill content
   MachODefinedAtom(const File &f, const StringRef name, Scope scope,
@@ -28,7 +28,7 @@ public:
       : SimpleDefinedAtom(f), _name(name),
         _content(ArrayRef<uint8_t>(nullptr, size)),
         _contentType(DefinedAtom::typeZeroFill),
-        _scope(scope), _merge(mergeNo) {}
+        _scope(scope), _merge(mergeNo), _thumb(false) {}
 
   uint64_t size() const override { return _content.size(); }
 
@@ -53,6 +53,8 @@ public:
     return _content;
   }
 
+  bool isThumb() const { return _thumb; }
+
   void addReference(uint32_t offsetInAtom, uint16_t relocType, 
                const Atom *target, Reference::Addend addend, 
                Reference::KindArch arch = Reference::KindArch::x86_64,
@@ -66,15 +68,16 @@ private:
   const ContentType _contentType;
   const Scope _scope;
   const Merge _merge;
+  const bool _thumb;
 };
 
 class MachODefinedCustomSectionAtom : public MachODefinedAtom {
 public:
   MachODefinedCustomSectionAtom(const File &f, const StringRef name, 
                                 Scope scope, ContentType type, Merge merge,
-                                const ArrayRef<uint8_t> content,
+                                bool thumb, const ArrayRef<uint8_t> content,
                                 StringRef sectionName)
-      : MachODefinedAtom(f, name, scope, type, merge, content), 
+      : MachODefinedAtom(f, name, scope, type, merge, thumb, content), 
         _sectionName(sectionName) {}
 
   SectionChoice sectionChoice() const override {

Modified: lld/trunk/lib/ReaderWriter/MachO/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/File.h?rev=212306&r1=212305&r2=212306&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/File.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/File.h Thu Jul  3 19:11:09 2014
@@ -30,7 +30,7 @@ public:
 
   void addDefinedAtom(StringRef name, Atom::Scope scope,
                       DefinedAtom::ContentType type, DefinedAtom::Merge merge,
-                      uint64_t sectionOffset, uint64_t contentSize, 
+                      uint64_t sectionOffset, uint64_t contentSize, bool thumb,
                       bool copyRefs, const Section *inSection) {
     assert(sectionOffset+contentSize <= inSection->content.size());
     ArrayRef<uint8_t> content = inSection->content.slice(sectionOffset, 
@@ -41,14 +41,14 @@ public:
       content = content.copy(_allocator);
     }
     MachODefinedAtom *atom =
-        new (_allocator) MachODefinedAtom(*this, name, scope, type, merge,
-                                          content);
+        new (_allocator) MachODefinedAtom(*this, name, scope, type, merge, 
+                                          thumb, content);
     addAtomForSection(inSection, atom, sectionOffset);
   }
 
   void addDefinedAtomInCustomSection(StringRef name, Atom::Scope scope,
                       DefinedAtom::ContentType type, DefinedAtom::Merge merge,
-                      uint64_t sectionOffset, uint64_t contentSize, 
+                      bool thumb, uint64_t sectionOffset, uint64_t contentSize,
                       StringRef sectionName, bool copyRefs, 
                       const Section *inSection) {
     assert(sectionOffset+contentSize <= inSection->content.size());
@@ -61,8 +61,9 @@ public:
       sectionName = sectionName.copy(_allocator);
     }
     MachODefinedCustomSectionAtom *atom =
-        new (_allocator) MachODefinedCustomSectionAtom(*this, name, scope, type, 
-                                                  merge, content, sectionName);
+        new (_allocator) MachODefinedCustomSectionAtom(*this, name, scope, type,
+                                                        merge, thumb, content,
+                                                        sectionName);
     addAtomForSection(inSection, atom, sectionOffset);
   }
 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=212306&r1=212305&r2=212306&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Thu Jul  3 19:11:09 2014
@@ -231,6 +231,7 @@ void atomFromSymbol(DefinedAtom::Content
   } else {
     DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF)
                               ? DefinedAtom::mergeAsWeak : DefinedAtom::mergeNo;
+    bool thumb = (symbolDescFlags & N_ARM_THUMB_DEF);
     if (atomType == DefinedAtom::typeUnknown) {
       // Mach-O needs a segment and section name.  Concatentate those two
       // with a / seperator (e.g. "seg/sect") to fit into the lld model
@@ -238,15 +239,15 @@ void atomFromSymbol(DefinedAtom::Content
       std::string segSectName = section.segmentName.str()
                                 + "/" + section.sectionName.str();
       file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType,
-                                         merge, offset, size, segSectName, true,
-                                         &section);
+                                         merge, thumb,offset, size, segSectName, 
+                                         true, &section);
     } else {
       if ((atomType == lld::DefinedAtom::typeCode) &&
           (symbolDescFlags & N_SYMBOL_RESOLVER)) {
         atomType = lld::DefinedAtom::typeResolver;
       }
       file.addDefinedAtom(symbolName, symbolScope, atomType, merge,
-                          offset, size, copyRefs, &section);
+                          offset, size, thumb, copyRefs, &section);
     }
   }
 }
@@ -418,7 +419,7 @@ std::error_code processSection(DefinedAt
                                      "not zero terminated.");
       }
       file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size,
-                          copyRefs, &section);
+                          false, copyRefs, &section);
       offset += size;
     }
   }
@@ -614,12 +615,6 @@ normalizedObjectToAtoms(const Normalized
     }
   }
 
-  // TEMP BEGIN: until all KindHandlers switched to new interface.
-  if ((normalizedFile.arch != lld::MachOLinkingContext::arch_x86_64) &&
-      (normalizedFile.arch != lld::MachOLinkingContext::arch_x86))
-    return std::unique_ptr<File>(std::move(file));
-  // TEMP END
-
   // Convert mach-o relocations to References
   std::unique_ptr<mach_o::KindHandler> handler
                                      = KindHandler::create(normalizedFile.arch);

Modified: lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp?rev=212306&r1=212305&r2=212306&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp Thu Jul  3 19:11:09 2014
@@ -10,6 +10,7 @@
 
 #include "ReferenceKinds.h"
 #include "MachONormalizedFileBinaryUtils.h"
+#include "Atoms.h"
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -93,37 +94,6 @@ int64_t KindHandler::readS64(bool swap,
 }
 
 
-bool KindHandler::isPairedReloc(const Relocation &reloc) {
-  llvm_unreachable("abstract");
-}
-
-std::error_code 
-KindHandler::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) {
-  llvm_unreachable("abstract");
-}
-
-std::error_code
-KindHandler::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) {
-  llvm_unreachable("abstract");
-}
-
 //===----------------------------------------------------------------------===//
 //  KindHandler_x86_64
 //===----------------------------------------------------------------------===//
@@ -564,7 +534,7 @@ KindHandler_x86::getPairReferenceInfo(co
       uint32_t ta = fromAddress + value - toAddress;
       *addend = ta - offsetInFrom;
     } else {
-      *addend= fromAddress + value - toAddress;
+      *addend = fromAddress + value - toAddress;
     }
     return std::error_code();
     break;
@@ -622,36 +592,447 @@ KindHandler_arm::~KindHandler_arm() {
 }
 
 const Registry::KindStrings KindHandler_arm::kindStrings[] = {
-  LLD_KIND_STRING_ENTRY(ARM_RELOC_BR24),
-  LLD_KIND_STRING_ENTRY(ARM_THUMB_RELOC_BR22),
-  LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_THUMB_ABS_LO16),
-  LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_THUMB_ABS_HI16),
-  LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_THUMB_REL_LO16),
-  LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_THUMB_REL_HI16),
-  LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_ABS32),
-  LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_POINTER32),
-  LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_LAZY_TARGET),
-  LLD_KIND_STRING_ENTRY(LLD_ARM_RELOC_LAZY_IMMEDIATE),
+  LLD_KIND_STRING_ENTRY(thumb_b22),
+  LLD_KIND_STRING_ENTRY(thumb_movw),
+  LLD_KIND_STRING_ENTRY(thumb_movt),
+  LLD_KIND_STRING_ENTRY(thumb_movw_funcRel),
+  LLD_KIND_STRING_ENTRY(thumb_movt_funcRel),
+  LLD_KIND_STRING_ENTRY(arm_b24),
+  LLD_KIND_STRING_ENTRY(arm_movw),
+  LLD_KIND_STRING_ENTRY(arm_movt),
+  LLD_KIND_STRING_ENTRY(arm_movw_funcRel),
+  LLD_KIND_STRING_ENTRY(arm_movt_funcRel),
+  LLD_KIND_STRING_ENTRY(pointer32),
+  LLD_KIND_STRING_ENTRY(delta32),
+  LLD_KIND_STRING_ENTRY(lazyPointer),
+  LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
   LLD_KIND_STRING_END
 };
 
 bool KindHandler_arm::isCallSite(const Reference &ref) {
-  return (ref.kindValue() == ARM_THUMB_RELOC_BR22) ||
-         (ref.kindValue() == ARM_RELOC_BR24);
+  return (ref.kindValue() == thumb_b22) ||
+         (ref.kindValue() == arm_b24);
 }
 
 bool KindHandler_arm::isPointer(const Reference &ref) {
-  return (ref.kindValue() == LLD_ARM_RELOC_POINTER32);
+  return (ref.kindValue() == pointer32);
 }
 
 bool KindHandler_arm::isLazyImmediate(const Reference &ref) {
-  return (ref.kindValue() == LLD_ARM_RELOC_LAZY_IMMEDIATE);
+  return (ref.kindValue() == lazyImmediateLocation);
 }
 
 bool KindHandler_arm::isLazyTarget(const Reference &ref) {
-  return (ref.kindValue() == LLD_ARM_RELOC_LAZY_TARGET);
+  return (ref.kindValue() == lazyPointer);
+}
+
+bool KindHandler_arm::isPairedReloc(const Relocation &reloc) {
+  switch (reloc.type) {
+  case ARM_RELOC_SECTDIFF:
+  case ARM_RELOC_LOCAL_SECTDIFF:
+  case ARM_RELOC_HALF_SECTDIFF:
+  case ARM_RELOC_HALF:
+    return true;
+  default:
+    return false;
+  }
 }
 
+
+int32_t KindHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction) {
+  uint32_t s = (instruction >> 10) & 0x1;
+  uint32_t j1 = (instruction >> 29) & 0x1;
+  uint32_t j2 = (instruction >> 27) & 0x1;
+  uint32_t imm10 = instruction & 0x3FF;
+  uint32_t imm11 = (instruction >> 16) & 0x7FF;
+  uint32_t i1 = (j1 == s);
+  uint32_t i2 = (j2 == s);
+  uint32_t dis = (s << 24) | (i1 << 23) | (i2 << 22) 
+               | (imm10 << 12) | (imm11 << 1);
+  int32_t sdis = dis;
+  if (s)
+    return (sdis | 0xFE000000);
+  else
+    return sdis;
+}
+
+int32_t KindHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) {
+  // Sign-extend imm24
+  int32_t displacement = (instruction & 0x00FFFFFF) << 2;
+  if ( (displacement & 0x02000000) != 0 )
+    displacement |= 0xFC000000;
+  // If this is BLX and H bit set, add 2.
+  if ((instruction & 0xFF000000) == 0xFB000000)
+    displacement += 2;
+  return displacement;
+}
+
+
+uint16_t KindHandler_arm::getWordFromThumbMov(uint32_t instruction) {
+  uint32_t i =    ((instruction & 0x00000400) >> 10);
+  uint32_t imm4 =  (instruction & 0x0000000F);
+  uint32_t imm3 = ((instruction & 0x70000000) >> 28);
+  uint32_t imm8 = ((instruction & 0x00FF0000) >> 16);
+  return (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
+}
+
+uint16_t KindHandler_arm::getWordFromArmMov(uint32_t instruction) {
+  uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
+  uint32_t imm12 = (instruction & 0x00000FFF);
+  return (imm4 << 12) | imm12;
+}
+
+uint32_t KindHandler_arm::clearThumbBit(uint32_t value, const Atom* target) {
+  // The assembler often adds one to the address of a thumb function.
+  // We need to undo that so it does not look like an addend.
+  if (value & 1) {
+    if (isa<DefinedAtom>(target)) {
+      const MachODefinedAtom *machoTarget = reinterpret_cast<
+                                              const MachODefinedAtom*>(target);
+      if (machoTarget->isThumb())
+        value &= -2;  // mask off thumb-bit
+    }
+  }
+  return value;
+}
+
+std::error_code
+KindHandler_arm::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];
+  uint64_t targetAddress;
+  uint32_t instruction = readU32(swap, fixupContent);
+  int32_t displacement;
+  switch (relocPattern(reloc)) {
+  case ARM_THUMB_RELOC_BR22 | rPcRel | rExtern | rLength4:
+    // ex: bl _foo (and _foo is undefined)
+    *kind = thumb_b22;
+    if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    // Instruction contains branch to addend.
+    displacement = getDisplacementFromThumbBranch(instruction);
+    *addend = fixupAddress + 4 + displacement;
+    return std::error_code();
+  case ARM_THUMB_RELOC_BR22 | rPcRel           | rLength4:
+    // ex: bl _foo (and _foo is defined)
+    *kind = thumb_b22;
+    displacement = getDisplacementFromThumbBranch(instruction);
+    targetAddress = fixupAddress + 4 + displacement;
+    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
+  case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4:
+    // ex: bl _foo+4 (and _foo is defined)
+    *kind = thumb_b22;
+    displacement = getDisplacementFromThumbBranch(instruction);
+    targetAddress = fixupAddress + 4 + displacement;
+    if (E ec = atomFromAddress(0, reloc.value, target, addend))
+      return ec;
+    // reloc.value is target atom's address.  Instruction contains branch
+    // to atom+addend.
+    *addend += (targetAddress - reloc.value);
+    return std::error_code();
+  case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4:
+    // ex: bl _foo (and _foo is undefined)
+    *kind = arm_b24;
+    if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    // Instruction contains branch to addend.
+    displacement = getDisplacementFromArmBranch(instruction);
+    *addend = fixupAddress + 8 + displacement;
+    return std::error_code();
+  case ARM_RELOC_BR24 | rPcRel           | rLength4:
+    // ex: bl _foo (and _foo is defined)
+    *kind = arm_b24;
+    displacement = getDisplacementFromArmBranch(instruction);
+    targetAddress = fixupAddress + 8 + displacement;
+    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
+  case ARM_RELOC_BR24 | rScattered | rPcRel | rLength4:
+    // ex: bl _foo+4 (and _foo is defined)
+    *kind = arm_b24;
+    displacement = getDisplacementFromArmBranch(instruction);
+    targetAddress = fixupAddress + 8 + displacement;
+    if (E ec = atomFromAddress(0, reloc.value, target, addend))
+      return ec;
+    // reloc.value is target atom's address.  Instruction contains branch
+    // to atom+addend.
+    *addend += (targetAddress - reloc.value);
+    return std::error_code();
+  case ARM_RELOC_VANILLA | rExtern   | rLength4:
+    // ex: .long _foo (and _foo is undefined)
+    *kind = pointer32;
+    if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = instruction;
+    return std::error_code();
+  case ARM_RELOC_VANILLA             | rLength4:
+    // ex: .long _foo (and _foo is defined)
+    *kind = pointer32;
+    if (E ec = atomFromAddress(reloc.symbol, instruction, target, addend))
+      return ec;
+    *addend = clearThumbBit((uint32_t)*addend, *target);
+    return std::error_code();
+  case ARM_RELOC_VANILLA | rScattered | rLength4:
+    // ex: .long _foo+a (and _foo is defined)
+    *kind = pointer32;
+    if (E ec = atomFromAddress(0, reloc.value, target, addend))
+      return ec;
+   *addend += (clearThumbBit(instruction, *target) - reloc.value);
+    return std::error_code();
+  default:
+    return make_dynamic_error_code(Twine("unsupported arm relocation type"));
+  }
+  return std::error_code();
+}
+
+
+std::error_code
+KindHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
+                                     const normalized::Relocation &reloc2,
+                                     const DefinedAtom *inAtom,
+                                     uint32_t offsetInAtom,
+                                     uint64_t fixupAddress, bool swap,
+                                     FindAtomBySectionAndAddress atomFromAddr,
+                                     FindAtomBySymbolIndex atomFromSymbolIndex,
+                                     Reference::KindValue *kind,
+                                     const lld::Atom **target,
+                                     Reference::Addend *addend) {
+  bool pointerDiff = false;
+  bool funcRel;
+  bool top;
+  bool thumbReloc;
+  switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
+  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLength4) << 16 |
+         ARM_RELOC_PAIR           | rScattered | rLength4):
+    // ex: movw	r1, :lower16:(_x-L1) [thumb mode]
+    *kind = thumb_movw_funcRel;
+    funcRel = true;
+    top = false;
+    thumbReloc = true;
+    break;
+  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLength8) << 16 |
+         ARM_RELOC_PAIR           | rScattered | rLength8):
+    // ex: movt	r1, :upper16:(_x-L1) [thumb mode]
+    *kind = thumb_movt_funcRel;
+    funcRel = true;
+    top = true;
+    thumbReloc = true;
+    break;
+  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLength1) << 16 |
+         ARM_RELOC_PAIR           | rScattered | rLength1):
+    // ex: movw	r1, :lower16:(_x-L1) [arm mode]
+    *kind = arm_movw_funcRel;
+    funcRel = true;
+    top = false;
+    thumbReloc = false;
+    break;
+  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLength2) << 16 |
+         ARM_RELOC_PAIR           | rScattered | rLength2):
+    // ex: movt	r1, :upper16:(_x-L1) [arm mode]
+    *kind = arm_movt_funcRel;
+    funcRel = true;
+    top = true;
+    thumbReloc = false;
+    break;
+  case ((ARM_RELOC_HALF     | rLength4) << 16 |
+         ARM_RELOC_PAIR     | rLength4):
+    // ex: movw	r1, :lower16:_x [thumb mode]
+    *kind = thumb_movw;
+    funcRel = false;
+    top = false;
+    thumbReloc = true;
+    break;
+  case ((ARM_RELOC_HALF     | rLength8) << 16 |
+         ARM_RELOC_PAIR     | rLength8):
+    // ex: movt	r1, :upper16:_x [thumb mode]
+    *kind = thumb_movt;
+    funcRel = false;
+    top = true;
+    thumbReloc = true;
+    break;
+  case ((ARM_RELOC_HALF     | rLength1) << 16 |
+         ARM_RELOC_PAIR     | rLength1):
+    // ex: movw	r1, :lower16:_x [arm mode]
+    *kind = arm_movw;
+    funcRel = false;
+    top = false;
+    thumbReloc = false;
+    break;
+  case ((ARM_RELOC_HALF     | rLength2) << 16 |
+         ARM_RELOC_PAIR     | rLength2):
+    // ex: movt	r1, :upper16:_x [arm mode]
+    *kind = arm_movt;
+    funcRel = false;
+    top = true;
+    thumbReloc = false;
+    break;
+  case ((ARM_RELOC_HALF | rScattered  | rLength4) << 16 |
+         ARM_RELOC_PAIR               | rLength4):
+    // ex: movw	r1, :lower16:_x+a [thumb mode]
+    *kind = thumb_movw;
+    funcRel = false;
+    top = false;
+    thumbReloc = true;
+    break;
+  case ((ARM_RELOC_HALF | rScattered  | rLength8) << 16 |
+         ARM_RELOC_PAIR               | rLength8):
+    // ex: movt	r1, :upper16:_x+a [thumb mode]
+    *kind = thumb_movt;
+    funcRel = false;
+    top = true;
+    thumbReloc = true;
+    break;
+  case ((ARM_RELOC_HALF | rScattered  | rLength1) << 16 |
+         ARM_RELOC_PAIR               | rLength1):
+    // ex: movw	r1, :lower16:_x+a [arm mode]
+    *kind = arm_movw;
+    funcRel = false;
+    top = false;
+    thumbReloc = false;
+    break;
+  case ((ARM_RELOC_HALF | rScattered  | rLength2) << 16 |
+         ARM_RELOC_PAIR               | rLength2):
+    // ex: movt	r1, :upper16:_x+a [arm mode]
+    *kind = arm_movt;
+    funcRel = false;
+    top = true;
+    thumbReloc = false;
+    break;
+  case ((ARM_RELOC_HALF | rExtern   | rLength4) << 16 |
+         ARM_RELOC_PAIR             | rLength4):
+    // ex: movw	r1, :lower16:_undef [thumb mode]
+    *kind = thumb_movw;
+    funcRel = false;
+    top = false;
+    thumbReloc = true;
+    break;
+  case ((ARM_RELOC_HALF | rExtern   | rLength8) << 16 |
+         ARM_RELOC_PAIR             | rLength8):
+    // ex: movt	r1, :upper16:_undef [thumb mode]
+    *kind = thumb_movt;
+    funcRel = false;
+    top = true;
+    thumbReloc = true;
+    break;
+  case ((ARM_RELOC_HALF | rExtern   | rLength1) << 16 |
+         ARM_RELOC_PAIR             | rLength1):
+    // ex: movw	r1, :lower16:_undef [arm mode]
+    *kind = arm_movw;
+    funcRel = false;
+    top = false;
+    thumbReloc = false;
+    break;
+  case ((ARM_RELOC_HALF | rExtern   | rLength2) << 16 |
+         ARM_RELOC_PAIR             | rLength2):
+    // ex: movt	r1, :upper16:_undef [arm mode]
+    *kind = arm_movt;
+    funcRel = false;
+    top = true;
+    thumbReloc = false;
+    break;
+  case ((ARM_RELOC_SECTDIFF       | rScattered | rLength4) << 16 |
+         ARM_RELOC_PAIR           | rScattered | rLength4):
+  case ((ARM_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
+         ARM_RELOC_PAIR           | rScattered | rLength4):
+    // ex: .long _foo - .
+    pointerDiff = true;
+    break;
+  default:
+    return make_dynamic_error_code(Twine("unsupported arm relocation pair"));
+  }
+  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
+  std::error_code ec;
+  uint32_t instruction = readU32(swap, fixupContent);
+  uint32_t value;
+  uint32_t fromAddress;
+  uint32_t toAddress;
+  uint16_t instruction16;
+  uint16_t other16;
+  const lld::Atom *fromTarget;
+  Reference::Addend offsetInTo;
+  Reference::Addend offsetInFrom;
+  if (pointerDiff) {
+    toAddress = reloc1.value;
+    fromAddress = reloc2.value;
+    ec = atomFromAddr(0, toAddress, target, &offsetInTo);
+    if (ec)
+      return ec;
+    ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
+    if (ec)
+      return ec;
+    if (fromTarget != inAtom)
+      return make_dynamic_error_code(Twine("SECTDIFF relocation where "
+                                     "subtrahend label is not in atom"));
+    *kind = delta32;
+    value = clearThumbBit(instruction, *target);
+    *addend = value - (toAddress - fromAddress);
+  } else if (funcRel) {
+    toAddress = reloc1.value;
+    fromAddress = reloc2.value;
+    ec = atomFromAddr(0, toAddress, target, &offsetInTo);
+    if (ec)
+      return ec;
+    ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom);
+    if (ec)
+      return ec;
+    if (fromTarget != inAtom)
+      return make_dynamic_error_code(Twine("ARM_RELOC_HALF_SECTDIFF relocation "
+                                     "where subtrahend label is not in atom"));
+    other16 = (reloc2.offset & 0xFFFF);
+    if (thumbReloc)
+      instruction16 = getWordFromThumbMov(instruction);
+    else
+      instruction16 = getWordFromArmMov(instruction);
+    if (top)
+      value = (instruction16 << 16) | other16;
+    else
+      value = (other16 << 16) | instruction16;
+    value = clearThumbBit(value, *target);
+    int64_t ta = (int64_t)value - (toAddress - fromAddress);
+    *addend = ta - offsetInFrom;
+    return std::error_code();
+  } else {
+    uint32_t sectIndex;
+    if (thumbReloc)
+      instruction16 = getWordFromThumbMov(instruction);
+    else
+      instruction16 = getWordFromArmMov(instruction);
+    other16 = (reloc2.offset & 0xFFFF);
+    if (top)
+      value = (instruction16 << 16) | other16;
+    else
+      value = (other16 << 16) | instruction16;
+    if (reloc1.isExtern) {
+      ec = atomFromSymbolIndex(reloc1.symbol, target);
+      if (ec)
+        return ec;
+      *addend = value;
+    } else {
+      if (reloc1.scattered) {
+        toAddress = reloc1.value;
+        sectIndex = 0;
+      } else {
+        toAddress = value;
+        sectIndex = reloc1.symbol;
+      }
+      ec = atomFromAddr(sectIndex, toAddress, target, &offsetInTo);
+      if (ec)
+        return ec;
+      *addend = value - toAddress;
+    }
+  }
+  
+  return std::error_code();
+}
+
+
+
 void KindHandler_arm::applyFixup(Reference::KindNamespace ns,
                                  Reference::KindArch arch,
                                  Reference::KindValue kindValue,
@@ -663,36 +1044,49 @@ void KindHandler_arm::applyFixup(Referen
     return;
   assert(arch == Reference::KindArch::ARM);
   //int32_t *loc32 = reinterpret_cast<int32_t*>(location);
+  // FIXME: these writes may need a swap.
   switch (kindValue) {
-  case ARM_THUMB_RELOC_BR22:
+  case thumb_b22:
+      // FIXME
+    break;
+  case thumb_movw:
+      // FIXME
+      break;
+  case thumb_movt:
       // FIXME
       break;
-  case ARM_RELOC_BR24:
+  case thumb_movw_funcRel:
       // FIXME
       break;
-  case LLD_ARM_RELOC_THUMB_ABS_LO16:
+  case thumb_movt_funcRel:
       // FIXME
       break;
-  case LLD_ARM_RELOC_THUMB_ABS_HI16:
+  case arm_b24:
       // FIXME
       break;
-  case LLD_ARM_RELOC_THUMB_REL_LO16:
+  case arm_movw:
       // FIXME
       break;
-  case LLD_ARM_RELOC_THUMB_REL_HI16:
+  case arm_movt:
       // FIXME
       break;
-  case LLD_ARM_RELOC_ABS32:
+  case arm_movw_funcRel:
       // FIXME
       break;
-  case LLD_ARM_RELOC_POINTER32:
+  case arm_movt_funcRel:
       // FIXME
       break;
-  case LLD_ARM_RELOC_LAZY_TARGET:
-  case LLD_ARM_RELOC_LAZY_IMMEDIATE:
+  case pointer32:
+      // FIXME
+      break;
+  case delta32:
+      // FIXME
+      break;
+  case lazyPointer:
+  case lazyImmediateLocation:
       // do nothing
       break;
-  default:
+  case invalid:
     llvm_unreachable("invalid ARM Reference Kind");
       break;
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h?rev=212306&r1=212305&r2=212306&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h Thu Jul  3 19:11:09 2014
@@ -23,18 +23,6 @@ namespace lld {
 namespace mach_o {
 
 
-// Additional Reference Kind values used internally.
-enum {
-  LLD_ARM_RELOC_THUMB_ABS_LO16 = 100, // thumb movw of absolute address
-  LLD_ARM_RELOC_THUMB_ABS_HI16 = 101, // thumb movt of absolute address
-  LLD_ARM_RELOC_THUMB_REL_LO16 = 102, // thumb movw of (target - pc)
-  LLD_ARM_RELOC_THUMB_REL_HI16 = 103, // thumb movt of (target - pc)
-  LLD_ARM_RELOC_ABS32          = 104, // 32-bit constant pointer
-  LLD_ARM_RELOC_POINTER32      = 105, // 32-bit data pointer
-  LLD_ARM_RELOC_LAZY_TARGET    = 106,
-  LLD_ARM_RELOC_LAZY_IMMEDIATE = 107,
-};
-
 ///
 /// The KindHandler class is the abstract interface to Reference::Kind
 /// values for mach-o files.  Particular Kind values (e.g. 3) has a different
@@ -52,7 +40,7 @@ public:
   virtual bool isLazyTarget(const Reference &) = 0;
   
   /// Returns true if the specified relocation is paired to the next relocation. 
-  virtual bool isPairedReloc(const normalized::Relocation &);
+  virtual bool isPairedReloc(const normalized::Relocation &) = 0;
   
   /// Prototype for a helper function.  Given a sectionIndex and address, 
   /// finds the atom and offset with that atom of that address. 
@@ -63,7 +51,7 @@ public:
   /// Prototype for a helper function.  Given a symbolIndex, finds the atom
   /// representing that symbol.
   typedef std::function<std::error_code (uint32_t symbolIndex, 
-                        const lld::Atom**)> FindAtomBySymbolIndex;
+                        const lld::Atom **)> FindAtomBySymbolIndex;
   
   /// Analyzes a relocation from a .o file and returns the info
   /// (kind, target, addend) needed to instantiate a Reference.
@@ -78,7 +66,7 @@ public:
                            FindAtomBySymbolIndex atomFromSymbolIndex,
                            Reference::KindValue *kind, 
                            const lld::Atom **target, 
-                           Reference::Addend *addend);
+                           Reference::Addend *addend) = 0;
 
   /// Analyzes a pair of relocations from a .o file and returns the info
   /// (kind, target, addend) needed to instantiate a Reference.
@@ -94,7 +82,7 @@ public:
                            FindAtomBySymbolIndex atomFromSymbolIndex,
                            Reference::KindValue *kind, 
                            const lld::Atom **target, 
-                           Reference::Addend *addend);
+                           Reference::Addend *addend) = 0;
                            
   /// Fixup an atom when generating a final linked binary.
   virtual void applyFixup(Reference::KindNamespace ns, Reference::KindArch arch,
@@ -278,11 +266,63 @@ public:
   bool isPointer(const Reference &) override;
   bool isLazyImmediate(const Reference &) override;
   bool isLazyTarget(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;
+
   void applyFixup(Reference::KindNamespace ns, Reference::KindArch arch,
                   Reference::KindValue kindValue, uint64_t addend,
                   uint8_t *location, uint64_t fixupAddress,
                   uint64_t targetAddress, uint64_t inAtomAddress) 
                   override;
+
+private:
+  enum : Reference::KindValue {
+    invalid,               /// for error condition
+
+    // Kinds found in mach-o .o files:
+    thumb_b22,             /// ex: bl _foo
+    thumb_movw,            /// ex: movw	r1, :lower16:_foo
+    thumb_movt,            /// ex: movt	r1, :lower16:_foo
+    thumb_movw_funcRel,    /// ex: movw	r1, :lower16:(_foo-(L1+4))
+    thumb_movt_funcRel,    /// ex: movt r1, :upper16:(_foo-(L1+4))
+    arm_b24,               /// ex: bl _foo
+    arm_movw,              /// ex: movw	r1, :lower16:_foo
+    arm_movt,              /// ex: movt	r1, :lower16:_foo
+    arm_movw_funcRel,      /// ex: movw	r1, :lower16:(_foo-(L1+4))
+    arm_movt_funcRel,      /// ex: movt r1, :upper16:(_foo-(L1+4))
+    pointer32,             /// ex: .long _foo
+    delta32,               /// ex: .long _foo - .
+
+    // Kinds introduced by Passes:
+    lazyPointer,           /// Location contains a lazy pointer.
+    lazyImmediateLocation, /// Location contains immediate value used in stub.
+  };
+
+  int32_t getDisplacementFromThumbBranch(uint32_t instruction);
+  int32_t getDisplacementFromArmBranch(uint32_t instruction);
+  uint16_t getWordFromThumbMov(uint32_t instruction);
+  uint16_t getWordFromArmMov(uint32_t instruction);
+  uint32_t clearThumbBit(uint32_t value, const Atom* target);
+
 };
 
 } // namespace mach_o

Added: lld/trunk/test/mach-o/parse-arm-relocs.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-arm-relocs.yaml?rev=212306&view=auto
==============================================================================
--- lld/trunk/test/mach-o/parse-arm-relocs.yaml (added)
+++ lld/trunk/test/mach-o/parse-arm-relocs.yaml Thu Jul  3 19:11:09 2014
@@ -0,0 +1,791 @@
+# RUN: lld -flavor darwin -arch armv7 -r -print_atoms %s -o %t  | FileCheck %s
+#
+# Test parsing of armv7 relocations.
+#
+#
+
+--- !mach-o
+arch:            armv7
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID:        false
+OS:              unknown
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    alignment:       2
+    address:         0x0000000000000000
+    content:         [ 0x00, 0xF0, 0x4A, 0xF8, 0x00, 0xF0, 0x4A, 0xF8, 
+                       0xFF, 0xF7, 0xFA, 0xFF, 0xFF, 0xF7, 0xFA, 0xFF, 
+                       0x40, 0xF2, 0x6E, 0x01, 0xC0, 0xF2, 0x00, 0x01, 
+                       0x40, 0xF2, 0x76, 0x02, 0xC0, 0xF2, 0x00, 0x02, 
+                       0x40, 0xF2, 0x29, 0x01, 0xC0, 0xF2, 0x00, 0x01, 
+                       0x79, 0x44, 0x40, 0xF2, 0x98, 0x03, 0xC0, 0xF2, 
+                       0x00, 0x03, 0x40, 0xF2, 0xA0, 0x04, 0xC0, 0xF2, 
+                       0x00, 0x04, 0x40, 0xF2, 0x53, 0x03, 0xC0, 0xF2, 
+                       0x00, 0x03, 0x40, 0xF2, 0x00, 0x05, 0xC0, 0xF2, 
+                       0x00, 0x05, 0x40, 0xF2, 0x08, 0x06, 0xC0, 0xF2, 
+                       0x00, 0x06, 0xC0, 0x46, 0x0F, 0x00, 0x00, 0xEB, 
+                       0x0F, 0x00, 0x00, 0xEB, 0xE7, 0xFF, 0xFF, 0xEB, 
+                       0xE7, 0xFF, 0xFF, 0xEB, 0x20, 0x10, 0x00, 0xE3, 
+                       0x00, 0x10, 0x40, 0xE3, 0x28, 0x20, 0x00, 0xE3, 
+                       0x00, 0x20, 0x40, 0xE3, 0x0F, 0x10, 0x81, 0xE0, 
+                       0x98, 0x30, 0x00, 0xE3, 0x00, 0x30, 0x40, 0xE3, 
+                       0xA0, 0x40, 0x00, 0xE3, 0x00, 0x40, 0x40, 0xE3, 
+                       0x00, 0x50, 0x00, 0xE3, 0x00, 0x50, 0x40, 0xE3, 
+                       0x08, 0x60, 0x00, 0xE3, 0x00, 0x60, 0x40, 0xE3 ]
+    relocations:
+      - offset:          0x00000094
+        type:            ARM_RELOC_HALF
+        length:          1
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000008
+        type:            ARM_RELOC_PAIR
+        length:          1
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000090
+        type:            ARM_RELOC_HALF
+        length:          0
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          0
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x0000008C
+        type:            ARM_RELOC_HALF
+        length:          1
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          1
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000088
+        type:            ARM_RELOC_HALF
+        length:          0
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          0
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000084
+        scattered:       true
+        type:            ARM_RELOC_HALF
+        length:          1
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x000000A0
+        type:            ARM_RELOC_PAIR
+        length:          1
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000080
+        scattered:       true
+        type:            ARM_RELOC_HALF
+        length:          0
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          0
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x0000007C
+        type:            ARM_RELOC_HALF
+        length:          1
+        pc-rel:          false
+        extern:          false
+        symbol:          2
+      - offset:          0x00000098
+        type:            ARM_RELOC_PAIR
+        length:          1
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000078
+        type:            ARM_RELOC_HALF
+        length:          0
+        pc-rel:          false
+        extern:          false
+        symbol:          2
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          0
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000070
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          1
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x00000028
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          1
+        pc-rel:          false
+        value:           0x00000078
+      - offset:          0x0000006C
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          0
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          0
+        pc-rel:          false
+        value:           0x00000078
+      - offset:          0x00000068
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          1
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x00000020
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          1
+        pc-rel:          false
+        value:           0x00000078
+      - offset:          0x00000064
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          0
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          0
+        pc-rel:          false
+        value:           0x00000078
+      - offset:          0x00000060
+        type:            ARM_RELOC_BR24
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          4
+      - offset:          0x0000005C
+        type:            ARM_RELOC_BR24
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          4
+      - offset:          0x00000058
+        scattered:       true
+        type:            ARM_RELOC_BR24
+        length:          2
+        pc-rel:          true
+        value:           0x00000098
+      - offset:          0x00000054
+        type:            ARM_RELOC_BR24
+        length:          2
+        pc-rel:          true
+        extern:          false
+        symbol:          2
+      - offset:          0x0000004E
+        type:            ARM_RELOC_HALF
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000008
+        type:            ARM_RELOC_PAIR
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x0000004A
+        type:            ARM_RELOC_HALF
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000046
+        type:            ARM_RELOC_HALF
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000042
+        type:            ARM_RELOC_HALF
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x0000003E
+        type:            ARM_RELOC_HALF
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+      - offset:          0x00000053
+        type:            ARM_RELOC_PAIR
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x0000003A
+        type:            ARM_RELOC_HALF
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000036
+        scattered:       true
+        type:            ARM_RELOC_HALF
+        length:          3
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x000000A0
+        type:            ARM_RELOC_PAIR
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000032
+        scattered:       true
+        type:            ARM_RELOC_HALF
+        length:          2
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x0000002E
+        type:            ARM_RELOC_HALF
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          2
+      - offset:          0x00000098
+        type:            ARM_RELOC_PAIR
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x0000002A
+        type:            ARM_RELOC_HALF
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          2
+      - offset:          0x00000000
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          16777215
+      - offset:          0x00000024
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          3
+        pc-rel:          false
+        value:           0x00000052
+      - offset:          0x00000028
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          3
+        pc-rel:          false
+        value:           0x0000002A
+      - offset:          0x00000020
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x00000052
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x0000002A
+      - offset:          0x0000001C
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          3
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x00000076
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          3
+        pc-rel:          false
+        value:           0x0000002A
+      - offset:          0x00000018
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x0000002A
+      - offset:          0x00000014
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          3
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x0000006E
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          3
+        pc-rel:          false
+        value:           0x0000002A
+      - offset:          0x00000010
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x00000098
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x0000002A
+      - offset:          0x0000000C
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          4
+      - offset:          0x00000008
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          4
+      - offset:          0x00000004
+        scattered:       true
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        value:           0x00000098
+      - offset:          0x00000000
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          false
+        symbol:          2
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    address:         0x0000000000000098
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
+                       0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x04, 0x00, 0x00, 0x00, 0xA8, 0xFF, 0xFF, 0xFF, 
+                       0xA8, 0xFF, 0xFF, 0xFF, 0x4D, 0xFF, 0xFF, 0xFF, 
+                       0x4D, 0xFF, 0xFF, 0xFF ]
+    relocations:
+      - offset:          0x00000020
+        scattered:       true
+        type:            ARM_RELOC_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x00000000
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x000000B8
+      - offset:          0x0000001C
+        scattered:       true
+        type:            ARM_RELOC_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x00000000
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x000000B4
+      - offset:          0x00000018
+        scattered:       true
+        type:            ARM_RELOC_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x00000054
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x000000B0
+      - offset:          0x00000014
+        scattered:       true
+        type:            ARM_RELOC_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x00000054
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x000000AC
+      - offset:          0x00000010
+        type:            ARM_RELOC_VANILLA
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x0000000C
+        type:            ARM_RELOC_VANILLA
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000008
+        scattered:       true
+        type:            ARM_RELOC_VANILLA
+        length:          2
+        pc-rel:          false
+        value:           0x00000000
+      - offset:          0x00000004
+        type:            ARM_RELOC_VANILLA
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+local-symbols:
+  - name:            _foo_thumb
+    type:            N_SECT
+    sect:            1
+    desc:            [ N_ARM_THUMB_DEF ]
+    value:           0x0000000000000000
+  - name:            _x
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000098
+  - name:            _t1
+    type:            N_SECT
+    sect:            1
+    desc:            [ N_ARM_THUMB_DEF ]
+    value:           0x0000000000000052
+  - name:            _foo_arm
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000054
+undefined-symbols: 
+  - name:            _undef
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+
+...
+
+# CHECK:  defined-atoms:
+# CHECK:    - name:            _x
+# CHECK:      type:            data
+# CHECK:      references:
+# CHECK:        - kind:            pointer32
+# CHECK:          offset:          4
+# CHECK:          target:          _foo_thumb
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            pointer32
+# CHECK:          offset:          8
+# CHECK:          target:          _foo_thumb
+# CHECK:          addend:          4
+# CHECK:        - kind:            pointer32
+# CHECK:          offset:          12
+# CHECK:          target:          _undef
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            pointer32
+# CHECK:          offset:          16
+# CHECK:          target:          _undef
+# CHECK:          addend:          4
+# CHECK:        - kind:            delta32
+# CHECK:          offset:          20
+# CHECK:          target:          _foo_arm
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            delta32
+# CHECK:          offset:          24
+# CHECK:          target:          _foo_arm
+# CHECK:          addend:          4
+# CHECK:        - kind:            delta32
+# CHECK:          offset:          28
+# CHECK:          target:          _foo_thumb
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            delta32
+# CHECK:          offset:          32
+# CHECK:          target:          _foo_thumb
+# CHECK:          addend:          4
+# CHECK:    - name:            _foo_thumb
+# CHECK:      references:
+# CHECK:        - kind:            thumb_b22
+# CHECK:          offset:          0
+# CHECK:          target:          _x
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            thumb_b22
+# CHECK:          offset:          4
+# CHECK:          target:          _x
+# CHECK:          addend:          4
+# CHECK:        - kind:            thumb_b22
+# CHECK:          offset:          8
+# CHECK:          target:          _undef
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            thumb_b22
+# CHECK:          offset:          12
+# CHECK:          target:          _undef
+# CHECK:          addend:          4
+# CHECK:        - kind:            thumb_movw_funcRel
+# CHECK:          offset:          16
+# CHECK:          target:          _x
+# CHECK:          addend:          -42
+# CHECK:        - kind:            thumb_movt_funcRel
+# CHECK:          offset:          20
+# CHECK:          target:          _x
+# CHECK:          addend:          -42
+# CHECK:        - kind:            thumb_movw_funcRel
+# CHECK:          offset:          24
+# CHECK:          target:          _x
+# CHECK:          addend:          -34
+# CHECK:        - kind:            thumb_movt_funcRel
+# CHECK:          offset:          28
+# CHECK:          target:          _x
+# CHECK:          addend:          -34
+# CHECK:        - kind:            thumb_movw_funcRel
+# CHECK:          offset:          32
+# CHECK:          target:          _t1
+# CHECK:          addend:          -42
+# CHECK:        - kind:            thumb_movt_funcRel
+# CHECK:          offset:          36
+# CHECK:          target:          _t1
+# CHECK:          addend:          -42
+# CHECK:        - kind:            thumb_movw
+# CHECK:          offset:          42
+# CHECK:          target:          _x
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            thumb_movt
+# CHECK:          offset:          46
+# CHECK:          target:          _x
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            thumb_movw
+# CHECK:          offset:          50
+# CHECK:          target:          _x
+# CHECK:          addend:          8
+# CHECK:        - kind:            thumb_movt
+# CHECK:          offset:          54
+# CHECK:          target:          _x
+# CHECK:          addend:          8
+# CHECK:        - kind:            thumb_movw
+# CHECK:          offset:          58
+# CHECK:          target:          _t1
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            thumb_movt
+# CHECK:          offset:          62
+# CHECK:          target:          _t1
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            thumb_movw
+# CHECK:          offset:          66
+# CHECK:          target:          _undef
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            thumb_movt
+# CHECK:          offset:          70
+# CHECK:          target:          _undef
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            thumb_movw
+# CHECK:          offset:          74
+# CHECK:          target:          _undef
+# CHECK:          addend:          8
+# CHECK:        - kind:            thumb_movt
+# CHECK:          offset:          78
+# CHECK:          target:          _undef
+# CHECK:          addend:          8
+# CHECK:    - name:            _t1
+# CHECK:      content:         [ C0, 46 ]
+# CHECK:    - name:            _foo_arm
+# CHECK:      references:
+# CHECK:        - kind:            arm_b24
+# CHECK:          offset:          0
+# CHECK:          target:          _x
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            arm_b24
+# CHECK:          offset:          4
+# CHECK:          target:          _x
+# CHECK:          addend:          4
+# CHECK:        - kind:            arm_b24
+# CHECK:          offset:          8
+# CHECK:          target:          _undef
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            arm_b24
+# CHECK:          offset:          12
+# CHECK:          target:          _undef
+# CHECK:          addend:          4
+# CHECK:        - kind:            arm_movw_funcRel
+# CHECK:          offset:          16
+# CHECK:          target:          _x
+# CHECK:          addend:          -36
+# CHECK:        - kind:            arm_movt_funcRel
+# CHECK:          offset:          20
+# CHECK:          target:          _x
+# CHECK:          addend:          -36
+# CHECK:        - kind:            arm_movw_funcRel
+# CHECK:          offset:          24
+# CHECK:          target:          _x
+# CHECK:          addend:          -28
+# CHECK:        - kind:            arm_movt_funcRel
+# CHECK:          offset:          28
+# CHECK:          target:          _x
+# CHECK:          addend:          -28
+# CHECK:        - kind:            arm_movw
+# CHECK:          offset:          36
+# CHECK:          target:          _x
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            arm_movt
+# CHECK:          offset:          40
+# CHECK:          target:          _x
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            arm_movw
+# CHECK:          offset:          44
+# CHECK:          target:          _x
+# CHECK:          addend:          8
+# CHECK:        - kind:            arm_movt
+# CHECK:          offset:          48
+# CHECK:          target:          _x
+# CHECK:          addend:          8
+# CHECK:        - kind:            arm_movw
+# CHECK:          offset:          52
+# CHECK:          target:          _undef
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            arm_movt
+# CHECK:          offset:          56
+# CHECK:          target:          _undef
+# CHECK-NOT:      addend:
+# CHECK:        - kind:            arm_movw
+# CHECK:          offset:          60
+# CHECK:          target:          _undef
+# CHECK:          addend:          8
+# CHECK:        - kind:            arm_movt
+# CHECK:          offset:          64
+# CHECK:          target:          _undef
+# CHECK:          addend:          8
+# CHECK:  undefined-atoms: 
+# CHECK:    - name:            _undef
+
+
+
+
+#	.align	2
+#	.code	16
+#  .thumb_func	_foo_thumb
+#_foo_thumb:
+#  bl    _x
+#  bl    _x+4
+#  bl    _undef
+#  bl    _undef+4
+#  movw	r1, :lower16:(_x-L1)
+# 	movt	r1, :upper16:(_x-L1)
+#  movw	r2, :lower16:(_x+8-L1)
+# 	movt	r2, :upper16:(_x+8-L1)
+#  movw	r1, :lower16:(_t1-L1)
+# 	movt	r1, :upper16:(_t1-L1)
+#	add	r1, pc
+#L1:
+#	movw	r3, :lower16:_x
+#	movt	r3, :upper16:_x
+#	movw	r4, :lower16:_x+8
+#	movt	r4, :upper16:_x+8
+#	movw	r3, :lower16:_t1
+#	movt	r3, :upper16:_t1
+#	movw	r5, :lower16:_undef
+#	movt	r5, :upper16:_undef
+#	movw	r6, :lower16:_undef+8
+#	movt	r6, :upper16:_undef+8
+#
+#  .thumb_func	_t1
+#_t1:
+#  nop
+#
+#
+#	.code	32
+#  .align 2  
+#_foo_arm:
+#  bl    _x
+#  bl    _x+4
+#  bl    _undef
+#  bl    _undef+4
+#  movw	r1, :lower16:(_x-L2)
+# 	movt	r1, :upper16:(_x-L2)
+#  movw	r2, :lower16:(_x+8-L2)
+# 	movt	r2, :upper16:(_x+8-L2)
+#	add	r1, pc
+#L2:
+#	movw	r3, :lower16:_x
+#	movt	r3, :upper16:_x
+#	movw	r4, :lower16:_x+8
+#	movt	r4, :upper16:_x+8
+#	movw	r5, :lower16:_undef
+#	movt	r5, :upper16:_undef
+#	movw	r6, :lower16:_undef+8
+#	movt	r6, :upper16:_undef+8
+#  
+#
+#  .data
+#_x:  .long 0
+#    .long _foo_thumb
+#    .long _foo_thumb+4
+#    .long _undef
+#    .long _undef+4
+#    .long _foo_arm - .
+#    .long _foo_arm+4- .
+#    .long _foo_thumb - .
+#    .long _foo_thumb+4 - .
+#





More information about the llvm-commits mailing list