[llvm] 3507df9 - [ORC][ORC-RT] Add support for callback-based lookup of JIT'd MachO unwind info.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 19 22:39:31 PST 2023


Author: Lang Hames
Date: 2023-01-19T22:37:57-08:00
New Revision: 3507df9c20a4e117a27c005d7ceb5d1468378aa2

URL: https://github.com/llvm/llvm-project/commit/3507df9c20a4e117a27c005d7ceb5d1468378aa2
DIFF: https://github.com/llvm/llvm-project/commit/3507df9c20a4e117a27c005d7ceb5d1468378aa2.diff

LOG: [ORC][ORC-RT] Add support for callback-based lookup of JIT'd MachO unwind info.

In LLVM the MachOPlatform class is modified to identify unwind info sections
and the address ranges of the functions these sections cover. These address
ranges are then communicated to the ORC runtime by attaching them to the
register-object-platform-sections allocation action.

In the ORC runtime the unwind-info section addresses are recorded and used to
support lookup of unwind info via the new `findDynamicUnwindSections` function.
At bootstrap time the ORC runtime checks for the presence of new
unwind-info-lookup-registration functions in libunwind (see
https://reviews.llvm.org/D142176), and if available uses them to register the
`findDynamicUnwindSections` function with libunwind to enable callback-based
lookup. If the new unwind-info-lookup-registration functions are not available
then the ORC runtime falls back to using the existing libunwind registration
APIs.

The callback-based scheme is intended to address three shortcomings in the
current registration scheme for JIT'd unwind info on Darwin: (1) Lack of
compact-unwind support, (2) inability to describe the subarchitecture of JIT'd
frames, and (3) lack of efficient address-based lookup data structures in
libunwind.

For more details see the proposed libunwind changes in
https://reviews.llvm.org/D142176.

Added: 
    

Modified: 
    compiler-rt/lib/orc/macho_platform.cpp
    llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
    llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp
index 5a5c8e49e0b10..9b5b954921c1f 100644
--- a/compiler-rt/lib/orc/macho_platform.cpp
+++ b/compiler-rt/lib/orc/macho_platform.cpp
@@ -71,6 +71,26 @@ extern "C" void swift_registerTypeMetadataRecords(
     const TypeMetadataRecord *begin,
     const TypeMetadataRecord *end) ORC_RT_WEAK_IMPORT;
 
+// Libunwind prototypes.
+struct unw_dynamic_unwind_sections {
+  uintptr_t dso_base;
+  uintptr_t dwarf_section;
+  size_t dwarf_section_length;
+  uintptr_t compact_unwind_section;
+  size_t compact_unwind_section_length;
+};
+
+typedef int (*unw_find_dynamic_unwind_sections)(
+    uintptr_t addr, struct unw_dynamic_unwind_sections *info);
+
+extern "C" int __unw_add_find_dynamic_unwind_sections(
+    unw_find_dynamic_unwind_sections find_dynamic_unwind_sections)
+    ORC_RT_WEAK_IMPORT;
+
+extern "C" int __unw_remove_find_dynamic_unwind_sections(
+    unw_find_dynamic_unwind_sections find_dynamic_unwind_sections)
+    ORC_RT_WEAK_IMPORT;
+
 namespace {
 
 struct MachOJITDylibDepInfo {
@@ -111,6 +131,35 @@ class SPSSerializationTraits<SPSMachOJITDylibDepInfo, MachOJITDylibDepInfo> {
   }
 };
 
+struct UnwindSectionInfo {
+  std::vector<ExecutorAddrRange> CodeRanges;
+  ExecutorAddrRange DwarfSection;
+  ExecutorAddrRange CompactUnwindSection;
+};
+
+using SPSUnwindSectionInfo =
+    SPSTuple<SPSSequence<SPSExecutorAddrRange>, SPSExecutorAddrRange,
+             SPSExecutorAddrRange>;
+
+template <>
+class SPSSerializationTraits<SPSUnwindSectionInfo, UnwindSectionInfo> {
+public:
+  static size_t size(const UnwindSectionInfo &USI) {
+    return SPSUnwindSectionInfo::AsArgList::size(
+        USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection);
+  }
+
+  static bool serialize(SPSOutputBuffer &OB, const UnwindSectionInfo &USI) {
+    return SPSUnwindSectionInfo::AsArgList::serialize(
+        OB, USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection);
+  }
+
+  static bool deserialize(SPSInputBuffer &IB, UnwindSectionInfo &USI) {
+    return SPSUnwindSectionInfo::AsArgList::deserialize(
+        IB, USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection);
+  }
+};
+
 } // namespace __orc_rt
 
 namespace {
@@ -216,6 +265,18 @@ class MachOPlatformRuntimeState {
     std::vector<span<RecordElement>> New;
   };
 
+  struct UnwindSections {
+    UnwindSections(const UnwindSectionInfo &USI)
+        : DwarfSection(USI.DwarfSection.toSpan<char>()),
+          CompactUnwindSection(USI.CompactUnwindSection.toSpan<char>()) {}
+
+    span<char> DwarfSection;
+    span<char> CompactUnwindSection;
+  };
+
+  using UnwindSectionsMap =
+      IntervalMap<char *, UnwindSections, IntervalCoalescing::Disabled>;
+
   struct JITDylibState {
     std::string Name;
     void *Header = nullptr;
@@ -227,6 +288,7 @@ class MachOPlatformRuntimeState {
     const objc_image_info *ObjCImageInfo = nullptr;
     std::unordered_map<void *, std::vector<char>> DataSectionContent;
     std::unordered_map<void *, size_t> ZeroInitRanges;
+    UnwindSectionsMap UnwindSections;
     RecordSectionsTracker<void (*)()> ModInitsSections;
     RecordSectionsTracker<void *> ObjCClassListSections;
     RecordSectionsTracker<void *> ObjCSelRefsSections;
@@ -240,9 +302,9 @@ class MachOPlatformRuntimeState {
   };
 
 public:
-  static void initialize();
+  static Error create();
   static MachOPlatformRuntimeState &get();
-  static void destroy();
+  static Error destroy();
 
   MachOPlatformRuntimeState() = default;
 
@@ -253,15 +315,18 @@ class MachOPlatformRuntimeState {
   MachOPlatformRuntimeState(MachOPlatformRuntimeState &&) = delete;
   MachOPlatformRuntimeState &operator=(MachOPlatformRuntimeState &&) = delete;
 
+  Error initialize();
+  Error shutdown();
+
   Error registerJITDylib(std::string Name, void *Header);
   Error deregisterJITDylib(void *Header);
   Error registerThreadDataSection(span<const char> ThreadDataSection);
   Error deregisterThreadDataSection(span<const char> ThreadDataSection);
   Error registerObjectPlatformSections(
-      ExecutorAddr HeaderAddr,
+      ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindSections,
       std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs);
   Error deregisterObjectPlatformSections(
-      ExecutorAddr HeaderAddr,
+      ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindSections,
       std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs);
 
   const char *dlerror();
@@ -285,6 +350,10 @@ class MachOPlatformRuntimeState {
   Expected<ExecutorAddr> lookupSymbolInJITDylib(void *DSOHandle,
                                                 std::string_view Symbol);
 
+  bool lookupUnwindSections(void *Addr, unw_dynamic_unwind_sections &Info);
+
+  static int findDynamicUnwindSections(uintptr_t addr,
+                                       unw_dynamic_unwind_sections *info);
   static Error registerEHFrames(span<const char> EHFrameSection);
   static Error deregisterEHFrames(span<const char> EHFrameSection);
 
@@ -308,6 +377,8 @@ class MachOPlatformRuntimeState {
 
   static MachOPlatformRuntimeState *MOPS;
 
+  bool UseCallbackStyleUnwindInfo = false;
+
   // FIXME: Move to thread-state.
   std::string DLFcnError;
 
@@ -327,9 +398,10 @@ class MachOPlatformRuntimeState {
 
 MachOPlatformRuntimeState *MachOPlatformRuntimeState::MOPS = nullptr;
 
-void MachOPlatformRuntimeState::initialize() {
+Error MachOPlatformRuntimeState::create() {
   assert(!MOPS && "MachOPlatformRuntimeState should be null");
   MOPS = new MachOPlatformRuntimeState();
+  return MOPS->initialize();
 }
 
 MachOPlatformRuntimeState &MachOPlatformRuntimeState::get() {
@@ -337,9 +409,42 @@ MachOPlatformRuntimeState &MachOPlatformRuntimeState::get() {
   return *MOPS;
 }
 
-void MachOPlatformRuntimeState::destroy() {
+Error MachOPlatformRuntimeState::destroy() {
   assert(MOPS && "MachOPlatformRuntimeState not initialized");
+  auto Err = MOPS->shutdown();
   delete MOPS;
+  return Err;
+}
+
+Error MachOPlatformRuntimeState::initialize() {
+  UseCallbackStyleUnwindInfo = __unw_add_find_dynamic_unwind_sections &&
+                               __unw_remove_find_dynamic_unwind_sections;
+  if (UseCallbackStyleUnwindInfo) {
+    ORC_RT_DEBUG({
+      printdbg("__unw_add/remove_find_dynamic_unwind_sections available."
+               " Using callback-based frame info lookup.\n");
+    });
+    if (__unw_add_find_dynamic_unwind_sections(&findDynamicUnwindSections))
+      return make_error<StringError>(
+          "Could not register findDynamicUnwindSections");
+  } else {
+    ORC_RT_DEBUG({
+      printdbg("__unw_add/remove_find_dynamic_unwind_sections not available."
+               " Using classic frame info registration.\n");
+    });
+  }
+  return Error::success();
+}
+
+Error MachOPlatformRuntimeState::shutdown() {
+  if (__unw_add_find_dynamic_unwind_sections &&
+      __unw_remove_find_dynamic_unwind_sections) {
+    if (__unw_remove_find_dynamic_unwind_sections(&findDynamicUnwindSections)) {
+      ORC_RT_DEBUG(
+          { printdbg("__unw_remove_find_dynamic_unwind_sections failed.\n"); });
+    }
+  }
+  return Error::success();
 }
 
 Error MachOPlatformRuntimeState::registerJITDylib(std::string Name,
@@ -419,7 +524,7 @@ Error MachOPlatformRuntimeState::deregisterThreadDataSection(
 }
 
 Error MachOPlatformRuntimeState::registerObjectPlatformSections(
-    ExecutorAddr HeaderAddr,
+    ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindInfo,
     std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs) {
 
   // FIXME: Reject platform section registration after the JITDylib is
@@ -440,11 +545,35 @@ Error MachOPlatformRuntimeState::registerObjectPlatformSections(
     return make_error<StringError>(ErrStream.str());
   }
 
+  if (UnwindInfo && UseCallbackStyleUnwindInfo) {
+    ORC_RT_DEBUG({
+      printdbg("  Registering new-style unwind info for:\n"
+               "    DWARF: %p -- %p\n"
+               "    Compact-unwind: %p -- %p\n"
+               "  for:\n",
+               UnwindInfo->DwarfSection.Start.toPtr<void *>(),
+               UnwindInfo->DwarfSection.End.toPtr<void *>(),
+               UnwindInfo->CompactUnwindSection.Start.toPtr<void *>(),
+               UnwindInfo->CompactUnwindSection.End.toPtr<void *>());
+    });
+    for (auto &CodeRange : UnwindInfo->CodeRanges) {
+      JDS->UnwindSections.insert(CodeRange.Start.toPtr<char *>(),
+                                 CodeRange.End.toPtr<char *>(), *UnwindInfo);
+      ORC_RT_DEBUG({
+        printdbg("    [ %p -- %p ]\n", CodeRange.Start.toPtr<void *>(),
+                 CodeRange.End.toPtr<void *>());
+      });
+    }
+  }
+
   for (auto &KV : Secs) {
     // FIXME: Validate section ranges?
     if (KV.first == "__TEXT,__eh_frame") {
-      if (auto Err = registerEHFrames(KV.second.toSpan<const char>()))
-        return Err;
+      if (!UseCallbackStyleUnwindInfo) {
+        // Use classic libunwind registration.
+        if (auto Err = registerEHFrames(KV.second.toSpan<const char>()))
+          return Err;
+      }
     } else if (KV.first == "__DATA,__data") {
       assert(!JDS->DataSectionContent.count(KV.second.Start.toPtr<char *>()) &&
              "Address already registered.");
@@ -483,7 +612,7 @@ Error MachOPlatformRuntimeState::registerObjectPlatformSections(
 }
 
 Error MachOPlatformRuntimeState::deregisterObjectPlatformSections(
-    ExecutorAddr HeaderAddr,
+    ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindInfo,
     std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs) {
   // TODO: Make this more efficient? (maybe unnecessary if removal is rare?)
   // TODO: Add a JITDylib prepare-for-teardown operation that clears all
@@ -510,11 +639,35 @@ Error MachOPlatformRuntimeState::deregisterObjectPlatformSections(
   // any Swift or ObjC. Once this happens we can clear (and no longer record)
   // data section content, as the library could never be re-initialized.
 
+  if (UnwindInfo && UseCallbackStyleUnwindInfo) {
+    ORC_RT_DEBUG({
+      printdbg("  Deregistering new-style unwind info for:\n"
+               "    DWARF: %p -- %p\n"
+               "    Compact-unwind: %p -- %p\n"
+               "  for:\n",
+               UnwindInfo->DwarfSection.Start.toPtr<void *>(),
+               UnwindInfo->DwarfSection.End.toPtr<void *>(),
+               UnwindInfo->CompactUnwindSection.Start.toPtr<void *>(),
+               UnwindInfo->CompactUnwindSection.End.toPtr<void *>());
+    });
+    for (auto &CodeRange : UnwindInfo->CodeRanges) {
+      JDS->UnwindSections.erase(CodeRange.Start.toPtr<char *>(),
+                                CodeRange.End.toPtr<char *>());
+      ORC_RT_DEBUG({
+        printdbg("    [ %p -- %p ]\n", CodeRange.Start.toPtr<void *>(),
+                 CodeRange.End.toPtr<void *>());
+      });
+    }
+  }
+
   for (auto &KV : Secs) {
     // FIXME: Validate section ranges?
     if (KV.first == "__TEXT,__eh_frame") {
-      if (auto Err = deregisterEHFrames(KV.second.toSpan<const char>()))
-        return Err;
+      if (!UseCallbackStyleUnwindInfo) {
+        // Use classic libunwind registration.
+        if (auto Err = deregisterEHFrames(KV.second.toSpan<const char>()))
+          return Err;
+      }
     } else if (KV.first == "__DATA,__data") {
       JDS->DataSectionContent.erase(KV.second.Start.toPtr<char *>());
     } else if (KV.first == "__DATA,__common") {
@@ -710,6 +863,37 @@ void walkEHFrameSection(span<const char> EHFrameSection,
   }
 }
 
+bool MachOPlatformRuntimeState::lookupUnwindSections(
+    void *Addr, unw_dynamic_unwind_sections &Info) {
+  ORC_RT_DEBUG(
+      { printdbg("Tried to lookup unwind-info via new lookup call.\n"); });
+  std::lock_guard<std::mutex> Lock(JDStatesMutex);
+  for (auto &KV : JDStates) {
+    auto &JD = KV.second;
+    auto I = JD.UnwindSections.find(reinterpret_cast<char *>(Addr));
+    if (I != JD.UnwindSections.end()) {
+      Info.dso_base = reinterpret_cast<uintptr_t>(JD.Header);
+      Info.dwarf_section =
+          reinterpret_cast<uintptr_t>(I->second.DwarfSection.data());
+      Info.dwarf_section_length = I->second.DwarfSection.size();
+      Info.compact_unwind_section =
+          reinterpret_cast<uintptr_t>(I->second.CompactUnwindSection.data());
+      Info.compact_unwind_section_length =
+          I->second.CompactUnwindSection.size();
+      return true;
+    }
+  }
+  return false;
+}
+
+int MachOPlatformRuntimeState::findDynamicUnwindSections(
+    uintptr_t addr, unw_dynamic_unwind_sections *info) {
+  if (!info)
+    return 0;
+  return MachOPlatformRuntimeState::get().lookupUnwindSections((void *)addr,
+                                                               *info);
+}
+
 Error MachOPlatformRuntimeState::registerEHFrames(
     span<const char> EHFrameSection) {
   walkEHFrameSection(EHFrameSection, __register_frame);
@@ -1101,10 +1285,7 @@ ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
 __orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) {
   return WrapperFunction<SPSError()>::handle(
              ArgData, ArgSize,
-             []() -> Error {
-               MachOPlatformRuntimeState::initialize();
-               return Error::success();
-             })
+             []() { return MachOPlatformRuntimeState::create(); })
       .release();
 }
 
@@ -1112,10 +1293,7 @@ ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
 __orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) {
   return WrapperFunction<SPSError()>::handle(
              ArgData, ArgSize,
-             []() -> Error {
-               MachOPlatformRuntimeState::destroy();
-               return Error::success();
-             })
+             []() { return MachOPlatformRuntimeState::destroy(); })
       .release();
 }
 
@@ -1145,13 +1323,15 @@ ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
 __orc_rt_macho_register_object_platform_sections(char *ArgData,
                                                  size_t ArgSize) {
   return WrapperFunction<SPSError(SPSExecutorAddr,
+                                  SPSOptional<SPSUnwindSectionInfo>,
                                   SPSMachOObjectPlatformSectionsMap)>::
       handle(ArgData, ArgSize,
-             [](ExecutorAddr HeaderAddr,
+             [](ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> USI,
                 std::vector<std::pair<std::string_view, ExecutorAddrRange>>
                     &Secs) {
                return MachOPlatformRuntimeState::get()
-                   .registerObjectPlatformSections(HeaderAddr, std::move(Secs));
+                   .registerObjectPlatformSections(HeaderAddr, std::move(USI),
+                                                   std::move(Secs));
              })
           .release();
 }
@@ -1160,13 +1340,14 @@ ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
 __orc_rt_macho_deregister_object_platform_sections(char *ArgData,
                                                    size_t ArgSize) {
   return WrapperFunction<SPSError(SPSExecutorAddr,
+                                  SPSOptional<SPSUnwindSectionInfo>,
                                   SPSMachOObjectPlatformSectionsMap)>::
       handle(ArgData, ArgSize,
-             [](ExecutorAddr HeaderAddr,
+             [](ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> USI,
                 std::vector<std::pair<std::string_view, ExecutorAddrRange>>
                     &Secs) {
                return MachOPlatformRuntimeState::get()
-                   .deregisterObjectPlatformSections(HeaderAddr,
+                   .deregisterObjectPlatformSections(HeaderAddr, std::move(USI),
                                                      std::move(Secs));
              })
           .release();

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
index 051ab3a85935f..c51608899e041 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
@@ -147,6 +147,12 @@ class MachOPlatform : public Platform {
     using InitSymbolDepMap =
         DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>;
 
+    struct UnwindSections {
+      SmallVector<ExecutorAddrRange> CodeRanges;
+      ExecutorAddrRange DwarfSection;
+      ExecutorAddrRange CompactUnwindSection;
+    };
+
     Error bootstrapPipelineStart(jitlink::LinkGraph &G);
     Error bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G);
     Error bootstrapPipelineEnd(jitlink::LinkGraph &G);
@@ -164,6 +170,8 @@ class MachOPlatform : public Platform {
 
     Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
 
+    std::optional<UnwindSections> findUnwindSectionInfo(jitlink::LinkGraph &G);
+
     Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD,
                                          bool InBootstrapPhase);
 

diff  --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index a926222dc458f..914a1b5afc712 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -249,6 +249,7 @@ class MachOPlatformCompleteBootstrapMaterializationUnit
 StringRef DataCommonSectionName = "__DATA,__common";
 StringRef DataDataSectionName = "__DATA,__data";
 StringRef EHFrameSectionName = "__TEXT,__eh_frame";
+StringRef CompactUnwindInfoSectionName = "__TEXT,__unwind_info";
 StringRef ModInitFuncSectionName = "__DATA,__mod_init_func";
 StringRef ObjCClassListSectionName = "__DATA,__objc_classlist";
 StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info";
@@ -1068,6 +1069,81 @@ Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
   return Error::success();
 }
 
+std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections>
+MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
+    jitlink::LinkGraph &G) {
+  using namespace jitlink;
+
+  UnwindSections US;
+
+  // ScanSection records a section range and adds any executable blocks that
+  // that section points to to the CodeBlocks vector.
+  SmallVector<Block *> CodeBlocks;
+  auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) {
+    if (Sec.blocks().empty())
+      return;
+    SecRange = (*Sec.blocks().begin())->getRange();
+    for (auto *B : Sec.blocks()) {
+      auto R = B->getRange();
+      SecRange.Start = std::min(SecRange.Start, R.Start);
+      SecRange.End = std::max(SecRange.End, R.End);
+      for (auto &E : B->edges()) {
+        if (!E.getTarget().isDefined())
+          continue;
+        auto &TargetBlock = E.getTarget().getBlock();
+        auto &TargetSection = TargetBlock.getSection();
+        if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec)
+          CodeBlocks.push_back(&TargetBlock);
+      }
+    }
+  };
+
+  if (Section *EHFrameSec = G.findSectionByName(EHFrameSectionName))
+    ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
+
+  if (Section *CUInfoSec = G.findSectionByName(CompactUnwindInfoSectionName))
+    ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
+
+  // If we didn't find any pointed-to code-blocks then there's no need to
+  // register any info.
+  if (CodeBlocks.empty())
+    return std::nullopt;
+
+  // We have info to register. Sort the code blocks into address order and
+  // build a list of contiguous address ranges covering them all.
+  llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) {
+    return LHS->getAddress() < RHS->getAddress();
+  });
+  for (auto *B : CodeBlocks) {
+    if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress())
+      US.CodeRanges.push_back(B->getRange());
+    else
+      US.CodeRanges.back().End = B->getRange().End;
+  }
+
+  LLVM_DEBUG({
+    dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n"
+           << "  DWARF: ";
+    if (US.DwarfSection.Start)
+      dbgs() << US.DwarfSection << "\n";
+    else
+      dbgs() << "none\n";
+    dbgs() << "  Compact-unwind: ";
+    if (US.CompactUnwindSection.Start)
+      dbgs() << US.CompactUnwindSection << "\n";
+    else
+      dbgs() << "none\n"
+             << "for code ranges:\n";
+    for (auto &CR : US.CodeRanges)
+      dbgs() << "  " << CR << "\n";
+    if (US.CodeRanges.size() >= G.sections_size())
+      dbgs() << "WARNING: High number of discontiguous code ranges! "
+                "Padding may be interfering with coalescing.\n";
+  });
+
+  return US;
+}
+
 Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
     jitlink::LinkGraph &G, JITDylib &JD, bool InBootstrapPhase) {
 
@@ -1128,7 +1204,14 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
     MachOPlatformSecs.push_back({SecName, R.getRange()});
   }
 
-  if (!MachOPlatformSecs.empty()) {
+  std::optional<std::tuple<SmallVector<ExecutorAddrRange>, ExecutorAddrRange,
+                           ExecutorAddrRange>>
+      UnwindInfo;
+  if (auto UI = findUnwindSectionInfo(G))
+    UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection,
+                                 UI->CompactUnwindSection);
+
+  if (!MachOPlatformSecs.empty() || UnwindInfo) {
     ExecutorAddr HeaderAddr;
     {
       std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
@@ -1145,9 +1228,11 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
         dbgs() << "  " << KV.first << ": " << KV.second << "\n";
     });
 
-    using SPSRegisterObjectPlatformSectionsArgs =
-        SPSArgList<SPSExecutorAddr,
-                   SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;
+    using SPSRegisterObjectPlatformSectionsArgs = SPSArgList<
+        SPSExecutorAddr,
+        SPSOptional<SPSTuple<SPSSequence<SPSExecutorAddrRange>,
+                             SPSExecutorAddrRange, SPSExecutorAddrRange>>,
+        SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;
 
     shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase)
                                              ? G.allocActions()
@@ -1156,12 +1241,12 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
     allocActions.push_back(
         {cantFail(
              WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
-                 MP.RegisterObjectPlatformSections.Addr, HeaderAddr,
+                 MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,
                  MachOPlatformSecs)),
          cantFail(
              WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
                  MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,
-                 MachOPlatformSecs))});
+                 UnwindInfo, MachOPlatformSecs))});
   }
 
   return Error::success();


        


More information about the llvm-commits mailing list