(1) Print debugging output under a session lock to avoid garbled messages when compiling on multiple threads. (2) Name MaterializationUnits, add an ostream operator for them, and so they can be easily referenced in debugging output, and have that ostream operator optionally print code/data/hidden symbols provided by that materialization unit based on command line options. llvm-svn: 343323
209 lines
6.7 KiB
C++
209 lines
6.7 KiB
C++
//===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#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 {
|
|
|
|
void LazyCallThroughManager::NotifyResolvedFunction::anchor() {}
|
|
|
|
LazyCallThroughManager::LazyCallThroughManager(
|
|
ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr,
|
|
std::unique_ptr<TrampolinePool> TP)
|
|
: ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(std::move(TP)) {}
|
|
|
|
Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
|
|
JITDylib &SourceJD, SymbolStringPtr SymbolName,
|
|
std::shared_ptr<NotifyResolvedFunction> NotifyResolved) {
|
|
std::lock_guard<std::mutex> Lock(LCTMMutex);
|
|
auto Trampoline = TP->getTrampoline();
|
|
|
|
if (!Trampoline)
|
|
return Trampoline.takeError();
|
|
|
|
Reexports[*Trampoline] = std::make_pair(&SourceJD, std::move(SymbolName));
|
|
Notifiers[*Trampoline] = std::move(NotifyResolved);
|
|
return *Trampoline;
|
|
}
|
|
|
|
JITTargetAddress
|
|
LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
|
|
JITDylib *SourceJD = nullptr;
|
|
SymbolStringPtr SymbolName;
|
|
|
|
{
|
|
std::lock_guard<std::mutex> Lock(LCTMMutex);
|
|
auto I = Reexports.find(TrampolineAddr);
|
|
if (I == Reexports.end())
|
|
return ErrorHandlerAddr;
|
|
SourceJD = I->second.first;
|
|
SymbolName = I->second.second;
|
|
}
|
|
|
|
auto LookupResult =
|
|
ES.lookup({SourceJD}, {SymbolName}, NoDependenciesToRegister);
|
|
|
|
if (!LookupResult) {
|
|
ES.reportError(LookupResult.takeError());
|
|
return ErrorHandlerAddr;
|
|
}
|
|
|
|
assert(LookupResult->size() == 1 && "Unexpected number of results");
|
|
assert(LookupResult->count(SymbolName) && "Unexpected result");
|
|
|
|
auto ResolvedAddr = LookupResult->begin()->second.getAddress();
|
|
|
|
std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
|
|
{
|
|
std::lock_guard<std::mutex> Lock(LCTMMutex);
|
|
auto I = Notifiers.find(TrampolineAddr);
|
|
if (I != Notifiers.end()) {
|
|
NotifyResolved = I->second;
|
|
Notifiers.erase(I);
|
|
}
|
|
}
|
|
|
|
if (NotifyResolved) {
|
|
if (auto Err = (*NotifyResolved)(*SourceJD, SymbolName, ResolvedAddr)) {
|
|
ES.reportError(std::move(Err));
|
|
return ErrorHandlerAddr;
|
|
}
|
|
}
|
|
|
|
return ResolvedAddr;
|
|
}
|
|
|
|
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:
|
|
return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
|
|
ErrorHandlerAddr);
|
|
|
|
case Triple::x86:
|
|
return LocalLazyCallThroughManager::Create<OrcI386>(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::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)
|
|
: MaterializationUnit(extractFlags(CallableAliases)),
|
|
LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
|
|
CallableAliases(std::move(CallableAliases)),
|
|
NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
|
|
[&ISManager](JITDylib &JD, const SymbolStringPtr &SymbolName,
|
|
JITTargetAddress ResolvedAddr) {
|
|
return ISManager.updatePointer(*SymbolName, ResolvedAddr);
|
|
})) {}
|
|
|
|
StringRef LazyReexportsMaterializationUnit::getName() const {
|
|
return "<Lazy Reexports>";
|
|
}
|
|
|
|
void LazyReexportsMaterializationUnit::materialize(
|
|
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())
|
|
R.replace(lazyReexports(LCTManager, ISManager, SourceJD,
|
|
std::move(CallableAliases)));
|
|
|
|
IndirectStubsManager::StubInitsMap StubInits;
|
|
for (auto &Alias : RequestedAliases) {
|
|
|
|
auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
|
|
SourceJD, Alias.second.Aliasee, NotifyResolved);
|
|
|
|
if (!CallThroughTrampoline) {
|
|
SourceJD.getExecutionSession().reportError(
|
|
CallThroughTrampoline.takeError());
|
|
R.failMaterialization();
|
|
return;
|
|
}
|
|
|
|
StubInits[*Alias.first] =
|
|
std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
|
|
}
|
|
|
|
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);
|
|
|
|
R.resolve(Stubs);
|
|
R.emit();
|
|
}
|
|
|
|
void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
|
|
SymbolStringPtr Name) {
|
|
assert(CallableAliases.count(Name) &&
|
|
"Symbol not covered by this MaterializationUnit");
|
|
CallableAliases.erase(Name);
|
|
}
|
|
|
|
SymbolFlagsMap
|
|
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 SymbolFlags;
|
|
}
|
|
|
|
} // End namespace orc.
|
|
} // End namespace llvm.
|