Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
35294 views
1
//===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
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/LazyReexports.h"
10
11
#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
12
#include "llvm/TargetParser/Triple.h"
13
14
#define DEBUG_TYPE "orc"
15
16
namespace llvm {
17
namespace orc {
18
19
LazyCallThroughManager::LazyCallThroughManager(ExecutionSession &ES,
20
ExecutorAddr ErrorHandlerAddr,
21
TrampolinePool *TP)
22
: ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(TP) {}
23
24
Expected<ExecutorAddr> LazyCallThroughManager::getCallThroughTrampoline(
25
JITDylib &SourceJD, SymbolStringPtr SymbolName,
26
NotifyResolvedFunction NotifyResolved) {
27
assert(TP && "TrampolinePool not set");
28
29
std::lock_guard<std::mutex> Lock(LCTMMutex);
30
auto Trampoline = TP->getTrampoline();
31
32
if (!Trampoline)
33
return Trampoline.takeError();
34
35
Reexports[*Trampoline] = ReexportsEntry{&SourceJD, std::move(SymbolName)};
36
Notifiers[*Trampoline] = std::move(NotifyResolved);
37
return *Trampoline;
38
}
39
40
ExecutorAddr LazyCallThroughManager::reportCallThroughError(Error Err) {
41
ES.reportError(std::move(Err));
42
return ErrorHandlerAddr;
43
}
44
45
Expected<LazyCallThroughManager::ReexportsEntry>
46
LazyCallThroughManager::findReexport(ExecutorAddr TrampolineAddr) {
47
std::lock_guard<std::mutex> Lock(LCTMMutex);
48
auto I = Reexports.find(TrampolineAddr);
49
if (I == Reexports.end())
50
return createStringError(inconvertibleErrorCode(),
51
"Missing reexport for trampoline address %p" +
52
formatv("{0:x}", TrampolineAddr));
53
return I->second;
54
}
55
56
Error LazyCallThroughManager::notifyResolved(ExecutorAddr TrampolineAddr,
57
ExecutorAddr ResolvedAddr) {
58
NotifyResolvedFunction NotifyResolved;
59
{
60
std::lock_guard<std::mutex> Lock(LCTMMutex);
61
auto I = Notifiers.find(TrampolineAddr);
62
if (I != Notifiers.end()) {
63
NotifyResolved = std::move(I->second);
64
Notifiers.erase(I);
65
}
66
}
67
68
return NotifyResolved ? NotifyResolved(ResolvedAddr) : Error::success();
69
}
70
71
void LazyCallThroughManager::resolveTrampolineLandingAddress(
72
ExecutorAddr TrampolineAddr,
73
NotifyLandingResolvedFunction NotifyLandingResolved) {
74
75
auto Entry = findReexport(TrampolineAddr);
76
if (!Entry)
77
return NotifyLandingResolved(reportCallThroughError(Entry.takeError()));
78
79
// Declaring SLS and the callback outside of the call to ES.lookup is a
80
// workaround to fix build failures on AIX and on z/OS platforms.
81
SymbolLookupSet SLS({Entry->SymbolName});
82
auto Callback = [this, TrampolineAddr, SymbolName = Entry->SymbolName,
83
NotifyLandingResolved = std::move(NotifyLandingResolved)](
84
Expected<SymbolMap> Result) mutable {
85
if (Result) {
86
assert(Result->size() == 1 && "Unexpected result size");
87
assert(Result->count(SymbolName) && "Unexpected result value");
88
ExecutorAddr LandingAddr = (*Result)[SymbolName].getAddress();
89
90
if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))
91
NotifyLandingResolved(reportCallThroughError(std::move(Err)));
92
else
93
NotifyLandingResolved(LandingAddr);
94
} else {
95
NotifyLandingResolved(reportCallThroughError(Result.takeError()));
96
}
97
};
98
99
ES.lookup(LookupKind::Static,
100
makeJITDylibSearchOrder(Entry->SourceJD,
101
JITDylibLookupFlags::MatchAllSymbols),
102
std::move(SLS), SymbolState::Ready, std::move(Callback),
103
NoDependenciesToRegister);
104
}
105
106
Expected<std::unique_ptr<LazyCallThroughManager>>
107
createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
108
ExecutorAddr ErrorHandlerAddr) {
109
switch (T.getArch()) {
110
default:
111
return make_error<StringError>(
112
std::string("No callback manager available for ") + T.str(),
113
inconvertibleErrorCode());
114
115
case Triple::aarch64:
116
case Triple::aarch64_32:
117
return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
118
ErrorHandlerAddr);
119
120
case Triple::x86:
121
return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
122
123
case Triple::loongarch64:
124
return LocalLazyCallThroughManager::Create<OrcLoongArch64>(
125
ES, ErrorHandlerAddr);
126
127
case Triple::mips:
128
return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
129
ErrorHandlerAddr);
130
131
case Triple::mipsel:
132
return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
133
ErrorHandlerAddr);
134
135
case Triple::mips64:
136
case Triple::mips64el:
137
return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
138
139
case Triple::riscv64:
140
return LocalLazyCallThroughManager::Create<OrcRiscv64>(ES,
141
ErrorHandlerAddr);
142
143
case Triple::x86_64:
144
if (T.getOS() == Triple::OSType::Win32)
145
return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
146
ES, ErrorHandlerAddr);
147
else
148
return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
149
ES, ErrorHandlerAddr);
150
}
151
}
152
153
LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
154
LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
155
JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)
156
: MaterializationUnit(extractFlags(CallableAliases)),
157
LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
158
CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}
159
160
StringRef LazyReexportsMaterializationUnit::getName() const {
161
return "<Lazy Reexports>";
162
}
163
164
void LazyReexportsMaterializationUnit::materialize(
165
std::unique_ptr<MaterializationResponsibility> R) {
166
auto RequestedSymbols = R->getRequestedSymbols();
167
168
SymbolAliasMap RequestedAliases;
169
for (auto &RequestedSymbol : RequestedSymbols) {
170
auto I = CallableAliases.find(RequestedSymbol);
171
assert(I != CallableAliases.end() && "Symbol not found in alias map?");
172
RequestedAliases[I->first] = std::move(I->second);
173
CallableAliases.erase(I);
174
}
175
176
if (!CallableAliases.empty())
177
if (auto Err = R->replace(lazyReexports(LCTManager, ISManager, SourceJD,
178
std::move(CallableAliases),
179
AliaseeTable))) {
180
R->getExecutionSession().reportError(std::move(Err));
181
R->failMaterialization();
182
return;
183
}
184
185
IndirectStubsManager::StubInitsMap StubInits;
186
for (auto &Alias : RequestedAliases) {
187
188
auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
189
SourceJD, Alias.second.Aliasee,
190
[&ISManager = this->ISManager,
191
StubSym = Alias.first](ExecutorAddr ResolvedAddr) -> Error {
192
return ISManager.updatePointer(*StubSym, ResolvedAddr);
193
});
194
195
if (!CallThroughTrampoline) {
196
SourceJD.getExecutionSession().reportError(
197
CallThroughTrampoline.takeError());
198
R->failMaterialization();
199
return;
200
}
201
202
StubInits[*Alias.first] =
203
std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
204
}
205
206
if (AliaseeTable != nullptr && !RequestedAliases.empty())
207
AliaseeTable->trackImpls(RequestedAliases, &SourceJD);
208
209
if (auto Err = ISManager.createStubs(StubInits)) {
210
SourceJD.getExecutionSession().reportError(std::move(Err));
211
R->failMaterialization();
212
return;
213
}
214
215
SymbolMap Stubs;
216
for (auto &Alias : RequestedAliases)
217
Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
218
219
// No registered dependencies, so these calls cannot fail.
220
cantFail(R->notifyResolved(Stubs));
221
cantFail(R->notifyEmitted({}));
222
}
223
224
void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
225
const SymbolStringPtr &Name) {
226
assert(CallableAliases.count(Name) &&
227
"Symbol not covered by this MaterializationUnit");
228
CallableAliases.erase(Name);
229
}
230
231
MaterializationUnit::Interface
232
LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
233
SymbolFlagsMap SymbolFlags;
234
for (auto &KV : Aliases) {
235
assert(KV.second.AliasFlags.isCallable() &&
236
"Lazy re-exports must be callable symbols");
237
SymbolFlags[KV.first] = KV.second.AliasFlags;
238
}
239
return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
240
}
241
242
} // End namespace orc.
243
} // End namespace llvm.
244
245