Skip to content

Commit e05d80e

Browse files
authored
[ORC] Add Executor Resolver Utility (#143654)
This patch adds the new **executor-side resolver API** as suggested by @lhames. It introduces a `DylibSymbolResolver` that helps resolve symbols for each loaded dylib. Previously, we returned a `DylibHandle` to the controller. Now, we wrap the native handle inside `DylibSymbolResolver` and return a `ResolverHandle` instead. This makes the code cleaner and separates the symbol resolution logic from raw handle management.
1 parent bb09cc4 commit e05d80e

19 files changed

+363
-99
lines changed

llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class EPCGenericDylibManager {
3434
struct SymbolAddrs {
3535
ExecutorAddr Instance;
3636
ExecutorAddr Open;
37-
ExecutorAddr Lookup;
37+
ExecutorAddr Resolve;
3838
};
3939

4040
/// Create an EPCGenericMemoryAccess instance from a given set of
@@ -51,25 +51,25 @@ class EPCGenericDylibManager {
5151
LLVM_ABI Expected<tpctypes::DylibHandle> open(StringRef Path, uint64_t Mode);
5252

5353
/// Looks up symbols within the given dylib.
54-
Expected<std::vector<ExecutorSymbolDef>>
55-
lookup(tpctypes::DylibHandle H, const SymbolLookupSet &Lookup) {
56-
std::promise<MSVCPExpected<std::vector<ExecutorSymbolDef>>> RP;
54+
Expected<tpctypes::LookupResult> lookup(tpctypes::DylibHandle H,
55+
const SymbolLookupSet &Lookup) {
56+
std::promise<MSVCPExpected<tpctypes::LookupResult>> RP;
5757
auto RF = RP.get_future();
5858
lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); });
5959
return RF.get();
6060
}
6161

6262
/// Looks up symbols within the given dylib.
63-
Expected<std::vector<ExecutorSymbolDef>>
64-
lookup(tpctypes::DylibHandle H, const RemoteSymbolLookupSet &Lookup) {
65-
std::promise<MSVCPExpected<std::vector<ExecutorSymbolDef>>> RP;
63+
Expected<tpctypes::LookupResult> lookup(tpctypes::DylibHandle H,
64+
const RemoteSymbolLookupSet &Lookup) {
65+
std::promise<MSVCPExpected<tpctypes::LookupResult>> RP;
6666
auto RF = RP.get_future();
6767
lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); });
6868
return RF.get();
6969
}
7070

7171
using SymbolLookupCompleteFn =
72-
unique_function<void(Expected<std::vector<ExecutorSymbolDef>>)>;
72+
unique_function<void(Expected<tpctypes::LookupResult>)>;
7373

7474
/// Looks up symbols within the given dylib.
7575
LLVM_ABI void lookupAsync(tpctypes::DylibHandle H,
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//===----- ExecutorResolver.h - Resolve symbols in executor -----*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Declares ExecutorResolutionGenerator for symbol resolution,
10+
// dynamic library loading, and lookup in an executor process via
11+
// ExecutorResolver.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTORRESOLUTIONGENERATOR_H
16+
#define LLVM_EXECUTIONENGINE_ORC_EXECUTORRESOLUTIONGENERATOR_H
17+
18+
#include "llvm/ADT/FunctionExtras.h"
19+
#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
20+
#include "llvm/ExecutionEngine/Orc/Core.h"
21+
22+
namespace llvm::orc {
23+
24+
class ExecutorResolutionGenerator : public DefinitionGenerator {
25+
public:
26+
using SymbolPredicate = unique_function<bool(const SymbolStringPtr &)>;
27+
using AbsoluteSymbolsFn =
28+
unique_function<std::unique_ptr<MaterializationUnit>(SymbolMap)>;
29+
30+
ExecutorResolutionGenerator(
31+
ExecutionSession &ES, tpctypes::ResolverHandle H,
32+
SymbolPredicate Allow = SymbolPredicate(),
33+
AbsoluteSymbolsFn AbsoluteSymbols = absoluteSymbols)
34+
: EPC(ES.getExecutorProcessControl()), H(H), Allow(std::move(Allow)),
35+
AbsoluteSymbols(std::move(AbsoluteSymbols)) {}
36+
37+
ExecutorResolutionGenerator(
38+
ExecutionSession &ES, SymbolPredicate Allow = SymbolPredicate(),
39+
AbsoluteSymbolsFn AbsoluteSymbols = absoluteSymbols)
40+
: EPC(ES.getExecutorProcessControl()), Allow(std::move(Allow)),
41+
AbsoluteSymbols(std::move(AbsoluteSymbols)) {}
42+
43+
/// Permanently loads the library at the given path and, on success, returns
44+
/// an ExecutorResolutionGenerator that will search it for symbol
45+
/// definitions in the library. On failure returns the reason the library
46+
/// failed to load.
47+
static Expected<std::unique_ptr<ExecutorResolutionGenerator>>
48+
Load(ExecutionSession &ES, const char *LibraryPath,
49+
SymbolPredicate Allow = SymbolPredicate(),
50+
AbsoluteSymbolsFn AbsoluteSymbols = absoluteSymbols);
51+
52+
/// Creates a ExecutorResolutionGenerator that searches for symbols in
53+
/// the target process.
54+
static Expected<std::unique_ptr<ExecutorResolutionGenerator>>
55+
GetForTargetProcess(ExecutionSession &ES,
56+
SymbolPredicate Allow = SymbolPredicate(),
57+
AbsoluteSymbolsFn AbsoluteSymbols = absoluteSymbols) {
58+
return Load(ES, nullptr, std::move(Allow), std::move(AbsoluteSymbols));
59+
}
60+
61+
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
62+
JITDylibLookupFlags JDLookupFlags,
63+
const SymbolLookupSet &LookupSet) override;
64+
65+
private:
66+
ExecutorProcessControl &EPC;
67+
tpctypes::ResolverHandle H;
68+
SymbolPredicate Allow;
69+
AbsoluteSymbolsFn AbsoluteSymbols;
70+
};
71+
72+
} // namespace llvm::orc
73+
74+
#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTORRESOLUTIONGENERATOR_H

llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace rt {
2525

2626
LLVM_ABI extern const char *SimpleExecutorDylibManagerInstanceName;
2727
LLVM_ABI extern const char *SimpleExecutorDylibManagerOpenWrapperName;
28-
LLVM_ABI extern const char *SimpleExecutorDylibManagerLookupWrapperName;
28+
LLVM_ABI extern const char *SimpleExecutorDylibManagerResolveWrapperName;
2929

3030
LLVM_ABI extern const char *SimpleExecutorMemoryManagerInstanceName;
3131
LLVM_ABI extern const char *SimpleExecutorMemoryManagerReserveWrapperName;
@@ -66,10 +66,9 @@ using SPSSimpleExecutorDylibManagerOpenSignature =
6666
shared::SPSExpected<shared::SPSExecutorAddr>(shared::SPSExecutorAddr,
6767
shared::SPSString, uint64_t);
6868

69-
using SPSSimpleExecutorDylibManagerLookupSignature =
70-
shared::SPSExpected<shared::SPSSequence<shared::SPSExecutorSymbolDef>>(
71-
shared::SPSExecutorAddr, shared::SPSExecutorAddr,
72-
shared::SPSRemoteSymbolLookupSet);
69+
using SPSSimpleExecutorDylibManagerResolveSignature = shared::SPSExpected<
70+
shared::SPSSequence<shared::SPSOptional<shared::SPSExecutorSymbolDef>>>(
71+
shared::SPSExecutorAddr, shared::SPSRemoteSymbolLookupSet);
7372

7473
using SPSSimpleExecutorMemoryManagerReserveSignature =
7574
shared::SPSExpected<shared::SPSExecutorAddr>(shared::SPSExecutorAddr,

llvm/include/llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,11 @@ struct PointerWrite {
114114
/// A handle used to represent a loaded dylib in the target process.
115115
using DylibHandle = ExecutorAddr;
116116

117-
using LookupResult = std::vector<ExecutorSymbolDef>;
117+
/// A handle used to reference the resolver associated with a loaded
118+
/// dylib in the target process.
119+
using ResolverHandle = ExecutorAddr;
120+
121+
using LookupResult = std::vector<std::optional<ExecutorSymbolDef>>;
118122

119123
} // end namespace tpctypes
120124

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//===----- ExecutorResolver.h - Symbol resolver -----*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Executor Symbol resolver.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_EXECUTORRESOLVER_H
14+
#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_EXECUTORRESOLVER_H
15+
16+
#include "llvm/ADT/FunctionExtras.h"
17+
18+
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
19+
#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
20+
#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
21+
22+
namespace llvm::orc {
23+
24+
class ExecutorResolver {
25+
public:
26+
using ResolveResult = Expected<std::vector<std::optional<ExecutorSymbolDef>>>;
27+
using YieldResolveResultFn = unique_function<void(ResolveResult)>;
28+
29+
virtual ~ExecutorResolver() = default;
30+
31+
virtual void resolveAsync(const RemoteSymbolLookupSet &L,
32+
YieldResolveResultFn &&OnResolve) = 0;
33+
};
34+
35+
class DylibSymbolResolver : public ExecutorResolver {
36+
public:
37+
DylibSymbolResolver(tpctypes::DylibHandle H) : Handle(H) {}
38+
39+
void
40+
resolveAsync(const RemoteSymbolLookupSet &L,
41+
ExecutorResolver::YieldResolveResultFn &&OnResolve) override;
42+
43+
private:
44+
tpctypes::DylibHandle Handle;
45+
};
46+
47+
} // end namespace llvm::orc
48+
#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_EXECUTORRESOLVER_H

llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
2424
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
2525
#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorBootstrapService.h"
26+
#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorResolver.h"
2627
#include "llvm/Support/Compiler.h"
2728
#include "llvm/Support/DynamicLibrary.h"
2829
#include "llvm/Support/Error.h"
@@ -39,8 +40,6 @@ class LLVM_ABI SimpleExecutorDylibManager : public ExecutorBootstrapService {
3940
virtual ~SimpleExecutorDylibManager();
4041

4142
Expected<tpctypes::DylibHandle> open(const std::string &Path, uint64_t Mode);
42-
Expected<std::vector<ExecutorSymbolDef>>
43-
lookup(tpctypes::DylibHandle H, const RemoteSymbolLookupSet &L);
4443

4544
Error shutdown() override;
4645
void addBootstrapSymbols(StringMap<ExecutorAddr> &M) override;
@@ -52,10 +51,11 @@ class LLVM_ABI SimpleExecutorDylibManager : public ExecutorBootstrapService {
5251
openWrapper(const char *ArgData, size_t ArgSize);
5352

5453
static llvm::orc::shared::CWrapperFunctionResult
55-
lookupWrapper(const char *ArgData, size_t ArgSize);
54+
resolveWrapper(const char *ArgData, size_t ArgSize);
5655

5756
std::mutex M;
5857
DylibSet Dylibs;
58+
std::vector<std::unique_ptr<ExecutorResolver>> Resolvers;
5959
};
6060

6161
} // end namespace rt_bootstrap

llvm/lib/ExecutionEngine/Orc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ add_llvm_component_library(LLVMOrcJIT
2424
EPCGenericRTDyldMemoryManager.cpp
2525
EPCIndirectionUtils.cpp
2626
ExecutionUtils.cpp
27+
ExecutorResolutionGenerator.cpp
2728
ObjectFileInterface.cpp
2829
GetDylibInterface.cpp
2930
IndirectionUtils.cpp

llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ Expected<std::unique_ptr<EPCDebugObjectRegistrar>> createJITLoaderGDBRegistrar(
4242
assert((*Result)[0].size() == 1 &&
4343
"Unexpected number of addresses in result");
4444

45-
ExecutorAddr RegisterAddr = (*Result)[0][0].getAddress();
45+
if (!(*Result)[0][0].has_value())
46+
return make_error<StringError>(
47+
"Expected a valid address in the lookup result",
48+
inconvertibleErrorCode());
49+
50+
ExecutorAddr RegisterAddr = (*Result)[0][0]->getAddress();
4651
return std::make_unique<EPCDebugObjectRegistrar>(ES, RegisterAddr);
4752
}
4853

llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,16 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
7979
assert(Result->front().size() == LookupSymbols.size() &&
8080
"Result has incorrect number of elements");
8181

82+
auto SymsIt = Result->front().begin();
83+
SymbolNameSet MissingSymbols;
8284
SymbolMap NewSymbols;
83-
auto ResultI = Result->front().begin();
84-
for (auto &KV : LookupSymbols) {
85-
if (ResultI->getAddress())
86-
NewSymbols[KV.first] = *ResultI;
87-
++ResultI;
85+
for (auto &[Name, Flags] : LookupSymbols) {
86+
const auto &Sym = *SymsIt++;
87+
if (Sym && Sym->getAddress())
88+
NewSymbols[Name] = *Sym;
89+
else if (LLVM_UNLIKELY(!Sym &&
90+
Flags == SymbolLookupFlags::RequiredSymbol))
91+
MissingSymbols.insert(Name);
8892
}
8993

9094
LLVM_DEBUG({
@@ -96,6 +100,10 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
96100
if (NewSymbols.empty())
97101
return LS.continueLookup(Error::success());
98102

103+
if (LLVM_UNLIKELY(!MissingSymbols.empty()))
104+
return LS.continueLookup(make_error<SymbolsNotFound>(
105+
this->EPC.getSymbolStringPool(), std::move(MissingSymbols)));
106+
99107
// Define resolved symbols.
100108
Error Err = addAbsolutes(JD, std::move(NewSymbols));
101109

llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(
6666
if (auto Err = EPC.getBootstrapSymbols(
6767
{{SAs.Instance, rt::SimpleExecutorDylibManagerInstanceName},
6868
{SAs.Open, rt::SimpleExecutorDylibManagerOpenWrapperName},
69-
{SAs.Lookup, rt::SimpleExecutorDylibManagerLookupWrapperName}}))
69+
{SAs.Resolve, rt::SimpleExecutorDylibManagerResolveWrapperName}}))
7070
return std::move(Err);
7171
return EPCGenericDylibManager(EPC, std::move(SAs));
7272
}
@@ -84,37 +84,39 @@ Expected<tpctypes::DylibHandle> EPCGenericDylibManager::open(StringRef Path,
8484
void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
8585
const SymbolLookupSet &Lookup,
8686
SymbolLookupCompleteFn Complete) {
87-
EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerLookupSignature>(
88-
SAs.Lookup,
87+
EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerResolveSignature>(
88+
SAs.Resolve,
8989
[Complete = std::move(Complete)](
9090
Error SerializationErr,
91-
Expected<std::vector<ExecutorSymbolDef>> Result) mutable {
91+
Expected<std::vector<std::optional<ExecutorSymbolDef>>>
92+
Result) mutable {
9293
if (SerializationErr) {
9394
cantFail(Result.takeError());
9495
Complete(std::move(SerializationErr));
9596
return;
9697
}
9798
Complete(std::move(Result));
9899
},
99-
SAs.Instance, H, Lookup);
100+
H, Lookup);
100101
}
101102

102103
void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
103104
const RemoteSymbolLookupSet &Lookup,
104105
SymbolLookupCompleteFn Complete) {
105-
EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerLookupSignature>(
106-
SAs.Lookup,
106+
EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerResolveSignature>(
107+
SAs.Resolve,
107108
[Complete = std::move(Complete)](
108109
Error SerializationErr,
109-
Expected<std::vector<ExecutorSymbolDef>> Result) mutable {
110+
Expected<std::vector<std::optional<ExecutorSymbolDef>>>
111+
Result) mutable {
110112
if (SerializationErr) {
111113
cantFail(Result.takeError());
112114
Complete(std::move(SerializationErr));
113115
return;
114116
}
115117
Complete(std::move(Result));
116118
},
117-
SAs.Instance, H, Lookup);
119+
H, Lookup);
118120
}
119121

120122
} // end namespace orc

0 commit comments

Comments
 (0)