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 // FIXME: Switch to move capture of OnResolved once we have c++14.
31 auto OnResolvedWithUnwrap
=
32 [OnResolved
](Expected
<SymbolMap
> InternedResult
) {
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 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
);
136 // FIXME: Switch to move-capture for the 'O' buffer once we have c++14.
137 MemoryBuffer
*UnownedObjBuffer
= O
.release();
139 **Obj
, std::move(O
), *MemMgr
, Resolver
, ProcessAllSections
,
140 [this, K
, SharedR
, &Obj
, InternalSymbols
](
141 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> LoadedObjInfo
,
142 std::map
<StringRef
, JITEvaluatedSymbol
> ResolvedSymbols
) {
143 return onObjLoad(K
, *SharedR
, **Obj
, std::move(LoadedObjInfo
),
144 ResolvedSymbols
, *InternalSymbols
);
146 [this, K
, SharedR
, UnownedObjBuffer
](Error Err
) {
147 std::unique_ptr
<MemoryBuffer
> ObjBuffer(UnownedObjBuffer
);
148 onObjEmit(K
, std::move(ObjBuffer
), *SharedR
, std::move(Err
));
152 Error
RTDyldObjectLinkingLayer::onObjLoad(
153 VModuleKey K
, MaterializationResponsibility
&R
, object::ObjectFile
&Obj
,
154 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> LoadedObjInfo
,
155 std::map
<StringRef
, JITEvaluatedSymbol
> Resolved
,
156 std::set
<StringRef
> &InternalSymbols
) {
157 SymbolFlagsMap ExtraSymbolsToClaim
;
159 for (auto &KV
: Resolved
) {
160 // Scan the symbols and add them to the Symbols map for resolution.
162 // We never claim internal symbols.
163 if (InternalSymbols
.count(KV
.first
))
166 auto InternedName
= getExecutionSession().intern(KV
.first
);
167 auto Flags
= KV
.second
.getFlags();
169 // Override object flags and claim responsibility for symbols if
171 if (OverrideObjectFlags
|| AutoClaimObjectSymbols
) {
172 auto I
= R
.getSymbols().find(InternedName
);
174 if (OverrideObjectFlags
&& I
!= R
.getSymbols().end())
176 else if (AutoClaimObjectSymbols
&& I
== R
.getSymbols().end())
177 ExtraSymbolsToClaim
[InternedName
] = Flags
;
180 Symbols
[InternedName
] = JITEvaluatedSymbol(KV
.second
.getAddress(), Flags
);
183 if (!ExtraSymbolsToClaim
.empty())
184 if (auto Err
= R
.defineMaterializing(ExtraSymbolsToClaim
))
187 if (auto Err
= R
.notifyResolved(Symbols
)) {
188 R
.failMaterialization();
193 NotifyLoaded(K
, Obj
, *LoadedObjInfo
);
195 return Error::success();
198 void RTDyldObjectLinkingLayer::onObjEmit(
199 VModuleKey K
, std::unique_ptr
<MemoryBuffer
> ObjBuffer
,
200 MaterializationResponsibility
&R
, Error Err
) {
202 getExecutionSession().reportError(std::move(Err
));
203 R
.failMaterialization();
207 if (auto Err
= R
.notifyEmitted()) {
208 getExecutionSession().reportError(std::move(Err
));
209 R
.failMaterialization();
214 NotifyEmitted(K
, std::move(ObjBuffer
));
217 LegacyRTDyldObjectLinkingLayer::LegacyRTDyldObjectLinkingLayer(
218 ExecutionSession
&ES
, ResourcesGetter GetResources
,
219 NotifyLoadedFtor NotifyLoaded
, NotifyFinalizedFtor NotifyFinalized
,
220 NotifyFreedFtor NotifyFreed
)
221 : ES(ES
), GetResources(std::move(GetResources
)),
222 NotifyLoaded(std::move(NotifyLoaded
)),
223 NotifyFinalized(std::move(NotifyFinalized
)),
224 NotifyFreed(std::move(NotifyFreed
)), ProcessAllSections(false) {}
226 } // End namespace orc.
227 } // End namespace llvm.