Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -39,7 +39,15 @@ // section class InputSectionData { public: - enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions, MipsAbiFlags }; + enum Kind { + Regular, + EHFrame, + Merge, + MipsReginfo, + MipsOptions, + MipsAbiFlags, + Synthetic + }; // The garbage collector sets sections' Live bits. // If GC is disabled, all sections are considered live by default. @@ -235,10 +243,11 @@ typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::uint uintX_t; + typedef InputSectionData::Kind Kind; public: InputSection(uintX_t Flags, uint32_t Type, uintX_t Addralign, - ArrayRef Data, StringRef Name); + ArrayRef Data, StringRef Name, Kind K = Base::Regular); InputSection(ObjectFile *F, const Elf_Shdr *Header, StringRef Name); // Write this section to a mmap'ed file, assuming Buf is pointing to Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -14,6 +14,7 @@ #include "InputFiles.h" #include "LinkerScript.h" #include "OutputSections.h" +#include "SyntheticSections.h" #include "Target.h" #include "Thunks.h" @@ -80,9 +81,12 @@ } template size_t InputSectionBase::getSize() const { - if (auto *D = dyn_cast>(this)) + if (auto *S = dyn_cast>(this)) { + return S->getSize(); + } else if (auto *D = dyn_cast>(this)) { if (D->getThunksSize() > 0) return D->getThunkOff() + D->getThunksSize(); + } return Data.size(); } @@ -95,6 +99,7 @@ typename ELFT::uint InputSectionBase::getOffset(uintX_t Offset) const { switch (kind()) { case Regular: + case Synthetic: return cast>(this)->OutSecOff + Offset; case EHFrame: // The file crtbeginT.o has relocations pointing to the start of an empty @@ -192,10 +197,10 @@ template InputSection::InputSection(uintX_t Flags, uint32_t Type, uintX_t Addralign, ArrayRef Data, - StringRef Name) + StringRef Name, Kind K) : InputSectionBase(nullptr, Flags, Type, /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Addralign, - Data, Name, Base::Regular) {} + Data, Name, K) {} template InputSection::InputSection(elf::ObjectFile *F, @@ -204,7 +209,7 @@ template bool InputSection::classof(const InputSectionData *S) { - return S->kind() == Base::Regular; + return S->kind() == Base::Regular || S->kind() == Base::Synthetic; } template @@ -492,6 +497,11 @@ return; } + if (auto *S = dyn_cast>(this)) { + S->writeTo(Buf); + return; + } + // Copy section contents from source object file to output file. ArrayRef Data = this->Data; memcpy(Buf + OutSecOff, Data.data(), Data.size()); Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -54,7 +54,6 @@ EHFrameHdr, GnuHashTable, Got, - GotPlt, HashTable, Merge, MipsReginfo, @@ -220,24 +219,6 @@ void writeMipsGot(uint8_t *Buf); }; -template -class GotPltSection final : public OutputSectionBase { - typedef typename ELFT::uint uintX_t; - typedef OutputSectionBase Base; - -public: - GotPltSection(); - void finalize() override; - void writeTo(uint8_t *Buf) override; - void addEntry(SymbolBody &Sym); - bool empty() const; - typename Base::Kind getKind() const override { return Base::GotPlt; } - static bool classof(const Base *B) { return B->getKind() == Base::GotPlt; } - -private: - std::vector Entries; -}; - template class PltSection final : public OutputSectionBase { typedef OutputSectionBase Base; typedef typename ELFT::uint uintX_t; @@ -611,12 +592,15 @@ int32_t Tag; union { OutputSectionBase *OutSec; + InputSection *InSec; uint64_t Val; const SymbolBody *Sym; }; - enum KindT { SecAddr, SecSize, SymAddr, PlainInt } Kind; + enum KindT { SecAddr, SecSize, SymAddr, PlainInt, InSecAddr } Kind; Entry(int32_t Tag, OutputSectionBase *OutSec, KindT Kind = SecAddr) : Tag(Tag), OutSec(OutSec), Kind(Kind) {} + Entry(int32_t Tag, InputSection *Sec) + : Tag(Tag), InSec(Sec), Kind(InSecAddr) {} Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {} Entry(int32_t Tag, const SymbolBody *Sym) : Tag(Tag), Sym(Sym), Kind(SymAddr) {} @@ -740,7 +724,6 @@ static EhOutputSection *EhFrame; static GdbIndexSection *GdbIndex; static GnuHashTableSection *GnuHashTab; - static GotPltSection *GotPlt; static GotSection *Got; static HashTableSection *HashTab; static OutputSection *Bss; @@ -806,7 +789,6 @@ template EhOutputSection *Out::EhFrame; template GdbIndexSection *Out::GdbIndex; template GnuHashTableSection *Out::GnuHashTab; -template GotPltSection *Out::GotPlt; template GotSection *Out::Got; template HashTableSection *Out::HashTab; template OutputSection *Out::Bss; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -102,35 +102,6 @@ } template -GotPltSection::GotPltSection() - : OutputSectionBase(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) { - this->Header.sh_addralign = Target->GotPltEntrySize; -} - -template void GotPltSection::addEntry(SymbolBody &Sym) { - Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size(); - Entries.push_back(&Sym); -} - -template bool GotPltSection::empty() const { - return Entries.empty(); -} - -template void GotPltSection::finalize() { - this->Header.sh_size = (Target->GotPltHeaderEntriesNum + Entries.size()) * - Target->GotPltEntrySize; -} - -template void GotPltSection::writeTo(uint8_t *Buf) { - Target->writeGotPltHeader(Buf); - Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize; - for (const SymbolBody *B : Entries) { - Target->writeGotPlt(Buf, *B); - Buf += sizeof(uintX_t); - } -} - -template GotSection::GotSection() : OutputSectionBase(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) { if (Config->EMachine == EM_MIPS) @@ -772,7 +743,7 @@ Add({DT_JMPREL, Out::RelaPlt}); Add({DT_PLTRELSZ, Out::RelaPlt->getSize()}); Add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT, - Out::GotPlt}); + In::GotPlt}); Add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)}); } @@ -843,6 +814,9 @@ case Entry::SecAddr: P->d_un.d_ptr = E.OutSec->getVA(); break; + case Entry::InSecAddr: + P->d_un.d_ptr = E.InSec->OutSec->getVA() + E.InSec->OutSecOff; + break; case Entry::SecSize: P->d_un.d_val = E.OutSec->getSize(); break; @@ -1863,6 +1837,7 @@ uint32_t Type = C->Type; switch (C->kind()) { case InputSectionBase::Regular: + case InputSectionBase::Synthetic: Sec = make>(Key.Name, Type, Flags); break; case InputSectionBase::EHFrame: @@ -1927,11 +1902,6 @@ template class EhFrameHeader; template class EhFrameHeader; -template class GotPltSection; -template class GotPltSection; -template class GotPltSection; -template class GotPltSection; - template class GotSection; template class GotSection; template class GotSection; Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -44,10 +44,11 @@ #include "Relocations.h" #include "Config.h" #include "OutputSections.h" +#include "Strings.h" #include "SymbolTable.h" +#include "SyntheticSections.h" #include "Target.h" #include "Thunks.h" -#include "Strings.h" #include "llvm/Support/Endian.h" #include "llvm/Support/raw_ostream.h" @@ -753,8 +754,8 @@ else Rel = Target->PltRel; - Out::GotPlt->addEntry(Body); - Out::RelaPlt->addReloc({Rel, Out::GotPlt, + In::GotPlt->addEntry(Body); + Out::RelaPlt->addReloc({Rel, In::GotPlt, Body.getGotPltOffset(), !Preemptible, &Body, 0}); continue; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -159,7 +159,7 @@ } template typename ELFT::uint SymbolBody::getGotPltVA() const { - return Out::GotPlt->getVA() + getGotPltOffset(); + return In::GotPlt->getVA() + getGotPltOffset(); } template typename ELFT::uint SymbolBody::getGotPltOffset() const { Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -15,6 +15,26 @@ namespace lld { namespace elf { +template class SyntheticSection : public InputSection { + typedef typename ELFT::uint uintX_t; + +public: + SyntheticSection(uintX_t Flags, uint32_t Type, uintX_t Addralign, + StringRef Name) + : InputSection(Flags, Type, Addralign, ArrayRef(), Name, + InputSectionData::Synthetic) {} + + virtual void writeTo(uint8_t *Buf) {} + virtual size_t getSize() const { return this->Data.size(); } + + static bool classof(const InputSectionData *D) { + return D->kind() == InputSectionData::Synthetic; + } + +protected: + ~SyntheticSection() = default; +}; + // .note.gnu.build-id section. template class BuildIdSection : public InputSection { public: @@ -69,15 +89,33 @@ template InputSection *createCommonSection(); template InputSection *createInterpSection(); +template +class GotPltSection final : public SyntheticSection { + typedef typename ELFT::uint uintX_t; + +public: + GotPltSection(); + void addEntry(SymbolBody &Sym); + bool empty() const; + size_t getSize() const override; + void writeTo(uint8_t *Buf) override; + uintX_t getVA() { return this->OutSec->getVA() + this->OutSecOff; } + +private: + std::vector Entries; +}; + // Linker generated sections which can be used as inputs. template struct In { static BuildIdSection *BuildId; static InputSection *Common; + static GotPltSection *GotPlt; static InputSection *Interp; }; template BuildIdSection *In::BuildId; template InputSection *In::Common; +template GotPltSection *In::GotPlt; template InputSection *In::Interp; } // namespace elf Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -22,6 +22,7 @@ #include "OutputSections.h" #include "Strings.h" #include "SymbolTable.h" +#include "Target.h" #include "lld/Core/Parallel.h" #include "llvm/Support/Endian.h" @@ -188,6 +189,36 @@ Config->BuildIdVector.size()); } +template +GotPltSection::GotPltSection() + : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, + Target->GotPltEntrySize, ".got.plt") { + this->Live = true; +} + +template void GotPltSection::addEntry(SymbolBody &Sym) { + Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size(); + Entries.push_back(&Sym); +} + +template bool GotPltSection::empty() const { + return Entries.empty(); +} + +template size_t GotPltSection::getSize() const { + return (Target->GotPltHeaderEntriesNum + Entries.size()) * + Target->GotPltEntrySize; +} + +template void GotPltSection::writeTo(uint8_t *Buf) { + Target->writeGotPltHeader(Buf); + Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize; + for (const SymbolBody *B : Entries) { + Target->writeGotPlt(Buf, *B); + Buf += sizeof(uintX_t); + } +} + template InputSection *elf::createCommonSection(); template InputSection *elf::createCommonSection(); template InputSection *elf::createCommonSection(); @@ -227,3 +258,8 @@ template class elf::BuildIdHexstring; template class elf::BuildIdHexstring; template class elf::BuildIdHexstring; + +template class elf::GotPltSection; +template class elf::GotPltSection; +template class elf::GotPltSection; +template class elf::GotPltSection; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -29,6 +29,7 @@ #include "InputFiles.h" #include "OutputSections.h" #include "Symbols.h" +#include "SyntheticSections.h" #include "Thunks.h" #include "Writer.h" @@ -403,7 +404,7 @@ 0x90, 0x90, 0x90, 0x90 // nop; nop; nop; nop }; memcpy(Buf, PltData, sizeof(PltData)); - uint32_t Got = Out::GotPlt->getVA(); + uint32_t Got = In::GotPlt->getVA(); write32le(Buf + 2, Got + 4); write32le(Buf + 8, Got + 8); } @@ -420,7 +421,7 @@ // jmp *foo@GOT(%ebx) or jmp *foo_in_GOT Buf[1] = Config->Pic ? 0xa3 : 0x25; - uint32_t Got = Out::GotPlt->getVA(); + uint32_t Got = In::GotPlt->getVA(); write32le(Buf + 2, Config->Shared ? GotEntryAddr - Got : GotEntryAddr); write32le(Buf + 7, RelOff); write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16); @@ -613,7 +614,7 @@ 0x0f, 0x1f, 0x40, 0x00 // nopl 0x0(rax) }; memcpy(Buf, PltData, sizeof(PltData)); - uint64_t Got = Out::GotPlt->getVA(); + uint64_t Got = In::GotPlt->getVA(); uint64_t Plt = Out::Plt->getVA(); write32le(Buf + 2, Got - Plt + 2); // GOT+8 write32le(Buf + 8, Got - Plt + 4); // GOT+16 @@ -1274,7 +1275,7 @@ }; memcpy(Buf, PltData, sizeof(PltData)); - uint64_t Got = Out::GotPlt->getVA(); + uint64_t Got = In::GotPlt->getVA(); uint64_t Plt = Out::Plt->getVA(); relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, getAArch64Page(Got + 16) - getAArch64Page(Plt + 4)); @@ -1628,7 +1629,7 @@ 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8 }; memcpy(Buf, PltData, sizeof(PltData)); - uint64_t GotPlt = Out::GotPlt->getVA(); + uint64_t GotPlt = In::GotPlt->getVA(); uint64_t L1 = Out::Plt->getVA() + 8; write32le(Buf + 16, GotPlt - L1 - 8); } @@ -2063,7 +2064,7 @@ write32(Buf + 20, 0x0018c082); // srl $24, $24, 2 write32(Buf + 24, 0x0320f809); // jalr $25 write32(Buf + 28, 0x2718fffe); // subu $24, $24, 2 - uint64_t Got = Out::GotPlt->getVA(); + uint64_t Got = In::GotPlt->getVA(); writeMipsHi16(Buf, Got); writeMipsLo16(Buf + 4, Got); writeMipsLo16(Buf + 8, Got); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -249,7 +249,6 @@ if (Config->GdbIndex) Out::GdbIndex = make>(); - Out::GotPlt = make>(); Out::RelaPlt = make>( Config->Rela ? ".rela.plt" : ".rel.plt", false /*Sort*/); if (Config->Strip != StripPolicy::All) { @@ -292,6 +291,8 @@ In::Common = Common; Symtab::X->Sections.push_back(Common); } + + In::GotPlt = make>(); } template @@ -404,7 +405,7 @@ if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY || Type == SHT_PREINIT_ARRAY) return true; - if (Sec == Out::GotPlt) + if (Sec == In::GotPlt->OutSec) return Config->ZNow; if (Sec == Out::Dynamic || Sec == Out::Got) return true; @@ -850,6 +851,12 @@ // This function adds linker-created Out::* sections. addPredefinedSections(); + // Add .got.plt section if it is not empty. + if (!In::GotPlt->empty()) { + addInputSec(In::GotPlt); + In::GotPlt->OutSec->assignOffsets(); + } + sortSections(); unsigned I = 1; @@ -933,8 +940,6 @@ if (needsGot()) Add(Out::Got); - if (Out::GotPlt && !Out::GotPlt->empty()) - Add(Out::GotPlt); if (!Out::Plt->empty()) Add(Out::Plt); if (!Out::EhFrame->empty())