1//===------- EPCGenericDylibManager.cpp -- Dylib management via EPC -------===//
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/EPCGenericDylibManager.h"
10
11#include "llvm/ExecutionEngine/Orc/Core.h"
12#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
13#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
14
15namespace llvm {
16namespace orc {
17namespace shared {
18
19template <>
20class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement,
21 SymbolLookupSet::value_type> {
22public:
23 static size_t size(const SymbolLookupSet::value_type &V) {
24 return SPSArgList<SPSString, bool>::size(
25 Arg: *V.first, Args: V.second == SymbolLookupFlags::RequiredSymbol);
26 }
27
28 static bool serialize(SPSOutputBuffer &OB,
29 const SymbolLookupSet::value_type &V) {
30 return SPSArgList<SPSString, bool>::serialize(
31 OB, Arg: *V.first, Args: V.second == SymbolLookupFlags::RequiredSymbol);
32 }
33};
34
35template <>
36class TrivialSPSSequenceSerialization<SPSRemoteSymbolLookupSetElement,
37 SymbolLookupSet> {
38public:
39 static constexpr bool available = true;
40};
41
42template <>
43class SPSSerializationTraits<SPSRemoteSymbolLookup,
44 DylibManager::LookupRequest> {
45 using MemberSerialization =
46 SPSArgList<SPSExecutorAddr, SPSRemoteSymbolLookupSet>;
47
48public:
49 static size_t size(const DylibManager::LookupRequest &LR) {
50 return MemberSerialization::size(Arg: ExecutorAddr(LR.Handle), Args: LR.Symbols);
51 }
52
53 static bool serialize(SPSOutputBuffer &OB,
54 const DylibManager::LookupRequest &LR) {
55 return MemberSerialization::serialize(OB, Arg: ExecutorAddr(LR.Handle),
56 Args: LR.Symbols);
57 }
58};
59
60} // end namespace shared
61
62Expected<EPCGenericDylibManager>
63EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(
64 ExecutorProcessControl &EPC) {
65 SymbolAddrs SAs;
66 if (auto Err = EPC.getBootstrapSymbols(
67 Pairs: {{SAs.Instance, rt::SimpleExecutorDylibManagerInstanceName},
68 {SAs.Open, rt::SimpleExecutorDylibManagerOpenWrapperName},
69 {SAs.Resolve, rt::SimpleExecutorDylibManagerResolveWrapperName}}))
70 return std::move(Err);
71 return EPCGenericDylibManager(EPC, std::move(SAs));
72}
73
74Expected<tpctypes::DylibHandle> EPCGenericDylibManager::open(StringRef Path,
75 uint64_t Mode) {
76 Expected<tpctypes::DylibHandle> H((ExecutorAddr()));
77 if (auto Err =
78 EPC.callSPSWrapper<rt::SPSSimpleExecutorDylibManagerOpenSignature>(
79 WrapperFnAddr: SAs.Open, WrapperCallArgs&: H, WrapperCallArgs&: SAs.Instance, WrapperCallArgs&: Path, WrapperCallArgs&: Mode))
80 return std::move(Err);
81 return H;
82}
83
84void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
85 const SymbolLookupSet &Lookup,
86 SymbolLookupCompleteFn Complete) {
87 EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerResolveSignature>(
88 WrapperFnAddr: SAs.Resolve,
89 SendResult: [Complete = std::move(Complete)](
90 Error SerializationErr,
91 Expected<std::vector<std::optional<ExecutorSymbolDef>>>
92 Result) mutable {
93 if (SerializationErr) {
94 cantFail(Err: Result.takeError());
95 Complete(std::move(SerializationErr));
96 return;
97 }
98 Complete(std::move(Result));
99 },
100 Args: H, Args: Lookup);
101}
102
103void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
104 const RemoteSymbolLookupSet &Lookup,
105 SymbolLookupCompleteFn Complete) {
106 EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerResolveSignature>(
107 WrapperFnAddr: SAs.Resolve,
108 SendResult: [Complete = std::move(Complete)](
109 Error SerializationErr,
110 Expected<std::vector<std::optional<ExecutorSymbolDef>>>
111 Result) mutable {
112 if (SerializationErr) {
113 cantFail(Err: Result.takeError());
114 Complete(std::move(SerializationErr));
115 return;
116 }
117 Complete(std::move(Result));
118 },
119 Args: H, Args: Lookup);
120}
121
122Expected<tpctypes::DylibHandle>
123EPCGenericDylibManager::loadDylib(const char *DylibPath) {
124 return open(Path: DylibPath, Mode: 0);
125}
126
127/// Async helper to chain together calls to lookupAsync to fulfill all
128/// the requests.
129/// FIXME: The dylib manager should support multiple LookupRequests natively.
130static void
131lookupSymbolsAsyncHelper(EPCGenericDylibManager &DylibMgr,
132 ArrayRef<DylibManager::LookupRequest> Request,
133 std::vector<tpctypes::LookupResult> Result,
134 DylibManager::SymbolLookupCompleteFn Complete) {
135 if (Request.empty())
136 return Complete(std::move(Result));
137
138 auto &Element = Request.front();
139 DylibMgr.lookupAsync(H: Element.Handle, Lookup: Element.Symbols,
140 Complete: [&DylibMgr, Request, Complete = std::move(Complete),
141 Result = std::move(Result)](auto R) mutable {
142 if (!R)
143 return Complete(R.takeError());
144 Result.push_back(x: {});
145 Result.back().reserve(n: R->size());
146 llvm::append_range(Result.back(), *R);
147
148 lookupSymbolsAsyncHelper(
149 DylibMgr, Request: Request.drop_front(), Result: std::move(Result),
150 Complete: std::move(Complete));
151 });
152}
153
154void EPCGenericDylibManager::lookupSymbolsAsync(
155 ArrayRef<DylibManager::LookupRequest> Request,
156 DylibManager::SymbolLookupCompleteFn Complete) {
157 lookupSymbolsAsyncHelper(DylibMgr&: *this, Request, Result: {}, Complete: std::move(Complete));
158}
159
160} // end namespace orc
161} // end namespace llvm
162