123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ExecutionEngine/Orc/LazyReexports.h"
- #include "llvm/ADT/Triple.h"
- #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
- #define DEBUG_TYPE "orc"
- namespace llvm {
- namespace orc {
- LazyCallThroughManager::LazyCallThroughManager(
- ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr, TrampolinePool *TP)
- : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(TP) {}
- Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
- JITDylib &SourceJD, SymbolStringPtr SymbolName,
- NotifyResolvedFunction NotifyResolved) {
- assert(TP && "TrampolinePool not set");
- std::lock_guard<std::mutex> Lock(LCTMMutex);
- auto Trampoline = TP->getTrampoline();
- if (!Trampoline)
- return Trampoline.takeError();
- Reexports[*Trampoline] = ReexportsEntry{&SourceJD, std::move(SymbolName)};
- Notifiers[*Trampoline] = std::move(NotifyResolved);
- return *Trampoline;
- }
- JITTargetAddress LazyCallThroughManager::reportCallThroughError(Error Err) {
- ES.reportError(std::move(Err));
- return ErrorHandlerAddr;
- }
- Expected<LazyCallThroughManager::ReexportsEntry>
- LazyCallThroughManager::findReexport(JITTargetAddress TrampolineAddr) {
- std::lock_guard<std::mutex> Lock(LCTMMutex);
- auto I = Reexports.find(TrampolineAddr);
- if (I == Reexports.end())
- return createStringError(inconvertibleErrorCode(),
- "Missing reexport for trampoline address %p",
- TrampolineAddr);
- return I->second;
- }
- Error LazyCallThroughManager::notifyResolved(JITTargetAddress TrampolineAddr,
- JITTargetAddress ResolvedAddr) {
- NotifyResolvedFunction NotifyResolved;
- {
- std::lock_guard<std::mutex> Lock(LCTMMutex);
- auto I = Notifiers.find(TrampolineAddr);
- if (I != Notifiers.end()) {
- NotifyResolved = std::move(I->second);
- Notifiers.erase(I);
- }
- }
- return NotifyResolved ? NotifyResolved(ResolvedAddr) : Error::success();
- }
- void LazyCallThroughManager::resolveTrampolineLandingAddress(
- JITTargetAddress TrampolineAddr,
- NotifyLandingResolvedFunction NotifyLandingResolved) {
- auto Entry = findReexport(TrampolineAddr);
- if (!Entry)
- return NotifyLandingResolved(reportCallThroughError(Entry.takeError()));
- // Declaring SLS and the callback outside of the call to ES.lookup is a
- // workaround to fix build failures on AIX and on z/OS platforms.
- SymbolLookupSet SLS({Entry->SymbolName});
- auto Callback = [this, TrampolineAddr, SymbolName = Entry->SymbolName,
- NotifyLandingResolved = std::move(NotifyLandingResolved)](
- Expected<SymbolMap> Result) mutable {
- if (Result) {
- assert(Result->size() == 1 && "Unexpected result size");
- assert(Result->count(SymbolName) && "Unexpected result value");
- JITTargetAddress LandingAddr = (*Result)[SymbolName].getAddress();
- if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))
- NotifyLandingResolved(reportCallThroughError(std::move(Err)));
- else
- NotifyLandingResolved(LandingAddr);
- } else {
- NotifyLandingResolved(reportCallThroughError(Result.takeError()));
- }
- };
- ES.lookup(LookupKind::Static,
- makeJITDylibSearchOrder(Entry->SourceJD,
- JITDylibLookupFlags::MatchAllSymbols),
- std::move(SLS), SymbolState::Ready, std::move(Callback),
- NoDependenciesToRegister);
- }
- Expected<std::unique_ptr<LazyCallThroughManager>>
- createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
- JITTargetAddress ErrorHandlerAddr) {
- switch (T.getArch()) {
- default:
- return make_error<StringError>(
- std::string("No callback manager available for ") + T.str(),
- inconvertibleErrorCode());
- case Triple::aarch64:
- case Triple::aarch64_32:
- return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
- ErrorHandlerAddr);
- case Triple::x86:
- return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
- case Triple::loongarch64:
- return LocalLazyCallThroughManager::Create<OrcLoongArch64>(
- ES, ErrorHandlerAddr);
- case Triple::mips:
- return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
- ErrorHandlerAddr);
- case Triple::mipsel:
- return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
- ErrorHandlerAddr);
- case Triple::mips64:
- case Triple::mips64el:
- return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
- case Triple::riscv64:
- return LocalLazyCallThroughManager::Create<OrcRiscv64>(ES,
- ErrorHandlerAddr);
- case Triple::x86_64:
- if (T.getOS() == Triple::OSType::Win32)
- return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
- ES, ErrorHandlerAddr);
- else
- return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
- ES, ErrorHandlerAddr);
- }
- }
- LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
- LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
- JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)
- : MaterializationUnit(extractFlags(CallableAliases)),
- LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
- CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}
- StringRef LazyReexportsMaterializationUnit::getName() const {
- return "<Lazy Reexports>";
- }
- void LazyReexportsMaterializationUnit::materialize(
- std::unique_ptr<MaterializationResponsibility> R) {
- auto RequestedSymbols = R->getRequestedSymbols();
- SymbolAliasMap RequestedAliases;
- for (auto &RequestedSymbol : RequestedSymbols) {
- auto I = CallableAliases.find(RequestedSymbol);
- assert(I != CallableAliases.end() && "Symbol not found in alias map?");
- RequestedAliases[I->first] = std::move(I->second);
- CallableAliases.erase(I);
- }
- if (!CallableAliases.empty())
- if (auto Err = R->replace(lazyReexports(LCTManager, ISManager, SourceJD,
- std::move(CallableAliases),
- AliaseeTable))) {
- R->getExecutionSession().reportError(std::move(Err));
- R->failMaterialization();
- return;
- }
- IndirectStubsManager::StubInitsMap StubInits;
- for (auto &Alias : RequestedAliases) {
- auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
- SourceJD, Alias.second.Aliasee,
- [&ISManager = this->ISManager,
- StubSym = Alias.first](JITTargetAddress ResolvedAddr) -> Error {
- return ISManager.updatePointer(*StubSym, ResolvedAddr);
- });
- if (!CallThroughTrampoline) {
- SourceJD.getExecutionSession().reportError(
- CallThroughTrampoline.takeError());
- R->failMaterialization();
- return;
- }
- StubInits[*Alias.first] =
- std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
- }
- if (AliaseeTable != nullptr && !RequestedAliases.empty())
- AliaseeTable->trackImpls(RequestedAliases, &SourceJD);
- if (auto Err = ISManager.createStubs(StubInits)) {
- SourceJD.getExecutionSession().reportError(std::move(Err));
- R->failMaterialization();
- return;
- }
- SymbolMap Stubs;
- for (auto &Alias : RequestedAliases)
- Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
- // No registered dependencies, so these calls cannot fail.
- cantFail(R->notifyResolved(Stubs));
- cantFail(R->notifyEmitted());
- }
- void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
- const SymbolStringPtr &Name) {
- assert(CallableAliases.count(Name) &&
- "Symbol not covered by this MaterializationUnit");
- CallableAliases.erase(Name);
- }
- MaterializationUnit::Interface
- LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
- SymbolFlagsMap SymbolFlags;
- for (auto &KV : Aliases) {
- assert(KV.second.AliasFlags.isCallable() &&
- "Lazy re-exports must be callable symbols");
- SymbolFlags[KV.first] = KV.second.AliasFlags;
- }
- return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
- }
- } // End namespace orc.
- } // End namespace llvm.
|