[lld] r213333 - [mach-o] implement more x86 and x86_64 relocation support

Nick Kledzik kledzik at apple.com
Thu Jul 17 16:16:21 PDT 2014


Author: kledzik
Date: Thu Jul 17 18:16:21 2014
New Revision: 213333

URL: http://llvm.org/viewvc/llvm-project?rev=213333&view=rev
Log:
[mach-o] implement more x86 and x86_64 relocation support

Add support for adding section relocations in -r mode.  Enhance the test
cases which validate the parsing of .o files to also round trip.  They now
write out the .o file and then parse that, verifying all relocations survived
the round trip.

Modified:
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
    lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml
    lld/trunk/test/mach-o/parse-relocs-x86.yaml
    lld/trunk/test/mach-o/parse-text-relocs-x86_64.yaml

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp?rev=213333&r1=213332&r2=213333&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp Thu Jul 17 18:16:21 2014
@@ -86,6 +86,44 @@ ArchHandler::RelocPattern ArchHandler::r
   return result;
 }
 
+normalized::Relocation
+ArchHandler::relocFromPattern(ArchHandler::RelocPattern pattern) {
+  normalized::Relocation result;
+  result.offset    = 0;
+  result.scattered = (pattern & rScattered);
+  result.type     = (RelocationInfoType)(pattern & 0xF);
+  result.pcRel    = (pattern & rPcRel);
+  result.isExtern = (pattern & rExtern);
+  result.value    = 0;
+  result.symbol    = 0;
+  switch (pattern & 0x300) {
+  case rLength1:
+    result.length = 0;
+    break;
+  case rLength2:
+    result.length = 1;
+    break;
+  case rLength4:
+    result.length = 2;
+    break;
+  case rLength8:
+    result.length = 3;
+    break;
+  }
+  return result;
+}
+
+void ArchHandler::appendReloc(normalized::Relocations &relocs, uint32_t offset,
+                              uint32_t symbol, uint32_t value,
+                              RelocPattern pattern) {
+  normalized::Relocation reloc = relocFromPattern(pattern);
+  reloc.offset = offset;
+  reloc.symbol = symbol;
+  reloc.value  = value;
+  relocs.push_back(reloc);
+}
+
+
 int16_t ArchHandler::readS16(bool swap, const uint8_t *addr) {
   return read16(swap, *reinterpret_cast<const uint16_t*>(addr));
 }

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=213333&r1=213332&r2=213333&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h Thu Jul 17 18:16:21 2014
@@ -105,11 +105,37 @@ public:
                            const lld::Atom **target, 
                            Reference::Addend *addend) = 0;
 
-  /// 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,
-                          uint64_t targetAddress, uint64_t inAtomAddress) = 0;
+  /// Prototype for a helper function.  Given an atom, finds the symbol table
+  /// index for it in the output file.
+  typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
+
+  /// Prototype for a helper function.  Given an atom, finds the index
+  /// of the section that will contain the atom.
+  typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
+
+  /// Prototype for a helper function.  Given an atom, finds the address
+  /// assigned to it in the output file.
+  typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
+
+  /// Some architectures require local symbols on anonymous atoms.
+  virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
+    return false;
+  }
+
+  /// Copy raw content then apply all fixup References on an Atom.
+  virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
+                                   FindAddressForAtom findAddress,
+                                   uint8_t *atomContentBuffer) = 0;
+
+  /// Used in -r mode to convert a Reference to a mach-o relocation.
+  virtual void appendSectionRelocations(const DefinedAtom &atom,
+                                        uint64_t atomSectionOffset,
+                                        const Reference &ref,
+                                        FindSymbolIndexForAtom,
+                                        FindSectionIndexForAtom,
+                                        FindAddressForAtom,
+                                        normalized::Relocations&) = 0;
+
 
   struct ReferenceInfo {
     Reference::KindArch arch;
@@ -161,7 +187,15 @@ protected:
     rLength4   = 0x0200,
     rLength8   = 0x0300
   };
+  /// Extract RelocPattern from normalized mach-o relocation.
   static RelocPattern relocPattern(const normalized::Relocation &reloc);
+  /// Create normalized Relocation initialized from pattern.
+  static normalized::Relocation relocFromPattern(RelocPattern pattern);
+  /// One liner to add a relocation.
+  static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
+                          uint32_t symbol, uint32_t value,
+                          RelocPattern pattern);
+
 
   static int16_t  readS16(bool swap, const uint8_t *addr);
   static int32_t  readS32(bool swap, const uint8_t *addr);

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp?rev=213333&r1=213332&r2=213333&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Thu Jul 17 18:16:21 2014
@@ -57,11 +57,18 @@ public:
                            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;
+  void generateAtomContent(const DefinedAtom &atom, bool relocatable,
+                           FindAddressForAtom findAddress,
+                           uint8_t *atomContentBuffer) override;
+
+  void appendSectionRelocations(const DefinedAtom &atom,
+                                uint64_t atomSectionOffset,
+                                const Reference &ref,
+                                FindSymbolIndexForAtom,
+                                FindSectionIndexForAtom,
+                                FindAddressForAtom,
+                                normalized::Relocations &) override;
+
 
 private:
   static const Registry::KindStrings _sKindStrings[];
@@ -96,6 +103,14 @@ private:
   uint32_t clearThumbBit(uint32_t value, const Atom *target);
   uint32_t setDisplacementInArmBranch(uint32_t instruction, int32_t disp);
   
+  void applyFixupFinal(const Reference &ref, uint8_t *location,
+                       uint64_t fixupAddress, uint64_t targetAddress,
+                       uint64_t inAtomAddress);
+
+  void applyFixupRelocatable(const Reference &ref, uint8_t *location,
+                             uint64_t fixupAddress,
+                             uint64_t targetAddress,
+                             uint64_t inAtomAddress);
   
   const bool _swap;
 };
@@ -594,19 +609,17 @@ ArchHandler_arm::getPairReferenceInfo(co
   return std::error_code();
 }
 
-void ArchHandler_arm::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) {
-  if (ns != Reference::KindNamespace::mach_o)
+void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *location,
+                                      uint64_t fixupAddress,
+                                      uint64_t targetAddress,
+                                      uint64_t inAtomAddress) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
     return;
-  assert(arch == Reference::KindArch::ARM);
+  assert(ref.kindArch() == Reference::KindArch::ARM);
   int32_t *loc32 = reinterpret_cast<int32_t *>(location);
   int32_t displacement;
   // FIXME: these writes may need a swap.
-  switch (kindValue) {
+  switch (ref.kindValue()) {
   case thumb_b22:
     // FIXME
     break;
@@ -623,7 +636,7 @@ void ArchHandler_arm::applyFixup(Referen
     // FIXME
     break;
   case arm_b24:
-    displacement = (targetAddress - (fixupAddress + 8)) + addend;
+    displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
     *loc32 = setDisplacementInArmBranch(*loc32, displacement);
     break;
   case arm_movw:
@@ -654,6 +667,51 @@ void ArchHandler_arm::applyFixup(Referen
   }
 }
 
+void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
+                                           bool relocatable,
+                                           FindAddressForAtom findAddress,
+                                           uint8_t *atomContentBuffer) {
+  // Copy raw bytes.
+  memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
+  // Apply fix-ups.
+  for (const Reference *ref : atom) {
+    uint32_t offset = ref->offsetInAtom();
+    const Atom *target = ref->target();
+    uint64_t targetAddress = 0;
+    if (isa<DefinedAtom>(target))
+      targetAddress = findAddress(*target);
+    uint64_t atomAddress = findAddress(atom);
+    uint64_t fixupAddress = atomAddress + offset;
+    if (relocatable) {
+      applyFixupRelocatable(*ref, &atomContentBuffer[offset],
+                                        fixupAddress, targetAddress,
+                                        atomAddress);
+    } else {
+      applyFixupFinal(*ref, &atomContentBuffer[offset],
+                                  fixupAddress, targetAddress,
+                                  atomAddress);
+    }
+  }
+}
+
+void ArchHandler_arm::applyFixupRelocatable(const Reference &ref,
+                                             uint8_t *location,
+                                             uint64_t fixupAddress,
+                                             uint64_t targetAddress,
+                                             uint64_t inAtomAddress)  {
+  // FIXME: to do
+}
+
+void ArchHandler_arm::appendSectionRelocations(const DefinedAtom &atom,
+                                               uint64_t atomSectionOffset,
+                                               const Reference &ref,
+                                               FindSymbolIndexForAtom,
+                                               FindSectionIndexForAtom,
+                                               FindAddressForAtom,
+                                               normalized::Relocations &) {
+  // FIXME: to do
+}
+
 std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm() {
   return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm());
 }

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp?rev=213333&r1=213332&r2=213333&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp Thu Jul 17 18:16:21 2014
@@ -57,11 +57,17 @@ public:
                            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;
+  void generateAtomContent(const DefinedAtom &atom, bool relocatable,
+                           FindAddressForAtom findAddress,
+                           uint8_t *atomContentBuffer) override;
+
+  void appendSectionRelocations(const DefinedAtom &atom,
+                                uint64_t atomSectionOffset,
+                                const Reference &ref,
+                                FindSymbolIndexForAtom symbolIndexForAtom,
+                                FindSectionIndexForAtom sectionIndexForAtom,
+                                FindAddressForAtom addressForAtom,
+                                normalized::Relocations &relocs) override;
 
 private:
   static const Registry::KindStrings _sKindStrings[];
@@ -83,6 +89,17 @@ private:
     lazyImmediateLocation, /// Location contains immediate value used in stub.
   };
   
+  static bool useExternalRelocationTo(const Atom &target);
+
+  void applyFixupFinal(const Reference &ref, uint8_t *location,
+                       uint64_t fixupAddress, uint64_t targetAddress,
+                       uint64_t inAtomAddress);
+
+  void applyFixupRelocatable(const Reference &ref, uint8_t *location,
+                             uint64_t fixupAddress,
+                             uint64_t targetAddress,
+                             uint64_t inAtomAddress);
+
   const bool _swap;
 };
 
@@ -246,12 +263,10 @@ ArchHandler_x86::getPairReferenceInfo(co
   Reference::Addend offsetInTo;
   Reference::Addend offsetInFrom;
   switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
-  case((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
-       GENERIC_RELOC_PAIR | rScattered | rLength4)
-      :
-  case((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
-       GENERIC_RELOC_PAIR | rScattered | rLength4)
-      :
+  case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
+         GENERIC_RELOC_PAIR | rScattered | rLength4):
+  case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
+         GENERIC_RELOC_PAIR | rScattered | rLength4):
     toAddress = reloc1.value;
     fromAddress = reloc2.value;
     value = readS32(swap, fixupContent);
@@ -285,33 +300,58 @@ ArchHandler_x86::getPairReferenceInfo(co
   }
 }
 
-void ArchHandler_x86::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) {
-  if (ns != Reference::KindNamespace::mach_o)
+void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,
+                                           bool relocatable,
+                                           FindAddressForAtom findAddress,
+                                           uint8_t *atomContentBuffer) {
+  // Copy raw bytes.
+  memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
+  // Apply fix-ups.
+  for (const Reference *ref : atom) {
+    uint32_t offset = ref->offsetInAtom();
+    const Atom *target = ref->target();
+    uint64_t targetAddress = 0;
+    if (isa<DefinedAtom>(target))
+      targetAddress = findAddress(*target);
+    uint64_t atomAddress = findAddress(atom);
+    uint64_t fixupAddress = atomAddress + offset;
+    if (relocatable) {
+      applyFixupRelocatable(*ref, &atomContentBuffer[offset],
+                                        fixupAddress, targetAddress,
+                                        atomAddress);
+    } else {
+      applyFixupFinal(*ref, &atomContentBuffer[offset],
+                                  fixupAddress, targetAddress,
+                                  atomAddress);
+    }
+  }
+}
+
+void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *location,
+                                      uint64_t fixupAddress,
+                                      uint64_t targetAddress,
+                                      uint64_t inAtomAddress) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
     return;
-  assert(arch == Reference::KindArch::x86);
+  assert(ref.kindArch() == Reference::KindArch::x86);
   int32_t *loc32 = reinterpret_cast<int32_t *>(location);
   int16_t *loc16 = reinterpret_cast<int16_t *>(location);
-  switch (kindValue) {
+  switch (ref.kindValue()) {
   case branch32:
-    write32(*loc32, _swap, (targetAddress - (fixupAddress + 4)) + addend);
+    write32(*loc32, _swap, (targetAddress - (fixupAddress + 4)) + ref.addend());
     break;
   case branch16:
-    write16(*loc16, _swap, (targetAddress - (fixupAddress + 4)) + addend);
+    write16(*loc16, _swap, (targetAddress - (fixupAddress + 2)) + ref.addend());
     break;
   case pointer32:
   case abs32:
-    write32(*loc32, _swap, targetAddress + addend);
+    write32(*loc32, _swap, targetAddress + ref.addend());
     break;
   case funcRel32:
-    write32(*loc32, _swap, targetAddress - inAtomAddress + addend); // FIXME
+    write32(*loc32, _swap, targetAddress - inAtomAddress + ref.addend()); 
     break;
   case delta32:
-    write32(*loc32, _swap, targetAddress - fixupAddress + addend);
+    write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
     break;
   case lazyPointer:
   case lazyImmediateLocation:
@@ -323,6 +363,125 @@ void ArchHandler_x86::applyFixup(Referen
   }
 }
 
+void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
+                                               uint8_t *location,
+                                               uint64_t fixupAddress,
+                                               uint64_t targetAddress,
+                                               uint64_t inAtomAddress) {
+  int32_t *loc32 = reinterpret_cast<int32_t *>(location);
+  int16_t *loc16 = reinterpret_cast<int16_t *>(location);
+  switch (ref.kindValue()) {
+  case branch32:
+    write32(*loc32, _swap, ref.addend() - (fixupAddress + 4));
+    break;
+  case branch16:
+    write16(*loc16, _swap, ref.addend() - (fixupAddress + 2));
+    break;
+  case pointer32:
+  case abs32:
+    write32(*loc32, _swap, targetAddress + ref.addend());
+    break;
+  case funcRel32:
+    write32(*loc32, _swap, targetAddress - inAtomAddress + ref.addend()); // FIXME
+    break;
+  case delta32:
+    write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
+    break;
+  case lazyPointer:
+  case lazyImmediateLocation:
+    // do nothing
+    break;
+  default:
+    llvm_unreachable("invalid x86 Reference Kind");
+    break;
+  }
+}
+
+bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) {
+  // Undefined symbols are referenced via external relocations.
+  if (isa<UndefinedAtom>(&target))
+    return true;
+  if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
+     switch (defAtom->merge()) {
+     case DefinedAtom::mergeAsTentative:
+       // Tentative definitions are referenced via external relocations.
+       return true;
+     case DefinedAtom::mergeAsWeak:
+     case DefinedAtom::mergeAsWeakAndAddressUsed:
+       // Global weak-defs are referenced via external relocations.
+       return (defAtom->scope() == DefinedAtom::scopeGlobal);
+     default:
+       break;
+    }
+  }
+  // Everything else is reference via an internal relocation.
+  return false;
+}
+
+
+void ArchHandler_x86::appendSectionRelocations(
+                                   const DefinedAtom &atom,
+                                   uint64_t atomSectionOffset,
+                                   const Reference &ref,
+                                   FindSymbolIndexForAtom symbolIndexForAtom,
+                                   FindSectionIndexForAtom sectionIndexForAtom,
+                                   FindAddressForAtom addressForAtom,
+                                   normalized::Relocations &relocs) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return;
+  assert(ref.kindArch() == Reference::KindArch::x86);
+  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
+  bool useExternalReloc = useExternalRelocationTo(*ref.target());
+  switch (ref.kindValue()) {
+  case branch32:
+    if (useExternalReloc)
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()),  0,
+                GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4);
+    else
+      appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+                GENERIC_RELOC_VANILLA | rPcRel           | rLength4);
+    break;
+  case branch16:
+    if (useExternalReloc)
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()),  0,
+                GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2);
+    else
+      appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+                GENERIC_RELOC_VANILLA | rPcRel           | rLength2);
+    break;
+  case pointer32:
+  case abs32:
+    if (useExternalReloc)
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()),  0,
+                GENERIC_RELOC_VANILLA |         rExtern | rLength4);
+    else
+      appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+                GENERIC_RELOC_VANILLA |                   rLength4);
+    break;
+  case funcRel32:
+      appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
+                GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
+      appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(),
+                GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
+    break;
+  case delta32:
+      appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
+                GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
+      appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) + ref.offsetInAtom(),
+                GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
+    break;
+  case lazyPointer:
+  case lazyImmediateLocation:
+    llvm_unreachable("lazy reference kind implies Stubs pass was run");
+    break;
+  default:
+    llvm_unreachable("unknown x86 Reference Kind");
+    break;
+
+  }
+}
+
+
 std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86() {
   return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86());
 }

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=213333&r1=213332&r2=213333&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Thu Jul 17 18:16:21 2014
@@ -84,12 +84,22 @@ public:
                            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, uint64_t inAtomAddress) 
-                          override;
+
+  virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
+    return (atom->contentType() == DefinedAtom::typeCString);
+  }
+
+  void generateAtomContent(const DefinedAtom &atom, bool relocatable,
+                           FindAddressForAtom findAddress,
+                           uint8_t *atomContentBuffer) override;
+
+  void appendSectionRelocations(const DefinedAtom &atom,
+                                uint64_t atomSectionOffset,
+                                const Reference &ref,
+                                FindSymbolIndexForAtom symbolIndexForAtom,
+                                FindSectionIndexForAtom sectionIndexForAtom,
+                                FindAddressForAtom addressForAtom,
+                                normalized::Relocations &relocs) override;
 
 private:
   static const Registry::KindStrings _sKindStrings[];
@@ -126,6 +136,15 @@ private:
   Reference::KindValue kindFromRelocPair(const normalized::Relocation &reloc1,
                                          const normalized::Relocation &reloc2);
 
+  void applyFixupFinal(const Reference &ref, uint8_t *location,
+                       uint64_t fixupAddress, uint64_t targetAddress,
+                       uint64_t inAtomAddress);
+
+  void applyFixupRelocatable(const Reference &ref, uint8_t *location,
+                             uint64_t fixupAddress,
+                             uint64_t targetAddress,
+                             uint64_t inAtomAddress);
+
   const bool _swap;
 };
 
@@ -357,51 +376,76 @@ ArchHandler_x86_64::getPairReferenceInfo
   }
 }
 
-void ArchHandler_x86_64::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) {
-  if (ns != Reference::KindNamespace::mach_o)
+void ArchHandler_x86_64::generateAtomContent(const DefinedAtom &atom,
+                                             bool relocatable,
+                                             FindAddressForAtom findAddress,
+                                             uint8_t *atomContentBuffer) {
+  // Copy raw bytes.
+  memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
+  // Apply fix-ups.
+  for (const Reference *ref : atom) {
+    uint32_t offset = ref->offsetInAtom();
+    const Atom *target = ref->target();
+    uint64_t targetAddress = 0;
+    if (isa<DefinedAtom>(target))
+      targetAddress = findAddress(*target);
+    uint64_t atomAddress = findAddress(atom);
+    uint64_t fixupAddress = atomAddress + offset;
+    if (relocatable) {
+      applyFixupRelocatable(*ref, &atomContentBuffer[offset],
+                                        fixupAddress, targetAddress,
+                                        atomAddress);
+    } else {
+      applyFixupFinal(*ref, &atomContentBuffer[offset],
+                                  fixupAddress, targetAddress,
+                                  atomAddress);
+    }
+  }
+}
+
+void ArchHandler_x86_64::applyFixupFinal(const Reference &ref,
+                                         uint8_t *location,
+                                         uint64_t fixupAddress,
+                                         uint64_t targetAddress,
+                                         uint64_t inAtomAddress) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
     return;
-  assert(arch == Reference::KindArch::x86_64);
+  assert(ref.kindArch() == Reference::KindArch::x86_64);
   int32_t *loc32 = reinterpret_cast<int32_t *>(location);
   uint64_t *loc64 = reinterpret_cast<uint64_t *>(location);
-  switch (kindValue) {
+  switch (ref.kindValue()) {
   case branch32:
   case ripRel32:
   case ripRel32Got:
   case ripRel32GotLoad:
-    write32(*loc32, _swap, (targetAddress - (fixupAddress + 4)) + addend);
+    write32(*loc32, _swap, (targetAddress - (fixupAddress + 4)) + ref.addend());
     break;
   case pointer64:
   case pointer64Anon:
-    write64(*loc64, _swap, targetAddress + addend);
+    write64(*loc64, _swap, targetAddress + ref.addend());
     break;
   case ripRel32Minus1:
-    write32(*loc32, _swap, (targetAddress - (fixupAddress + 5)) + addend);
+    write32(*loc32, _swap, (targetAddress - (fixupAddress + 5)) + ref.addend());
     break;
   case ripRel32Minus2:
-    write32(*loc32, _swap, (targetAddress - (fixupAddress + 6)) + addend);
+    write32(*loc32, _swap, (targetAddress - (fixupAddress + 6)) + ref.addend());
     break;
   case ripRel32Minus4:
-    write32(*loc32, _swap, (targetAddress - (fixupAddress + 8)) + addend);
+    write32(*loc32, _swap, (targetAddress - (fixupAddress + 8)) + ref.addend());
     break;
   case delta32:
   case delta32Anon:
-    write32(*loc32, _swap, (targetAddress - fixupAddress) + addend);
+    write32(*loc32, _swap, (targetAddress - fixupAddress) + ref.addend());
     break;
   case delta64:
   case delta64Anon:
-    write64(*loc64, _swap, (targetAddress - fixupAddress) + addend);
+    write64(*loc64, _swap, (targetAddress - fixupAddress) + ref.addend());
     break;
   case ripRel32GotLoadNowLea:
     // Change MOVQ to LEA
     assert(location[-2] == 0x8B);
     location[-2] = 0x8D;
-    write32(*loc32, _swap, (targetAddress - (fixupAddress + 4)) + addend);
+    write32(*loc32, _swap, (targetAddress - (fixupAddress + 4)) + ref.addend());
     break;
   case lazyPointer:
   case lazyImmediateLocation:
@@ -413,6 +457,148 @@ void ArchHandler_x86_64::applyFixup(Refe
   }
 }
 
+
+void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
+                                               uint8_t *location,
+                                               uint64_t fixupAddress,
+                                               uint64_t targetAddress,
+                                               uint64_t inAtomAddress)  {
+  int32_t *loc32 = reinterpret_cast<int32_t *>(location);
+  uint64_t *loc64 = reinterpret_cast<uint64_t *>(location);
+  switch (ref.kindValue()) {
+  case branch32:
+  case ripRel32:
+  case ripRel32Got:
+  case ripRel32GotLoad:
+    write32(*loc32, _swap, ref.addend());
+    break;
+  case pointer64:
+    write64(*loc64, _swap, ref.addend());
+    break;
+  case pointer64Anon:
+    write64(*loc64, _swap, targetAddress + ref.addend());
+    break;
+  case ripRel32Minus1:
+    write32(*loc32, _swap, ref.addend() - 1);
+    break;
+  case ripRel32Minus2:
+    write32(*loc32, _swap, ref.addend() - 2);
+    break;
+  case ripRel32Minus4:
+    write32(*loc32, _swap, ref.addend() - 4);
+    break;
+  case delta32:
+    write32(*loc32, _swap, ref.addend() + inAtomAddress - fixupAddress);
+    break;
+  case delta32Anon:
+    write32(*loc32, _swap, (targetAddress - fixupAddress) + ref.addend());
+    break;
+  case delta64:
+    write64(*loc64, _swap, ref.addend() + inAtomAddress - fixupAddress);
+    break;
+  case delta64Anon:
+    write64(*loc64, _swap, (targetAddress - fixupAddress) + ref.addend());
+    break;
+  case ripRel32GotLoadNowLea:
+    llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
+    break;
+  case lazyPointer:
+  case lazyImmediateLocation:
+    llvm_unreachable("lazy reference kind implies Stubs pass was run");
+    break;
+  default:
+    llvm_unreachable("unknown x86_64 Reference Kind");
+    break;
+  }
+}
+
+void ArchHandler_x86_64::appendSectionRelocations(
+                                   const DefinedAtom &atom,
+                                   uint64_t atomSectionOffset,
+                                   const Reference &ref,
+                                   FindSymbolIndexForAtom symbolIndexForAtom,
+                                   FindSectionIndexForAtom sectionIndexForAtom,
+                                   FindAddressForAtom addressForAtom,
+                                   normalized::Relocations &relocs) {
+  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
+    return;
+  assert(ref.kindArch() == Reference::KindArch::x86_64);
+  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
+  switch (ref.kindValue()) {
+  case branch32:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_BRANCH | rPcRel | rExtern | rLength4);
+    break;
+  case ripRel32:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_SIGNED | rPcRel | rExtern | rLength4 );
+    break;
+  case ripRel32Got:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_GOT | rPcRel | rExtern | rLength4 );
+    break;
+  case ripRel32GotLoad:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4 );
+    break;
+  case pointer64:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_UNSIGNED  | rExtern | rLength8);
+    break;
+  case pointer64Anon:
+    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_UNSIGNED | rLength8);
+    break;
+  case ripRel32Minus1:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4 );
+    break;
+  case ripRel32Minus2:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4 );
+    break;
+  case ripRel32Minus4:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4 );
+    break;
+  case delta32:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+                X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_UNSIGNED   | rExtern | rLength4 );
+    break;
+  case delta32Anon:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+                X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
+    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_UNSIGNED             | rLength4 );
+    break;
+  case delta64:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+                X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_UNSIGNED   | rExtern | rLength8 );
+    break;
+  case delta64Anon:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+                X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
+    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_UNSIGNED             | rLength8 );
+    break;
+  case ripRel32GotLoadNowLea:
+    llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
+    break;
+  case lazyPointer:
+  case lazyImmediateLocation:
+    llvm_unreachable("lazy reference kind implies Stubs pass was run");
+    break;
+  default:
+    llvm_unreachable("unknown x86_64 Reference Kind");
+    break;
+  }
+}
+
+
 std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86_64() {
   return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86_64());
 }

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=213333&r1=213332&r2=213333&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Thu Jul 17 18:16:21 2014
@@ -88,7 +88,8 @@ SegmentInfo::SegmentInfo(StringRef n)
 
 class Util {
 public:
-  Util(const MachOLinkingContext &ctxt) : _context(ctxt), _entryAtom(nullptr) {}
+  Util(const MachOLinkingContext &ctxt) : _context(ctxt), 
+    _archHandler(ctxt.archHandler()), _entryAtom(nullptr) {}
 
   void      assignAtomsToSections(const lld::File &atomFile);
   void      organizeSections();
@@ -128,8 +129,7 @@ private:
   const Atom  *targetOfStub(const DefinedAtom *stubAtom);
   bool         belongsInGlobalSymbolsSection(const DefinedAtom* atom);
   void         appendSection(SectionInfo *si, NormalizedFile &file);
-  void         appendReloc(const DefinedAtom *atom, const Reference *ref,
-                                                      Relocations &relocations);
+  uint32_t     sectionIndexForAtom(const Atom *atom);
 
   static uint64_t alignTo(uint64_t value, uint8_t align2);
   typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
@@ -147,6 +147,7 @@ private:
   };
 
   const MachOLinkingContext    &_context;
+  mach_o::ArchHandler          &_archHandler;
   llvm::BumpPtrAllocator        _allocator;
   std::vector<SectionInfo*>     _sectionInfos;
   std::vector<SegmentInfo*>     _segmentInfos;
@@ -509,6 +510,14 @@ void Util::copySegmentInfo(NormalizedFil
 
 void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
   const bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
+
+  // Utility function for ArchHandler to find address of atom in output file.
+  auto addrForAtom = [&] (const Atom &atom) -> uint64_t {
+    auto pos = _atomToAddress.find(&atom);
+    assert(pos != _atomToAddress.end());
+    return pos->second;
+  };
+
   // Add new empty section to end of file.sections.
   Section temp;
   file.sections.push_back(std::move(temp));
@@ -528,28 +537,9 @@ void Util::appendSection(SectionInfo *si
   uint8_t *sectionContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
   normSect->content = llvm::makeArrayRef(sectionContent, si->size);
   for (AtomInfo &ai : si->atomsAndOffsets) {
-    // Copy raw bytes.
     uint8_t *atomContent = reinterpret_cast<uint8_t*>
                                           (&sectionContent[ai.offsetInSection]);
-    memcpy(atomContent, ai.atom->rawContent().data(), ai.atom->size());
-    // Apply fix-ups.
-    for (const Reference *ref : *ai.atom) {
-      uint32_t offset = ref->offsetInAtom();
-      uint64_t targetAddress = 0;
-      if ( ref->target() != nullptr )
-        targetAddress = _atomToAddress[ref->target()];
-      uint64_t atomAddress = _atomToAddress[ai.atom];
-      uint64_t fixupAddress = atomAddress + offset;
-      if ( rMode ) {
-        // FIXME: Need a handler method to update content for .o file
-        // output and any needed section relocations.
-      } else {
-        _context.archHandler().applyFixup(
-          ref->kindNamespace(), ref->kindArch(), ref->kindValue(),
-          ref->addend(), &atomContent[offset], fixupAddress, targetAddress,
-          atomAddress);
-      }
-    }
+    _archHandler.generateAtomContent(*ai.atom, rMode, addrForAtom, atomContent);
   }
 }
 
@@ -647,6 +637,7 @@ bool Util::belongsInGlobalSymbolsSection
 }
 
 void Util::addSymbols(const lld::File &atomFile, NormalizedFile &file) {
+  bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
   // Mach-O symbol table has three regions: locals, globals, undefs.
 
   // Add all local (non-global) symbols in address order
@@ -667,14 +658,31 @@ void Util::addSymbols(const lld::File &a
           sym.sect  = sect->finalSectionIndex;
           sym.desc  = 0;
           sym.value = _atomToAddress[atom];
+          _atomToSymbolIndex[atom] = file.localSymbols.size();
           file.localSymbols.push_back(sym);
         }
+      } else if (rMode && _archHandler.needsLocalSymbolInRelocatableFile(atom)){
+        // Create 'Lxxx' labels for anonymous atoms if archHandler says so.
+        static unsigned tempNum = 1;
+        char tmpName[16];
+        sprintf(tmpName, "L%04u", tempNum++);
+        StringRef tempRef(tmpName);
+        Symbol sym;
+        sym.name  = tempRef.copy(file.ownedAllocations);
+        sym.type  = N_SECT;
+        sym.scope = 0;
+        sym.sect  = sect->finalSectionIndex;
+        sym.desc  = 0;
+        sym.value = _atomToAddress[atom];
+        _atomToSymbolIndex[atom] = file.localSymbols.size();
+        file.localSymbols.push_back(sym);
       }
     }
   }
 
   // Sort global symbol alphabetically, then add to symbol table.
   std::sort(globals.begin(), globals.end(), AtomSorter());
+  const uint32_t globalStartIndex = file.localSymbols.size();
   for (AtomAndIndex &ai : globals) {
     Symbol sym;
     sym.name  = ai.atom->name();
@@ -683,6 +691,7 @@ void Util::addSymbols(const lld::File &a
     sym.sect  = ai.index;
     sym.desc  = descBits(static_cast<const DefinedAtom*>(ai.atom));
     sym.value = _atomToAddress[ai.atom];
+    _atomToSymbolIndex[ai.atom] = globalStartIndex + file.globalSymbols.size();
     file.globalSymbols.push_back(sym);
   }
 
@@ -715,7 +724,7 @@ void Util::addSymbols(const lld::File &a
 
 const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
   for (const Reference *ref : *lpAtom) {
-    if (_context.archHandler().isLazyPointer(*ref)) {
+    if (_archHandler.isLazyPointer(*ref)) {
       return ref->target();
     }
   }
@@ -838,21 +847,51 @@ void Util::segIndexForSection(const Sect
 }
 
 
-void Util::appendReloc(const DefinedAtom *atom, const Reference *ref,
-                                                     Relocations &relocations) {
-  // TODO: convert Reference to normalized relocation
+uint32_t Util::sectionIndexForAtom(const Atom *atom) {
+  uint64_t address = _atomToAddress[atom];
+  uint32_t index = 1;
+  for (const SectionInfo *si : _sectionInfos) {
+    if ((si->address <= address) && (address < si->address+si->size))
+      return index;
+    ++index;
+  }
+  llvm_unreachable("atom not in any section");
 }
 
 void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
   if (_context.outputMachOType() != llvm::MachO::MH_OBJECT)
     return;
 
+
+  // Utility function for ArchHandler to find symbol index for an atom.
+  auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t {
+    auto pos = _atomToSymbolIndex.find(&atom);
+    assert(pos != _atomToSymbolIndex.end());
+    return pos->second;
+  };
+
+  // Utility function for ArchHandler to find section index for an atom.
+  auto sectIndexForAtom = [&] (const Atom &atom) -> uint32_t {
+    return sectionIndexForAtom(&atom);
+  };
+
+  // Utility function for ArchHandler to find address of atom in output file.
+  auto addressForAtom = [&] (const Atom &atom) -> uint64_t {
+    auto pos = _atomToAddress.find(&atom);
+    assert(pos != _atomToAddress.end());
+    return pos->second;
+  };
+
   for (SectionInfo *si : _sectionInfos) {
     Section &normSect = file.sections[si->normalizedSectionIndex];
     for (const AtomInfo &info : si->atomsAndOffsets) {
       const DefinedAtom *atom = info.atom;
       for (const Reference *ref : *atom) {
-        appendReloc(atom, ref, normSect.relocations);
+        _archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref,
+                                              symIndexForAtom,
+                                              sectIndexForAtom,
+                                              addressForAtom,
+                                              normSect.relocations);
       }
     }
   }
@@ -873,7 +912,7 @@ void Util::addRebaseAndBindingInfo(const
         uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom()
                                 - segmentStartAddr;
         const Atom* targ = ref->target();
-        if (_context.archHandler().isPointer(*ref)) {
+        if (_archHandler.isPointer(*ref)) {
           // A pointer to a DefinedAtom requires rebasing.
           if (dyn_cast<DefinedAtom>(targ)) {
             RebaseLocation rebase;
@@ -895,13 +934,13 @@ void Util::addRebaseAndBindingInfo(const
             nFile.bindingInfo.push_back(bind);
           }
         }
-        if (_context.archHandler().isLazyPointer(*ref)) {
+        if (_archHandler.isLazyPointer(*ref)) {
             BindLocation bind;
             bind.segIndex = segmentIndex;
             bind.segOffset = segmentOffset;
             bind.kind = llvm::MachO::BIND_TYPE_POINTER;
             bind.canBeNull = false; //sa->canBeNullAtRuntime();
-            bind.ordinal = 1;
+            bind.ordinal = 1; // FIXME
             bind.symbolName = targ->name();
             bind.addend = ref->addend();
             nFile.lazyBindingInfo.push_back(bind);

Modified: 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=213333&r1=213332&r2=213333&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml (original)
+++ lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml Thu Jul 17 18:16:21 2014
@@ -1,6 +1,12 @@
-# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %s -o %t  | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -r %s -o %t -print_atoms | FileCheck %s \
+# RUN: && lld -flavor darwin -arch x86_64 %t -r -print_atoms -o %t2  | FileCheck %s
 #
-# Test parsing of x86_64 data relocations.
+# Test parsing and writing of x86_64 text relocations.
+#
+# The first step tests if the supplied mach-o file is parsed into the correct
+# set of references.  The second step verifies relocations can be round-tripped
+# by writing to a new .o file, then parsing that file which should result in
+# the same references.
 #
 #_foo:
 #  ret

Modified: lld/trunk/test/mach-o/parse-relocs-x86.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-relocs-x86.yaml?rev=213333&r1=213332&r2=213333&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-relocs-x86.yaml (original)
+++ lld/trunk/test/mach-o/parse-relocs-x86.yaml Thu Jul 17 18:16:21 2014
@@ -1,9 +1,14 @@
-# RUN: lld -flavor darwin -arch i386 -r -print_atoms %s -o %t  | FileCheck %s
+# RUN: lld -flavor darwin -arch i386 -r -print_atoms %s -o %t  | FileCheck %s \
+# RUN: && lld -flavor darwin -arch i386 -r -print_atoms %t -o %t2  | FileCheck %s
 #
-# Test parsing of x86 relocations.
+# Test parsing and writing of x86 relocations.
 #
-#  .text
+# The first step tests if the supplied mach-o file is parsed into the correct
+# set of references.  The second step verifies relocations can be round-tripped
+# by writing to a new .o file, then parsing that file which should result in
+# the same references.
 #
+#  .text
 #_test:
 #  	call _undef
 #  	call _undef+2

Modified: 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=213333&r1=213332&r2=213333&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-text-relocs-x86_64.yaml (original)
+++ lld/trunk/test/mach-o/parse-text-relocs-x86_64.yaml Thu Jul 17 18:16:21 2014
@@ -1,6 +1,12 @@
-# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %s -o %t  | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s \
+# RUN:  && lld -flavor darwin -arch x86_64 -r -print_atoms %t -o %t2 | FileCheck %s
 #
-# Test parsing of x86_64 text relocations.
+# Test parsing and writing of x86_64 text relocations.
+#
+# The first step tests if the supplied mach-o file is parsed into the correct
+# set of references.  The second step verifies relocations can be round-tripped
+# by writing to a new .o file, then parsing that file which should result in
+# the same references.
 #
 #_test:
 #  call  _foo





More information about the llvm-commits mailing list