<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Sep 30, 2014 at 2:29 PM, Tim Northover <span dir="ltr"><<a href="mailto:tnorthover@apple.com" target="_blank">tnorthover@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: tnorthover<br>
Date: Tue Sep 30 16:29:54 2014<br>
New Revision: 218703<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=218703&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=218703&view=rev</a><br>
Log:<br>
[mach-o] create __unwind_info section on x86_64<br>
<br>
This is a minimally useful pass to construct the __unwind_info section in a<br>
final object from the various __compact_unwind inputs. Currently it doesn't<br>
produce any compressed pages, only works for x86_64 and will fail if any<br>
function ends up without __compact_unwind.<br>
<br>
rdar://problem/18208653<br>
<br>
Added:<br>
    lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp<br>
    lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml<br>
Modified:<br>
    lld/trunk/include/lld/Core/DefinedAtom.h<br>
    lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h<br>
    lld/trunk/lib/Core/DefinedAtom.cpp<br>
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h<br>
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp<br>
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp<br>
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp<br>
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp<br>
    lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt<br>
    lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp<br>
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp<br>
    lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h<br>
    lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp<br>
    lld/trunk/test/mach-o/exe-offsets.yaml<br>
    lld/trunk/test/mach-o/exe-segment-overlap.yaml<br>
<br>
Modified: lld/trunk/include/lld/Core/DefinedAtom.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)<br>
+++ lld/trunk/include/lld/Core/DefinedAtom.h Tue Sep 30 16:29:54 2014<br>
@@ -137,6 +137,7 @@ public:<br>
     typeDTraceDOF,          // runtime data for Dtrace [Darwin]<br>
     typeTempLTO,            // temporary atom for bitcode reader<br>
     typeCompactUnwindInfo,  // runtime data for unwinder [Darwin]<br>
+    typeProcessedUnwindInfo,// compressed compact unwind info [Darwin]<br>
     typeThunkTLV,           // thunk used to access a TLV [Darwin]<br>
     typeTLVInitialData,     // initial data for a TLV [Darwin]<br>
     typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]<br>
<br>
Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)<br>
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Tue Sep 30 16:29:54 2014<br>
@@ -214,6 +214,9 @@ public:<br>
   // GOT creation Pass should be run.<br>
   bool needsGOTPass() const;<br>
<br>
+  /// Pass to transform __compact_unwind into __unwind_info should be run.<br>
+  bool needsCompactUnwindPass() const;<br>
+<br>
   /// Magic symbol name stubs will need to help lazy bind.<br>
   StringRef binderSymbolName() const;<br>
<br>
<br>
Modified: lld/trunk/lib/Core/DefinedAtom.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/DefinedAtom.cpp?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/DefinedAtom.cpp?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/DefinedAtom.cpp (original)<br>
+++ lld/trunk/lib/Core/DefinedAtom.cpp Tue Sep 30 16:29:54 2014<br>
@@ -41,6 +41,7 @@ DefinedAtom::ContentPermissions DefinedA<br>
   case typeLiteral16:<br>
   case typeDTraceDOF:<br>
   case typeCompactUnwindInfo:<br>
+  case typeProcessedUnwindInfo:<br>
   case typeRONote:<br>
   case typeNoAlloc:<br>
     return permR__;<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h (original)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h Tue Sep 30 16:29:54 2014<br>
@@ -53,6 +53,20 @@ public:<br>
   /// Used by GOTPass to update GOT References<br>
   virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}<br>
<br>
+  /// Does this architecture make use of __unwind_info sections for exception<br>
+  /// handling? If so, it will need a separate pass to create them.<br>
+  virtual bool needsCompactUnwind() = 0;<br>
+<br>
+  /// Returns the kind of reference to use to synthesize a 32-bit image-offset<br>
+  /// value, used in the __unwind_info section.<br>
+  virtual Reference::KindValue imageOffsetKind() = 0;<br>
+<br>
+  /// Returns the kind of reference to use to synthesize a 32-bit image-offset<br>
+  /// indirect value. Used for personality functions in the __unwind_info<br>
+  /// section.<br>
+  virtual Reference::KindValue imageOffsetKindIndirect() = 0;<br>
+<br>
+<br>
   /// Used by normalizedFromAtoms() to know where to generated rebasing and<br>
   /// binding info in final executables.<br>
   virtual bool isPointer(const Reference &) = 0;<br>
@@ -126,6 +140,7 @@ public:<br>
   /// Copy raw content then apply all fixup References on an Atom.<br>
   virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,<br>
                                    FindAddressForAtom findAddress,<br>
+                                   uint64_t imageBaseAddress,<br>
                                    uint8_t *atomContentBuffer) = 0;<br>
<br>
   /// Used in -r mode to convert a Reference to a mach-o relocation.<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Tue Sep 30 16:29:54 2014<br>
@@ -36,6 +36,17 @@ public:<br>
   bool isCallSite(const Reference &) override;<br>
   bool isPointer(const Reference &) override;<br>
   bool isPairedReloc(const normalized::Relocation &) override;<br>
+<br>
+  bool needsCompactUnwind() override {<br>
+    return false;<br>
+  }<br>
+  Reference::KindValue imageOffsetKind() override {<br>
+    return invalid;<br>
+  }<br>
+  Reference::KindValue imageOffsetKindIndirect() override {<br>
+    return invalid;<br>
+  }<br>
+<br>
   std::error_code getReferenceInfo(const normalized::Relocation &reloc,<br>
                                    const DefinedAtom *inAtom,<br>
                                    uint32_t offsetInAtom,<br>
@@ -59,6 +70,7 @@ public:<br>
<br>
   void generateAtomContent(const DefinedAtom &atom, bool relocatable,<br>
                            FindAddressForAtom findAddress,<br>
+                           uint64_t imageBaseAddress,<br>
                            uint8_t *atomContentBuffer) override;<br>
<br>
   void appendSectionRelocations(const DefinedAtom &atom,<br>
@@ -904,9 +916,10 @@ void ArchHandler_arm::applyFixupFinal(co<br>
 }<br>
<br>
 void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,<br>
-                                           bool relocatable,<br>
-                                           FindAddressForAtom findAddress,<br>
-                                           uint8_t *atomContentBuffer) {<br>
+                                          bool relocatable,<br>
+                                          FindAddressForAtom findAddress,<br>
+                                          uint64_t imageBaseAddress,<br>
+                                          uint8_t *atomContentBuffer) {<br>
   // Copy raw bytes.<br>
   memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());<br>
   // Apply fix-ups.<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp Tue Sep 30 16:29:54 2014<br>
@@ -76,6 +76,17 @@ public:<br>
   bool isCallSite(const Reference &) override;<br>
   bool isPointer(const Reference &) override;<br>
   bool isPairedReloc(const normalized::Relocation &) override;<br>
+<br>
+  bool needsCompactUnwind() override {<br>
+    return false;<br>
+  }<br>
+  Reference::KindValue imageOffsetKind() override {<br>
+    return invalid;<br>
+  }<br>
+  Reference::KindValue imageOffsetKindIndirect() override {<br>
+    return invalid;<br>
+  }<br>
+<br>
   std::error_code getReferenceInfo(const normalized::Relocation &reloc,<br>
                                    const DefinedAtom *inAtom,<br>
                                    uint32_t offsetInAtom,<br>
@@ -103,6 +114,7 @@ public:<br>
<br>
   void generateAtomContent(const DefinedAtom &atom, bool relocatable,<br>
                            FindAddressForAtom findAddress,<br>
+                           uint64_t imageBaseAddress,<br>
                            uint8_t *atomContentBuffer) override;<br>
<br>
   void appendSectionRelocations(const DefinedAtom &atom,<br>
@@ -440,6 +452,7 @@ std::error_code ArchHandler_arm64::getPa<br>
 void ArchHandler_arm64::generateAtomContent(const DefinedAtom &atom,<br>
                                             bool relocatable,<br>
                                             FindAddressForAtom findAddress,<br>
+                                            uint64_t imageBaseAddress,<br>
                                             uint8_t *atomContentBuffer) {<br>
   // Copy raw bytes.<br>
   memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp Tue Sep 30 16:29:54 2014<br>
@@ -36,6 +36,17 @@ public:<br>
   bool isCallSite(const Reference &) override;<br>
   bool isPointer(const Reference &) override;<br>
   bool isPairedReloc(const normalized::Relocation &) override;<br>
+<br>
+  bool needsCompactUnwind() override {<br>
+    return false;<br>
+  }<br>
+  Reference::KindValue imageOffsetKind() override {<br>
+    return invalid;<br>
+  }<br>
+  Reference::KindValue imageOffsetKindIndirect() override {<br>
+    return invalid;<br>
+  }<br>
+<br>
   std::error_code getReferenceInfo(const normalized::Relocation &reloc,<br>
                                    const DefinedAtom *inAtom,<br>
                                    uint32_t offsetInAtom,<br>
@@ -59,6 +70,7 @@ public:<br>
<br>
   void generateAtomContent(const DefinedAtom &atom, bool relocatable,<br>
                            FindAddressForAtom findAddress,<br>
+                           uint64_t imageBaseAddress,<br>
                            uint8_t *atomContentBuffer) override;<br>
<br>
   void appendSectionRelocations(const DefinedAtom &atom,<br>
@@ -364,9 +376,10 @@ ArchHandler_x86::getPairReferenceInfo(co<br>
 }<br>
<br>
 void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,<br>
-                                           bool relocatable,<br>
-                                           FindAddressForAtom findAddress,<br>
-                                           uint8_t *atomContentBuffer) {<br>
+                                          bool relocatable,<br>
+                                          FindAddressForAtom findAddress,<br>
+                                          uint64_t imageBaseAddress,<br>
+                                          uint8_t *atomContentBuffer) {<br>
   // Copy raw bytes.<br>
   memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());<br>
   // Apply fix-ups.<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Tue Sep 30 16:29:54 2014<br>
@@ -46,6 +46,9 @@ public:<br>
     case ripRel32Got:<br>
       canBypassGOT = false;<br>
       return true;<br>
+    case imageOffsetGot:<br>
+      canBypassGOT = false;<br>
+      return true;<br>
     default:<br>
       return false;<br>
     }<br>
@@ -55,8 +58,30 @@ public:<br>
   void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override {<br>
     assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);<br>
     assert(ref->kindArch() == Reference::KindArch::x86_64);<br>
-    const_cast<Reference *>(ref)<br>
+<br>
+    switch (ref->kindValue()) {<br>
+    case ripRel32Got:<br>
+      assert(targetNowGOT && "target must be GOT");<br>
+    case ripRel32GotLoad:<br>
+      const_cast<Reference *>(ref)<br>
         ->setKindValue(targetNowGOT ? ripRel32 : ripRel32GotLoadNowLea);<br>
+      break;<br>
+    case imageOffsetGot:<br>
+      const_cast<Reference *>(ref)->setKindValue(imageOffset);<br>
+      break;<br>
+    default:<br>
+      llvm_unreachable("unknown GOT reference kind");<br>
+    }<br>
+  }<br>
+<br>
+  bool needsCompactUnwind() override {<br>
+    return true;<br>
+  }<br>
+  Reference::KindValue imageOffsetKind() override {<br>
+    return imageOffset;<br>
+  }<br>
+  Reference::KindValue imageOffsetKindIndirect() override {<br>
+    return imageOffsetGot;<br>
   }<br>
<br>
   const StubInfo &stubInfo() override { return _sStubInfo; }<br>
@@ -64,6 +89,7 @@ public:<br>
   bool isCallSite(const Reference &) override;<br>
   bool isPointer(const Reference &) override;<br>
   bool isPairedReloc(const normalized::Relocation &) override;<br>
+<br>
   std::error_code getReferenceInfo(const normalized::Relocation &reloc,<br>
                                    const DefinedAtom *inAtom,<br>
                                    uint32_t offsetInAtom,<br>
@@ -91,6 +117,7 @@ public:<br>
<br>
   void generateAtomContent(const DefinedAtom &atom, bool relocatable,<br>
                            FindAddressForAtom findAddress,<br>
+                           uint64_t imageBase,<br>
                            uint8_t *atomContentBuffer) override;<br>
<br>
   void appendSectionRelocations(const DefinedAtom &atom,<br>
@@ -130,6 +157,11 @@ private:<br>
                            /// to "leaq _foo(%rip), %rax<br>
     lazyPointer,           /// Location contains a lazy pointer.<br>
     lazyImmediateLocation, /// Location contains immediate value used in stub.<br>
+<br>
+    imageOffset,           /// Location contains offset of atom in final image<br>
+    imageOffsetGot,        /// Location contains offset of GOT entry for atom in<br>
+                           /// final image (typically personality function).<br>
+<br>
   };<br>
<br>
   Reference::KindValue kindFromReloc(const normalized::Relocation &reloc);<br>
@@ -138,7 +170,7 @@ private:<br>
<br>
   void applyFixupFinal(const Reference &ref, uint8_t *location,<br>
                        uint64_t fixupAddress, uint64_t targetAddress,<br>
-                       uint64_t inAtomAddress);<br>
+                       uint64_t inAtomAddress, uint64_t imageBaseAddress);<br>
<br>
   void applyFixupRelocatable(const Reference &ref, uint8_t *location,<br>
                              uint64_t fixupAddress,<br>
@@ -165,6 +197,7 @@ const Registry::KindStrings ArchHandler_<br>
   LLD_KIND_STRING_ENTRY(pointer64), LLD_KIND_STRING_ENTRY(pointer64Anon),<br>
   LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(delta64),<br>
   LLD_KIND_STRING_ENTRY(delta32Anon), LLD_KIND_STRING_ENTRY(delta64Anon),<br>
+  LLD_KIND_STRING_ENTRY(imageOffset), LLD_KIND_STRING_ENTRY(imageOffsetGot),<br>
   LLD_KIND_STRING_END<br>
 };<br>
<br>
@@ -382,6 +415,7 @@ ArchHandler_x86_64::getPairReferenceInfo<br>
 void ArchHandler_x86_64::generateAtomContent(const DefinedAtom &atom,<br>
                                              bool relocatable,<br>
                                              FindAddressForAtom findAddress,<br>
+                                             uint64_t imageBaseAddress,<br>
                                              uint8_t *atomContentBuffer) {<br>
   // Copy raw bytes.<br>
   memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());<br>
@@ -400,8 +434,8 @@ void ArchHandler_x86_64::generateAtomCon<br>
                                         atomAddress);<br>
     } else {<br>
       applyFixupFinal(*ref, &atomContentBuffer[offset],<br>
-                                  fixupAddress, targetAddress,<br>
-                                  atomAddress);<br>
+                      fixupAddress, targetAddress,<br>
+                      atomAddress, imageBaseAddress);<br>
     }<br>
   }<br>
 }<br>
@@ -410,7 +444,8 @@ void ArchHandler_x86_64::applyFixupFinal<br>
                                          uint8_t *location,<br>
                                          uint64_t fixupAddress,<br>
                                          uint64_t targetAddress,<br>
-                                         uint64_t inAtomAddress) {<br>
+                                         uint64_t inAtomAddress,<br>
+                                         uint64_t imageBaseAddress) {<br>
   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)<br>
     return;<br>
   assert(ref.kindArch() == Reference::KindArch::x86_64);<br>
@@ -455,6 +490,10 @@ void ArchHandler_x86_64::applyFixupFinal<br>
   case lazyImmediateLocation:<br>
     // do nothing<br>
     return;<br>
+  case imageOffset:<br>
+  case imageOffsetGot:<br>
+    write32(*loc32, _swap, (targetAddress - imageBaseAddress) + ref.addend());<br>
+    return;<br>
   case invalid:<br>
     // Fall into llvm_unreachable().<br>
     break;<br>
@@ -514,6 +553,10 @@ void ArchHandler_x86_64::applyFixupReloc<br>
   case lazyImmediateLocation:<br>
     llvm_unreachable("lazy reference kind implies Stubs pass was run");<br>
     return;<br>
+  case imageOffset:<br>
+  case imageOffsetGot:<br>
+    llvm_unreachable("image offset implies __unwind_info");<br>
+    return;<br>
   case invalid:<br>
     // Fall into llvm_unreachable().<br>
     break;<br>
@@ -605,6 +648,10 @@ void ArchHandler_x86_64::appendSectionRe<br>
   case lazyImmediateLocation:<br>
     llvm_unreachable("lazy reference kind implies Stubs pass was run");<br>
     return;<br>
+  case imageOffset:<br>
+  case imageOffsetGot:<br>
+    llvm_unreachable("__unwind_info references should have been resolved");<br>
+    return;<br>
   case invalid:<br>
     // Fall into llvm_unreachable().<br>
     break;<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt (original)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt Tue Sep 30 16:29:54 2014<br>
@@ -4,6 +4,7 @@ add_lld_library(lldMachO<br>
   ArchHandler_arm64.cpp<br>
   ArchHandler_x86.cpp<br>
   ArchHandler_x86_64.cpp<br>
+  CompactUnwindPass.cpp<br>
   GOTPass.cpp<br>
   MachOLinkingContext.cpp<br>
   MachONormalizedFileBinaryReader.cpp<br>
<br>
Added: lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp?rev=218703&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp?rev=218703&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp (added)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp Tue Sep 30 16:29:54 2014<br>
@@ -0,0 +1,456 @@<br>
+//===- lib/ReaderWriter/MachO/CompactUnwindPass.cpp -----------------------===//<br>
+//<br>
+//                             The LLVM Linker<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "ArchHandler.h"<br>
+#include "File.h"<br>
+#include "MachOPasses.h"<br>
+#include "MachONormalizedFileBinaryUtils.h"<br>
+<br>
+#include "lld/Core/DefinedAtom.h"<br>
+#include "lld/Core/File.h"<br>
+#include "lld/Core/LLVM.h"<br>
+#include "lld/Core/Reference.h"<br>
+#include "lld/Core/Simple.h"<br>
+<br>
+#include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/Endian.h"<br>
+#include "llvm/Support/Format.h"<br>
+<br>
+#define DEBUG_TYPE "macho-compact-unwind"<br>
+<br>
+namespace lld {<br>
+namespace mach_o {<br>
+<br>
+namespace {<br>
+struct CompactUnwindEntry {<br>
+  const Atom *rangeStart;<br>
+  const Atom *personalityFunction;<br>
+  const Atom *lsdaLocation;<br>
+<br>
+  uint32_t rangeLength;<br>
+  uint32_t encoding;<br>
+};<br>
+<br>
+struct UnwindInfoPage {<br>
+  std::vector<CompactUnwindEntry> entries;<br>
+};<br>
+}<br>
+<br>
+class UnwindInfoAtom : public SimpleDefinedAtom {<br>
+public:<br>
+  UnwindInfoAtom(ArchHandler &archHandler, const File &file, bool swap,<br>
+                 std::vector<uint32_t> commonEncodings,<br>
+                 std::vector<const Atom *> personalities,<br>
+                 std::vector<UnwindInfoPage> pages, uint32_t numLSDAs)<br>
+      : SimpleDefinedAtom(file), _archHandler(archHandler),<br>
+        _commonEncodingsOffset(7 * sizeof(uint32_t)),<br>
+        _personalityArrayOffset(_commonEncodingsOffset +<br>
+                                commonEncodings.size() * sizeof(uint32_t)),<br>
+        _topLevelIndexOffset(_personalityArrayOffset +<br>
+                             personalities.size() * sizeof(uint32_t)),<br>
+        _lsdaIndexOffset(_topLevelIndexOffset +<br>
+                         3 * (pages.size() + 1) * sizeof(uint32_t)),<br>
+        _firstPageOffset(_lsdaIndexOffset + 2 * numLSDAs * sizeof(uint32_t)),<br>
+        _swap(swap) {<br>
+<br>
+    addHeader(commonEncodings.size(), personalities.size(), pages.size());<br>
+    addCommonEncodings(commonEncodings);<br>
+    addPersonalityFunctions(personalities);<br>
+    addTopLevelIndexes(pages);<br>
+    addLSDAIndexes(pages, numLSDAs);<br>
+    addSecondLevelPages(pages);<br>
+  }<br>
+<br>
+  ContentType contentType() const override {<br>
+    return DefinedAtom::typeProcessedUnwindInfo;<br>
+  }<br>
+<br>
+  Alignment alignment() const override { return Alignment(2); }<br>
+<br>
+  uint64_t size() const override { return _contents.size(); }<br>
+<br>
+  ContentPermissions permissions() const override {<br>
+    return DefinedAtom::permR__;<br>
+  }<br>
+<br>
+  ArrayRef<uint8_t> rawContent() const override { return _contents; }<br>
+<br>
+  void addHeader(uint32_t numCommon, uint32_t numPersonalities,<br>
+                 uint32_t numPages) {<br>
+    using normalized::write32;<br>
+<br>
+    uint32_t headerSize = 7 * sizeof(uint32_t);<br>
+    _contents.resize(headerSize);<br>
+<br>
+    int32_t *headerEntries = (int32_t *)_contents.data();<br>
+    // version<br>
+    write32(headerEntries[0], _swap, 1);<br>
+    // commonEncodingsArraySectionOffset<br>
+    write32(headerEntries[1], _swap, _commonEncodingsOffset);<br>
+    // commonEncodingsArrayCount<br>
+    write32(headerEntries[2], _swap, numCommon);<br>
+    // personalityArraySectionOffset<br>
+    write32(headerEntries[3], _swap, _personalityArrayOffset);<br>
+    // personalityArrayCount<br>
+    write32(headerEntries[4], _swap, numPersonalities);<br>
+    // indexSectionOffset<br>
+    write32(headerEntries[5], _swap, _topLevelIndexOffset);<br>
+    // indexCount<br>
+    write32(headerEntries[6], _swap, numPages + 1);<br>
+  }<br>
+<br>
+  /// Add the list of common encodings to the section; this is simply an array<br>
+  /// of uint32_t compact values. Size has already been specified in the header.<br>
+  void addCommonEncodings(std::vector<uint32_t> &commonEncodings) {<br>
+    using normalized::write32;<br>
+<br>
+    _contents.resize(_commonEncodingsOffset +<br>
+                     commonEncodings.size() * sizeof(uint32_t));<br>
+    int32_t *commonEncodingsArea =<br>
+        (int32_t *)&_contents[_commonEncodingsOffset];<br></blockquote><div><br></div><div>It doesn't seem to be guaranteed that _commonEncodingsOffset is a valid index. If I add</div><div><br></div><div>  <span style="color:rgb(0,0,0)">assert(_commonEncodingsOffset < _contents.size());</span></div><div><br></div><div>many tests start failing.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+    for (uint32_t encoding : commonEncodings)<br>
+      write32(*commonEncodingsArea++, _swap, encoding);<br>
+  }<br>
+<br>
+  void addPersonalityFunctions(std::vector<const Atom *> personalities) {<br>
+    _contents.resize(_personalityArrayOffset +<br>
+                     personalities.size() * sizeof(uint32_t));<br>
+<br>
+    for (unsigned i = 0; i < personalities.size(); ++i)<br>
+      addImageReferenceIndirect(_personalityArrayOffset + i * sizeof(uint32_t),<br>
+                                personalities[i]);<br>
+  }<br>
+<br>
+  void addTopLevelIndexes(std::vector<UnwindInfoPage> &pages) {<br>
+    using normalized::write32;<br>
+<br>
+    uint32_t numIndexes = pages.size() + 1;<br>
+    _contents.resize(_topLevelIndexOffset + numIndexes * 3 * sizeof(uint32_t));<br>
+<br>
+    uint32_t pageLoc = _firstPageOffset;<br>
+<br>
+    // The most difficult job here is calculating the LSDAs; everything else<br>
+    // follows fairly naturally, but we can't state where the first<br>
+    int32_t *indexData = (int32_t *)&_contents[_topLevelIndexOffset];<br>
+    uint32_t numLSDAs = 0;<br>
+    for (unsigned i = 0; i < pages.size(); ++i) {<br>
+      // functionOffset<br>
+      addImageReference(_topLevelIndexOffset + 3 * i * sizeof(uint32_t),<br>
+                        pages[i].entries[0].rangeStart);<br>
+      // secondLevelPagesSectionOffset<br>
+      write32(indexData[3 * i + 1], _swap, pageLoc);<br>
+      write32(indexData[3 * i + 2], _swap,<br>
+              _lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t));<br>
+<br>
+      for (auto &entry : pages[i].entries)<br>
+        if (entry.lsdaLocation)<br>
+          ++numLSDAs;<br>
+    }<br>
+<br>
+    // Finally, write out the final sentinel index<br>
+    CompactUnwindEntry &finalEntry = pages[pages.size() - 1].entries.back();<br>
+    addImageReference(_topLevelIndexOffset +<br>
+                          3 * pages.size() * sizeof(uint32_t),<br>
+                      finalEntry.rangeStart, finalEntry.rangeLength);<br>
+    // secondLevelPagesSectionOffset => 0<br>
+    indexData[3 * pages.size() + 2] =<br>
+        _lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t);<br>
+  }<br>
+<br>
+  void addLSDAIndexes(std::vector<UnwindInfoPage> &pages, uint32_t numLSDAs) {<br>
+    _contents.resize(_lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t));<br>
+<br>
+    uint32_t curOffset = _lsdaIndexOffset;<br>
+    for (auto &page : pages) {<br>
+      for (auto &entry : page.entries) {<br>
+        if (!entry.lsdaLocation)<br>
+          continue;<br>
+<br>
+        addImageReference(curOffset, entry.rangeStart);<br>
+        addImageReference(curOffset + sizeof(uint32_t), entry.lsdaLocation);<br>
+        curOffset += 2 * sizeof(uint32_t);<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  void addSecondLevelPages(std::vector<UnwindInfoPage> &pages) {<br>
+    for (auto &page : pages) {<br>
+      addRegularSecondLevelPage(page);<br>
+    }<br>
+  }<br>
+<br>
+  void addRegularSecondLevelPage(const UnwindInfoPage &page) {<br>
+    uint32_t curPageOffset = _contents.size();<br>
+    const int16_t headerSize = sizeof(uint32_t) + 2 * sizeof(uint16_t);<br>
+    uint32_t curPageSize =<br>
+        headerSize + 2 * page.entries.size() * sizeof(uint32_t);<br>
+    _contents.resize(curPageOffset + curPageSize);<br>
+<br>
+    using normalized::write32;<br>
+    using normalized::write16;<br>
+    // 2 => regular page<br>
+    write32(*(int32_t *)&_contents[curPageOffset], _swap, 2);<br>
+    // offset of 1st entry<br>
+    write16(*(int16_t *)&_contents[curPageOffset + 4], _swap, headerSize);<br>
+    write16(*(int16_t *)&_contents[curPageOffset + 6], _swap,<br>
+            page.entries.size());<br>
+<br>
+    uint32_t pagePos = curPageOffset + headerSize;<br>
+    for (auto &entry : page.entries) {<br>
+      addImageReference(pagePos, entry.rangeStart);<br>
+      write32(reinterpret_cast<int32_t *>(_contents.data() + pagePos)[1], _swap,<br>
+              entry.encoding);<br>
+      pagePos += 2 * sizeof(uint32_t);<br>
+    }<br>
+  }<br>
+<br>
+  void addImageReference(uint32_t offset, const Atom *dest,<br>
+                         Reference::Addend addend = 0) {<br>
+    addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),<br>
+                 _archHandler.imageOffsetKind(), offset, dest, addend);<br>
+  }<br>
+<br>
+  void addImageReferenceIndirect(uint32_t offset, const Atom *dest) {<br>
+    addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),<br>
+                 _archHandler.imageOffsetKindIndirect(), offset, dest, 0);<br>
+  }<br>
+<br>
+private:<br>
+  mach_o::ArchHandler &_archHandler;<br>
+  std::vector<uint8_t> _contents;<br>
+  uint32_t _commonEncodingsOffset;<br>
+  uint32_t _personalityArrayOffset;<br>
+  uint32_t _topLevelIndexOffset;<br>
+  uint32_t _lsdaIndexOffset;<br>
+  uint32_t _firstPageOffset;<br>
+  bool _swap;<br>
+};<br>
+<br>
+/// Pass for instantiating and optimizing GOT slots.<br>
+///<br>
+class CompactUnwindPass : public Pass {<br>
+public:<br>
+  CompactUnwindPass(const MachOLinkingContext &context)<br>
+      : _context(context), _archHandler(_context.archHandler()),<br>
+        _file("<mach-o Compact Unwind Pass>"),<br>
+        _swap(!MachOLinkingContext::isHostEndian(_context.arch())) {}<br>
+<br>
+private:<br>
+  void perform(std::unique_ptr<MutableFile> &mergedFile) override {<br>
+    DEBUG(llvm::dbgs() << "MachO Compact Unwind pass\n");<br>
+<br>
+    // First collect all __compact_unwind entries, addressable by the function<br>
+    // it's referring to.<br>
+    std::map<const Atom *, CompactUnwindEntry> unwindLocs;<br>
+    std::vector<const Atom *> personalities;<br>
+    uint32_t numLSDAs = 0;<br>
+<br>
+    collectCompactUnwindEntries(mergedFile, unwindLocs, personalities,<br>
+                                numLSDAs);<br>
+<br>
+    // FIXME: if there are more than 4 personality functions then we need to<br>
+    // defer to DWARF info for the ones we don't put in the list. They should<br>
+    // also probably be sorted by frequency.<br>
+    assert(personalities.size() <= 4);<br>
+<br>
+    // Now sort the entries by final address and fixup the compact encoding to<br>
+    // its final form (i.e. set personality function bits & create DWARF<br>
+    // references where needed).<br>
+    std::vector<CompactUnwindEntry> unwindInfos =<br>
+        createUnwindInfoEntries(mergedFile, unwindLocs, personalities);<br>
+<br>
+    // Finally, we can start creating pages based on these entries.<br>
+<br>
+    DEBUG(llvm::dbgs() << "  Splitting entries into pages\n");<br>
+    // FIXME: we split the entries into pages naively: lots of 4k pages followed<br>
+    // by a small one. ld64 tried to minimize space and align them to real 4k<br>
+    // boundaries. That might be worth doing, or perhaps we could perform some<br>
+    // minor balancing for expected number of lookups.<br>
+    std::vector<UnwindInfoPage> pages;<br>
+    unsigned pageStart = 0;<br>
+    do {<br>
+      pages.push_back(UnwindInfoPage());<br>
+<br>
+      // FIXME: we only create regular pages at the moment. These can hold up to<br>
+      // 1021 entries according to the documentation.<br>
+      unsigned entriesInPage =<br>
+          std::min(1021U, (unsigned)unwindInfos.size() - pageStart);<br>
+<br>
+      std::copy(unwindInfos.begin() + pageStart,<br>
+                unwindInfos.begin() + pageStart + entriesInPage,<br>
+                std::back_inserter(pages.back().entries));<br>
+      pageStart += entriesInPage;<br>
+<br>
+      DEBUG(llvm::dbgs()<br>
+            << "    Page from " << pages.back().entries[0].rangeStart->name()<br>
+            << " to " << pages.back().entries.back().rangeStart->name() << " + "<br>
+            << llvm::format("0x%x", pages.back().entries.back().rangeLength)<br>
+            << " has " << entriesInPage << " entries\n");<br>
+    } while (pageStart < unwindInfos.size());<br>
+<br>
+    // FIXME: we should also erase all compact-unwind atoms; their job is done.<br>
+    UnwindInfoAtom *unwind = new (_file.allocator())<br>
+        UnwindInfoAtom(_archHandler, _file, _swap, std::vector<uint32_t>(),<br>
+                       personalities, pages, numLSDAs);<br>
+    mergedFile->addAtom(*unwind);<br>
+  }<br>
+<br>
+  void collectCompactUnwindEntries(<br>
+      std::unique_ptr<MutableFile> &mergedFile,<br>
+      std::map<const Atom *, CompactUnwindEntry> &unwindLocs,<br>
+      std::vector<const Atom *> &personalities, uint32_t &numLSDAs) {<br>
+    DEBUG(llvm::dbgs() << "  Collecting __compact_unwind entries\n");<br>
+<br>
+    for (const DefinedAtom *atom : mergedFile->defined()) {<br>
+      if (atom->contentType() != DefinedAtom::typeCompactUnwindInfo)<br>
+        continue;<br>
+<br>
+      auto unwindEntry = extractCompactUnwindEntry(atom);<br>
+      unwindLocs.insert(std::make_pair(unwindEntry.rangeStart, unwindEntry));<br>
+<br>
+      DEBUG(llvm::dbgs() << "    Entry for " << unwindEntry.rangeStart->name()<br>
+                         << ", encoding="<br>
+                         << llvm::format("0x%08x", unwindEntry.encoding));<br>
+      if (unwindEntry.personalityFunction)<br>
+        DEBUG(llvm::dbgs() << ", personality="<br>
+                           << unwindEntry.personalityFunction->name()<br>
+                           << ", lsdaLoc=" << unwindEntry.lsdaLocation->name());<br>
+      DEBUG(llvm::dbgs() << '\n');<br>
+<br>
+      // Count number of LSDAs we see, since we need to know how big the index<br>
+      // will be while laying out the section.<br>
+      if (unwindEntry.lsdaLocation)<br>
+        ++numLSDAs;<br>
+<br>
+      // Gather the personality functions now, so that they're in deterministic<br>
+      // order (derived from the DefinedAtom order).<br>
+      if (unwindEntry.personalityFunction) {<br>
+        auto pFunc = std::find(personalities.begin(), personalities.end(),<br>
+                               unwindEntry.personalityFunction);<br>
+        if (pFunc == personalities.end())<br>
+          personalities.push_back(unwindEntry.personalityFunction);<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  CompactUnwindEntry extractCompactUnwindEntry(const DefinedAtom *atom) {<br>
+    CompactUnwindEntry entry = {nullptr, nullptr, nullptr, 0, 0};<br>
+<br>
+    for (const Reference *ref : *atom) {<br>
+      switch (ref->offsetInAtom()) {<br>
+      case 0:<br>
+        // FIXME: there could legitimately be functions with multiple encoding<br>
+        // entries. However, nothing produces them at the moment.<br>
+        assert(ref->addend() == 0 && "unexpected offset into function");<br>
+        entry.rangeStart = ref->target();<br>
+        break;<br>
+      case 0x10:<br>
+        assert(ref->addend() == 0 && "unexpected offset into personality fn");<br>
+        entry.personalityFunction = ref->target();<br>
+        break;<br>
+      case 0x18:<br>
+        assert(ref->addend() == 0 && "unexpected offset into LSDA atom");<br>
+        entry.lsdaLocation = ref->target();<br>
+        break;<br>
+      }<br>
+    }<br>
+<br>
+    using normalized::read32;<br>
+    entry.rangeLength =<br>
+        read32(_swap, ((uint32_t *)atom->rawContent().data())[2]);<br>
+    entry.encoding = read32(_swap, ((uint32_t *)atom->rawContent().data())[3]);<br>
+    return entry;<br>
+  }<br>
+<br>
+  /// Every atom defined in __TEXT,__text needs an entry in the final<br>
+  /// __unwind_info section (in order). These comes from two sources:<br>
+  ///   + Input __compact_unwind sections where possible (after adding the<br>
+  ///      personality function offset which is only known now).<br>
+  ///   + A synthesised reference to __eh_frame if there's no __compact_unwind<br>
+  ///     or too many personality functions to be accommodated.<br>
+  std::vector<CompactUnwindEntry> createUnwindInfoEntries(<br>
+      const std::unique_ptr<MutableFile> &mergedFile,<br>
+      const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,<br>
+      const std::vector<const Atom *> &personalities) {<br>
+    std::vector<CompactUnwindEntry> unwindInfos;<br>
+<br>
+    DEBUG(llvm::dbgs() << "  Creating __unwind_info entries\n");<br>
+    // The final order in the __unwind_info section must be derived from the<br>
+    // order of typeCode atoms, since that's how they'll be put into the object<br>
+    // file eventually (yuck!).<br>
+    for (const DefinedAtom *atom : mergedFile->defined()) {<br>
+      if (atom->contentType() != DefinedAtom::typeCode)<br>
+        continue;<br>
+<br>
+      unwindInfos.push_back(<br>
+          finalizeUnwindInfoEntryForAtom(atom, unwindLocs, personalities));<br>
+<br>
+      DEBUG(llvm::dbgs() << "    Entry for " << atom->name()<br>
+                         << ", final encoding="<br>
+                         << llvm::format("0x%08x", unwindInfos.back().encoding)<br>
+                         << '\n');<br>
+    }<br>
+<br>
+    return unwindInfos;<br>
+  }<br>
+<br>
+  CompactUnwindEntry finalizeUnwindInfoEntryForAtom(<br>
+      const DefinedAtom *function,<br>
+      const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,<br>
+      const std::vector<const Atom *> &personalities) {<br>
+    auto unwindLoc = unwindLocs.find(function);<br>
+<br>
+    // FIXME: we should synthesize a DWARF compact unwind entry before claiming<br>
+    // there's no unwind if a __compact_unwind atom doesn't exist.<br>
+    if (unwindLoc == unwindLocs.end()) {<br>
+      CompactUnwindEntry entry;<br>
+      memset(&entry, 0, sizeof(CompactUnwindEntry));<br>
+      entry.rangeStart = function;<br>
+      entry.rangeLength = function->size();<br>
+      return entry;<br>
+    }<br>
+<br>
+    CompactUnwindEntry entry = unwindLoc->second;<br>
+    auto personality = std::find(personalities.begin(), personalities.end(),<br>
+                                 entry.personalityFunction);<br>
+    uint32_t personalityIdx = personality == personalities.end()<br>
+                                  ? 0<br>
+                                  : personality - personalities.begin() + 1;<br>
+<br>
+    // FIXME: We should also use DWARF when there isn't enough room for the<br>
+    // personality function in the compact encoding.<br>
+    assert(personalityIdx < 4 && "too many personality functions");<br>
+<br>
+    entry.encoding |= personalityIdx << 28;<br>
+<br>
+    if (entry.lsdaLocation)<br>
+      entry.encoding |= 1U << 30;<br>
+<br>
+    return entry;<br>
+  }<br>
+<br>
+  const MachOLinkingContext &_context;<br>
+  mach_o::ArchHandler &_archHandler;<br>
+  MachOFile _file;<br>
+  bool _swap;<br>
+};<br>
+<br>
+void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx) {<br>
+  assert(ctx.needsCompactUnwindPass());<br>
+  pm.add(std::unique_ptr<Pass>(new CompactUnwindPass(ctx)));<br>
+}<br>
+<br>
+} // end namesapce mach_o<br>
+} // end namesapce lld<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Tue Sep 30 16:29:54 2014<br>
@@ -281,6 +281,16 @@ bool MachOLinkingContext::needsGOTPass()<br>
   }<br>
 }<br>
<br>
+bool MachOLinkingContext::needsCompactUnwindPass() const {<br>
+  switch (_outputMachOType) {<br>
+  case MH_EXECUTE:<br>
+  case MH_DYLIB:<br>
+  case MH_BUNDLE:<br>
+    return archHandler().needsCompactUnwind();<br>
+  default:<br>
+    return false;<br>
+  }<br>
+}<br>
<br>
 StringRef MachOLinkingContext::binderSymbolName() const {<br>
   return archHandler().stubInfo().binderSymbolName;<br>
@@ -511,6 +521,8 @@ void MachOLinkingContext::addPasses(Pass<br>
   pm.add(std::unique_ptr<Pass>(new LayoutPass(registry())));<br>
   if (needsStubsPass())<br>
     mach_o::addStubsPass(pm, *this);<br>
+  if (needsCompactUnwindPass())<br>
+    mach_o::addCompactUnwindPass(pm, *this);<br>
   if (needsGOTPass())<br>
     mach_o::addGOTPass(pm, *this);<br>
 }<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Tue Sep 30 16:29:54 2014<br>
@@ -220,6 +220,7 @@ const MachOFinalSectionFromAtomType sect<br>
   ENTRY("__TEXT", "__stub_helper",    S_REGULAR,          typeStubHelper),<br>
   ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR,          typeLSDA),<br>
   ENTRY("__TEXT", "__eh_frame",       S_COALESCED,        typeCFI),<br>
+  ENTRY("__TEXT", "__unwind_info",    S_REGULAR,          typeProcessedUnwindInfo),<br>
   ENTRY("__DATA", "__data",           S_REGULAR,          typeData),<br>
   ENTRY("__DATA", "__const",          S_REGULAR,          typeConstData),<br>
   ENTRY("__DATA", "__cfstring",       S_REGULAR,          typeCFString),<br>
@@ -565,7 +566,8 @@ void Util::copySectionContent(Normalized<br>
     for (AtomInfo &ai : si->atomsAndOffsets) {<br>
       uint8_t *atomContent = reinterpret_cast<uint8_t*><br>
                                           (&sectionContent[ai.offsetInSection]);<br>
-      _archHandler.generateAtomContent(*ai.atom, r, addrForAtom, atomContent);<br>
+      _archHandler.generateAtomContent(*ai.atom, r, addrForAtom,<br>
+                                       _context.baseAddress(), atomContent);<br>
     }<br>
   }<br>
 }<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h (original)<br>
+++ lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h Tue Sep 30 16:29:54 2014<br>
@@ -18,6 +18,7 @@ namespace mach_o {<br>
<br>
 void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx);<br>
 void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx);<br>
+void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx);<br>
<br>
 } // namespace mach_o<br>
 } // namespace lld<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp Tue Sep 30 16:29:54 2014<br>
@@ -439,6 +439,7 @@ template <> struct ScalarEnumerationTrai<br>
     io.enumCase(value, "dtraceDOF",       DefinedAtom::typeDTraceDOF);<br>
     io.enumCase(value, "lto-temp",        DefinedAtom::typeTempLTO);<br>
     io.enumCase(value, "compact-unwind",  DefinedAtom::typeCompactUnwindInfo);<br>
+    io.enumCase(value, "unwind-info",     DefinedAtom::typeProcessedUnwindInfo);<br>
     io.enumCase(value, "tlv-thunk",       DefinedAtom::typeThunkTLV);<br>
     io.enumCase(value, "tlv-data",        DefinedAtom::typeTLVInitialData);<br>
     io.enumCase(value, "tlv-zero-fill",   DefinedAtom::typeTLVInitialZeroFill);<br>
<br>
Modified: lld/trunk/test/mach-o/exe-offsets.yaml<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/exe-offsets.yaml?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/exe-offsets.yaml?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/mach-o/exe-offsets.yaml (original)<br>
+++ lld/trunk/test/mach-o/exe-offsets.yaml Tue Sep 30 16:29:54 2014<br>
@@ -54,6 +54,9 @@ global-symbols:<br>
 # CHECK:     Offset: 0<br>
<br>
 # CHECK-LABEL: Section {<br>
+# CHECK:     Name: __unwind_info<br>
+<br>
+# CHECK-LABEL: Section {<br>
 # CHECK:     Name: __data<br>
 # CHECK:     Segment: __DATA<br>
 # CHECK:     Size: 0x5<br>
<br>
Modified: lld/trunk/test/mach-o/exe-segment-overlap.yaml<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/exe-segment-overlap.yaml?rev=218703&r1=218702&r2=218703&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/exe-segment-overlap.yaml?rev=218703&r1=218702&r2=218703&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/mach-o/exe-segment-overlap.yaml (original)<br>
+++ lld/trunk/test/mach-o/exe-segment-overlap.yaml Tue Sep 30 16:29:54 2014<br>
@@ -43,7 +43,10 @@ global-symbols:<br>
 # CHECK:     Name: __text<br>
 # CHECK:     Segment: __TEXT<br>
 # CHECK:     Size: 0x1<br>
-# CHECK:     Offset: 4095<br>
+# CHECK:     Offset: 4027<br>
+<br>
+# CHECK-LABEL: Section {<br>
+# CHECK:     Name: __unwind_info<br>
<br>
 # CHECK-LABEL: Section {<br>
 # CHECK:     Name: __data<br>
<br>
Added: lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml?rev=218703&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml?rev=218703&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml (added)<br>
+++ lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml Tue Sep 30 16:29:54 2014<br>
@@ -0,0 +1,71 @@<br>
+# RUN: lld -flavor darwin -arch x86_64 %s -o %t -e _main %p/Inputs/libSystem.yaml<br>
+# RUN: llvm-objdump -unwind-info %t | FileCheck %s<br>
+<br>
+# CHECK: Contents of __unwind_info section:<br>
+# CHECK:   Version:                                   0x1<br>
+# CHECK:   Common encodings array section offset:     0x1c<br>
+# CHECK:   Number of common encodings in array:       0x0<br>
+# CHECK:   Personality function array section offset: 0x1c<br>
+# CHECK:   Number of personality functions in array:  0x1<br>
+# CHECK:   Index array section offset:                0x20<br>
+# CHECK:   Number of indices in array:                0x2<br>
+# CHECK:   Common encodings: (count = 0)<br>
+# CHECK:   Personality functions: (count = 1)<br>
+# CHECK:     personality[1]: 0x00001000<br>
+# CHECK:   Top level indices: (count = 2)<br>
+# CHECK:     [0]: function offset=0x00000f7e, 2nd level page offset=0x00000040, LSDA offset=0x00000038<br>
+# CHECK:     [1]: function offset=0x00000f80, 2nd level page offset=0x00000000, LSDA offset=0x00000040<br>
+# CHECK:   LSDA descriptors:<br>
+# CHECK:     [0]: function offset=0x00000f7e, LSDA offset=0x00000f80<br>
+# CHECK:   Second level indices:<br>
+# CHECK:     Second level index[0]: offset in section=0x00000040, base function offset=0x00000f7e<br>
+# CHECK:       [0]: function offset=0x00000f7e, encoding=0x51000000<br>
+# CHECK:       [1]: function offset=0x00000f7f, encoding=0x01000000<br>
+<br>
+--- !native<br>
+path:            '<linker-internal>'<br>
+defined-atoms:<br>
+  - name:            GCC_except_table1<br>
+    type:            unwind-lsda<br>
+    content:         [ FF, 9B, A2, 80, 80, 00, 03, 1A, 08, 00, 00, 00,<br>
+                       05, 00, 00, 00, 1A, 00, 00, 00, 01, 0D, 00, 00,<br>
+                       00, 64, 00, 00, 00, 00, 00, 00, 00, 00, 01, 00,<br>
+                       04, 00, 00, 00 ]<br>
+  - type:            compact-unwind<br>
+    content:         [ 40, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00,<br>
+                       00, 00, 00, 41, 00, 00, 00, 00, 00, 00, 00, 00,<br>
+                       E0, 00, 00, 00, 00, 00, 00, 00 ]<br>
+    references:<br>
+      - kind:            pointer64Anon<br>
+        offset:          0<br>
+        target:          __Z3barv<br>
+      - kind:            pointer64<br>
+        offset:          16<br>
+        target:          ___gxx_personality_v0<br>
+      - kind:            pointer64Anon<br>
+        offset:          24<br>
+        target:          GCC_except_table1<br>
+  - type:            compact-unwind<br>
+    content:         [ C0, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00,<br>
+                       00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00,<br>
+                       00, 00, 00, 00, 00, 00, 00, 00 ]<br>
+    references:<br>
+      - kind:            pointer64Anon<br>
+        offset:          0<br>
+        target:          _main<br>
+<br>
+  - name:            __Z3barv<br>
+    scope:           global<br>
+    content:         [ C3 ]<br>
+  - name:            _main<br>
+    scope:           global<br>
+    content:         [ C3 ]<br>
+    references:<br>
+      - kind:            branch32<br>
+        offset:          9<br>
+        target:          __Z3barv<br>
+<br>
+shared-library-atoms:<br>
+  - name:            ___gxx_personality_v0<br>
+    load-name:       '/usr/lib/libc++abi.dylib'<br>
+    type:            unknown<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>