xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp (revision 39f64c4c83754b4e436d7fffa31bd70f11d7a657)
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