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 // We're not waiting for symbols to be ready. Just log any errors.
45 auto OnReady
= [&ES
](Error Err
) { ES
.reportError(std::move(Err
)); };
47 // Register dependencies for all symbols contained in this set.
48 auto RegisterDependencies
= [&](const SymbolDependenceMap
&Deps
) {
49 MR
.addDependenciesForAll(Deps
);
52 JITDylibSearchList SearchOrder
;
53 MR
.getTargetJITDylib().withSearchOrderDo(
54 [&](const JITDylibSearchList
&JDs
) { SearchOrder
= JDs
; });
55 ES
.lookup(SearchOrder
, InternedSymbols
, OnResolvedWithUnwrap
, OnReady
,
56 RegisterDependencies
);
59 Expected
<LookupSet
> getResponsibilitySet(const LookupSet
&Symbols
) {
62 for (auto &KV
: MR
.getSymbols()) {
63 if (Symbols
.count(*KV
.first
))
64 Result
.insert(*KV
.first
);
71 MaterializationResponsibility
&MR
;
74 } // end anonymous namespace
79 RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(
80 ExecutionSession
&ES
, GetMemoryManagerFunction GetMemoryManager
,
81 NotifyLoadedFunction NotifyLoaded
, NotifyEmittedFunction NotifyEmitted
)
82 : ObjectLayer(ES
), GetMemoryManager(GetMemoryManager
),
83 NotifyLoaded(std::move(NotifyLoaded
)),
84 NotifyEmitted(std::move(NotifyEmitted
)) {}
86 void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R
,
87 std::unique_ptr
<MemoryBuffer
> O
) {
88 assert(O
&& "Object must not be null");
90 // This method launches an asynchronous link step that will fulfill our
91 // materialization responsibility. We need to switch R to be heap
92 // allocated before that happens so it can live as long as the asynchronous
93 // link needs it to (i.e. it must be able to outlive this method).
94 auto SharedR
= std::make_shared
<MaterializationResponsibility
>(std::move(R
));
96 auto &ES
= getExecutionSession();
98 auto Obj
= object::ObjectFile::createObjectFile(*O
);
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 /* Thoughts on proper cross-dylib weak symbol handling:
138 * Change selection of canonical defs to be a manually triggered process, and
139 * add a 'canonical' bit to symbol definitions. When canonical def selection
140 * is triggered, sweep the JITDylibs to mark defs as canonical, discard
144 **Obj
, std::move(O
), *MemMgr
, Resolver
, ProcessAllSections
,
145 [this, K
, SharedR
, &Obj
, InternalSymbols
](
146 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> LoadedObjInfo
,
147 std::map
<StringRef
, JITEvaluatedSymbol
> ResolvedSymbols
) {
148 return onObjLoad(K
, *SharedR
, **Obj
, std::move(LoadedObjInfo
),
149 ResolvedSymbols
, *InternalSymbols
);
151 [this, K
, SharedR
](Error Err
) {
152 onObjEmit(K
, *SharedR
, std::move(Err
));
156 Error
RTDyldObjectLinkingLayer::onObjLoad(
157 VModuleKey K
, MaterializationResponsibility
&R
, object::ObjectFile
&Obj
,
158 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
> LoadedObjInfo
,
159 std::map
<StringRef
, JITEvaluatedSymbol
> Resolved
,
160 std::set
<StringRef
> &InternalSymbols
) {
161 SymbolFlagsMap ExtraSymbolsToClaim
;
163 for (auto &KV
: Resolved
) {
164 // Scan the symbols and add them to the Symbols map for resolution.
166 // We never claim internal symbols.
167 if (InternalSymbols
.count(KV
.first
))
170 auto InternedName
= getExecutionSession().intern(KV
.first
);
171 auto Flags
= KV
.second
.getFlags();
173 // Override object flags and claim responsibility for symbols if
175 if (OverrideObjectFlags
|| AutoClaimObjectSymbols
) {
176 auto I
= R
.getSymbols().find(InternedName
);
178 if (OverrideObjectFlags
&& I
!= R
.getSymbols().end())
179 Flags
= JITSymbolFlags::stripTransientFlags(I
->second
);
180 else if (AutoClaimObjectSymbols
&& I
== R
.getSymbols().end())
181 ExtraSymbolsToClaim
[InternedName
] = Flags
;
184 Symbols
[InternedName
] = JITEvaluatedSymbol(KV
.second
.getAddress(), Flags
);
187 if (!ExtraSymbolsToClaim
.empty())
188 if (auto Err
= R
.defineMaterializing(ExtraSymbolsToClaim
))
194 NotifyLoaded(K
, Obj
, *LoadedObjInfo
);
196 return Error::success();
199 void RTDyldObjectLinkingLayer::onObjEmit(VModuleKey K
,
200 MaterializationResponsibility
&R
,
203 getExecutionSession().reportError(std::move(Err
));
204 R
.failMaterialization();
214 } // End namespace orc.
215 } // End namespace llvm.