//===------- 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::handle( Data, Size, [](ExecutorAddr Instance, ExecutorAddr FindFn) { return Instance.toPtr()->enable( FindFn.toPtr()); }) .release(); } static orc::shared::CWrapperFunctionResult llvm_orc_rt_alt_UnwindInfoManager_disable(const char *Data, uint64_t Size) { return WrapperFunction::handle( Data, Size, [](ExecutorAddr Instance) { return Instance.toPtr()->disable(); }) .release(); } static orc::shared::CWrapperFunctionResult llvm_orc_rt_alt_UnwindInfoManager_register(const char *Data, uint64_t Size) { using SPSSig = SPSError(SPSExecutorAddr, SPSSequence, SPSExecutorAddr, SPSExecutorAddrRange, SPSExecutorAddrRange); return WrapperFunction::handle( Data, Size, [](ExecutorAddr Instance, std::vector CodeRanges, ExecutorAddr DSOBase, ExecutorAddrRange DWARFRange, ExecutorAddrRange CompactUnwindRange) { return Instance.toPtr()->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); return WrapperFunction::handle( Data, Size, [](ExecutorAddr Instance, std::vector CodeRanges) { return Instance.toPtr()->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::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(new UnwindInfoManager( AddFindDynamicUnwindSections, RemoveFindDynamicUnwindSections)); } Error UnwindInfoManager::shutdown() { return Error::success(); } void UnwindInfoManager::addBootstrapSymbols(StringMap &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(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( Twine("Could not deregister function via ") + RemoveFnName + "error code = " + Twine(Err), inconvertibleErrorCode()); FindDynamicUnwindSections = nullptr; return Error::success(); } Error UnwindInfoManager::registerSections( 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::deregisterSections( 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(); } int UnwindInfoManager::findSections(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::findSectionsHelper(UnwindInfoManager *Instance, uintptr_t Addr, UnwindSections *Info) { return Instance->findSections(Addr, Info); } } // namespace llvm::orc