Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -487,13 +487,13 @@ size_t Size = 0; }; -// The PltSection is used for both the Plt and Iplt. The former always has a +// The PltSection is used for both the Plt and Iplt. The former usually has a // header as its first entry that is used at run-time to resolve lazy binding. // The latter is used for GNU Ifunc symbols, that will be subject to a // Target->IRelativeRel. class PltSection : public SyntheticSection { public: - PltSection(size_t HeaderSize); + PltSection(size_t HeaderSize, bool IsIplt); void writeTo(uint8_t *Buf) override; size_t getSize() const override; bool empty() const override { return Entries.empty(); } @@ -504,8 +504,8 @@ private: unsigned getPltRelocOff() const; std::vector> Entries; - // Iplt always has HeaderSize of 0, the Plt HeaderSize is always non-zero size_t HeaderSize; + bool IsIplt; }; // GdbIndexChunk is created for each .debug_info section and contains Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1858,9 +1858,9 @@ } } -PltSection::PltSection(size_t S) +PltSection::PltSection(size_t HeaderSize, bool IsIplt) : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"), - HeaderSize(S) { + HeaderSize(HeaderSize), IsIplt(IsIplt) { // The PLT needs to be writable on SPARC as the dynamic linker will // modify the instructions in the PLT entries. if (Config->EMachine == EM_SPARCV9) @@ -1870,7 +1870,7 @@ void PltSection::writeTo(uint8_t *Buf) { // At beginning of PLT but not the IPLT, we have code to call the dynamic // linker to resolve dynsyms at runtime. Write such code. - if (HeaderSize != 0) + if (!IsIplt) Target->writePltHeader(Buf); size_t Off = HeaderSize; // The IPlt is immediately after the Plt, account for this in RelOff @@ -1889,7 +1889,7 @@ template void PltSection::addEntry(Symbol &Sym) { Sym.PltIndex = Entries.size(); RelocationBaseSection *PltRelocSection = InX::RelaPlt; - if (HeaderSize == 0) { + if (IsIplt) { PltRelocSection = InX::RelaIplt; Sym.IsInIplt = true; } @@ -1906,7 +1906,7 @@ // example ARM uses mapping symbols to aid disassembly void PltSection::addSymbols() { // The PLT may have symbols defined for the Header, the IPLT has no header - if (HeaderSize != 0) + if (!IsIplt) Target->addPltHeaderSymbols(*this); size_t Off = HeaderSize; for (size_t I = 0; I < Entries.size(); ++I) { @@ -1916,7 +1916,7 @@ } unsigned PltSection::getPltRelocOff() const { - return (HeaderSize == 0) ? InX::Plt->getSize() : 0; + return IsIplt ? InX::Plt->getSize() : 0; } // The string hash function for .gdb_index. Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -369,9 +369,9 @@ false /*Sort*/); Add(InX::RelaIplt); - InX::Plt = make(Target->PltHeaderSize); + InX::Plt = make(Target->PltHeaderSize, false /*IsIplt*/); Add(InX::Plt); - InX::Iplt = make(0); + InX::Iplt = make(0 /*HeaderSize*/, true /*IsIplt*/); Add(InX::Iplt); if (!Config->Relocatable) { Index: test/ELF/ppc64-ifunc.s =================================================================== --- test/ELF/ppc64-ifunc.s +++ test/ELF/ppc64-ifunc.s @@ -0,0 +1,41 @@ +# REQUIRES: ppc +# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t2.so +# RUN: ld.lld %t.o %t2.so -o %t +# RUN: llvm-objdump -d %t | FileCheck %s + +# CHECK: _start: +# CHECK-NEXT: 10010004: {{.*}} bl .+12 +# CHECK-NEXT: 10010008: {{.*}} bl .+40 + +# 0x10010004 + 12 = 0x10010010 (PLT entry 0) +# 0x10010008 + 40 = 0x10010030 (PLT entry 1) + +# CHECK: Disassembly of section .plt: +# CHECK: 10010010: {{.*}} std 2, 40(1) +# CHECK-NEXT: 10010014: {{.*}} addis 11, 2, 4098 +# CHECK-NEXT: 10010018: {{.*}} ld 12, -32744(11) +# CHECK-NEXT: 1001001c: {{.*}} ld 11, 0(12) +# CHECK-NEXT: 10010020: {{.*}} mtctr 11 +# CHECK-NEXT: 10010024: {{.*}} ld 2, 8(12) +# CHECK-NEXT: 10010028: {{.*}} ld 11, 16(12) +# CHECK-NEXT: 1001002c: {{.*}} bctr +# CHECK-NEXT: 10010030: {{.*}} std 2, 40(1) +# CHECK-NEXT: 10010034: {{.*}} addis 11, 2, 4098 +# CHECK-NEXT: 10010038: {{.*}} ld 12, -32736(11) +# CHECK-NEXT: 1001003c: {{.*}} ld 11, 0(12) +# CHECK-NEXT: 10010040: {{.*}} mtctr 11 +# CHECK-NEXT: 10010044: {{.*}} ld 2, 8(12) +# CHECK-NEXT: 10010048: {{.*}} ld 11, 16(12) +# CHECK-NEXT: 1001004c: {{.*}} bctr + +.type ifunc STT_GNU_IFUNC +.globl ifunc +ifunc: + nop + +.global _start +_start: + bl bar + bl ifunc