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/TargetProcess/TargetExecutionUtils.h" 13 #include "llvm/Support/FormatVariadic.h" 14 #include "llvm/Support/Host.h" 15 #include "llvm/Support/Process.h" 16 17 namespace llvm { 18 namespace orc { 19 20 ExecutorProcessControl::MemoryAccess::~MemoryAccess() {} 21 22 ExecutorProcessControl::~ExecutorProcessControl() {} 23 24 Error ExecutorProcessControl::associateJITSideWrapperFunctions( 25 JITDylib &JD, WrapperFunctionAssociationMap WFs) { 26 27 // Look up tag addresses. 28 auto &ES = JD.getExecutionSession(); 29 auto TagAddrs = 30 ES.lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}}, 31 SymbolLookupSet::fromMapKeys( 32 WFs, SymbolLookupFlags::WeaklyReferencedSymbol)); 33 if (!TagAddrs) 34 return TagAddrs.takeError(); 35 36 // Associate tag addresses with implementations. 37 std::lock_guard<std::mutex> Lock(TagToFuncMapMutex); 38 for (auto &KV : *TagAddrs) { 39 auto TagAddr = KV.second.getAddress(); 40 if (TagToFunc.count(TagAddr)) 41 return make_error<StringError>("Tag " + formatv("{0:x16}", TagAddr) + 42 " (for " + *KV.first + 43 ") already registered", 44 inconvertibleErrorCode()); 45 auto I = WFs.find(KV.first); 46 assert(I != WFs.end() && I->second && 47 "AsyncWrapperFunction implementation missing"); 48 TagToFunc[KV.second.getAddress()] = 49 std::make_shared<AsyncWrapperFunction>(std::move(I->second)); 50 } 51 return Error::success(); 52 } 53 54 void ExecutorProcessControl::runJITSideWrapperFunction( 55 SendResultFunction SendResult, JITTargetAddress TagAddr, 56 ArrayRef<char> ArgBuffer) { 57 58 std::shared_ptr<AsyncWrapperFunction> F; 59 { 60 std::lock_guard<std::mutex> Lock(TagToFuncMapMutex); 61 auto I = TagToFunc.find(TagAddr); 62 if (I != TagToFunc.end()) 63 F = I->second; 64 } 65 66 if (F) 67 (*F)(std::move(SendResult), ArgBuffer.data(), ArgBuffer.size()); 68 else 69 SendResult(shared::WrapperFunctionResult::createOutOfBandError( 70 ("No function registered for tag " + formatv("{0:x16}", TagAddr)) 71 .str())); 72 } 73 74 SelfExecutorProcessControl::SelfExecutorProcessControl( 75 std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple, 76 unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) 77 : ExecutorProcessControl(std::move(SSP)) { 78 79 OwnedMemMgr = std::move(MemMgr); 80 if (!OwnedMemMgr) 81 OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>(); 82 83 this->TargetTriple = std::move(TargetTriple); 84 this->PageSize = PageSize; 85 this->MemMgr = OwnedMemMgr.get(); 86 this->MemAccess = this; 87 if (this->TargetTriple.isOSBinFormatMachO()) 88 GlobalManglingPrefix = '_'; 89 } 90 91 Expected<std::unique_ptr<SelfExecutorProcessControl>> 92 SelfExecutorProcessControl::Create( 93 std::shared_ptr<SymbolStringPool> SSP, 94 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) { 95 auto PageSize = sys::Process::getPageSize(); 96 if (!PageSize) 97 return PageSize.takeError(); 98 99 Triple TT(sys::getProcessTriple()); 100 101 return std::make_unique<SelfExecutorProcessControl>( 102 std::move(SSP), std::move(TT), *PageSize, std::move(MemMgr)); 103 } 104 105 Expected<tpctypes::DylibHandle> 106 SelfExecutorProcessControl::loadDylib(const char *DylibPath) { 107 std::string ErrMsg; 108 auto Dylib = std::make_unique<sys::DynamicLibrary>( 109 sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg)); 110 if (!Dylib->isValid()) 111 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 112 DynamicLibraries.push_back(std::move(Dylib)); 113 return pointerToJITTargetAddress(DynamicLibraries.back().get()); 114 } 115 116 Expected<std::vector<tpctypes::LookupResult>> 117 SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) { 118 std::vector<tpctypes::LookupResult> R; 119 120 for (auto &Elem : Request) { 121 auto *Dylib = jitTargetAddressToPointer<sys::DynamicLibrary *>(Elem.Handle); 122 assert(llvm::any_of(DynamicLibraries, 123 [=](const std::unique_ptr<sys::DynamicLibrary> &DL) { 124 return DL.get() == Dylib; 125 }) && 126 "Invalid handle"); 127 128 R.push_back(std::vector<JITTargetAddress>()); 129 for (auto &KV : Elem.Symbols) { 130 auto &Sym = KV.first; 131 std::string Tmp((*Sym).data() + !!GlobalManglingPrefix, 132 (*Sym).size() - !!GlobalManglingPrefix); 133 void *Addr = Dylib->getAddressOfSymbol(Tmp.c_str()); 134 if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) { 135 // FIXME: Collect all failing symbols before erroring out. 136 SymbolNameVector MissingSymbols; 137 MissingSymbols.push_back(Sym); 138 return make_error<SymbolsNotFound>(std::move(MissingSymbols)); 139 } 140 R.back().push_back(pointerToJITTargetAddress(Addr)); 141 } 142 } 143 144 return R; 145 } 146 147 Expected<int32_t> 148 SelfExecutorProcessControl::runAsMain(JITTargetAddress MainFnAddr, 149 ArrayRef<std::string> Args) { 150 using MainTy = int (*)(int, char *[]); 151 return orc::runAsMain(jitTargetAddressToFunction<MainTy>(MainFnAddr), Args); 152 } 153 154 void SelfExecutorProcessControl::runWrapperAsync(SendResultFunction SendResult, 155 JITTargetAddress WrapperFnAddr, 156 ArrayRef<char> ArgBuffer) { 157 using WrapperFnTy = 158 shared::detail::CWrapperFunctionResult (*)(const char *Data, size_t Size); 159 auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr); 160 SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size())); 161 } 162 163 Error SelfExecutorProcessControl::disconnect() { return Error::success(); } 164 165 void SelfExecutorProcessControl::writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws, 166 WriteResultFn OnWriteComplete) { 167 for (auto &W : Ws) 168 *jitTargetAddressToPointer<uint8_t *>(W.Address) = W.Value; 169 OnWriteComplete(Error::success()); 170 } 171 172 void SelfExecutorProcessControl::writeUInt16s( 173 ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) { 174 for (auto &W : Ws) 175 *jitTargetAddressToPointer<uint16_t *>(W.Address) = W.Value; 176 OnWriteComplete(Error::success()); 177 } 178 179 void SelfExecutorProcessControl::writeUInt32s( 180 ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) { 181 for (auto &W : Ws) 182 *jitTargetAddressToPointer<uint32_t *>(W.Address) = W.Value; 183 OnWriteComplete(Error::success()); 184 } 185 186 void SelfExecutorProcessControl::writeUInt64s( 187 ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) { 188 for (auto &W : Ws) 189 *jitTargetAddressToPointer<uint64_t *>(W.Address) = W.Value; 190 OnWriteComplete(Error::success()); 191 } 192 193 void SelfExecutorProcessControl::writeBuffers( 194 ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) { 195 for (auto &W : Ws) 196 memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(), 197 W.Buffer.size()); 198 OnWriteComplete(Error::success()); 199 } 200 201 } // end namespace orc 202 } // end namespace llvm 203