Line data Source code
1 : //===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
11 :
12 : namespace {
13 :
14 : using namespace llvm;
15 : using namespace llvm::orc;
16 :
17 31 : class JITDylibSearchOrderResolver : public JITSymbolResolver {
18 : public:
19 31 : JITDylibSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {}
20 :
21 14 : void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) {
22 14 : auto &ES = MR.getTargetJITDylib().getExecutionSession();
23 : SymbolNameSet InternedSymbols;
24 :
25 : // Intern the requested symbols: lookup takes interned strings.
26 40 : for (auto &S : Symbols)
27 52 : InternedSymbols.insert(ES.intern(S));
28 :
29 : // Build an OnResolve callback to unwrap the interned strings and pass them
30 : // to the OnResolved callback.
31 : // FIXME: Switch to move capture of OnResolved once we have c++14.
32 : auto OnResolvedWithUnwrap =
33 14 : [OnResolved](Expected<SymbolMap> InternedResult) {
34 : if (!InternedResult) {
35 : OnResolved(InternedResult.takeError());
36 : return;
37 : }
38 :
39 : LookupResult Result;
40 : for (auto &KV : *InternedResult)
41 : Result[*KV.first] = std::move(KV.second);
42 : OnResolved(Result);
43 : };
44 :
45 : // We're not waiting for symbols to be ready. Just log any errors.
46 14 : auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
47 :
48 : // Register dependencies for all symbols contained in this set.
49 : auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
50 12 : MR.addDependenciesForAll(Deps);
51 14 : };
52 :
53 14 : MR.getTargetJITDylib().withSearchOrderDo([&](const JITDylibList &JDs) {
54 : ES.lookup(JDs, InternedSymbols, OnResolvedWithUnwrap, OnReady,
55 : RegisterDependencies, &MR.getTargetJITDylib());
56 : });
57 14 : }
58 :
59 31 : Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) {
60 : LookupSet Result;
61 :
62 132 : for (auto &KV : MR.getSymbols()) {
63 114 : if (Symbols.count(*KV.first))
64 6 : Result.insert(*KV.first);
65 : }
66 :
67 31 : return Result;
68 : }
69 :
70 : private:
71 : MaterializationResponsibility &MR;
72 : };
73 :
74 : } // end anonymous namespace
75 :
76 : namespace llvm {
77 : namespace orc {
78 :
79 17 : RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(
80 : ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
81 17 : NotifyLoadedFunction NotifyLoaded, NotifyEmittedFunction NotifyEmitted)
82 : : ObjectLayer(ES), GetMemoryManager(GetMemoryManager),
83 : NotifyLoaded(std::move(NotifyLoaded)),
84 17 : NotifyEmitted(std::move(NotifyEmitted)) {}
85 :
86 31 : void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R,
87 : std::unique_ptr<MemoryBuffer> O) {
88 : assert(O && "Object must not be null");
89 :
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));
95 :
96 31 : auto &ES = getExecutionSession();
97 :
98 62 : auto Obj = object::ObjectFile::createObjectFile(*O);
99 :
100 31 : if (!Obj) {
101 0 : getExecutionSession().reportError(Obj.takeError());
102 0 : SharedR->failMaterialization();
103 0 : return;
104 : }
105 :
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>>();
109 : {
110 184 : for (auto &Sym : (*Obj)->symbols()) {
111 153 : if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) {
112 86 : if (auto SymName = Sym.getName())
113 : InternalSymbols->insert(*SymName);
114 : else {
115 0 : ES.reportError(SymName.takeError());
116 0 : R.failMaterialization();
117 : return;
118 : }
119 : }
120 : }
121 : }
122 :
123 31 : auto K = R.getVModuleKey();
124 62 : MemMgrs.push_back(GetMemoryManager());
125 : auto &MemMgr = *MemMgrs.back();
126 :
127 : JITDylibSearchOrderResolver Resolver(*SharedR);
128 :
129 : /* Thoughts on proper cross-dylib weak symbol handling:
130 : *
131 : * Change selection of canonical defs to be a manually triggered process, and
132 : * add a 'canonical' bit to symbol definitions. When canonical def selection
133 : * is triggered, sweep the JITDylibs to mark defs as canonical, discard
134 : * duplicate defs.
135 : */
136 155 : jitLinkForORC(
137 31 : **Obj, std::move(O), MemMgr, Resolver, ProcessAllSections,
138 0 : [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);
143 : },
144 0 : [this, K, SharedR](Error Err) {
145 : onObjEmit(K, *SharedR, std::move(Err));
146 : });
147 : }
148 :
149 31 : 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;
155 : SymbolMap Symbols;
156 71 : for (auto &KV : Resolved) {
157 : // Scan the symbols and add them to the Symbols map for resolution.
158 :
159 : // We never claim internal symbols.
160 40 : if (InternalSymbols.count(KV.first))
161 0 : continue;
162 :
163 40 : auto InternedName = getExecutionSession().intern(KV.first);
164 : auto Flags = KV.second.getFlags();
165 :
166 : // Override object flags and claim responsibility for symbols if
167 : // requested.
168 40 : if (OverrideObjectFlags || AutoClaimObjectSymbols) {
169 4 : auto I = R.getSymbols().find(InternedName);
170 :
171 4 : if (OverrideObjectFlags && I != R.getSymbols().end())
172 2 : Flags = JITSymbolFlags::stripTransientFlags(I->second);
173 2 : else if (AutoClaimObjectSymbols && I == R.getSymbols().end())
174 1 : ExtraSymbolsToClaim[InternedName] = Flags;
175 : }
176 :
177 40 : Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
178 : }
179 :
180 31 : if (!ExtraSymbolsToClaim.empty())
181 2 : if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))
182 : return Err;
183 :
184 31 : R.resolve(Symbols);
185 :
186 31 : if (NotifyLoaded)
187 0 : NotifyLoaded(K, Obj, *LoadedObjInfo);
188 :
189 : return Error::success();
190 : }
191 :
192 31 : void RTDyldObjectLinkingLayer::onObjEmit(VModuleKey K,
193 : MaterializationResponsibility &R,
194 : Error Err) {
195 31 : if (Err) {
196 0 : getExecutionSession().reportError(std::move(Err));
197 0 : R.failMaterialization();
198 0 : return;
199 : }
200 :
201 31 : R.emit();
202 :
203 31 : if (NotifyEmitted)
204 0 : NotifyEmitted(K);
205 : }
206 :
207 : } // End namespace orc.
208 : } // End namespace llvm.
|