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 @@ -92,7 +92,7 @@ uint32_t glink = in.plt->getVA(); // VA of .glink const uint8_t *end = buf + 64; if (config->isPic) { - uint32_t afterBcl = in.plt->getSize() - target->pltHeaderSize + 12; + uint32_t afterBcl = in.plt->getSize() - 64 + 12; // 12 bytes from PLTresolve uint32_t gotBcl = got + 4 - (glink + afterBcl); write32(buf + 0, 0x3d6b0000 | ha(afterBcl)); // addis r11,r11,1f-glink@ha write32(buf + 4, 0x7c0802a6); // mflr r0 @@ -150,7 +150,7 @@ gotBaseSymInGotPlt = false; gotHeaderEntriesNum = 3; gotPltHeaderEntriesNum = 0; - pltHeaderSize = 64; // size of PLTresolve in .glink + pltHeaderSize = 0; // PLTresolve is a footer in .glink pltEntrySize = 4; ipltEntrySize = 16; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -684,6 +684,7 @@ size_t getNumEntries() const { return entries.size(); } size_t headerSize = 0; + 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 @@ -2449,6 +2449,9 @@ if (config->emachine == EM_PPC || config->emachine == EM_PPC64) { name = ".glink"; alignment = 4; + // PLTresolve is at the bottom of .glink + if (config->emachine == EM_PPC) + footerSize = 64; } // On x86 when IBT is enabled, this section contains the second PLT (lazy @@ -2486,7 +2489,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-pcrel.s b/lld/test/ELF/ppc32-canonical-plt-pcrel.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc32-canonical-plt-pcrel.s @@ -0,0 +1,32 @@ +# 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 %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: ] + +# CHECK: .glink PROGBITS 100101dc + +## The canonical PLT entry of func is at &.glink[0] +## The canonical PLT entry of ifunc is at &.glink[1] +# CHECK: 100101dc 0 FUNC GLOBAL DEFAULT UND func +# CHECK: 100101e0 0 FUNC GLOBAL DEFAULT UND ifunc + +.globl _start +_start: + lis 3, func@ha + la 3, func@l(3) + lis 4, ifunc@ha + la 4, ifunc@l(4)