xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/LazyReexports.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
1206c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #define DEBUG_TYPE "orc"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric namespace orc {
180b57cec5SDimitry Andric 
LazyCallThroughManager(ExecutionSession & ES,ExecutorAddr ErrorHandlerAddr,TrampolinePool * TP)1906c3fb27SDimitry Andric LazyCallThroughManager::LazyCallThroughManager(ExecutionSession &ES,
2006c3fb27SDimitry Andric                                                ExecutorAddr ErrorHandlerAddr,
2106c3fb27SDimitry Andric                                                TrampolinePool *TP)
225ffd83dbSDimitry Andric     : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(TP) {}
230b57cec5SDimitry Andric 
getCallThroughTrampoline(JITDylib & SourceJD,SymbolStringPtr SymbolName,NotifyResolvedFunction NotifyResolved)2406c3fb27SDimitry Andric Expected<ExecutorAddr> LazyCallThroughManager::getCallThroughTrampoline(
250b57cec5SDimitry Andric     JITDylib &SourceJD, SymbolStringPtr SymbolName,
265ffd83dbSDimitry Andric     NotifyResolvedFunction NotifyResolved) {
275ffd83dbSDimitry Andric   assert(TP && "TrampolinePool not set");
285ffd83dbSDimitry Andric 
290b57cec5SDimitry Andric   std::lock_guard<std::mutex> Lock(LCTMMutex);
300b57cec5SDimitry Andric   auto Trampoline = TP->getTrampoline();
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   if (!Trampoline)
330b57cec5SDimitry Andric     return Trampoline.takeError();
340b57cec5SDimitry Andric 
355ffd83dbSDimitry Andric   Reexports[*Trampoline] = ReexportsEntry{&SourceJD, std::move(SymbolName)};
360b57cec5SDimitry Andric   Notifiers[*Trampoline] = std::move(NotifyResolved);
370b57cec5SDimitry Andric   return *Trampoline;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric 
reportCallThroughError(Error Err)4006c3fb27SDimitry Andric ExecutorAddr LazyCallThroughManager::reportCallThroughError(Error Err) {
415ffd83dbSDimitry Andric   ES.reportError(std::move(Err));
425ffd83dbSDimitry Andric   return ErrorHandlerAddr;
435ffd83dbSDimitry Andric }
440b57cec5SDimitry Andric 
455ffd83dbSDimitry Andric Expected<LazyCallThroughManager::ReexportsEntry>
findReexport(ExecutorAddr TrampolineAddr)4606c3fb27SDimitry Andric LazyCallThroughManager::findReexport(ExecutorAddr TrampolineAddr) {
470b57cec5SDimitry Andric   std::lock_guard<std::mutex> Lock(LCTMMutex);
480b57cec5SDimitry Andric   auto I = Reexports.find(TrampolineAddr);
490b57cec5SDimitry Andric   if (I == Reexports.end())
505ffd83dbSDimitry Andric     return createStringError(inconvertibleErrorCode(),
5106c3fb27SDimitry Andric                              "Missing reexport for trampoline address %p" +
5206c3fb27SDimitry Andric                                  formatv("{0:x}", TrampolineAddr));
535ffd83dbSDimitry Andric   return I->second;
540b57cec5SDimitry Andric }
55480093f4SDimitry Andric 
notifyResolved(ExecutorAddr TrampolineAddr,ExecutorAddr ResolvedAddr)5606c3fb27SDimitry Andric Error LazyCallThroughManager::notifyResolved(ExecutorAddr TrampolineAddr,
5706c3fb27SDimitry Andric                                              ExecutorAddr ResolvedAddr) {
585ffd83dbSDimitry Andric   NotifyResolvedFunction NotifyResolved;
590b57cec5SDimitry Andric   {
600b57cec5SDimitry Andric     std::lock_guard<std::mutex> Lock(LCTMMutex);
610b57cec5SDimitry Andric     auto I = Notifiers.find(TrampolineAddr);
620b57cec5SDimitry Andric     if (I != Notifiers.end()) {
635ffd83dbSDimitry Andric       NotifyResolved = std::move(I->second);
640b57cec5SDimitry Andric       Notifiers.erase(I);
650b57cec5SDimitry Andric     }
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric 
685ffd83dbSDimitry Andric   return NotifyResolved ? NotifyResolved(ResolvedAddr) : Error::success();
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
resolveTrampolineLandingAddress(ExecutorAddr TrampolineAddr,NotifyLandingResolvedFunction NotifyLandingResolved)715ffd83dbSDimitry Andric void LazyCallThroughManager::resolveTrampolineLandingAddress(
7206c3fb27SDimitry Andric     ExecutorAddr TrampolineAddr,
735ffd83dbSDimitry Andric     NotifyLandingResolvedFunction NotifyLandingResolved) {
745ffd83dbSDimitry Andric 
755ffd83dbSDimitry Andric   auto Entry = findReexport(TrampolineAddr);
765ffd83dbSDimitry Andric   if (!Entry)
775ffd83dbSDimitry Andric     return NotifyLandingResolved(reportCallThroughError(Entry.takeError()));
785ffd83dbSDimitry Andric 
79e8d8bef9SDimitry Andric   // Declaring SLS and the callback outside of the call to ES.lookup is a
80e8d8bef9SDimitry Andric   // workaround to fix build failures on AIX and on z/OS platforms.
81e8d8bef9SDimitry Andric   SymbolLookupSet SLS({Entry->SymbolName});
82e8d8bef9SDimitry Andric   auto Callback = [this, TrampolineAddr, SymbolName = Entry->SymbolName,
835ffd83dbSDimitry Andric                    NotifyLandingResolved = std::move(NotifyLandingResolved)](
845ffd83dbSDimitry Andric                       Expected<SymbolMap> Result) mutable {
855ffd83dbSDimitry Andric     if (Result) {
865ffd83dbSDimitry Andric       assert(Result->size() == 1 && "Unexpected result size");
875ffd83dbSDimitry Andric       assert(Result->count(SymbolName) && "Unexpected result value");
8806c3fb27SDimitry Andric       ExecutorAddr LandingAddr = (*Result)[SymbolName].getAddress();
895ffd83dbSDimitry Andric 
905ffd83dbSDimitry Andric       if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))
915ffd83dbSDimitry Andric         NotifyLandingResolved(reportCallThroughError(std::move(Err)));
925ffd83dbSDimitry Andric       else
935ffd83dbSDimitry Andric         NotifyLandingResolved(LandingAddr);
94e8d8bef9SDimitry Andric     } else {
955ffd83dbSDimitry Andric       NotifyLandingResolved(reportCallThroughError(Result.takeError()));
96e8d8bef9SDimitry Andric     }
97e8d8bef9SDimitry Andric   };
98e8d8bef9SDimitry Andric 
99e8d8bef9SDimitry Andric   ES.lookup(LookupKind::Static,
100e8d8bef9SDimitry Andric             makeJITDylibSearchOrder(Entry->SourceJD,
101e8d8bef9SDimitry Andric                                     JITDylibLookupFlags::MatchAllSymbols),
102e8d8bef9SDimitry Andric             std::move(SLS), SymbolState::Ready, std::move(Callback),
1035ffd83dbSDimitry Andric             NoDependenciesToRegister);
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric Expected<std::unique_ptr<LazyCallThroughManager>>
createLocalLazyCallThroughManager(const Triple & T,ExecutionSession & ES,ExecutorAddr ErrorHandlerAddr)1070b57cec5SDimitry Andric createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
10806c3fb27SDimitry Andric                                   ExecutorAddr ErrorHandlerAddr) {
1090b57cec5SDimitry Andric   switch (T.getArch()) {
1100b57cec5SDimitry Andric   default:
1110b57cec5SDimitry Andric     return make_error<StringError>(
1120b57cec5SDimitry Andric         std::string("No callback manager available for ") + T.str(),
1130b57cec5SDimitry Andric         inconvertibleErrorCode());
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   case Triple::aarch64:
1168bcb0991SDimitry Andric   case Triple::aarch64_32:
1170b57cec5SDimitry Andric     return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
1180b57cec5SDimitry Andric                                                            ErrorHandlerAddr);
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   case Triple::x86:
1210b57cec5SDimitry Andric     return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
1220b57cec5SDimitry Andric 
123bdd1243dSDimitry Andric   case Triple::loongarch64:
124bdd1243dSDimitry Andric     return LocalLazyCallThroughManager::Create<OrcLoongArch64>(
125bdd1243dSDimitry Andric         ES, ErrorHandlerAddr);
126bdd1243dSDimitry Andric 
1270b57cec5SDimitry Andric   case Triple::mips:
1280b57cec5SDimitry Andric     return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
1290b57cec5SDimitry Andric                                                             ErrorHandlerAddr);
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   case Triple::mipsel:
1320b57cec5SDimitry Andric     return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
1330b57cec5SDimitry Andric                                                             ErrorHandlerAddr);
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   case Triple::mips64:
1360b57cec5SDimitry Andric   case Triple::mips64el:
1370b57cec5SDimitry Andric     return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
1380b57cec5SDimitry Andric 
13981ad6265SDimitry Andric   case Triple::riscv64:
14081ad6265SDimitry Andric     return LocalLazyCallThroughManager::Create<OrcRiscv64>(ES,
14181ad6265SDimitry Andric                                                            ErrorHandlerAddr);
14281ad6265SDimitry Andric 
1430b57cec5SDimitry Andric   case Triple::x86_64:
1440b57cec5SDimitry Andric     if (T.getOS() == Triple::OSType::Win32)
1450b57cec5SDimitry Andric       return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
1460b57cec5SDimitry Andric           ES, ErrorHandlerAddr);
1470b57cec5SDimitry Andric     else
1480b57cec5SDimitry Andric       return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
1490b57cec5SDimitry Andric           ES, ErrorHandlerAddr);
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
LazyReexportsMaterializationUnit(LazyCallThroughManager & LCTManager,IndirectStubsManager & ISManager,JITDylib & SourceJD,SymbolAliasMap CallableAliases,ImplSymbolMap * SrcJDLoc)1530b57cec5SDimitry Andric LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
1540b57cec5SDimitry Andric     LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
155e8d8bef9SDimitry Andric     JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)
1560eae32dcSDimitry Andric     : MaterializationUnit(extractFlags(CallableAliases)),
1570b57cec5SDimitry Andric       LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
1585ffd83dbSDimitry Andric       CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}
1590b57cec5SDimitry Andric 
getName() const1600b57cec5SDimitry Andric StringRef LazyReexportsMaterializationUnit::getName() const {
1610b57cec5SDimitry Andric   return "<Lazy Reexports>";
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
materialize(std::unique_ptr<MaterializationResponsibility> R)1640b57cec5SDimitry Andric void LazyReexportsMaterializationUnit::materialize(
165e8d8bef9SDimitry Andric     std::unique_ptr<MaterializationResponsibility> R) {
166e8d8bef9SDimitry Andric   auto RequestedSymbols = R->getRequestedSymbols();
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   SymbolAliasMap RequestedAliases;
1690b57cec5SDimitry Andric   for (auto &RequestedSymbol : RequestedSymbols) {
1700b57cec5SDimitry Andric     auto I = CallableAliases.find(RequestedSymbol);
1710b57cec5SDimitry Andric     assert(I != CallableAliases.end() && "Symbol not found in alias map?");
1720b57cec5SDimitry Andric     RequestedAliases[I->first] = std::move(I->second);
1730b57cec5SDimitry Andric     CallableAliases.erase(I);
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   if (!CallableAliases.empty())
177e8d8bef9SDimitry Andric     if (auto Err = R->replace(lazyReexports(LCTManager, ISManager, SourceJD,
178e8d8bef9SDimitry Andric                                             std::move(CallableAliases),
179e8d8bef9SDimitry Andric                                             AliaseeTable))) {
180e8d8bef9SDimitry Andric       R->getExecutionSession().reportError(std::move(Err));
181e8d8bef9SDimitry Andric       R->failMaterialization();
182e8d8bef9SDimitry Andric       return;
183e8d8bef9SDimitry Andric     }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   IndirectStubsManager::StubInitsMap StubInits;
1860b57cec5SDimitry Andric   for (auto &Alias : RequestedAliases) {
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric     auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
1895ffd83dbSDimitry Andric         SourceJD, Alias.second.Aliasee,
1905ffd83dbSDimitry Andric         [&ISManager = this->ISManager,
19106c3fb27SDimitry Andric          StubSym = Alias.first](ExecutorAddr ResolvedAddr) -> Error {
1925ffd83dbSDimitry Andric           return ISManager.updatePointer(*StubSym, ResolvedAddr);
1935ffd83dbSDimitry Andric         });
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric     if (!CallThroughTrampoline) {
1960b57cec5SDimitry Andric       SourceJD.getExecutionSession().reportError(
1970b57cec5SDimitry Andric           CallThroughTrampoline.takeError());
198e8d8bef9SDimitry Andric       R->failMaterialization();
1990b57cec5SDimitry Andric       return;
2000b57cec5SDimitry Andric     }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric     StubInits[*Alias.first] =
2030b57cec5SDimitry Andric         std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric 
2068bcb0991SDimitry Andric   if (AliaseeTable != nullptr && !RequestedAliases.empty())
2078bcb0991SDimitry Andric     AliaseeTable->trackImpls(RequestedAliases, &SourceJD);
2088bcb0991SDimitry Andric 
2090b57cec5SDimitry Andric   if (auto Err = ISManager.createStubs(StubInits)) {
2100b57cec5SDimitry Andric     SourceJD.getExecutionSession().reportError(std::move(Err));
211e8d8bef9SDimitry Andric     R->failMaterialization();
2120b57cec5SDimitry Andric     return;
2130b57cec5SDimitry Andric   }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   SymbolMap Stubs;
2160b57cec5SDimitry Andric   for (auto &Alias : RequestedAliases)
2170b57cec5SDimitry Andric     Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
2180b57cec5SDimitry Andric 
2198bcb0991SDimitry Andric   // No registered dependencies, so these calls cannot fail.
220e8d8bef9SDimitry Andric   cantFail(R->notifyResolved(Stubs));
221*0fca6ea1SDimitry Andric   cantFail(R->notifyEmitted({}));
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric 
discard(const JITDylib & JD,const SymbolStringPtr & Name)2240b57cec5SDimitry Andric void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
2250b57cec5SDimitry Andric                                                const SymbolStringPtr &Name) {
2260b57cec5SDimitry Andric   assert(CallableAliases.count(Name) &&
2270b57cec5SDimitry Andric          "Symbol not covered by this MaterializationUnit");
2280b57cec5SDimitry Andric   CallableAliases.erase(Name);
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric 
2310eae32dcSDimitry Andric MaterializationUnit::Interface
extractFlags(const SymbolAliasMap & Aliases)2320b57cec5SDimitry Andric LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
2330b57cec5SDimitry Andric   SymbolFlagsMap SymbolFlags;
2340b57cec5SDimitry Andric   for (auto &KV : Aliases) {
2350b57cec5SDimitry Andric     assert(KV.second.AliasFlags.isCallable() &&
2360b57cec5SDimitry Andric            "Lazy re-exports must be callable symbols");
2370b57cec5SDimitry Andric     SymbolFlags[KV.first] = KV.second.AliasFlags;
2380b57cec5SDimitry Andric   }
2390eae32dcSDimitry Andric   return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric } // End namespace orc.
2430b57cec5SDimitry Andric } // End namespace llvm.
244