Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -457,9 +457,10 @@ size_t Size = 0; }; -template class PltSection final : public SyntheticSection { +// Common base class for Plt and IPlt. +template class PltSectionBase : public SyntheticSection { public: - PltSection(); + PltSectionBase(size_t HeaderSize, RelocationSection *PltRelSec); void writeTo(uint8_t *Buf) override; size_t getSize() const override; void addEntry(SymbolBody &Sym); @@ -467,23 +468,36 @@ void addSymbols(); private: + virtual void writeHeader(uint8_t *Buf){}; + virtual void addHeaderSymbols(){}; + virtual unsigned getPltRelocOff() const = 0; std::vector> Entries; + // IPlt always has HeaderSize of 0 + size_t HeaderSize; + RelocationSection *PltRelocSection; +}; + +// The traditional Plt section for non GNU Ifunc symbols. This always has a +// header as the first entry to facilitate lazy binding at run time. +template class PltSection final : public PltSectionBase { +public: + PltSection(); + +private: + virtual void writeHeader(uint8_t *Buf) override; + virtual void addHeaderSymbols() override; + virtual unsigned getPltRelocOff() const override { return 0; } }; // The IpltSection is a variant of Plt for recording entries for GNU Ifunc // symbols that will be subject to a Target->IRelativeRel // The IpltSection immediately follows the Plt section in the Output Section -template class IpltSection final : public SyntheticSection { +template class IpltSection final : public PltSectionBase { public: IpltSection(); - void writeTo(uint8_t *Buf) override; - size_t getSize() const override; - void addEntry(SymbolBody &Sym); - bool empty() const override { return Entries.empty(); } - void addSymbols(); private: - std::vector> Entries; + virtual unsigned getPltRelocOff() const override; }; template Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1427,19 +1427,23 @@ } template -PltSection::PltSection() +PltSectionBase::PltSectionBase(size_t S, + RelocationSection *PltRelSec) : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, - ".plt") {} + ".plt"), + HeaderSize(S), PltRelocSection(PltRelSec) {} -template void PltSection::writeTo(uint8_t *Buf) { - // At beginning of PLT, we have code to call the dynamic linker - // to resolve dynsyms at runtime. Write such code. - Target->writePltHeader(Buf); - size_t Off = Target->PltHeaderSize; +template void PltSectionBase::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. + writeHeader(Buf); + size_t Off = HeaderSize; + // The IPlt is immediately after the Plt, account for this in RelOff + unsigned PltOff = getPltRelocOff(); for (auto &I : Entries) { const SymbolBody *B = I.first; - unsigned RelOff = I.second; + unsigned RelOff = I.second + PltOff; uint64_t Got = B->getGotPltVA(); uint64_t Plt = this->getVA() + Off; Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); @@ -1447,21 +1451,24 @@ } } -template void PltSection::addEntry(SymbolBody &Sym) { +template void PltSectionBase::addEntry(SymbolBody &Sym) { Sym.PltIndex = Entries.size(); - unsigned RelOff = In::RelaPlt->getRelocOffset(); + unsigned RelOff = PltRelocSection->getRelocOffset(); + Sym.IsInIplt = HeaderSize == 0; Entries.push_back(std::make_pair(&Sym, RelOff)); } -template size_t PltSection::getSize() const { - return Target->PltHeaderSize + Entries.size() * Target->PltEntrySize; +template size_t PltSectionBase::getSize() const { + return HeaderSize + Entries.size() * Target->PltEntrySize; } // Some architectures such as additional symbols in the PLT section. For // example ARM uses mapping symbols to aid disassembly -template void PltSection::addSymbols() { - Target->addPltHeaderSymbols(this); - size_t Off = Target->PltHeaderSize; +template void PltSectionBase::addSymbols() { + // The PLT may have symbols defined for the Header, the IPLT has no header + addHeaderSymbols(); + size_t Off = HeaderSize; + for (size_t I = 0; I < Entries.size(); ++I) { Target->addPltSymbols(this, Off); Off += Target->PltEntrySize; @@ -1469,41 +1476,25 @@ } template -IpltSection::IpltSection() - : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, - ".plt") {} +PltSection::PltSection() + : PltSectionBase(Target->PltHeaderSize, In::RelaPlt) {} -template void IpltSection::writeTo(uint8_t *Buf) { - // The IRelative relocations do not support lazy binding so no header is - // needed - size_t Off = 0; - for (auto &I : Entries) { - const SymbolBody *B = I.first; - unsigned RelOff = I.second + In::Plt->getSize(); - uint64_t Got = B->getGotPltVA(); - uint64_t Plt = this->getVA() + Off; - Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); - Off += Target->PltEntrySize; - } +template void PltSection::writeHeader(uint8_t *Buf) { + Target->writePltHeader(Buf); } -template void IpltSection::addEntry(SymbolBody &Sym) { - Sym.PltIndex = Entries.size(); - Sym.IsInIplt = true; - unsigned RelOff = In::RelaIplt->getRelocOffset(); - Entries.push_back(std::make_pair(&Sym, RelOff)); +// Some architectures such as additional symbols in the PLT section. For +// example ARM uses mapping symbols to aid disassembly +template void PltSection::addHeaderSymbols() { + Target->addPltHeaderSymbols(this); } -template size_t IpltSection::getSize() const { - return Entries.size() * Target->PltEntrySize; -} +template +IpltSection::IpltSection() + : PltSectionBase(0, In::RelaIplt) {} -template void IpltSection::addSymbols() { - size_t Off = 0; - for (size_t I = 0; I < Entries.size(); ++I) { - Target->addPltSymbols(this, Off); - Off += Target->PltEntrySize; - } +template unsigned IpltSection::getPltRelocOff() const { + return In::Plt->getSize(); } template @@ -2101,6 +2092,11 @@ template class elf::HashTableSection; template class elf::HashTableSection; +template class elf::PltSectionBase; +template class elf::PltSectionBase; +template class elf::PltSectionBase; +template class elf::PltSectionBase; + template class elf::PltSection; template class elf::PltSection; template class elf::PltSection;