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 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
14 using namespace llvm::orc
;
16 class JITDylibSearchOrderResolver
: public JITSymbolResolver
{
18 JITDylibSearchOrderResolver(MaterializationResponsibility
&MR
) : MR(MR
) {}
20 void lookup(const LookupSet
&Symbols
, OnResolvedFunction OnResolved
) {
21 auto &ES
= MR
.getTargetJITDylib().getExecutionSession();
22 SymbolNameSet InternedSymbols
;
24 // Intern the requested symbols: lookup takes interned strings.
25 for (auto &S
: Symbols
)
26 InternedSymbols
.insert(ES
.intern(S
));
28 // Build an OnResolve callback to unwrap the interned strings and pass them
29 // to the OnResolved callback.
30 auto OnResolvedWithUnwrap
=
31 [OnResolved
= std::move(OnResolved
)](
32 Expected
<SymbolMap
> InternedResult
) mutable {
33 if (!InternedResult
) {
34 OnResolved(InternedResult
.takeError());
39 for (auto &KV
: *InternedResult
)
40 Result
[*KV
.first
] = std::move(KV
.second
);
44 // Register dependencies for all symbols contained in this set.
45 auto RegisterDependencies
= [&](const SymbolDependenceMap
&Deps
) {
46 MR
.addDependenciesForAll(Deps
);
49 JITDylibSearchList SearchOrder
;
50 MR
.getTargetJITDylib().withSearchOrderDo(
51 [&](const JITDylibSearchList
&JDs
) { SearchOrder
= JDs
; });
52 ES
.lookup(SearchOrder
, InternedSymbols
, SymbolState::Resolved
,
53 std::move(OnResolvedWithUnwrap
), RegisterDependencies
);
56 Expected
<LookupSet
> getResponsibilitySet(const LookupSet
&Symbols
) {
59 for (auto &KV
: MR
.getSymbols()) {
60 if (Symbols
.count(*KV
.first
))
61 Result
.insert(*KV
.first
);
68 MaterializationResponsibility
&MR
;
71 } // end anonymous namespace
76 RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(
77 ExecutionSession
&ES
, GetMemoryManagerFunction GetMemoryManager
)
78 : ObjectLayer(ES
), GetMemoryManager(GetMemoryManager
) {}
80 void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R
,
81 std::unique_ptr
<MemoryBuffer
> O
) {
82 assert(O
&& "Object must not be null");
84 // This method launches an asynchronous link step that will fulfill our
85 // materialization responsibility. We need to switch R to be heap
86 // allocated before that happens so it can live as long as the asynchronous
87 // link needs it to (i.e. it must be able to outlive this method).
88 auto SharedR
= std::make_shared
<MaterializationResponsibility
>(std::move(R
));
90 auto &ES
= getExecutionSession();
92 // Create a MemoryBufferRef backed MemoryBuffer (i.e. shallow) copy of the
93 // the underlying buffer to pass into RuntimeDyld. This allows us to hold
94 // ownership of the real underlying buffer and return it to the user once
95 // the object has been emitted.
96 auto ObjBuffer
= MemoryBuffer::getMemBuffer(O
->getMemBufferRef(), false);
98 auto Obj
= object::ObjectFile::createObjectFile(*ObjBuffer
);
101 getExecutionSession().reportError(Obj
.takeError());
102 SharedR
->failMaterialization();
106 // Collect the internal symbols from the object file: We will need to
107 // filter these later.
108 auto InternalSymbols
= std::make_shared
<std::set
<StringRef
>>();
110 for (auto &Sym
: (*Obj
)->symbols()) {
111 if (!(Sym
.getFlags() & object::BasicSymbolRef::SF_Global
)) {
112 if (auto SymName
= Sym
.getName())
113 InternalSymbols
->insert(*SymName
);
115 ES
.reportError(SymName
.takeError());
116 R
.failMaterialization();
123 auto K
= R
.getVModuleKey();
124 RuntimeDyld::MemoryManager
*MemMgr
= nullptr;
126 // Create a record a memory manager for this object.
128 auto Tmp
= GetMemoryManager();
129 std::lock_guard
<std::mutex
> Lock(RTDyldLayerMutex
);
130 MemMgrs
.push_back(std::move(Tmp
));
131 MemMgr
= MemMgrs
.back().get();
134 JITDylibSearchOrderResolver
Resolver(*SharedR
);
137 **Obj
, std::move(O
), *MemMgr
, Resolver
, ProcessAllSections
,
138 [this, K
, SharedR
, &Obj
, InternalSymbols
](
139 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> LoadedObjInfo
,
140 std::map
<StringRef
, JITEvaluatedSymbol
> ResolvedSymbols
) {
141 return onObjLoad(K
, *SharedR
, **Obj
, std::move(LoadedObjInfo
),
142 ResolvedSymbols
, *InternalSymbols
);
144 [this, K
, SharedR
, O
= std::move(O
)](Error Err
) mutable {
145 onObjEmit(K
, std::move(O
), *SharedR
, std::move(Err
));
149 Error
RTDyldObjectLinkingLayer::onObjLoad(
150 VModuleKey K
, MaterializationResponsibility
&R
, object::ObjectFile
&Obj
,
151 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> LoadedObjInfo
,
152 std::map
<StringRef
, JITEvaluatedSymbol
> Resolved
,
153 std::set
<StringRef
> &InternalSymbols
) {
154 SymbolFlagsMap ExtraSymbolsToClaim
;
156 for (auto &KV
: Resolved
) {
157 // Scan the symbols and add them to the Symbols map for resolution.
159 // We never claim internal symbols.
160 if (InternalSymbols
.count(KV
.first
))
163 auto InternedName
= getExecutionSession().intern(KV
.first
);
164 auto Flags
= KV
.second
.getFlags();
166 // Override object flags and claim responsibility for symbols if
168 if (OverrideObjectFlags
|| AutoClaimObjectSymbols
) {
169 auto I
= R
.getSymbols().find(InternedName
);
171 if (OverrideObjectFlags
&& I
!= R
.getSymbols().end())
173 else if (AutoClaimObjectSymbols
&& I
== R
.getSymbols().end())
174 ExtraSymbolsToClaim
[InternedName
] = Flags
;
177 Symbols
[InternedName
] = JITEvaluatedSymbol(KV
.second
.getAddress(), Flags
);
180 if (!ExtraSymbolsToClaim
.empty())
181 if (auto Err
= R
.defineMaterializing(ExtraSymbolsToClaim
))
184 if (auto Err
= R
.notifyResolved(Symbols
)) {
185 R
.failMaterialization();
190 NotifyLoaded(K
, Obj
, *LoadedObjInfo
);
192 return Error::success();
195 void RTDyldObjectLinkingLayer::onObjEmit(
196 VModuleKey K
, std::unique_ptr
<MemoryBuffer
> ObjBuffer
,
197 MaterializationResponsibility
&R
, Error Err
) {
199 getExecutionSession().reportError(std::move(Err
));
200 R
.failMaterialization();
204 if (auto Err
= R
.notifyEmitted()) {
205 getExecutionSession().reportError(std::move(Err
));
206 R
.failMaterialization();
211 NotifyEmitted(K
, std::move(ObjBuffer
));
214 LegacyRTDyldObjectLinkingLayer::LegacyRTDyldObjectLinkingLayer(
215 ExecutionSession
&ES
, ResourcesGetter GetResources
,
216 NotifyLoadedFtor NotifyLoaded
, NotifyFinalizedFtor NotifyFinalized
,
217 NotifyFreedFtor NotifyFreed
)
218 : ES(ES
), GetResources(std::move(GetResources
)),
219 NotifyLoaded(std::move(NotifyLoaded
)),
220 NotifyFinalized(std::move(NotifyFinalized
)),
221 NotifyFreed(std::move(NotifyFreed
)), ProcessAllSections(false) {}
223 } // End namespace orc.
224 } // End namespace llvm.