Files
clang-p2996/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
Lang Hames 6d32002e2b [ORC] Add utilities to RTDyldObjectLinkingLayer2 to simplify symbol flag
management and materialization responsibility registration.

The setOverrideObjectFlagsWithResponsibilityFlags method instructs
RTDyldObjectlinkingLayer2 to override the symbol flags produced by RuntimeDyld with
the flags provided by the MaterializationResponsibility instance. This can be used
to enable symbol visibility (hidden/exported) for COFF object files, which do not
currently support the SF_Exported flag.

The setAutoClaimResponsibilityForObjectSymbols method instructs
RTDyldObjectLinkingLayer2 to claim responsibility for any symbols provided by a
given object file that were not already in the MaterializationResponsibility
instance. Setting this flag allows higher-level program representations (e.g.
LLVM IR) to be added based on only a subset of the symbols they provide, without
having to write intervening layers to scan and add the additional symbols. This
trades diagnostic quality for convenience however: If all symbols are enumerated
up-front then clashes can be detected and reported early. If this option is set,
clashes for the additional symbols may not be detected until late, and detection
may depend on the flow of control through JIT'd code.

llvm-svn: 341154
2018-08-31 00:53:17 +00:00

192 lines
5.5 KiB
C++

//===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===//
//
// 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/RTDyldObjectLinkingLayer.h"
namespace {
using namespace llvm;
using namespace llvm::orc;
class JITDylibSearchOrderResolver : public JITSymbolResolver {
public:
JITDylibSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {}
Expected<LookupResult> lookup(const LookupSet &Symbols) {
auto &ES = MR.getTargetJITDylib().getExecutionSession();
SymbolNameSet InternedSymbols;
for (auto &S : Symbols)
InternedSymbols.insert(ES.getSymbolStringPool().intern(S));
auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
MR.addDependenciesForAll(Deps);
};
auto InternedResult =
MR.getTargetJITDylib().withSearchOrderDo([&](const JITDylibList &JDs) {
return ES.lookup(JDs, InternedSymbols, RegisterDependencies, false);
});
if (!InternedResult)
return InternedResult.takeError();
LookupResult Result;
for (auto &KV : *InternedResult)
Result[*KV.first] = std::move(KV.second);
return Result;
}
Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) {
LookupSet Result;
for (auto &KV : MR.getSymbols()) {
if (Symbols.count(*KV.first))
Result.insert(*KV.first);
}
return Result;
}
private:
MaterializationResponsibility &MR;
};
} // end anonymous namespace
namespace llvm {
namespace orc {
RTDyldObjectLinkingLayer2::RTDyldObjectLinkingLayer2(
ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
NotifyLoadedFunction NotifyLoaded, NotifyEmittedFunction NotifyEmitted)
: ObjectLayer(ES), GetMemoryManager(GetMemoryManager),
NotifyLoaded(std::move(NotifyLoaded)),
NotifyEmitted(std::move(NotifyEmitted)) {}
void RTDyldObjectLinkingLayer2::emit(MaterializationResponsibility R,
VModuleKey K,
std::unique_ptr<MemoryBuffer> O) {
assert(O && "Object must not be null");
auto &ES = getExecutionSession();
auto ObjFile = object::ObjectFile::createObjectFile(*O);
if (!ObjFile) {
getExecutionSession().reportError(ObjFile.takeError());
R.failMaterialization();
}
auto MemoryManager = GetMemoryManager(K);
JITDylibSearchOrderResolver Resolver(R);
auto RTDyld = llvm::make_unique<RuntimeDyld>(*MemoryManager, Resolver);
RTDyld->setProcessAllSections(ProcessAllSections);
{
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
assert(!ActiveRTDylds.count(K) &&
"An active RTDyld already exists for this key?");
ActiveRTDylds[K] = RTDyld.get();
assert(!MemMgrs.count(K) &&
"A memory manager already exists for this key?");
MemMgrs[K] = std::move(MemoryManager);
}
auto Info = RTDyld->loadObject(**ObjFile);
{
std::set<StringRef> InternalSymbols;
for (auto &Sym : (*ObjFile)->symbols()) {
if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) {
if (auto SymName = Sym.getName())
InternalSymbols.insert(*SymName);
else {
ES.reportError(SymName.takeError());
R.failMaterialization();
return;
}
}
}
SymbolFlagsMap ExtraSymbolsToClaim;
SymbolMap Symbols;
for (auto &KV : RTDyld->getSymbolTable()) {
// Scan the symbols and add them to the Symbols map for resolution.
// We never claim internal symbols.
if (InternalSymbols.count(KV.first))
continue;
auto InternedName = ES.getSymbolStringPool().intern(KV.first);
auto Flags = KV.second.getFlags();
// Override object flags and claim responsibility for symbols if
// requested.
if (OverrideObjectFlags || AutoClaimObjectSymbols) {
auto I = R.getSymbols().find(InternedName);
if (OverrideObjectFlags && I != R.getSymbols().end())
Flags = JITSymbolFlags::stripTransientFlags(I->second);
else if (AutoClaimObjectSymbols && I == R.getSymbols().end())
ExtraSymbolsToClaim[InternedName] = Flags;
}
Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
}
if (!ExtraSymbolsToClaim.empty())
if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim)) {
ES.reportError(std::move(Err));
R.failMaterialization();
return;
}
R.resolve(Symbols);
}
if (NotifyLoaded)
NotifyLoaded(K, **ObjFile, *Info);
RTDyld->finalizeWithMemoryManagerLocking();
{
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
ActiveRTDylds.erase(K);
}
if (RTDyld->hasError()) {
ES.reportError(make_error<StringError>(RTDyld->getErrorString(),
inconvertibleErrorCode()));
R.failMaterialization();
return;
}
R.emit();
if (NotifyEmitted)
NotifyEmitted(K);
}
void RTDyldObjectLinkingLayer2::mapSectionAddress(
VModuleKey K, const void *LocalAddress, JITTargetAddress TargetAddr) const {
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
auto ActiveRTDyldItr = ActiveRTDylds.find(K);
assert(ActiveRTDyldItr != ActiveRTDylds.end() &&
"No active RTDyld instance found for key");
ActiveRTDyldItr->second->mapSectionAddress(LocalAddress, TargetAddr);
}
} // End namespace orc.
} // End namespace llvm.