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/RTDyldObjectLinkingLayer.cpp
35266 views
1
//===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===//
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/RTDyldObjectLinkingLayer.h"
10
#include "llvm/Object/COFF.h"
11
12
namespace {
13
14
using namespace llvm;
15
using namespace llvm::orc;
16
17
class JITDylibSearchOrderResolver : public JITSymbolResolver {
18
public:
19
JITDylibSearchOrderResolver(MaterializationResponsibility &MR,
20
SymbolDependenceMap &Deps)
21
: MR(MR), Deps(Deps) {}
22
23
void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override {
24
auto &ES = MR.getTargetJITDylib().getExecutionSession();
25
SymbolLookupSet InternedSymbols;
26
27
// Intern the requested symbols: lookup takes interned strings.
28
for (auto &S : Symbols)
29
InternedSymbols.add(ES.intern(S));
30
31
// Build an OnResolve callback to unwrap the interned strings and pass them
32
// to the OnResolved callback.
33
auto OnResolvedWithUnwrap =
34
[OnResolved = std::move(OnResolved)](
35
Expected<SymbolMap> InternedResult) mutable {
36
if (!InternedResult) {
37
OnResolved(InternedResult.takeError());
38
return;
39
}
40
41
LookupResult Result;
42
for (auto &KV : *InternedResult)
43
Result[*KV.first] = {KV.second.getAddress().getValue(),
44
KV.second.getFlags()};
45
OnResolved(Result);
46
};
47
48
JITDylibSearchOrder LinkOrder;
49
MR.getTargetJITDylib().withLinkOrderDo(
50
[&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
51
ES.lookup(
52
LookupKind::Static, LinkOrder, InternedSymbols, SymbolState::Resolved,
53
std::move(OnResolvedWithUnwrap),
54
[this](const SymbolDependenceMap &LookupDeps) { Deps = LookupDeps; });
55
}
56
57
Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override {
58
LookupSet Result;
59
60
for (auto &KV : MR.getSymbols()) {
61
if (Symbols.count(*KV.first))
62
Result.insert(*KV.first);
63
}
64
65
return Result;
66
}
67
68
private:
69
MaterializationResponsibility &MR;
70
SymbolDependenceMap &Deps;
71
};
72
73
} // end anonymous namespace
74
75
namespace llvm {
76
namespace orc {
77
78
char RTDyldObjectLinkingLayer::ID;
79
80
using BaseT = RTTIExtends<RTDyldObjectLinkingLayer, ObjectLayer>;
81
82
RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(
83
ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
84
: BaseT(ES), GetMemoryManager(std::move(GetMemoryManager)) {
85
ES.registerResourceManager(*this);
86
}
87
88
RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer() {
89
assert(MemMgrs.empty() && "Layer destroyed with resources still attached");
90
}
91
92
void RTDyldObjectLinkingLayer::emit(
93
std::unique_ptr<MaterializationResponsibility> R,
94
std::unique_ptr<MemoryBuffer> O) {
95
assert(O && "Object must not be null");
96
97
auto &ES = getExecutionSession();
98
99
auto Obj = object::ObjectFile::createObjectFile(*O);
100
101
if (!Obj) {
102
getExecutionSession().reportError(Obj.takeError());
103
R->failMaterialization();
104
return;
105
}
106
107
// Collect the internal symbols from the object file: We will need to
108
// filter these later.
109
auto InternalSymbols = std::make_shared<std::set<StringRef>>();
110
{
111
SymbolFlagsMap ExtraSymbolsToClaim;
112
for (auto &Sym : (*Obj)->symbols()) {
113
114
// Skip file symbols.
115
if (auto SymType = Sym.getType()) {
116
if (*SymType == object::SymbolRef::ST_File)
117
continue;
118
} else {
119
ES.reportError(SymType.takeError());
120
R->failMaterialization();
121
return;
122
}
123
124
Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
125
if (!SymFlagsOrErr) {
126
// TODO: Test this error.
127
ES.reportError(SymFlagsOrErr.takeError());
128
R->failMaterialization();
129
return;
130
}
131
132
// Try to claim responsibility of weak symbols
133
// if AutoClaimObjectSymbols flag is set.
134
if (AutoClaimObjectSymbols &&
135
(*SymFlagsOrErr & object::BasicSymbolRef::SF_Weak)) {
136
auto SymName = Sym.getName();
137
if (!SymName) {
138
ES.reportError(SymName.takeError());
139
R->failMaterialization();
140
return;
141
}
142
143
// Already included in responsibility set, skip it
144
SymbolStringPtr SymbolName = ES.intern(*SymName);
145
if (R->getSymbols().count(SymbolName))
146
continue;
147
148
auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
149
if (!SymFlags) {
150
ES.reportError(SymFlags.takeError());
151
R->failMaterialization();
152
return;
153
}
154
155
ExtraSymbolsToClaim[SymbolName] = *SymFlags;
156
continue;
157
}
158
159
// Don't include symbols that aren't global.
160
if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) {
161
if (auto SymName = Sym.getName())
162
InternalSymbols->insert(*SymName);
163
else {
164
ES.reportError(SymName.takeError());
165
R->failMaterialization();
166
return;
167
}
168
}
169
}
170
171
if (!ExtraSymbolsToClaim.empty()) {
172
if (auto Err = R->defineMaterializing(ExtraSymbolsToClaim)) {
173
ES.reportError(std::move(Err));
174
R->failMaterialization();
175
}
176
}
177
}
178
179
auto MemMgr = GetMemoryManager();
180
auto &MemMgrRef = *MemMgr;
181
182
// Switch to shared ownership of MR so that it can be captured by both
183
// lambdas below.
184
std::shared_ptr<MaterializationResponsibility> SharedR(std::move(R));
185
auto Deps = std::make_unique<SymbolDependenceMap>();
186
187
JITDylibSearchOrderResolver Resolver(*SharedR, *Deps);
188
189
jitLinkForORC(
190
object::OwningBinary<object::ObjectFile>(std::move(*Obj), std::move(O)),
191
MemMgrRef, Resolver, ProcessAllSections,
192
[this, SharedR, &MemMgrRef, InternalSymbols](
193
const object::ObjectFile &Obj,
194
RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
195
std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {
196
return onObjLoad(*SharedR, Obj, MemMgrRef, LoadedObjInfo,
197
ResolvedSymbols, *InternalSymbols);
198
},
199
[this, SharedR, MemMgr = std::move(MemMgr), Deps = std::move(Deps)](
200
object::OwningBinary<object::ObjectFile> Obj,
201
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
202
Error Err) mutable {
203
onObjEmit(*SharedR, std::move(Obj), std::move(MemMgr),
204
std::move(LoadedObjInfo), std::move(Deps), std::move(Err));
205
});
206
}
207
208
void RTDyldObjectLinkingLayer::registerJITEventListener(JITEventListener &L) {
209
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
210
assert(!llvm::is_contained(EventListeners, &L) &&
211
"Listener has already been registered");
212
EventListeners.push_back(&L);
213
}
214
215
void RTDyldObjectLinkingLayer::unregisterJITEventListener(JITEventListener &L) {
216
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
217
auto I = llvm::find(EventListeners, &L);
218
assert(I != EventListeners.end() && "Listener not registered");
219
EventListeners.erase(I);
220
}
221
222
Error RTDyldObjectLinkingLayer::onObjLoad(
223
MaterializationResponsibility &R, const object::ObjectFile &Obj,
224
RuntimeDyld::MemoryManager &MemMgr,
225
RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
226
std::map<StringRef, JITEvaluatedSymbol> Resolved,
227
std::set<StringRef> &InternalSymbols) {
228
SymbolFlagsMap ExtraSymbolsToClaim;
229
SymbolMap Symbols;
230
231
// Hack to support COFF constant pool comdats introduced during compilation:
232
// (See http://llvm.org/PR40074)
233
if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(&Obj)) {
234
auto &ES = getExecutionSession();
235
236
// For all resolved symbols that are not already in the responsibility set:
237
// check whether the symbol is in a comdat section and if so mark it as
238
// weak.
239
for (auto &Sym : COFFObj->symbols()) {
240
// getFlags() on COFF symbols can't fail.
241
uint32_t SymFlags = cantFail(Sym.getFlags());
242
if (SymFlags & object::BasicSymbolRef::SF_Undefined)
243
continue;
244
auto Name = Sym.getName();
245
if (!Name)
246
return Name.takeError();
247
auto I = Resolved.find(*Name);
248
249
// Skip unresolved symbols, internal symbols, and symbols that are
250
// already in the responsibility set.
251
if (I == Resolved.end() || InternalSymbols.count(*Name) ||
252
R.getSymbols().count(ES.intern(*Name)))
253
continue;
254
auto Sec = Sym.getSection();
255
if (!Sec)
256
return Sec.takeError();
257
if (*Sec == COFFObj->section_end())
258
continue;
259
auto &COFFSec = *COFFObj->getCOFFSection(**Sec);
260
if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)
261
I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak);
262
}
263
264
// Handle any aliases.
265
for (auto &Sym : COFFObj->symbols()) {
266
uint32_t SymFlags = cantFail(Sym.getFlags());
267
if (SymFlags & object::BasicSymbolRef::SF_Undefined)
268
continue;
269
auto Name = Sym.getName();
270
if (!Name)
271
return Name.takeError();
272
auto I = Resolved.find(*Name);
273
274
// Skip already-resolved symbols, and symbols that we're not responsible
275
// for.
276
if (I != Resolved.end() || !R.getSymbols().count(ES.intern(*Name)))
277
continue;
278
279
// Skip anything other than weak externals.
280
auto COFFSym = COFFObj->getCOFFSymbol(Sym);
281
if (!COFFSym.isWeakExternal())
282
continue;
283
auto *WeakExternal = COFFSym.getAux<object::coff_aux_weak_external>();
284
if (WeakExternal->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS)
285
continue;
286
287
// We found an alias. Reuse the resolution of the alias target for the
288
// alias itself.
289
Expected<object::COFFSymbolRef> TargetSymbol =
290
COFFObj->getSymbol(WeakExternal->TagIndex);
291
if (!TargetSymbol)
292
return TargetSymbol.takeError();
293
Expected<StringRef> TargetName = COFFObj->getSymbolName(*TargetSymbol);
294
if (!TargetName)
295
return TargetName.takeError();
296
auto J = Resolved.find(*TargetName);
297
if (J == Resolved.end())
298
return make_error<StringError>("Could alias target " + *TargetName +
299
" not resolved",
300
inconvertibleErrorCode());
301
Resolved[*Name] = J->second;
302
}
303
}
304
305
for (auto &KV : Resolved) {
306
// Scan the symbols and add them to the Symbols map for resolution.
307
308
// We never claim internal symbols.
309
if (InternalSymbols.count(KV.first))
310
continue;
311
312
auto InternedName = getExecutionSession().intern(KV.first);
313
auto Flags = KV.second.getFlags();
314
auto I = R.getSymbols().find(InternedName);
315
if (I != R.getSymbols().end()) {
316
// Override object flags and claim responsibility for symbols if
317
// requested.
318
if (OverrideObjectFlags)
319
Flags = I->second;
320
else {
321
// RuntimeDyld/MCJIT's weak tracking isn't compatible with ORC's. Even
322
// if we're not overriding flags in general we should set the weak flag
323
// according to the MaterializationResponsibility object symbol table.
324
if (I->second.isWeak())
325
Flags |= JITSymbolFlags::Weak;
326
}
327
} else if (AutoClaimObjectSymbols)
328
ExtraSymbolsToClaim[InternedName] = Flags;
329
330
Symbols[InternedName] = {ExecutorAddr(KV.second.getAddress()), Flags};
331
}
332
333
if (!ExtraSymbolsToClaim.empty()) {
334
if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))
335
return Err;
336
337
// If we claimed responsibility for any weak symbols but were rejected then
338
// we need to remove them from the resolved set.
339
for (auto &KV : ExtraSymbolsToClaim)
340
if (KV.second.isWeak() && !R.getSymbols().count(KV.first))
341
Symbols.erase(KV.first);
342
}
343
344
if (auto Err = R.notifyResolved(Symbols)) {
345
R.failMaterialization();
346
return Err;
347
}
348
349
if (NotifyLoaded)
350
NotifyLoaded(R, Obj, LoadedObjInfo);
351
352
return Error::success();
353
}
354
355
void RTDyldObjectLinkingLayer::onObjEmit(
356
MaterializationResponsibility &R,
357
object::OwningBinary<object::ObjectFile> O,
358
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
359
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
360
std::unique_ptr<SymbolDependenceMap> Deps, Error Err) {
361
if (Err) {
362
getExecutionSession().reportError(std::move(Err));
363
R.failMaterialization();
364
return;
365
}
366
367
SymbolDependenceGroup SDG;
368
for (auto &[Sym, Flags] : R.getSymbols())
369
SDG.Symbols.insert(Sym);
370
SDG.Dependencies = std::move(*Deps);
371
372
if (auto Err = R.notifyEmitted(SDG)) {
373
getExecutionSession().reportError(std::move(Err));
374
R.failMaterialization();
375
return;
376
}
377
378
std::unique_ptr<object::ObjectFile> Obj;
379
std::unique_ptr<MemoryBuffer> ObjBuffer;
380
std::tie(Obj, ObjBuffer) = O.takeBinary();
381
382
// Run EventListener notifyLoaded callbacks.
383
{
384
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
385
for (auto *L : EventListeners)
386
L->notifyObjectLoaded(pointerToJITTargetAddress(MemMgr.get()), *Obj,
387
*LoadedObjInfo);
388
}
389
390
if (NotifyEmitted)
391
NotifyEmitted(R, std::move(ObjBuffer));
392
393
if (auto Err = R.withResourceKeyDo(
394
[&](ResourceKey K) { MemMgrs[K].push_back(std::move(MemMgr)); })) {
395
getExecutionSession().reportError(std::move(Err));
396
R.failMaterialization();
397
}
398
}
399
400
Error RTDyldObjectLinkingLayer::handleRemoveResources(JITDylib &JD,
401
ResourceKey K) {
402
403
std::vector<MemoryManagerUP> MemMgrsToRemove;
404
405
getExecutionSession().runSessionLocked([&] {
406
auto I = MemMgrs.find(K);
407
if (I != MemMgrs.end()) {
408
std::swap(MemMgrsToRemove, I->second);
409
MemMgrs.erase(I);
410
}
411
});
412
413
{
414
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
415
for (auto &MemMgr : MemMgrsToRemove) {
416
for (auto *L : EventListeners)
417
L->notifyFreeingObject(pointerToJITTargetAddress(MemMgr.get()));
418
MemMgr->deregisterEHFrames();
419
}
420
}
421
422
return Error::success();
423
}
424
425
void RTDyldObjectLinkingLayer::handleTransferResources(JITDylib &JD,
426
ResourceKey DstKey,
427
ResourceKey SrcKey) {
428
auto I = MemMgrs.find(SrcKey);
429
if (I != MemMgrs.end()) {
430
auto &SrcMemMgrs = I->second;
431
auto &DstMemMgrs = MemMgrs[DstKey];
432
DstMemMgrs.reserve(DstMemMgrs.size() + SrcMemMgrs.size());
433
for (auto &MemMgr : SrcMemMgrs)
434
DstMemMgrs.push_back(std::move(MemMgr));
435
436
// Erase SrcKey entry using value rather than iterator I: I may have been
437
// invalidated when we looked up DstKey.
438
MemMgrs.erase(SrcKey);
439
}
440
}
441
442
} // End namespace orc.
443
} // End namespace llvm.
444
445