[llvm] [ORC] Add absoluteSymbolsObjectLayer to expose absolute symbols to platform (PR #77008)
Ben Langmuir via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 5 14:02:35 PST 2024
https://github.com/benlangmuir updated https://github.com/llvm/llvm-project/pull/77008
>From 90d9a7ddb3f4d60a90bd3d1fc4d8060b36ada7a6 Mon Sep 17 00:00:00 2001
From: Ben Langmuir <blangmuir at apple.com>
Date: Wed, 3 Jan 2024 15:52:33 -0800
Subject: [PATCH] [ORC] Add absoluteSymbolsLinkGraph to expose absolute symbols
to platform
Adds a function to create a LinkGraph of absolute symbols, and a
callback in dynamic library search generators to enable using it to
expose its symbols to the platform/orc runtime. This allows e.g. using
__orc_rt_run_program to run a precompiled function that was found via
dlsym. Ideally we would use this in llvm-jitlink's own search generator,
but it will require more work to align with the Process/Platform
JITDylib split, so not handled here.
As part of this change we need to handle LinkGraphs that only have
absolute symbols.
---
bolt/lib/Rewrite/JITLinkLinker.cpp | 3 +-
.../llvm/ExecutionEngine/JITLink/JITLink.h | 5 +
.../Orc/EPCDynamicLibrarySearchGenerator.h | 23 +++--
.../llvm/ExecutionEngine/Orc/ExecutionUtils.h | 20 +++-
llvm/lib/ExecutionEngine/JITLink/JITLink.cpp | 35 +++++++
.../JITLink/JITLinkGeneric.cpp | 34 ++++---
.../Orc/EPCDynamicLibrarySearchGenerator.cpp | 12 ++-
.../ExecutionEngine/Orc/ExecutionUtils.cpp | 12 ++-
.../lib/ExecutionEngine/Orc/MachOPlatform.cpp | 2 +
.../Orc/ObjectLinkingLayer.cpp | 14 ++-
.../Orc/ObjectLinkingLayerTest.cpp | 97 +++++++++++++++++++
11 files changed, 222 insertions(+), 35 deletions(-)
diff --git a/bolt/lib/Rewrite/JITLinkLinker.cpp b/bolt/lib/Rewrite/JITLinkLinker.cpp
index 10a3b6a0407ff3..66e129bf1d05db 100644
--- a/bolt/lib/Rewrite/JITLinkLinker.cpp
+++ b/bolt/lib/Rewrite/JITLinkLinker.cpp
@@ -173,7 +173,8 @@ struct JITLinkLinker::Context : jitlink::JITLinkContext {
void notifyFinalized(
jitlink::JITLinkMemoryManager::FinalizedAlloc Alloc) override {
- Linker.Allocs.push_back(std::move(Alloc));
+ if (Alloc)
+ Linker.Allocs.push_back(std::move(Alloc));
++Linker.MM->ObjectsLoaded;
}
};
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
index 8a019492c12d59..f4d2f56c34d9d5 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
#include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h"
@@ -1923,6 +1924,10 @@ void visitExistingEdges(LinkGraph &G, VisitorTs &&...Vs) {
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromObject(MemoryBufferRef ObjectBuffer);
+/// Create a \c LinkGraph defining the given absolute symbols.
+std::unique_ptr<LinkGraph> absoluteSymbolsLinkGraph(const Triple &TT,
+ orc::SymbolMap Symbols);
+
/// Link the given graph.
void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h b/llvm/include/llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h
index 63797edec89e61..e56afe4fe656b3 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h
@@ -25,6 +25,7 @@ class ExecutorProcessControl;
class EPCDynamicLibrarySearchGenerator : public DefinitionGenerator {
public:
using SymbolPredicate = unique_function<bool(const SymbolStringPtr &)>;
+ using AddAbsoluteSymbolsFn = unique_function<Error(JITDylib &, SymbolMap)>;
/// Create a DynamicLibrarySearchGenerator that searches for symbols in the
/// library with the given handle.
@@ -32,24 +33,31 @@ class EPCDynamicLibrarySearchGenerator : public DefinitionGenerator {
/// If the Allow predicate is given then only symbols matching the predicate
/// will be searched for. If the predicate is not given then all symbols will
/// be searched for.
- EPCDynamicLibrarySearchGenerator(ExecutionSession &ES,
- tpctypes::DylibHandle H,
- SymbolPredicate Allow = SymbolPredicate())
- : EPC(ES.getExecutorProcessControl()), H(H), Allow(std::move(Allow)) {}
+ ///
+ /// If \p AddAbsoluteSymbols is provided, it is used to add the symbols to the
+ /// \c JITDylib; otherwise it uses JD.define(absoluteSymbols(...)).
+ EPCDynamicLibrarySearchGenerator(
+ ExecutionSession &ES, tpctypes::DylibHandle H,
+ SymbolPredicate Allow = SymbolPredicate(),
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr)
+ : EPC(ES.getExecutorProcessControl()), H(H), Allow(std::move(Allow)),
+ AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)) {}
/// Permanently loads the library at the given path and, on success, returns
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
/// in the library. On failure returns the reason the library failed to load.
static Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
Load(ExecutionSession &ES, const char *LibraryPath,
- SymbolPredicate Allow = SymbolPredicate());
+ SymbolPredicate Allow = SymbolPredicate(),
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr);
/// Creates a EPCDynamicLibrarySearchGenerator that searches for symbols in
/// the target process.
static Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
GetForTargetProcess(ExecutionSession &ES,
- SymbolPredicate Allow = SymbolPredicate()) {
- return Load(ES, nullptr, std::move(Allow));
+ SymbolPredicate Allow = SymbolPredicate(),
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr) {
+ return Load(ES, nullptr, std::move(Allow), std::move(AddAbsoluteSymbols));
}
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
@@ -60,6 +68,7 @@ class EPCDynamicLibrarySearchGenerator : public DefinitionGenerator {
ExecutorProcessControl &EPC;
tpctypes::DylibHandle H;
SymbolPredicate Allow;
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols;
};
} // end namespace orc
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index 6a43376a5bd909..f7c286bec778b0 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -216,6 +216,7 @@ class ItaniumCXAAtExitSupport {
class DynamicLibrarySearchGenerator : public DefinitionGenerator {
public:
using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>;
+ using AddAbsoluteSymbolsFn = unique_function<Error(JITDylib &, SymbolMap)>;
/// Create a DynamicLibrarySearchGenerator that searches for symbols in the
/// given sys::DynamicLibrary.
@@ -223,22 +224,30 @@ class DynamicLibrarySearchGenerator : public DefinitionGenerator {
/// If the Allow predicate is given then only symbols matching the predicate
/// will be searched for. If the predicate is not given then all symbols will
/// be searched for.
- DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, char GlobalPrefix,
- SymbolPredicate Allow = SymbolPredicate());
+ ///
+ /// If \p AddAbsoluteSymbols is provided, it is used to add the symbols to the
+ /// \c JITDylib; otherwise it uses JD.define(absoluteSymbols(...)).
+ DynamicLibrarySearchGenerator(
+ sys::DynamicLibrary Dylib, char GlobalPrefix,
+ SymbolPredicate Allow = SymbolPredicate(),
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr);
/// Permanently loads the library at the given path and, on success, returns
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
/// in the library. On failure returns the reason the library failed to load.
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
Load(const char *FileName, char GlobalPrefix,
- SymbolPredicate Allow = SymbolPredicate());
+ SymbolPredicate Allow = SymbolPredicate(),
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr);
/// Creates a DynamicLibrarySearchGenerator that searches for symbols in
/// the current process.
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
GetForCurrentProcess(char GlobalPrefix,
- SymbolPredicate Allow = SymbolPredicate()) {
- return Load(nullptr, GlobalPrefix, std::move(Allow));
+ SymbolPredicate Allow = SymbolPredicate(),
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr) {
+ return Load(nullptr, GlobalPrefix, std::move(Allow),
+ std::move(AddAbsoluteSymbols));
}
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
@@ -248,6 +257,7 @@ class DynamicLibrarySearchGenerator : public DefinitionGenerator {
private:
sys::DynamicLibrary Dylib;
SymbolPredicate Allow;
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols;
char GlobalPrefix;
};
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index d86ceb99ded0e6..7f743dba60a934 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -468,6 +468,41 @@ createLinkGraphFromObject(MemoryBufferRef ObjectBuffer) {
};
}
+std::unique_ptr<LinkGraph> absoluteSymbolsLinkGraph(const Triple &TT,
+ orc::SymbolMap Symbols) {
+ unsigned PointerSize;
+ endianness Endianness =
+ TT.isLittleEndian() ? endianness::little : endianness::big;
+ switch (TT.getArch()) {
+ case Triple::aarch64:
+ case llvm::Triple::riscv64:
+ case Triple::x86_64:
+ PointerSize = 8;
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::x86:
+ PointerSize = 4;
+ break;
+ default:
+ llvm::report_fatal_error("unhandled target architecture");
+ }
+
+ static std::atomic<uint64_t> Counter = {0};
+ auto Index = Counter.fetch_add(1, std::memory_order_relaxed);
+ auto G = std::make_unique<LinkGraph>(
+ "<Absolute Symbols " + std::to_string(Index) + ">", TT, PointerSize,
+ Endianness, /*GetEdgeKindName=*/nullptr);
+ for (auto &[Name, Def] : Symbols) {
+ auto &Sym =
+ G->addAbsoluteSymbol(*Name, Def.getAddress(), /*Size=*/0,
+ Linkage::Strong, Scope::Default, /*IsLive=*/true);
+ Sym.setCallable(Def.getFlags().isCallable());
+ }
+
+ return G;
+}
+
void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) {
switch (G->getTargetTriple().getObjectFormat()) {
case Triple::MachO:
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
index 5361272ae79ef7..5494697119fb94 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
@@ -48,15 +48,22 @@ void JITLinkerBase::linkPhase1(std::unique_ptr<JITLinkerBase> Self) {
if (auto Err = runPasses(Passes.PostPrunePasses))
return Ctx->notifyFailed(std::move(Err));
- Ctx->getMemoryManager().allocate(
- Ctx->getJITLinkDylib(), *G,
- [S = std::move(Self)](AllocResult AR) mutable {
- // FIXME: Once MSVC implements c++17 order of evaluation rules for calls
- // this can be simplified to
- // S->linkPhase2(std::move(S), std::move(AR));
- auto *TmpSelf = S.get();
- TmpSelf->linkPhase2(std::move(S), std::move(AR));
- });
+ auto LinkPhase2 = [S = std::move(Self)](AllocResult AR) mutable {
+ // FIXME: Once MSVC implements c++17 order of evaluation rules for calls
+ // this can be simplified to
+ // S->linkPhase2(std::move(S), std::move(AR));
+ auto *TmpSelf = S.get();
+ TmpSelf->linkPhase2(std::move(S), std::move(AR));
+ };
+
+ if (G->allocActions().empty() && llvm::all_of(G->sections(), [](Section &S) {
+ return S.getMemLifetime() == orc::MemLifetime::NoAlloc;
+ })) {
+ LinkPhase2(nullptr);
+ } else {
+ Ctx->getMemoryManager().allocate(Ctx->getJITLinkDylib(), *G,
+ std::move(LinkPhase2));
+ }
}
void JITLinkerBase::linkPhase2(std::unique_ptr<JITLinkerBase> Self,
@@ -163,13 +170,18 @@ void JITLinkerBase::linkPhase3(std::unique_ptr<JITLinkerBase> Self,
if (auto Err = runPasses(Passes.PostFixupPasses))
return abandonAllocAndBailOut(std::move(Self), std::move(Err));
- Alloc->finalize([S = std::move(Self)](FinalizeResult FR) mutable {
+ auto LinkPhase4 = [S = std::move(Self)](FinalizeResult FR) mutable {
// FIXME: Once MSVC implements c++17 order of evaluation rules for calls
// this can be simplified to
// S->linkPhase2(std::move(S), std::move(AR));
auto *TmpSelf = S.get();
TmpSelf->linkPhase4(std::move(S), std::move(FR));
- });
+ };
+
+ if (Alloc)
+ Alloc->finalize(std::move(LinkPhase4));
+ else
+ LinkPhase4(FinalizeResult{JITLinkMemoryManager::FinalizedAlloc{}});
}
void JITLinkerBase::linkPhase4(std::unique_ptr<JITLinkerBase> Self,
diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
index 2e2e7a9c5f32e8..460f4e1c448e67 100644
--- a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
@@ -12,15 +12,15 @@ namespace llvm {
namespace orc {
Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
-EPCDynamicLibrarySearchGenerator::Load(ExecutionSession &ES,
- const char *LibraryPath,
- SymbolPredicate Allow) {
+EPCDynamicLibrarySearchGenerator::Load(
+ ExecutionSession &ES, const char *LibraryPath, SymbolPredicate Allow,
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols) {
auto Handle = ES.getExecutorProcessControl().loadDylib(LibraryPath);
if (!Handle)
return Handle.takeError();
- return std::make_unique<EPCDynamicLibrarySearchGenerator>(ES, *Handle,
- std::move(Allow));
+ return std::make_unique<EPCDynamicLibrarySearchGenerator>(
+ ES, *Handle, std::move(Allow), std::move(AddAbsoluteSymbols));
}
Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
@@ -62,6 +62,8 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
return Error::success();
// Define resolved symbols.
+ if (AddAbsoluteSymbols)
+ return AddAbsoluteSymbols(JD, std::move(NewSymbols));
return JD.define(absoluteSymbols(std::move(NewSymbols)));
}
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
index 8d5608cc4d4cfd..3952445bb1aa4b 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
@@ -218,19 +218,23 @@ void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) {
}
DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
- sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow)
+ sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow,
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols)
: Dylib(std::move(Dylib)), Allow(std::move(Allow)),
+ AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)),
GlobalPrefix(GlobalPrefix) {}
Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
- SymbolPredicate Allow) {
+ SymbolPredicate Allow,
+ AddAbsoluteSymbolsFn AddAbsoluteSymbols) {
std::string ErrMsg;
auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
if (!Lib.isValid())
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
return std::make_unique<DynamicLibrarySearchGenerator>(
- std::move(Lib), GlobalPrefix, std::move(Allow));
+ std::move(Lib), GlobalPrefix, std::move(Allow),
+ std::move(AddAbsoluteSymbols));
}
Error DynamicLibrarySearchGenerator::tryToGenerate(
@@ -261,6 +265,8 @@ Error DynamicLibrarySearchGenerator::tryToGenerate(
if (NewSymbols.empty())
return Error::success();
+ if (AddAbsoluteSymbols)
+ return AddAbsoluteSymbols(JD, std::move(NewSymbols));
return JD.define(absoluteSymbols(std::move(NewSymbols)));
}
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index 9057300bf04352..6c17f14aa4c7c5 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -1608,6 +1608,8 @@ Error MachOPlatform::MachOPlatformPlugin::prepareSymbolTableRegistration(
SmallVector<jitlink::Symbol *> SymsToProcess;
for (auto *Sym : G.defined_symbols())
SymsToProcess.push_back(Sym);
+ for (auto *Sym : G.absolute_symbols())
+ SymsToProcess.push_back(Sym);
for (auto *Sym : SymsToProcess) {
if (!Sym->hasName())
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index 3d77f82e65696a..b8282948034ec3 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -93,15 +93,20 @@ class LinkGraphMaterializationUnit : public MaterializationUnit {
Interface LGI;
- for (auto *Sym : G.defined_symbols()) {
+ auto AddSymbol = [&](Symbol *Sym) {
// Skip local symbols.
if (Sym->getScope() == Scope::Local)
- continue;
+ return;
assert(Sym->hasName() && "Anonymous non-local symbol?");
LGI.SymbolFlags[ES.intern(Sym->getName())] =
getJITSymbolFlagsForSymbol(*Sym);
- }
+ };
+
+ for (auto *Sym : G.defined_symbols())
+ AddSymbol(Sym);
+ for (auto *Sym : G.absolute_symbols())
+ AddSymbol(Sym);
if (hasInitializerSection(G))
LGI.InitSymbol = makeInitSymbol(ES, G);
@@ -705,6 +710,9 @@ Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
if (Err)
return Err;
+ if (!FA)
+ return Error::success();
+
return MR.withResourceKeyDo(
[&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
}
diff --git a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
index 91659240c9d6dc..edd12ebb62e1a4 100644
--- a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
@@ -10,6 +10,11 @@
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
+#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
@@ -173,4 +178,96 @@ TEST_F(ObjectLinkingLayerTest, HandleErrorDuringPostAllocationPass) {
EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_anchor"), Failed());
}
+TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) {
+ class TestEPC : public UnsupportedExecutorProcessControl {
+ public:
+ TestEPC()
+ : UnsupportedExecutorProcessControl(nullptr, nullptr,
+ "x86_64-apple-darwin") {}
+
+ Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override {
+ return ExecutorAddr::fromPtr((void *)nullptr);
+ }
+
+ Expected<std::vector<tpctypes::LookupResult>>
+ lookupSymbols(ArrayRef<LookupRequest> Request) override {
+ std::vector<ExecutorSymbolDef> Result;
+ EXPECT_EQ(Request.size(), 1u);
+ for (auto &LR : Request) {
+ EXPECT_EQ(LR.Symbols.size(), 1u);
+ for (auto &Sym : LR.Symbols) {
+ if (*Sym.first == "_testFunc") {
+ ExecutorSymbolDef Def{ExecutorAddr::fromPtr((void *)0x1000),
+ JITSymbolFlags::Exported};
+ Result.push_back(Def);
+ } else {
+ ADD_FAILURE() << "unexpected symbol request " << *Sym.first;
+ }
+ }
+ }
+ return std::vector<tpctypes::LookupResult>{1, Result};
+ }
+ };
+
+ ExecutionSession ES{std::make_unique<TestEPC>()};
+ JITDylib &JD = ES.createBareJITDylib("main");
+ ObjectLinkingLayer ObjLinkingLayer{
+ ES, std::make_unique<InProcessMemoryManager>(4096)};
+
+ auto G = EPCDynamicLibrarySearchGenerator::GetForTargetProcess(
+ ES, {}, [&](JITDylib &JD, SymbolMap Syms) {
+ auto G =
+ absoluteSymbolsLinkGraph(ES.getTargetTriple(), std::move(Syms));
+ return ObjLinkingLayer.add(JD, std::move(G));
+ });
+ ASSERT_THAT_EXPECTED(G, Succeeded());
+ JD.addGenerator(std::move(*G));
+
+ class CheckDefs : public ObjectLinkingLayer::Plugin {
+ public:
+ ~CheckDefs() { EXPECT_TRUE(SawSymbolDef); }
+
+ void modifyPassConfig(MaterializationResponsibility &MR,
+ jitlink::LinkGraph &G,
+ jitlink::PassConfiguration &Config) override {
+ Config.PostAllocationPasses.push_back([this](LinkGraph &G) {
+ unsigned SymCount = 0;
+ for (Symbol *Sym : G.absolute_symbols()) {
+ SymCount += 1;
+ if (!Sym->hasName()) {
+ ADD_FAILURE() << "unexpected unnamed symbol";
+ continue;
+ }
+ if (Sym->getName() == "_testFunc")
+ SawSymbolDef = true;
+ else
+ ADD_FAILURE() << "unexpected symbol " << Sym->getName();
+ }
+ EXPECT_EQ(SymCount, 1u);
+ return Error::success();
+ });
+ }
+
+ Error notifyFailed(MaterializationResponsibility &MR) override {
+ return Error::success();
+ }
+
+ Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
+ return Error::success();
+ }
+ void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
+ ResourceKey SrcKey) override {
+ llvm_unreachable("unexpected resource transfer");
+ }
+
+ private:
+ bool SawSymbolDef = false;
+ };
+
+ ObjLinkingLayer.addPlugin(std::make_unique<CheckDefs>());
+
+ EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_testFunc"), Succeeded());
+ EXPECT_THAT_ERROR(ES.endSession(), Succeeded());
+}
+
} // end anonymous namespace
More information about the llvm-commits
mailing list