Line data Source code
1 : //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
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/LazyReexports.h"
11 :
12 : #include "llvm/ADT/Triple.h"
13 : #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
14 :
15 : #define DEBUG_TYPE "orc"
16 :
17 : namespace llvm {
18 : namespace orc {
19 :
20 0 : void LazyCallThroughManager::NotifyResolvedFunction::anchor() {}
21 :
22 14 : LazyCallThroughManager::LazyCallThroughManager(
23 : ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr,
24 14 : std::unique_ptr<TrampolinePool> TP)
25 28 : : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(std::move(TP)) {}
26 :
27 20 : Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
28 : JITDylib &SourceJD, SymbolStringPtr SymbolName,
29 : std::shared_ptr<NotifyResolvedFunction> NotifyResolved) {
30 20 : std::lock_guard<std::mutex> Lock(LCTMMutex);
31 20 : auto Trampoline = TP->getTrampoline();
32 :
33 20 : if (!Trampoline)
34 : return Trampoline.takeError();
35 :
36 20 : Reexports[*Trampoline] = std::make_pair(&SourceJD, std::move(SymbolName));
37 20 : Notifiers[*Trampoline] = std::move(NotifyResolved);
38 : return *Trampoline;
39 : }
40 :
41 : JITTargetAddress
42 20 : LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
43 : JITDylib *SourceJD = nullptr;
44 20 : SymbolStringPtr SymbolName;
45 :
46 : {
47 20 : std::lock_guard<std::mutex> Lock(LCTMMutex);
48 : auto I = Reexports.find(TrampolineAddr);
49 20 : if (I == Reexports.end())
50 0 : return ErrorHandlerAddr;
51 20 : SourceJD = I->second.first;
52 20 : SymbolName = I->second.second;
53 : }
54 :
55 20 : auto LookupResult = ES.lookup({SourceJD}, {SymbolName},
56 100 : NoDependenciesToRegister, true, nullptr, true);
57 :
58 20 : if (!LookupResult) {
59 0 : ES.reportError(LookupResult.takeError());
60 0 : return ErrorHandlerAddr;
61 : }
62 :
63 : assert(LookupResult->size() == 1 && "Unexpected number of results");
64 : assert(LookupResult->count(SymbolName) && "Unexpected result");
65 :
66 20 : auto ResolvedAddr = LookupResult->begin()->second.getAddress();
67 :
68 : std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
69 : {
70 : std::lock_guard<std::mutex> Lock(LCTMMutex);
71 : auto I = Notifiers.find(TrampolineAddr);
72 20 : if (I != Notifiers.end()) {
73 : NotifyResolved = I->second;
74 : Notifiers.erase(I);
75 : }
76 : }
77 :
78 20 : if (NotifyResolved) {
79 38 : if (auto Err = (*NotifyResolved)(*SourceJD, SymbolName, ResolvedAddr)) {
80 0 : ES.reportError(std::move(Err));
81 0 : return ErrorHandlerAddr;
82 : }
83 : }
84 :
85 : return ResolvedAddr;
86 : }
87 :
88 : Expected<std::unique_ptr<LazyCallThroughManager>>
89 14 : createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
90 : JITTargetAddress ErrorHandlerAddr) {
91 14 : switch (T.getArch()) {
92 0 : default:
93 0 : return make_error<StringError>(
94 0 : std::string("No callback manager available for ") + T.str(),
95 0 : inconvertibleErrorCode());
96 :
97 0 : case Triple::aarch64:
98 0 : return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
99 : ErrorHandlerAddr);
100 :
101 0 : case Triple::x86:
102 0 : return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
103 :
104 0 : case Triple::mips:
105 0 : return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
106 : ErrorHandlerAddr);
107 :
108 0 : case Triple::mipsel:
109 0 : return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
110 : ErrorHandlerAddr);
111 :
112 0 : case Triple::mips64:
113 : case Triple::mips64el:
114 0 : return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
115 :
116 14 : case Triple::x86_64:
117 14 : if (T.getOS() == Triple::OSType::Win32)
118 0 : return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
119 : ES, ErrorHandlerAddr);
120 : else
121 28 : return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
122 : ES, ErrorHandlerAddr);
123 : }
124 : }
125 :
126 22 : LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
127 : LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
128 22 : JITDylib &SourceJD, SymbolAliasMap CallableAliases, VModuleKey K)
129 22 : : MaterializationUnit(extractFlags(CallableAliases), std::move(K)),
130 : LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
131 : CallableAliases(std::move(CallableAliases)),
132 22 : NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
133 : [&ISManager](JITDylib &JD, const SymbolStringPtr &SymbolName,
134 : JITTargetAddress ResolvedAddr) {
135 36 : return ISManager.updatePointer(*SymbolName, ResolvedAddr);
136 22 : })) {}
137 :
138 0 : StringRef LazyReexportsMaterializationUnit::getName() const {
139 0 : return "<Lazy Reexports>";
140 : }
141 :
142 19 : void LazyReexportsMaterializationUnit::materialize(
143 : MaterializationResponsibility R) {
144 19 : auto RequestedSymbols = R.getRequestedSymbols();
145 :
146 : SymbolAliasMap RequestedAliases;
147 38 : for (auto &RequestedSymbol : RequestedSymbols) {
148 19 : auto I = CallableAliases.find(RequestedSymbol);
149 : assert(I != CallableAliases.end() && "Symbol not found in alias map?");
150 19 : RequestedAliases[I->first] = std::move(I->second);
151 19 : CallableAliases.erase(I);
152 : }
153 :
154 19 : if (!CallableAliases.empty())
155 27 : R.replace(lazyReexports(LCTManager, ISManager, SourceJD,
156 : std::move(CallableAliases)));
157 :
158 19 : IndirectStubsManager::StubInitsMap StubInits;
159 57 : for (auto &Alias : RequestedAliases) {
160 :
161 19 : auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
162 38 : SourceJD, Alias.second.Aliasee, NotifyResolved);
163 :
164 19 : if (!CallThroughTrampoline) {
165 0 : SourceJD.getExecutionSession().reportError(
166 0 : CallThroughTrampoline.takeError());
167 0 : R.failMaterialization();
168 : return;
169 : }
170 :
171 19 : StubInits[*Alias.first] =
172 19 : std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
173 : }
174 :
175 38 : if (auto Err = ISManager.createStubs(StubInits)) {
176 0 : SourceJD.getExecutionSession().reportError(std::move(Err));
177 0 : R.failMaterialization();
178 : return;
179 : }
180 :
181 : SymbolMap Stubs;
182 57 : for (auto &Alias : RequestedAliases)
183 38 : Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
184 :
185 19 : R.resolve(Stubs);
186 19 : R.emit();
187 : }
188 :
189 0 : void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
190 : const SymbolStringPtr &Name) {
191 : assert(CallableAliases.count(Name) &&
192 : "Symbol not covered by this MaterializationUnit");
193 0 : CallableAliases.erase(Name);
194 0 : }
195 :
196 : SymbolFlagsMap
197 22 : LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
198 : SymbolFlagsMap SymbolFlags;
199 78 : for (auto &KV : Aliases) {
200 : assert(KV.second.AliasFlags.isCallable() &&
201 : "Lazy re-exports must be callable symbols");
202 34 : SymbolFlags[KV.first] = KV.second.AliasFlags;
203 : }
204 22 : return SymbolFlags;
205 : }
206 :
207 : } // End namespace orc.
208 : } // End namespace llvm.
|