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 case Triple::aarch64_32
:
94 return LocalLazyCallThroughManager::Create
<OrcAArch64
>(ES
,
98 return LocalLazyCallThroughManager::Create
<OrcI386
>(ES
, ErrorHandlerAddr
);
101 return LocalLazyCallThroughManager::Create
<OrcMips32Be
>(ES
,
105 return LocalLazyCallThroughManager::Create
<OrcMips32Le
>(ES
,
109 case Triple::mips64el
:
110 return LocalLazyCallThroughManager::Create
<OrcMips64
>(ES
, ErrorHandlerAddr
);
113 if (T
.getOS() == Triple::OSType::Win32
)
114 return LocalLazyCallThroughManager::Create
<OrcX86_64_Win32
>(
115 ES
, ErrorHandlerAddr
);
117 return LocalLazyCallThroughManager::Create
<OrcX86_64_SysV
>(
118 ES
, ErrorHandlerAddr
);
122 LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
123 LazyCallThroughManager
&LCTManager
, IndirectStubsManager
&ISManager
,
124 JITDylib
&SourceJD
, SymbolAliasMap CallableAliases
, ImplSymbolMap
*SrcJDLoc
,
126 : MaterializationUnit(extractFlags(CallableAliases
), std::move(K
)),
127 LCTManager(LCTManager
), ISManager(ISManager
), SourceJD(SourceJD
),
128 CallableAliases(std::move(CallableAliases
)),
129 NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
130 [&ISManager
](JITDylib
&JD
, const SymbolStringPtr
&SymbolName
,
131 JITTargetAddress ResolvedAddr
) {
132 return ISManager
.updatePointer(*SymbolName
, ResolvedAddr
);
134 AliaseeTable(SrcJDLoc
) {}
136 StringRef
LazyReexportsMaterializationUnit::getName() const {
137 return "<Lazy Reexports>";
140 void LazyReexportsMaterializationUnit::materialize(
141 MaterializationResponsibility R
) {
142 auto RequestedSymbols
= R
.getRequestedSymbols();
144 SymbolAliasMap RequestedAliases
;
145 for (auto &RequestedSymbol
: RequestedSymbols
) {
146 auto I
= CallableAliases
.find(RequestedSymbol
);
147 assert(I
!= CallableAliases
.end() && "Symbol not found in alias map?");
148 RequestedAliases
[I
->first
] = std::move(I
->second
);
149 CallableAliases
.erase(I
);
152 if (!CallableAliases
.empty())
153 R
.replace(lazyReexports(LCTManager
, ISManager
, SourceJD
,
154 std::move(CallableAliases
), AliaseeTable
));
156 IndirectStubsManager::StubInitsMap StubInits
;
157 for (auto &Alias
: RequestedAliases
) {
159 auto CallThroughTrampoline
= LCTManager
.getCallThroughTrampoline(
160 SourceJD
, Alias
.second
.Aliasee
, NotifyResolved
);
162 if (!CallThroughTrampoline
) {
163 SourceJD
.getExecutionSession().reportError(
164 CallThroughTrampoline
.takeError());
165 R
.failMaterialization();
169 StubInits
[*Alias
.first
] =
170 std::make_pair(*CallThroughTrampoline
, Alias
.second
.AliasFlags
);
173 if (AliaseeTable
!= nullptr && !RequestedAliases
.empty())
174 AliaseeTable
->trackImpls(RequestedAliases
, &SourceJD
);
176 if (auto Err
= ISManager
.createStubs(StubInits
)) {
177 SourceJD
.getExecutionSession().reportError(std::move(Err
));
178 R
.failMaterialization();
183 for (auto &Alias
: RequestedAliases
)
184 Stubs
[Alias
.first
] = ISManager
.findStub(*Alias
.first
, false);
186 // No registered dependencies, so these calls cannot fail.
187 cantFail(R
.notifyResolved(Stubs
));
188 cantFail(R
.notifyEmitted());
191 void LazyReexportsMaterializationUnit::discard(const JITDylib
&JD
,
192 const SymbolStringPtr
&Name
) {
193 assert(CallableAliases
.count(Name
) &&
194 "Symbol not covered by this MaterializationUnit");
195 CallableAliases
.erase(Name
);
199 LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap
&Aliases
) {
200 SymbolFlagsMap SymbolFlags
;
201 for (auto &KV
: Aliases
) {
202 assert(KV
.second
.AliasFlags
.isCallable() &&
203 "Lazy re-exports must be callable symbols");
204 SymbolFlags
[KV
.first
] = KV
.second
.AliasFlags
;
209 } // End namespace orc.
210 } // End namespace llvm.