Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -18,8 +18,6 @@ template class ObjectFile; template class OutputSection; -template class PltSection; -template class GotSection; // This corresponds to a section of an input file. template class InputSection { @@ -37,8 +35,7 @@ // Write this section to a mmap'ed file, assuming Buf is pointing to // beginning of the output section. - void writeTo(uint8_t *Buf, const OutputSection &BssSec, - const PltSection &PltSec, const GotSection &GotSec); + void writeTo(uint8_t *Buf); StringRef getSectionName() const; const Elf_Shdr *getSectionHdr() const { return Header; } @@ -53,8 +50,8 @@ } void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; } - void setOutputSection(OutputSection *O) { Out = O; } - OutputSection *getOutputSection() const { return Out; } + void setOutputSection(OutputSection *O) { OutSec = O; } + OutputSection *getOutputSection() const { return OutSec; } // Relocation sections that refer to this one. SmallVector RelocSections; @@ -64,9 +61,7 @@ void relocate(uint8_t *Buf, llvm::iterator_range< const llvm::object::Elf_Rel_Impl *> Rels, - const ObjectFile &File, uintX_t BaseAddr, - const OutputSection &BssSec, - const PltSection &PltSec, const GotSection &GotSec); + const ObjectFile &File, uintX_t BaseAddr); // The offset from beginning of the output sections this section was assigned // to. The writer sets a value. @@ -75,7 +70,7 @@ // The file this section is from. ObjectFile *File; - OutputSection *Out = nullptr; + OutputSection *OutSec = nullptr; const Elf_Shdr *Header; }; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -29,15 +29,12 @@ template void InputSection::relocate( uint8_t *Buf, iterator_range *> Rels, - const ObjectFile &File, uintX_t BaseAddr, - const OutputSection &BssSec, const PltSection &PltSec, - const GotSection &GotSec) { + const ObjectFile &File, uintX_t BaseAddr) { typedef Elf_Rel_Impl RelType; bool IsMips64EL = File.getObj().isMips64EL(); for (const RelType &RI : Rels) { uint32_t SymIndex = RI.getSymbol(IsMips64EL); uint32_t Type = RI.getType(IsMips64EL); - uintX_t GotVA = GotSec.getVA(); uintX_t SymVA; // Handle relocations for local symbols -- they never get @@ -50,15 +47,15 @@ SymVA = getLocalSymVA(Sym, File); } else { SymbolBody &Body = *File.getSymbolBody(SymIndex); - SymVA = getSymVA(Body, BssSec); + SymVA = getSymVA(Body); if (Target->relocNeedsPlt(Type, Body)) { - SymVA = PltSec.getEntryAddr(Body); + SymVA = Out::Plt->getEntryAddr(Body); Type = Target->getPCRelReloc(); } else if (Target->relocNeedsGot(Type, Body)) { - SymVA = GotSec.getEntryAddr(Body); + SymVA = Out::Got->getEntryAddr(Body); Type = Target->getGotRefReloc(); } else if (Target->relocPointsToGot(Type)) { - SymVA = GotVA; + SymVA = Out::Got->getVA(); Type = Target->getPCRelReloc(); } else if (isa>(Body)) { continue; @@ -66,15 +63,12 @@ } Target->relocateOne(Buf, reinterpret_cast(&RI), Type, - BaseAddr, SymVA, GotVA); + BaseAddr, SymVA, Out::Got->getVA()); } } template -void InputSection::writeTo(uint8_t *Buf, - const OutputSection &BssSec, - const PltSection &PltSec, - const GotSection &GotSec) { +void InputSection::writeTo(uint8_t *Buf) { if (Header->sh_type == SHT_NOBITS) return; // Copy section contents from source object file to output file. @@ -84,15 +78,13 @@ ObjectFile *File = getFile(); ELFFile &EObj = File->getObj(); uint8_t *Base = Buf + getOutputSectionOff(); - uintX_t BaseAddr = Out->getVA() + getOutputSectionOff(); + uintX_t BaseAddr = OutSec->getVA() + getOutputSectionOff(); // Iterate over all relocation sections that apply to this section. for (const Elf_Shdr *RelSec : RelocSections) { if (RelSec->sh_type == SHT_RELA) - relocate(Base, EObj.relas(RelSec), *File, BaseAddr, BssSec, PltSec, - GotSec); + relocate(Base, EObj.relas(RelSec), *File, BaseAddr); else - relocate(Base, EObj.rels(RelSec), *File, BaseAddr, BssSec, PltSec, - GotSec); + relocate(Base, EObj.rels(RelSec), *File, BaseAddr); } } Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -34,7 +34,7 @@ template typename llvm::object::ELFFile::uintX_t -getSymVA(const SymbolBody &S, const OutputSection &BssSec); +getSymVA(const SymbolBody &S); template typename llvm::object::ELFFile::uintX_t @@ -122,7 +122,7 @@ typedef typename Base::uintX_t uintX_t; public: - PltSection(const GotSection &GotSec); + PltSection(); void finalize() override { this->Header.sh_size = Entries.size() * EntrySize; } @@ -134,7 +134,6 @@ private: std::vector Entries; - const GotSection &GotSec; }; template struct DynamicReloc { @@ -151,26 +150,12 @@ typedef typename llvm::object::ELFFile::Elf_Sym_Range Elf_Sym_Range; typedef typename OutputSectionBase::uintX_t uintX_t; SymbolTableSection(SymbolTable &Table, - StringTableSection &StrTabSec, - const OutputSection &BssSec); - - void finalize() override { - this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym); - this->Header.sh_link = StrTabSec.getSectionIndex(); - this->Header.sh_info = NumLocals + 1; - } + StringTableSection &StrTabSec); + void finalize() override; void writeTo(uint8_t *Buf) override; - SymbolTable &getSymTable() const { return Table; } - - void addSymbol(StringRef Name, bool isLocal = false) { - StrTabSec.add(Name); - ++NumVisible; - if (isLocal) - ++NumLocals; - } - + void addSymbol(StringRef Name, bool isLocal = false); StringTableSection &getStrTabSec() const { return StrTabSec; } unsigned getNumSymbols() const { return NumVisible + 1; } @@ -182,7 +167,6 @@ StringTableSection &StrTabSec; unsigned NumVisible = 0; unsigned NumLocals = 0; - const OutputSection &BssSec; }; template @@ -192,9 +176,7 @@ typedef typename llvm::object::ELFFile::uintX_t uintX_t; public: - RelocationSection(SymbolTableSection &DynSymSec, - const GotSection &GotSec, - const OutputSection &BssSec, bool IsRela); + RelocationSection(bool IsRela); void addReloc(const DynamicReloc &Reloc) { Relocs.push_back(Reloc); } void finalize() override; void writeTo(uint8_t *Buf) override; @@ -203,9 +185,6 @@ private: std::vector> Relocs; - SymbolTableSection &DynSymSec; - const GotSection &GotSec; - const OutputSection &BssSec; const bool IsRela; }; @@ -217,17 +196,12 @@ typedef typename llvm::object::ELFFile::Elf_Sym Elf_Sym; typedef typename llvm::object::ELFFile::Elf_Rel Elf_Rel; typedef typename llvm::object::ELFFile::Elf_Rela Elf_Rela; - OutputSection(const PltSection &PltSec, const GotSection &GotSec, - const OutputSection &BssSec, StringRef Name, - uint32_t sh_type, uintX_t sh_flags); + OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags); void addSection(InputSection *C); void writeTo(uint8_t *Buf) override; private: std::vector *> Sections; - const PltSection &PltSec; - const GotSection &GotSec; - const OutputSection &BssSec; }; template @@ -265,40 +239,10 @@ typedef typename llvm::object::ELFFile::Elf_Word Elf_Word; public: - HashTableSection(SymbolTableSection &DynSymSec); + HashTableSection(); void addSymbol(SymbolBody *S); - - void finalize() override { - this->Header.sh_link = DynSymSec.getSectionIndex(); - - assert(DynSymSec.getNumSymbols() == Hashes.size() + 1); - unsigned NumEntries = 2; // nbucket and nchain. - NumEntries += DynSymSec.getNumSymbols(); // The chain entries. - - // Create as many buckets as there are symbols. - // FIXME: This is simplistic. We can try to optimize it, but implementing - // support for SHT_GNU_HASH is probably even more profitable. - NumEntries += DynSymSec.getNumSymbols(); - this->Header.sh_size = NumEntries * sizeof(Elf_Word); - } - - void writeTo(uint8_t *Buf) override { - unsigned NumSymbols = DynSymSec.getNumSymbols(); - auto *P = reinterpret_cast(Buf); - *P++ = NumSymbols; // nbucket - *P++ = NumSymbols; // nchain - - Elf_Word *Buckets = P; - Elf_Word *Chains = P + NumSymbols; - - for (unsigned I = 1; I < NumSymbols; ++I) { - uint32_t Hash = Hashes[I - 1] % NumSymbols; - Chains[I] = Buckets[Hash]; - Buckets[Hash] = I; - } - } - - SymbolTableSection &getDynSymSec() { return DynSymSec; } + void finalize() override; + void writeTo(uint8_t *Buf) override; private: uint32_t hash(StringRef Name) { @@ -312,7 +256,6 @@ } return H; } - SymbolTableSection &DynSymSec; std::vector Hashes; }; @@ -326,9 +269,7 @@ typedef typename llvm::object::ELFFile::Elf_Dyn Elf_Dyn; public: - DynamicSection(SymbolTable &SymTab, HashTableSection &HashSec, - RelocationSection &RelaDynSec, - const OutputSection &BssSec); + DynamicSection(SymbolTable &SymTab); void finalize() override; void writeTo(uint8_t *Buf) override; @@ -337,15 +278,29 @@ OutputSection *FiniArraySec = nullptr; private: - HashTableSection &HashSec; - SymbolTableSection &DynSymSec; - StringTableSection &DynStrSec; - RelocationSection &RelaDynSec; - const OutputSection &BssSec; SymbolTable &SymTab; const ELFSymbolBody *InitSym = nullptr; const ELFSymbolBody *FiniSym = nullptr; }; + +// All output sections that are hadnled by the linker specially are +// globally accessible. Writer initializes that, so don't use them +// until Writer is initialized. +template +struct Out { + static DynamicSection *Dynamic; + static GotSection *Got; + static HashTableSection *HashTab; + static InterpSection *Interp; + static OutputSection *Bss; + static PltSection *Plt; + static RelocationSection *RelaDyn; + static StringTableSection *DynStrTab; + static StringTableSection *StrTab; + static SymbolTableSection *DynSymTab; + static SymbolTableSection *SymTab; +}; + } } #endif Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -19,6 +19,51 @@ using namespace lld; using namespace lld::elf2; +template<> DynamicSection *Out::Dynamic = nullptr; +template<> DynamicSection *Out::Dynamic = nullptr; +template<> DynamicSection *Out::Dynamic = nullptr; +template<> DynamicSection *Out::Dynamic = nullptr; +template<> GotSection *Out::Got = nullptr; +template<> GotSection *Out::Got = nullptr; +template<> GotSection *Out::Got = nullptr; +template<> GotSection *Out::Got = nullptr; +template<> HashTableSection *Out::HashTab = nullptr; +template<> HashTableSection *Out::HashTab = nullptr; +template<> HashTableSection *Out::HashTab = nullptr; +template<> HashTableSection *Out::HashTab = nullptr; +template<> InterpSection *Out::Interp = nullptr; +template<> InterpSection *Out::Interp = nullptr; +template<> InterpSection *Out::Interp = nullptr; +template<> InterpSection *Out::Interp = nullptr; +template<> OutputSection *Out::Bss = nullptr; +template<> OutputSection *Out::Bss = nullptr; +template<> OutputSection *Out::Bss = nullptr; +template<> OutputSection *Out::Bss = nullptr; +template<> PltSection *Out::Plt = nullptr; +template<> PltSection *Out::Plt = nullptr; +template<> PltSection *Out::Plt = nullptr; +template<> PltSection *Out::Plt = nullptr; +template<> RelocationSection *Out::RelaDyn = nullptr; +template<> RelocationSection *Out::RelaDyn = nullptr; +template<> RelocationSection *Out::RelaDyn = nullptr; +template<> RelocationSection *Out::RelaDyn = nullptr; +template<> StringTableSection *Out::DynStrTab = nullptr; +template<> StringTableSection *Out::DynStrTab = nullptr; +template<> StringTableSection *Out::DynStrTab = nullptr; +template<> StringTableSection *Out::DynStrTab = nullptr; +template<> StringTableSection *Out::StrTab = nullptr; +template<> StringTableSection *Out::StrTab = nullptr; +template<> StringTableSection *Out::StrTab = nullptr; +template<> StringTableSection *Out::StrTab = nullptr; +template<> SymbolTableSection *Out::DynSymTab = nullptr; +template<> SymbolTableSection *Out::DynSymTab = nullptr; +template<> SymbolTableSection *Out::DynSymTab = nullptr; +template<> SymbolTableSection *Out::DynSymTab = nullptr; +template<> SymbolTableSection *Out::SymTab = nullptr; +template<> SymbolTableSection *Out::SymTab = nullptr; +template<> SymbolTableSection *Out::SymTab = nullptr; +template<> SymbolTableSection *Out::SymTab = nullptr; + template OutputSectionBase::OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_flags) @@ -48,18 +93,17 @@ } template -PltSection::PltSection(const GotSection &GotSec) +PltSection::PltSection() : OutputSectionBase(".plt", llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | - llvm::ELF::SHF_EXECINSTR), - GotSec(GotSec) { + llvm::ELF::SHF_EXECINSTR) { this->Header.sh_addralign = 16; } template void PltSection::writeTo(uint8_t *Buf) { uintptr_t Start = reinterpret_cast(Buf); for (const SymbolBody *E : Entries) { - uint64_t GotEntryAddr = GotSec.getEntryAddr(*E); + uint64_t GotEntryAddr = Out::Got->getEntryAddr(*E); uintptr_t InstPos = reinterpret_cast(Buf); uint64_t PltEntryAddr = (InstPos - Start) + this->getVA(); Target->writePltEntry(Buf, GotEntryAddr, PltEntryAddr); @@ -79,15 +123,12 @@ } template -RelocationSection::RelocationSection(SymbolTableSection &DynSymSec, - const GotSection &GotSec, - const OutputSection &BssSec, - bool IsRela) +RelocationSection::RelocationSection(bool IsRela) : OutputSectionBase(IsRela ? ".rela.dyn" : ".rel.dyn", IsRela ? llvm::ELF::SHT_RELA : llvm::ELF::SHT_REL, llvm::ELF::SHF_ALLOC), - DynSymSec(DynSymSec), GotSec(GotSec), BssSec(BssSec), IsRela(IsRela) { + IsRela(IsRela) { this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; } @@ -107,7 +148,7 @@ const InputSection &C = Rel.C; const Elf_Rel &RI = Rel.RI; - OutputSection *Out = C.getOutputSection(); + OutputSection *OutSec = C.getOutputSection(); uint32_t SymIndex = RI.getSymbol(IsMips64EL); const ObjectFile &File = *C.getFile(); const SymbolBody *Body = File.getSymbolBody(SymIndex); @@ -115,11 +156,11 @@ uint32_t Type = RI.getType(IsMips64EL); if (Body && Target->relocNeedsGot(Type, *Body)) { - P->r_offset = GotSec.getEntryAddr(*Body); + P->r_offset = Out::Got->getEntryAddr(*Body); P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Target->getGotReloc(), IsMips64EL); } else { - P->r_offset = RI.r_offset + C.getOutputSectionOff() + Out->getVA(); + P->r_offset = RI.r_offset + C.getOutputSectionOff() + OutSec->getVA(); uintX_t Addent = 0; if (IsRela) Addent = static_cast(RI).r_addend; @@ -131,7 +172,7 @@ P->setSymbolAndType(0, Target->getRelativeReloc(), IsMips64EL); if (IsRela) { if (Body) - Addent += getSymVA(cast>(*Body), BssSec); + Addent += getSymVA(cast>(*Body)); else Addent += getLocalSymVA( Obj.getRelocationSymbol(&RI, File.getSymbolTable()), File); @@ -144,7 +185,7 @@ } template void RelocationSection::finalize() { - this->Header.sh_link = DynSymSec.getSectionIndex(); + this->Header.sh_link = Out::DynSymTab->getSectionIndex(); this->Header.sh_size = Relocs.size() * this->Header.sh_entsize; } @@ -177,32 +218,56 @@ } template -HashTableSection::HashTableSection(SymbolTableSection &DynSymSec) +HashTableSection::HashTableSection() : OutputSectionBase(".hash", llvm::ELF::SHT_HASH, - llvm::ELF::SHF_ALLOC), - DynSymSec(DynSymSec) { + llvm::ELF::SHF_ALLOC) { this->Header.sh_entsize = sizeof(Elf_Word); this->Header.sh_addralign = sizeof(Elf_Word); } template void HashTableSection::addSymbol(SymbolBody *S) { StringRef Name = S->getName(); - DynSymSec.addSymbol(Name); + Out::DynSymTab->addSymbol(Name); Hashes.push_back(hash(Name)); S->setDynamicSymbolTableIndex(Hashes.size()); } +template void HashTableSection::finalize() { + this->Header.sh_link = Out::DynSymTab->getSectionIndex(); + + assert(Out::DynSymTab->getNumSymbols() == Hashes.size() + 1); + unsigned NumEntries = 2; // nbucket and nchain. + NumEntries += Out::DynSymTab->getNumSymbols(); // The chain entries. + + // Create as many buckets as there are symbols. + // FIXME: This is simplistic. We can try to optimize it, but implementing + // support for SHT_GNU_HASH is probably even more profitable. + NumEntries += Out::DynSymTab->getNumSymbols(); + this->Header.sh_size = NumEntries * sizeof(Elf_Word); +} + +template void HashTableSection::writeTo(uint8_t *Buf) { + unsigned NumSymbols = Out::DynSymTab->getNumSymbols(); + auto *P = reinterpret_cast(Buf); + *P++ = NumSymbols; // nbucket + *P++ = NumSymbols; // nchain + + Elf_Word *Buckets = P; + Elf_Word *Chains = P + NumSymbols; + + for (unsigned I = 1; I < NumSymbols; ++I) { + uint32_t Hash = Hashes[I - 1] % NumSymbols; + Chains[I] = Buckets[Hash]; + Buckets[Hash] = I; + } +} + template -DynamicSection::DynamicSection(SymbolTable &SymTab, - HashTableSection &HashSec, - RelocationSection &RelaDynSec, - const OutputSection &BssSec) +DynamicSection::DynamicSection(SymbolTable &SymTab) : OutputSectionBase(".dynamic", llvm::ELF::SHT_DYNAMIC, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE), - HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()), - DynStrSec(DynSymSec.getStrTabSec()), RelaDynSec(RelaDynSec), - BssSec(BssSec), SymTab(SymTab) { + SymTab(SymTab) { typename Base::HeaderT &Header = this->Header; Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; Header.sh_entsize = ELFT::Is64Bits ? 16 : 8; @@ -213,10 +278,10 @@ return; // Already finalized. typename Base::HeaderT &Header = this->Header; - Header.sh_link = DynStrSec.getSectionIndex(); + Header.sh_link = Out::DynStrTab->getSectionIndex(); unsigned NumEntries = 0; - if (RelaDynSec.hasRelocs()) { + if (Out::RelaDyn->hasRelocs()) { ++NumEntries; // DT_RELA / DT_REL ++NumEntries; // DT_RELASZ / DT_RELSZ ++NumEntries; // DT_RELAENT / DT_RELENT @@ -229,12 +294,12 @@ if (!Config->RPath.empty()) { ++NumEntries; // DT_RUNPATH / DT_RPATH - DynStrSec.add(Config->RPath); + Out::DynStrTab->add(Config->RPath); } if (!Config->SoName.empty()) { ++NumEntries; // DT_SONAME - DynStrSec.add(Config->SoName); + Out::DynStrTab->add(Config->SoName); } if (PreInitArraySec) @@ -247,7 +312,7 @@ const std::vector> &SharedFiles = SymTab.getSharedFiles(); for (const std::unique_ptr &File : SharedFiles) - DynStrSec.add(File->getSoName()); + Out::DynStrTab->add(File->getSoName()); NumEntries += SharedFiles.size(); if (Symbol *S = SymTab.getSymbols().lookup(Config->Init)) @@ -279,19 +344,19 @@ ++P; }; - if (RelaDynSec.hasRelocs()) { - bool IsRela = RelaDynSec.isRela(); - WritePtr(IsRela ? DT_RELA : DT_REL, RelaDynSec.getVA()); - WriteVal(IsRela ? DT_RELASZ : DT_RELSZ, RelaDynSec.getSize()); + if (Out::RelaDyn->hasRelocs()) { + bool IsRela = Out::RelaDyn->isRela(); + WritePtr(IsRela ? DT_RELA : DT_REL, Out::RelaDyn->getVA()); + WriteVal(IsRela ? DT_RELASZ : DT_RELSZ, Out::RelaDyn->getSize()); WriteVal(IsRela ? DT_RELAENT : DT_RELENT, IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)); } - WritePtr(DT_SYMTAB, DynSymSec.getVA()); + WritePtr(DT_SYMTAB, Out::DynSymTab->getVA()); WritePtr(DT_SYMENT, sizeof(Elf_Sym)); - WritePtr(DT_STRTAB, DynStrSec.getVA()); - WriteVal(DT_STRSZ, DynStrSec.data().size()); - WritePtr(DT_HASH, HashSec.getVA()); + WritePtr(DT_STRTAB, Out::DynStrTab->getVA()); + WriteVal(DT_STRSZ, Out::DynStrTab->data().size()); + WritePtr(DT_HASH, Out::HashTab->getVA()); if (!Config->RPath.empty()) @@ -304,10 +369,10 @@ // dependencies of the object it's contained in, while // DT_RPATH is used for indirect dependencies as well. WriteVal(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, - DynStrSec.getFileOff(Config->RPath)); + Out::DynStrTab->getFileOff(Config->RPath)); if (!Config->SoName.empty()) - WriteVal(DT_SONAME, DynStrSec.getFileOff(Config->SoName)); + WriteVal(DT_SONAME, Out::DynStrTab->getFileOff(Config->SoName)); auto WriteArray = [&](int32_t T1, int32_t T2, const OutputSection *Sec) { @@ -323,24 +388,20 @@ const std::vector> &SharedFiles = SymTab.getSharedFiles(); for (const std::unique_ptr &File : SharedFiles) - WriteVal(DT_NEEDED, DynStrSec.getFileOff(File->getSoName())); + WriteVal(DT_NEEDED, Out::DynStrTab->getFileOff(File->getSoName())); if (InitSym) - WritePtr(DT_INIT, getSymVA(*InitSym, BssSec)); + WritePtr(DT_INIT, getSymVA(*InitSym)); if (FiniSym) - WritePtr(DT_FINI, getSymVA(*FiniSym, BssSec)); + WritePtr(DT_FINI, getSymVA(*FiniSym)); WriteVal(DT_NULL, 0); } template -OutputSection::OutputSection(const PltSection &PltSec, - const GotSection &GotSec, - const OutputSection &BssSec, - StringRef Name, uint32_t sh_type, +OutputSection::OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags) - : OutputSectionBase(Name, sh_type, sh_flags), - PltSec(PltSec), GotSec(GotSec), BssSec(BssSec) {} + : OutputSectionBase(Name, sh_type, sh_flags) {} template void OutputSection::addSection(InputSection *C) { @@ -359,7 +420,7 @@ template typename ELFFile::uintX_t -lld::elf2::getSymVA(const SymbolBody &S, const OutputSection &BssSec) { +lld::elf2::getSymVA(const SymbolBody &S) { switch (S.kind()) { case SymbolBody::DefinedSyntheticKind: { auto &D = cast>(S); @@ -374,7 +435,7 @@ return OS->getVA() + SC->getOutputSectionOff() + DR.Sym.st_value; } case SymbolBody::DefinedCommonKind: - return BssSec.getVA() + cast>(S).OffsetInBSS; + return Out::Bss->getVA() + cast>(S).OffsetInBSS; case SymbolBody::SharedKind: case SymbolBody::UndefinedKind: return 0; @@ -401,7 +462,7 @@ template void OutputSection::writeTo(uint8_t *Buf) { for (InputSection *C : Sections) - C->writeTo(Buf, BssSec, PltSec, GotSec); + C->writeTo(Buf); } template @@ -456,13 +517,12 @@ template SymbolTableSection::SymbolTableSection( - SymbolTable &Table, StringTableSection &StrTabSec, - const OutputSection &BssSec) + SymbolTable &Table, StringTableSection &StrTabSec) : OutputSectionBase( StrTabSec.isDynamic() ? ".dynsym" : ".symtab", StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM : llvm::ELF::SHT_SYMTAB, StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0), - Table(Table), StrTabSec(StrTabSec), BssSec(BssSec) { + Table(Table), StrTabSec(StrTabSec) { typedef OutputSectionBase Base; typename Base::HeaderT &Header = this->Header; @@ -470,6 +530,20 @@ Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; } +template void SymbolTableSection::finalize() { + this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym); + this->Header.sh_link = StrTabSec.getSectionIndex(); + this->Header.sh_info = NumLocals + 1; +} + +template +void SymbolTableSection::addSymbol(StringRef Name, bool isLocal) { + StrTabSec.add(Name); + ++NumVisible; + if (isLocal) + ++NumLocals; +} + template void SymbolTableSection::writeTo(uint8_t *Buf) { Buf += sizeof(Elf_Sym); @@ -535,18 +609,18 @@ ESym->st_name = StrTabSec.getFileOff(Name); - const OutputSection *Out = nullptr; + const OutputSection *OutSec = nullptr; const InputSection *Section = nullptr; switch (Body->kind()) { case SymbolBody::DefinedSyntheticKind: - Out = &cast>(Body)->Section; + OutSec = &cast>(Body)->Section; break; case SymbolBody::DefinedRegularKind: Section = &cast>(Body)->Section; break; case SymbolBody::DefinedCommonKind: - Out = &BssSec; + OutSec = Out::Bss; break; case SymbolBody::UndefinedKind: case SymbolBody::DefinedAbsoluteKind: @@ -572,15 +646,15 @@ ESym->setBindingAndType(Binding, Type); ESym->st_size = Size; ESym->setVisibility(Visibility); - ESym->st_value = getSymVA(*Body, BssSec); + ESym->st_value = getSymVA(*Body); if (Section) - Out = Section->getOutputSection(); + OutSec = Section->getOutputSection(); if (isa>(Body)) ESym->st_shndx = SHN_ABS; - else if (Out) - ESym->st_shndx = Out->getSectionIndex(); + else if (OutSec) + ESym->st_shndx = OutSec->getSectionIndex(); } if (!StrTabSec.isDynamic()) std::stable_sort( @@ -645,14 +719,10 @@ template class SymbolTableSection; template class SymbolTableSection; -template ELFFile::uintX_t getSymVA(const SymbolBody &, - const OutputSection &); -template ELFFile::uintX_t getSymVA(const SymbolBody &, - const OutputSection &); -template ELFFile::uintX_t getSymVA(const SymbolBody &, - const OutputSection &); -template ELFFile::uintX_t getSymVA(const SymbolBody &, - const OutputSection &); +template ELFFile::uintX_t getSymVA(const SymbolBody &); +template ELFFile::uintX_t getSymVA(const SymbolBody &); +template ELFFile::uintX_t getSymVA(const SymbolBody &); +template ELFFile::uintX_t getSymVA(const SymbolBody &); template ELFFile::uintX_t getLocalSymVA(const ELFFile::Elf_Sym *, const ObjectFile &); @@ -679,5 +749,6 @@ const ELFFile::Elf_Sym &); template bool shouldKeepInSymtab(StringRef, const ELFFile::Elf_Sym &); + } } Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "Target.h" #include "Error.h" #include "Symbols.h" +#include "Target.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Object/ELF.h" Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -58,14 +58,14 @@ Header.p_paddr = VA; } - void setValuesFromSection(OutputSectionBase &Sec) { - Header.p_flags = toPHDRFlags(Sec.getFlags()); - Header.p_offset = Sec.getFileOff(); - Header.p_vaddr = Sec.getVA(); + void setValuesFromSection(OutputSectionBase *Sec) { + Header.p_flags = toPHDRFlags(Sec->getFlags()); + Header.p_offset = Sec->getFileOff(); + Header.p_vaddr = Sec->getVA(); Header.p_paddr = Header.p_vaddr; - Header.p_filesz = Sec.getSize(); + Header.p_filesz = Sec->getSize(); Header.p_memsz = Header.p_filesz; - Header.p_align = Sec.getAlign(); + Header.p_align = Sec->getAlign(); } Elf_Phdr Header; @@ -82,13 +82,6 @@ typedef typename ELFFile::Elf_Sym Elf_Sym; typedef typename ELFFile::Elf_Sym_Range Elf_Sym_Range; typedef typename ELFFile::Elf_Rela Elf_Rela; - Writer(SymbolTable *T) - : SymTabSec(*T, StrTabSec, BssSec), DynSymSec(*T, DynStrSec, BssSec), - RelaDynSec(DynSymSec, GotSec, BssSec, T->shouldUseRela()), - PltSec(GotSec), HashSec(DynSymSec), - DynamicSec(*T, HashSec, RelaDynSec, BssSec), - BssSec(PltSec, GotSec, BssSec, ".bss", SHT_NOBITS, - SHF_ALLOC | SHF_WRITE) {} void run(); private: @@ -102,11 +95,11 @@ void writeHeader(); void writeSections(); bool needsInterpSection() const { - return !SymTabSec.getSymTable().getSharedFiles().empty() && + return !Out::SymTab->getSymTable().getSharedFiles().empty() && !Config->DynamicLinker.empty(); } bool needsDynamicSections() const { - return !SymTabSec.getSymTable().getSharedFiles().empty() || Config->Shared; + return !Out::SymTab->getSymTable().getSharedFiles().empty() || Config->Shared; } unsigned getVAStart() const { return Config->Shared ? 0 : VAStart; } @@ -125,41 +118,31 @@ uintX_t FileSize; uintX_t ProgramHeaderOff; uintX_t SectionHeaderOff; - - StringTableSection StrTabSec = { /*dynamic=*/false }; - StringTableSection DynStrSec = { /*dynamic=*/true }; - - lld::elf2::SymbolTableSection SymTabSec; - lld::elf2::SymbolTableSection DynSymSec; - - RelocationSection RelaDynSec; - - GotSection GotSec; - PltSection PltSec; - - HashTableSection HashSec; - - DynamicSection DynamicSec; - - InterpSection InterpSec; - - OutputSection BssSec; }; } // anonymous namespace -namespace lld { -namespace elf2 { - template -void writeResult(SymbolTable *Symtab) { Writer(Symtab).run(); } - -template void writeResult(SymbolTable *); -template void writeResult(SymbolTable *); -template void writeResult(SymbolTable *); -template void writeResult(SymbolTable *); +void lld::elf2::writeResult(SymbolTable *Symtab) { + // Initialize output sections that are handled by Writer specially. + Out::Interp = new InterpSection(); + Out::StrTab = new StringTableSection(/*dynamic=*/false); + Out::DynStrTab = new StringTableSection(/*dynamic=*/true); + Out::Bss = new OutputSection(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); + Out::Got = new GotSection(); + Out::Plt = new PltSection(); + Out::SymTab = new SymbolTableSection(*Symtab, *Out::StrTab); + Out::DynSymTab = new SymbolTableSection(*Symtab, *Out::DynStrTab); + Out::HashTab = new HashTableSection(); + Out::RelaDyn = new RelocationSection(Symtab->shouldUseRela()); + Out::Dynamic = new DynamicSection(*Symtab); + + Writer().run(); +} -} // namespace elf2 -} // namespace lld +template void lld::elf2::writeResult(SymbolTable *); +template void lld::elf2::writeResult(SymbolTable *); +template void lld::elf2::writeResult(SymbolTable *); +template void lld::elf2::writeResult(SymbolTable *); // The main function of the writer. template void Writer::run() { @@ -223,24 +206,24 @@ if (Target->relocNeedsPlt(Type, *Body)) { if (Body->isInPlt()) continue; - PltSec.addEntry(Body); + Out::Plt->addEntry(Body); } if (Target->relocNeedsGot(Type, *Body)) { if (Body->isInGot()) continue; - GotSec.addEntry(Body); + Out::Got->addEntry(Body); Body->setUsedInDynamicReloc(); - RelaDynSec.addReloc({C, RI}); + Out::RelaDyn->addReloc({C, RI}); continue; } if (Body->isShared()) { Body->setUsedInDynamicReloc(); - RelaDynSec.addReloc({C, RI}); + Out::RelaDyn->addReloc({C, RI}); continue; } } if (Config->Shared && !Target->isRelRelative(Type)) - RelaDynSec.addReloc({C, RI}); + Out::RelaDyn->addReloc({C, RI}); } } @@ -291,10 +274,10 @@ template void Writer::createSections() { SmallDenseMap, OutputSection *> Map; - OutputSections.push_back(&BssSec); - Map[{BssSec.getName(), BssSec.getType(), BssSec.getFlags()}] = &BssSec; + OutputSections.push_back(Out::Bss); + Map[{Out::Bss->getName(), Out::Bss->getType(), Out::Bss->getFlags()}] = Out::Bss; - SymbolTable &Symtab = SymTabSec.getSymTable(); + SymbolTable &Symtab = Out::SymTab->getSymTable(); for (const std::unique_ptr &FileB : Symtab.getObjectFiles()) { auto &File = cast>(*FileB); if (!Config->DiscardAll) { @@ -302,7 +285,7 @@ for (const Elf_Sym &Sym : Syms) { ErrorOr SymName = Sym.getName(File.getStringTable()); if (SymName && shouldKeepInSymtab(*SymName, Sym)) - SymTabSec.addSymbol(*SymName, true); + Out::SymTab->addSymbol(*SymName, true); } } for (InputSection *C : File.getSections()) { @@ -313,8 +296,7 @@ H->sh_flags}; OutputSection *&Sec = Map[Key]; if (!Sec) { - Sec = new (CAlloc.Allocate()) OutputSection( - PltSec, GotSec, BssSec, Key.Name, Key.Type, Key.Flags); + Sec = new (CAlloc.Allocate()) OutputSection(Key.Name, Key.Type, Key.Flags); OutputSections.push_back(Sec); } Sec->addSection(C); @@ -322,11 +304,11 @@ } } - DynamicSec.PreInitArraySec = + Out::Dynamic->PreInitArraySec = Map.lookup({".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC}); - DynamicSec.InitArraySec = + Out::Dynamic->InitArraySec = Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC}); - DynamicSec.FiniArraySec = + Out::Dynamic->FiniArraySec = Map.lookup({".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC}); auto AddStartEnd = [&Symtab](StringRef Start, StringRef End, @@ -341,11 +323,11 @@ }; AddStartEnd("__preinit_array_start", "__preinit_array_end", - DynamicSec.PreInitArraySec); + Out::Dynamic->PreInitArraySec); AddStartEnd("__init_array_start", "__init_array_end", - DynamicSec.InitArraySec); + Out::Dynamic->InitArraySec); AddStartEnd("__fini_array_start", "__fini_array_end", - DynamicSec.FiniArraySec); + Out::Dynamic->FiniArraySec); // FIXME: Try to avoid the extra walk over all global symbols. std::vector *> CommonSymbols; @@ -361,10 +343,10 @@ CommonSymbols.push_back(C); if (!includeInSymtab(*Body)) continue; - SymTabSec.addSymbol(Name); + Out::SymTab->addSymbol(Name); if (needsDynamicSections() && includeInDynamicSymtab(*Body)) - HashSec.addSymbol(Body); + Out::HashTab->addSymbol(Body); } // Sort the common symbols by alignment as an heuristic to pack them better. @@ -374,7 +356,7 @@ return A->MaxAlignment > B->MaxAlignment; }); - uintX_t Off = BssSec.getSize(); + uintX_t Off = Out::Bss->getSize(); for (DefinedCommon *C : CommonSymbols) { const Elf_Sym &Sym = C->Sym; uintX_t Align = C->MaxAlignment; @@ -383,24 +365,24 @@ Off += Sym.st_size; } - BssSec.setSize(Off); + Out::Bss->setSize(Off); - OutputSections.push_back(&SymTabSec); + OutputSections.push_back(Out::SymTab); if (needsDynamicSections()) { if (needsInterpSection()) - OutputSections.push_back(&InterpSec); - OutputSections.push_back(&DynSymSec); - OutputSections.push_back(&HashSec); - OutputSections.push_back(&DynamicSec); - OutputSections.push_back(&DynStrSec); - if (RelaDynSec.hasRelocs()) - OutputSections.push_back(&RelaDynSec); + OutputSections.push_back(Out::Interp); + OutputSections.push_back(Out::DynSymTab); + OutputSections.push_back(Out::HashTab); + OutputSections.push_back(Out::Dynamic); + OutputSections.push_back(Out::DynStrTab); + if (Out::RelaDyn->hasRelocs()) + OutputSections.push_back(Out::RelaDyn); } - if (!GotSec.empty()) - OutputSections.push_back(&GotSec); - if (!PltSec.empty()) - OutputSections.push_back(&PltSec); + if (!Out::Got->empty()) + OutputSections.push_back(Out::Got); + if (!Out::Plt->empty()) + OutputSections.push_back(Out::Plt); std::stable_sort( OutputSections.begin(), OutputSections.end(), @@ -446,13 +428,13 @@ // Always put StrTabSec last so that no section names are added to it after // it's finalized. - OutputSections.push_back(&StrTabSec); + OutputSections.push_back(Out::StrTab); for (unsigned I = 0, N = OutputSections.size(); I < N; ++I) OutputSections[I]->setSectionIndex(I + 1); - // Fill the DynStrSec early. - DynamicSec.finalize(); + // Fill the DynStrTab early. + Out::Dynamic->finalize(); } template @@ -485,7 +467,7 @@ FileHeaderPHDR.Header.p_align = PageSize; for (OutputSectionBase *Sec : OutputSections) { - StrTabSec.add(Sec->getName()); + Out::StrTab->add(Sec->getName()); Sec->finalize(); if (Sec->getSize()) { @@ -546,7 +528,7 @@ : ELFDATA2MSB; EHdr->e_ident[EI_VERSION] = EV_CURRENT; - const SymbolTable &Symtab = SymTabSec.getSymTable(); + const SymbolTable &Symtab = Out::SymTab->getSymTable(); auto &FirstObj = cast>(*Symtab.getFirstELF()); EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI(); @@ -557,8 +539,7 @@ EHdr->e_machine = FirstObj.getEMachine(); EHdr->e_version = EV_CURRENT; SymbolBody *Entry = Symtab.getEntrySym(); - EHdr->e_entry = - Entry ? getSymVA(cast>(*Entry), BssSec) : 0; + EHdr->e_entry = Entry ? getSymVA(cast>(*Entry)) : 0; EHdr->e_phoff = ProgramHeaderOff; EHdr->e_shoff = SectionHeaderOff; EHdr->e_ehsize = sizeof(Elf_Ehdr); @@ -566,7 +547,7 @@ EHdr->e_phnum = PHDRs.size(); EHdr->e_shentsize = sizeof(Elf_Shdr); EHdr->e_shnum = getNumSections(); - EHdr->e_shstrndx = StrTabSec.getSectionIndex(); + EHdr->e_shstrndx = Out::StrTab->getSectionIndex(); // If nothing was merged into the file header PT_LOAD, set the size correctly. if (FileHeaderPHDR.Header.p_filesz == PageSize) { @@ -576,9 +557,9 @@ } if (needsInterpSection()) - InterpPHDR.setValuesFromSection(InterpSec); + InterpPHDR.setValuesFromSection(Out::Interp); if (needsDynamicSections()) - DynamicPHDR.setValuesFromSection(DynamicSec); + DynamicPHDR.setValuesFromSection(Out::Dynamic); auto PHdrs = reinterpret_cast(Buf + EHdr->e_phoff); for (ProgramHeader *PHDR : PHDRs) @@ -588,7 +569,7 @@ // First entry is null. ++SHdrs; for (OutputSectionBase *Sec : OutputSections) { - Sec->setNameOffset(StrTabSec.getFileOff(Sec->getName())); + Sec->setNameOffset(Out::StrTab->getFileOff(Sec->getName())); Sec->template writeHeaderTo(SHdrs++); } }