llvm-project/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp
Lang Hames 253e11695b [ORC][llvm-jitlink] Add support for emulating ld64 -weak-lx / -weak_library.
Linking libraries in ld64 with -weak-lx / -weak_library causes all references
to symbols in those libraries to be made weak, allowing the librarie to be
missing at runtime.

This patch extends EPCDynamicLibrarySearchGenerator with support for emulating
this behavior: If an instance is constructed with an Allow predicate but no
dylib handle then all symbols matching the predicate are immediately resolved
to null.

The llvm-jitlink tool is updated with -weak-lx / -weak_library options for
testing. Unlike their ld64 counterparts these options take a TBD file as input,
and always resolve all exports in the TBD file to null.
2025-02-25 13:54:17 +11:00

116 lines
3.7 KiB
C++

//===---------------- EPCDynamicLibrarySearchGenerator.cpp ----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/Support/Error.h"
#define DEBUG_TYPE "orc"
namespace llvm {
namespace orc {
Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
EPCDynamicLibrarySearchGenerator::Load(
ExecutionSession &ES, const char *LibraryPath, SymbolPredicate Allow,
AddAbsoluteSymbolsFn AddAbsoluteSymbols) {
auto Handle =
ES.getExecutorProcessControl().getDylibMgr().loadDylib(LibraryPath);
if (!Handle)
return Handle.takeError();
return std::make_unique<EPCDynamicLibrarySearchGenerator>(
ES, *Handle, std::move(Allow), std::move(AddAbsoluteSymbols));
}
Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
LookupState &LS, LookupKind K, JITDylib &JD,
JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
if (Symbols.empty())
return Error::success();
LLVM_DEBUG({
dbgs() << "EPCDynamicLibrarySearchGenerator trying to generate "
<< Symbols << "\n";
});
// If there's no handle then resolve all requested symbols to null.
if (!H) {
assert(Allow && "No handle or filter?");
SymbolMap Nulls;
for (auto &[Name, LookupFlags] : Symbols) {
if (Allow(Name))
Nulls[Name] = {};
}
return addAbsolutes(JD, std::move(Nulls));
}
// Otherwise proceed with lookup in the remote.
SymbolLookupSet LookupSymbols;
for (auto &KV : Symbols) {
// Skip symbols that don't match the filter.
if (Allow && !Allow(KV.first))
continue;
LookupSymbols.add(KV.first, SymbolLookupFlags::WeaklyReferencedSymbol);
}
DylibManager::LookupRequest Request(*H, LookupSymbols);
// Copy-capture LookupSymbols, since LookupRequest keeps a reference.
EPC.getDylibMgr().lookupSymbolsAsync(Request, [this, &JD, LS = std::move(LS),
LookupSymbols](
auto Result) mutable {
if (!Result) {
LLVM_DEBUG({
dbgs() << "EPCDynamicLibrarySearchGenerator lookup failed due to error";
});
return LS.continueLookup(Result.takeError());
}
assert(Result->size() == 1 && "Results for more than one library returned");
assert(Result->front().size() == LookupSymbols.size() &&
"Result has incorrect number of elements");
SymbolMap NewSymbols;
auto ResultI = Result->front().begin();
for (auto &KV : LookupSymbols) {
if (ResultI->getAddress())
NewSymbols[KV.first] = *ResultI;
++ResultI;
}
LLVM_DEBUG({
dbgs() << "EPCDynamicLibrarySearchGenerator lookup returned "
<< NewSymbols << "\n";
});
// If there were no resolved symbols bail out.
if (NewSymbols.empty())
return LS.continueLookup(Error::success());
// Define resolved symbols.
Error Err = addAbsolutes(JD, std::move(NewSymbols));
LS.continueLookup(std::move(Err));
});
return Error::success();
}
Error EPCDynamicLibrarySearchGenerator::addAbsolutes(JITDylib &JD,
SymbolMap Symbols) {
return AddAbsoluteSymbols ? AddAbsoluteSymbols(JD, std::move(Symbols))
: JD.define(absoluteSymbols(std::move(Symbols)));
}
} // end namespace orc
} // end namespace llvm