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) @@ -784,7 +755,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)}); } @@ -855,6 +826,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; @@ -1939,11 +1913,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 @@ -79,16 +79,33 @@ void writeBuildId(llvm::MutableArrayRef) override; }; +template class GotPltSection final : public InputSection { + 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 CommonSection *Common; static InterpSection *Interp; + static GotPltSection *GotPlt; }; template BuildIdSection *In::BuildId; template CommonSection *In::Common; template InterpSection *In::Interp; +template GotPltSection *In::GotPlt; } // namespace elf } // namespace lld 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,37 @@ Config->BuildIdVector.size()); } +template +GotPltSection::GotPltSection() + : InputSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, + Target->GotPltEntrySize, ArrayRef(), + ".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 class elf::CommonSection; template class elf::CommonSection; template class elf::CommonSection; @@ -227,3 +259,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; @@ -751,6 +752,10 @@ } } +template static void removeElt(Range &R, const T &Val) { + R.erase(std::remove(R.begin(), R.end(), Val), R.end()); +} + // Create output section objects and add them to OutputSections. template void Writer::finalizeSections() { Out::DebugInfo = findSection(".debug_info"); @@ -813,6 +818,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; @@ -896,8 +907,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())