Index: lld/trunk/ELF/InputSection.h =================================================================== --- lld/trunk/ELF/InputSection.h +++ lld/trunk/ELF/InputSection.h @@ -39,7 +39,7 @@ // section class InputSectionData { public: - enum Kind { Regular, EHFrame, Merge }; + enum Kind { Regular, EHFrame, Merge, Synthetic, }; // The garbage collector sets sections' Live bits. // If GC is disabled, all sections are considered live by default. @@ -232,11 +232,13 @@ typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::uint uintX_t; + typedef InputSectionData::Kind Kind; public: InputSection(); InputSection(uintX_t Flags, uint32_t Type, uintX_t Addralign, - ArrayRef Data, StringRef Name); + ArrayRef Data, StringRef Name, + Kind K = InputSectionData::Regular); InputSection(ObjectFile *F, const Elf_Shdr *Header, StringRef Name); static InputSection Discarded; Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/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,13 @@ } template size_t InputSectionBase::getSize() const { + if (auto *S = dyn_cast>(this)) + return S->getSize(); + if (auto *D = dyn_cast>(this)) if (D->getThunksSize() > 0) return D->getThunkOff() + D->getThunksSize(); + return Data.size(); } @@ -95,6 +100,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 @@ -184,10 +190,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, @@ -196,7 +202,7 @@ template bool InputSection::classof(const InputSectionData *S) { - return S->kind() == Base::Regular; + return S->kind() == Base::Regular || S->kind() == Base::Synthetic; } template @@ -528,6 +534,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: lld/trunk/ELF/OutputSections.h =================================================================== --- lld/trunk/ELF/OutputSections.h +++ lld/trunk/ELF/OutputSections.h @@ -51,7 +51,6 @@ EHFrameHdr, GnuHashTable, Got, - GotPlt, HashTable, Merge, Plt, @@ -211,24 +210,6 @@ void writeMipsGot(uint8_t *Buf); }; -template class GotPltSection final : public OutputSectionBase { - typedef typename ELFT::uint uintX_t; - -public: - GotPltSection(); - void finalize() override; - void writeTo(uint8_t *Buf) override; - void addEntry(SymbolBody &Sym); - bool empty() const; - Kind getKind() const override { return GotPlt; } - static bool classof(const OutputSectionBase *B) { - return B->getKind() == GotPlt; - } - -private: - std::vector Entries; -}; - template class PltSection final : public OutputSectionBase { typedef typename ELFT::uint uintX_t; @@ -603,12 +584,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) {} @@ -677,7 +661,6 @@ static EhOutputSection *EhFrame; static GdbIndexSection *GdbIndex; static GnuHashTableSection *GnuHashTab; - static GotPltSection *GotPlt; static GotSection *Got; static HashTableSection *HashTab; static OutputSection *Bss; @@ -743,7 +726,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: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -109,35 +109,6 @@ } template -GotPltSection::GotPltSection() - : OutputSectionBase(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) { - this->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->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) @@ -775,7 +746,7 @@ Add({DT_JMPREL, Out::RelaPlt}); Add({DT_PLTRELSZ, Out::RelaPlt->Size}); 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)}); } @@ -846,6 +817,9 @@ case Entry::SecAddr: P->d_un.d_ptr = E.OutSec->Addr; break; + case Entry::InSecAddr: + P->d_un.d_ptr = E.InSec->OutSec->Addr + E.InSec->OutSecOff; + break; case Entry::SecSize: P->d_un.d_val = E.OutSec->Size; break; @@ -1789,6 +1763,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: @@ -1845,11 +1820,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: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/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" @@ -743,8 +744,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: lld/trunk/ELF/Symbols.cpp =================================================================== --- lld/trunk/ELF/Symbols.cpp +++ lld/trunk/ELF/Symbols.cpp @@ -159,7 +159,7 @@ } template typename ELFT::uint SymbolBody::getGotPltVA() const { - return Out::GotPlt->Addr + getGotPltOffset(); + return In::GotPlt->getVA() + getGotPltOffset(); } template typename ELFT::uint SymbolBody::getGotPltOffset() const { Index: lld/trunk/ELF/SyntheticSections.h =================================================================== --- lld/trunk/ELF/SyntheticSections.h +++ lld/trunk/ELF/SyntheticSections.h @@ -58,6 +58,26 @@ Elf_Mips_RegInfo Reginfo = {}; }; +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: @@ -109,6 +129,22 @@ void writeBuildId(llvm::MutableArrayRef) override; }; +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->Addr + this->OutSecOff; } + +private: + std::vector Entries; +}; + template InputSection *createCommonSection(); template InputSection *createInterpSection(); @@ -116,6 +152,7 @@ template struct In { static BuildIdSection *BuildId; static InputSection *Common; + static GotPltSection *GotPlt; static InputSection *Interp; static MipsAbiFlagsSection *MipsAbiFlags; static MipsOptionsSection *MipsOptions; @@ -124,6 +161,7 @@ template BuildIdSection *In::BuildId; template InputSection *In::Common; +template GotPltSection *In::GotPlt; template InputSection *In::Interp; template MipsAbiFlagsSection *In::MipsAbiFlags; template MipsOptionsSection *In::MipsOptions; Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -313,6 +313,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(); @@ -367,3 +397,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: lld/trunk/ELF/Target.h =================================================================== --- lld/trunk/ELF/Target.h +++ lld/trunk/ELF/Target.h @@ -82,7 +82,7 @@ uint32_t TlsModuleIndexRel; uint32_t TlsOffsetRel; unsigned GotEntrySize; - unsigned GotPltEntrySize; + unsigned GotPltEntrySize = 0; unsigned PltEntrySize; unsigned PltHeaderSize; Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/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->Addr; + 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->Addr; + 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->Addr; + uint64_t Got = In::GotPlt->getVA(); uint64_t Plt = Out::Plt->Addr; 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->Addr; + uint64_t Got = In::GotPlt->getVA(); uint64_t Plt = Out::Plt->Addr; 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->Addr; + uint64_t GotPlt = In::GotPlt->getVA(); uint64_t L1 = Out::Plt->Addr + 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->Addr; + uint64_t Got = In::GotPlt->getVA(); writeMipsHi16(Buf, Got); writeMipsLo16(Buf + 4, Got); writeMipsLo16(Buf + 8, Got); Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -248,7 +248,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) { @@ -312,6 +311,8 @@ Symtab::X->Sections.push_back(RegSec); } } + + In::GotPlt = make>(); } template @@ -423,7 +424,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; @@ -893,6 +894,13 @@ // This function adds linker-created Out::* sections. addPredefinedSections(); + // We fill .got.plt section in scanRelocs(). This is the + // reason we don't add it earlier in createSections(). + if (!In::GotPlt->empty()) { + addInputSec(In::GotPlt); + In::GotPlt->OutSec->assignOffsets(); + } + sortSections(); unsigned I = 1; @@ -976,8 +984,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())