1 //===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===// 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/ExecutorProcessControl.h" 10 11 #include "llvm/ExecutionEngine/Orc/Core.h" 12 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 13 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" 14 #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" 15 #include "llvm/Support/Process.h" 16 #include "llvm/TargetParser/Host.h" 17 18 #define DEBUG_TYPE "orc" 19 20 namespace llvm { 21 namespace orc { 22 23 DylibManager::~DylibManager() = default; 24 25 ExecutorProcessControl::MemoryAccess::~MemoryAccess() = default; 26 27 ExecutorProcessControl::~ExecutorProcessControl() = default; 28 29 SelfExecutorProcessControl::SelfExecutorProcessControl( 30 std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D, 31 Triple TargetTriple, unsigned PageSize, 32 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) 33 : ExecutorProcessControl(std::move(SSP), std::move(D)), 34 InProcessMemoryAccess(TargetTriple.isArch64Bit()) { 35 36 OwnedMemMgr = std::move(MemMgr); 37 if (!OwnedMemMgr) 38 OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>( 39 sys::Process::getPageSizeEstimate()); 40 41 this->TargetTriple = std::move(TargetTriple); 42 this->PageSize = PageSize; 43 this->MemMgr = OwnedMemMgr.get(); 44 this->MemAccess = this; 45 this->DylibMgr = this; 46 this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager), 47 ExecutorAddr::fromPtr(this)}; 48 if (this->TargetTriple.isOSBinFormatMachO()) 49 GlobalManglingPrefix = '_'; 50 51 this->BootstrapSymbols[rt::RegisterEHFrameSectionWrapperName] = 52 ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper); 53 this->BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] = 54 ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper); 55 } 56 57 Expected<std::unique_ptr<SelfExecutorProcessControl>> 58 SelfExecutorProcessControl::Create( 59 std::shared_ptr<SymbolStringPool> SSP, 60 std::unique_ptr<TaskDispatcher> D, 61 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) { 62 63 if (!SSP) 64 SSP = std::make_shared<SymbolStringPool>(); 65 66 if (!D) 67 D = std::make_unique<InPlaceTaskDispatcher>(); 68 69 auto PageSize = sys::Process::getPageSize(); 70 if (!PageSize) 71 return PageSize.takeError(); 72 73 Triple TT(sys::getProcessTriple()); 74 75 return std::make_unique<SelfExecutorProcessControl>( 76 std::move(SSP), std::move(D), std::move(TT), *PageSize, 77 std::move(MemMgr)); 78 } 79 80 Expected<tpctypes::DylibHandle> 81 SelfExecutorProcessControl::loadDylib(const char *DylibPath) { 82 std::string ErrMsg; 83 auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg); 84 if (!Dylib.isValid()) 85 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 86 return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle()); 87 } 88 89 void SelfExecutorProcessControl::lookupSymbolsAsync( 90 ArrayRef<LookupRequest> Request, 91 DylibManager::SymbolLookupCompleteFn Complete) { 92 std::vector<tpctypes::LookupResult> R; 93 94 for (auto &Elem : Request) { 95 sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>()); 96 R.push_back(std::vector<ExecutorSymbolDef>()); 97 for (auto &KV : Elem.Symbols) { 98 auto &Sym = KV.first; 99 std::string Tmp((*Sym).data() + !!GlobalManglingPrefix, 100 (*Sym).size() - !!GlobalManglingPrefix); 101 void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str()); 102 if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) { 103 // FIXME: Collect all failing symbols before erroring out. 104 SymbolNameVector MissingSymbols; 105 MissingSymbols.push_back(Sym); 106 return Complete( 107 make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols))); 108 } 109 // FIXME: determine accurate JITSymbolFlags. 110 R.back().push_back( 111 {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported}); 112 } 113 } 114 115 Complete(std::move(R)); 116 } 117 118 Expected<int32_t> 119 SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr, 120 ArrayRef<std::string> Args) { 121 using MainTy = int (*)(int, char *[]); 122 return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args); 123 } 124 125 Expected<int32_t> 126 SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) { 127 using VoidTy = int (*)(); 128 return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>()); 129 } 130 131 Expected<int32_t> 132 SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) { 133 using IntTy = int (*)(int); 134 return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg); 135 } 136 137 void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr, 138 IncomingWFRHandler SendResult, 139 ArrayRef<char> ArgBuffer) { 140 using WrapperFnTy = 141 shared::CWrapperFunctionResult (*)(const char *Data, size_t Size); 142 auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>(); 143 SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size())); 144 } 145 146 Error SelfExecutorProcessControl::disconnect() { 147 D->shutdown(); 148 return Error::success(); 149 } 150 151 void InProcessMemoryAccess::writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws, 152 WriteResultFn OnWriteComplete) { 153 for (auto &W : Ws) 154 *W.Addr.toPtr<uint8_t *>() = W.Value; 155 OnWriteComplete(Error::success()); 156 } 157 158 void InProcessMemoryAccess::writeUInt16sAsync( 159 ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) { 160 for (auto &W : Ws) 161 *W.Addr.toPtr<uint16_t *>() = W.Value; 162 OnWriteComplete(Error::success()); 163 } 164 165 void InProcessMemoryAccess::writeUInt32sAsync( 166 ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) { 167 for (auto &W : Ws) 168 *W.Addr.toPtr<uint32_t *>() = W.Value; 169 OnWriteComplete(Error::success()); 170 } 171 172 void InProcessMemoryAccess::writeUInt64sAsync( 173 ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) { 174 for (auto &W : Ws) 175 *W.Addr.toPtr<uint64_t *>() = W.Value; 176 OnWriteComplete(Error::success()); 177 } 178 179 void InProcessMemoryAccess::writeBuffersAsync( 180 ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) { 181 for (auto &W : Ws) 182 memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size()); 183 OnWriteComplete(Error::success()); 184 } 185 186 void InProcessMemoryAccess::writePointersAsync( 187 ArrayRef<tpctypes::PointerWrite> Ws, WriteResultFn OnWriteComplete) { 188 if (IsArch64Bit) { 189 for (auto &W : Ws) 190 *W.Addr.toPtr<uint64_t *>() = W.Value.getValue(); 191 } else { 192 for (auto &W : Ws) 193 *W.Addr.toPtr<uint32_t *>() = static_cast<uint32_t>(W.Value.getValue()); 194 } 195 196 OnWriteComplete(Error::success()); 197 } 198 199 shared::CWrapperFunctionResult 200 SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager( 201 void *Ctx, const void *FnTag, const char *Data, size_t Size) { 202 203 LLVM_DEBUG({ 204 dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size 205 << " byte payload.\n"; 206 }); 207 208 std::promise<shared::WrapperFunctionResult> ResultP; 209 auto ResultF = ResultP.get_future(); 210 static_cast<SelfExecutorProcessControl *>(Ctx) 211 ->getExecutionSession() 212 .runJITDispatchHandler( 213 [ResultP = std::move(ResultP)]( 214 shared::WrapperFunctionResult Result) mutable { 215 ResultP.set_value(std::move(Result)); 216 }, 217 ExecutorAddr::fromPtr(FnTag), {Data, Size}); 218 219 return ResultF.get().release(); 220 } 221 222 } // end namespace orc 223 } // end namespace llvm 224