diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -76,12 +76,11 @@ // non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE. uint32_t glink = in.plt->getVA(); // VA of .glink if (!config->isPic) { - for (const Symbol *sym : in.plt->entries) - if (sym->needsPltAddr) { - writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0); - buf += 16; - glink += 16; - } + for (const Symbol *sym : cast(in.plt)->canonical_plts) { + writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0); + buf += 16; + glink += 16; + } } // On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1226,6 +1226,7 @@ // PPC32 canonical PLT entries are at the beginning of .glink cast(sym).value = in.plt->headerSize; in.plt->headerSize += 16; + cast(in.plt)->canonical_plts.push_back(&sym); } } sym.needsPltAddr = true; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -684,7 +684,6 @@ size_t getNumEntries() const { return entries.size(); } size_t headerSize; - size_t footerSize = 0; std::vector entries; }; @@ -705,6 +704,16 @@ void addEntry(Symbol &sym); }; +class PPC32GlinkSection : public PltSection { +public: + PPC32GlinkSection(); + void writeTo(uint8_t *buf) override; + size_t getSize() const override; + + std::vector canonical_plts; + static constexpr size_t footerSize = 64; +}; + // This is x86-only. class IBTPltSection : public SyntheticSection { public: diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2447,12 +2447,9 @@ : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"), headerSize(target->pltHeaderSize) { // On PowerPC, this section contains lazy symbol resolvers. - if (config->emachine == EM_PPC || config->emachine == EM_PPC64) { + if (config->emachine == EM_PPC64) { name = ".glink"; 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 @@ -2468,11 +2465,6 @@ } 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 // linker to resolve dynsyms at runtime. Write such code. target->writePltHeader(buf); @@ -2490,7 +2482,7 @@ } size_t PltSection::getSize() const { - return headerSize + entries.size() * target->pltEntrySize + footerSize; + return headerSize + entries.size() * target->pltEntrySize; } bool PltSection::isNeeded() const { @@ -2544,6 +2536,19 @@ } } +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 // 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. diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -525,7 +525,8 @@ add(in.ibtPlt); } - in.plt = make(); + in.plt = config->emachine == EM_PPC ? make() + : make(); add(in.plt); in.iplt = make(); add(in.iplt);