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