1 //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
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/LazyReexports.h"
11 #include "llvm/ADT/Triple.h"
12 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
14 #define DEBUG_TYPE "orc"
19 void LazyCallThroughManager::NotifyResolvedFunction::anchor() {}
21 LazyCallThroughManager::LazyCallThroughManager(
22 ExecutionSession
&ES
, JITTargetAddress ErrorHandlerAddr
,
23 std::unique_ptr
<TrampolinePool
> TP
)
24 : ES(ES
), ErrorHandlerAddr(ErrorHandlerAddr
), TP(std::move(TP
)) {}
26 Expected
<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();
33 return Trampoline
.takeError();
35 Reexports
[*Trampoline
] = std::make_pair(&SourceJD
, std::move(SymbolName
));
36 Notifiers
[*Trampoline
] = std::move(NotifyResolved
);
41 LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr
) {
42 JITDylib
*SourceJD
= nullptr;
43 SymbolStringPtr SymbolName
;
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
;
54 ES
.lookup(JITDylibSearchList({{SourceJD
, true}}), SymbolName
);
57 ES
.reportError(LookupResult
.takeError());
58 return ErrorHandlerAddr
;
61 auto ResolvedAddr
= LookupResult
->getAddress();
63 std::shared_ptr
<NotifyResolvedFunction
> NotifyResolved
= nullptr;
65 std::lock_guard
<std::mutex
> Lock(LCTMMutex
);
66 auto I
= Notifiers
.find(TrampolineAddr
);
67 if (I
!= Notifiers
.end()) {
68 NotifyResolved
= I
->second
;
74 if (auto Err
= (*NotifyResolved
)(*SourceJD
, SymbolName
, ResolvedAddr
)) {
75 ES
.reportError(std::move(Err
));
76 return ErrorHandlerAddr
;
83 Expected
<std::unique_ptr
<LazyCallThroughManager
>>
84 createLocalLazyCallThroughManager(const Triple
&T
, ExecutionSession
&ES
,
85 JITTargetAddress ErrorHandlerAddr
) {
86 switch (T
.getArch()) {
88 return make_error
<StringError
>(
89 std::string("No callback manager available for ") + T
.str(),
90 inconvertibleErrorCode());
93 return LocalLazyCallThroughManager::Create
<OrcAArch64
>(ES
,
97 return LocalLazyCallThroughManager::Create
<OrcI386
>(ES
, ErrorHandlerAddr
);
100 return LocalLazyCallThroughManager::Create
<OrcMips32Be
>(ES
,
104 return LocalLazyCallThroughManager::Create
<OrcMips32Le
>(ES
,
108 case Triple::mips64el
:
109 return LocalLazyCallThroughManager::Create
<OrcMips64
>(ES
, ErrorHandlerAddr
);
112 if (T
.getOS() == Triple::OSType::Win32
)
113 return LocalLazyCallThroughManager::Create
<OrcX86_64_Win32
>(
114 ES
, ErrorHandlerAddr
);
116 return LocalLazyCallThroughManager::Create
<OrcX86_64_SysV
>(
117 ES
, ErrorHandlerAddr
);
121 LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
122 LazyCallThroughManager
&LCTManager
, IndirectStubsManager
&ISManager
,
123 JITDylib
&SourceJD
, SymbolAliasMap CallableAliases
, ImplSymbolMap
*SrcJDLoc
,
125 : MaterializationUnit(extractFlags(CallableAliases
), std::move(K
)),
126 LCTManager(LCTManager
), ISManager(ISManager
), SourceJD(SourceJD
),
127 CallableAliases(std::move(CallableAliases
)),
128 NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
129 [&ISManager
](JITDylib
&JD
, const SymbolStringPtr
&SymbolName
,
130 JITTargetAddress ResolvedAddr
) {
131 return ISManager
.updatePointer(*SymbolName
, ResolvedAddr
);
133 AliaseeTable(SrcJDLoc
) {}
135 StringRef
LazyReexportsMaterializationUnit::getName() const {
136 return "<Lazy Reexports>";
139 void LazyReexportsMaterializationUnit::materialize(
140 MaterializationResponsibility R
) {
141 auto RequestedSymbols
= R
.getRequestedSymbols();
143 SymbolAliasMap RequestedAliases
;
144 for (auto &RequestedSymbol
: RequestedSymbols
) {
145 auto I
= CallableAliases
.find(RequestedSymbol
);
146 assert(I
!= CallableAliases
.end() && "Symbol not found in alias map?");
147 RequestedAliases
[I
->first
] = std::move(I
->second
);
148 CallableAliases
.erase(I
);
151 if (!CallableAliases
.empty())
152 R
.replace(lazyReexports(LCTManager
, ISManager
, SourceJD
,
153 std::move(CallableAliases
), AliaseeTable
));
155 IndirectStubsManager::StubInitsMap StubInits
;
156 for (auto &Alias
: RequestedAliases
) {
158 auto CallThroughTrampoline
= LCTManager
.getCallThroughTrampoline(
159 SourceJD
, Alias
.second
.Aliasee
, NotifyResolved
);
161 if (!CallThroughTrampoline
) {
162 SourceJD
.getExecutionSession().reportError(
163 CallThroughTrampoline
.takeError());
164 R
.failMaterialization();
168 StubInits
[*Alias
.first
] =
169 std::make_pair(*CallThroughTrampoline
, Alias
.second
.AliasFlags
);
172 if (AliaseeTable
!= nullptr && !RequestedAliases
.empty())
173 AliaseeTable
->trackImpls(RequestedAliases
, &SourceJD
);
175 if (auto Err
= ISManager
.createStubs(StubInits
)) {
176 SourceJD
.getExecutionSession().reportError(std::move(Err
));
177 R
.failMaterialization();
182 for (auto &Alias
: RequestedAliases
)
183 Stubs
[Alias
.first
] = ISManager
.findStub(*Alias
.first
, false);
185 // No registered dependencies, so these calls cannot fail.
186 cantFail(R
.notifyResolved(Stubs
));
187 cantFail(R
.notifyEmitted());
190 void LazyReexportsMaterializationUnit::discard(const JITDylib
&JD
,
191 const SymbolStringPtr
&Name
) {
192 assert(CallableAliases
.count(Name
) &&
193 "Symbol not covered by this MaterializationUnit");
194 CallableAliases
.erase(Name
);
198 LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap
&Aliases
) {
199 SymbolFlagsMap SymbolFlags
;
200 for (auto &KV
: Aliases
) {
201 assert(KV
.second
.AliasFlags
.isCallable() &&
202 "Lazy re-exports must be callable symbols");
203 SymbolFlags
[KV
.first
] = KV
.second
.AliasFlags
;
208 } // End namespace orc.
209 } // End namespace llvm.