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 @@ -137,6 +137,16 @@ // Pad with nop. They should not be executed. for (; buf < end; buf += 4) write32(buf, 0x60000000); + + // Create canonical PLT entries for non-PIE code. Compilers don't generate + // non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE. + if (config->isPic) + return; + for (const Symbol *sym : in.plt->entries) + if (sym->needsPltAddr) { + writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0); + buf += 16; + } } PPC::PPC() { diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1198,10 +1198,13 @@ getLocation(sec, sym, offset)); if (!sym.isInPlt()) addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym); - if (!sym.isDefined()) + if (!sym.isDefined()) { replaceWithDefined( sym, in.plt, target->pltHeaderSize + target->pltEntrySize * sym.pltIndex, 0); + if (config->emachine == EM_PPC) + in.plt->footerSize += 16; + } sym.needsPltAddr = true; sec.relocations.push_back({expr, type, offset, addend, &sym}); return; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -683,9 +683,9 @@ void addEntry(Symbol &sym); size_t getNumEntries() const { return entries.size(); } - size_t headerSize = 0; + size_t headerSize; + size_t footerSize = 0; -private: std::vector entries; }; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -2486,7 +2486,7 @@ } size_t PltSection::getSize() const { - return headerSize + entries.size() * target->pltEntrySize; + return headerSize + entries.size() * target->pltEntrySize + footerSize; } bool PltSection::isNeeded() const { diff --git a/lld/test/ELF/ppc32-canonical-plt.s b/lld/test/ELF/ppc32-canonical-plt.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc32-canonical-plt.s @@ -0,0 +1,57 @@ +# REQUIRES: ppc + +## Test that we create canonical PLT entries for -no-pie. + +# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=powerpc %p/Inputs/canonical-plt-pcrel.s -o %t1.o +# RUN: ld.lld %t1.o -o %t1.so -shared -soname=so + +# RUN: ld.lld %t.o %t1.so -o %t +# RUN: llvm-readobj -r %t | FileCheck --check-prefix=REL %s +# RUN: llvm-readelf -S --dyn-syms %t | FileCheck --check-prefix=SYM %s +# RUN: llvm-readelf -x .plt %t | FileCheck --check-prefix=HEX %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s + +# REL: Relocations [ +# REL-NEXT: .rela.plt { +# REL-NEXT: R_PPC_JMP_SLOT func 0x0 +# REL-NEXT: R_PPC_JMP_SLOT ifunc 0x0 +# REL-NEXT: } +# REL-NEXT: ] + +# SYM: .glink PROGBITS 100101dc + +## The canonical PLT entry of func is at &.glink[0] +## The canonical PLT entry of ifunc is at &.glink[1] +# SYM: 1001021c 0 FUNC GLOBAL DEFAULT UND func +# SYM: 10010220 0 FUNC GLOBAL DEFAULT UND ifunc + +# HEX: 0x100302b4 100101dc 100101e0 + +## The first 2 instructions are referenced by .plt entries. +# CHECK: 100101dc .glink: +# CHECK-NEXT: b .+8 +# CHECK-NEXT: b .+4 +## Followed by PLTresolve of 64 bytes. + +## Canonical PLT entry of func. +## 0x100101dc + 4*2 + 64 = 0x10010224 +## 0x1001021c = 65536*4099+692 +# CHECK: 10010224: lis 11, 4099 +# CHECK-NEXT: lwz 11, 692(11) +# CHECK-NEXT: mtctr 11 +# CHECK-NEXT: bctr + +## Canonical PLT entry of ifunc. +## 0x10010220 = 65536*4099+696 +# CHECK-NEXT: 10010234: lis 11, 4099 +# CHECK-NEXT: lwz 11, 696(11) +# CHECK-NEXT: mtctr 11 +# CHECK-NEXT: bctr + +.globl _start +_start: + lis 3, func@ha + la 3, func@l(3) + lis 4, ifunc@ha + la 4, ifunc@l(4)