Merge commit 00925aadb from llvm git (by Fangrui Song):

[ELF][PPC32] Fix canonical PLTs when the order does not match the PLT order

  Reviewed By: Bdragon28

  Differential Revision: https://reviews.llvm.org/D75394

This is needed to fix miscompiled canonical PLTs on ppc32/lld10.

Requested by:	bdragon
MFC after:	6 weeks
X-MFC-With:	358851
Differential Revision: https://reviews.freebsd.org/D24109
This commit is contained in:
Dimitry Andric 2020-03-18 20:28:26 +00:00
parent 0d02682c96
commit 92c0d181e5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=359084
5 changed files with 33 additions and 18 deletions

View File

@ -71,12 +71,11 @@ void writePPC32GlinkSection(uint8_t *buf, size_t numEntries) {
// non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE. // non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE.
uint32_t glink = in.plt->getVA(); // VA of .glink uint32_t glink = in.plt->getVA(); // VA of .glink
if (!config->isPic) { if (!config->isPic) {
for (const Symbol *sym : in.plt->entries) for (const Symbol *sym : cast<PPC32GlinkSection>(in.plt)->canonical_plts) {
if (sym->needsPltAddr) { writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0);
writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0); buf += 16;
buf += 16; glink += 16;
glink += 16; }
}
} }
// On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an // On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an

View File

@ -1206,6 +1206,7 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
// PPC32 canonical PLT entries are at the beginning of .glink // PPC32 canonical PLT entries are at the beginning of .glink
cast<Defined>(sym).value = in.plt->headerSize; cast<Defined>(sym).value = in.plt->headerSize;
in.plt->headerSize += 16; in.plt->headerSize += 16;
cast<PPC32GlinkSection>(in.plt)->canonical_plts.push_back(&sym);
} }
} }
sym.needsPltAddr = true; sym.needsPltAddr = true;

View File

@ -2446,12 +2446,9 @@ PltSection::PltSection()
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"), : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"),
headerSize(target->pltHeaderSize) { headerSize(target->pltHeaderSize) {
// On PowerPC, this section contains lazy symbol resolvers. // On PowerPC, this section contains lazy symbol resolvers.
if (config->emachine == EM_PPC || config->emachine == EM_PPC64) { if (config->emachine == EM_PPC64) {
name = ".glink"; name = ".glink";
alignment = 4; alignment = 4;
// PLTresolve is at the end.
if (config->emachine == EM_PPC)
footerSize = 64;
} }
// On x86 when IBT is enabled, this section contains the second PLT (lazy // On x86 when IBT is enabled, this section contains the second PLT (lazy
@ -2467,11 +2464,6 @@ PltSection::PltSection()
} }
void PltSection::writeTo(uint8_t *buf) { void PltSection::writeTo(uint8_t *buf) {
if (config->emachine == EM_PPC) {
writePPC32GlinkSection(buf, entries.size());
return;
}
// At beginning of PLT, we have code to call the dynamic // At beginning of PLT, we have code to call the dynamic
// linker to resolve dynsyms at runtime. Write such code. // linker to resolve dynsyms at runtime. Write such code.
target->writePltHeader(buf); target->writePltHeader(buf);
@ -2489,7 +2481,7 @@ void PltSection::addEntry(Symbol &sym) {
} }
size_t PltSection::getSize() const { size_t PltSection::getSize() const {
return headerSize + entries.size() * target->pltEntrySize + footerSize; return headerSize + entries.size() * target->pltEntrySize;
} }
bool PltSection::isNeeded() const { bool PltSection::isNeeded() const {
@ -2543,6 +2535,19 @@ void IpltSection::addSymbols() {
} }
} }
PPC32GlinkSection::PPC32GlinkSection() {
name = ".glink";
alignment = 4;
}
void PPC32GlinkSection::writeTo(uint8_t *buf) {
writePPC32GlinkSection(buf, entries.size());
}
size_t PPC32GlinkSection::getSize() const {
return headerSize + entries.size() * target->pltEntrySize + footerSize;
}
// This is an x86-only extra PLT section and used only when a security // This is an x86-only extra PLT section and used only when a security
// enhancement feature called CET is enabled. In this comment, I'll explain what // enhancement feature called CET is enabled. In this comment, I'll explain what
// the feature is and why we have two PLT sections if CET is enabled. // the feature is and why we have two PLT sections if CET is enabled.

View File

@ -684,7 +684,6 @@ class PltSection : public SyntheticSection {
size_t getNumEntries() const { return entries.size(); } size_t getNumEntries() const { return entries.size(); }
size_t headerSize; size_t headerSize;
size_t footerSize = 0;
std::vector<const Symbol *> entries; std::vector<const Symbol *> entries;
}; };
@ -705,6 +704,16 @@ class IpltSection final : public SyntheticSection {
void addEntry(Symbol &sym); void addEntry(Symbol &sym);
}; };
class PPC32GlinkSection : public PltSection {
public:
PPC32GlinkSection();
void writeTo(uint8_t *buf) override;
size_t getSize() const override;
std::vector<const Symbol *> canonical_plts;
static constexpr size_t footerSize = 64;
};
// This is x86-only. // This is x86-only.
class IBTPltSection : public SyntheticSection { class IBTPltSection : public SyntheticSection {
public: public:

View File

@ -521,7 +521,8 @@ template <class ELFT> void createSyntheticSections() {
add(in.ibtPlt); add(in.ibtPlt);
} }
in.plt = make<PltSection>(); in.plt = config->emachine == EM_PPC ? make<PPC32GlinkSection>()
: make<PltSection>();
add(in.plt); add(in.plt);
in.iplt = make<IpltSection>(); in.iplt = make<IpltSection>();
add(in.iplt); add(in.iplt);