1 //===-- OrcRPCTPCServer.h -- OrcRPCTargetProcessControl Server --*- C++ -*-===//
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 // OrcRPCTargetProcessControl server class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
14 #define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
15
16 #include "llvm/ADT/BitmaskEnum.h"
17 #include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
18 #include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h"
19 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
20 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
21 #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
22 #include "llvm/Support/DynamicLibrary.h"
23 #include "llvm/Support/FormatVariadic.h"
24 #include "llvm/Support/Host.h"
25 #include "llvm/Support/MathExtras.h"
26 #include "llvm/Support/Memory.h"
27 #include "llvm/Support/Process.h"
28
29 #include <atomic>
30
31 namespace llvm {
32 namespace orc {
33
34 namespace orcrpctpc {
35
36 enum WireProtectionFlags : uint8_t {
37 WPF_None = 0,
38 WPF_Read = 1U << 0,
39 WPF_Write = 1U << 1,
40 WPF_Exec = 1U << 2,
41 LLVM_MARK_AS_BITMASK_ENUM(WPF_Exec)
42 };
43
44 struct ExecutorProcessInfo {
45 std::string Triple;
46 unsigned PageSize;
47 JITTargetAddress DispatchFuncAddr;
48 JITTargetAddress DispatchCtxAddr;
49 };
50
51 /// Convert from sys::Memory::ProtectionFlags
52 inline WireProtectionFlags
toWireProtectionFlags(sys::Memory::ProtectionFlags PF)53 toWireProtectionFlags(sys::Memory::ProtectionFlags PF) {
54 WireProtectionFlags WPF = WPF_None;
55 if (PF & sys::Memory::MF_READ)
56 WPF |= WPF_Read;
57 if (PF & sys::Memory::MF_WRITE)
58 WPF |= WPF_Write;
59 if (PF & sys::Memory::MF_EXEC)
60 WPF |= WPF_Exec;
61 return WPF;
62 }
63
64 inline sys::Memory::ProtectionFlags
fromWireProtectionFlags(WireProtectionFlags WPF)65 fromWireProtectionFlags(WireProtectionFlags WPF) {
66 int PF = 0;
67 if (WPF & WPF_Read)
68 PF |= sys::Memory::MF_READ;
69 if (WPF & WPF_Write)
70 PF |= sys::Memory::MF_WRITE;
71 if (WPF & WPF_Exec)
72 PF |= sys::Memory::MF_EXEC;
73 return static_cast<sys::Memory::ProtectionFlags>(PF);
74 }
75
76 struct ReserveMemRequestElement {
77 WireProtectionFlags Prot = WPF_None;
78 uint64_t Size = 0;
79 uint64_t Alignment = 0;
80 };
81
82 using ReserveMemRequest = std::vector<ReserveMemRequestElement>;
83
84 struct ReserveMemResultElement {
85 WireProtectionFlags Prot = WPF_None;
86 JITTargetAddress Address = 0;
87 uint64_t AllocatedSize = 0;
88 };
89
90 using ReserveMemResult = std::vector<ReserveMemResultElement>;
91
92 struct ReleaseOrFinalizeMemRequestElement {
93 WireProtectionFlags Prot = WPF_None;
94 JITTargetAddress Address = 0;
95 uint64_t Size = 0;
96 };
97
98 using ReleaseOrFinalizeMemRequest =
99 std::vector<ReleaseOrFinalizeMemRequestElement>;
100
101 } // end namespace orcrpctpc
102
103 namespace shared {
104
105 template <> class SerializationTypeName<WrapperFunctionResult> {
106 public:
getName()107 static const char *getName() { return "WrapperFunctionResult"; }
108 };
109
110 template <typename ChannelT>
111 class SerializationTraits<
112 ChannelT, WrapperFunctionResult, WrapperFunctionResult,
113 std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
114 public:
serialize(ChannelT & C,const WrapperFunctionResult & E)115 static Error serialize(ChannelT &C, const WrapperFunctionResult &E) {
116 if (auto Err = serializeSeq(C, static_cast<uint64_t>(E.size())))
117 return Err;
118 if (E.size() == 0)
119 return Error::success();
120 return C.appendBytes(E.data(), E.size());
121 }
122
deserialize(ChannelT & C,WrapperFunctionResult & E)123 static Error deserialize(ChannelT &C, WrapperFunctionResult &E) {
124 uint64_t Size;
125 if (auto Err = deserializeSeq(C, Size))
126 return Err;
127
128 WrapperFunctionResult Tmp;
129 char *Data = WrapperFunctionResult::allocate(Tmp, Size);
130
131 if (auto Err = C.readBytes(Data, Size))
132 return Err;
133
134 E = std::move(Tmp);
135
136 return Error::success();
137 }
138 };
139
140 template <> class SerializationTypeName<tpctypes::UInt8Write> {
141 public:
getName()142 static const char *getName() { return "UInt8Write"; }
143 };
144
145 template <> class SerializationTypeName<tpctypes::UInt16Write> {
146 public:
getName()147 static const char *getName() { return "UInt16Write"; }
148 };
149
150 template <> class SerializationTypeName<tpctypes::UInt32Write> {
151 public:
getName()152 static const char *getName() { return "UInt32Write"; }
153 };
154
155 template <> class SerializationTypeName<tpctypes::UInt64Write> {
156 public:
getName()157 static const char *getName() { return "UInt64Write"; }
158 };
159
160 template <> class SerializationTypeName<tpctypes::BufferWrite> {
161 public:
getName()162 static const char *getName() { return "BufferWrite"; }
163 };
164
165 template <> class SerializationTypeName<orcrpctpc::ReserveMemRequestElement> {
166 public:
getName()167 static const char *getName() { return "ReserveMemRequestElement"; }
168 };
169
170 template <> class SerializationTypeName<orcrpctpc::ReserveMemResultElement> {
171 public:
getName()172 static const char *getName() { return "ReserveMemResultElement"; }
173 };
174
175 template <>
176 class SerializationTypeName<orcrpctpc::ReleaseOrFinalizeMemRequestElement> {
177 public:
getName()178 static const char *getName() { return "ReleaseOrFinalizeMemRequestElement"; }
179 };
180
181 template <> class SerializationTypeName<orcrpctpc::ExecutorProcessInfo> {
182 public:
getName()183 static const char *getName() { return "ExecutorProcessInfo"; }
184 };
185
186 template <typename ChannelT, typename WriteT>
187 class SerializationTraits<
188 ChannelT, WriteT, WriteT,
189 std::enable_if_t<std::is_same<WriteT, tpctypes::UInt8Write>::value ||
190 std::is_same<WriteT, tpctypes::UInt16Write>::value ||
191 std::is_same<WriteT, tpctypes::UInt32Write>::value ||
192 std::is_same<WriteT, tpctypes::UInt64Write>::value>> {
193 public:
serialize(ChannelT & C,const WriteT & W)194 static Error serialize(ChannelT &C, const WriteT &W) {
195 return serializeSeq(C, W.Address, W.Value);
196 }
deserialize(ChannelT & C,WriteT & W)197 static Error deserialize(ChannelT &C, WriteT &W) {
198 return deserializeSeq(C, W.Address, W.Value);
199 }
200 };
201
202 template <typename ChannelT>
203 class SerializationTraits<
204 ChannelT, tpctypes::BufferWrite, tpctypes::BufferWrite,
205 std::enable_if_t<std::is_base_of<RawByteChannel, ChannelT>::value>> {
206 public:
serialize(ChannelT & C,const tpctypes::BufferWrite & W)207 static Error serialize(ChannelT &C, const tpctypes::BufferWrite &W) {
208 uint64_t Size = W.Buffer.size();
209 if (auto Err = serializeSeq(C, W.Address, Size))
210 return Err;
211
212 return C.appendBytes(W.Buffer.data(), Size);
213 }
deserialize(ChannelT & C,tpctypes::BufferWrite & W)214 static Error deserialize(ChannelT &C, tpctypes::BufferWrite &W) {
215 JITTargetAddress Address;
216 uint64_t Size;
217
218 if (auto Err = deserializeSeq(C, Address, Size))
219 return Err;
220
221 char *Buffer = jitTargetAddressToPointer<char *>(Address);
222
223 if (auto Err = C.readBytes(Buffer, Size))
224 return Err;
225
226 W = {Address, StringRef(Buffer, Size)};
227 return Error::success();
228 }
229 };
230
231 template <typename ChannelT>
232 class SerializationTraits<ChannelT, orcrpctpc::ReserveMemRequestElement> {
233 public:
serialize(ChannelT & C,const orcrpctpc::ReserveMemRequestElement & E)234 static Error serialize(ChannelT &C,
235 const orcrpctpc::ReserveMemRequestElement &E) {
236 return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Size, E.Alignment);
237 }
238
deserialize(ChannelT & C,orcrpctpc::ReserveMemRequestElement & E)239 static Error deserialize(ChannelT &C,
240 orcrpctpc::ReserveMemRequestElement &E) {
241 return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Size,
242 E.Alignment);
243 }
244 };
245
246 template <typename ChannelT>
247 class SerializationTraits<ChannelT, orcrpctpc::ReserveMemResultElement> {
248 public:
serialize(ChannelT & C,const orcrpctpc::ReserveMemResultElement & E)249 static Error serialize(ChannelT &C,
250 const orcrpctpc::ReserveMemResultElement &E) {
251 return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address,
252 E.AllocatedSize);
253 }
254
deserialize(ChannelT & C,orcrpctpc::ReserveMemResultElement & E)255 static Error deserialize(ChannelT &C, orcrpctpc::ReserveMemResultElement &E) {
256 return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Address,
257 E.AllocatedSize);
258 }
259 };
260
261 template <typename ChannelT>
262 class SerializationTraits<ChannelT,
263 orcrpctpc::ReleaseOrFinalizeMemRequestElement> {
264 public:
265 static Error
serialize(ChannelT & C,const orcrpctpc::ReleaseOrFinalizeMemRequestElement & E)266 serialize(ChannelT &C,
267 const orcrpctpc::ReleaseOrFinalizeMemRequestElement &E) {
268 return serializeSeq(C, static_cast<uint8_t>(E.Prot), E.Address, E.Size);
269 }
270
deserialize(ChannelT & C,orcrpctpc::ReleaseOrFinalizeMemRequestElement & E)271 static Error deserialize(ChannelT &C,
272 orcrpctpc::ReleaseOrFinalizeMemRequestElement &E) {
273 return deserializeSeq(C, *reinterpret_cast<uint8_t *>(&E.Prot), E.Address,
274 E.Size);
275 }
276 };
277
278 template <typename ChannelT>
279 class SerializationTraits<ChannelT, orcrpctpc::ExecutorProcessInfo> {
280 public:
serialize(ChannelT & C,const orcrpctpc::ExecutorProcessInfo & EPI)281 static Error serialize(ChannelT &C,
282 const orcrpctpc::ExecutorProcessInfo &EPI) {
283 return serializeSeq(C, EPI.Triple, EPI.PageSize, EPI.DispatchFuncAddr,
284 EPI.DispatchCtxAddr);
285 }
286
deserialize(ChannelT & C,orcrpctpc::ExecutorProcessInfo & EPI)287 static Error deserialize(ChannelT &C, orcrpctpc::ExecutorProcessInfo &EPI) {
288 return deserializeSeq(C, EPI.Triple, EPI.PageSize, EPI.DispatchFuncAddr,
289 EPI.DispatchCtxAddr);
290 }
291 };
292
293 } // end namespace shared
294
295 namespace orcrpctpc {
296
297 using RemoteSymbolLookupSet = std::vector<std::pair<std::string, bool>>;
298 using RemoteLookupRequest =
299 std::pair<tpctypes::DylibHandle, RemoteSymbolLookupSet>;
300
301 class GetExecutorProcessInfo
302 : public shared::RPCFunction<GetExecutorProcessInfo,
303 orcrpctpc::ExecutorProcessInfo()> {
304 public:
getName()305 static const char *getName() { return "GetJITDispatchInfo"; }
306 };
307
308 class ReserveMem
309 : public shared::RPCFunction<ReserveMem, Expected<ReserveMemResult>(
310 ReserveMemRequest)> {
311 public:
getName()312 static const char *getName() { return "ReserveMem"; }
313 };
314
315 class FinalizeMem
316 : public shared::RPCFunction<FinalizeMem,
317 Error(ReleaseOrFinalizeMemRequest)> {
318 public:
getName()319 static const char *getName() { return "FinalizeMem"; }
320 };
321
322 class ReleaseMem
323 : public shared::RPCFunction<ReleaseMem,
324 Error(ReleaseOrFinalizeMemRequest)> {
325 public:
getName()326 static const char *getName() { return "ReleaseMem"; }
327 };
328
329 class WriteUInt8s
330 : public shared::RPCFunction<WriteUInt8s,
331 Error(std::vector<tpctypes::UInt8Write>)> {
332 public:
getName()333 static const char *getName() { return "WriteUInt8s"; }
334 };
335
336 class WriteUInt16s
337 : public shared::RPCFunction<WriteUInt16s,
338 Error(std::vector<tpctypes::UInt16Write>)> {
339 public:
getName()340 static const char *getName() { return "WriteUInt16s"; }
341 };
342
343 class WriteUInt32s
344 : public shared::RPCFunction<WriteUInt32s,
345 Error(std::vector<tpctypes::UInt32Write>)> {
346 public:
getName()347 static const char *getName() { return "WriteUInt32s"; }
348 };
349
350 class WriteUInt64s
351 : public shared::RPCFunction<WriteUInt64s,
352 Error(std::vector<tpctypes::UInt64Write>)> {
353 public:
getName()354 static const char *getName() { return "WriteUInt64s"; }
355 };
356
357 class WriteBuffers
358 : public shared::RPCFunction<WriteBuffers,
359 Error(std::vector<tpctypes::BufferWrite>)> {
360 public:
getName()361 static const char *getName() { return "WriteBuffers"; }
362 };
363
364 class LoadDylib
365 : public shared::RPCFunction<LoadDylib, Expected<tpctypes::DylibHandle>(
366 std::string DylibPath)> {
367 public:
getName()368 static const char *getName() { return "LoadDylib"; }
369 };
370
371 class LookupSymbols
372 : public shared::RPCFunction<LookupSymbols,
373 Expected<std::vector<tpctypes::LookupResult>>(
374 std::vector<RemoteLookupRequest>)> {
375 public:
getName()376 static const char *getName() { return "LookupSymbols"; }
377 };
378
379 class RunMain
380 : public shared::RPCFunction<RunMain,
381 int64_t(JITTargetAddress MainAddr,
382 std::vector<std::string> Args)> {
383 public:
getName()384 static const char *getName() { return "RunMain"; }
385 };
386
387 class RunWrapper
388 : public shared::RPCFunction<RunWrapper,
389 shared::WrapperFunctionResult(
390 JITTargetAddress, std::vector<uint8_t>)> {
391 public:
getName()392 static const char *getName() { return "RunWrapper"; }
393 };
394
395 class CloseConnection : public shared::RPCFunction<CloseConnection, void()> {
396 public:
getName()397 static const char *getName() { return "CloseConnection"; }
398 };
399
400 } // end namespace orcrpctpc
401
402 /// TargetProcessControl for a process connected via an ORC RPC Endpoint.
403 template <typename RPCEndpointT> class OrcRPCTPCServer {
404 private:
405 using ThisT = OrcRPCTPCServer<RPCEndpointT>;
406
407 public:
408 /// Create an OrcRPCTPCServer from the given endpoint.
OrcRPCTPCServer(RPCEndpointT & EP)409 OrcRPCTPCServer(RPCEndpointT &EP) : EP(EP) {
410
411 TripleStr = sys::getProcessTriple();
412 PageSize = sys::Process::getPageSizeEstimate();
413
414 EP.template addHandler<orcrpctpc::GetExecutorProcessInfo>(
415 *this, &ThisT::getExecutorProcessInfo);
416 EP.template addHandler<orcrpctpc::ReserveMem>(*this, &ThisT::reserveMemory);
417 EP.template addHandler<orcrpctpc::FinalizeMem>(*this,
418 &ThisT::finalizeMemory);
419 EP.template addHandler<orcrpctpc::ReleaseMem>(*this, &ThisT::releaseMemory);
420
421 EP.template addHandler<orcrpctpc::WriteUInt8s>(
422 handleWriteUInt<tpctypes::UInt8Write>);
423 EP.template addHandler<orcrpctpc::WriteUInt16s>(
424 handleWriteUInt<tpctypes::UInt16Write>);
425 EP.template addHandler<orcrpctpc::WriteUInt32s>(
426 handleWriteUInt<tpctypes::UInt32Write>);
427 EP.template addHandler<orcrpctpc::WriteUInt64s>(
428 handleWriteUInt<tpctypes::UInt64Write>);
429 EP.template addHandler<orcrpctpc::WriteBuffers>(handleWriteBuffer);
430
431 EP.template addHandler<orcrpctpc::LoadDylib>(*this, &ThisT::loadDylib);
432 EP.template addHandler<orcrpctpc::LookupSymbols>(*this,
433 &ThisT::lookupSymbols);
434
435 EP.template addHandler<orcrpctpc::RunMain>(*this, &ThisT::runMain);
436 EP.template addHandler<orcrpctpc::RunWrapper>(*this, &ThisT::runWrapper);
437
438 EP.template addHandler<orcrpctpc::CloseConnection>(*this,
439 &ThisT::closeConnection);
440 }
441
442 /// Set the ProgramName to be used as the first argv element when running
443 /// functions via runAsMain.
444 void setProgramName(Optional<std::string> ProgramName = None) {
445 this->ProgramName = std::move(ProgramName);
446 }
447
448 /// Get the RPC endpoint for this server.
getEndpoint()449 RPCEndpointT &getEndpoint() { return EP; }
450
451 /// Run the server loop.
run()452 Error run() {
453 while (!Finished) {
454 if (auto Err = EP.handleOne())
455 return Err;
456 }
457 return Error::success();
458 }
459
460 Expected<shared::WrapperFunctionResult>
runWrapperInJIT(JITTargetAddress FunctionId,ArrayRef<char> ArgBuffer)461 runWrapperInJIT(JITTargetAddress FunctionId, ArrayRef<char> ArgBuffer) {
462 return EP.template callB<orcrpctpc::RunWrapper>(
463 FunctionId,
464 ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(ArgBuffer.data()),
465 ArgBuffer.size()));
466 }
467
468 private:
469 static shared::detail::CWrapperFunctionResult
jitDispatchViaOrcRPCTPCServer(void * Ctx,const void * FnTag,const char * Data,size_t Size)470 jitDispatchViaOrcRPCTPCServer(void *Ctx, const void *FnTag, const char *Data,
471 size_t Size) {
472 assert(Ctx && "Attempt to dispatch with null context ptr");
473 auto R = static_cast<ThisT *>(Ctx)->runWrapperInJIT(
474 pointerToJITTargetAddress(FnTag), {Data, Size});
475 if (!R) {
476 auto ErrMsg = toString(R.takeError());
477 return shared::WrapperFunctionResult::createOutOfBandError(ErrMsg.data())
478 .release();
479 }
480 return R->release();
481 }
482
getExecutorProcessInfo()483 orcrpctpc::ExecutorProcessInfo getExecutorProcessInfo() {
484 return {TripleStr, static_cast<uint32_t>(PageSize),
485 pointerToJITTargetAddress(jitDispatchViaOrcRPCTPCServer),
486 pointerToJITTargetAddress(this)};
487 }
488
489 template <typename WriteT>
handleWriteUInt(const std::vector<WriteT> & Ws)490 static void handleWriteUInt(const std::vector<WriteT> &Ws) {
491 using ValueT = decltype(std::declval<WriteT>().Value);
492 for (auto &W : Ws)
493 *jitTargetAddressToPointer<ValueT *>(W.Address) = W.Value;
494 }
495
getProtStr(orcrpctpc::WireProtectionFlags WPF)496 std::string getProtStr(orcrpctpc::WireProtectionFlags WPF) {
497 std::string Result;
498 Result += (WPF & orcrpctpc::WPF_Read) ? 'R' : '-';
499 Result += (WPF & orcrpctpc::WPF_Write) ? 'W' : '-';
500 Result += (WPF & orcrpctpc::WPF_Exec) ? 'X' : '-';
501 return Result;
502 }
503
handleWriteBuffer(const std::vector<tpctypes::BufferWrite> & Ws)504 static void handleWriteBuffer(const std::vector<tpctypes::BufferWrite> &Ws) {
505 for (auto &W : Ws) {
506 memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(),
507 W.Buffer.size());
508 }
509 }
510
511 Expected<orcrpctpc::ReserveMemResult>
reserveMemory(const orcrpctpc::ReserveMemRequest & Request)512 reserveMemory(const orcrpctpc::ReserveMemRequest &Request) {
513 orcrpctpc::ReserveMemResult Allocs;
514 auto PF = sys::Memory::MF_READ | sys::Memory::MF_WRITE;
515
516 uint64_t TotalSize = 0;
517
518 for (const auto &E : Request) {
519 uint64_t Size = alignTo(E.Size, PageSize);
520 uint16_t Align = E.Alignment;
521
522 if ((Align > PageSize) || (PageSize % Align))
523 return make_error<StringError>(
524 "Page alignmen does not satisfy requested alignment",
525 inconvertibleErrorCode());
526
527 TotalSize += Size;
528 }
529
530 // Allocate memory slab.
531 std::error_code EC;
532 auto MB = sys::Memory::allocateMappedMemory(TotalSize, nullptr, PF, EC);
533 if (EC)
534 return make_error<StringError>("Unable to allocate memory: " +
535 EC.message(),
536 inconvertibleErrorCode());
537
538 // Zero-fill the whole thing.
539 memset(MB.base(), 0, MB.allocatedSize());
540
541 // Carve up sections to return.
542 uint64_t SectionBase = 0;
543 for (const auto &E : Request) {
544 uint64_t SectionSize = alignTo(E.Size, PageSize);
545 Allocs.push_back({E.Prot,
546 pointerToJITTargetAddress(MB.base()) + SectionBase,
547 SectionSize});
548 SectionBase += SectionSize;
549 }
550
551 return Allocs;
552 }
553
finalizeMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest & FMR)554 Error finalizeMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &FMR) {
555 for (const auto &E : FMR) {
556 sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size);
557
558 auto PF = orcrpctpc::fromWireProtectionFlags(E.Prot);
559 if (auto EC =
560 sys::Memory::protectMappedMemory(MB, static_cast<unsigned>(PF)))
561 return make_error<StringError>("error protecting memory: " +
562 EC.message(),
563 inconvertibleErrorCode());
564 }
565 return Error::success();
566 }
567
releaseMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest & RMR)568 Error releaseMemory(const orcrpctpc::ReleaseOrFinalizeMemRequest &RMR) {
569 for (const auto &E : RMR) {
570 sys::MemoryBlock MB(jitTargetAddressToPointer<void *>(E.Address), E.Size);
571
572 if (auto EC = sys::Memory::releaseMappedMemory(MB))
573 return make_error<StringError>("error release memory: " + EC.message(),
574 inconvertibleErrorCode());
575 }
576 return Error::success();
577 }
578
loadDylib(const std::string & Path)579 Expected<tpctypes::DylibHandle> loadDylib(const std::string &Path) {
580 std::string ErrMsg;
581 const char *DLPath = !Path.empty() ? Path.c_str() : nullptr;
582 auto DL = sys::DynamicLibrary::getPermanentLibrary(DLPath, &ErrMsg);
583 if (!DL.isValid())
584 return make_error<StringError>(std::move(ErrMsg),
585 inconvertibleErrorCode());
586
587 tpctypes::DylibHandle H = Dylibs.size();
588 Dylibs[H] = std::move(DL);
589 return H;
590 }
591
592 Expected<std::vector<tpctypes::LookupResult>>
lookupSymbols(const std::vector<orcrpctpc::RemoteLookupRequest> & Request)593 lookupSymbols(const std::vector<orcrpctpc::RemoteLookupRequest> &Request) {
594 std::vector<tpctypes::LookupResult> Result;
595
596 for (const auto &E : Request) {
597 auto I = Dylibs.find(E.first);
598 if (I == Dylibs.end())
599 return make_error<StringError>("Unrecognized handle",
600 inconvertibleErrorCode());
601 auto &DL = I->second;
602 Result.push_back({});
603
604 for (const auto &KV : E.second) {
605 auto &SymString = KV.first;
606 bool WeakReference = KV.second;
607
608 const char *Sym = SymString.c_str();
609 #ifdef __APPLE__
610 if (*Sym == '_')
611 ++Sym;
612 #endif
613
614 void *Addr = DL.getAddressOfSymbol(Sym);
615 if (!Addr && !WeakReference)
616 return make_error<StringError>(Twine("Missing definition for ") + Sym,
617 inconvertibleErrorCode());
618
619 Result.back().push_back(pointerToJITTargetAddress(Addr));
620 }
621 }
622
623 return Result;
624 }
625
runMain(JITTargetAddress MainFnAddr,const std::vector<std::string> & Args)626 int64_t runMain(JITTargetAddress MainFnAddr,
627 const std::vector<std::string> &Args) {
628 Optional<StringRef> ProgramNameOverride;
629 if (ProgramName)
630 ProgramNameOverride = *ProgramName;
631
632 return runAsMain(
633 jitTargetAddressToFunction<int (*)(int, char *[])>(MainFnAddr), Args,
634 ProgramNameOverride);
635 }
636
637 shared::WrapperFunctionResult
runWrapper(JITTargetAddress WrapperFnAddr,const std::vector<uint8_t> & ArgBuffer)638 runWrapper(JITTargetAddress WrapperFnAddr,
639 const std::vector<uint8_t> &ArgBuffer) {
640 using WrapperFnTy = shared::detail::CWrapperFunctionResult (*)(
641 const char *Data, uint64_t Size);
642 auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr);
643 return WrapperFn(reinterpret_cast<const char *>(ArgBuffer.data()),
644 ArgBuffer.size());
645 }
646
closeConnection()647 void closeConnection() { Finished = true; }
648
649 std::string TripleStr;
650 uint64_t PageSize = 0;
651 Optional<std::string> ProgramName;
652 RPCEndpointT &EP;
653 std::atomic<bool> Finished{false};
654 DenseMap<tpctypes::DylibHandle, sys::DynamicLibrary> Dylibs;
655 };
656
657 } // end namespace orc
658 } // end namespace llvm
659
660 #endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_ORCRPCTPCSERVER_H
661