[lld] r211921 - [mach-o] refactor x86_64 relocation handling.

Nick Kledzik kledzik at apple.com
Fri Jun 27 11:25:01 PDT 2014


Author: kledzik
Date: Fri Jun 27 13:25:01 2014
New Revision: 211921

URL: http://llvm.org/viewvc/llvm-project?rev=211921&view=rev
Log:
[mach-o] refactor x86_64 relocation handling.

This is first step in reworking how mach-o relocations are processed.
The existing KindHandler is going to become a delgate/helper object for
processing architecture specific references.  The KindHandler knows how
to convert mach-o relocations into References and back, as well, as fixing
up the content the relocation is on.

One of the messy things about mach-o relocations is that they sometime 
come in pairs, but the pairs still convert to one lld::Reference. So, the
conversion has to detect pairs (arch specific) and change the stride.




Added:
    lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml
    lld/trunk/test/mach-o/parse-text-relocs-x86_64.yaml
Modified:
    lld/trunk/lib/ReaderWriter/MachO/Atoms.h
    lld/trunk/lib/ReaderWriter/MachO/File.h
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp
    lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h
    lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp
    lld/trunk/test/darwin/hello-world.objtxt
    lld/trunk/test/darwin/native-and-mach-o.objtxt
    lld/trunk/test/mach-o/parse-cfstring64.yaml
    lld/trunk/test/mach-o/parse-initializers64.yaml

Modified: lld/trunk/lib/ReaderWriter/MachO/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/Atoms.h?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/Atoms.h Fri Jun 27 13:25:01 2014
@@ -49,11 +49,17 @@ public:
   }
 
   ArrayRef<uint8_t> rawContent() const override {
-    // Zerofill atoms have a content pointer which is null.
-    assert(_content.data() != nullptr);
+    // Note: Zerofill atoms have a content pointer which is null.
     return _content;
   }
 
+  void addReference(uint32_t offsetInAtom, uint16_t relocType, 
+               const Atom *target, Reference::Addend addend, 
+               Reference::KindArch arch = Reference::KindArch::x86_64,
+               Reference::KindNamespace ns = Reference::KindNamespace::mach_o) {
+    SimpleDefinedAtom::addReference(ns, arch, relocType, offsetInAtom, target, addend);
+  }
+  
 private:
   const StringRef _name;
   const ArrayRef<uint8_t> _content;

Modified: lld/trunk/lib/ReaderWriter/MachO/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/File.h?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/File.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/File.h Fri Jun 27 13:25:01 2014
@@ -10,6 +10,8 @@
 #ifndef LLD_READER_WRITER_MACHO_FILE_H
 #define LLD_READER_WRITER_MACHO_FILE_H
 
+#include "llvm/ADT/StringMap.h"
+
 #include "Atoms.h"
 
 #include "lld/Core/Simple.h"
@@ -17,13 +19,19 @@
 namespace lld {
 namespace mach_o {
 
+using lld::mach_o::normalized::Section;
+
 class MachOFile : public SimpleFile {
 public:
   MachOFile(StringRef path) : SimpleFile(path) {}
 
   void addDefinedAtom(StringRef name, Atom::Scope scope,
                       DefinedAtom::ContentType type, DefinedAtom::Merge merge,
-                      ArrayRef<uint8_t> content, bool copyRefs) {
+                      uint64_t sectionOffset, uint64_t contentSize, 
+                      bool copyRefs, const Section *inSection) {
+    assert(sectionOffset+contentSize <= inSection->content.size());
+    ArrayRef<uint8_t> content = inSection->content.slice(sectionOffset, 
+                                                        contentSize);
     if (copyRefs) {
       // Make a copy of the atom's name and content that is owned by this file.
       name = name.copy(_allocator);
@@ -33,13 +41,18 @@ public:
         new (_allocator) MachODefinedAtom(*this, name, scope, type, merge,
                                           content);
     addAtom(*atom);
+    _sectionAtoms[inSection].push_back({sectionOffset, atom});
   }
 
   void addDefinedAtomInCustomSection(StringRef name, Atom::Scope scope,
                       DefinedAtom::ContentType type, DefinedAtom::Merge merge,
-                      ArrayRef<uint8_t> content, StringRef sectionName,
-                      bool copyRefs) {
-    if (copyRefs) {
+                      uint64_t sectionOffset, uint64_t contentSize, 
+                      StringRef sectionName, bool copyRefs, 
+                      const Section *inSection) {
+    assert(sectionOffset+contentSize <= inSection->content.size());
+    ArrayRef<uint8_t> content = inSection->content.slice(sectionOffset, 
+                                                        contentSize);
+   if (copyRefs) {
       // Make a copy of the atom's name and content that is owned by this file.
       name = name.copy(_allocator);
       content = content.copy(_allocator);
@@ -49,10 +62,12 @@ public:
         new (_allocator) MachODefinedCustomSectionAtom(*this, name, scope, type, 
                                                   merge, content, sectionName);
     addAtom(*atom);
+    _sectionAtoms[inSection].push_back({sectionOffset, atom});
   }
 
-  void addZeroFillDefinedAtom(StringRef name, Atom::Scope scope, uint64_t size,
-                              bool copyRefs) {
+  void addZeroFillDefinedAtom(StringRef name, Atom::Scope scope,
+                              uint64_t sectionOffset, uint64_t size,
+                              bool copyRefs, const Section *inSection) {
     if (copyRefs) {
       // Make a copy of the atom's name and content that is owned by this file.
       name = name.copy(_allocator);
@@ -60,6 +75,7 @@ public:
     MachODefinedAtom *atom =
         new (_allocator) MachODefinedAtom(*this, name, scope, size);
     addAtom(*atom);
+    _sectionAtoms[inSection].push_back({sectionOffset, atom});
   }
 
   void addUndefinedAtom(StringRef name, bool copyRefs) {
@@ -70,6 +86,7 @@ public:
     SimpleUndefinedAtom *atom =
         new (_allocator) SimpleUndefinedAtom(*this, name);
     addAtom(*atom);
+    _undefAtoms[name] = atom;
   }
 
   void addTentativeDefAtom(StringRef name, Atom::Scope scope, uint64_t size,
@@ -81,13 +98,58 @@ public:
     MachOTentativeDefAtom *atom =
         new (_allocator) MachOTentativeDefAtom(*this, name, scope, size, align);
     addAtom(*atom);
+    _undefAtoms[name] = atom;
   }
-
-
+  
+  /// Search this file for an the atom from 'section' that covers
+  /// 'offsetInSect'.  Returns nullptr is no atom found.
+  MachODefinedAtom *findAtomCoveringAddress(const Section &section,
+                                            uint64_t offsetInSect,
+                                            uint32_t *foundOffsetAtom=nullptr) {
+    auto pos = _sectionAtoms.find(&section);
+    if (pos == _sectionAtoms.end())
+      return nullptr;
+    auto vec = pos->second;
+    assert(offsetInSect < section.content.size());
+    // Vector of atoms for section are already sorted, so do binary search.
+    auto atomPos = std::lower_bound(vec.begin(), vec.end(), offsetInSect, 
+        [offsetInSect](const SectionOffsetAndAtom &ao, 
+                       uint64_t targetAddr) -> bool {
+          // Each atom has a start offset of its slice of the
+          // section's content. This compare function must return true
+          // iff the atom's range is before the offset being searched for.
+          uint64_t atomsEndOffset = ao.offset+ao.atom->rawContent().size();
+          return (atomsEndOffset <= offsetInSect);
+        });
+    if (atomPos == vec.end())
+      return nullptr;
+    if (foundOffsetAtom)
+      *foundOffsetAtom = offsetInSect - atomPos->offset;
+    return atomPos->atom;
+  }
+  
+  /// Searches this file for an UndefinedAtom named 'name'. Returns
+  /// nullptr is no such atom found.
+  const lld::Atom *findUndefAtom(StringRef name) {
+    auto pos = _undefAtoms.find(name);
+    if (pos == _undefAtoms.end())
+      return nullptr;
+    return pos->second;
+  }
+  
 private:
-  llvm::BumpPtrAllocator _allocator;
+  struct SectionOffsetAndAtom { uint64_t offset;  MachODefinedAtom *atom; };
+  typedef llvm::DenseMap<const normalized::Section *, 
+                         std::vector<SectionOffsetAndAtom>>  SectionToAtoms;
+  typedef llvm::StringMap<const lld::Atom *> NameToAtom;
+
+  llvm::BumpPtrAllocator  _allocator;
+  SectionToAtoms          _sectionAtoms;
+  NameToAtom              _undefAtoms;
 };
 
+
+
 } // end namespace mach_o
 } // end namespace lld
 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp Fri Jun 27 13:25:01 2014
@@ -339,7 +339,7 @@ readBinary(std::unique_ptr<MemoryBuffer>
           sout.value = sin->n_value;
           if (sout.type == N_UNDF)
             f->undefinedSymbols.push_back(sout);
-          else if (sout.scope == (SymbolScope)N_EXT)
+          else if (sin->n_type & N_EXT)
             f->globalSymbols.push_back(sout);
           else
             f->localSymbols.push_back(sout);

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Fri Jun 27 13:25:01 2014
@@ -498,6 +498,7 @@ void Util::copySegmentInfo(NormalizedFil
 }
 
 void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
+  const bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
   // Add new empty section to end of file.sections.
   Section temp;
   file.sections.push_back(std::move(temp));
@@ -528,9 +529,14 @@ void Util::appendSection(SectionInfo *si
       if ( ref->target() != nullptr )
         targetAddress = _atomToAddress[ref->target()];
       uint64_t fixupAddress = _atomToAddress[ai.atom] + offset;
-      _context.kindHandler().applyFixup(
+      if ( rMode ) {
+        // FIXME: Need a handler method to update content for .o file
+        // output and any needed section relocations.
+      } else {
+        _context.kindHandler().applyFixup(
           ref->kindNamespace(), ref->kindArch(), ref->kindValue(),
           ref->addend(), &atomContent[offset], fixupAddress, targetAddress);
+      }
     }
   }
 }

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Fri Jun 27 13:25:01 2014
@@ -24,11 +24,13 @@
 #include "MachONormalizedFileBinaryUtils.h"
 #include "File.h"
 #include "Atoms.h"
+#include "ReferenceKinds.h"
 
 #include "lld/Core/Error.h"
 #include "lld/Core/LLVM.h"
 
 #include "llvm/Support/MachO.h"
+#include "llvm/Support/Format.h"
 
 using namespace llvm::MachO;
 using namespace lld::mach_o::normalized;
@@ -57,12 +59,14 @@ const MachORelocatableSectionToAtomType
   ENTRY("",       "",                 S_CSTRING_LITERALS, typeCString),
   ENTRY("__TEXT", "__ustring",        S_REGULAR,          typeUTF16String),
   ENTRY("__TEXT", "__const",          S_REGULAR,          typeConstant),
+  ENTRY("__TEXT", "__const_coal",     S_COALESCED,        typeConstant),
   ENTRY("__TEXT", "__eh_frame",       S_COALESCED,        typeCFI),
   ENTRY("__TEXT", "__literal4",       S_4BYTE_LITERALS,   typeLiteral4),
   ENTRY("__TEXT", "__literal8",       S_8BYTE_LITERALS,   typeLiteral8),
   ENTRY("__TEXT", "__literal16",      S_16BYTE_LITERALS,  typeLiteral16),
   ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR,          typeLSDA),
   ENTRY("__DATA", "__data",           S_REGULAR,          typeData),
+  ENTRY("__DATA", "__datacoal_nt",    S_COALESCED,        typeData),
   ENTRY("__DATA", "__const",          S_REGULAR,          typeConstData),
   ENTRY("__DATA", "__cfstring",       S_REGULAR,          typeCFString),
   ENTRY("__DATA", "__mod_init_func",  S_MOD_INIT_FUNC_POINTERS,
@@ -108,7 +112,8 @@ enum AtomizeModel {
   atomizeUTF8,
   atomizeUTF16,
   atomizeCFI,
-  atomizeCU
+  atomizeCU,
+  atomizeCFString
 };
 
 /// Returns info on how to atomize a section of the specified ContentType.
@@ -151,8 +156,8 @@ void sectionParseInfo(DefinedAtom::Conte
                                                             atomizeFixedSize),
     ENTRY(typeLiteral16,        16, scopeLinkageUnit,     mergeByContent, 
                                                             atomizeFixedSize),
-    ENTRY(typeCFString,         16, scopeLinkageUnit,     mergeByContent, 
-                                                            atomizeFixedSize),
+    ENTRY(typeCFString,          4, scopeLinkageUnit,     mergeByContent, 
+                                                            atomizeCFString),
     ENTRY(typeInitializerPtr,    4, scopeTranslationUnit, mergeNo, 
                                                             atomizePointerSize),
     ENTRY(typeTerminatorPtr,     4, scopeTranslationUnit, mergeNo, 
@@ -218,12 +223,12 @@ void atomFromSymbol(DefinedAtom::Content
   // Mach-O symbol table does have size in it. Instead the size is the
   // difference between this and the next symbol.
   uint64_t size = nextSymbolAddr - symbolAddr;
+  uint64_t offset = symbolAddr - section.address;
   if (section.type == llvm::MachO::S_ZEROFILL) {
-    file.addZeroFillDefinedAtom(symbolName, symbolScope, size, copyRefs);
+    file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size, copyRefs, 
+                                &section);
   } else {
-    uint64_t offset = symbolAddr - section.address;
-    ArrayRef<uint8_t> atomContent = section.content.slice(offset, size);
-    DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF) 
+    DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF)
                               ? DefinedAtom::mergeAsWeak : DefinedAtom::mergeNo;
     if (atomType == DefinedAtom::typeUnknown) {
       // Mach-O needs a segment and section name.  Concatentate those two
@@ -232,14 +237,15 @@ void atomFromSymbol(DefinedAtom::Content
       std::string segSectName = section.segmentName.str()
                                 + "/" + section.sectionName.str();
       file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType,
-                                         merge, atomContent, segSectName, true);
+                                         merge, offset, size, segSectName, true,
+                                         &section);
     } else {
-      if ((atomType == lld::DefinedAtom::typeCode) && 
+      if ((atomType == lld::DefinedAtom::typeCode) &&
           (symbolDescFlags & N_SYMBOL_RESOLVER)) {
-       atomType = lld::DefinedAtom::typeResolver;
+        atomType = lld::DefinedAtom::typeResolver;
       }
       file.addDefinedAtom(symbolName, symbolScope, atomType, merge,
-                          atomContent, copyRefs);
+                          offset, size, copyRefs, &section);
     }
   }
 }
@@ -264,10 +270,14 @@ std::error_code processSymboledSection(D
   // Sort symbols.
   std::sort(symbols.begin(), symbols.end(),
             [](const Symbol *lhs, const Symbol *rhs) -> bool {
+              if (lhs == rhs)
+                return false;
               // First by address.
-              if (lhs->value != rhs->value)
-                return lhs->value < rhs->value;
-              // If same address, one is an alias.  Sort by scope.
+              uint64_t lhsAddr = lhs->value;
+              uint64_t rhsAddr = rhs->value;
+              if (lhsAddr != rhsAddr)
+                return lhsAddr < rhsAddr;
+               // If same address, one is an alias so sort by scope.
               Atom::Scope lScope = atomScope(lhs->scope);
               Atom::Scope rScope = atomScope(rhs->scope);
               if (lScope != rScope)
@@ -278,19 +288,25 @@ std::error_code processSymboledSection(D
 
   // Debug logging of symbols.
   //for (const Symbol *sym : symbols)
-  //  llvm::errs() << "sym: " << sym->value << ", " << sym->name << "\n";
+  //  llvm::errs() << "  sym: " 
+  //    << llvm::format("0x%08llx ", (uint64_t)sym->value) 
+  //    << ", " << sym->name << "\n";
 
   // If section has no symbols and no content, there are no atoms.
   if (symbols.empty() && section.content.empty())
     return std::error_code();
 
-  uint64_t anonAtomEnd = symbols.empty()
-                             ? section.address + section.content.size()
-                             : (uint64_t)symbols.front()->value;
-  if (anonAtomEnd != section.address) {
+  if (symbols.empty()) {
+    // Section has no symbols, put all content in one anoymous atom.
+    atomFromSymbol(atomType, section, file, section.address, StringRef(),
+                  0, Atom::scopeTranslationUnit,
+                  section.address + section.content.size(), copyRefs);
+  }
+  else if (symbols.front()->value != section.address) {
     // Section has anonymous content before first symbol.
-    atomFromSymbol(atomType, section, file, section.address, StringRef(), 0,
-                   Atom::scopeTranslationUnit, anonAtomEnd, copyRefs);
+    atomFromSymbol(atomType, section, file, section.address, StringRef(),
+                   0, Atom::scopeTranslationUnit, symbols.front()->value,
+                   copyRefs);
   }
 
   const Symbol *lastSym = nullptr;
@@ -347,7 +363,7 @@ std::error_code processSection(DefinedAt
         break;
       case atomizePointerSize:
         // Break section up into atoms each the size of a pointer.
-        size = is64 ? 8 : 4;;
+        size = is64 ? 8 : 4;
         break;
       case atomizeUTF8:
         // Break section up into zero terminated c-strings.
@@ -387,6 +403,10 @@ std::error_code processSection(DefinedAt
         // Break section up into compact unwind entries.
         size = is64 ? 32 : 20;
         break;
+      case atomizeCFString:
+        // Break section up into compact unwind entries.
+        size = is64 ? 32 : 16;
+        break;
       case atomizeAtSymbols:
         break;
       }
@@ -396,21 +416,153 @@ std::error_code processSection(DefinedAt
                                      + " is malformed.  The last atom is "
                                      "not zero terminated.");
       }
-      ArrayRef<uint8_t> byteContent = section.content.slice(offset, size);
-      file.addDefinedAtom(StringRef(), scope, atomType, merge, byteContent,
-                          copyRefs);
+      file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size,
+                          copyRefs, &section);
       offset += size;
     }
   }
   return std::error_code();
 }
 
+// Walks all relocations for a section in a normalized .o file and
+// creates corresponding lld::Reference objects.
+std::error_code convertRelocs(const Section &section,
+                              const NormalizedFile &normalizedFile,
+                              MachOFile &file,
+                              KindHandler &handler) {
+  // Utility function for KindHandler to find atom by its address.
+  auto atomByAddr = [&] (uint32_t sectIndex, uint64_t addr,
+                         const lld::Atom **atom, Reference::Addend *addend)
+                         -> std::error_code {
+    if (sectIndex > normalizedFile.sections.size())
+      return make_dynamic_error_code(Twine("out of range section "
+                                     "index (") + Twine(sectIndex) + ")");
+    const Section &sect = normalizedFile.sections[sectIndex-1];
+    uint32_t offsetInTarget;
+    uint64_t offsetInSect = addr - sect.address;
+    *atom = file.findAtomCoveringAddress(sect, offsetInSect, &offsetInTarget);
+    *addend = offsetInTarget;
+    return std::error_code();
+  };
+
+  // Utility function for KindHandler to find atom by its symbol index.
+  auto atomBySymbol = [&] (uint32_t symbolIndex, const lld::Atom **result)
+                           -> std::error_code {
+    // Find symbol from index.
+    const Symbol *sym = nullptr;
+    uint32_t numLocal  = normalizedFile.localSymbols.size();
+    uint32_t numGlobal = normalizedFile.globalSymbols.size();
+    uint32_t numUndef  = normalizedFile.undefinedSymbols.size();
+    if (symbolIndex < numLocal) {
+      sym = &normalizedFile.localSymbols[symbolIndex];
+    } else if (symbolIndex < numLocal+numGlobal) {
+      sym = &normalizedFile.globalSymbols[symbolIndex-numLocal];
+    } else if (symbolIndex < numLocal+numGlobal+numUndef) {
+      sym = &normalizedFile.undefinedSymbols[symbolIndex-numLocal-numGlobal];
+    } else {
+      return make_dynamic_error_code(Twine("symbol index (")
+                                     + Twine(symbolIndex) + ") out of range");
+    }
+    // Find atom from symbol.
+    if ((sym->type & N_TYPE) == N_SECT) {
+      if (sym->sect > normalizedFile.sections.size())
+        return make_dynamic_error_code(Twine("symbol section index (")
+                                        + Twine(sym->sect) + ") out of range ");
+      const Section &symSection = normalizedFile.sections[sym->sect-1];
+      uint64_t targetOffsetInSect = sym->value - symSection.address;
+      MachODefinedAtom *target = file.findAtomCoveringAddress(symSection,
+                                                            targetOffsetInSect);
+      if (target) {
+        *result = target;
+        return std::error_code();
+      }
+      return make_dynamic_error_code(Twine("no atom found for defined symbol"));
+    } else if ((sym->type & N_TYPE) == N_UNDF) {
+      const lld::Atom *target = file.findUndefAtom(sym->name);
+      if (target) {
+        *result = target;
+        return std::error_code();
+      }
+      return make_dynamic_error_code(Twine("no undefined atom found for sym"));
+    } else {
+      // Search undefs
+      return make_dynamic_error_code(Twine("no atom found for symbol"));
+    }
+  };
+
+  const bool swap = !MachOLinkingContext::isHostEndian(normalizedFile.arch);
+  // Use old-school iterator so that paired relocations can be grouped.
+  for (auto it=section.relocations.begin(), e=section.relocations.end();
+                                                                it != e; ++it) {
+    const Relocation &reloc = *it;
+    // Find atom this relocation is in.
+    if (reloc.offset > section.content.size())
+      return make_dynamic_error_code(Twine("r_address (") + Twine(reloc.offset)
+                                    + ") is larger than section size ("
+                                    + Twine(section.content.size()) + ")");
+    uint32_t offsetInAtom;
+    MachODefinedAtom *inAtom = file.findAtomCoveringAddress(section,
+                                                            reloc.offset,
+                                                            &offsetInAtom);
+    if (!inAtom)
+      return make_dynamic_error_code(Twine("no atom at r_address"));
+    uint64_t fixupAddress = section.address + reloc.offset;
+
+    const lld::Atom *target = nullptr;
+    Reference::Addend addend = 0;
+    Reference::KindValue kind;
+    std::error_code relocErr;
+    if (handler.isPairedReloc(reloc)) {
+     // Handle paired relocations together.
+     relocErr = handler.getPairReferenceInfo(reloc, *++it, inAtom,
+                                              offsetInAtom, fixupAddress, swap,
+                                              atomByAddr, atomBySymbol, &kind,
+                                               &target, &addend);
+    }
+    else {
+      // Use KindHandler to convert relocation record into information
+      // needed to instantiate an lld::Reference object.
+      relocErr = handler.getReferenceInfo(reloc, inAtom, offsetInAtom,
+                                          fixupAddress,swap, atomByAddr,
+                                         atomBySymbol, &kind, &target, &addend);
+    }
+    if (relocErr) {
+      return make_dynamic_error_code(
+        Twine("bad relocation (") + relocErr.message()
+         + ") in section "
+         + section.segmentName + "/" + section.sectionName
+         + " (r_address=" + Twine::utohexstr(reloc.offset)
+         + ", r_type=" + Twine(reloc.type)
+         + ", r_extern=" + Twine(reloc.isExtern)
+         + ", r_length=" + Twine(reloc.length)
+         + ", r_pcrel=" + Twine(reloc.pcRel)
+         + (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
+                             : (Twine(", r_scattered=1, r_value=")
+                                + Twine(reloc.value)))
+         + ")" );
+    } else {
+      // Instantiate an lld::Reference object and add to its atom.
+      inAtom->addReference(offsetInAtom, kind, target, addend);
+    }
+  }
+  return std::error_code();
+}
+
+bool isDebugInfoSection(const Section &section) {
+  if ((section.attributes & S_ATTR_DEBUG) == 0)
+    return false;
+  return section.segmentName.equals("__DWARF");
+}
+
+/// Converts normalized mach-o file into an lld::File and lld::Atoms.
 ErrorOr<std::unique_ptr<lld::File>>
 normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
                         bool copyRefs) {
   std::unique_ptr<MachOFile> file(new MachOFile(path));
   // Create atoms from each section.
   for (auto &sect : normalizedFile.sections) {
+    if (isDebugInfoSection(sect))
+      continue;
     DefinedAtom::ContentType atomType = atomTypeFromSection(sect);
     if (std::error_code ec =
             processSection(atomType, sect, normalizedFile, *file, copyRefs))
@@ -427,6 +579,26 @@ normalizedObjectToAtoms(const Normalized
     }
   }
 
+  // TEMP BEGIN: until all KindHandlers switched to new interface.
+  if (normalizedFile.arch != lld::MachOLinkingContext::arch_x86_64)
+    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);
+  for (auto &sect : normalizedFile.sections) {
+    if (isDebugInfoSection(sect))
+      continue;
+    if (std::error_code ec = convertRelocs(sect, normalizedFile, *file, *handler))
+        return ec;
+  }
+
+  // Sort references in each atom to their canonical order.
+  for (const DefinedAtom* defAtom : file->defined()) {
+    reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
+  }
+
   return std::unique_ptr<File>(std::move(file));
 }
 

Modified: lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.cpp Fri Jun 27 13:25:01 2014
@@ -9,7 +9,7 @@
 
 
 #include "ReferenceKinds.h"
-
+#include "MachONormalizedFileBinaryUtils.h"
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -18,6 +18,7 @@
 #include "llvm/Support/ErrorHandling.h"
 
 using namespace llvm::MachO;
+using namespace lld::mach_o::normalized;
 
 namespace lld {
 namespace mach_o {
@@ -48,6 +49,64 @@ KindHandler::create(MachOLinkingContext:
   }
 }
 
+KindHandler::RelocPattern KindHandler::relocPattern(const Relocation &reloc) {
+  assert((reloc.type & 0xFFF0) == 0);
+  uint16_t result = reloc.type;
+  if (reloc.scattered)
+    result |= rScattered;
+  if (reloc.pcRel)
+    result |= rPcRel;
+  if (reloc.isExtern)
+    result |= rExtern;
+  switch(reloc.length) {
+  case 0:
+    break;
+  case 1:
+    result |= rLength2;
+    break;
+  case 2:
+    result |= rLength4;
+    break;
+  case 3:
+    result |= rLength8;
+    break;
+  default:
+    llvm_unreachable("bad r_length");
+  }
+  return result;
+}
+
+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
 //===----------------------------------------------------------------------===//
@@ -56,38 +115,226 @@ KindHandler_x86_64::~KindHandler_x86_64(
 }
 
 const Registry::KindStrings KindHandler_x86_64::kindStrings[] = {
-  LLD_KIND_STRING_ENTRY(X86_64_RELOC_UNSIGNED),
-  LLD_KIND_STRING_ENTRY(X86_64_RELOC_BRANCH),
-  LLD_KIND_STRING_ENTRY(X86_64_RELOC_SIGNED),
-  LLD_KIND_STRING_ENTRY(X86_64_RELOC_SIGNED_1),
-  LLD_KIND_STRING_ENTRY(X86_64_RELOC_SIGNED_2),
-  LLD_KIND_STRING_ENTRY(X86_64_RELOC_SIGNED_4),
-  LLD_KIND_STRING_ENTRY(X86_64_RELOC_GOT_LOAD),
-  LLD_KIND_STRING_ENTRY(X86_64_RELOC_GOT),
-  LLD_KIND_STRING_ENTRY(X86_64_RELOC_TLV),
-  LLD_KIND_STRING_ENTRY(LLD_X86_64_RELOC_GOT_LOAD_NOW_LEA),
-  LLD_KIND_STRING_ENTRY(LLD_X86_64_RELOC_TLV_NOW_LEA),
-  LLD_KIND_STRING_ENTRY(LLD_X86_64_RELOC_LAZY_TARGET),
-  LLD_KIND_STRING_ENTRY(LLD_X86_64_RELOC_LAZY_IMMEDIATE),
+  LLD_KIND_STRING_ENTRY(invalid),
+  LLD_KIND_STRING_ENTRY(branch32),
+  LLD_KIND_STRING_ENTRY(ripRel32),
+  LLD_KIND_STRING_ENTRY(ripRel32Minus1),
+  LLD_KIND_STRING_ENTRY(ripRel32Minus2),
+  LLD_KIND_STRING_ENTRY(ripRel32Minus4),
+  LLD_KIND_STRING_ENTRY(ripRel32Anon),
+  LLD_KIND_STRING_ENTRY(ripRel32GotLoad),
+  LLD_KIND_STRING_ENTRY(ripRel32GotLoadNowLea),
+  LLD_KIND_STRING_ENTRY(ripRel32Got),
+  LLD_KIND_STRING_ENTRY(lazyPointer),
+  LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
+  LLD_KIND_STRING_ENTRY(pointer64),
+  LLD_KIND_STRING_ENTRY(pointer64Anon),
+  LLD_KIND_STRING_ENTRY(delta32),
+  LLD_KIND_STRING_ENTRY(delta64),
+  LLD_KIND_STRING_ENTRY(delta32Anon),
+  LLD_KIND_STRING_ENTRY(delta64Anon),
   LLD_KIND_STRING_END
 };
-
+ 
 bool KindHandler_x86_64::isCallSite(const Reference &ref) {
-  return (ref.kindValue() == X86_64_RELOC_BRANCH);
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return false;
+  assert(ref.kindArch() == Reference::KindArch::x86_64);
+  return (ref.kindValue() == branch32);
 }
 
 bool KindHandler_x86_64::isPointer(const Reference &ref) {
-  return (ref.kindValue() == X86_64_RELOC_UNSIGNED);
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return false;
+  assert(ref.kindArch() == Reference::KindArch::x86_64);
+  return (ref.kindValue() == pointer64);
 }
 
 bool KindHandler_x86_64::isLazyImmediate(const Reference &ref) {
-  return (ref.kindValue() == LLD_X86_64_RELOC_LAZY_IMMEDIATE);
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return false;
+  assert(ref.kindArch() == Reference::KindArch::x86_64);
+  return (ref.kindValue() == lazyImmediateLocation);
 }
 
 bool KindHandler_x86_64::isLazyTarget(const Reference &ref) {
-  return (ref.kindValue() == LLD_X86_64_RELOC_LAZY_TARGET);
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return false;
+  assert(ref.kindArch() == Reference::KindArch::x86_64);
+  return (ref.kindValue() == lazyPointer);
+}
+
+bool KindHandler_x86_64::isPairedReloc(const Relocation &reloc) {
+  return (reloc.type == X86_64_RELOC_SUBTRACTOR);
+}
+
+static int32_t readS32(bool swap, const uint8_t *addr) {
+  return read32(swap, *reinterpret_cast<const uint32_t*>(addr));
+}
+
+static int64_t readS64(bool swap, const uint8_t *addr) {
+  return read64(swap, *reinterpret_cast<const uint64_t*>(addr));
+}
+
+Reference::KindValue 
+KindHandler_x86_64::kindFromReloc(const Relocation &reloc) {
+  switch(relocPattern(reloc)) {
+  case X86_64_RELOC_BRANCH   | rPcRel | rExtern | rLength4:
+    return branch32;
+  case X86_64_RELOC_SIGNED   | rPcRel | rExtern | rLength4:
+    return ripRel32;
+  case X86_64_RELOC_SIGNED   | rPcRel |           rLength4:
+    return ripRel32Anon;
+  case X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4:
+    return ripRel32Minus1;
+  case X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4:
+    return ripRel32Minus2;
+  case X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4:
+    return ripRel32Minus4;
+  case X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4:
+    return ripRel32GotLoad;
+  case X86_64_RELOC_GOT      | rPcRel | rExtern | rLength4:
+    return ripRel32Got;
+  case X86_64_RELOC_UNSIGNED          | rExtern | rLength8:
+    return pointer64;
+  case X86_64_RELOC_UNSIGNED                    | rLength8:
+    return pointer64Anon;
+  default:
+    return invalid;
+  }
+
+}
+
+
+std::error_code 
+KindHandler_x86_64::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;
+  *kind = kindFromReloc(reloc);
+  if (*kind == invalid)
+    return make_dynamic_error_code(Twine("unknown type"));
+  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
+  uint64_t targetAddress;
+  switch (*kind) {
+  case branch32:
+  case ripRel32:
+    if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = readS32(swap, fixupContent);
+    return std::error_code();
+  case ripRel32Minus1:
+    if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = readS32(swap, fixupContent) + 1;
+    return std::error_code();
+  case ripRel32Minus2:
+    if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = readS32(swap, fixupContent) + 2;
+    return std::error_code();
+  case ripRel32Minus4:
+    if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = readS32(swap, fixupContent) + 4;
+    return std::error_code();
+  case ripRel32Anon:
+    targetAddress = fixupAddress + 4 + readS32(swap, fixupContent);
+    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
+  case ripRel32GotLoad:
+  case ripRel32Got:
+    if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = 0;
+    return std::error_code();
+  case pointer64:
+    if (E ec = atomFromSymbolIndex(reloc.symbol, target))
+      return ec;
+    *addend = readS64(swap, fixupContent);
+    return std::error_code();
+  case pointer64Anon:
+    targetAddress = readS64(swap, fixupContent);
+    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
+  default:
+    llvm_unreachable("bad reloc kind");
+  }
+}
+
+
+Reference::KindValue 
+KindHandler_x86_64::kindFromRelocPair(const normalized::Relocation &reloc1,
+                                      const normalized::Relocation &reloc2) {
+  switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
+  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
+        X86_64_RELOC_UNSIGNED    | rExtern | rLength8):
+    return delta64;
+  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
+        X86_64_RELOC_UNSIGNED    | rExtern | rLength4):
+    return delta32;
+  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
+        X86_64_RELOC_UNSIGNED              | rLength8):
+    return delta64Anon;
+  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
+        X86_64_RELOC_UNSIGNED              | rLength4):
+    return delta32Anon;
+  default:
+    llvm_unreachable("bad reloc pairs");
+  }
+}
+
+
+std::error_code 
+KindHandler_x86_64::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) {
+  *kind = kindFromRelocPair(reloc1, reloc2);
+  if (*kind == invalid)
+    return make_dynamic_error_code(Twine("unknown pair"));
+  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
+  typedef std::error_code E;
+  uint64_t targetAddress;
+  const lld::Atom *fromTarget;
+  if (E ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget))
+    return ec;
+  if (fromTarget != inAtom)
+    return make_dynamic_error_code(Twine("pointer diff not in base atom"));
+  switch (*kind) {
+  case delta64:
+    if (E ec = atomFromSymbolIndex(reloc2.symbol, target))
+      return ec;
+    *addend = readS64(swap, fixupContent) + offsetInAtom;
+    return std::error_code();
+  case delta32:
+    if (E ec = atomFromSymbolIndex(reloc2.symbol, target))
+      return ec;
+    *addend = readS32(swap, fixupContent) + offsetInAtom;
+    return std::error_code();
+  case delta64Anon:
+    targetAddress = offsetInAtom + readS64(swap, fixupContent);
+    return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
+  case delta32Anon:
+    targetAddress = offsetInAtom + readS32(swap, fixupContent);
+    return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
+  default:
+    llvm_unreachable("bad reloc pair kind");
+  }
 }
 
+
+
 void KindHandler_x86_64::applyFixup(Reference::KindNamespace ns,
                                     Reference::KindArch arch,
                                     Reference::KindValue kindValue,
@@ -100,39 +347,43 @@ void KindHandler_x86_64::applyFixup(Refe
   int32_t *loc32 = reinterpret_cast<int32_t*>(location);
   uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
   switch (kindValue) {
-  case X86_64_RELOC_BRANCH:
-  case X86_64_RELOC_SIGNED:
-  case X86_64_RELOC_GOT_LOAD:
-  case X86_64_RELOC_GOT:
-  case X86_64_RELOC_TLV:
-      *loc32 = (targetAddress - (fixupAddress+4)) + addend;
-      break;
-  case X86_64_RELOC_UNSIGNED:
-      *loc64 = targetAddress + addend;
-      break;
-  case X86_64_RELOC_SIGNED_1:
-      *loc32 = (targetAddress - (fixupAddress+5)) + addend;
-      break;
-  case X86_64_RELOC_SIGNED_2:
-      *loc32 = (targetAddress - (fixupAddress+6)) + addend;
-      break;
-  case X86_64_RELOC_SIGNED_4:
-      *loc32 = (targetAddress - (fixupAddress+8)) + addend;
-      break;
-  case LLD_X86_64_RELOC_SIGNED_32:
-      *loc32 = (targetAddress - fixupAddress) + addend;
-      break;
-  case LLD_X86_64_RELOC_GOT_LOAD_NOW_LEA:
-  case LLD_X86_64_RELOC_TLV_NOW_LEA:
-      // Change MOVQ to LEA
-      assert(location[-2] == 0x8B);
-      location[-2] = 0x8D;
-      *loc32 = (targetAddress - (fixupAddress+4)) + addend;
-      break;
-  case LLD_X86_64_RELOC_LAZY_TARGET:
-  case LLD_X86_64_RELOC_LAZY_IMMEDIATE:
-      // do nothing
-      break;
+  case branch32:
+  case ripRel32:
+  case ripRel32Got:
+  case ripRel32GotLoad:
+    *loc32 = (targetAddress - (fixupAddress+4)) + addend;
+    break;
+  case pointer64:
+  case pointer64Anon:
+    *loc64 = targetAddress + addend;
+    break;
+  case ripRel32Minus1:
+    *loc32 = (targetAddress - (fixupAddress+5)) + addend;
+    break;
+  case ripRel32Minus2:
+    *loc32 = (targetAddress - (fixupAddress+6)) + addend;
+    break;
+  case ripRel32Minus4:
+    *loc32 = (targetAddress - (fixupAddress+8)) + addend;
+    break;
+  case delta32:
+  case delta32Anon:
+   *loc32 = (targetAddress - fixupAddress) + addend;
+    break;
+  case delta64:
+  case delta64Anon:
+    *loc64 = (targetAddress - fixupAddress) + addend;
+    break;
+  case ripRel32GotLoadNowLea:
+    // Change MOVQ to LEA
+    assert(location[-2] == 0x8B);
+    location[-2] = 0x8D;
+    *loc32 = (targetAddress - (fixupAddress+4)) + addend;
+    break;
+  case lazyPointer:
+  case lazyImmediateLocation:
+    // do nothing
+    break;
   default:
     llvm_unreachable("invalid x86_64 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=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ReferenceKinds.h Fri Jun 27 13:25:01 2014
@@ -8,6 +8,8 @@
 //===----------------------------------------------------------------------===//
 
 
+#include "MachONormalizedFile.h"
+
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Reference.h"
 #include "lld/ReaderWriter/MachOLinkingContext.h"
@@ -20,15 +22,9 @@
 namespace lld {
 namespace mach_o {
 
+
 // Additional Reference Kind values used internally.
 enum {
-  LLD_X86_64_RELOC_GOT_LOAD_NOW_LEA = 100,
-  LLD_X86_64_RELOC_TLV_NOW_LEA      = 101,
-  LLD_X86_64_RELOC_LAZY_TARGET      = 102,
-  LLD_X86_64_RELOC_LAZY_IMMEDIATE   = 103,
-  LLD_X86_64_RELOC_SIGNED_32        = 104,
-};
-enum {
   LLD_X86_RELOC_BRANCH32       = 100, // CALL or JMP 32-bit pc-rel
   LLD_X86_RELOC_ABS32          = 101, // 32-bit absolute addr in instruction
   LLD_X86_RELOC_FUNC_REL32     = 102, // 32-bit target from start of func
@@ -62,6 +58,53 @@ public:
   virtual bool isPointer(const Reference &) = 0;
   virtual bool isLazyImmediate(const Reference &) = 0;
   virtual bool isLazyTarget(const Reference &) = 0;
+  
+  /// Returns true if the specified relocation is paired to the next relocation. 
+  virtual bool isPairedReloc(const normalized::Relocation &);
+  
+  /// Prototype for a helper function.  Given a sectionIndex and address, 
+  /// finds the atom and offset with that atom of that address. 
+  typedef std::function<std::error_code (uint32_t sectionIndex, uint64_t addr, 
+                        const lld::Atom **, Reference::Addend *)> 
+                        FindAtomBySectionAndAddress;
+  
+  /// 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;
+  
+  /// Analyzes a relocation from a .o file and returns the info
+  /// (kind, target, addend) needed to instantiate a Reference.
+  /// Two helper functions are passed as parameters to find the target atom
+  /// given a symbol index or address.
+  virtual 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);
+
+  /// Analyzes a pair of relocations from a .o file and returns the info
+  /// (kind, target, addend) needed to instantiate a Reference.
+  /// Two helper functions are passed as parameters to find the target atom
+  /// given a symbol index or address.
+  virtual 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);
+                           
+  /// Fixup an atom when generating a final linked binary.
   virtual void applyFixup(Reference::KindNamespace ns, Reference::KindArch arch,
                           Reference::KindValue kindValue, uint64_t addend,
                           uint8_t *location, uint64_t fixupAddress,
@@ -69,6 +112,20 @@ public:
 
 protected:
   KindHandler();
+  
+  // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
+  typedef uint16_t RelocPattern;
+  enum {
+    rScattered = 0x8000,
+    rPcRel     = 0x4000,
+    rExtern    = 0x2000,
+    rLength1   = 0x0000,
+    rLength2   = 0x0100,
+    rLength4   = 0x0200,
+    rLength8   = 0x0300
+  };
+  static RelocPattern relocPattern(const normalized::Relocation &reloc);
+  
 };
 
 
@@ -82,10 +139,72 @@ 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;
+                           
   virtual void applyFixup(Reference::KindNamespace ns, Reference::KindArch arch,
                           Reference::KindValue kindValue, uint64_t addend,
                           uint8_t *location, uint64_t fixupAddress,
                           uint64_t targetAddress) override;
+
+private:
+  friend class X86_64LazyPointerAtom;
+  friend class X86_64StubHelperAtom;
+  friend class X86_64StubAtom;
+  friend class X86_64StubHelperCommonAtom;
+  friend class X86_64NonLazyPointerAtom;
+ 
+  enum : Reference::KindValue {
+    invalid,               /// for error condition
+    
+    // Kinds found in mach-o .o files:
+    branch32,              /// ex: call _foo
+    ripRel32,              /// ex: movq _foo(%rip), %rax
+    ripRel32Minus1,        /// ex: movb $0x12, _foo(%rip)
+    ripRel32Minus2,        /// ex: movw $0x1234, _foo(%rip)
+    ripRel32Minus4,        /// ex: movl $0x12345678, _foo(%rip)
+    ripRel32Anon,          /// ex: movq L1(%rip), %rax
+    ripRel32GotLoad,       /// ex: movq  _foo at GOTPCREL(%rip), %rax
+    ripRel32Got,           /// ex: pushq _foo at GOTPCREL(%rip)
+    pointer64,             /// ex: .quad _foo
+    pointer64Anon,         /// ex: .quad L1
+    delta64,               /// ex: .quad _foo - .
+    delta32,               /// ex: .long _foo - .
+    delta64Anon,           /// ex: .quad L1 - .
+    delta32Anon,           /// ex: .long L1 - .
+    
+    // Kinds introduced by Passes:
+    ripRel32GotLoadNowLea, /// Target of GOT load is in linkage unit so 
+                           ///  "movq  _foo at GOTPCREL(%rip), %rax" can be changed
+                           /// to "leaq _foo(%rip), %rax
+    lazyPointer,           /// Location contains a lazy pointer.
+    lazyImmediateLocation, /// Location contains immediate value used in stub.
+  };
+  
+  Reference::KindValue kindFromReloc(const normalized::Relocation &reloc);
+  Reference::KindValue kindFromRelocPair(const normalized::Relocation &reloc1,
+                                         const normalized::Relocation &reloc2);
+
+
 };
 
 class KindHandler_x86 : public KindHandler {

Modified: lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/StubAtoms_x86_64.hpp Fri Jun 27 13:25:01 2014
@@ -33,7 +33,8 @@ public:
   X86_64StubAtom(const File &file, const Atom &lazyPointer)
       : SimpleDefinedAtom(file) {
     this->addReference(Reference::KindNamespace::mach_o,
-                       Reference::KindArch::x86_64, X86_64_RELOC_SIGNED, 2,
+                       Reference::KindArch::x86_64, 
+                       KindHandler_x86_64::ripRel32, 2,
                        &lazyPointer, 0);
   }
 
@@ -66,11 +67,11 @@ public:
                              const Atom &binder)
       : SimpleDefinedAtom(file) {
     this->addReference(Reference::KindNamespace::mach_o,
-                       Reference::KindArch::x86_64, X86_64_RELOC_SIGNED, 3,
-                       &cache, 0);
+                       Reference::KindArch::x86_64, 
+                       KindHandler_x86_64::ripRel32, 3, &cache, 0);
     this->addReference(Reference::KindNamespace::mach_o,
-                       Reference::KindArch::x86_64, X86_64_RELOC_SIGNED, 11,
-                       &binder, 0);
+                       Reference::KindArch::x86_64, 
+                       KindHandler_x86_64::ripRel32, 11, &binder, 0);
   }
 
   ContentType contentType() const override {
@@ -105,9 +106,10 @@ public:
       : SimpleDefinedAtom(file) {
     this->addReference(Reference::KindNamespace::mach_o,
                        Reference::KindArch::x86_64,
-                       LLD_X86_64_RELOC_LAZY_IMMEDIATE, 1, this, 0);
+                       KindHandler_x86_64::lazyImmediateLocation, 1, this, 0);
     this->addReference(Reference::KindNamespace::mach_o,
-                       Reference::KindArch::x86_64, X86_64_RELOC_SIGNED, 6,
+                       Reference::KindArch::x86_64, 
+                       KindHandler_x86_64::ripRel32, 6,
                        &helperCommon, 0);
   }
 
@@ -141,11 +143,11 @@ public:
                         const Atom &shlib)
       : SimpleDefinedAtom(file) {
     this->addReference(Reference::KindNamespace::mach_o,
-                       Reference::KindArch::x86_64, X86_64_RELOC_UNSIGNED, 0,
-                       &helper, 0);
+                       Reference::KindArch::x86_64, 
+                       KindHandler_x86_64::pointer64, 0, &helper, 0);
     this->addReference(Reference::KindNamespace::mach_o,
                        Reference::KindArch::x86_64,
-                       LLD_X86_64_RELOC_LAZY_TARGET, 0, &shlib, 0);
+                       KindHandler_x86_64::lazyPointer, 0, &shlib, 0);
   }
 
   ContentType contentType() const override {
@@ -182,8 +184,8 @@ public:
   X86_64NonLazyPointerAtom(const File &file, const Atom &shlib)
       : SimpleDefinedAtom(file) {
     this->addReference(Reference::KindNamespace::mach_o,
-                       Reference::KindArch::x86_64, X86_64_RELOC_UNSIGNED, 0,
-                       &shlib, 0);
+                       Reference::KindArch::x86_64, 
+                       KindHandler_x86_64::pointer64, 0, &shlib, 0);
   }
 
   ContentType contentType() const override {

Modified: lld/trunk/test/darwin/hello-world.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/darwin/hello-world.objtxt?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/test/darwin/hello-world.objtxt (original)
+++ lld/trunk/test/darwin/hello-world.objtxt Fri Jun 27 13:25:01 2014
@@ -14,10 +14,10 @@ defined-atoms:
                            31, C0, 5D, C3 ]
       references:
       - offset:          7
-        kind:            X86_64_RELOC_SIGNED
+        kind:            ripRel32
         target:          LC1
       - offset:          12
-        kind:            X86_64_RELOC_BRANCH
+        kind:            branch32
         target:          _printf
 
     - ref-name:          LC1

Modified: lld/trunk/test/darwin/native-and-mach-o.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/darwin/native-and-mach-o.objtxt?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/test/darwin/native-and-mach-o.objtxt (original)
+++ lld/trunk/test/darwin/native-and-mach-o.objtxt Fri Jun 27 13:25:01 2014
@@ -13,7 +13,7 @@ defined-atoms:
                            00, 00, 00, 31, C0, 5D, C3 ]
       references:
       - offset:          7
-        kind:            X86_64_RELOC_BRANCH
+        kind:            branch32
         target:          _foo
 
 undefined-atoms:

Modified: lld/trunk/test/mach-o/parse-cfstring64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-cfstring64.yaml?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-cfstring64.yaml (original)
+++ lld/trunk/test/mach-o/parse-cfstring64.yaml Fri Jun 27 13:25:01 2014
@@ -72,20 +72,37 @@ undefined-symbols:
     value:           0x0000000000000000
 ...
 
-# CHECK: defined-atoms:
-# CHECK:  - scope:           hidden
+# CHECK:defined-atoms:   
+# CHECK:  - ref-name:        L000
+# CHECK:    scope:           hidden
 # CHECK:    type:            c-string
 # CHECK:    content:         [ 68, 65, 6C, 6C, 6F, 00 ]
 # CHECK:    merge:           by-content
-# CHECK:  - scope:           hidden
+# CHECK:  - ref-name:        L001
+# CHECK:    scope:           hidden
 # CHECK:    type:            c-string
 # CHECK:    content:         [ 74, 68, 65, 72, 65, 00 ]
 # CHECK:    merge:           by-content
 # CHECK:  - scope:           hidden
 # CHECK:    type:            cfstring
 # CHECK:    merge:           by-content
+# CHECK:    references:      
+# CHECK:      - kind:            pointer64
+# CHECK:        offset:          0
+# CHECK:        target:          ___CFConstantStringClassReference
+# CHECK:      - kind:            pointer64
+# CHECK:        offset:          16
+# CHECK:        target:          L000
 # CHECK:  - scope:           hidden
 # CHECK:    type:            cfstring
 # CHECK:    merge:           by-content
-# CHECK:undefined-atoms:
+# CHECK:    references:      
+# CHECK:      - kind:            pointer64
+# CHECK:        offset:          0
+# CHECK:        target:          ___CFConstantStringClassReference
+# CHECK:      - kind:            pointer64
+# CHECK:        offset:          16
+# CHECK:        target:          L001
+# CHECK:undefined-atoms: 
 # CHECK:  - name:            ___CFConstantStringClassReference
+

Added: lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml?rev=211921&view=auto
==============================================================================
--- lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml (added)
+++ lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml Fri Jun 27 13:25:01 2014
@@ -0,0 +1,223 @@
+# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %s -o %t  | FileCheck %s
+#
+# Test parsing of x86_64 data relocations.
+#
+#_foo:
+#  ret
+#
+#_bar:
+#  ret
+#  
+#  .section __DATA,__custom
+#L1:
+#  .quad 0
+#  
+#  .data
+#_d:
+#  .quad   _foo
+#  .quad   _foo+4
+#  .quad   _foo - .
+#  .quad   L1
+#  .quad   L1 + 2
+#  .quad   _foo - .
+#  .quad   _foo + 4 - .
+#  .quad   L1 - .
+#  .long   _foo - .
+#  .long   _foo + 4 - .
+#  .long   L1 - .
+#
+
+--- !mach-o
+arch:            x86_64
+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:         [ 0xC3, 0xC3 ]
+  - segment:         __DATA
+    section:         __custom
+    type:            S_REGULAR
+    attributes:      [  ]
+    address:         0x0000000000000002
+    content:         [ 0x00, 0x00, 0x00, 0x00 ]
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    alignment:       3
+    address:         0x0000000000000008
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+                       0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+                       0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+                       0xC8, 0xFF, 0xFF, 0xFF, 0xC8, 0xFF, 0xFF, 0xFF, 
+                       0xC2, 0xFF, 0xFF, 0xFF ]
+    relocations:     
+      - offset:          0x00000040
+        type:            X86_64_RELOC_SUBTRACTOR
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000040
+        type:            X86_64_RELOC_UNSIGNED
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          2
+      - offset:          0x0000003C
+        type:            X86_64_RELOC_SUBTRACTOR
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x0000003C
+        type:            X86_64_RELOC_UNSIGNED
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          0
+      - offset:          0x00000038
+        type:            X86_64_RELOC_SUBTRACTOR
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000038
+        type:            X86_64_RELOC_UNSIGNED
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          0
+      - offset:          0x00000030
+        type:            X86_64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000030
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          2
+      - offset:          0x00000028
+        type:            X86_64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000028
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          0
+      - offset:          0x00000020
+        type:            X86_64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000020
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          0
+      - offset:          0x00000018
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          2
+      - offset:          0x00000010
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          2
+      - offset:          0x00000008
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          0
+      - offset:          0x00000000
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          0
+local-symbols:   
+  - name:            _foo
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000000
+  - name:            _bar
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000001
+  - name:            _d
+    type:            N_SECT
+    sect:            3
+    value:           0x0000000000000008
+...
+
+
+# CHECK: defined-atoms:
+# CHECK:  - name:            _d
+# CHECK:    type:            data
+# CHECK:    references:      
+# CHECK:      - kind:            pointer64
+# CHECK:        offset:          0
+# CHECK:        target:          _foo
+# CHECK:      - kind:            pointer64
+# CHECK:        offset:          8
+# CHECK:        target:          _foo
+# CHECK:        addend:          4
+# CHECK:      - kind:            pointer64Anon
+# CHECK:        offset:          16
+# CHECK:        target:          L003
+# CHECK:      - kind:            pointer64Anon
+# CHECK:        offset:          24
+# CHECK:        target:          L003
+# CHECK:        addend:          2
+# CHECK:      - kind:            delta64
+# CHECK:        offset:          32
+# CHECK:        target:          _foo
+# CHECK:      - kind:            delta64
+# CHECK:        offset:          40
+# CHECK:        target:          _foo
+# CHECK:        addend:          4
+# CHECK:      - kind:            delta64Anon
+# CHECK:        offset:          48
+# CHECK:        target:          L003
+# CHECK:      - kind:            delta32
+# CHECK:        offset:          56
+# CHECK:        target:          _foo
+# CHECK:      - kind:            delta32
+# CHECK:        offset:          60
+# CHECK:        target:          _foo
+# CHECK:        addend:          4
+# CHECK:      - kind:            delta32Anon
+# CHECK:        offset:          64
+# CHECK:        target:          L003
+# CHECK:  - name:            _foo
+# CHECK:    content:         [ C3 ]
+# CHECK:  - name:            _bar
+# CHECK:    content:         [ C3 ]
+# CHECK:  - ref-name:        L003
+# CHECK:    type:            unknown
+# CHECK:    content:         [ 00, 00, 00, 00 ]
+# CHECK:    section-choice:  custom-required
+# CHECK:    section-name:    __DATA/__custom

Modified: lld/trunk/test/mach-o/parse-initializers64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-initializers64.yaml?rev=211921&r1=211920&r2=211921&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-initializers64.yaml (original)
+++ lld/trunk/test/mach-o/parse-initializers64.yaml Fri Jun 27 13:25:01 2014
@@ -32,13 +32,13 @@ sections:
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          1
+        symbol:          0
       - offset:          0x00000008
         type:            X86_64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          2
+        symbol:          1
   - segment:         __DATA
     section:         __mod_term_func
     type:            S_MOD_TERM_FUNC_POINTERS
@@ -52,7 +52,7 @@ sections:
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          3
+        symbol:          2
 global-symbols:
   - name:            _init
     type:            N_SECT
@@ -76,12 +76,24 @@ global-symbols:
 # CHECK:  - type:            initializer-pointer
 # CHECK:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
 # CHECK:    dead-strip:      never
+# CHECK:     references:      
+# CHECK:       - kind:        pointer64
+# CHECK:         offset:      0
+# CHECK:         target:      _init
 # CHECK:  - type:            initializer-pointer
 # CHECK:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
 # CHECK:    dead-strip:      never
+# CHECK:     references:      
+# CHECK:       - kind:        pointer64
+# CHECK:         offset:      0
+# CHECK:         target:      _init2
 # CHECK:  - type:            terminator-pointer
 # CHECK:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
 # CHECK:    dead-strip:      never
+# CHECK:     references:      
+# CHECK:       - kind:        pointer64
+# CHECK:         offset:      0
+# CHECK:         target:      _term
 # CHECK:  - name:            _init
 # CHECK:    scope:           global
 # CHECK:    content:         [ 55, 48, 89, E5, 5D, C3 ]

Added: lld/trunk/test/mach-o/parse-text-relocs-x86_64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-text-relocs-x86_64.yaml?rev=211921&view=auto
==============================================================================
--- lld/trunk/test/mach-o/parse-text-relocs-x86_64.yaml (added)
+++ lld/trunk/test/mach-o/parse-text-relocs-x86_64.yaml Fri Jun 27 13:25:01 2014
@@ -0,0 +1,138 @@
+# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %s -o %t  | FileCheck %s
+#
+# Test parsing of x86_64 text relocations.
+#
+#_test:
+#  call  _foo
+#  call  _foo+4
+#  movq  _foo at GOTPCREL(%rip), %rax
+#  pushq _foo at GOTPCREL(%rip)
+#  movl  _foo(%rip), %eax
+#  movl  _foo+4(%rip), %eax
+#  movb  $0x12, _foo(%rip)
+#  movw  $0x1234, _foo(%rip)
+#  movl  $0x12345678, _foo(%rip)
+#
+
+--- !mach-o
+arch:            x86_64
+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:         [ 0xE8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x04, 0x00, 
+                       0x00, 0x00, 0x48, 0x8B, 0x05, 0x00, 0x00, 0x00, 
+                       0x00, 0xFF, 0x35, 0x00, 0x00, 0x00, 0x00, 0x8B, 
+                       0x05, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x05, 0x04, 
+                       0x00, 0x00, 0x00, 0xC6, 0x05, 0xFF, 0xFF, 0xFF, 
+                       0xFF, 0x12, 0x66, 0xC7, 0x05, 0xFE, 0xFF, 0xFF, 
+                       0xFF, 0x34, 0x12, 0xC7, 0x05, 0xFC, 0xFF, 0xFF, 
+                       0xFF, 0x78, 0x56, 0x34, 0x12 ]
+    relocations:     
+      - offset:          0x00000035
+        type:            X86_64_RELOC_SIGNED_4
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x0000002D
+        type:            X86_64_RELOC_SIGNED_2
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x00000025
+        type:            X86_64_RELOC_SIGNED_1
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x0000001F
+        type:            X86_64_RELOC_SIGNED
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x00000019
+        type:            X86_64_RELOC_SIGNED
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x00000013
+        type:            X86_64_RELOC_GOT
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x0000000D
+        type:            X86_64_RELOC_GOT_LOAD
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x00000006
+        type:            X86_64_RELOC_BRANCH
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x00000001
+        type:            X86_64_RELOC_BRANCH
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+local-symbols:   
+  - name:            _test
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000000
+undefined-symbols: 
+  - name:            _foo
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+...
+# CHECK: defined-atoms:
+# CHECK:  - name:            _test
+# CHECK:    references:      
+# CHECK:      - kind:            branch32
+# CHECK:        offset:          1
+# CHECK:        target:          _foo
+# CHECK:      - kind:            branch32
+# CHECK:        offset:          6
+# CHECK:        target:          _foo
+# CHECK:        addend:          4
+# CHECK:      - kind:            ripRel32GotLoad
+# CHECK:        offset:          13
+# CHECK:        target:          _foo
+# CHECK:      - kind:            ripRel32Got
+# CHECK:        offset:          19
+# CHECK:        target:          _foo
+# CHECK:      - kind:            ripRel32
+# CHECK:        offset:          25
+# CHECK:        target:          _foo
+# CHECK:      - kind:            ripRel32
+# CHECK:        offset:          31
+# CHECK:        target:          _foo
+# CHECK:        addend:          4
+# CHECK:      - kind:            ripRel32Minus1
+# CHECK:        offset:          37
+# CHECK:        target:          _foo
+# CHECK-NOT:    addend: 
+# CHECK:      - kind:            ripRel32Minus2
+# CHECK:        offset:          45
+# CHECK:        target:          _foo
+# CHECK-NOT:    addend: 
+# CHECK:      - kind:            ripRel32Minus4
+# CHECK:        offset:          53
+# CHECK:        target:          _foo
+# CHECK-NOT:    addend: 
+





More information about the llvm-commits mailing list