ELF: Allow GOT relocs pointing to non-preemptable ifunc to resolve to an IRELATIVE where possible.
Non-GOT non-PLT relocations to non-preemptible ifuncs result in the
creation of a canonical PLT, which now takes the identity of the IFUNC
in the symbol table. This (a) ensures address consistency inside and
outside the module, and (b) fixes a bug where some of these relocations
end up pointing to the resolver.
Fixes (at least) PR40474 and PR40501.
Differential Revision: https://reviews.llvm.org/D57371
llvm-svn: 353981
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 52fa72a..96e23b9 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -120,20 +120,24 @@
return OutVA + Addend;
}
-uint64_t Symbol::getGotVA() const { return In.Got->getVA() + getGotOffset(); }
+uint64_t Symbol::getGotVA() const {
+ if (GotInIgot)
+ return In.IgotPlt->getVA() + getGotPltOffset();
+ return In.Got->getVA() + getGotOffset();
+}
uint64_t Symbol::getGotOffset() const {
return GotIndex * Target->GotEntrySize;
}
uint64_t Symbol::getGotPltVA() const {
- if (this->IsInIgot)
+ if (IsInIplt)
return In.IgotPlt->getVA() + getGotPltOffset();
return In.GotPlt->getVA() + getGotPltOffset();
}
uint64_t Symbol::getGotPltOffset() const {
- if (IsInIgot)
+ if (IsInIplt)
return PltIndex * Target->GotPltEntrySize;
return (PltIndex + Target->GotPltHeaderEntriesNum) * Target->GotPltEntrySize;
}