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