[llvm-jitlink] Support promotion of ODR weak symbols in -harness mode.

This prevents weak symbols from being immediately dead-stripped when not
directly referenced from the test harneess, enabling use of weak symbols
from the code under test.
This commit is contained in:
Lang Hames 2020-07-31 21:32:27 -07:00
parent e281376e99
commit e12a028ed3
3 changed files with 44 additions and 7 deletions

View File

@ -17,9 +17,16 @@ _public_func_to_interpose:
_private_func_to_interpose:
retq
.globl _used_weak
.weak_definition _used_weak
.p2align 4, 0x90
_used_weak:
retq
.globl _public_func_to_test
.p2align 4, 0x90
_public_func_to_test:
callq _used_weak
jmp _public_func_to_interpose
.p2align 4, 0x90

View File

@ -188,10 +188,28 @@ static Error applyHarnessPromotions(Session &S, LinkGraph &G) {
if (!Sym->hasName())
continue;
if (S.HarnessExternals.count(Sym->getName())) {
if (Sym->getLinkage() == Linkage::Weak) {
if (!S.CanonicalWeakDefs.count(Sym->getName()) ||
S.CanonicalWeakDefs[Sym->getName()] != G.getName()) {
LLVM_DEBUG({
dbgs() << " Externalizing weak symbol " << Sym->getName() << "\n";
});
DefinitionsToRemove.push_back(Sym);
} else {
LLVM_DEBUG({
dbgs() << " Making weak symbol " << Sym->getName() << " strong\n";
});
if (S.HarnessExternals.count(Sym->getName()))
Sym->setScope(Scope::Default);
else
Sym->setScope(Scope::Hidden);
Sym->setLinkage(Linkage::Strong);
}
} else if (S.HarnessExternals.count(Sym->getName())) {
LLVM_DEBUG(dbgs() << " Promoting " << Sym->getName() << "\n");
Sym->setScope(Scope::Default);
Sym->setLive(true);
continue;
} else if (S.HarnessDefinitions.count(Sym->getName())) {
LLVM_DEBUG(dbgs() << " Externalizing " << Sym->getName() << "\n");
DefinitionsToRemove.push_back(Sym);
@ -504,10 +522,6 @@ Error LLVMJITLinkObjectLinkingLayer::add(JITDylib &JD,
if (!Name)
return Name.takeError();
// Skip symbols that aren't in the HarnessExternals set.
if (!S.HarnessExternals.count(*Name))
continue;
// Skip symbols that have type SF_File.
if (auto SymType = Sym.getType()) {
if (*SymType == object::SymbolRef::ST_File)
@ -515,13 +529,28 @@ Error LLVMJITLinkObjectLinkingLayer::add(JITDylib &JD,
} else
return SymType.takeError();
auto InternedName = S.ES.intern(*Name);
auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
if (!SymFlags)
return SymFlags.takeError();
*SymFlags |= JITSymbolFlags::Exported;
if (SymFlags->isWeak()) {
// If this is a weak symbol that's not defined in the harness then we
// need to either mark it as strong (if this is the first definition
// that we've seen) or discard it.
if (S.HarnessDefinitions.count(*Name) || S.CanonicalWeakDefs.count(*Name))
continue;
S.CanonicalWeakDefs[*Name] = O->getBufferIdentifier();
*SymFlags &= ~JITSymbolFlags::Weak;
if (!S.HarnessExternals.count(*Name))
*SymFlags &= ~JITSymbolFlags::Exported;
} else if (S.HarnessExternals.count(*Name)) {
*SymFlags |= JITSymbolFlags::Exported;
} else {
// Skip symbols that aren't in the HarnessExternals set.
continue;
}
auto InternedName = S.ES.intern(*Name);
SymbolFlags[InternedName] = std::move(*SymFlags);
}

View File

@ -86,6 +86,7 @@ struct Session {
StringSet<> HarnessFiles;
StringSet<> HarnessExternals;
StringSet<> HarnessDefinitions;
DenseMap<StringRef, StringRef> CanonicalWeakDefs;
private:
Session(Triple TT, Error &Err);