1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[llvm-jitlink] Add -phony-externals option to suppress unresolved externals.

The -phony-externals option adds a generator which explicitly defines any
otherwise unresolved externals as null. This transforms link-time
unresolved-symbol errors into potential runtime null pointer accesses
(if an unresolved external is actually accessed during execution).

This option can be useful in -harness mode to avoid having to mock a
large number of symbols that are not reachable at runtime (e.g. unused
methods referenced by a class vtable).
This commit is contained in:
Lang Hames 2020-08-01 17:44:34 -07:00
parent f9871c7f15
commit b014cb8f2f
4 changed files with 31 additions and 10 deletions

View File

@ -337,12 +337,6 @@ void JITLinkerBase::applyLookupResult(AsyncLookupResult Result) {
dbgs() << " " << Sym->getName() << ": "
<< formatv("{0:x16}", Sym->getAddress()) << "\n";
});
assert(llvm::all_of(G->external_symbols(),
[](Symbol *Sym) {
return Sym->getAddress() != 0 ||
Sym->getLinkage() == Linkage::Weak;
}) &&
"All strong external symbols should have been resolved by now");
}
void JITLinkerBase::copyBlockContentToWorkingMemory(

View File

@ -27,6 +27,7 @@ _used_weak:
.p2align 4, 0x90
_public_func_to_test:
callq _used_weak
callq _used_unresolved_external
jmp _public_func_to_interpose
.p2align 4, 0x90

View File

@ -3,7 +3,9 @@
# RUN: -o %t/file_to_test.o %S/Inputs/MachO_test_harness_test.s
# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj \
# RUN: -o %t/test_harness.o %s
# RUN: llvm-jitlink -noexec -check %s %t/file_to_test.o \
# RUN: not llvm-jitlink -noexec -check %s %t/file_to_test.o \
# RUN: -harness %t/test_harness.o
# RUN: llvm-jitlink -noexec -phony-externals -check %s %t/file_to_test.o \
# RUN: -harness %t/test_harness.o
#
# Check that we

View File

@ -132,6 +132,11 @@ static cl::opt<bool> ShowRelocatedSectionContents(
cl::desc("show section contents after fixups have been applied"),
cl::init(false));
static cl::opt<bool> PhonyExternals(
"phony-externals",
cl::desc("resolve all otherwise unresolved externals to null"),
cl::init(false));
ExitOnError ExitOnErr;
namespace llvm {
@ -179,9 +184,9 @@ static Error applyHarnessPromotions(Session &S, LinkGraph &G) {
LLVM_DEBUG(dbgs() << "Appling promotions to graph " << G.getName() << "\n");
// If it isn't then promote any symbols referenced by the harness to default
// scope, remove all symbols that clash with harness definitions, and demote
// all others.
// If this graph is part of the test then promote any symbols referenced by
// the harness to default scope, remove all symbols that clash with harness
// definitions, demote all other definitions.
std::vector<Symbol *> DefinitionsToRemove;
for (auto *Sym : G.defined_symbols()) {
@ -560,6 +565,18 @@ Error LLVMJITLinkObjectLinkingLayer::add(JITDylib &JD,
return JD.define(std::move(MU));
}
class PhonyExternalsGenerator : public JITDylib::DefinitionGenerator {
public:
Error tryToGenerate(LookupKind K, JITDylib &JD,
JITDylibLookupFlags JDLookupFlags,
const SymbolLookupSet &LookupSet) override {
SymbolMap PhonySymbols;
for (auto &KV : LookupSet)
PhonySymbols[KV.first] = JITEvaluatedSymbol(0, JITSymbolFlags::Exported);
return JD.define(absoluteSymbols(std::move(PhonySymbols)));
}
};
Expected<std::unique_ptr<Session>> Session::Create(Triple TT) {
Error Err = Error::success();
std::unique_ptr<Session> S(new Session(std::move(TT), Err));
@ -813,6 +830,10 @@ Error loadDylibs() {
return Error::success();
}
void addPhonyExternalsGenerator(Session &S) {
S.MainJD->addGenerator(std::make_unique<PhonyExternalsGenerator>());
}
Error loadObjects(Session &S) {
std::map<unsigned, JITDylib *> IdxToJLD;
@ -1039,6 +1060,9 @@ int main(int argc, char *argv[]) {
ExitOnErr(loadProcessSymbols(*S));
ExitOnErr(loadDylibs());
if (PhonyExternals)
addPhonyExternalsGenerator(*S);
{
TimeRegion TR(Timers ? &Timers->LoadObjectsTimer : nullptr);
ExitOnErr(loadObjects(*S));