diff options
| -rw-r--r-- | lld/ELF/SyntheticSections.cpp | 76 | ||||
| -rw-r--r-- | lld/ELF/SyntheticSections.h | 35 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 4 |
3 files changed, 40 insertions, 75 deletions
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index b43d52bbc3f..70a338b6e3e 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1434,19 +1434,23 @@ template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) { } template <class ELFT> -PltSection<ELFT>::PltSection() +PltSection<ELFT>::PltSection(size_t S) : SyntheticSection<ELFT>(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, - ".plt") {} + ".plt"), + HeaderSize(S) {} template <class ELFT> void PltSection<ELFT>::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; + // 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) + Target->writePltHeader(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<ELFT>(); uint64_t Plt = this->getVA() + Off; Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); @@ -1456,61 +1460,34 @@ template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) { template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody &Sym) { Sym.PltIndex = Entries.size(); - unsigned RelOff = In<ELFT>::RelaPlt->getRelocOffset(); + RelocationSection<ELFT> *PltRelocSection = In<ELFT>::RelaPlt; + if (HeaderSize == 0) { + PltRelocSection = In<ELFT>::RelaIplt; + Sym.IsInIplt = true; + } + unsigned RelOff = PltRelocSection->getRelocOffset(); Entries.push_back(std::make_pair(&Sym, RelOff)); } template <class ELFT> size_t PltSection<ELFT>::getSize() const { - return Target->PltHeaderSize + Entries.size() * Target->PltEntrySize; + 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 <class ELFT> void PltSection<ELFT>::addSymbols() { - Target->addPltHeaderSymbols(this); - size_t Off = Target->PltHeaderSize; + // The PLT may have symbols defined for the Header, the IPLT has no header + if (HeaderSize != 0) + Target->addPltHeaderSymbols(this); + size_t Off = HeaderSize; for (size_t I = 0; I < Entries.size(); ++I) { Target->addPltSymbols(this, Off); Off += Target->PltEntrySize; } } -template <class ELFT> -IpltSection<ELFT>::IpltSection() - : SyntheticSection<ELFT>(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, - ".plt") {} - -template <class ELFT> void IpltSection<ELFT>::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<ELFT>::Plt->getSize(); - uint64_t Got = B->getGotPltVA<ELFT>(); - uint64_t Plt = this->getVA() + Off; - Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); - Off += Target->PltEntrySize; - } -} - -template <class ELFT> void IpltSection<ELFT>::addEntry(SymbolBody &Sym) { - Sym.PltIndex = Entries.size(); - Sym.IsInIplt = true; - unsigned RelOff = In<ELFT>::RelaIplt->getRelocOffset(); - Entries.push_back(std::make_pair(&Sym, RelOff)); -} - -template <class ELFT> size_t IpltSection<ELFT>::getSize() const { - return Entries.size() * Target->PltEntrySize; -} - -template <class ELFT> void IpltSection<ELFT>::addSymbols() { - size_t Off = 0; - for (size_t I = 0; I < Entries.size(); ++I) { - Target->addPltSymbols(this, Off); - Off += Target->PltEntrySize; - } +template <class ELFT> unsigned PltSection<ELFT>::getPltRelocOff() const { + return (HeaderSize == 0) ? In<ELFT>::Plt->getSize() : 0; } template <class ELFT> @@ -2118,11 +2095,6 @@ template class elf::PltSection<ELF32BE>; template class elf::PltSection<ELF64LE>; template class elf::PltSection<ELF64BE>; -template class elf::IpltSection<ELF32LE>; -template class elf::IpltSection<ELF32BE>; -template class elf::IpltSection<ELF64LE>; -template class elf::IpltSection<ELF64BE>; - template class elf::GdbIndexSection<ELF32LE>; template class elf::GdbIndexSection<ELF32BE>; template class elf::GdbIndexSection<ELF64LE>; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index ff25c5f80a7..5765086710c 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -234,7 +234,7 @@ private: std::vector<const SymbolBody *> Entries; }; -// The IgotPltSection is a Got associated with the IpltSection for GNU Ifunc +// The IgotPltSection is a Got associated with the PltSection for GNU Ifunc // Symbols that will be relocated by Target->IRelativeRel. // On most Targets the IgotPltSection will immediately follow the GotPltSection // on ARM the IgotPltSection will immediately follow the GotSection. @@ -461,25 +461,13 @@ private: size_t Size = 0; }; -template <class ELFT> class PltSection final : public SyntheticSection<ELFT> { +// The PltSection is used for both the Plt and Iplt. The former always 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. +template <class ELFT> class PltSection : public SyntheticSection<ELFT> { public: - PltSection(); - 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<std::pair<const SymbolBody *, unsigned>> Entries; -}; - -// 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 ELFT> class IpltSection final : public SyntheticSection<ELFT> { -public: - IpltSection(); + PltSection(size_t HeaderSize); void writeTo(uint8_t *Buf) override; size_t getSize() const override; void addEntry(SymbolBody &Sym); @@ -487,7 +475,12 @@ public: void addSymbols(); private: + void writeHeader(uint8_t *Buf){}; + void addHeaderSymbols(){}; + unsigned getPltRelocOff() const; std::vector<std::pair<const SymbolBody *, unsigned>> Entries; + // Iplt always has HeaderSize of 0, the Plt HeaderSize is always non-zero + size_t HeaderSize; }; template <class ELFT> @@ -777,7 +770,7 @@ template <class ELFT> struct In { static InputSection<ELFT> *Interp; static MipsRldMapSection<ELFT> *MipsRldMap; static PltSection<ELFT> *Plt; - static IpltSection<ELFT> *Iplt; + static PltSection<ELFT> *Iplt; static RelocationSection<ELFT> *RelaDyn; static RelocationSection<ELFT> *RelaPlt; static RelocationSection<ELFT> *RelaIplt; @@ -806,7 +799,7 @@ template <class ELFT> HashTableSection<ELFT> *In<ELFT>::HashTab; template <class ELFT> InputSection<ELFT> *In<ELFT>::Interp; template <class ELFT> MipsRldMapSection<ELFT> *In<ELFT>::MipsRldMap; template <class ELFT> PltSection<ELFT> *In<ELFT>::Plt; -template <class ELFT> IpltSection<ELFT> *In<ELFT>::Iplt; +template <class ELFT> PltSection<ELFT> *In<ELFT>::Iplt; template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaDyn; template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaPlt; template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaIplt; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 81c01b06824..e158b7e8a50 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -426,9 +426,9 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() { false /*Sort*/); Add(In<ELFT>::RelaIplt); - In<ELFT>::Plt = make<PltSection<ELFT>>(); + In<ELFT>::Plt = make<PltSection<ELFT>>(Target->PltHeaderSize); Add(In<ELFT>::Plt); - In<ELFT>::Iplt = make<IpltSection<ELFT>>(); + In<ELFT>::Iplt = make<PltSection<ELFT>>(0); Add(In<ELFT>::Iplt); if (Config->EhFrameHdr) { |

