diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp index b3cc78710e9..249c9634f0a 100644 --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -71,12 +71,17 @@ void writePPC32GlinkSection(uint8_t *buf, size_t numEntries) { // 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; + // Canonical symbols can be in a different order from PLT symbols. + uint32_t canonical = 1; + for (; canonical < (in.plt->headerSize/16); ) { + for (const Symbol *sym : in.plt->entries) + if (sym->needsPltAddr && sym->canonicalPltIndex == canonical) { + writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0); + buf += 16; + glink += 16; + canonical++; } + } } // 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 index 93ec0661071..f778bf35b2f 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1206,6 +1206,7 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type, // PPC32 canonical PLT entries are at the beginning of .glink cast(sym).value = in.plt->headerSize; in.plt->headerSize += 16; + sym.canonicalPltIndex = in.plt->headerSize / 16; } } sym.needsPltAddr = true; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index ac606198afd..2b41698f97f 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -78,6 +78,7 @@ public: uint32_t dynsymIndex = 0; uint32_t gotIndex = -1; uint32_t pltIndex = -1; + uint32_t canonicalPltIndex = -1; uint32_t globalDynIndex = -1;