mirror of
https://github.com/RPCS3/llvm.git
synced 2026-08-27 21:00:01 -04:00
54d4881c35
This adds two arguments to the main ExecutionSession::lookup method: MatchNonExportedInJD, and MatchNonExported. These control whether and where hidden symbols should be matched when searching a list of JITDylibs. A similar effect could have been achieved by filtering search results, but this would have involved materializing symbol definitions (since materialization is triggered on lookup) only to throw the results away, among other issues. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@344467 91177308-0d34-0410-b5e6-96231b3b80d8
216 lines
6.9 KiB
C++
216 lines
6.9 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) {}
|
|
|
|
void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) {
|
|
auto &ES = MR.getTargetJITDylib().getExecutionSession();
|
|
SymbolNameSet InternedSymbols;
|
|
|
|
// Intern the requested symbols: lookup takes interned strings.
|
|
for (auto &S : Symbols)
|
|
InternedSymbols.insert(ES.intern(S));
|
|
|
|
// Build an OnResolve callback to unwrap the interned strings and pass them
|
|
// to the OnResolved callback.
|
|
// FIXME: Switch to move capture of OnResolved once we have c++14.
|
|
auto OnResolvedWithUnwrap =
|
|
[OnResolved](Expected<SymbolMap> InternedResult) {
|
|
if (!InternedResult) {
|
|
OnResolved(InternedResult.takeError());
|
|
return;
|
|
}
|
|
|
|
LookupResult Result;
|
|
for (auto &KV : *InternedResult)
|
|
Result[*KV.first] = std::move(KV.second);
|
|
OnResolved(Result);
|
|
};
|
|
|
|
// We're not waiting for symbols to be ready. Just log any errors.
|
|
auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
|
|
|
|
// Register dependencies for all symbols contained in this set.
|
|
auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
|
|
MR.addDependenciesForAll(Deps);
|
|
};
|
|
|
|
MR.getTargetJITDylib().withSearchOrderDo([&](const JITDylibList &JDs) {
|
|
ES.lookup(JDs, InternedSymbols, OnResolvedWithUnwrap, OnReady,
|
|
RegisterDependencies, &MR.getTargetJITDylib());
|
|
});
|
|
}
|
|
|
|
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");
|
|
|
|
// This method launches an asynchronous link step that will fulfill our
|
|
// materialization responsibility. We need to switch R to be heap
|
|
// allocated before that happens so it can live as long as the asynchronous
|
|
// link needs it to (i.e. it must be able to outlive this method).
|
|
auto SharedR = std::make_shared<MaterializationResponsibility>(std::move(R));
|
|
|
|
auto &ES = getExecutionSession();
|
|
|
|
auto Obj = object::ObjectFile::createObjectFile(*O);
|
|
|
|
if (!Obj) {
|
|
getExecutionSession().reportError(Obj.takeError());
|
|
SharedR->failMaterialization();
|
|
return;
|
|
}
|
|
|
|
// Collect the internal symbols from the object file: We will need to
|
|
// filter these later.
|
|
auto InternalSymbols = std::make_shared<std::set<StringRef>>();
|
|
{
|
|
for (auto &Sym : (*Obj)->symbols()) {
|
|
if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) {
|
|
if (auto SymName = Sym.getName())
|
|
InternalSymbols->insert(*SymName);
|
|
else {
|
|
ES.reportError(SymName.takeError());
|
|
R.failMaterialization();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
auto MemoryManager = GetMemoryManager(K);
|
|
auto &MemMgr = *MemoryManager;
|
|
{
|
|
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
|
|
|
|
assert(!MemMgrs.count(K) &&
|
|
"A memory manager already exists for this key?");
|
|
MemMgrs[K] = std::move(MemoryManager);
|
|
}
|
|
|
|
JITDylibSearchOrderResolver Resolver(*SharedR);
|
|
|
|
/* Thoughts on proper cross-dylib weak symbol handling:
|
|
*
|
|
* Change selection of canonical defs to be a manually triggered process, and
|
|
* add a 'canonical' bit to symbol definitions. When canonical def selection
|
|
* is triggered, sweep the JITDylibs to mark defs as canonical, discard
|
|
* duplicate defs.
|
|
*/
|
|
jitLinkForORC(
|
|
**Obj, std::move(O), MemMgr, Resolver, ProcessAllSections,
|
|
[this, K, SharedR, &Obj, InternalSymbols](
|
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
|
|
std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {
|
|
return onObjLoad(K, *SharedR, **Obj, std::move(LoadedObjInfo),
|
|
ResolvedSymbols, *InternalSymbols);
|
|
},
|
|
[this, K, SharedR](Error Err) {
|
|
onObjEmit(K, *SharedR, std::move(Err));
|
|
});
|
|
}
|
|
|
|
Error RTDyldObjectLinkingLayer2::onObjLoad(
|
|
VModuleKey K, MaterializationResponsibility &R, object::ObjectFile &Obj,
|
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
|
|
std::map<StringRef, JITEvaluatedSymbol> Resolved,
|
|
std::set<StringRef> &InternalSymbols) {
|
|
SymbolFlagsMap ExtraSymbolsToClaim;
|
|
SymbolMap Symbols;
|
|
for (auto &KV : Resolved) {
|
|
// 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 = getExecutionSession().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))
|
|
return Err;
|
|
|
|
R.resolve(Symbols);
|
|
|
|
if (NotifyLoaded)
|
|
NotifyLoaded(K, Obj, *LoadedObjInfo);
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
void RTDyldObjectLinkingLayer2::onObjEmit(VModuleKey K,
|
|
MaterializationResponsibility &R,
|
|
Error Err) {
|
|
if (Err) {
|
|
getExecutionSession().reportError(std::move(Err));
|
|
R.failMaterialization();
|
|
return;
|
|
}
|
|
|
|
R.emit();
|
|
|
|
if (NotifyEmitted)
|
|
NotifyEmitted(K);
|
|
}
|
|
|
|
} // End namespace orc.
|
|
} // End namespace llvm.
|