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(bool IsIplt); void writeTo(uint8_t *Buf) override; size_t getSize() const override; bool empty() const override { return Entries.empty(); } @@ -503,9 +503,11 @@ private: unsigned getPltRelocOff() const; + unsigned getHeaderSize() const; + std::vector> Entries; - // Iplt always has HeaderSize of 0, the Plt HeaderSize is always non-zero - size_t HeaderSize; + // True if section is Iplt. + 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(bool IsIplt) : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"), - HeaderSize(S) { + 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,9 +1870,10 @@ 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; + + size_t Off = getHeaderSize(); // The IPlt is immediately after the Plt, account for this in RelOff unsigned PltOff = getPltRelocOff(); @@ -1889,7 +1890,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; } @@ -1899,16 +1900,16 @@ } size_t PltSection::getSize() const { - return HeaderSize + Entries.size() * Target->PltEntrySize; + return getHeaderSize() + Entries.size() * Target->PltEntrySize; } // Some architectures such as additional symbols in the PLT section. For // 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; + size_t Off = getHeaderSize(); for (size_t I = 0; I < Entries.size(); ++I) { Target->addPltSymbols(*this, Off); Off += Target->PltEntrySize; @@ -1916,7 +1917,11 @@ } unsigned PltSection::getPltRelocOff() const { - return (HeaderSize == 0) ? InX::Plt->getSize() : 0; + return IsIplt ? InX::Plt->getSize() : 0; +} + +unsigned PltSection::getHeaderSize() const { + return IsIplt ? 0 : Target->PltHeaderSize; } // 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(false /*IsIplt*/); Add(InX::Plt); - InX::Iplt = make(0); + InX::Iplt = make(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