1 //===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===//
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
7 //===----------------------------------------------------------------------===//
11 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
12 #include "llvm/Object/COFF.h"
17 using namespace llvm::orc
;
19 class JITDylibSearchOrderResolver
: public JITSymbolResolver
{
21 JITDylibSearchOrderResolver(MaterializationResponsibility
&MR
,
22 SymbolDependenceMap
&Deps
)
23 : MR(MR
), Deps(Deps
) {}
25 void lookup(const LookupSet
&Symbols
, OnResolvedFunction OnResolved
) override
{
26 auto &ES
= MR
.getTargetJITDylib().getExecutionSession();
27 SymbolLookupSet InternedSymbols
;
29 // Intern the requested symbols: lookup takes interned strings.
30 for (auto &S
: Symbols
)
31 InternedSymbols
.add(ES
.intern(S
));
33 // Build an OnResolve callback to unwrap the interned strings and pass them
34 // to the OnResolved callback.
35 auto OnResolvedWithUnwrap
=
36 [OnResolved
= std::move(OnResolved
)](
37 Expected
<SymbolMap
> InternedResult
) mutable {
38 if (!InternedResult
) {
39 OnResolved(InternedResult
.takeError());
44 for (auto &KV
: *InternedResult
)
45 Result
[*KV
.first
] = {KV
.second
.getAddress().getValue(),
46 KV
.second
.getFlags()};
50 JITDylibSearchOrder LinkOrder
;
51 MR
.getTargetJITDylib().withLinkOrderDo(
52 [&](const JITDylibSearchOrder
&LO
) { LinkOrder
= LO
; });
54 LookupKind::Static
, LinkOrder
, InternedSymbols
, SymbolState::Resolved
,
55 std::move(OnResolvedWithUnwrap
),
56 [this](const SymbolDependenceMap
&LookupDeps
) { Deps
= LookupDeps
; });
59 Expected
<LookupSet
> getResponsibilitySet(const LookupSet
&Symbols
) override
{
62 for (auto &KV
: MR
.getSymbols()) {
63 if (Symbols
.count(*KV
.first
))
64 Result
.insert(*KV
.first
);
71 MaterializationResponsibility
&MR
;
72 SymbolDependenceMap
&Deps
;
75 } // end anonymous namespace
80 char RTDyldObjectLinkingLayer::ID
;
82 using BaseT
= RTTIExtends
<RTDyldObjectLinkingLayer
, ObjectLayer
>;
84 RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(
85 ExecutionSession
&ES
, GetMemoryManagerFunction GetMemoryManager
)
86 : BaseT(ES
), GetMemoryManager(std::move(GetMemoryManager
)) {
87 ES
.registerResourceManager(*this);
90 RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer() {
91 assert(MemMgrs
.empty() && "Layer destroyed with resources still attached");
94 void RTDyldObjectLinkingLayer::emit(
95 std::unique_ptr
<MaterializationResponsibility
> R
,
96 std::unique_ptr
<MemoryBuffer
> O
) {
97 assert(O
&& "Object must not be null");
99 auto &ES
= getExecutionSession();
101 auto Obj
= object::ObjectFile::createObjectFile(*O
);
104 getExecutionSession().reportError(Obj
.takeError());
105 R
->failMaterialization();
109 // Collect the internal symbols from the object file: We will need to
110 // filter these later.
111 auto InternalSymbols
= std::make_shared
<std::set
<StringRef
>>();
113 SymbolFlagsMap ExtraSymbolsToClaim
;
114 for (auto &Sym
: (*Obj
)->symbols()) {
116 // Skip file symbols.
117 if (auto SymType
= Sym
.getType()) {
118 if (*SymType
== object::SymbolRef::ST_File
)
121 ES
.reportError(SymType
.takeError());
122 R
->failMaterialization();
126 Expected
<uint32_t> SymFlagsOrErr
= Sym
.getFlags();
127 if (!SymFlagsOrErr
) {
128 // TODO: Test this error.
129 ES
.reportError(SymFlagsOrErr
.takeError());
130 R
->failMaterialization();
134 // Try to claim responsibility of weak symbols
135 // if AutoClaimObjectSymbols flag is set.
136 if (AutoClaimObjectSymbols
&&
137 (*SymFlagsOrErr
& object::BasicSymbolRef::SF_Weak
)) {
138 auto SymName
= Sym
.getName();
140 ES
.reportError(SymName
.takeError());
141 R
->failMaterialization();
145 // Already included in responsibility set, skip it
146 SymbolStringPtr SymbolName
= ES
.intern(*SymName
);
147 if (R
->getSymbols().count(SymbolName
))
150 auto SymFlags
= JITSymbolFlags::fromObjectSymbol(Sym
);
152 ES
.reportError(SymFlags
.takeError());
153 R
->failMaterialization();
157 ExtraSymbolsToClaim
[SymbolName
] = *SymFlags
;
161 // Don't include symbols that aren't global.
162 if (!(*SymFlagsOrErr
& object::BasicSymbolRef::SF_Global
)) {
163 if (auto SymName
= Sym
.getName())
164 InternalSymbols
->insert(*SymName
);
166 ES
.reportError(SymName
.takeError());
167 R
->failMaterialization();
173 if (!ExtraSymbolsToClaim
.empty()) {
174 if (auto Err
= R
->defineMaterializing(ExtraSymbolsToClaim
)) {
175 ES
.reportError(std::move(Err
));
176 R
->failMaterialization();
181 auto MemMgr
= GetMemoryManager();
182 auto &MemMgrRef
= *MemMgr
;
184 // Switch to shared ownership of MR so that it can be captured by both
186 std::shared_ptr
<MaterializationResponsibility
> SharedR(std::move(R
));
187 auto Deps
= std::make_unique
<SymbolDependenceMap
>();
190 std::make_unique
<JITDylibSearchOrderResolver
>(*SharedR
, *Deps
);
191 auto *ResolverPtr
= Resolver
.get();
194 object::OwningBinary
<object::ObjectFile
>(std::move(*Obj
), std::move(O
)),
195 MemMgrRef
, *ResolverPtr
, ProcessAllSections
,
196 [this, SharedR
, &MemMgrRef
, InternalSymbols
](
197 const object::ObjectFile
&Obj
,
198 RuntimeDyld::LoadedObjectInfo
&LoadedObjInfo
,
199 std::map
<StringRef
, JITEvaluatedSymbol
> ResolvedSymbols
) {
200 return onObjLoad(*SharedR
, Obj
, MemMgrRef
, LoadedObjInfo
,
201 ResolvedSymbols
, *InternalSymbols
);
203 [this, SharedR
, MemMgr
= std::move(MemMgr
), Deps
= std::move(Deps
),
204 Resolver
= std::move(Resolver
)](
205 object::OwningBinary
<object::ObjectFile
> Obj
,
206 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> LoadedObjInfo
,
208 onObjEmit(*SharedR
, std::move(Obj
), std::move(MemMgr
),
209 std::move(LoadedObjInfo
), std::move(Deps
), std::move(Err
));
213 void RTDyldObjectLinkingLayer::registerJITEventListener(JITEventListener
&L
) {
214 std::lock_guard
<std::mutex
> Lock(RTDyldLayerMutex
);
215 assert(!llvm::is_contained(EventListeners
, &L
) &&
216 "Listener has already been registered");
217 EventListeners
.push_back(&L
);
220 void RTDyldObjectLinkingLayer::unregisterJITEventListener(JITEventListener
&L
) {
221 std::lock_guard
<std::mutex
> Lock(RTDyldLayerMutex
);
222 auto I
= llvm::find(EventListeners
, &L
);
223 assert(I
!= EventListeners
.end() && "Listener not registered");
224 EventListeners
.erase(I
);
227 Error
RTDyldObjectLinkingLayer::onObjLoad(
228 MaterializationResponsibility
&R
, const object::ObjectFile
&Obj
,
229 RuntimeDyld::MemoryManager
&MemMgr
,
230 RuntimeDyld::LoadedObjectInfo
&LoadedObjInfo
,
231 std::map
<StringRef
, JITEvaluatedSymbol
> Resolved
,
232 std::set
<StringRef
> &InternalSymbols
) {
233 SymbolFlagsMap ExtraSymbolsToClaim
;
236 // Hack to support COFF constant pool comdats introduced during compilation:
237 // (See http://llvm.org/PR40074)
238 if (auto *COFFObj
= dyn_cast
<object::COFFObjectFile
>(&Obj
)) {
239 auto &ES
= getExecutionSession();
241 // For all resolved symbols that are not already in the responsibility set:
242 // check whether the symbol is in a comdat section and if so mark it as
244 for (auto &Sym
: COFFObj
->symbols()) {
245 // getFlags() on COFF symbols can't fail.
246 uint32_t SymFlags
= cantFail(Sym
.getFlags());
247 if (SymFlags
& object::BasicSymbolRef::SF_Undefined
)
249 auto Name
= Sym
.getName();
251 return Name
.takeError();
252 auto I
= Resolved
.find(*Name
);
254 // Skip unresolved symbols, internal symbols, and symbols that are
255 // already in the responsibility set.
256 if (I
== Resolved
.end() || InternalSymbols
.count(*Name
) ||
257 R
.getSymbols().count(ES
.intern(*Name
)))
259 auto Sec
= Sym
.getSection();
261 return Sec
.takeError();
262 if (*Sec
== COFFObj
->section_end())
264 auto &COFFSec
= *COFFObj
->getCOFFSection(**Sec
);
265 if (COFFSec
.Characteristics
& COFF::IMAGE_SCN_LNK_COMDAT
)
266 I
->second
.setFlags(I
->second
.getFlags() | JITSymbolFlags::Weak
);
269 // Handle any aliases.
270 for (auto &Sym
: COFFObj
->symbols()) {
271 uint32_t SymFlags
= cantFail(Sym
.getFlags());
272 if (SymFlags
& object::BasicSymbolRef::SF_Undefined
)
274 auto Name
= Sym
.getName();
276 return Name
.takeError();
277 auto I
= Resolved
.find(*Name
);
279 // Skip already-resolved symbols, and symbols that we're not responsible
281 if (I
!= Resolved
.end() || !R
.getSymbols().count(ES
.intern(*Name
)))
284 // Skip anything other than weak externals.
285 auto COFFSym
= COFFObj
->getCOFFSymbol(Sym
);
286 if (!COFFSym
.isWeakExternal())
288 auto *WeakExternal
= COFFSym
.getAux
<object::coff_aux_weak_external
>();
289 if (WeakExternal
->Characteristics
!= COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS
)
292 // We found an alias. Reuse the resolution of the alias target for the
294 Expected
<object::COFFSymbolRef
> TargetSymbol
=
295 COFFObj
->getSymbol(WeakExternal
->TagIndex
);
297 return TargetSymbol
.takeError();
298 Expected
<StringRef
> TargetName
= COFFObj
->getSymbolName(*TargetSymbol
);
300 return TargetName
.takeError();
301 auto J
= Resolved
.find(*TargetName
);
302 if (J
== Resolved
.end())
303 return make_error
<StringError
>("Could alias target " + *TargetName
+
305 inconvertibleErrorCode());
306 Resolved
[*Name
] = J
->second
;
310 for (auto &KV
: Resolved
) {
311 // Scan the symbols and add them to the Symbols map for resolution.
313 // We never claim internal symbols.
314 if (InternalSymbols
.count(KV
.first
))
317 auto InternedName
= getExecutionSession().intern(KV
.first
);
318 auto Flags
= KV
.second
.getFlags();
319 auto I
= R
.getSymbols().find(InternedName
);
320 if (I
!= R
.getSymbols().end()) {
321 // Override object flags and claim responsibility for symbols if
323 if (OverrideObjectFlags
)
326 // RuntimeDyld/MCJIT's weak tracking isn't compatible with ORC's. Even
327 // if we're not overriding flags in general we should set the weak flag
328 // according to the MaterializationResponsibility object symbol table.
329 if (I
->second
.isWeak())
330 Flags
|= JITSymbolFlags::Weak
;
332 } else if (AutoClaimObjectSymbols
)
333 ExtraSymbolsToClaim
[InternedName
] = Flags
;
335 Symbols
[InternedName
] = {ExecutorAddr(KV
.second
.getAddress()), Flags
};
338 if (!ExtraSymbolsToClaim
.empty()) {
339 if (auto Err
= R
.defineMaterializing(ExtraSymbolsToClaim
))
342 // If we claimed responsibility for any weak symbols but were rejected then
343 // we need to remove them from the resolved set.
344 for (auto &KV
: ExtraSymbolsToClaim
)
345 if (KV
.second
.isWeak() && !R
.getSymbols().count(KV
.first
))
346 Symbols
.erase(KV
.first
);
349 if (auto Err
= R
.notifyResolved(Symbols
)) {
350 R
.failMaterialization();
355 NotifyLoaded(R
, Obj
, LoadedObjInfo
);
357 return Error::success();
360 void RTDyldObjectLinkingLayer::onObjEmit(
361 MaterializationResponsibility
&R
,
362 object::OwningBinary
<object::ObjectFile
> O
,
363 std::unique_ptr
<RuntimeDyld::MemoryManager
> MemMgr
,
364 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> LoadedObjInfo
,
365 std::unique_ptr
<SymbolDependenceMap
> Deps
, Error Err
) {
367 getExecutionSession().reportError(std::move(Err
));
368 R
.failMaterialization();
372 SymbolDependenceGroup SDG
;
373 for (auto &[Sym
, Flags
] : R
.getSymbols())
374 SDG
.Symbols
.insert(Sym
);
375 SDG
.Dependencies
= std::move(*Deps
);
377 if (auto Err
= R
.notifyEmitted(SDG
)) {
378 getExecutionSession().reportError(std::move(Err
));
379 R
.failMaterialization();
383 std::unique_ptr
<object::ObjectFile
> Obj
;
384 std::unique_ptr
<MemoryBuffer
> ObjBuffer
;
385 std::tie(Obj
, ObjBuffer
) = O
.takeBinary();
387 // Run EventListener notifyLoaded callbacks.
389 std::lock_guard
<std::mutex
> Lock(RTDyldLayerMutex
);
390 for (auto *L
: EventListeners
)
391 L
->notifyObjectLoaded(pointerToJITTargetAddress(MemMgr
.get()), *Obj
,
396 NotifyEmitted(R
, std::move(ObjBuffer
));
398 if (auto Err
= R
.withResourceKeyDo(
399 [&](ResourceKey K
) { MemMgrs
[K
].push_back(std::move(MemMgr
)); })) {
400 getExecutionSession().reportError(std::move(Err
));
401 R
.failMaterialization();
405 Error
RTDyldObjectLinkingLayer::handleRemoveResources(JITDylib
&JD
,
408 std::vector
<MemoryManagerUP
> MemMgrsToRemove
;
410 getExecutionSession().runSessionLocked([&] {
411 auto I
= MemMgrs
.find(K
);
412 if (I
!= MemMgrs
.end()) {
413 std::swap(MemMgrsToRemove
, I
->second
);
419 std::lock_guard
<std::mutex
> Lock(RTDyldLayerMutex
);
420 for (auto &MemMgr
: MemMgrsToRemove
) {
421 for (auto *L
: EventListeners
)
422 L
->notifyFreeingObject(pointerToJITTargetAddress(MemMgr
.get()));
423 MemMgr
->deregisterEHFrames();
427 return Error::success();
430 void RTDyldObjectLinkingLayer::handleTransferResources(JITDylib
&JD
,
432 ResourceKey SrcKey
) {
433 if (MemMgrs
.contains(SrcKey
)) {
434 // DstKey may not be in the DenseMap yet, so the following line may resize
435 // the container and invalidate iterators and value references.
436 auto &DstMemMgrs
= MemMgrs
[DstKey
];
437 auto &SrcMemMgrs
= MemMgrs
[SrcKey
];
438 DstMemMgrs
.reserve(DstMemMgrs
.size() + SrcMemMgrs
.size());
439 for (auto &MemMgr
: SrcMemMgrs
)
440 DstMemMgrs
.push_back(std::move(MemMgr
));
442 MemMgrs
.erase(SrcKey
);
446 } // End namespace orc.
447 } // End namespace llvm.