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-exception 6 // 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 19 using namespace llvm; 20 using namespace llvm::orc; 21 using namespace llvm::orc::shared; 22 23 static orc::shared::CWrapperFunctionResult 24 llvm_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 40 static orc::shared::CWrapperFunctionResult 41 llvm_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 53 namespace 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"; 59 static std::unique_ptr<UnwindInfoManager> Instance; 60 static int (*RemoveFindDynamicUnwindSections)(void *) = nullptr; 61 62 UnwindInfoManager::~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 = " << Err 67 << "\n"; 68 }); 69 (void)Err; 70 } 71 } 72 73 bool 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 #else 104 return false; 105 #endif // __APPLE__ 106 } 107 108 void 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 115 Error 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 122 Error UnwindInfoManager::deregisterSections( 123 ArrayRef<orc::ExecutorAddrRange> CodeRanges) { 124 return Instance->deregisterSectionsImpl(CodeRanges); 125 } 126 127 int 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 137 int UnwindInfoManager::findSections(uintptr_t Addr, UnwindSections *Info) { 138 return Instance->findSectionsImpl(Addr, Info); 139 } 140 141 Error 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 155 Error 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::orc 171