1662c5544SLang Hames //===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===// 2662c5544SLang Hames // 3662c5544SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4662c5544SLang Hames // See https://llvm.org/LICENSE.txt for license information. 5662c5544SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6662c5544SLang Hames // 7662c5544SLang Hames //===----------------------------------------------------------------------===// 8662c5544SLang Hames 9662c5544SLang Hames #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" 10662c5544SLang Hames 11662c5544SLang Hames #include "llvm/ExecutionEngine/Orc/Core.h" 12662c5544SLang Hames #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h" 13*39f64c4cSLang Hames #include "llvm/Support/FormatVariadic.h" 14662c5544SLang Hames #include "llvm/Support/Host.h" 15662c5544SLang Hames #include "llvm/Support/Process.h" 16662c5544SLang Hames 17662c5544SLang Hames namespace llvm { 18662c5544SLang Hames namespace orc { 19662c5544SLang Hames 20662c5544SLang Hames ExecutorProcessControl::MemoryAccess::~MemoryAccess() {} 21662c5544SLang Hames 22662c5544SLang Hames ExecutorProcessControl::~ExecutorProcessControl() {} 23662c5544SLang Hames 24*39f64c4cSLang Hames Error ExecutorProcessControl::associateJITSideWrapperFunctions( 25*39f64c4cSLang Hames JITDylib &JD, WrapperFunctionAssociationMap WFs) { 26*39f64c4cSLang Hames 27*39f64c4cSLang Hames // Look up tag addresses. 28*39f64c4cSLang Hames auto &ES = JD.getExecutionSession(); 29*39f64c4cSLang Hames auto TagAddrs = 30*39f64c4cSLang Hames ES.lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}}, 31*39f64c4cSLang Hames SymbolLookupSet::fromMapKeys( 32*39f64c4cSLang Hames WFs, SymbolLookupFlags::WeaklyReferencedSymbol)); 33*39f64c4cSLang Hames if (!TagAddrs) 34*39f64c4cSLang Hames return TagAddrs.takeError(); 35*39f64c4cSLang Hames 36*39f64c4cSLang Hames // Associate tag addresses with implementations. 37*39f64c4cSLang Hames std::lock_guard<std::mutex> Lock(TagToFuncMapMutex); 38*39f64c4cSLang Hames for (auto &KV : *TagAddrs) { 39*39f64c4cSLang Hames auto TagAddr = KV.second.getAddress(); 40*39f64c4cSLang Hames if (TagToFunc.count(TagAddr)) 41*39f64c4cSLang Hames return make_error<StringError>("Tag " + formatv("{0:x16}", TagAddr) + 42*39f64c4cSLang Hames " (for " + *KV.first + 43*39f64c4cSLang Hames ") already registered", 44*39f64c4cSLang Hames inconvertibleErrorCode()); 45*39f64c4cSLang Hames auto I = WFs.find(KV.first); 46*39f64c4cSLang Hames assert(I != WFs.end() && I->second && 47*39f64c4cSLang Hames "AsyncWrapperFunction implementation missing"); 48*39f64c4cSLang Hames TagToFunc[KV.second.getAddress()] = 49*39f64c4cSLang Hames std::make_shared<AsyncWrapperFunction>(std::move(I->second)); 50*39f64c4cSLang Hames } 51*39f64c4cSLang Hames return Error::success(); 52*39f64c4cSLang Hames } 53*39f64c4cSLang Hames 54*39f64c4cSLang Hames void ExecutorProcessControl::runJITSideWrapperFunction( 55*39f64c4cSLang Hames SendResultFunction SendResult, JITTargetAddress TagAddr, 56*39f64c4cSLang Hames ArrayRef<char> ArgBuffer) { 57*39f64c4cSLang Hames 58*39f64c4cSLang Hames std::shared_ptr<AsyncWrapperFunction> F; 59*39f64c4cSLang Hames { 60*39f64c4cSLang Hames std::lock_guard<std::mutex> Lock(TagToFuncMapMutex); 61*39f64c4cSLang Hames auto I = TagToFunc.find(TagAddr); 62*39f64c4cSLang Hames if (I != TagToFunc.end()) 63*39f64c4cSLang Hames F = I->second; 64*39f64c4cSLang Hames } 65*39f64c4cSLang Hames 66*39f64c4cSLang Hames if (F) 67*39f64c4cSLang Hames (*F)(std::move(SendResult), ArgBuffer.data(), ArgBuffer.size()); 68*39f64c4cSLang Hames else 69*39f64c4cSLang Hames SendResult(shared::WrapperFunctionResult::createOutOfBandError( 70*39f64c4cSLang Hames ("No function registered for tag " + formatv("{0:x16}", TagAddr)) 71*39f64c4cSLang Hames .str())); 72*39f64c4cSLang Hames } 73*39f64c4cSLang Hames 74662c5544SLang Hames SelfExecutorProcessControl::SelfExecutorProcessControl( 75662c5544SLang Hames std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple, 76662c5544SLang Hames unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) 77662c5544SLang Hames : ExecutorProcessControl(std::move(SSP)) { 78662c5544SLang Hames 79662c5544SLang Hames OwnedMemMgr = std::move(MemMgr); 80662c5544SLang Hames if (!OwnedMemMgr) 81662c5544SLang Hames OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>(); 82662c5544SLang Hames 83662c5544SLang Hames this->TargetTriple = std::move(TargetTriple); 84662c5544SLang Hames this->PageSize = PageSize; 85662c5544SLang Hames this->MemMgr = OwnedMemMgr.get(); 86662c5544SLang Hames this->MemAccess = this; 87662c5544SLang Hames if (this->TargetTriple.isOSBinFormatMachO()) 88662c5544SLang Hames GlobalManglingPrefix = '_'; 89662c5544SLang Hames } 90662c5544SLang Hames 91662c5544SLang Hames Expected<std::unique_ptr<SelfExecutorProcessControl>> 92662c5544SLang Hames SelfExecutorProcessControl::Create( 93662c5544SLang Hames std::shared_ptr<SymbolStringPool> SSP, 94662c5544SLang Hames std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) { 95662c5544SLang Hames auto PageSize = sys::Process::getPageSize(); 96662c5544SLang Hames if (!PageSize) 97662c5544SLang Hames return PageSize.takeError(); 98662c5544SLang Hames 99662c5544SLang Hames Triple TT(sys::getProcessTriple()); 100662c5544SLang Hames 101662c5544SLang Hames return std::make_unique<SelfExecutorProcessControl>( 102662c5544SLang Hames std::move(SSP), std::move(TT), *PageSize, std::move(MemMgr)); 103662c5544SLang Hames } 104662c5544SLang Hames 105662c5544SLang Hames Expected<tpctypes::DylibHandle> 106662c5544SLang Hames SelfExecutorProcessControl::loadDylib(const char *DylibPath) { 107662c5544SLang Hames std::string ErrMsg; 108662c5544SLang Hames auto Dylib = std::make_unique<sys::DynamicLibrary>( 109662c5544SLang Hames sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg)); 110662c5544SLang Hames if (!Dylib->isValid()) 111662c5544SLang Hames return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 112662c5544SLang Hames DynamicLibraries.push_back(std::move(Dylib)); 113662c5544SLang Hames return pointerToJITTargetAddress(DynamicLibraries.back().get()); 114662c5544SLang Hames } 115662c5544SLang Hames 116662c5544SLang Hames Expected<std::vector<tpctypes::LookupResult>> 117662c5544SLang Hames SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) { 118662c5544SLang Hames std::vector<tpctypes::LookupResult> R; 119662c5544SLang Hames 120662c5544SLang Hames for (auto &Elem : Request) { 121662c5544SLang Hames auto *Dylib = jitTargetAddressToPointer<sys::DynamicLibrary *>(Elem.Handle); 122662c5544SLang Hames assert(llvm::any_of(DynamicLibraries, 123662c5544SLang Hames [=](const std::unique_ptr<sys::DynamicLibrary> &DL) { 124662c5544SLang Hames return DL.get() == Dylib; 125662c5544SLang Hames }) && 126662c5544SLang Hames "Invalid handle"); 127662c5544SLang Hames 128662c5544SLang Hames R.push_back(std::vector<JITTargetAddress>()); 129662c5544SLang Hames for (auto &KV : Elem.Symbols) { 130662c5544SLang Hames auto &Sym = KV.first; 131662c5544SLang Hames std::string Tmp((*Sym).data() + !!GlobalManglingPrefix, 132662c5544SLang Hames (*Sym).size() - !!GlobalManglingPrefix); 133662c5544SLang Hames void *Addr = Dylib->getAddressOfSymbol(Tmp.c_str()); 134662c5544SLang Hames if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) { 135662c5544SLang Hames // FIXME: Collect all failing symbols before erroring out. 136662c5544SLang Hames SymbolNameVector MissingSymbols; 137662c5544SLang Hames MissingSymbols.push_back(Sym); 138662c5544SLang Hames return make_error<SymbolsNotFound>(std::move(MissingSymbols)); 139662c5544SLang Hames } 140662c5544SLang Hames R.back().push_back(pointerToJITTargetAddress(Addr)); 141662c5544SLang Hames } 142662c5544SLang Hames } 143662c5544SLang Hames 144662c5544SLang Hames return R; 145662c5544SLang Hames } 146662c5544SLang Hames 147662c5544SLang Hames Expected<int32_t> 148662c5544SLang Hames SelfExecutorProcessControl::runAsMain(JITTargetAddress MainFnAddr, 149662c5544SLang Hames ArrayRef<std::string> Args) { 150662c5544SLang Hames using MainTy = int (*)(int, char *[]); 151662c5544SLang Hames return orc::runAsMain(jitTargetAddressToFunction<MainTy>(MainFnAddr), Args); 152662c5544SLang Hames } 153662c5544SLang Hames 154*39f64c4cSLang Hames void SelfExecutorProcessControl::runWrapperAsync(SendResultFunction SendResult, 155*39f64c4cSLang Hames JITTargetAddress WrapperFnAddr, 156662c5544SLang Hames ArrayRef<char> ArgBuffer) { 157*39f64c4cSLang Hames using WrapperFnTy = 158*39f64c4cSLang Hames shared::detail::CWrapperFunctionResult (*)(const char *Data, size_t Size); 159662c5544SLang Hames auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr); 160*39f64c4cSLang Hames SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size())); 161662c5544SLang Hames } 162662c5544SLang Hames 163662c5544SLang Hames Error SelfExecutorProcessControl::disconnect() { return Error::success(); } 164662c5544SLang Hames 165662c5544SLang Hames void SelfExecutorProcessControl::writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws, 166662c5544SLang Hames WriteResultFn OnWriteComplete) { 167662c5544SLang Hames for (auto &W : Ws) 168662c5544SLang Hames *jitTargetAddressToPointer<uint8_t *>(W.Address) = W.Value; 169662c5544SLang Hames OnWriteComplete(Error::success()); 170662c5544SLang Hames } 171662c5544SLang Hames 172662c5544SLang Hames void SelfExecutorProcessControl::writeUInt16s( 173662c5544SLang Hames ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) { 174662c5544SLang Hames for (auto &W : Ws) 175662c5544SLang Hames *jitTargetAddressToPointer<uint16_t *>(W.Address) = W.Value; 176662c5544SLang Hames OnWriteComplete(Error::success()); 177662c5544SLang Hames } 178662c5544SLang Hames 179662c5544SLang Hames void SelfExecutorProcessControl::writeUInt32s( 180662c5544SLang Hames ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) { 181662c5544SLang Hames for (auto &W : Ws) 182662c5544SLang Hames *jitTargetAddressToPointer<uint32_t *>(W.Address) = W.Value; 183662c5544SLang Hames OnWriteComplete(Error::success()); 184662c5544SLang Hames } 185662c5544SLang Hames 186662c5544SLang Hames void SelfExecutorProcessControl::writeUInt64s( 187662c5544SLang Hames ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) { 188662c5544SLang Hames for (auto &W : Ws) 189662c5544SLang Hames *jitTargetAddressToPointer<uint64_t *>(W.Address) = W.Value; 190662c5544SLang Hames OnWriteComplete(Error::success()); 191662c5544SLang Hames } 192662c5544SLang Hames 193662c5544SLang Hames void SelfExecutorProcessControl::writeBuffers( 194662c5544SLang Hames ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) { 195662c5544SLang Hames for (auto &W : Ws) 196662c5544SLang Hames memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(), 197662c5544SLang Hames W.Buffer.size()); 198662c5544SLang Hames OnWriteComplete(Error::success()); 199662c5544SLang Hames } 200662c5544SLang Hames 201662c5544SLang Hames } // end namespace orc 202662c5544SLang Hames } // end namespace llvm 203