//===------- 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" #ifdef __APPLE__ #include #endif // __APPLE__ #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_register(const char *ArgData, size_t ArgSize) { using SPSSig = SPSError(SPSSequence, SPSExecutorAddr, SPSExecutorAddrRange, SPSExecutorAddrRange); return WrapperFunction::handle( ArgData, ArgSize, [](std::vector CodeRanges, ExecutorAddr DSOBase, ExecutorAddrRange DWARFRange, ExecutorAddrRange CompactUnwindRange) { return UnwindInfoManager::registerSections( CodeRanges, DSOBase, DWARFRange, CompactUnwindRange); }) .release(); } static orc::shared::CWrapperFunctionResult llvm_orc_rt_alt_UnwindInfoManager_deregister(const char *ArgData, size_t ArgSize) { using SPSSig = SPSError(SPSSequence); return WrapperFunction::handle( ArgData, ArgSize, [](std::vector CodeRanges) { return UnwindInfoManager::deregisterSections(CodeRanges); }) .release(); } namespace llvm::orc { [[maybe_unused]] static const char *AddFnName = "__unw_add_find_dynamic_unwind_sections"; [[maybe_unused]] static const char *RemoveFnName = "__unw_remove_find_dynamic_unwind_sections"; static std::unique_ptr Instance; static int (*RemoveFindDynamicUnwindSections)(void *) = nullptr; UnwindInfoManager::~UnwindInfoManager() { if (int Err = RemoveFindDynamicUnwindSections((void *)&findSections)) { (void)Err; // Silence unused variable warning in release builds. LLVM_DEBUG({ dbgs() << "Failed call to " << RemoveFnName << ": error = " << Err << "\n"; }); (void)Err; } } bool UnwindInfoManager::TryEnable() { #ifdef __APPLE__ static std::mutex M; std::lock_guard Lock(M); if (Instance) return true; auto AddFn = (int (*)(void *))dlsym(RTLD_DEFAULT, AddFnName); if (!AddFn) return false; auto RemoveFn = (int (*)(void *))dlsym(RTLD_DEFAULT, RemoveFnName); if (!RemoveFn) return false; Instance.reset(new UnwindInfoManager()); if (auto Err = AddFn((void *)&findSections)) { (void)Err; // Silence unused variable warning in release builds. LLVM_DEBUG({ dbgs() << "Failed call to " << AddFnName << ": error = " << Err << "\n"; }); Instance = nullptr; return false; } RemoveFindDynamicUnwindSections = RemoveFn; return true; #else return false; #endif // __APPLE__ } void UnwindInfoManager::addBootstrapSymbols(StringMap &M) { 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::registerSections( ArrayRef CodeRanges, orc::ExecutorAddr DSOBase, orc::ExecutorAddrRange DWARFEHFrame, orc::ExecutorAddrRange CompactUnwind) { return Instance->registerSectionsImpl(CodeRanges, DSOBase, DWARFEHFrame, CompactUnwind); } Error UnwindInfoManager::deregisterSections( ArrayRef CodeRanges) { return Instance->deregisterSectionsImpl(CodeRanges); } int UnwindInfoManager::findSectionsImpl(uintptr_t Addr, UnwindSections *Info) { std::lock_guard Lock(M); auto I = UWSecs.upper_bound(Addr); if (I == UWSecs.begin()) return 0; --I; *Info = I->second; return 1; } int UnwindInfoManager::findSections(uintptr_t Addr, UnwindSections *Info) { return Instance->findSectionsImpl(Addr, Info); } Error UnwindInfoManager::registerSectionsImpl( ArrayRef CodeRanges, ExecutorAddr DSOBase, ExecutorAddrRange DWARFEHFrame, ExecutorAddrRange CompactUnwind) { std::lock_guard Lock(M); for (auto &R : CodeRanges) UWSecs[R.Start.getValue()] = UnwindSections{static_cast(DSOBase.getValue()), static_cast(DWARFEHFrame.Start.getValue()), static_cast(DWARFEHFrame.size()), static_cast(CompactUnwind.Start.getValue()), static_cast(CompactUnwind.size())}; return Error::success(); } Error UnwindInfoManager::deregisterSectionsImpl( ArrayRef CodeRanges) { std::lock_guard Lock(M); for (auto &R : CodeRanges) { auto I = UWSecs.find(R.Start.getValue()); if (I == UWSecs.end()) return make_error( "No unwind-info sections registered for range " + formatv("{0:x} - {1:x}", R.Start, R.End), inconvertibleErrorCode()); UWSecs.erase(I); } return Error::success(); } } // namespace llvm::orc