https://github.com/benlangmuir created https://github.com/llvm/llvm-project/pull/125098
This reverts commit d6524c8dfa37634257050ca71d16e117b802181c. This reverts commit b1bd73700a1fb6f450e0f6f9c405a9c8bde2cae7. This was causing bot failures on Darwin https://green.lab.llvm.org/job/llvm.org/job/clang-stage1-cmake-RA-incremental/7315/ Clang.Interpreter.simple-exception.cpp Clang-Unit.Interpreter/ExceptionTests/_/ClangReplInterpreterExceptionTests/0.1 LLVM.ExecutionEngine/OrcLazy.minimal-throw-catch.ll https://green.lab.llvm.org/job/llvm.org/job/clang-stage1-RA/3415/ ORC-x86_64-darwin.TestCases/Darwin/Generic.exceptions.cpp ORC-x86_64-darwin.TestCases/Darwin/x86-64.lljit-ehframe.cpp >From d2cf4b637cc667f2ccd094097828058524c90ec9 Mon Sep 17 00:00:00 2001 From: Ben Langmuir <blangm...@apple.com> Date: Thu, 30 Jan 2025 09:48:33 -0800 Subject: [PATCH] Revert "Reapply "[ORC] Enable JIT support for the compact-unwind frame..." with fixes." This reverts commit d6524c8dfa37634257050ca71d16e117b802181c. This reverts commit b1bd73700a1fb6f450e0f6f9c405a9c8bde2cae7. This was causing bot failures on Darwin https://green.lab.llvm.org/job/llvm.org/job/clang-stage1-cmake-RA-incremental/7315/ Clang.Interpreter.simple-exception.cpp Clang-Unit.Interpreter/ExceptionTests/_/ClangReplInterpreterExceptionTests/0.1 LLVM.ExecutionEngine/OrcLazy.minimal-throw-catch.ll https://green.lab.llvm.org/job/llvm.org/job/clang-stage1-RA/3415/ ORC-x86_64-darwin.TestCases/Darwin/Generic.exceptions.cpp ORC-x86_64-darwin.TestCases/Darwin/x86-64.lljit-ehframe.cpp --- clang/test/Interpreter/simple-exception.cpp | 4 +- compiler-rt/lib/orc/macho_platform.cpp | 6 - .../TestCases/Darwin/Generic/exceptions.cpp | 13 - llvm/include/llvm/ExecutionEngine/Orc/Core.h | 9 +- .../Orc/ExecutorProcessControl.h | 4 - .../ExecutionEngine/Orc/Shared/OrcRTBridge.h | 9 - .../Orc/TargetProcess/UnwindInfoManager.h | 78 --- .../Orc/UnwindInfoRegistrationPlugin.h | 70 -- .../ExecutionEngine/JITLink/CMakeLists.txt | 1 - .../JITLink/CompactUnwindSupport.cpp | 103 --- .../JITLink/CompactUnwindSupport.h | 653 ------------------ .../JITLink/MachOLinkGraphBuilder.cpp | 116 ++++ .../JITLink/MachOLinkGraphBuilder.h | 11 + .../ExecutionEngine/JITLink/MachO_arm64.cpp | 49 +- .../ExecutionEngine/JITLink/MachO_x86_64.cpp | 57 +- llvm/lib/ExecutionEngine/Orc/CMakeLists.txt | 1 - llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp | 3 - llvm/lib/ExecutionEngine/Orc/Core.cpp | 34 +- .../Orc/ExecutorProcessControl.cpp | 7 - llvm/lib/ExecutionEngine/Orc/LLJIT.cpp | 29 +- .../Orc/Shared/OrcRTBridge.cpp | 14 - .../Orc/TargetProcess/CMakeLists.txt | 1 - .../Orc/TargetProcess/UnwindInfoManager.cpp | 188 ----- .../Orc/UnwindInfoRegistrationPlugin.cpp | 238 ------- 24 files changed, 164 insertions(+), 1534 deletions(-) delete mode 100644 compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp delete mode 100644 llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h delete mode 100644 llvm/include/llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h delete mode 100644 llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.cpp delete mode 100644 llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h delete mode 100644 llvm/lib/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.cpp delete mode 100644 llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp diff --git a/clang/test/Interpreter/simple-exception.cpp b/clang/test/Interpreter/simple-exception.cpp index 651e8d9402f89e..6749acd6e6bd23 100644 --- a/clang/test/Interpreter/simple-exception.cpp +++ b/clang/test/Interpreter/simple-exception.cpp @@ -1,7 +1,7 @@ // clang-format off // UNSUPPORTED: system-aix -// XFAIL for arm, or running on Windows. -// XFAIL: target=arm-{{.*}}, target=armv{{.*}}, system-windows +// XFAIL for arm and arm64, or running on Windows. +// XFAIL: target=arm{{.*}}, system-windows // RUN: cat %s | clang-repl | FileCheck %s // Incompatible with msan. It passes with -O3 but fail -Oz. Interpreter diff --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp index 4b603fd95e3163..8ca68587aeb363 100644 --- a/compiler-rt/lib/orc/macho_platform.cpp +++ b/compiler-rt/lib/orc/macho_platform.cpp @@ -557,12 +557,6 @@ Error MachOPlatformRuntimeState::registerObjectPlatformSections( return make_error<StringError>(ErrStream.str()); } - ORC_RT_DEBUG({ - printdbg(" UnwindInfo: %s, UseCallbackStyleUnwindInfo: %s\n", - UnwindInfo ? "true" : "false", - UseCallbackStyleUnwindInfo ? "true" : "false"); - }); - if (UnwindInfo && UseCallbackStyleUnwindInfo) { ORC_RT_DEBUG({ printdbg(" Registering new-style unwind info for:\n" diff --git a/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp b/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp deleted file mode 100644 index 7e9c40c724aec6..00000000000000 --- a/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// RUN: %clangxx -c -o %t %s -// RUN: %llvm_jitlink -slab-allocate=20Mb %t -// -// REQUIRES: system-darwin && host-arch-compatible - -int main(int argc, char *argv[]) { - try { - throw 42; - } catch (int E) { - return 42 - E; - } - return 1; -} diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h index 3eddaf4c9c59ff..db853362f65733 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -1204,13 +1204,8 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>, JITDylib(ExecutionSession &ES, std::string Name); - struct RemoveTrackerResult { - AsynchronousSymbolQuerySet QueriesToFail; - std::shared_ptr<SymbolDependenceMap> FailedSymbols; - std::vector<std::unique_ptr<MaterializationUnit>> DefunctMUs; - }; - - RemoveTrackerResult IL_removeTracker(ResourceTracker &RT); + std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>> + IL_removeTracker(ResourceTracker &RT); void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT); diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h index 86e98e74b7055b..dcf5592f1717c2 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h @@ -20,7 +20,6 @@ #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h" #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" -#include "llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h" #include "llvm/ExecutionEngine/Orc/TaskDispatch.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/MSVCErrorWorkarounds.h" @@ -508,9 +507,6 @@ class SelfExecutorProcessControl : public ExecutorProcessControl, SymbolLookupCompleteFn F) override; std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr; -#ifdef __APPLE__ - std::unique_ptr<UnwindInfoManager> UnwindInfoMgr; -#endif // __APPLE__ char GlobalManglingPrefix = 0; }; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h index db5ff135a7164c..aed43f6308cbaa 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h @@ -88,15 +88,6 @@ using SPSRunAsMainSignature = int64_t(shared::SPSExecutorAddr, using SPSRunAsVoidFunctionSignature = int32_t(shared::SPSExecutorAddr); using SPSRunAsIntFunctionSignature = int32_t(shared::SPSExecutorAddr, int32_t); } // end namespace rt - -namespace rt_alt { -extern const char *UnwindInfoManagerInstanceName; -extern const char *UnwindInfoManagerFindSectionsHelperName; -extern const char *UnwindInfoManagerEnableWrapperName; -extern const char *UnwindInfoManagerDisableWrapperName; -extern const char *UnwindInfoManagerRegisterActionName; -extern const char *UnwindInfoManagerDeregisterActionName; -} // end namespace rt_alt } // end namespace orc } // end namespace llvm diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h deleted file mode 100644 index fc7719f2821222..00000000000000 --- a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h +++ /dev/null @@ -1,78 +0,0 @@ -//===--- UnwindInfoManager.h -- Register unwind info sections ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Utilities for managing eh-frame and compact-unwind registration and lookup -// through libunwind's find_dynamic_unwind_sections mechanism. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H -#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H - -#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" -#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorBootstrapService.h" -#include "llvm/Support/Error.h" -#include <map> -#include <mutex> - -namespace llvm::orc { - -class UnwindInfoManager : public ExecutorBootstrapService { -public: - // This struct's layout should match the unw_dynamic_unwind_sections struct - // from libunwind/src/libunwid_ext.h. - struct UnwindSections { - uintptr_t dso_base; - uintptr_t dwarf_section; - size_t dwarf_section_length; - uintptr_t compact_unwind_section; - size_t compact_unwind_section_length; - }; - - /// If the libunwind find-dynamic-unwind-info callback registration APIs are - /// available then this method will return an UnwindInfoManager instance, - /// otherwise it will return nullptr. - static std::unique_ptr<UnwindInfoManager> TryCreate(); - - Error shutdown() override; - void addBootstrapSymbols(StringMap<ExecutorAddr> &M) override; - - Error enable(void *FindDynamicUnwindSections); - Error disable(void); - - Error registerSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges, - orc::ExecutorAddr DSOBase, - orc::ExecutorAddrRange DWARFEHFrame, - orc::ExecutorAddrRange CompactUnwind); - - Error deregisterSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges); - - int findSections(uintptr_t Addr, UnwindSections *Info); - -private: - UnwindInfoManager(int (*AddFindDynamicUnwindSections)(void *), - int (*RemoveFindDynamicUnwindSections)(void *)) - : AddFindDynamicUnwindSections(AddFindDynamicUnwindSections), - RemoveFindDynamicUnwindSections(RemoveFindDynamicUnwindSections) {} - - static int findSectionsHelper(UnwindInfoManager *Instance, uintptr_t Addr, - UnwindSections *Info); - - std::mutex M; - std::map<uintptr_t, UnwindSections> UWSecs; - - int (*AddFindDynamicUnwindSections)(void *) = nullptr; - int (*RemoveFindDynamicUnwindSections)(void *) = nullptr; - void *FindDynamicUnwindSections = nullptr; - - static const char *AddFnName, *RemoveFnName; -}; - -} // namespace llvm::orc - -#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H diff --git a/llvm/include/llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h b/llvm/include/llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h deleted file mode 100644 index eb883a79a93d87..00000000000000 --- a/llvm/include/llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h +++ /dev/null @@ -1,70 +0,0 @@ -//===- UnwindInfoRegistrationPlugin.h -- libunwind registration -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Register eh-frame and compact-unwind sections with libunwind -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_UNWINDINFOREGISTRATIONPLUGIN_H -#define LLVM_EXECUTIONENGINE_ORC_UNWINDINFOREGISTRATIONPLUGIN_H - -#include "llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h" - -namespace llvm::orc { - -class UnwindInfoRegistrationPlugin : public LinkGraphLinkingLayer::Plugin { -public: - static Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>> - Create(IRLayer &IRL, JITDylib &PlatformJD, ExecutorAddr Instance, - ExecutorAddr FindHelper, ExecutorAddr Enable, ExecutorAddr Disable, - ExecutorAddr Register, ExecutorAddr Deregister); - - static Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>> - Create(IRLayer &IRL, JITDylib &PlatformJD); - - ~UnwindInfoRegistrationPlugin(); - - void modifyPassConfig(MaterializationResponsibility &MR, - jitlink::LinkGraph &G, - jitlink::PassConfiguration &PassConfig) override; - - Error notifyEmitted(MaterializationResponsibility &MR) override { - return Error::success(); - } - - Error notifyFailed(MaterializationResponsibility &MR) override { - return Error::success(); - } - - Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override { - return Error::success(); - } - - void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, - ResourceKey SrcKey) override {} - -private: - UnwindInfoRegistrationPlugin(ExecutionSession &ES, ExecutorAddr Instance, - ExecutorAddr Disable, ExecutorAddr Register, - ExecutorAddr Deregister) - : ES(ES), Instance(Instance), Disable(Disable), Register(Register), - Deregister(Deregister) { - DSOBaseName = ES.intern("__jitlink$libunwind_dso_base"); - } - - static Expected<ThreadSafeModule> makeBouncerModule(ExecutionSession &ES); - Error addUnwindInfoRegistrationActions(jitlink::LinkGraph &G); - - ExecutionSession &ES; - SymbolStringPtr DSOBaseName; - ExecutorAddr Instance, Disable, Register, Deregister; -}; - -} // namespace llvm::orc - -#endif // LLVM_EXECUTIONENGINE_ORC_UNWINDINFOREGISTRATIONPLUGIN_H diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt index 65dd0c7468ae1d..e5f5a99c39bc00 100644 --- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt @@ -3,7 +3,6 @@ tablegen(LLVM COFFOptions.inc -gen-opt-parser-defs) add_public_tablegen_target(JITLinkTableGen) add_llvm_component_library(LLVMJITLink - CompactUnwindSupport.cpp DWARFRecordSectionSplitter.cpp EHFrameSupport.cpp JITLink.cpp diff --git a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.cpp deleted file mode 100644 index 51e3d26479ffdf..00000000000000 --- a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.cpp +++ /dev/null @@ -1,103 +0,0 @@ -//=------- CompactUnwindSupport.cpp - Compact Unwind format support -------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Compact Unwind support. -// -//===----------------------------------------------------------------------===// - -#include "CompactUnwindSupport.h" - -#include "llvm/ADT/Sequence.h" - -#define DEBUG_TYPE "jitlink" - -namespace llvm { -namespace jitlink { - -Error splitCompactUnwindBlocks(LinkGraph &G, Section &CompactUnwindSection, - size_t RecordSize) { - - std::vector<Block *> OriginalBlocks(CompactUnwindSection.blocks().begin(), - CompactUnwindSection.blocks().end()); - LLVM_DEBUG({ - dbgs() << "In " << G.getName() << " splitting compact unwind section " - << CompactUnwindSection.getName() << " containing " - << OriginalBlocks.size() << " initial blocks...\n"; - }); - - while (!OriginalBlocks.empty()) { - auto *B = OriginalBlocks.back(); - OriginalBlocks.pop_back(); - - if (B->getSize() == 0) { - LLVM_DEBUG({ - dbgs() << " Skipping empty block at " - << formatv("{0:x16}", B->getAddress()) << "\n"; - }); - continue; - } - - unsigned NumBlocks = B->getSize() / RecordSize; - - LLVM_DEBUG({ - dbgs() << " Splitting block at " << formatv("{0:x16}", B->getAddress()) - << " into " << NumBlocks << " compact unwind record(s)\n"; - }); - - if (B->getSize() % RecordSize) - return make_error<JITLinkError>( - "Error splitting compact unwind record in " + G.getName() + - ": block at " + formatv("{0:x}", B->getAddress()) + " has size " + - formatv("{0:x}", B->getSize()) + - " (not a multiple of CU record size of " + - formatv("{0:x}", RecordSize) + ")"); - - auto Blocks = - G.splitBlock(*B, map_range(seq(1U, NumBlocks), [=](Edge::OffsetT Idx) { - return Idx * RecordSize; - })); - - for (auto *CURec : Blocks) { - bool AddedKeepAlive = false; - - for (auto &E : CURec->edges()) { - if (E.getOffset() == 0) { - LLVM_DEBUG({ - dbgs() << " Updating compact unwind record at " - << CURec->getAddress() << " to point to " - << (E.getTarget().hasName() ? *E.getTarget().getName() - : StringRef()) - << " (at " << E.getTarget().getAddress() << ")\n"; - }); - - if (E.getTarget().isExternal()) - return make_error<JITLinkError>( - "Error adding keep-alive edge for compact unwind record at " + - formatv("{0:x}", CURec->getAddress()) + ": target " + - *E.getTarget().getName() + " is an external symbol"); - auto &TgtBlock = E.getTarget().getBlock(); - auto &CURecSym = - G.addAnonymousSymbol(*CURec, 0, RecordSize, false, false); - TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0); - AddedKeepAlive = true; - } - } - - if (!AddedKeepAlive) - return make_error<JITLinkError>( - "Error adding keep-alive edge for compact unwind record at " + - formatv("{0:x}", CURec->getAddress()) + - ": no outgoing target edge at offset 0"); - } - } - - return Error::success(); -} - -} // end namespace jitlink -} // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h deleted file mode 100644 index dc3ed942aa8ac8..00000000000000 --- a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h +++ /dev/null @@ -1,653 +0,0 @@ -//===- CompactUnwindSupportImpl.h - Compact Unwind format impl --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Compact Unwind format support implementation details. -// -//===----------------------------------------------------------------------===// - -#ifndef LIB_EXECUTIONENGINE_JITLINK_COMPACTUNWINDSUPPORTIMPL_H -#define LIB_EXECUTIONENGINE_JITLINK_COMPACTUNWINDSUPPORTIMPL_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ExecutionEngine/JITLink/MachO.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Endian.h" - -#define DEBUG_TYPE "jitlink_cu" - -namespace llvm { -namespace jitlink { - -/// Split blocks in an __LD,__compact_unwind section on record boundaries. -/// When this function returns edges within each record are guaranteed to be -/// sorted by offset. -Error splitCompactUnwindBlocks(LinkGraph &G, Section &CompactUnwindSection, - size_t RecordSize); - -/// CRTP base for compact unwind traits classes. Automatically provides derived -/// constants. -/// -/// FIXME: Passing PtrSize as a template parameter is a hack to work around a -/// bug in older MSVC compilers (until at least MSVC 15) where constexpr -/// fields in the CRTP impl class were not visible to the base class. -/// Once we no longer need to support these compilers the PtrSize -/// template argument should be removed and PointerSize should be -/// defined as a member in the CRTP Impl classes. -template <typename CRTPImpl, size_t PtrSize> struct CompactUnwindTraits { - static constexpr size_t PointerSize = PtrSize; - static constexpr size_t Size = 3 * PointerSize + 2 * 4; - static constexpr size_t FnFieldOffset = 0; - static constexpr size_t SizeFieldOffset = FnFieldOffset + PointerSize; - static constexpr size_t EncodingFieldOffset = SizeFieldOffset + 4; - static constexpr size_t PersonalityFieldOffset = EncodingFieldOffset + 4; - static constexpr size_t LSDAFieldOffset = - PersonalityFieldOffset + PointerSize; - - static uint32_t readPCRangeSize(ArrayRef<char> RecordContent) { - assert(SizeFieldOffset + 4 <= RecordContent.size() && - "Truncated CU record?"); - return support::endian::read32<CRTPImpl::Endianness>(RecordContent.data() + - SizeFieldOffset); - } - - static uint32_t readEncoding(ArrayRef<char> RecordContent) { - assert(EncodingFieldOffset + 4 <= RecordContent.size() && - "Truncated CU record?"); - return support::endian::read32<CRTPImpl::Endianness>(RecordContent.data() + - EncodingFieldOffset); - } -}; - -/// Architecture specific implementation of CompactUnwindManager. -template <typename CURecTraits> class CompactUnwindManager { -public: - CompactUnwindManager(StringRef CompactUnwindSectionName, - StringRef UnwindInfoSectionName, - StringRef EHFrameSectionName) - : CompactUnwindSectionName(CompactUnwindSectionName), - UnwindInfoSectionName(UnwindInfoSectionName), - EHFrameSectionName(EHFrameSectionName) {} - - // Split compact unwind records, add keep-alive edges from functions to - // compact unwind records, and from compact unwind records to FDEs where - // needed. - // - // This method must be called *after* __eh_frame has been processed: it - // assumes that eh-frame records have been split up and keep-alive edges have - // been inserted. - Error prepareForPrune(LinkGraph &G) { - Section *CUSec = G.findSectionByName(CompactUnwindSectionName); - if (!CUSec || CUSec->empty()) { - LLVM_DEBUG({ - dbgs() << "Compact unwind: No compact unwind info for " << G.getName() - << "\n"; - }); - return Error::success(); - } - - LLVM_DEBUG({ - dbgs() << "Compact unwind: preparing " << G.getName() << " for prune\n"; - }); - - Section *EHFrameSec = G.findSectionByName(EHFrameSectionName); - - if (auto Err = splitCompactUnwindBlocks(G, *CUSec, CURecTraits::Size)) - return Err; - - LLVM_DEBUG({ - dbgs() << " Preparing " << CUSec->blocks_size() << " blocks in " - << CompactUnwindSectionName << "\n"; - }); - - for (auto *B : CUSec->blocks()) { - - // Find target function edge. - Edge *PCBeginEdge = nullptr; - for (auto &E : B->edges_at(CURecTraits::FnFieldOffset)) { - PCBeginEdge = &E; - break; - } - - if (!PCBeginEdge) - return make_error<JITLinkError>( - "In " + G.getName() + ", compact unwind record at " + - formatv("{0:x}", B->getAddress()) + " has no pc-begin edge"); - - if (!PCBeginEdge->getTarget().isDefined()) - return make_error<JITLinkError>( - "In " + G.getName() + ", compact unwind record at " + - formatv("{0:x}", B->getAddress()) + " points at external symbol " + - *PCBeginEdge->getTarget().getName()); - - auto &Fn = PCBeginEdge->getTarget(); - - if (!Fn.isDefined()) { - LLVM_DEBUG({ - dbgs() << "In " << CompactUnwindSectionName << " for " << G.getName() - << " encountered unexpected pc-edge to undefined symbol " - << Fn.getName() << "\n"; - }); - continue; - } else { - LLVM_DEBUG({ - dbgs() << " Found record for function "; - if (Fn.hasName()) - dbgs() << Fn.getName(); - else - dbgs() << "<anon @ " << Fn.getAddress() << '>'; - dbgs() << '\n'; - }); - } - - bool NeedsDWARF = CURecTraits::encodingSpecifiesDWARF( - CURecTraits::readEncoding(B->getContent())); - - auto &CURecSym = - G.addAnonymousSymbol(*B, 0, CURecTraits::Size, false, false); - - bool KeepAliveAlreadyPresent = false; - if (EHFrameSec) { - Edge *KeepAliveEdge = nullptr; - for (auto &E : Fn.getBlock().edges_at(0)) { - if (E.getKind() == Edge::KeepAlive && E.getTarget().isDefined() && - &E.getTarget().getBlock().getSection() == EHFrameSec) { - KeepAliveEdge = &E; - break; - } - } - - if (KeepAliveEdge) { - // Found a keep-alive edge to an FDE in the eh-frame. Switch the keep - // alive edge to point to the CU and if the CU needs DWARF then add - // an extra keep-alive edge from the CU to the FDE. - auto &FDE = KeepAliveEdge->getTarget(); - KeepAliveEdge->setTarget(CURecSym); - KeepAliveAlreadyPresent = true; - if (NeedsDWARF) { - LLVM_DEBUG({ - dbgs() << " Needs DWARF: adding keep-alive edge to FDE at " - << FDE.getAddress() << "\n"; - }); - B->addEdge(Edge::KeepAlive, 0, FDE, 0); - } - } else { - if (NeedsDWARF) - return make_error<JITLinkError>( - "In " + G.getName() + ", compact unwind recard ot " + - formatv("{0:x}", B->getAddress()) + - " needs DWARF, but no FDE was found"); - } - } else { - if (NeedsDWARF) - return make_error<JITLinkError>( - "In " + G.getName() + ", compact unwind recard ot " + - formatv("{0:x}", B->getAddress()) + " needs DWARF, but no " + - EHFrameSectionName + " section exists"); - } - - if (!KeepAliveAlreadyPresent) { - // No FDE edge. We'll need to add a new edge from the function back - // to the CU record. - Fn.getBlock().addEdge(Edge::KeepAlive, 0, CURecSym, 0); - } - } - - return Error::success(); - } - - /// Process all __compact_unwind records and reserve space for __unwind_info. - Error processAndReserveUnwindInfo(LinkGraph &G) { - // Bail out early if no unwind info. - Section *CUSec = G.findSectionByName(CompactUnwindSectionName); - if (!CUSec) - return Error::success(); - - // The __LD/__compact_unwind section is only used as input for the linker. - // We'll create a new __TEXT,__unwind_info section for unwind info output. - CUSec->setMemLifetime(orc::MemLifetime::NoAlloc); - - // Find / make a mach-header to act as the base for unwind-info offsets - // (and to report the arch / subarch to libunwind). - if (auto Err = getOrCreateCompactUnwindBase(G)) - return Err; - - // Error out if there's already unwind-info in the graph: We have no idea - // how to merge unwind-info sections. - if (G.findSectionByName(UnwindInfoSectionName)) - return make_error<JITLinkError>("In " + G.getName() + ", " + - UnwindInfoSectionName + - " already exists"); - - // Process the __compact_unwind section to build the Records vector that - // we'll use for writing the __unwind_info section. - if (auto Err = processCompactUnwind(G, *CUSec)) - return Err; - - // Calculate the size of __unwind_info. - size_t UnwindInfoSectionSize = - UnwindInfoSectionHeaderSize + - Personalities.size() * PersonalityEntrySize + - (NumSecondLevelPages + 1) * IndexEntrySize + NumLSDAs * LSDAEntrySize + - NumSecondLevelPages * SecondLevelPageHeaderSize + - Records.size() * SecondLevelPageEntrySize; - - LLVM_DEBUG({ - dbgs() << "In " << G.getName() << ", reserving " - << formatv("{0:x}", UnwindInfoSectionSize) << " bytes for " - << UnwindInfoSectionName << "\n"; - }); - - // Create the __unwind_info section and reserve space for it. - Section &UnwindInfoSec = - G.createSection(UnwindInfoSectionName, orc::MemProt::Read); - - auto UnwindInfoSectionContent = G.allocateBuffer(UnwindInfoSectionSize); - memset(UnwindInfoSectionContent.data(), 0, UnwindInfoSectionContent.size()); - auto &B = G.createMutableContentBlock( - UnwindInfoSec, UnwindInfoSectionContent, orc::ExecutorAddr(), 8, 0); - - // Add Keep-alive edges from the __unwind_info block to all of the target - // functions. - for (auto &R : Records) - B.addEdge(Edge::KeepAlive, 0, *R.Fn, 0); - - return Error::success(); - } - - Error writeUnwindInfo(LinkGraph &G) { - Section *CUSec = G.findSectionByName(CompactUnwindSectionName); - if (!CUSec || CUSec->empty()) - return Error::success(); - - Section *UnwindInfoSec = G.findSectionByName(UnwindInfoSectionName); - if (!UnwindInfoSec) - return make_error<JITLinkError>("In " + G.getName() + ", " + - UnwindInfoSectionName + - " missing after allocation"); - - if (UnwindInfoSec->blocks_size() != 1) - return make_error<JITLinkError>( - "In " + G.getName() + ", " + UnwindInfoSectionName + - " contains more than one block post-allocation"); - - LLVM_DEBUG( - { dbgs() << "Writing unwind info for " << G.getName() << "...\n"; }); - - mergeRecords(); - - auto &UnwindInfoBlock = **UnwindInfoSec->blocks().begin(); - auto Content = UnwindInfoBlock.getMutableContent(G); - BinaryStreamWriter Writer( - {reinterpret_cast<uint8_t *>(Content.data()), Content.size()}, - CURecTraits::Endianness); - - // __unwind_info format, from mach-o/compact_unwind_encoding.h on Darwin: - // - // #define UNWIND_SECTION_VERSION 1 - // struct unwind_info_section_header - // { - // uint32_t version; // UNWIND_SECTION_VERSION - // uint32_t commonEncodingsArraySectionOffset; - // uint32_t commonEncodingsArrayCount; - // uint32_t personalityArraySectionOffset; - // uint32_t personalityArrayCount; - // uint32_t indexSectionOffset; - // uint32_t indexCount; - // // compact_unwind_encoding_t[] - // // uint32_t personalities[] - // // unwind_info_section_header_index_entry[] - // // unwind_info_section_header_lsda_index_entry[] - // }; - - if (auto Err = writeHeader(G, Writer)) - return Err; - - // Skip common encodings: JITLink doesn't use them. - - if (auto Err = writePersonalities(G, Writer)) - return Err; - - // Calculate the offset to the LSDAs. - size_t SectionOffsetToLSDAs = - Writer.getOffset() + (NumSecondLevelPages + 1) * IndexEntrySize; - - // Calculate offset to the 1st second-level page. - size_t SectionOffsetToSecondLevelPages = - SectionOffsetToLSDAs + NumLSDAs * LSDAEntrySize; - - if (auto Err = writeIndexes(G, Writer, SectionOffsetToLSDAs, - SectionOffsetToSecondLevelPages)) - return Err; - - if (auto Err = writeLSDAs(G, Writer)) - return Err; - - if (auto Err = writeSecondLevelPages(G, Writer)) - return Err; - - LLVM_DEBUG({ - dbgs() << " Wrote " << formatv("{0:x}", Writer.getOffset()) - << " bytes of unwind info.\n"; - }); - - return Error::success(); - } - -private: - // Calculate the size of unwind-info. - static constexpr size_t MaxPersonalities = 4; - static constexpr size_t PersonalityShift = 28; - - static constexpr size_t UnwindInfoSectionHeaderSize = 4 * 7; - static constexpr size_t PersonalityEntrySize = 4; - static constexpr size_t IndexEntrySize = 3 * 4; - static constexpr size_t LSDAEntrySize = 2 * 4; - static constexpr size_t SecondLevelPageSize = 4096; - static constexpr size_t SecondLevelPageHeaderSize = 8; - static constexpr size_t SecondLevelPageEntrySize = 8; - static constexpr size_t NumRecordsPerSecondLevelPage = - (SecondLevelPageSize - SecondLevelPageHeaderSize) / - SecondLevelPageEntrySize; - - struct CompactUnwindRecord { - Symbol *Fn = nullptr; - uint32_t Size = 0; - uint32_t Encoding = 0; - Symbol *LSDA = nullptr; - Symbol *FDE = nullptr; - }; - - Error processCompactUnwind(LinkGraph &G, Section &CUSec) { - // TODO: Reset NumLSDAs, Personalities and CompactUnwindRecords if - // processing more than once. - assert(NumLSDAs == 0 && "NumLSDAs should be zero"); - assert(Records.empty() && "CompactUnwindRecords vector should be empty."); - assert(Personalities.empty() && "Personalities vector should be empty."); - - SmallVector<CompactUnwindRecord> NonUniquedRecords; - NonUniquedRecords.reserve(CUSec.blocks_size()); - - // Process __compact_unwind blocks. - for (auto *B : CUSec.blocks()) { - CompactUnwindRecord R; - R.Encoding = CURecTraits::readEncoding(B->getContent()); - for (auto &E : B->edges()) { - switch (E.getOffset()) { - case CURecTraits::FnFieldOffset: - // This could be the function-pointer, or the FDE keep-alive. Check - // the type to decide. - if (E.getKind() == Edge::KeepAlive) - R.FDE = &E.getTarget(); - else - R.Fn = &E.getTarget(); - break; - case CURecTraits::PersonalityFieldOffset: { - // Add the Personality to the Personalities map and update the - // encoding. - size_t PersonalityIdx = 0; - for (; PersonalityIdx != Personalities.size(); ++PersonalityIdx) - if (Personalities[PersonalityIdx] == &E.getTarget()) - break; - if (PersonalityIdx == MaxPersonalities) - return make_error<JITLinkError>( - "In " + G.getName() + - ", __compact_unwind contains too many personalities (max " + - formatv("{}", MaxPersonalities) + ")"); - if (PersonalityIdx == Personalities.size()) - Personalities.push_back(&E.getTarget()); - - R.Encoding |= (PersonalityIdx + 1) << PersonalityShift; - break; - } - case CURecTraits::LSDAFieldOffset: - ++NumLSDAs; - R.LSDA = &E.getTarget(); - break; - default: - return make_error<JITLinkError>("In " + G.getName() + - ", compact unwind record at " + - formatv("{0:x}", B->getAddress()) + - " has unrecognized edge at offset " + - formatv("{0:x}", E.getOffset())); - } - } - Records.push_back(R); - } - - // Sort the records into ascending order. - llvm::sort(Records, [](const CompactUnwindRecord &LHS, - const CompactUnwindRecord &RHS) { - return LHS.Fn->getAddress() < RHS.Fn->getAddress(); - }); - - // Calculate the number of second-level pages required. - NumSecondLevelPages = (Records.size() + NumRecordsPerSecondLevelPage - 1) / - NumRecordsPerSecondLevelPage; - - // Convert personality symbols to GOT entry pointers. - typename CURecTraits::GOTManager GOT(G); - for (auto &Personality : Personalities) - Personality = &GOT.getEntryForTarget(G, *Personality); - - LLVM_DEBUG({ - dbgs() << " In " << G.getName() << ", " << CompactUnwindSectionName - << ": raw records = " << Records.size() - << ", personalities = " << Personalities.size() - << ", lsdas = " << NumLSDAs << "\n"; - }); - - return Error::success(); - } - - void mergeRecords() { - SmallVector<CompactUnwindRecord> NonUniqued = std::move(Records); - Records.reserve(NonUniqued.size()); - - Records.push_back(NonUniqued.front()); - for (size_t I = 1; I != NonUniqued.size(); ++I) { - auto &Next = NonUniqued[I]; - auto &Last = Records.back(); - - bool NextNeedsDWARF = CURecTraits::encodingSpecifiesDWARF(Next.Encoding); - bool CannotBeMerged = CURecTraits::encodingCannotBeMerged(Next.Encoding); - if (NextNeedsDWARF || (Next.Encoding != Last.Encoding) || - CannotBeMerged || Next.LSDA || Last.LSDA) - Records.push_back(Next); - } - - // Recalculate derived values that may have changed. - NumSecondLevelPages = (Records.size() + NumRecordsPerSecondLevelPage - 1) / - NumRecordsPerSecondLevelPage; - } - - Error writeHeader(LinkGraph &G, BinaryStreamWriter &W) { - if (!isUInt<32>(NumSecondLevelPages + 1)) - return make_error<JITLinkError>("In " + G.getName() + ", too many " + - UnwindInfoSectionName + - "second-level pages required"); - - // Write __unwind_info header. - size_t IndexArrayOffset = UnwindInfoSectionHeaderSize + - Personalities.size() * PersonalityEntrySize; - - cantFail(W.writeInteger<uint32_t>(1)); - cantFail(W.writeInteger<uint32_t>(UnwindInfoSectionHeaderSize)); - cantFail(W.writeInteger<uint32_t>(0)); - cantFail(W.writeInteger<uint32_t>(UnwindInfoSectionHeaderSize)); - cantFail(W.writeInteger<uint32_t>(Personalities.size())); - cantFail(W.writeInteger<uint32_t>(IndexArrayOffset)); - cantFail(W.writeInteger<uint32_t>(NumSecondLevelPages + 1)); - - return Error::success(); - } - - Error writePersonalities(LinkGraph &G, BinaryStreamWriter &W) { - // Write personalities. - for (auto *PSym : Personalities) { - auto Delta = PSym->getAddress() - CompactUnwindBase->getAddress(); - if (!isUInt<32>(Delta)) - return makePersonalityRangeError(G, *PSym); - cantFail(W.writeInteger<uint32_t>(Delta)); - } - return Error::success(); - } - - Error writeIndexes(LinkGraph &G, BinaryStreamWriter &W, - size_t SectionOffsetToLSDAs, - size_t SectionOffsetToSecondLevelPages) { - // Assume that function deltas are ok in this method -- we'll error - // check all of them when we write the second level pages. - - // Write the header index entries. - size_t RecordIdx = 0; - size_t NumPreviousLSDAs = 0; - for (auto &R : Records) { - // If this record marks the start of a new second level page. - if (RecordIdx % NumRecordsPerSecondLevelPage == 0) { - auto FnDelta = R.Fn->getAddress() - CompactUnwindBase->getAddress(); - auto SecondLevelPageOffset = SectionOffsetToSecondLevelPages + - (RecordIdx / NumRecordsPerSecondLevelPage); - auto LSDAOffset = - SectionOffsetToLSDAs + NumPreviousLSDAs * LSDAEntrySize; - - cantFail(W.writeInteger<uint32_t>(FnDelta)); - cantFail(W.writeInteger<uint32_t>(SecondLevelPageOffset)); - cantFail(W.writeInteger<uint32_t>(LSDAOffset)); - } - if (R.LSDA) - ++NumPreviousLSDAs; - ++RecordIdx; - } - - // Write the index array terminator. - { - auto FnEndDelta = - Records.back().Fn->getRange().End - CompactUnwindBase->getAddress(); - - if (LLVM_UNLIKELY(!isUInt<32>(FnEndDelta))) - return make_error<JITLinkError>( - "In " + G.getName() + " " + UnwindInfoSectionName + - ", delta to end of functions " + - formatv("{0:x}", Records.back().Fn->getRange().End) + - " exceeds 32 bits"); - - cantFail(W.writeInteger<uint32_t>(FnEndDelta)); - cantFail(W.writeInteger<uint32_t>(0)); - cantFail(W.writeInteger<uint32_t>(SectionOffsetToSecondLevelPages)); - } - - return Error::success(); - } - - Error writeLSDAs(LinkGraph &G, BinaryStreamWriter &W) { - // As with writeIndexes, assume that function deltas are ok for now. - for (auto &R : Records) { - if (R.LSDA) { - auto FnDelta = R.Fn->getAddress() - CompactUnwindBase->getAddress(); - auto LSDADelta = R.LSDA->getAddress() - CompactUnwindBase->getAddress(); - - if (LLVM_UNLIKELY(!isUInt<32>(LSDADelta))) - return make_error<JITLinkError>( - "In " + G.getName() + " " + UnwindInfoSectionName + - ", delta to lsda at " + formatv("{0:x}", R.LSDA->getAddress()) + - " exceeds 32 bits"); - - cantFail(W.writeInteger<uint32_t>(FnDelta)); - cantFail(W.writeInteger<uint32_t>(LSDADelta)); - } - } - - return Error::success(); - } - - Error writeSecondLevelPages(LinkGraph &G, BinaryStreamWriter &W) { - size_t RecordIdx = 0; - - for (auto &R : Records) { - // When starting a new second-level page, write the page header: - // - // 2 : uint32_t -- UNWIND_SECOND_LEVEL_REGULAR - // 8 : uint16_t -- size of second level page table header - // count : uint16_t -- num entries in this second-level page - if (RecordIdx % NumRecordsPerSecondLevelPage == 0) { - constexpr uint32_t SecondLevelPageHeaderKind = 2; - constexpr uint16_t SecondLevelPageHeaderSize = 8; - uint16_t SecondLevelPageNumEntries = - std::min(Records.size() - RecordIdx, NumRecordsPerSecondLevelPage); - - cantFail(W.writeInteger<uint32_t>(SecondLevelPageHeaderKind)); - cantFail(W.writeInteger<uint16_t>(SecondLevelPageHeaderSize)); - cantFail(W.writeInteger<uint16_t>(SecondLevelPageNumEntries)); - } - - // Write entry. - auto FnDelta = R.Fn->getAddress() - CompactUnwindBase->getAddress(); - - if (LLVM_UNLIKELY(!isUInt<32>(FnDelta))) - return make_error<JITLinkError>( - "In " + G.getName() + " " + UnwindInfoSectionName + - ", delta to function at " + formatv("{0:x}", R.Fn->getAddress()) + - " exceeds 32 bits"); - - cantFail(W.writeInteger<uint32_t>(FnDelta)); - cantFail(W.writeInteger<uint32_t>(R.Encoding)); - - ++RecordIdx; - } - - return Error::success(); - } - - Error getOrCreateCompactUnwindBase(LinkGraph &G) { - auto Name = G.intern("__jitlink$libunwind_dso_base"); - CompactUnwindBase = G.findAbsoluteSymbolByName(Name); - if (!CompactUnwindBase) { - if (auto LocalCUBase = getOrCreateLocalMachOHeader(G)) { - CompactUnwindBase = &*LocalCUBase; - auto &B = LocalCUBase->getBlock(); - G.addDefinedSymbol(B, 0, *Name, B.getSize(), Linkage::Strong, - Scope::Local, false, true); - } else - return LocalCUBase.takeError(); - } - CompactUnwindBase->setLive(true); - return Error::success(); - } - - Error makePersonalityRangeError(LinkGraph &G, Symbol &PSym) { - std::string ErrMsg; - { - raw_string_ostream ErrStream(ErrMsg); - ErrStream << "In " << G.getName() << " " << UnwindInfoSectionName - << ", personality "; - if (PSym.hasName()) - ErrStream << PSym.getName() << " "; - ErrStream << "at " << PSym.getAddress() - << " is out of 32-bit delta range of compact-unwind base at " - << CompactUnwindBase->getAddress(); - } - return make_error<JITLinkError>(std::move(ErrMsg)); - } - - StringRef CompactUnwindSectionName; - StringRef UnwindInfoSectionName; - StringRef EHFrameSectionName; - Symbol *CompactUnwindBase = nullptr; - - size_t NumLSDAs = 0; - size_t NumSecondLevelPages = 0; - SmallVector<Symbol *, MaxPersonalities> Personalities; - SmallVector<CompactUnwindRecord> Records; -}; - -} // end namespace jitlink -} // end namespace llvm - -#undef DEBUG_TYPE - -#endif // LIB_EXECUTIONENGINE_JITLINK_COMPACTUNWINDSUPPORTIMPL_H diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp index 179e458c3cd1f2..3e757f780b550e 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp @@ -733,5 +733,121 @@ Error MachOLinkGraphBuilder::graphifyCStringSection( return Error::success(); } +Error CompactUnwindSplitter::operator()(LinkGraph &G) { + auto *CUSec = G.findSectionByName(CompactUnwindSectionName); + if (!CUSec) + return Error::success(); + + if (!G.getTargetTriple().isOSBinFormatMachO()) + return make_error<JITLinkError>( + "Error linking " + G.getName() + + ": compact unwind splitting not supported on non-macho target " + + G.getTargetTriple().str()); + + unsigned CURecordSize = 0; + unsigned PersonalityEdgeOffset = 0; + unsigned LSDAEdgeOffset = 0; + switch (G.getTargetTriple().getArch()) { + case Triple::aarch64: + case Triple::x86_64: + // 64-bit compact-unwind record format: + // Range start: 8 bytes. + // Range size: 4 bytes. + // CU encoding: 4 bytes. + // Personality: 8 bytes. + // LSDA: 8 bytes. + CURecordSize = 32; + PersonalityEdgeOffset = 16; + LSDAEdgeOffset = 24; + break; + default: + return make_error<JITLinkError>( + "Error linking " + G.getName() + + ": compact unwind splitting not supported on " + + G.getTargetTriple().getArchName()); + } + + std::vector<Block *> OriginalBlocks(CUSec->blocks().begin(), + CUSec->blocks().end()); + LLVM_DEBUG({ + dbgs() << "In " << G.getName() << " splitting compact unwind section " + << CompactUnwindSectionName << " containing " + << OriginalBlocks.size() << " initial blocks...\n"; + }); + + while (!OriginalBlocks.empty()) { + auto *B = OriginalBlocks.back(); + OriginalBlocks.pop_back(); + + if (B->getSize() == 0) { + LLVM_DEBUG({ + dbgs() << " Skipping empty block at " + << formatv("{0:x16}", B->getAddress()) << "\n"; + }); + continue; + } + + unsigned NumBlocks = B->getSize() / CURecordSize; + + LLVM_DEBUG({ + dbgs() << " Splitting block at " << formatv("{0:x16}", B->getAddress()) + << " into " << NumBlocks << " compact unwind record(s)\n"; + }); + + if (B->getSize() % CURecordSize) + return make_error<JITLinkError>( + "Error splitting compact unwind record in " + G.getName() + + ": block at " + formatv("{0:x}", B->getAddress()) + " has size " + + formatv("{0:x}", B->getSize()) + + " (not a multiple of CU record size of " + + formatv("{0:x}", CURecordSize) + ")"); + + auto Blocks = + G.splitBlock(*B, map_range(seq(1U, NumBlocks), [=](Edge::OffsetT Idx) { + return Idx * CURecordSize; + })); + + for (auto *CURec : Blocks) { + bool AddedKeepAlive = false; + + for (auto &E : CURec->edges()) { + if (E.getOffset() == 0) { + LLVM_DEBUG({ + dbgs() << " Updating compact unwind record at " + << CURec->getAddress() << " to point to " + << (E.getTarget().hasName() ? *E.getTarget().getName() + : StringRef()) + << " (at " << E.getTarget().getAddress() << ")\n"; + }); + + if (E.getTarget().isExternal()) + return make_error<JITLinkError>( + "Error adding keep-alive edge for compact unwind record at " + + formatv("{0:x}", CURec->getAddress()) + ": target " + + *E.getTarget().getName() + " is an external symbol"); + auto &TgtBlock = E.getTarget().getBlock(); + auto &CURecSym = + G.addAnonymousSymbol(*CURec, 0, CURecordSize, false, false); + TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0); + AddedKeepAlive = true; + } else if (E.getOffset() != PersonalityEdgeOffset && + E.getOffset() != LSDAEdgeOffset) + return make_error<JITLinkError>( + "Unexpected edge at offset " + formatv("{0:x}", E.getOffset()) + + " in compact unwind record at " + + formatv("{0:x}", CURec->getAddress())); + } + + if (!AddedKeepAlive) + return make_error<JITLinkError>( + "Error adding keep-alive edge for compact unwind record at " + + formatv("{0:x}", CURec->getAddress()) + + ": no outgoing target edge at offset 0"); + } + } + + return Error::success(); +} + } // end namespace jitlink } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h index 343218ec9ad188..6afa01250f62d6 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h +++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h @@ -236,6 +236,17 @@ class MachOLinkGraphBuilder { StringMap<SectionParserFunction> CustomSectionParserFunctions; }; +/// A pass to split up __LD,__compact_unwind sections. +class CompactUnwindSplitter { +public: + CompactUnwindSplitter(StringRef CompactUnwindSectionName) + : CompactUnwindSectionName(CompactUnwindSectionName) {} + Error operator()(LinkGraph &G); + +private: + StringRef CompactUnwindSectionName; +}; + } // end namespace jitlink } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp index f9f2f4ebb2c8c3..29061fff9c2aea 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp @@ -14,7 +14,6 @@ #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" #include "llvm/ExecutionEngine/JITLink/aarch64.h" -#include "CompactUnwindSupport.h" #include "DefineExternalSectionStartAndEndSymbols.h" #include "MachOLinkGraphBuilder.h" @@ -626,27 +625,6 @@ static Error applyPACSigningToModInitPointers(LinkGraph &G) { return Error::success(); } -struct CompactUnwindTraits_MachO_arm64 - : public CompactUnwindTraits<CompactUnwindTraits_MachO_arm64, - /* PointerSize = */ 8> { - // FIXME: Reinstate once we no longer need the MSVC workaround. See - // FIXME for CompactUnwindTraits in CompactUnwindSupport.h. - // constexpr static size_t PointerSize = 8; - - constexpr static endianness Endianness = endianness::little; - - constexpr static uint32_t EncodingModeMask = 0x0f000000; - - using GOTManager = aarch64::GOTTableManager; - - static bool encodingSpecifiesDWARF(uint32_t Encoding) { - constexpr uint32_t DWARFMode = 0x03000000; - return (Encoding & EncodingModeMask) == DWARFMode; - } - - static bool encodingCannotBeMerged(uint32_t Encoding) { return false; } -}; - void link_MachO_arm64(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) { @@ -659,21 +637,16 @@ void link_MachO_arm64(std::unique_ptr<LinkGraph> G, else Config.PrePrunePasses.push_back(markAllSymbolsLive); + // Add compact unwind splitter pass. + Config.PrePrunePasses.push_back( + CompactUnwindSplitter("__LD,__compact_unwind")); + // Add eh-frame passes. + // FIXME: Prune eh-frames for which compact-unwind is available once + // we support compact-unwind registration with libunwind. Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_arm64()); Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_arm64()); - // Create a compact-unwind manager for use in passes below. - auto CompactUnwindMgr = - std::make_shared<CompactUnwindManager<CompactUnwindTraits_MachO_arm64>>( - "__LD,__compact_unwind", "__TEXT,__unwind_info", - "__TEXT,__eh_frame"); - - // Add compact unwind prepare pass. - Config.PrePrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) { - return CompactUnwindMgr->prepareForPrune(G); - }); - // Resolve any external section start / end symbols. Config.PostAllocationPasses.push_back( createDefineExternalSectionStartAndEndSymbolsPass( @@ -690,16 +663,6 @@ void link_MachO_arm64(std::unique_ptr<LinkGraph> G, Config.PreFixupPasses.push_back( aarch64::lowerPointer64AuthEdgesToSigningFunction); } - - // Reserve unwind-info space. - Config.PostPrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) { - return CompactUnwindMgr->processAndReserveUnwindInfo(G); - }); - - // Translate compact-unwind to unwind-info. - Config.PreFixupPasses.push_back([CompactUnwindMgr](LinkGraph &G) { - return CompactUnwindMgr->writeUnwindInfo(G); - }); } if (auto Err = Ctx->modifyPassConfig(*G, Config)) diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp index 218f8ce97ef037..9547266dc97892 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp @@ -14,7 +14,6 @@ #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" #include "llvm/ExecutionEngine/JITLink/x86_64.h" -#include "CompactUnwindSupport.h" #include "DefineExternalSectionStartAndEndSymbols.h" #include "MachOLinkGraphBuilder.h" @@ -501,55 +500,25 @@ Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromMachOObject_x86_64( .buildGraph(); } -struct CompactUnwindTraits_MachO_x86_64 - : public CompactUnwindTraits<CompactUnwindTraits_MachO_x86_64, - /* PointerSize = */ 8> { - // FIXME: Reinstate once we no longer need the MSVC workaround. See - // FIXME for CompactUnwindTraits in CompactUnwindSupport.h. - // constexpr static size_t PointerSize = 8; - - constexpr static endianness Endianness = endianness::little; - - constexpr static uint32_t EncodingModeMask = 0x0f000000; - - using GOTManager = x86_64::GOTTableManager; - - static bool encodingSpecifiesDWARF(uint32_t Encoding) { - constexpr uint32_t DWARFMode = 0x04000000; - return (Encoding & EncodingModeMask) == DWARFMode; - } - - static bool encodingCannotBeMerged(uint32_t Encoding) { - constexpr uint32_t StackIndirectMode = 0x03000000; - return (Encoding & EncodingModeMask) == StackIndirectMode; - } -}; - void link_MachO_x86_64(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) { PassConfiguration Config; if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { - // Add a mark-live pass. - if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) - Config.PrePrunePasses.push_back(std::move(MarkLive)); - else - Config.PrePrunePasses.push_back(markAllSymbolsLive); - // Add eh-frame passes. Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_x86_64()); Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_x86_64()); - // Create a compact-unwind manager for use in passes below. - auto CompactUnwindMgr = std::make_shared< - CompactUnwindManager<CompactUnwindTraits_MachO_x86_64>>( - "__LD,__compact_unwind", "__TEXT,__unwind_info", "__TEXT,__eh_frame"); + // Add compact unwind splitter pass. + Config.PrePrunePasses.push_back( + CompactUnwindSplitter("__LD,__compact_unwind")); - // Add compact unwind prepare pass. - Config.PrePrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) { - return CompactUnwindMgr->prepareForPrune(G); - }); + // Add a mark-live pass. + if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) + Config.PrePrunePasses.push_back(std::move(MarkLive)); + else + Config.PrePrunePasses.push_back(markAllSymbolsLive); // Resolve any external section start / end symbols. Config.PostAllocationPasses.push_back( @@ -559,16 +528,6 @@ void link_MachO_x86_64(std::unique_ptr<LinkGraph> G, // Add an in-place GOT/Stubs pass. Config.PostPrunePasses.push_back(buildGOTAndStubs_MachO_x86_64); - // Reserve space for unwind-info. - Config.PostPrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) { - return CompactUnwindMgr->processAndReserveUnwindInfo(G); - }); - - // Translate compact-unwind to unwind-info. - Config.PreFixupPasses.push_back([CompactUnwindMgr](LinkGraph &G) { - return CompactUnwindMgr->writeUnwindInfo(G); - }); - // Add GOT/Stubs optimizer pass. Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses); } diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt index 8a866294eee25e..2ab5d6dd39b635 100644 --- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -57,7 +57,6 @@ add_llvm_component_library(LLVMOrcJIT ExecutorProcessControl.cpp TaskDispatch.cpp ThreadSafeModule.cpp - UnwindInfoRegistrationPlugin.cpp RedirectionManager.cpp JITLinkRedirectableSymbolManager.cpp ReOptimizeLayer.cpp diff --git a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp index c4d65af1b57f84..5d2f3cd4a8be8a 100644 --- a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp @@ -33,9 +33,6 @@ irManglingOptionsFromTargetOptions(const TargetOptions &Opts) { /// Compile a Module to an ObjectFile. Expected<SimpleCompiler::CompileResult> SimpleCompiler::operator()(Module &M) { - if (M.getDataLayout().isDefault()) - M.setDataLayout(TM.createDataLayout()); - CompileResult CachedObject = tryToLoadFromObjectCache(M); if (CachedObject) return std::move(CachedObject); diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp index 9f466e725668a2..d47eb4416d3c28 100644 --- a/llvm/lib/ExecutionEngine/Orc/Core.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp @@ -1251,7 +1251,9 @@ JITDylib::JITDylib(ExecutionSession &ES, std::string Name) LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols}); } -JITDylib::RemoveTrackerResult JITDylib::IL_removeTracker(ResourceTracker &RT) { +std::pair<JITDylib::AsynchronousSymbolQuerySet, + std::shared_ptr<SymbolDependenceMap>> +JITDylib::IL_removeTracker(ResourceTracker &RT) { // Note: Should be called under the session lock. assert(State != Closed && "JD is defunct"); @@ -1290,10 +1292,7 @@ JITDylib::RemoveTrackerResult JITDylib::IL_removeTracker(ResourceTracker &RT) { SymbolsToFail.push_back(Sym); } - auto [QueriesToFail, FailedSymbols] = - ES.IL_failSymbols(*this, std::move(SymbolsToFail)); - - std::vector<std::unique_ptr<MaterializationUnit>> DefunctMUs; + auto Result = ES.IL_failSymbols(*this, std::move(SymbolsToFail)); // Removed symbols should be taken out of the table altogether. for (auto &Sym : SymbolsToRemove) { @@ -1303,12 +1302,7 @@ JITDylib::RemoveTrackerResult JITDylib::IL_removeTracker(ResourceTracker &RT) { // Remove Materializer if present. if (I->second.hasMaterializerAttached()) { // FIXME: Should this discard the symbols? - auto J = UnmaterializedInfos.find(Sym); - assert(J != UnmaterializedInfos.end() && - "Symbol table indicates MU present, but no UMI record"); - if (J->second->MU) - DefunctMUs.push_back(std::move(J->second->MU)); - UnmaterializedInfos.erase(J); + UnmaterializedInfos.erase(Sym); } else { assert(!UnmaterializedInfos.count(Sym) && "Symbol has materializer attached"); @@ -1319,8 +1313,7 @@ JITDylib::RemoveTrackerResult JITDylib::IL_removeTracker(ResourceTracker &RT) { shrinkMaterializationInfoMemory(); - return {std::move(QueriesToFail), std::move(FailedSymbols), - std::move(DefunctMUs)}; + return Result; } void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) { @@ -2187,17 +2180,16 @@ Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) { }); std::vector<ResourceManager *> CurrentResourceManagers; - JITDylib::RemoveTrackerResult R; + JITDylib::AsynchronousSymbolQuerySet QueriesToFail; + std::shared_ptr<SymbolDependenceMap> FailedSymbols; runSessionLocked([&] { CurrentResourceManagers = ResourceManagers; RT.makeDefunct(); - R = RT.getJITDylib().IL_removeTracker(RT); + std::tie(QueriesToFail, FailedSymbols) = + RT.getJITDylib().IL_removeTracker(RT); }); - // Release any defunct MaterializationUnits. - R.DefunctMUs.clear(); - Error Err = Error::success(); auto &JD = RT.getJITDylib(); @@ -2205,9 +2197,9 @@ Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) { Err = joinErrors(std::move(Err), L->handleRemoveResources(JD, RT.getKeyUnsafe())); - for (auto &Q : R.QueriesToFail) - Q->handleFailed(make_error<FailedToMaterialize>(getSymbolStringPool(), - R.FailedSymbols)); + for (auto &Q : QueriesToFail) + Q->handleFailed( + make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols)); return Err; } diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp index b51fa24be76d1a..aa799687e6d5d1 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp @@ -45,7 +45,6 @@ SelfExecutorProcessControl::SelfExecutorProcessControl( this->DylibMgr = this; this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager), ExecutorAddr::fromPtr(this)}; - if (this->TargetTriple.isOSBinFormatMachO()) GlobalManglingPrefix = '_'; @@ -53,12 +52,6 @@ SelfExecutorProcessControl::SelfExecutorProcessControl( ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper); this->BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] = ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper); - -#ifdef __APPLE__ - this->UnwindInfoMgr = UnwindInfoManager::TryCreate(); - if (this->UnwindInfoMgr) - this->UnwindInfoMgr->addBootstrapSymbols(this->BootstrapSymbols); -#endif // __APPLE__ } Expected<std::unique_ptr<SelfExecutorProcessControl>> diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp index ab7f854187b335..80500d0fdd9bcb 100644 --- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp @@ -21,7 +21,6 @@ #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" -#include "llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" @@ -1221,28 +1220,12 @@ Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J) { if (auto *OLL = dyn_cast<ObjectLinkingLayer>(&J.getObjLinkingLayer())) { - bool CompactUnwindInfoSupported = false; - - // Enable compact-unwind support if possible. - if (J.getTargetTriple().isOSDarwin() || - J.getTargetTriple().isOSBinFormatMachO()) { - if (auto UIRP = UnwindInfoRegistrationPlugin::Create( - J.getIRCompileLayer(), PlatformJD)) { - CompactUnwindInfoSupported = true; - OLL->addPlugin(std::move(*UIRP)); - } else - consumeError(UIRP.takeError()); - } - - // Otherwise fall back to standard unwind registration. - if (!CompactUnwindInfoSupported) { - auto &ES = J.getExecutionSession(); - if (auto EHFrameRegistrar = EPCEHFrameRegistrar::Create(ES)) - OLL->addPlugin(std::make_unique<EHFrameRegistrationPlugin>( - ES, std::move(*EHFrameRegistrar))); - else - return EHFrameRegistrar.takeError(); - } + auto &ES = J.getExecutionSession(); + if (auto EHFrameRegistrar = EPCEHFrameRegistrar::Create(ES)) + OLL->addPlugin(std::make_unique<EHFrameRegistrationPlugin>( + ES, std::move(*EHFrameRegistrar))); + else + return EHFrameRegistrar.takeError(); } J.setPlatformSupport( diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp index fef3ff989a52ae..54a25c007c589d 100644 --- a/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp @@ -64,19 +64,5 @@ const char *RunAsIntFunctionWrapperName = "__llvm_orc_bootstrap_run_as_int_function_wrapper"; } // end namespace rt -namespace rt_alt { -const char *UnwindInfoManagerInstanceName = - "orc_rt_alt_UnwindInfoManager_Instance"; -const char *UnwindInfoManagerFindSectionsHelperName = - "orc_rt_alt_UnwindInfoManager_findSectionsHelper"; -const char *UnwindInfoManagerEnableWrapperName = - "orc_rt_alt_UnwindInfoManager_enable"; -const char *UnwindInfoManagerDisableWrapperName = - "orc_rt_alt_UnwindInfoManager_disable"; -const char *UnwindInfoManagerRegisterActionName = - "orc_rt_alt_UnwindInfoManager_register"; -const char *UnwindInfoManagerDeregisterActionName = - "orc_rt_alt_UnwindInfoManager_deregister"; -} // end namespace rt_alt } // end namespace orc } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt index ffc1bbfa121b39..3d1dfe758c79dd 100644 --- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt @@ -20,7 +20,6 @@ add_llvm_component_library(LLVMOrcTargetProcess SimpleExecutorMemoryManager.cpp SimpleRemoteEPCServer.cpp TargetExecutionUtils.cpp - UnwindInfoManager.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.cpp deleted file mode 100644 index 68bba9520c19fe..00000000000000 --- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.cpp +++ /dev/null @@ -1,188 +0,0 @@ -//===------- UnwindInfoManager.cpp - Register unwind info sections --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h" -#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" -#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" -#include "llvm/Support/DynamicLibrary.h" - -#define DEBUG_TYPE "orc" - -using namespace llvm; -using namespace llvm::orc; -using namespace llvm::orc::shared; - -static orc::shared::CWrapperFunctionResult -llvm_orc_rt_alt_UnwindInfoManager_enable(const char *Data, uint64_t Size) { - return WrapperFunction<SPSError(SPSExecutorAddr, SPSExecutorAddr)>::handle( - Data, Size, - [](ExecutorAddr Instance, ExecutorAddr FindFn) { - return Instance.toPtr<UnwindInfoManager *>()->enable( - FindFn.toPtr<void *>()); - }) - .release(); -} - -static orc::shared::CWrapperFunctionResult -llvm_orc_rt_alt_UnwindInfoManager_disable(const char *Data, uint64_t Size) { - return WrapperFunction<SPSError(SPSExecutorAddr)>::handle( - Data, Size, - [](ExecutorAddr Instance) { - return Instance.toPtr<UnwindInfoManager *>()->disable(); - }) - .release(); -} - -static orc::shared::CWrapperFunctionResult -llvm_orc_rt_alt_UnwindInfoManager_register(const char *Data, uint64_t Size) { - using SPSSig = - SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddrRange>, - SPSExecutorAddr, SPSExecutorAddrRange, SPSExecutorAddrRange); - - return WrapperFunction<SPSSig>::handle( - Data, Size, - [](ExecutorAddr Instance, - std::vector<ExecutorAddrRange> CodeRanges, ExecutorAddr DSOBase, - ExecutorAddrRange DWARFRange, - ExecutorAddrRange CompactUnwindRange) { - return Instance.toPtr<UnwindInfoManager *>()->registerSections( - CodeRanges, DSOBase, DWARFRange, CompactUnwindRange); - }) - .release(); -} - -static orc::shared::CWrapperFunctionResult -llvm_orc_rt_alt_UnwindInfoManager_deregister(const char *Data, uint64_t Size) { - using SPSSig = SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddrRange>); - - return WrapperFunction<SPSSig>::handle( - Data, Size, - [](ExecutorAddr Instance, - std::vector<ExecutorAddrRange> CodeRanges) { - return Instance.toPtr<UnwindInfoManager *>()->deregisterSections( - CodeRanges); - }) - .release(); -} - -namespace llvm::orc { - -const char *UnwindInfoManager::AddFnName = - "__unw_add_find_dynamic_unwind_sections"; -const char *UnwindInfoManager::RemoveFnName = - "__unw_remove_find_dynamic_unwind_sections"; - -std::unique_ptr<UnwindInfoManager> UnwindInfoManager::TryCreate() { - std::string ErrMsg; - auto DL = sys::DynamicLibrary::getPermanentLibrary(nullptr, &ErrMsg); - if (!DL.isValid()) - return nullptr; - - auto AddFindDynamicUnwindSections = - (int (*)(void *))DL.getAddressOfSymbol(AddFnName); - if (!AddFindDynamicUnwindSections) - return nullptr; - - auto RemoveFindDynamicUnwindSections = - (int (*)(void *))DL.getAddressOfSymbol(RemoveFnName); - if (!RemoveFindDynamicUnwindSections) - return nullptr; - - return std::unique_ptr<UnwindInfoManager>(new UnwindInfoManager( - AddFindDynamicUnwindSections, RemoveFindDynamicUnwindSections)); -} - -Error UnwindInfoManager::shutdown() { return Error::success(); } - -void UnwindInfoManager::addBootstrapSymbols(StringMap<ExecutorAddr> &M) { - M[rt_alt::UnwindInfoManagerInstanceName] = ExecutorAddr::fromPtr(this); - M[rt_alt::UnwindInfoManagerFindSectionsHelperName] = - ExecutorAddr::fromPtr(&findSectionsHelper); - M[rt_alt::UnwindInfoManagerEnableWrapperName] = - ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_enable); - M[rt_alt::UnwindInfoManagerDisableWrapperName] = - ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_disable); - M[rt_alt::UnwindInfoManagerRegisterActionName] = - ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_register); - M[rt_alt::UnwindInfoManagerDeregisterActionName] = - ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_deregister); -} - -Error UnwindInfoManager::enable(void *FindDynamicUnwindSections) { - LLVM_DEBUG(dbgs() << "Enabling UnwindInfoManager.\n"); - - if (auto Err = AddFindDynamicUnwindSections(FindDynamicUnwindSections)) - return make_error<StringError>(Twine("Could not register function via ") + - AddFnName + - ", error code = " + Twine(Err), - inconvertibleErrorCode()); - - this->FindDynamicUnwindSections = FindDynamicUnwindSections; - return Error::success(); -} - -Error UnwindInfoManager::disable(void) { - LLVM_DEBUG(dbgs() << "Disabling UnwindInfoManager.\n"); - - if (FindDynamicUnwindSections) - if (auto Err = RemoveFindDynamicUnwindSections(FindDynamicUnwindSections)) - return make_error<StringError>( - Twine("Could not deregister function via ") + RemoveFnName + - "error code = " + Twine(Err), - inconvertibleErrorCode()); - - FindDynamicUnwindSections = nullptr; - return Error::success(); -} - -Error UnwindInfoManager::registerSections( - ArrayRef<ExecutorAddrRange> CodeRanges, ExecutorAddr DSOBase, - ExecutorAddrRange DWARFEHFrame, ExecutorAddrRange CompactUnwind) { - std::lock_guard<std::mutex> Lock(M); - for (auto &R : CodeRanges) - UWSecs[R.Start.getValue()] = UnwindSections{ - static_cast<uintptr_t>(DSOBase.getValue()), - static_cast<uintptr_t>(DWARFEHFrame.Start.getValue()), - static_cast<size_t>(DWARFEHFrame.size()), - static_cast<uintptr_t>(CompactUnwind.Start.getValue()), - static_cast<size_t>(CompactUnwind.size())}; - return Error::success(); -} - -Error UnwindInfoManager::deregisterSections( - ArrayRef<ExecutorAddrRange> CodeRanges) { - std::lock_guard<std::mutex> Lock(M); - for (auto &R : CodeRanges) { - auto I = UWSecs.find(R.Start.getValue()); - if (I == UWSecs.end()) - return make_error<StringError>( - "No unwind-info sections registered for range " + - formatv("{0:x} - {1:x}", R.Start, R.End), - inconvertibleErrorCode()); - UWSecs.erase(I); - } - return Error::success(); -} - -int UnwindInfoManager::findSections(uintptr_t Addr, UnwindSections *Info) { - std::lock_guard<std::mutex> Lock(M); - auto I = UWSecs.upper_bound(Addr); - if (I == UWSecs.begin()) - return 0; - --I; - *Info = I->second; - return 1; -} - -int UnwindInfoManager::findSectionsHelper(UnwindInfoManager *Instance, - uintptr_t Addr, - UnwindSections *Info) { - return Instance->findSections(Addr, Info); -} - -} // namespace llvm::orc diff --git a/llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp deleted file mode 100644 index 0073f3daf7f23a..00000000000000 --- a/llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp +++ /dev/null @@ -1,238 +0,0 @@ -//===----- UnwindInfoRegistrationPlugin.cpp - libunwind registration ------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h" - -#include "llvm/ADT/ScopeExit.h" -#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h" -#include "llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h" -#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" - -#define DEBUG_TYPE "orc" - -using namespace llvm::jitlink; - -static const char *FindDynamicUnwindSectionsFunctionName = - "_orc_rt_alt_find_dynamic_unwind_sections"; - -namespace llvm::orc { - -Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>> -UnwindInfoRegistrationPlugin::Create(IRLayer &IRL, JITDylib &PlatformJD, - ExecutorAddr Instance, - ExecutorAddr FindHelper, - ExecutorAddr Enable, ExecutorAddr Disable, - ExecutorAddr Register, - ExecutorAddr Deregister) { - - auto &ES = IRL.getExecutionSession(); - - // Build bouncer module. - auto M = makeBouncerModule(ES); - if (!M) - return M.takeError(); - - auto BouncerRT = PlatformJD.createResourceTracker(); - auto RemoveBouncerModule = make_scope_exit([&]() { - if (auto Err = BouncerRT->remove()) - ES.reportError(std::move(Err)); - }); - - if (auto Err = PlatformJD.define(absoluteSymbols( - {{ES.intern(rt_alt::UnwindInfoManagerInstanceName), - ExecutorSymbolDef(Instance, JITSymbolFlags())}, - {ES.intern(rt_alt::UnwindInfoManagerFindSectionsHelperName), - ExecutorSymbolDef(FindHelper, JITSymbolFlags::Callable)}}))) - return std::move(Err); - - if (auto Err = IRL.add(BouncerRT, std::move(*M))) - return Err; - - auto FindUnwindSections = - ES.lookup({&PlatformJD}, FindDynamicUnwindSectionsFunctionName); - if (!FindUnwindSections) - return FindUnwindSections.takeError(); - - using namespace shared; - using SPSEnableSig = SPSError(SPSExecutorAddr, SPSExecutorAddr); - Error CallErr = Error::success(); - if (auto Err = ES.callSPSWrapper<SPSEnableSig>( - Enable, CallErr, Instance, FindUnwindSections->getAddress())) { - consumeError(std::move(CallErr)); - return std::move(Err); - } - - if (CallErr) - return std::move(CallErr); - - RemoveBouncerModule.release(); - - return std::shared_ptr<UnwindInfoRegistrationPlugin>( - new UnwindInfoRegistrationPlugin(ES, Instance, Disable, Register, - Deregister)); -} - -Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>> -UnwindInfoRegistrationPlugin::Create(IRLayer &IRL, JITDylib &PlatformJD) { - - ExecutorAddr Instance, FindHelper, Enable, Disable, Register, Deregister; - - auto &EPC = IRL.getExecutionSession().getExecutorProcessControl(); - if (auto Err = EPC.getBootstrapSymbols( - {{Instance, rt_alt::UnwindInfoManagerInstanceName}, - {FindHelper, rt_alt::UnwindInfoManagerFindSectionsHelperName}, - {Enable, rt_alt::UnwindInfoManagerEnableWrapperName}, - {Disable, rt_alt::UnwindInfoManagerDisableWrapperName}, - {Register, rt_alt::UnwindInfoManagerRegisterActionName}, - {Deregister, rt_alt::UnwindInfoManagerDeregisterActionName}})) - return std::move(Err); - - return Create(IRL, PlatformJD, Instance, FindHelper, Enable, Disable, - Register, Deregister); -} - -UnwindInfoRegistrationPlugin::~UnwindInfoRegistrationPlugin() { - using namespace shared; - using SPSDisableSig = SPSError(SPSExecutorAddr); - Error CallErr = Error::success(); - if (auto Err = ES.callSPSWrapper<SPSDisableSig>(Disable, CallErr, Instance)) { - consumeError(std::move(CallErr)); - ES.reportError(std::move(Err)); - } - if (CallErr) - ES.reportError(std::move(CallErr)); -} - -void UnwindInfoRegistrationPlugin::modifyPassConfig( - MaterializationResponsibility &MR, LinkGraph &G, - PassConfiguration &PassConfig) { - - PassConfig.PostFixupPasses.push_back( - [this](LinkGraph &G) { return addUnwindInfoRegistrationActions(G); }); -} - -Expected<ThreadSafeModule> -UnwindInfoRegistrationPlugin::makeBouncerModule(ExecutionSession &ES) { - auto Ctx = std::make_unique<LLVMContext>(); - auto M = std::make_unique<Module>("__libunwind_find_unwind_bouncer", *Ctx); - M->setTargetTriple(ES.getTargetTriple().str()); - - auto EscapeName = [](const char *N) { return std::string("\01") + N; }; - - auto *PtrTy = PointerType::getUnqual(*Ctx); - auto *OpaqueStructTy = StructType::create(*Ctx, "UnwindInfoMgr"); - auto *UnwindMgrInstance = new GlobalVariable( - *M, OpaqueStructTy, true, GlobalValue::ExternalLinkage, nullptr, - EscapeName(rt_alt::UnwindInfoManagerInstanceName)); - - auto *Int64Ty = Type::getInt64Ty(*Ctx); - auto *FindHelperTy = FunctionType::get(Int64Ty, {PtrTy, PtrTy, PtrTy}, false); - auto *FindHelperFn = Function::Create( - FindHelperTy, GlobalValue::ExternalLinkage, - EscapeName(rt_alt::UnwindInfoManagerFindSectionsHelperName), *M); - - auto *FindFnTy = FunctionType::get(Int64Ty, {PtrTy, PtrTy}, false); - auto *FindFn = - Function::Create(FindFnTy, GlobalValue::ExternalLinkage, - EscapeName(FindDynamicUnwindSectionsFunctionName), *M); - auto *EntryBlock = BasicBlock::Create(M->getContext(), StringRef(), FindFn); - IRBuilder<> IB(EntryBlock); - - std::vector<Value *> FindHelperArgs; - FindHelperArgs.push_back(UnwindMgrInstance); - for (auto &Arg : FindFn->args()) - FindHelperArgs.push_back(&Arg); - - IB.CreateRet(IB.CreateCall(FindHelperFn, FindHelperArgs)); - - return ThreadSafeModule(std::move(M), std::move(Ctx)); -} - -Error UnwindInfoRegistrationPlugin::addUnwindInfoRegistrationActions( - LinkGraph &G) { - ExecutorAddrRange EHFrameRange, UnwindInfoRange; - - std::vector<Block *> CodeBlocks; - - auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) { - if (Sec.empty()) - return; - - SecRange.Start = (*Sec.blocks().begin())->getAddress(); - 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.getKind() != Edge::KeepAlive || !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 (auto *EHFrame = G.findSectionByName(MachOEHFrameSectionName)) - ScanUnwindInfoSection(*EHFrame, EHFrameRange); - - if (auto *UnwindInfo = G.findSectionByName(MachOCompactUnwindInfoSectionName)) - ScanUnwindInfoSection(*UnwindInfo, UnwindInfoRange); - - if (CodeBlocks.empty()) - return Error::success(); - - if ((EHFrameRange == ExecutorAddrRange() && - UnwindInfoRange == ExecutorAddrRange())) - return Error::success(); - - llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) { - return LHS->getAddress() < RHS->getAddress(); - }); - - SmallVector<ExecutorAddrRange> CodeRanges; - for (auto *B : CodeBlocks) { - if (CodeRanges.empty() || CodeRanges.back().End != B->getAddress()) - CodeRanges.push_back(B->getRange()); - else - CodeRanges.back().End = B->getRange().End; - } - - ExecutorAddr DSOBase; - if (auto *DSOBaseSym = G.findAbsoluteSymbolByName(DSOBaseName)) - DSOBase = DSOBaseSym->getAddress(); - else if (auto *DSOBaseSym = G.findExternalSymbolByName(DSOBaseName)) - DSOBase = DSOBaseSym->getAddress(); - else if (auto *DSOBaseSym = G.findDefinedSymbolByName(DSOBaseName)) - DSOBase = DSOBaseSym->getAddress(); - else - return make_error<StringError>("In " + G.getName() + - " could not find dso base symbol", - inconvertibleErrorCode()); - - using namespace shared; - using SPSRegisterArgs = - SPSArgList<SPSExecutorAddr, SPSSequence<SPSExecutorAddrRange>, - SPSExecutorAddr, SPSExecutorAddrRange, SPSExecutorAddrRange>; - using SPSDeregisterArgs = - SPSArgList<SPSExecutorAddr, SPSSequence<SPSExecutorAddrRange>>; - - G.allocActions().push_back( - {cantFail(WrapperFunctionCall::Create<SPSRegisterArgs>( - Register, Instance, CodeRanges, DSOBase, EHFrameRange, - UnwindInfoRange)), - cantFail(WrapperFunctionCall::Create<SPSDeregisterArgs>( - Deregister, Instance, CodeRanges))}); - - return Error::success(); -} - -} // namespace llvm::orc _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits