LLVM 19.0.0git
ExecutorProcessControl.cpp
Go to the documentation of this file.
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
10
18
19#define DEBUG_TYPE "orc"
20
21namespace llvm {
22namespace orc {
23
25
27
29 std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
30 Triple TargetTriple, unsigned PageSize,
31 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
33 InProcessMemoryAccess(TargetTriple.isArch64Bit()) {
34
35 OwnedMemMgr = std::move(MemMgr);
36 if (!OwnedMemMgr)
37 OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>(
39
40 this->TargetTriple = std::move(TargetTriple);
41 this->PageSize = PageSize;
42 this->MemMgr = OwnedMemMgr.get();
43 this->MemAccess = this;
44 this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager),
46 if (this->TargetTriple.isOSBinFormatMachO())
47 GlobalManglingPrefix = '_';
48
53}
54
57 std::shared_ptr<SymbolStringPool> SSP,
58 std::unique_ptr<TaskDispatcher> D,
59 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
60
61 if (!SSP)
62 SSP = std::make_shared<SymbolStringPool>();
63
64 if (!D) {
65#if LLVM_ENABLE_THREADS
66 D = std::make_unique<DynamicThreadPoolTaskDispatcher>();
67#else
68 D = std::make_unique<InPlaceTaskDispatcher>();
69#endif
70 }
71
73 if (!PageSize)
74 return PageSize.takeError();
75
77
78 return std::make_unique<SelfExecutorProcessControl>(
79 std::move(SSP), std::move(D), std::move(TT), *PageSize,
80 std::move(MemMgr));
81}
82
85 std::string ErrMsg;
86 auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg);
87 if (!Dylib.isValid())
88 return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
89 return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle());
90}
91
95 std::vector<tpctypes::LookupResult> R;
96
97 for (auto &Elem : Request) {
98 sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>());
99 R.push_back(std::vector<ExecutorSymbolDef>());
100 for (auto &KV : Elem.Symbols) {
101 auto &Sym = KV.first;
102 std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
103 (*Sym).size() - !!GlobalManglingPrefix);
104 void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str());
105 if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
106 // FIXME: Collect all failing symbols before erroring out.
107 SymbolNameVector MissingSymbols;
108 MissingSymbols.push_back(Sym);
109 return Complete(
110 make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)));
111 }
112 // FIXME: determine accurate JITSymbolFlags.
113 R.back().push_back(
115 }
116 }
117
118 Complete(std::move(R));
119}
120
124 using MainTy = int (*)(int, char *[]);
125 return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args);
126}
127
130 using VoidTy = int (*)();
131 return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>());
132}
133
136 using IntTy = int (*)(int);
137 return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg);
138}
139
141 IncomingWFRHandler SendResult,
142 ArrayRef<char> ArgBuffer) {
143 using WrapperFnTy =
144 shared::CWrapperFunctionResult (*)(const char *Data, size_t Size);
145 auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>();
146 SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size()));
147}
148
150 D->shutdown();
151 return Error::success();
152}
153
155 WriteResultFn OnWriteComplete) {
156 for (auto &W : Ws)
157 *W.Addr.toPtr<uint8_t *>() = W.Value;
158 OnWriteComplete(Error::success());
159}
160
163 for (auto &W : Ws)
164 *W.Addr.toPtr<uint16_t *>() = W.Value;
165 OnWriteComplete(Error::success());
166}
167
170 for (auto &W : Ws)
171 *W.Addr.toPtr<uint32_t *>() = W.Value;
172 OnWriteComplete(Error::success());
173}
174
177 for (auto &W : Ws)
178 *W.Addr.toPtr<uint64_t *>() = W.Value;
179 OnWriteComplete(Error::success());
180}
181
184 for (auto &W : Ws)
185 memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size());
186 OnWriteComplete(Error::success());
187}
188
191 if (IsArch64Bit) {
192 for (auto &W : Ws)
193 *W.Addr.toPtr<uint64_t *>() = W.Value.getValue();
194 } else {
195 for (auto &W : Ws)
196 *W.Addr.toPtr<uint32_t *>() = static_cast<uint32_t>(W.Value.getValue());
197 }
198
199 OnWriteComplete(Error::success());
200}
201
203SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
204 void *Ctx, const void *FnTag, const char *Data, size_t Size) {
205
206 LLVM_DEBUG({
207 dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size
208 << " byte payload.\n";
209 });
210
211 std::promise<shared::WrapperFunctionResult> ResultP;
212 auto ResultF = ResultP.get_future();
213 static_cast<SelfExecutorProcessControl *>(Ctx)
216 [ResultP = std::move(ResultP)](
217 shared::WrapperFunctionResult Result) mutable {
218 ResultP.set_value(std::move(Result));
219 },
220 ExecutorAddr::fromPtr(FnTag), {Data, Size});
221
222 return ResultF.get().release();
223}
224
225} // end namespace orc
226} // end namespace llvm
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Addr
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:479
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
Provides a library for accessing information about this process and other processes on the operating ...
llvm::orc::shared::CWrapperFunctionResult llvm_orc_deregisterEHFrameSectionWrapper(const char *Data, uint64_t Size)
llvm::orc::shared::CWrapperFunctionResult llvm_orc_registerEHFrameSectionWrapper(const char *Data, uint64_t Size)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
const T * data() const
Definition: ArrayRef.h:162
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
Tagged union holding either a T or a Error.
Definition: Error.h:474
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition: Triple.h:727
void runJITDispatchHandler(SendResultFunction SendResult, ExecutorAddr HandlerFnTagAddr, ArrayRef< char > ArgBuffer)
Run a registered jit-side wrapper function.
Definition: Core.cpp:1944
Represents an address in the executor process.
static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap=UnwrapFn())
Create an ExecutorAddr from the given pointer.
std::enable_if_t< std::is_pointer< T >::value, T > toPtr(WrapFn &&Wrap=WrapFn()) const
Cast this ExecutorAddr to a pointer of the given type.
A handler or incoming WrapperFunctionResults – either return values from callWrapper* calls,...
ExecutorProcessControl supports interaction with a JIT target process.
std::unique_ptr< TaskDispatcher > D
std::shared_ptr< SymbolStringPool > SSP
StringMap< ExecutorAddr > BootstrapSymbols
jitlink::JITLinkMemoryManager * MemMgr
ExecutionSession & getExecutionSession()
Return the ExecutionSession associated with this instance.
void writePointersAsync(ArrayRef< tpctypes::PointerWrite > Ws, WriteResultFn OnWriteComplete) override
void writeUInt32sAsync(ArrayRef< tpctypes::UInt32Write > Ws, WriteResultFn OnWriteComplete) override
void writeUInt8sAsync(ArrayRef< tpctypes::UInt8Write > Ws, WriteResultFn OnWriteComplete) override
void writeUInt16sAsync(ArrayRef< tpctypes::UInt16Write > Ws, WriteResultFn OnWriteComplete) override
void writeBuffersAsync(ArrayRef< tpctypes::BufferWrite > Ws, WriteResultFn OnWriteComplete) override
void writeUInt64sAsync(ArrayRef< tpctypes::UInt64Write > Ws, WriteResultFn OnWriteComplete) override
SelfExecutorProcessControl(std::shared_ptr< SymbolStringPool > SSP, std::unique_ptr< TaskDispatcher > D, Triple TargetTriple, unsigned PageSize, std::unique_ptr< jitlink::JITLinkMemoryManager > MemMgr)
Expected< tpctypes::DylibHandle > loadDylib(const char *DylibPath) override
Load the dynamic library at the given path and return a handle to it.
void lookupSymbolsAsync(ArrayRef< LookupRequest > Request, SymbolLookupCompleteFn F) override
Search for symbols in the target process.
Error disconnect() override
Disconnect from the target process.
Expected< int32_t > runAsVoidFunction(ExecutorAddr VoidFnAddr) override
Run function with a int (*)(void) signature.
Expected< int32_t > runAsMain(ExecutorAddr MainFnAddr, ArrayRef< std::string > Args) override
Run function with a main-like signature.
void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef< char > ArgBuffer) override
Run a wrapper function in the executor.
static Expected< std::unique_ptr< SelfExecutorProcessControl > > Create(std::shared_ptr< SymbolStringPool > SSP=nullptr, std::unique_ptr< TaskDispatcher > D=nullptr, std::unique_ptr< jitlink::JITLinkMemoryManager > MemMgr=nullptr)
Create a SelfExecutorProcessControl with the given symbol string pool and memory manager.
Expected< int32_t > runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override
Run function with a int (*)(int) signature.
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
static DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path using the library load operatio...
void * getAddressOfSymbol(const char *symbolName)
Searches through the library for the symbol symbolName.
static Expected< unsigned > getPageSize()
Get the process's page size.
static unsigned getPageSizeEstimate()
Get the process's estimated page size.
Definition: Process.h:61
unique_function is a type-erasing functor similar to std::function.
const char * DeregisterEHFrameSectionWrapperName
Definition: OrcRTBridge.cpp:55
const char * RegisterEHFrameSectionWrapperName
Definition: OrcRTBridge.cpp:53
int runAsVoidFunction(int(*Func)(void))
int runAsIntFunction(int(*Func)(int), int Arg)
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
Definition: Core.h:117
int runAsMain(int(*Main)(int, char *[]), ArrayRef< std::string > Args, std::optional< StringRef > ProgramName=std::nullopt)
Run a main function, returning the result.
std::string getProcessTriple()
getProcessTriple() - Return an appropriate target triple for generating code to be loaded into the cu...
Definition: Host.cpp:2037
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:90
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1849
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858