[lld] r219836 - [mach-o] make __unwind_info defer to __eh_frame when necessary.

Tim Northover tnorthover at apple.com
Wed Oct 15 12:32:21 PDT 2014


Author: tnorthover
Date: Wed Oct 15 14:32:21 2014
New Revision: 219836

URL: http://llvm.org/viewvc/llvm-project?rev=219836&view=rev
Log:
[mach-o] make __unwind_info defer to __eh_frame when necessary.

Not all situations are representable in the compressed __unwind_info format,
and when this happens the entry needs to point to the more general __eh_frame
description.

Just x86_64 implementation for now.

rdar://problem/18208653

Modified:
    lld/trunk/include/lld/Core/Simple.h
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
    lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
    lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml

Modified: lld/trunk/include/lld/Core/Simple.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Simple.h?rev=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Simple.h (original)
+++ lld/trunk/include/lld/Core/Simple.h Wed Oct 15 14:32:21 2014
@@ -168,6 +168,7 @@ public:
   void addReference(Reference::KindNamespace ns, Reference::KindArch arch,
                     Reference::KindValue kindValue, uint64_t off,
                     const Atom *target, Reference::Addend a) {
+    assert(target && "trying to create reference to nothing");
     _references.push_back(SimpleReference(ns, arch, kindValue, off, target, a));
   }
 

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp?rev=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.cpp Wed Oct 15 14:32:21 2014
@@ -142,6 +142,17 @@ int64_t ArchHandler::readS64(bool swap,
   return read64(swap, *reinterpret_cast<const uint64_t*>(addr));
 }
 
+bool ArchHandler::isDwarfCIE(bool swap, const DefinedAtom *atom) {
+  assert(atom->contentType() == DefinedAtom::typeCFI);
+  uint32_t size = read32(swap, *(uint32_t *)atom->rawContent().data());
+
+  uint32_t idOffset = sizeof(uint32_t);
+  if (size == 0xffffffffU)
+    idOffset += sizeof(uint64_t);
+
+  return read32(swap, *(uint32_t *)(atom->rawContent().data() + idOffset)) == 0;
+}
+
 } // namespace mach_o
 } // namespace lld
 

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h Wed Oct 15 14:32:21 2014
@@ -70,11 +70,21 @@ public:
   /// section.
   virtual Reference::KindValue imageOffsetKindIndirect() = 0;
 
+  /// Architecture specific compact unwind type that signals __eh_frame should
+  /// actually be used.
+  virtual uint32_t dwarfCompactUnwindType() = 0;
+
   /// Reference from an __eh_frame FDE atom to the function it's
   /// describing. Usually pointer-sized and PC-relative, but differs in whether
   /// it needs to be in relocatable objects.
   virtual Reference::KindValue unwindRefToFunctionKind() = 0;
 
+  /// Reference from an __unwind_info entry of dwarfCompactUnwindType to the
+  /// required __eh_frame entry. On current architectures, the low 24 bits
+  /// represent the offset of the function's FDE entry from the start of
+  /// __eh_frame.
+  virtual Reference::KindValue unwindRefToEhFrameKind() = 0;
+
   /// Used by normalizedFromAtoms() to know where to generated rebasing and 
   /// binding info in final executables.
   virtual bool isPointer(const Reference &) = 0;
@@ -148,6 +158,7 @@ public:
   /// Copy raw content then apply all fixup References on an Atom.
   virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
                                    FindAddressForAtom findAddress,
+                                   FindAddressForAtom findSectionAddress,
                                    uint64_t imageBaseAddress,
                                    uint8_t *atomContentBuffer) = 0;
 
@@ -196,6 +207,9 @@ public:
     llvm_unreachable("shims only support on arm");
   }
 
+  /// Does a given unwind-cfi atom represent a CIE (as opposed to an FDE).
+  static bool isDwarfCIE(bool swap, const DefinedAtom *atom);
+
   struct ReferenceInfo {
     Reference::KindArch arch;
     uint16_t            kind;

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=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Wed Oct 15 14:32:21 2014
@@ -52,6 +52,15 @@ public:
     return invalid;
   }
 
+  Reference::KindValue unwindRefToEhFrameKind() override {
+    return invalid;
+  }
+
+  uint32_t dwarfCompactUnwindType() override {
+    // FIXME
+    return -1;
+  }
+
   std::error_code getReferenceInfo(const normalized::Relocation &reloc,
                                    const DefinedAtom *inAtom,
                                    uint32_t offsetInAtom,
@@ -75,6 +84,7 @@ public:
 
   void generateAtomContent(const DefinedAtom &atom, bool relocatable,
                            FindAddressForAtom findAddress,
+                           FindAddressForAtom findSectionAddress,
                            uint64_t imageBaseAddress,
                            uint8_t *atomContentBuffer) override;
 
@@ -994,6 +1004,7 @@ void ArchHandler_arm::applyFixupFinal(co
 void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
                                           bool relocatable,
                                           FindAddressForAtom findAddress,
+                                          FindAddressForAtom findSectionAddress,
                                           uint64_t imageBaseAddress,
                                           uint8_t *atomContentBuffer) {
   // Copy raw bytes.

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp?rev=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp Wed Oct 15 14:32:21 2014
@@ -95,6 +95,15 @@ public:
     return invalid;
   }
 
+  Reference::KindValue unwindRefToEhFrameKind() override {
+    return invalid;
+  }
+
+  uint32_t dwarfCompactUnwindType() override {
+    // FIXME
+    return -1;
+  }
+
   std::error_code getReferenceInfo(const normalized::Relocation &reloc,
                                    const DefinedAtom *inAtom,
                                    uint32_t offsetInAtom,
@@ -122,6 +131,7 @@ public:
 
   void generateAtomContent(const DefinedAtom &atom, bool relocatable,
                            FindAddressForAtom findAddress,
+                           FindAddressForAtom findSectionAddress,
                            uint64_t imageBaseAddress,
                            uint8_t *atomContentBuffer) override;
 
@@ -457,11 +467,10 @@ std::error_code ArchHandler_arm64::getPa
   }
 }
 
-void ArchHandler_arm64::generateAtomContent(const DefinedAtom &atom,
-                                            bool relocatable,
-                                            FindAddressForAtom findAddress,
-                                            uint64_t imageBaseAddress,
-                                            uint8_t *atomContentBuffer) {
+void ArchHandler_arm64::generateAtomContent(
+    const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
+    FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
+    uint8_t *atomContentBuffer) {
   // Copy raw bytes.
   memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
   // Apply fix-ups.

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=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp Wed Oct 15 14:32:21 2014
@@ -55,6 +55,15 @@ public:
     return delta32;
   }
 
+  Reference::KindValue unwindRefToEhFrameKind() override {
+    return invalid;
+  }
+
+
+  uint32_t dwarfCompactUnwindType() override {
+    return 0x04000000U;
+  }
+
   std::error_code getReferenceInfo(const normalized::Relocation &reloc,
                                    const DefinedAtom *inAtom,
                                    uint32_t offsetInAtom,
@@ -78,6 +87,7 @@ public:
 
   void generateAtomContent(const DefinedAtom &atom, bool relocatable,
                            FindAddressForAtom findAddress,
+                           FindAddressForAtom findSectionAddress,
                            uint64_t imageBaseAddress,
                            uint8_t *atomContentBuffer) override;
 
@@ -386,6 +396,7 @@ ArchHandler_x86::getPairReferenceInfo(co
 void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,
                                           bool relocatable,
                                           FindAddressForAtom findAddress,
+                                          FindAddressForAtom findSectionAddress,
                                           uint64_t imageBaseAddress,
                                           uint8_t *atomContentBuffer) {
   // Copy raw bytes.

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=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Wed Oct 15 14:32:21 2014
@@ -88,6 +88,13 @@ public:
     return unwindFDEToFunction;
   }
 
+  Reference::KindValue unwindRefToEhFrameKind() override {
+    return unwindInfoToEhFrame;
+  }
+
+  uint32_t dwarfCompactUnwindType() override {
+    return 0x04000000U;
+  }
 
   const StubInfo &stubInfo() override { return _sStubInfo; }
 
@@ -126,6 +133,7 @@ public:
 
   void generateAtomContent(const DefinedAtom &atom, bool relocatable,
                            FindAddressForAtom findAddress,
+                           FindAddressForAtom findSectionAddress,
                            uint64_t imageBase,
                            uint8_t *atomContentBuffer) override;
 
@@ -172,7 +180,8 @@ private:
                            /// final image (typically personality function).
     unwindFDEToFunction,   /// Nearly delta64, but cannot be rematerialized in
                            /// relocatable object (yay for implicit contracts!).
-
+    unwindInfoToEhFrame,   /// Fix low 24 bits of compact unwind encoding to
+                           /// refer to __eh_frame entry.
   };
 
   Reference::KindValue kindFromReloc(const normalized::Relocation &reloc);
@@ -181,7 +190,8 @@ private:
 
   void applyFixupFinal(const Reference &ref, uint8_t *location,
                        uint64_t fixupAddress, uint64_t targetAddress,
-                       uint64_t inAtomAddress, uint64_t imageBaseAddress);
+                       uint64_t inAtomAddress, uint64_t imageBaseAddress,
+                       FindAddressForAtom findSectionAddress);
 
   void applyFixupRelocatable(const Reference &ref, uint8_t *location,
                              uint64_t fixupAddress,
@@ -210,6 +220,7 @@ const Registry::KindStrings ArchHandler_
   LLD_KIND_STRING_ENTRY(delta32Anon), LLD_KIND_STRING_ENTRY(delta64Anon),
   LLD_KIND_STRING_ENTRY(imageOffset), LLD_KIND_STRING_ENTRY(imageOffsetGot),
   LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
+  LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
   LLD_KIND_STRING_END
 };
 
@@ -424,11 +435,10 @@ ArchHandler_x86_64::getPairReferenceInfo
   }
 }
 
-void ArchHandler_x86_64::generateAtomContent(const DefinedAtom &atom,
-                                             bool relocatable,
-                                             FindAddressForAtom findAddress,
-                                             uint64_t imageBaseAddress,
-                                             uint8_t *atomContentBuffer) {
+void ArchHandler_x86_64::generateAtomContent(
+    const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
+    FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
+    uint8_t *atomContentBuffer) {
   // Copy raw bytes.
   memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
   // Apply fix-ups.
@@ -447,17 +457,15 @@ void ArchHandler_x86_64::generateAtomCon
     } else {
       applyFixupFinal(*ref, &atomContentBuffer[offset],
                       fixupAddress, targetAddress,
-                      atomAddress, imageBaseAddress);
+                      atomAddress, imageBaseAddress, findSectionAddress);
     }
   }
 }
 
-void ArchHandler_x86_64::applyFixupFinal(const Reference &ref,
-                                         uint8_t *location,
-                                         uint64_t fixupAddress,
-                                         uint64_t targetAddress,
-                                         uint64_t inAtomAddress,
-                                         uint64_t imageBaseAddress) {
+void ArchHandler_x86_64::applyFixupFinal(
+    const Reference &ref, uint8_t *location, uint64_t fixupAddress,
+    uint64_t targetAddress, uint64_t inAtomAddress, uint64_t imageBaseAddress,
+    FindAddressForAtom findSectionAddress) {
   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
     return;
   assert(ref.kindArch() == Reference::KindArch::x86_64);
@@ -507,6 +515,13 @@ void ArchHandler_x86_64::applyFixupFinal
   case imageOffsetGot:
     write32(*loc32, _swap, (targetAddress - imageBaseAddress) + ref.addend());
     return;
+  case unwindInfoToEhFrame: {
+    uint64_t val = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
+    assert(val < 0xffffffU && "offset in __eh_frame too large");
+    uint32_t encoding = read32(_swap, *loc32) & 0xff000000U;
+    write32(*loc32, _swap, encoding | val);
+    return;
+  }
   case invalid:
     // Fall into llvm_unreachable().
     break;
@@ -568,7 +583,8 @@ void ArchHandler_x86_64::applyFixupReloc
     return;
   case imageOffset:
   case imageOffsetGot:
-    llvm_unreachable("image offset implies __unwind_info");
+  case unwindInfoToEhFrame:
+    llvm_unreachable("fixup implies __unwind_info");
     return;
   case unwindFDEToFunction:
     // Do nothing for now
@@ -658,6 +674,7 @@ void ArchHandler_x86_64::appendSectionRe
                 X86_64_RELOC_UNSIGNED             | rLength8 );
     return;
   case unwindFDEToFunction:
+  case unwindInfoToEhFrame:
     return;
   case ripRel32GotLoadNowLea:
     llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");

Modified: lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp?rev=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp Wed Oct 15 14:32:21 2014
@@ -39,9 +39,26 @@ struct CompactUnwindEntry {
   const Atom *rangeStart;
   const Atom *personalityFunction;
   const Atom *lsdaLocation;
+  const Atom *ehFrame;
 
   uint32_t rangeLength;
+
+  // There are 3 types of compact unwind entry, distinguished by the encoding
+  // value: 0 indicates a function with no unwind info;
+  // _archHandler.dwarfCompactUnwindType() indicates that the entry defers to
+  // __eh_frame, and that the ehFrame entry will be valid; any other value is a
+  // real compact unwind entry -- personalityFunction will be set and
+  // lsdaLocation may be.
   uint32_t encoding;
+
+  CompactUnwindEntry(const DefinedAtom *function)
+      : rangeStart(function), personalityFunction(nullptr),
+        lsdaLocation(nullptr), ehFrame(nullptr), rangeLength(function->size()),
+        encoding(0) {}
+
+  CompactUnwindEntry()
+      : rangeStart(nullptr), personalityFunction(nullptr),
+        lsdaLocation(nullptr), ehFrame(nullptr), rangeLength(0), encoding(0) {}
 };
 
 struct UnwindInfoPage {
@@ -212,12 +229,23 @@ public:
     uint32_t pagePos = curPageOffset + headerSize;
     for (auto &entry : page.entries) {
       addImageReference(pagePos, entry.rangeStart);
+
       write32(reinterpret_cast<int32_t *>(_contents.data() + pagePos)[1], _swap,
               entry.encoding);
+      if ((entry.encoding & 0x0f000000U) ==
+          _archHandler.dwarfCompactUnwindType())
+        addEhFrameReference(pagePos + sizeof(uint32_t), entry.ehFrame);
+
       pagePos += 2 * sizeof(uint32_t);
     }
   }
 
+  void addEhFrameReference(uint32_t offset, const Atom *dest,
+                           Reference::Addend addend = 0) {
+    addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
+                 _archHandler.unwindRefToEhFrameKind(), offset, dest, addend);
+  }
+
   void addImageReference(uint32_t offset, const Atom *dest,
                          Reference::Addend addend = 0) {
     addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
@@ -253,15 +281,18 @@ private:
   void perform(std::unique_ptr<MutableFile> &mergedFile) override {
     DEBUG(llvm::dbgs() << "MachO Compact Unwind pass\n");
 
-    // First collect all __compact_unwind entries, addressable by the function
-    // it's referring to.
     std::map<const Atom *, CompactUnwindEntry> unwindLocs;
+    std::map<const Atom *, const Atom *> dwarfFrames;
     std::vector<const Atom *> personalities;
     uint32_t numLSDAs = 0;
 
+    // First collect all __compact_unwind and __eh_frame entries, addressable by
+    // the function referred to.
     collectCompactUnwindEntries(mergedFile, unwindLocs, personalities,
                                 numLSDAs);
 
+    collectDwarfFrameEntries(mergedFile, dwarfFrames);
+
     // FIXME: if there are more than 4 personality functions then we need to
     // defer to DWARF info for the ones we don't put in the list. They should
     // also probably be sorted by frequency.
@@ -270,8 +301,8 @@ private:
     // Now sort the entries by final address and fixup the compact encoding to
     // its final form (i.e. set personality function bits & create DWARF
     // references where needed).
-    std::vector<CompactUnwindEntry> unwindInfos =
-        createUnwindInfoEntries(mergedFile, unwindLocs, personalities);
+    std::vector<CompactUnwindEntry> unwindInfos = createUnwindInfoEntries(
+        mergedFile, unwindLocs, personalities, dwarfFrames);
 
     // Finally, we can start creating pages based on these entries.
 
@@ -348,7 +379,7 @@ private:
   }
 
   CompactUnwindEntry extractCompactUnwindEntry(const DefinedAtom *atom) {
-    CompactUnwindEntry entry = {nullptr, nullptr, nullptr, 0, 0};
+    CompactUnwindEntry entry;
 
     for (const Reference *ref : *atom) {
       switch (ref->offsetInAtom()) {
@@ -376,6 +407,28 @@ private:
     return entry;
   }
 
+  void
+  collectDwarfFrameEntries(std::unique_ptr<MutableFile> &mergedFile,
+                           std::map<const Atom *, const Atom *> &dwarfFrames) {
+    for (const DefinedAtom *ehFrameAtom : mergedFile->defined()) {
+      if (ehFrameAtom->contentType() != DefinedAtom::typeCFI ||
+          ArchHandler::isDwarfCIE(_swap, ehFrameAtom))
+        continue;
+
+      auto functionRef = std::find_if(ehFrameAtom->begin(), ehFrameAtom->end(),
+                                      [&](const Reference *ref) {
+        return ref->kindNamespace() == Reference::KindNamespace::mach_o &&
+               ref->kindArch() == _archHandler.kindArch() &&
+               ref->kindValue() == _archHandler.unwindRefToFunctionKind();
+      });
+
+      if (functionRef != ehFrameAtom->end()) {
+        const Atom *functionAtom = functionRef->target();
+        dwarfFrames.insert(std::make_pair(functionAtom, ehFrameAtom));
+      }
+    }
+  }
+
   /// Every atom defined in __TEXT,__text needs an entry in the final
   /// __unwind_info section (in order). These comes from two sources:
   ///   + Input __compact_unwind sections where possible (after adding the
@@ -385,7 +438,8 @@ private:
   std::vector<CompactUnwindEntry> createUnwindInfoEntries(
       const std::unique_ptr<MutableFile> &mergedFile,
       const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
-      const std::vector<const Atom *> &personalities) {
+      const std::vector<const Atom *> &personalities,
+      const std::map<const Atom *, const Atom *> &dwarfFrames) {
     std::vector<CompactUnwindEntry> unwindInfos;
 
     DEBUG(llvm::dbgs() << "  Creating __unwind_info entries\n");
@@ -396,8 +450,8 @@ private:
       if (atom->contentType() != DefinedAtom::typeCode)
         continue;
 
-      unwindInfos.push_back(
-          finalizeUnwindInfoEntryForAtom(atom, unwindLocs, personalities));
+      unwindInfos.push_back(finalizeUnwindInfoEntryForAtom(
+          atom, unwindLocs, personalities, dwarfFrames));
 
       DEBUG(llvm::dbgs() << "    Entry for " << atom->name()
                          << ", final encoding="
@@ -411,20 +465,32 @@ private:
   CompactUnwindEntry finalizeUnwindInfoEntryForAtom(
       const DefinedAtom *function,
       const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
-      const std::vector<const Atom *> &personalities) {
+      const std::vector<const Atom *> &personalities,
+      const std::map<const Atom *, const Atom *> &dwarfFrames) {
     auto unwindLoc = unwindLocs.find(function);
 
-    // FIXME: we should synthesize a DWARF compact unwind entry before claiming
-    // there's no unwind if a __compact_unwind atom doesn't exist.
+    CompactUnwindEntry entry;
     if (unwindLoc == unwindLocs.end()) {
-      CompactUnwindEntry entry;
-      memset(&entry, 0, sizeof(CompactUnwindEntry));
+      // Default entry has correct encoding (0 => no unwind), but we need to
+      // synthesise the function.
       entry.rangeStart = function;
       entry.rangeLength = function->size();
-      return entry;
+    } else
+      entry = unwindLoc->second;
+
+
+    // If there's no __compact_unwind entry, or it explicitly says to use
+    // __eh_frame, we need to try and fill in the correct DWARF atom.
+    if (entry.encoding == _archHandler.dwarfCompactUnwindType() ||
+        entry.encoding == 0) {
+      auto dwarfFrame = dwarfFrames.find(function);
+      if (dwarfFrame != dwarfFrames.end()) {
+        entry.encoding = _archHandler.dwarfCompactUnwindType();
+        entry.ehFrame = dwarfFrame->second;
+      }
     }
 
-    CompactUnwindEntry entry = unwindLoc->second;
+
     auto personality = std::find(personalities.begin(), personalities.end(),
                                  entry.personalityFunction);
     uint32_t personalityIdx = personality == personalities.end()

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Wed Oct 15 14:32:21 2014
@@ -556,6 +556,14 @@ void Util::copySectionContent(Normalized
     return pos->second;
   };
 
+  auto sectionAddrForAtom = [&] (const Atom &atom) -> uint64_t {
+    for (const SectionInfo *sectInfo : _sectionInfos)
+      for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets)
+        if (atomInfo.atom == &atom)
+          return sectInfo->address;
+    llvm_unreachable("atom not assigned to section");
+  };
+
   for (SectionInfo *si : _sectionInfos) {
     if (si->type == llvm::MachO::S_ZEROFILL)
       continue;
@@ -567,6 +575,7 @@ void Util::copySectionContent(Normalized
       uint8_t *atomContent = reinterpret_cast<uint8_t*>
                                           (&sectionContent[ai.offsetInSection]);
       _archHandler.generateAtomContent(*ai.atom, r, addrForAtom,
+                                       sectionAddrForAtom,
                                        _context.baseAddress(), atomContent);
     }
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Wed Oct 15 14:32:21 2014
@@ -621,17 +621,6 @@ bool isDebugInfoSection(const Section &s
   return section.segmentName.equals("__DWARF");
 }
 
-static bool isCIE(bool swap, const DefinedAtom *atom) {
-  assert(atom->contentType() == DefinedAtom::typeCFI);
-  uint32_t size = read32(swap, *(uint32_t *)atom->rawContent().data());
-
-  uint32_t idOffset = sizeof(uint32_t);
-  if (size == 0xffffffffU)
-    idOffset += sizeof(uint64_t);
-
-  return read32(swap, *(uint32_t *)(atom->rawContent().data() + idOffset)) == 0;
-}
-
 static int64_t readSPtr(bool is64, bool swap, const uint8_t *addr) {
   if (is64)
     return read64(swap, *reinterpret_cast<const uint64_t *>(addr));
@@ -662,7 +651,7 @@ std::error_code addEHFrameReferences(con
                          [&](MachODefinedAtom *atom, uint64_t offset) -> void {
     assert(atom->contentType() == DefinedAtom::typeCFI);
 
-    if (isCIE(swap, atom))
+    if (ArchHandler::isDwarfCIE(swap, atom))
       return;
 
     // Compiler wasn't lazy and actually told us what it meant.

Modified: lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml?rev=219836&r1=219835&r2=219836&view=diff
==============================================================================
--- lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml (original)
+++ lld/trunk/test/mach-o/unwind-info-simple-x86_64.yaml Wed Oct 15 14:32:21 2014
@@ -13,14 +13,17 @@
 # CHECK:   Personality functions: (count = 1)
 # CHECK:     personality[1]: 0x00001000
 # CHECK:   Top level indices: (count = 2)
-# CHECK:     [0]: function offset=0x00000f7e, 2nd level page offset=0x00000040, LSDA offset=0x00000038
-# CHECK:     [1]: function offset=0x00000f80, 2nd level page offset=0x00000000, LSDA offset=0x00000040
+# CHECK:     [0]: function offset=0x00000efb, 2nd level page offset=0x00000040, LSDA offset=0x00000038
+# CHECK:     [1]: function offset=0x00000f00, 2nd level page offset=0x00000000, LSDA offset=0x00000040
 # CHECK:   LSDA descriptors:
-# CHECK:     [0]: function offset=0x00000f7e, LSDA offset=0x00000f80
+# CHECK:     [0]: function offset=0x00000efb, LSDA offset=0x00000f00
 # CHECK:   Second level indices:
-# CHECK:     Second level index[0]: offset in section=0x00000040, base function offset=0x00000f7e
-# CHECK:       [0]: function offset=0x00000f7e, encoding=0x51000000
-# CHECK:       [1]: function offset=0x00000f7f, encoding=0x01000000
+# CHECK:     Second level index[0]: offset in section=0x00000040, base function offset=0x00000efb
+# CHECK:       [0]: function offset=0x00000efb, encoding=0x51000000
+# CHECK:       [1]: function offset=0x00000efc, encoding=0x01000000
+# CHECK:       [2]: function offset=0x00000efd, encoding=0x04000018
+# CHECK:       [3]: function offset=0x00000efe, encoding=0x04000040
+# CHECK:       [4]: function offset=0x00000eff, encoding=0x00000000
 
 --- !native
 path:            '<linker-internal>'
@@ -53,6 +56,40 @@ defined-atoms:
       - kind:            pointer64Anon
         offset:          0
         target:          _main
+  - type:            compact-unwind
+    content:         [ C1, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00,
+                       00, 00, 00, 04, 00, 00, 00, 00, 00, 00, 00, 00,
+                       00, 00, 00, 00, 00, 00, 00, 00 ]
+    references:
+      - kind:            pointer64Anon
+        offset:          0
+        target:          _needsDwarfButNoCompactUnwind
+
+# Generic x86_64 CIE:
+  - type:            unwind-cfi
+    content:         [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00, 
+                       01, 78, 10, 01, 10, 0C, 07, 08, 90, 01, 00, 00 ]
+
+  - type:            unwind-cfi
+    content:         [ 24, 00, 00, 00, 1C, 00, 00, 00, C8, FE, FF, FF,
+                       FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
+                       00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
+                       00, 00, 00, 00 ]
+    references:
+      - kind:            unwindFDEToFunction
+        offset:          8
+        target:          _needsDwarfButNoCompactUnwind
+
+  - type:            unwind-cfi
+    content:         [ 24, 00, 00, 00, 44, 00, 00, 00, C8, FE, FF, FF,
+                       FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
+                       00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
+                       00, 00, 00, 00 ]
+    references:
+      - kind:            unwindFDEToFunction
+        offset:          8
+        target:          _needsDwarfSaysCompactUnwind
+
 
   - name:            __Z3barv
     scope:           global
@@ -64,6 +101,15 @@ defined-atoms:
       - kind:            branch32
         offset:          9
         target:          __Z3barv
+  - name:            _needsDwarfButNoCompactUnwind
+    scope:           global
+    content:         [ C3 ]
+  - name:            _needsDwarfSaysCompactUnwind
+    scope:           global
+    content:         [ C3 ]
+  - name:            _noUnwindData
+    scope:           global
+    content:         [ C3 ]
 
 shared-library-atoms:
   - name:            ___gxx_personality_v0





More information about the llvm-commits mailing list