171 lines · cpp
1//===------- UnwindInfoManager.cpp - Register unwind info sections --------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h"10#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"11#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"12 13#ifdef __APPLE__14#include <dlfcn.h>15#endif // __APPLE__16 17#define DEBUG_TYPE "orc"18 19using namespace llvm;20using namespace llvm::orc;21using namespace llvm::orc::shared;22 23static orc::shared::CWrapperFunctionResult24llvm_orc_rt_alt_UnwindInfoManager_register(const char *ArgData,25 size_t ArgSize) {26 using SPSSig = SPSError(SPSSequence<SPSExecutorAddrRange>, SPSExecutorAddr,27 SPSExecutorAddrRange, SPSExecutorAddrRange);28 29 return WrapperFunction<SPSSig>::handle(30 ArgData, ArgSize,31 [](std::vector<ExecutorAddrRange> CodeRanges, ExecutorAddr DSOBase,32 ExecutorAddrRange DWARFRange,33 ExecutorAddrRange CompactUnwindRange) {34 return UnwindInfoManager::registerSections(35 CodeRanges, DSOBase, DWARFRange, CompactUnwindRange);36 })37 .release();38}39 40static orc::shared::CWrapperFunctionResult41llvm_orc_rt_alt_UnwindInfoManager_deregister(const char *ArgData,42 size_t ArgSize) {43 using SPSSig = SPSError(SPSSequence<SPSExecutorAddrRange>);44 45 return WrapperFunction<SPSSig>::handle(46 ArgData, ArgSize,47 [](std::vector<ExecutorAddrRange> CodeRanges) {48 return UnwindInfoManager::deregisterSections(CodeRanges);49 })50 .release();51}52 53namespace llvm::orc {54 55[[maybe_unused]] static const char *AddFnName =56 "__unw_add_find_dynamic_unwind_sections";57[[maybe_unused]] static const char *RemoveFnName =58 "__unw_remove_find_dynamic_unwind_sections";59static std::unique_ptr<UnwindInfoManager> Instance;60static int (*RemoveFindDynamicUnwindSections)(void *) = nullptr;61 62UnwindInfoManager::~UnwindInfoManager() {63 if (int Err = RemoveFindDynamicUnwindSections((void *)&findSections)) {64 (void)Err; // Silence unused variable warning in release builds.65 LLVM_DEBUG({66 dbgs() << "Failed call to " << RemoveFnName << ": error = " << Err67 << "\n";68 });69 (void)Err;70 }71}72 73bool UnwindInfoManager::TryEnable() {74#ifdef __APPLE__75 static std::mutex M;76 std::lock_guard<std::mutex> Lock(M);77 78 if (Instance)79 return true;80 81 auto AddFn = (int (*)(void *))dlsym(RTLD_DEFAULT, AddFnName);82 if (!AddFn)83 return false;84 85 auto RemoveFn = (int (*)(void *))dlsym(RTLD_DEFAULT, RemoveFnName);86 if (!RemoveFn)87 return false;88 89 Instance.reset(new UnwindInfoManager());90 91 if (auto Err = AddFn((void *)&findSections)) {92 (void)Err; // Silence unused variable warning in release builds.93 LLVM_DEBUG({94 dbgs() << "Failed call to " << AddFnName << ": error = " << Err << "\n";95 });96 Instance = nullptr;97 return false;98 }99 100 RemoveFindDynamicUnwindSections = RemoveFn;101 return true;102 103#else104 return false;105#endif // __APPLE__106}107 108void UnwindInfoManager::addBootstrapSymbols(StringMap<ExecutorAddr> &M) {109 M[rt_alt::UnwindInfoManagerRegisterActionName] =110 ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_register);111 M[rt_alt::UnwindInfoManagerDeregisterActionName] =112 ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_deregister);113}114 115Error UnwindInfoManager::registerSections(116 ArrayRef<orc::ExecutorAddrRange> CodeRanges, orc::ExecutorAddr DSOBase,117 orc::ExecutorAddrRange DWARFEHFrame, orc::ExecutorAddrRange CompactUnwind) {118 return Instance->registerSectionsImpl(CodeRanges, DSOBase, DWARFEHFrame,119 CompactUnwind);120}121 122Error UnwindInfoManager::deregisterSections(123 ArrayRef<orc::ExecutorAddrRange> CodeRanges) {124 return Instance->deregisterSectionsImpl(CodeRanges);125}126 127int UnwindInfoManager::findSectionsImpl(uintptr_t Addr, UnwindSections *Info) {128 std::lock_guard<std::mutex> Lock(M);129 auto I = UWSecs.upper_bound(Addr);130 if (I == UWSecs.begin())131 return 0;132 --I;133 *Info = I->second;134 return 1;135}136 137int UnwindInfoManager::findSections(uintptr_t Addr, UnwindSections *Info) {138 return Instance->findSectionsImpl(Addr, Info);139}140 141Error UnwindInfoManager::registerSectionsImpl(142 ArrayRef<ExecutorAddrRange> CodeRanges, ExecutorAddr DSOBase,143 ExecutorAddrRange DWARFEHFrame, ExecutorAddrRange CompactUnwind) {144 std::lock_guard<std::mutex> Lock(M);145 for (auto &R : CodeRanges)146 UWSecs[R.Start.getValue()] =147 UnwindSections{static_cast<uintptr_t>(DSOBase.getValue()),148 static_cast<uintptr_t>(DWARFEHFrame.Start.getValue()),149 static_cast<size_t>(DWARFEHFrame.size()),150 static_cast<uintptr_t>(CompactUnwind.Start.getValue()),151 static_cast<size_t>(CompactUnwind.size())};152 return Error::success();153}154 155Error UnwindInfoManager::deregisterSectionsImpl(156 ArrayRef<ExecutorAddrRange> CodeRanges) {157 std::lock_guard<std::mutex> Lock(M);158 for (auto &R : CodeRanges) {159 auto I = UWSecs.find(R.Start.getValue());160 if (I == UWSecs.end())161 return make_error<StringError>(162 "No unwind-info sections registered for range " +163 formatv("{0:x} - {1:x}", R.Start, R.End),164 inconvertibleErrorCode());165 UWSecs.erase(I);166 }167 return Error::success();168}169 170} // namespace llvm::orc171