Add another symbol generator to resolve the generated lazy symbol.

The in-process symbol generator resolves symbols available in the process and
all dlopened libraries. However, upon unresolved symbol, we trigger our lazy
loading function creator callbacks which load the relevant library. Then we
need another in-process symbol generator to catch the newly created symbol so
that the JIT is happy.

This solution is suboptimal and in the comments is provided a cleaner
implementation, however, this implementation loads libraries for weak symbols
that the JIT could generate. This needs to be further investigated.
This commit is contained in:
Vassil Vassilev 2022-04-01 09:02:48 +00:00 committed by jenkins
parent 090176dcfd
commit c8e1a89726

View File

@ -24,18 +24,58 @@ using namespace llvm::orc;
namespace cling {
class NotifyLazyFunctionCreatorsGenerator : public DefinitionGenerator {
/// This class is a combination of the logic in DynamicLibrarySearchGenerator,
/// falling back to our symbol resolution logic.
class HostLookupLazyFallbackGenerator : public DefinitionGenerator {
const IncrementalExecutor & m_IncrExecutor;
char m_GlobalPrefix;
public:
NotifyLazyFunctionCreatorsGenerator(const IncrementalExecutor &Exe)
: m_IncrExecutor(Exe) { }
HostLookupLazyFallbackGenerator(const IncrementalExecutor &Exe,
char GlobalPrefix)
: m_IncrExecutor(Exe), m_GlobalPrefix(GlobalPrefix) { }
Error tryToGenerate(LookupState& LS, LookupKind K, JITDylib& JD,
JITDylibLookupFlags JDLookupFlags,
const SymbolLookupSet& LookupSet) override {
const SymbolLookupSet& Symbols) override {
// FIXME: Uncomment when we figure out how to not load weak symbols from
// m_IncrExecutor.NotifyLazyFunctionCreators
// orc::SymbolMap NewSymbols;
// bool HasGlobalPrefix = (m_GlobalPrefix != '\0');
// for (auto &KV : Symbols) {
// auto &Name = KV.first;
// if ((*Name).empty())
// continue;
// if (HasGlobalPrefix && (*Name).front() != m_GlobalPrefix)
// continue;
// std::string Tmp((*Name).data() + HasGlobalPrefix,
// (*Name).size() - HasGlobalPrefix);
// void *Addr = sys::DynamicLibrary::SearchForAddressOfSymbol(Tmp.c_str());
// // FIXME: Here we will load random libraries due to weak symbols which is
// // suboptimal. We should let the JIT create them.
// if (!Addr)
// Addr = m_IncrExecutor.NotifyLazyFunctionCreators(Tmp.c_str());
// if (Addr) {
// NewSymbols[Name] = JITEvaluatedSymbol(
// static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)),
// JITSymbolFlags::Exported);
// }
// }
// if (NewSymbols.empty())
// return Error::success();
// return JD.define(absoluteSymbols(std::move(NewSymbols)));
SymbolNameSet Missing;
for (llvm::orc::SymbolStringPtr Name : LookupSet.getSymbolNames())
if (!m_IncrExecutor.NotifyLazyFunctionCreators((*Name).str()))
for (llvm::orc::SymbolStringPtr Name : Symbols.getSymbolNames())
if (!sys::DynamicLibrary::SearchForAddressOfSymbol((*Name).str()) &&
!m_IncrExecutor.NotifyLazyFunctionCreators((*Name).str()))
Missing.insert(Name);
if (!Missing.empty())
@ -88,17 +128,33 @@ IncrementalJIT::IncrementalJIT(
});
// FIXME: Make host process symbol lookup optional on a per-query basis
char LinkerPrefix = this->TM->createDataLayout().getGlobalPrefix();
// Process symbol resolution
Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> HostProcessLookup =
DynamicLibrarySearchGenerator::GetForCurrentProcess(LinkerPrefix);
if (!HostProcessLookup) {
Err = HostProcessLookup.takeError();
return;
}
Jit->getMainJITDylib().addGenerator(std::move(*HostProcessLookup));
auto Notifier = std::make_unique<NotifyLazyFunctionCreatorsGenerator>(Executor);
// Lazy symbol generation callback
auto Notifier =
std::make_unique<HostLookupLazyFallbackGenerator>(Executor, LinkerPrefix);
Jit->getMainJITDylib().addGenerator(std::move(Notifier));
// Process symbol resolution after the callback.
// FIXME: if we resolve the FIXME in HostLookupLazyFallbackGenerator, we will
// need just one generator.
HostProcessLookup =
DynamicLibrarySearchGenerator::GetForCurrentProcess(LinkerPrefix);
if (!HostProcessLookup) {
Err = HostProcessLookup.takeError();
return;
}
Jit->getMainJITDylib().addGenerator(std::move(*HostProcessLookup));
}
void IncrementalJIT::addModule(Transaction& T) {