Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
35294 views
//===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ExecutionEngine/Orc/LazyReexports.h"910#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"11#include "llvm/TargetParser/Triple.h"1213#define DEBUG_TYPE "orc"1415namespace llvm {16namespace orc {1718LazyCallThroughManager::LazyCallThroughManager(ExecutionSession &ES,19ExecutorAddr ErrorHandlerAddr,20TrampolinePool *TP)21: ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(TP) {}2223Expected<ExecutorAddr> LazyCallThroughManager::getCallThroughTrampoline(24JITDylib &SourceJD, SymbolStringPtr SymbolName,25NotifyResolvedFunction NotifyResolved) {26assert(TP && "TrampolinePool not set");2728std::lock_guard<std::mutex> Lock(LCTMMutex);29auto Trampoline = TP->getTrampoline();3031if (!Trampoline)32return Trampoline.takeError();3334Reexports[*Trampoline] = ReexportsEntry{&SourceJD, std::move(SymbolName)};35Notifiers[*Trampoline] = std::move(NotifyResolved);36return *Trampoline;37}3839ExecutorAddr LazyCallThroughManager::reportCallThroughError(Error Err) {40ES.reportError(std::move(Err));41return ErrorHandlerAddr;42}4344Expected<LazyCallThroughManager::ReexportsEntry>45LazyCallThroughManager::findReexport(ExecutorAddr TrampolineAddr) {46std::lock_guard<std::mutex> Lock(LCTMMutex);47auto I = Reexports.find(TrampolineAddr);48if (I == Reexports.end())49return createStringError(inconvertibleErrorCode(),50"Missing reexport for trampoline address %p" +51formatv("{0:x}", TrampolineAddr));52return I->second;53}5455Error LazyCallThroughManager::notifyResolved(ExecutorAddr TrampolineAddr,56ExecutorAddr ResolvedAddr) {57NotifyResolvedFunction NotifyResolved;58{59std::lock_guard<std::mutex> Lock(LCTMMutex);60auto I = Notifiers.find(TrampolineAddr);61if (I != Notifiers.end()) {62NotifyResolved = std::move(I->second);63Notifiers.erase(I);64}65}6667return NotifyResolved ? NotifyResolved(ResolvedAddr) : Error::success();68}6970void LazyCallThroughManager::resolveTrampolineLandingAddress(71ExecutorAddr TrampolineAddr,72NotifyLandingResolvedFunction NotifyLandingResolved) {7374auto Entry = findReexport(TrampolineAddr);75if (!Entry)76return NotifyLandingResolved(reportCallThroughError(Entry.takeError()));7778// Declaring SLS and the callback outside of the call to ES.lookup is a79// workaround to fix build failures on AIX and on z/OS platforms.80SymbolLookupSet SLS({Entry->SymbolName});81auto Callback = [this, TrampolineAddr, SymbolName = Entry->SymbolName,82NotifyLandingResolved = std::move(NotifyLandingResolved)](83Expected<SymbolMap> Result) mutable {84if (Result) {85assert(Result->size() == 1 && "Unexpected result size");86assert(Result->count(SymbolName) && "Unexpected result value");87ExecutorAddr LandingAddr = (*Result)[SymbolName].getAddress();8889if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))90NotifyLandingResolved(reportCallThroughError(std::move(Err)));91else92NotifyLandingResolved(LandingAddr);93} else {94NotifyLandingResolved(reportCallThroughError(Result.takeError()));95}96};9798ES.lookup(LookupKind::Static,99makeJITDylibSearchOrder(Entry->SourceJD,100JITDylibLookupFlags::MatchAllSymbols),101std::move(SLS), SymbolState::Ready, std::move(Callback),102NoDependenciesToRegister);103}104105Expected<std::unique_ptr<LazyCallThroughManager>>106createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,107ExecutorAddr ErrorHandlerAddr) {108switch (T.getArch()) {109default:110return make_error<StringError>(111std::string("No callback manager available for ") + T.str(),112inconvertibleErrorCode());113114case Triple::aarch64:115case Triple::aarch64_32:116return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,117ErrorHandlerAddr);118119case Triple::x86:120return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);121122case Triple::loongarch64:123return LocalLazyCallThroughManager::Create<OrcLoongArch64>(124ES, ErrorHandlerAddr);125126case Triple::mips:127return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,128ErrorHandlerAddr);129130case Triple::mipsel:131return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,132ErrorHandlerAddr);133134case Triple::mips64:135case Triple::mips64el:136return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);137138case Triple::riscv64:139return LocalLazyCallThroughManager::Create<OrcRiscv64>(ES,140ErrorHandlerAddr);141142case Triple::x86_64:143if (T.getOS() == Triple::OSType::Win32)144return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(145ES, ErrorHandlerAddr);146else147return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(148ES, ErrorHandlerAddr);149}150}151152LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(153LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,154JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)155: MaterializationUnit(extractFlags(CallableAliases)),156LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),157CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}158159StringRef LazyReexportsMaterializationUnit::getName() const {160return "<Lazy Reexports>";161}162163void LazyReexportsMaterializationUnit::materialize(164std::unique_ptr<MaterializationResponsibility> R) {165auto RequestedSymbols = R->getRequestedSymbols();166167SymbolAliasMap RequestedAliases;168for (auto &RequestedSymbol : RequestedSymbols) {169auto I = CallableAliases.find(RequestedSymbol);170assert(I != CallableAliases.end() && "Symbol not found in alias map?");171RequestedAliases[I->first] = std::move(I->second);172CallableAliases.erase(I);173}174175if (!CallableAliases.empty())176if (auto Err = R->replace(lazyReexports(LCTManager, ISManager, SourceJD,177std::move(CallableAliases),178AliaseeTable))) {179R->getExecutionSession().reportError(std::move(Err));180R->failMaterialization();181return;182}183184IndirectStubsManager::StubInitsMap StubInits;185for (auto &Alias : RequestedAliases) {186187auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(188SourceJD, Alias.second.Aliasee,189[&ISManager = this->ISManager,190StubSym = Alias.first](ExecutorAddr ResolvedAddr) -> Error {191return ISManager.updatePointer(*StubSym, ResolvedAddr);192});193194if (!CallThroughTrampoline) {195SourceJD.getExecutionSession().reportError(196CallThroughTrampoline.takeError());197R->failMaterialization();198return;199}200201StubInits[*Alias.first] =202std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);203}204205if (AliaseeTable != nullptr && !RequestedAliases.empty())206AliaseeTable->trackImpls(RequestedAliases, &SourceJD);207208if (auto Err = ISManager.createStubs(StubInits)) {209SourceJD.getExecutionSession().reportError(std::move(Err));210R->failMaterialization();211return;212}213214SymbolMap Stubs;215for (auto &Alias : RequestedAliases)216Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);217218// No registered dependencies, so these calls cannot fail.219cantFail(R->notifyResolved(Stubs));220cantFail(R->notifyEmitted({}));221}222223void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,224const SymbolStringPtr &Name) {225assert(CallableAliases.count(Name) &&226"Symbol not covered by this MaterializationUnit");227CallableAliases.erase(Name);228}229230MaterializationUnit::Interface231LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {232SymbolFlagsMap SymbolFlags;233for (auto &KV : Aliases) {234assert(KV.second.AliasFlags.isCallable() &&235"Lazy re-exports must be callable symbols");236SymbolFlags[KV.first] = KV.second.AliasFlags;237}238return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);239}240241} // End namespace orc.242} // End namespace llvm.243244245