Skip to content

Commit 2133aa7

Browse files
committed
[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.
1 parent 40b4ac2 commit 2133aa7

File tree

11 files changed

+213
-24
lines changed

11 files changed

+213
-24
lines changed

bolt/lib/Rewrite/JITLinkLinker.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ struct JITLinkLinker::Context : jitlink::JITLinkContext {
173173

174174
void notifyFinalized(
175175
jitlink::JITLinkMemoryManager::FinalizedAlloc Alloc) override {
176-
Linker.Allocs.push_back(std::move(Alloc));
176+
if (Alloc)
177+
Linker.Allocs.push_back(std::move(Alloc));
177178
++Linker.MM->ObjectsLoaded;
178179
}
179180
};

llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ADT/STLExtras.h"
2020
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
2121
#include "llvm/ExecutionEngine/JITSymbol.h"
22+
#include "llvm/ExecutionEngine/Orc/Core.h"
2223
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
2324
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
2425
#include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h"
@@ -1923,6 +1924,10 @@ void visitExistingEdges(LinkGraph &G, VisitorTs &&...Vs) {
19231924
Expected<std::unique_ptr<LinkGraph>>
19241925
createLinkGraphFromObject(MemoryBufferRef ObjectBuffer);
19251926

1927+
/// Create a \c LinkGraph defining the given absolute symbols.
1928+
std::unique_ptr<LinkGraph> absoluteSymbolsLinkGraph(const Triple &TT,
1929+
orc::SymbolMap Symbols);
1930+
19261931
/// Link the given graph.
19271932
void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx);
19281933

llvm/include/llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,39 @@ class ExecutorProcessControl;
2525
class EPCDynamicLibrarySearchGenerator : public DefinitionGenerator {
2626
public:
2727
using SymbolPredicate = unique_function<bool(const SymbolStringPtr &)>;
28+
using AddAbsoluteSymbolsFn = unique_function<Error(JITDylib &, SymbolMap)>;
2829

2930
/// Create a DynamicLibrarySearchGenerator that searches for symbols in the
3031
/// library with the given handle.
3132
///
3233
/// If the Allow predicate is given then only symbols matching the predicate
3334
/// will be searched for. If the predicate is not given then all symbols will
3435
/// be searched for.
35-
EPCDynamicLibrarySearchGenerator(ExecutionSession &ES,
36-
tpctypes::DylibHandle H,
37-
SymbolPredicate Allow = SymbolPredicate())
38-
: EPC(ES.getExecutorProcessControl()), H(H), Allow(std::move(Allow)) {}
36+
///
37+
/// If \p AddAbsoluteSymbols is provided, it is used to add the symbols to the
38+
/// \c JITDylib; otherwise it uses JD.define(absoluteSymbols(...)).
39+
EPCDynamicLibrarySearchGenerator(
40+
ExecutionSession &ES, tpctypes::DylibHandle H,
41+
SymbolPredicate Allow = SymbolPredicate(),
42+
AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr)
43+
: EPC(ES.getExecutorProcessControl()), H(H), Allow(std::move(Allow)),
44+
AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)) {}
3945

4046
/// Permanently loads the library at the given path and, on success, returns
4147
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
4248
/// in the library. On failure returns the reason the library failed to load.
4349
static Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
4450
Load(ExecutionSession &ES, const char *LibraryPath,
45-
SymbolPredicate Allow = SymbolPredicate());
51+
SymbolPredicate Allow = SymbolPredicate(),
52+
AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr);
4653

4754
/// Creates a EPCDynamicLibrarySearchGenerator that searches for symbols in
4855
/// the target process.
4956
static Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
5057
GetForTargetProcess(ExecutionSession &ES,
51-
SymbolPredicate Allow = SymbolPredicate()) {
52-
return Load(ES, nullptr, std::move(Allow));
58+
SymbolPredicate Allow = SymbolPredicate(),
59+
AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr) {
60+
return Load(ES, nullptr, std::move(Allow), std::move(AddAbsoluteSymbols));
5361
}
5462

5563
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
@@ -60,6 +68,7 @@ class EPCDynamicLibrarySearchGenerator : public DefinitionGenerator {
6068
ExecutorProcessControl &EPC;
6169
tpctypes::DylibHandle H;
6270
SymbolPredicate Allow;
71+
AddAbsoluteSymbolsFn AddAbsoluteSymbols;
6372
};
6473

6574
} // end namespace orc

llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,29 +216,38 @@ class ItaniumCXAAtExitSupport {
216216
class DynamicLibrarySearchGenerator : public DefinitionGenerator {
217217
public:
218218
using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>;
219+
using AddAbsoluteSymbolsFn = unique_function<Error(JITDylib &, SymbolMap)>;
219220

220221
/// Create a DynamicLibrarySearchGenerator that searches for symbols in the
221222
/// given sys::DynamicLibrary.
222223
///
223224
/// If the Allow predicate is given then only symbols matching the predicate
224225
/// will be searched for. If the predicate is not given then all symbols will
225226
/// be searched for.
226-
DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, char GlobalPrefix,
227-
SymbolPredicate Allow = SymbolPredicate());
227+
///
228+
/// If \p AddAbsoluteSymbols is provided, it is used to add the symbols to the
229+
/// \c JITDylib; otherwise it uses JD.define(absoluteSymbols(...)).
230+
DynamicLibrarySearchGenerator(
231+
sys::DynamicLibrary Dylib, char GlobalPrefix,
232+
SymbolPredicate Allow = SymbolPredicate(),
233+
AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr);
228234

229235
/// Permanently loads the library at the given path and, on success, returns
230236
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
231237
/// in the library. On failure returns the reason the library failed to load.
232238
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
233239
Load(const char *FileName, char GlobalPrefix,
234-
SymbolPredicate Allow = SymbolPredicate());
240+
SymbolPredicate Allow = SymbolPredicate(),
241+
AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr);
235242

236243
/// Creates a DynamicLibrarySearchGenerator that searches for symbols in
237244
/// the current process.
238245
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
239246
GetForCurrentProcess(char GlobalPrefix,
240-
SymbolPredicate Allow = SymbolPredicate()) {
241-
return Load(nullptr, GlobalPrefix, std::move(Allow));
247+
SymbolPredicate Allow = SymbolPredicate(),
248+
AddAbsoluteSymbolsFn AddAbsoluteSymbols = nullptr) {
249+
return Load(nullptr, GlobalPrefix, std::move(Allow),
250+
std::move(AddAbsoluteSymbols));
242251
}
243252

244253
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
@@ -248,6 +257,7 @@ class DynamicLibrarySearchGenerator : public DefinitionGenerator {
248257
private:
249258
sys::DynamicLibrary Dylib;
250259
SymbolPredicate Allow;
260+
AddAbsoluteSymbolsFn AddAbsoluteSymbols;
251261
char GlobalPrefix;
252262
};
253263

llvm/lib/ExecutionEngine/JITLink/JITLink.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,41 @@ createLinkGraphFromObject(MemoryBufferRef ObjectBuffer) {
468468
};
469469
}
470470

471+
std::unique_ptr<LinkGraph> absoluteSymbolsLinkGraph(const Triple &TT,
472+
orc::SymbolMap Symbols) {
473+
unsigned PointerSize;
474+
endianness Endianness =
475+
TT.isLittleEndian() ? endianness::little : endianness::big;
476+
switch (TT.getArch()) {
477+
case Triple::aarch64:
478+
case llvm::Triple::riscv64:
479+
case Triple::x86_64:
480+
PointerSize = 8;
481+
break;
482+
case llvm::Triple::arm:
483+
case llvm::Triple::riscv32:
484+
case llvm::Triple::x86:
485+
PointerSize = 4;
486+
break;
487+
default:
488+
llvm::report_fatal_error("unhandled target architecture");
489+
}
490+
491+
static std::atomic<uint64_t> Counter = {0};
492+
auto Index = Counter.fetch_add(1, std::memory_order_relaxed);
493+
auto G = std::make_unique<LinkGraph>(
494+
"<Absolute Symbols " + std::to_string(Index) + ">", TT, PointerSize,
495+
Endianness, /*GetEdgeKindName=*/nullptr);
496+
for (auto &[Name, Def] : Symbols) {
497+
auto &Sym =
498+
G->addAbsoluteSymbol(*Name, Def.getAddress(), /*Size=*/0,
499+
Linkage::Strong, Scope::Default, /*IsLive=*/true);
500+
Sym.setCallable(Def.getFlags().isCallable());
501+
}
502+
503+
return G;
504+
}
505+
471506
void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) {
472507
switch (G->getTargetTriple().getObjectFormat()) {
473508
case Triple::MachO:

llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ void JITLinkerBase::linkPhase1(std::unique_ptr<JITLinkerBase> Self) {
4848
if (auto Err = runPasses(Passes.PostPrunePasses))
4949
return Ctx->notifyFailed(std::move(Err));
5050

51+
// Skip straight to phase 2 if the graph is empty with no associated actions.
52+
if (G->allocActions().empty() && llvm::all_of(G->sections(), [](Section &S) {
53+
return S.getMemLifetime() == orc::MemLifetime::NoAlloc;
54+
})) {
55+
linkPhase2(std::move(Self), nullptr);
56+
return;
57+
}
58+
5159
Ctx->getMemoryManager().allocate(
5260
Ctx->getJITLinkDylib(), *G,
5361
[S = std::move(Self)](AllocResult AR) mutable {
@@ -163,6 +171,12 @@ void JITLinkerBase::linkPhase3(std::unique_ptr<JITLinkerBase> Self,
163171
if (auto Err = runPasses(Passes.PostFixupPasses))
164172
return abandonAllocAndBailOut(std::move(Self), std::move(Err));
165173

174+
// Skip straight to phase 4 if the graph has no allocation.
175+
if (!Alloc) {
176+
linkPhase4(std::move(Self), JITLinkMemoryManager::FinalizedAlloc{});
177+
return;
178+
}
179+
166180
Alloc->finalize([S = std::move(Self)](FinalizeResult FR) mutable {
167181
// FIXME: Once MSVC implements c++17 order of evaluation rules for calls
168182
// this can be simplified to

llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ namespace llvm {
1212
namespace orc {
1313

1414
Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
15-
EPCDynamicLibrarySearchGenerator::Load(ExecutionSession &ES,
16-
const char *LibraryPath,
17-
SymbolPredicate Allow) {
15+
EPCDynamicLibrarySearchGenerator::Load(
16+
ExecutionSession &ES, const char *LibraryPath, SymbolPredicate Allow,
17+
AddAbsoluteSymbolsFn AddAbsoluteSymbols) {
1818
auto Handle = ES.getExecutorProcessControl().loadDylib(LibraryPath);
1919
if (!Handle)
2020
return Handle.takeError();
2121

22-
return std::make_unique<EPCDynamicLibrarySearchGenerator>(ES, *Handle,
23-
std::move(Allow));
22+
return std::make_unique<EPCDynamicLibrarySearchGenerator>(
23+
ES, *Handle, std::move(Allow), std::move(AddAbsoluteSymbols));
2424
}
2525

2626
Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
@@ -62,6 +62,8 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
6262
return Error::success();
6363

6464
// Define resolved symbols.
65+
if (AddAbsoluteSymbols)
66+
return AddAbsoluteSymbols(JD, std::move(NewSymbols));
6567
return JD.define(absoluteSymbols(std::move(NewSymbols)));
6668
}
6769

llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,19 +218,23 @@ void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) {
218218
}
219219

220220
DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
221-
sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow)
221+
sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow,
222+
AddAbsoluteSymbolsFn AddAbsoluteSymbols)
222223
: Dylib(std::move(Dylib)), Allow(std::move(Allow)),
224+
AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)),
223225
GlobalPrefix(GlobalPrefix) {}
224226

225227
Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
226228
DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
227-
SymbolPredicate Allow) {
229+
SymbolPredicate Allow,
230+
AddAbsoluteSymbolsFn AddAbsoluteSymbols) {
228231
std::string ErrMsg;
229232
auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
230233
if (!Lib.isValid())
231234
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
232235
return std::make_unique<DynamicLibrarySearchGenerator>(
233-
std::move(Lib), GlobalPrefix, std::move(Allow));
236+
std::move(Lib), GlobalPrefix, std::move(Allow),
237+
std::move(AddAbsoluteSymbols));
234238
}
235239

236240
Error DynamicLibrarySearchGenerator::tryToGenerate(
@@ -261,6 +265,8 @@ Error DynamicLibrarySearchGenerator::tryToGenerate(
261265
if (NewSymbols.empty())
262266
return Error::success();
263267

268+
if (AddAbsoluteSymbols)
269+
return AddAbsoluteSymbols(JD, std::move(NewSymbols));
264270
return JD.define(absoluteSymbols(std::move(NewSymbols)));
265271
}
266272

llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,8 @@ Error MachOPlatform::MachOPlatformPlugin::prepareSymbolTableRegistration(
16081608
SmallVector<jitlink::Symbol *> SymsToProcess;
16091609
for (auto *Sym : G.defined_symbols())
16101610
SymsToProcess.push_back(Sym);
1611+
for (auto *Sym : G.absolute_symbols())
1612+
SymsToProcess.push_back(Sym);
16111613

16121614
for (auto *Sym : SymsToProcess) {
16131615
if (!Sym->hasName())

llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,20 @@ class LinkGraphMaterializationUnit : public MaterializationUnit {
9393

9494
Interface LGI;
9595

96-
for (auto *Sym : G.defined_symbols()) {
96+
auto AddSymbol = [&](Symbol *Sym) {
9797
// Skip local symbols.
9898
if (Sym->getScope() == Scope::Local)
99-
continue;
99+
return;
100100
assert(Sym->hasName() && "Anonymous non-local symbol?");
101101

102102
LGI.SymbolFlags[ES.intern(Sym->getName())] =
103103
getJITSymbolFlagsForSymbol(*Sym);
104-
}
104+
};
105+
106+
for (auto *Sym : G.defined_symbols())
107+
AddSymbol(Sym);
108+
for (auto *Sym : G.absolute_symbols())
109+
AddSymbol(Sym);
105110

106111
if (hasInitializerSection(G))
107112
LGI.InitSymbol = makeInitSymbol(ES, G);
@@ -705,6 +710,9 @@ Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
705710
if (Err)
706711
return Err;
707712

713+
if (!FA)
714+
return Error::success();
715+
708716
return MR.withResourceKeyDo(
709717
[&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
710718
}

0 commit comments

Comments
 (0)