From e9bab5d8571e8c4b9becf9fd2330d6557715238e Mon Sep 17 00:00:00 2001 From: Eugene Leviant Date: Mon, 21 Nov 2016 16:59:33 +0000 Subject: [PATCH] [ELF] Convert Version*** sections to input sections Differential revision: https://reviews.llvm.org/D26918 llvm-svn: 287554 --- lld/ELF/OutputSections.cpp | 179 -------------------------------------- lld/ELF/OutputSections.h | 86 ------------------ lld/ELF/SyntheticSections.cpp | 196 ++++++++++++++++++++++++++++++++++++++++-- lld/ELF/SyntheticSections.h | 74 ++++++++++++++++ lld/ELF/Writer.cpp | 32 +++---- 5 files changed, 279 insertions(+), 288 deletions(-) diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 9f22a4f..a198644 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -62,11 +62,6 @@ void OutputSectionBase::writeHeaderTo(typename ELFT::Shdr *Shdr) { Shdr->sh_name = ShName; } -// Returns the number of version definition entries. Because the first entry -// is for the version definition itself, it is the number of versioned symbols -// plus one. Note that we don't support multiple versions yet. -static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; } - template void EhFrameHeader::addFde(uint32_t Pc, uint32_t FdeVA) { Fdes.push_back({Pc, FdeVA}); @@ -531,165 +526,6 @@ template void MergeOutputSection::finalize() { } template -VersionDefinitionSection::VersionDefinitionSection() - : OutputSectionBase(".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC) { - this->Addralign = sizeof(uint32_t); -} - -static StringRef getFileDefName() { - if (!Config->SoName.empty()) - return Config->SoName; - return Config->OutputFile; -} - -template void VersionDefinitionSection::finalize() { - FileDefNameOff = In::DynStrTab->addString(getFileDefName()); - for (VersionDefinition &V : Config->VersionDefinitions) - V.NameOff = In::DynStrTab->addString(V.Name); - - this->Size = (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum(); - this->Link = In::DynStrTab->OutSec->SectionIndex; - - // sh_info should be set to the number of definitions. This fact is missed in - // documentation, but confirmed by binutils community: - // https://sourceware.org/ml/binutils/2014-11/msg00355.html - this->Info = getVerDefNum(); -} - -template -void VersionDefinitionSection::writeOne(uint8_t *Buf, uint32_t Index, - StringRef Name, size_t NameOff) { - auto *Verdef = reinterpret_cast(Buf); - Verdef->vd_version = 1; - Verdef->vd_cnt = 1; - Verdef->vd_aux = sizeof(Elf_Verdef); - Verdef->vd_next = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); - Verdef->vd_flags = (Index == 1 ? VER_FLG_BASE : 0); - Verdef->vd_ndx = Index; - Verdef->vd_hash = hashSysV(Name); - - auto *Verdaux = reinterpret_cast(Buf + sizeof(Elf_Verdef)); - Verdaux->vda_name = NameOff; - Verdaux->vda_next = 0; -} - -template -void VersionDefinitionSection::writeTo(uint8_t *Buf) { - writeOne(Buf, 1, getFileDefName(), FileDefNameOff); - - for (VersionDefinition &V : Config->VersionDefinitions) { - Buf += sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); - writeOne(Buf, V.Id, V.Name, V.NameOff); - } - - // Need to terminate the last version definition. - Elf_Verdef *Verdef = reinterpret_cast(Buf); - Verdef->vd_next = 0; -} - -template -VersionTableSection::VersionTableSection() - : OutputSectionBase(".gnu.version", SHT_GNU_versym, SHF_ALLOC) { - this->Addralign = sizeof(uint16_t); -} - -template void VersionTableSection::finalize() { - this->Size = - sizeof(Elf_Versym) * (In::DynSymTab->getSymbols().size() + 1); - this->Entsize = sizeof(Elf_Versym); - // At the moment of june 2016 GNU docs does not mention that sh_link field - // should be set, but Sun docs do. Also readelf relies on this field. - this->Link = In::DynSymTab->OutSec->SectionIndex; -} - -template void VersionTableSection::writeTo(uint8_t *Buf) { - auto *OutVersym = reinterpret_cast(Buf) + 1; - for (const SymbolTableEntry &S : In::DynSymTab->getSymbols()) { - OutVersym->vs_index = S.Symbol->symbol()->VersionId; - ++OutVersym; - } -} - -template -VersionNeedSection::VersionNeedSection() - : OutputSectionBase(".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC) { - this->Addralign = sizeof(uint32_t); - - // Identifiers in verneed section start at 2 because 0 and 1 are reserved - // for VER_NDX_LOCAL and VER_NDX_GLOBAL. - // First identifiers are reserved by verdef section if it exist. - NextIndex = getVerDefNum() + 1; -} - -template -void VersionNeedSection::addSymbol(SharedSymbol *SS) { - if (!SS->Verdef) { - SS->symbol()->VersionId = VER_NDX_GLOBAL; - return; - } - SharedFile *F = SS->file(); - // If we don't already know that we need an Elf_Verneed for this DSO, prepare - // to create one by adding it to our needed list and creating a dynstr entry - // for the soname. - if (F->VerdefMap.empty()) - Needed.push_back({F, In::DynStrTab->addString(F->getSoName())}); - typename SharedFile::NeededVer &NV = F->VerdefMap[SS->Verdef]; - // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef, - // prepare to create one by allocating a version identifier and creating a - // dynstr entry for the version name. - if (NV.Index == 0) { - NV.StrTab = In::DynStrTab->addString( - SS->file()->getStringTable().data() + SS->Verdef->getAux()->vda_name); - NV.Index = NextIndex++; - } - SS->symbol()->VersionId = NV.Index; -} - -template void VersionNeedSection::writeTo(uint8_t *Buf) { - // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs. - auto *Verneed = reinterpret_cast(Buf); - auto *Vernaux = reinterpret_cast(Verneed + Needed.size()); - - for (std::pair *, size_t> &P : Needed) { - // Create an Elf_Verneed for this DSO. - Verneed->vn_version = 1; - Verneed->vn_cnt = P.first->VerdefMap.size(); - Verneed->vn_file = P.second; - Verneed->vn_aux = - reinterpret_cast(Vernaux) - reinterpret_cast(Verneed); - Verneed->vn_next = sizeof(Elf_Verneed); - ++Verneed; - - // Create the Elf_Vernauxs for this Elf_Verneed. The loop iterates over - // VerdefMap, which will only contain references to needed version - // definitions. Each Elf_Vernaux is based on the information contained in - // the Elf_Verdef in the source DSO. This loop iterates over a std::map of - // pointers, but is deterministic because the pointers refer to Elf_Verdef - // data structures within a single input file. - for (auto &NV : P.first->VerdefMap) { - Vernaux->vna_hash = NV.first->vd_hash; - Vernaux->vna_flags = 0; - Vernaux->vna_other = NV.second.Index; - Vernaux->vna_name = NV.second.StrTab; - Vernaux->vna_next = sizeof(Elf_Vernaux); - ++Vernaux; - } - - Vernaux[-1].vna_next = 0; - } - Verneed[-1].vn_next = 0; -} - -template void VersionNeedSection::finalize() { - this->Link = In::DynStrTab->OutSec->SectionIndex; - this->Info = Needed.size(); - unsigned Size = Needed.size() * sizeof(Elf_Verneed); - for (std::pair *, size_t> &P : Needed) - Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux); - this->Size = Size; -} - -template static typename ELFT::uint getOutFlags(InputSectionBase *S) { return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED; } @@ -803,21 +639,6 @@ template class MergeOutputSection; template class MergeOutputSection; template class MergeOutputSection; -template class VersionTableSection; -template class VersionTableSection; -template class VersionTableSection; -template class VersionTableSection; - -template class VersionNeedSection; -template class VersionNeedSection; -template class VersionNeedSection; -template class VersionNeedSection; - -template class VersionDefinitionSection; -template class VersionDefinitionSection; -template class VersionDefinitionSection; -template class VersionDefinitionSection; - template class OutputSectionFactory; template class OutputSectionFactory; template class OutputSectionFactory; diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 1431ab9..22c6dc5 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -44,9 +44,6 @@ public: EHFrame, Merge, Regular, - VersDef, - VersNeed, - VersTable }; OutputSectionBase(StringRef Name, uint32_t Type, uint64_t Flags); @@ -103,83 +100,6 @@ public: uint32_t Link = 0; }; -// For more information about .gnu.version and .gnu.version_r see: -// https://www.akkadia.org/drepper/symbol-versioning - -// The .gnu.version_d section which has a section type of SHT_GNU_verdef shall -// contain symbol version definitions. The number of entries in this section -// shall be contained in the DT_VERDEFNUM entry of the .dynamic section. -// The section shall contain an array of Elf_Verdef structures, optionally -// followed by an array of Elf_Verdaux structures. -template -class VersionDefinitionSection final : public OutputSectionBase { - typedef typename ELFT::Verdef Elf_Verdef; - typedef typename ELFT::Verdaux Elf_Verdaux; - -public: - VersionDefinitionSection(); - void finalize() override; - void writeTo(uint8_t *Buf) override; - Kind getKind() const override { return VersDef; } - static bool classof(const OutputSectionBase *B) { - return B->getKind() == VersDef; - } - -private: - void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff); - - unsigned FileDefNameOff; -}; - -// The .gnu.version section specifies the required version of each symbol in the -// dynamic symbol table. It contains one Elf_Versym for each dynamic symbol -// table entry. An Elf_Versym is just a 16-bit integer that refers to a version -// identifier defined in the either .gnu.version_r or .gnu.version_d section. -// The values 0 and 1 are reserved. All other values are used for versions in -// the own object or in any of the dependencies. -template -class VersionTableSection final : public OutputSectionBase { - typedef typename ELFT::Versym Elf_Versym; - -public: - VersionTableSection(); - void finalize() override; - void writeTo(uint8_t *Buf) override; - Kind getKind() const override { return VersTable; } - static bool classof(const OutputSectionBase *B) { - return B->getKind() == VersTable; - } -}; - -// The .gnu.version_r section defines the version identifiers used by -// .gnu.version. It contains a linked list of Elf_Verneed data structures. Each -// Elf_Verneed specifies the version requirements for a single DSO, and contains -// a reference to a linked list of Elf_Vernaux data structures which define the -// mapping from version identifiers to version names. -template -class VersionNeedSection final : public OutputSectionBase { - typedef typename ELFT::Verneed Elf_Verneed; - typedef typename ELFT::Vernaux Elf_Vernaux; - - // A vector of shared files that need Elf_Verneed data structures and the - // string table offsets of their sonames. - std::vector *, size_t>> Needed; - - // The next available version identifier. - unsigned NextIndex; - -public: - VersionNeedSection(); - void addSymbol(SharedSymbol *SS); - void finalize() override; - void writeTo(uint8_t *Buf) override; - size_t getNeedNum() const { return Needed.size(); } - Kind getKind() const override { return VersNeed; } - static bool classof(const OutputSectionBase *B) { - return B->getKind() == VersNeed; - } -}; - template class OutputSection final : public OutputSectionBase { public: @@ -284,9 +204,6 @@ template struct Out { static OutputSection *MipsRldMap; static OutputSectionBase *Opd; static uint8_t *OpdBuf; - static VersionDefinitionSection *VerDef; - static VersionTableSection *VerSym; - static VersionNeedSection *VerNeed; static Elf_Phdr *TlsPhdr; static OutputSectionBase *DebugInfo; static OutputSectionBase *ElfHeader; @@ -335,9 +252,6 @@ template OutputSection *Out::Bss; template OutputSection *Out::MipsRldMap; template OutputSectionBase *Out::Opd; template uint8_t *Out::OpdBuf; -template VersionDefinitionSection *Out::VerDef; -template VersionTableSection *Out::VerSym; -template VersionNeedSection *Out::VerNeed; template typename ELFT::Phdr *Out::TlsPhdr; template OutputSectionBase *Out::DebugInfo; template OutputSectionBase *Out::ElfHeader; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 3feec78..dd5eb2b 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -704,6 +704,9 @@ template void StringTableSection::writeTo(uint8_t *Buf) { } } +// Returns the number of version definition entries. Because the first entry +// is for the version definition itself, it is the number of versioned symbols +// plus one. Note that we don't support multiple versions yet. static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; } template @@ -819,16 +822,16 @@ template void DynamicSection::finalize() { if (SymbolBody *B = Symtab::X->find(Config->Fini)) add({DT_FINI, B}); - bool HasVerNeed = Out::VerNeed->getNeedNum() != 0; - if (HasVerNeed || Out::VerDef) - add({DT_VERSYM, Out::VerSym}); - if (Out::VerDef) { - add({DT_VERDEF, Out::VerDef}); + bool HasVerNeed = In::VerNeed->getNeedNum() != 0; + if (HasVerNeed || In::VerDef) + add({DT_VERSYM, In::VerSym}); + if (In::VerDef) { + add({DT_VERDEF, In::VerDef}); add({DT_VERDEFNUM, getVerDefNum()}); } if (HasVerNeed) { - add({DT_VERNEED, Out::VerNeed}); - add({DT_VERNEEDNUM, Out::VerNeed->getNeedNum()}); + add({DT_VERNEED, In::VerNeed}); + add({DT_VERNEEDNUM, In::VerNeed->getNeedNum()}); } if (Config->EMachine == EM_MIPS) { @@ -1445,6 +1448,170 @@ template size_t EhFrameHeader::getSize() const { return 12 + Out::EhFrame->NumFdes * 8; } +template +VersionDefinitionSection::VersionDefinitionSection() + : SyntheticSection(SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t), + ".gnu.version_d") {} + +static StringRef getFileDefName() { + if (!Config->SoName.empty()) + return Config->SoName; + return Config->OutputFile; +} + +template void VersionDefinitionSection::finalize() { + FileDefNameOff = In::DynStrTab->addString(getFileDefName()); + for (VersionDefinition &V : Config->VersionDefinitions) + V.NameOff = In::DynStrTab->addString(V.Name); + + this->OutSec->Link = this->Link = In::DynStrTab->OutSec->SectionIndex; + + // sh_info should be set to the number of definitions. This fact is missed in + // documentation, but confirmed by binutils community: + // https://sourceware.org/ml/binutils/2014-11/msg00355.html + this->OutSec->Info = this->Info = getVerDefNum(); +} + +template +void VersionDefinitionSection::writeOne(uint8_t *Buf, uint32_t Index, + StringRef Name, size_t NameOff) { + auto *Verdef = reinterpret_cast(Buf); + Verdef->vd_version = 1; + Verdef->vd_cnt = 1; + Verdef->vd_aux = sizeof(Elf_Verdef); + Verdef->vd_next = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); + Verdef->vd_flags = (Index == 1 ? VER_FLG_BASE : 0); + Verdef->vd_ndx = Index; + Verdef->vd_hash = hashSysV(Name); + + auto *Verdaux = reinterpret_cast(Buf + sizeof(Elf_Verdef)); + Verdaux->vda_name = NameOff; + Verdaux->vda_next = 0; +} + +template +void VersionDefinitionSection::writeTo(uint8_t *Buf) { + writeOne(Buf, 1, getFileDefName(), FileDefNameOff); + + for (VersionDefinition &V : Config->VersionDefinitions) { + Buf += sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); + writeOne(Buf, V.Id, V.Name, V.NameOff); + } + + // Need to terminate the last version definition. + Elf_Verdef *Verdef = reinterpret_cast(Buf); + Verdef->vd_next = 0; +} + +template size_t VersionDefinitionSection::getSize() const { + return (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum(); +} + +template +VersionTableSection::VersionTableSection() + : SyntheticSection(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t), + ".gnu.version") {} + +template void VersionTableSection::finalize() { + this->OutSec->Entsize = this->Entsize = sizeof(Elf_Versym); + // At the moment of june 2016 GNU docs does not mention that sh_link field + // should be set, but Sun docs do. Also readelf relies on this field. + this->OutSec->Link = this->Link = In::DynSymTab->OutSec->SectionIndex; +} + +template size_t VersionTableSection::getSize() const { + return sizeof(Elf_Versym) * (In::DynSymTab->getSymbols().size() + 1); +} + +template void VersionTableSection::writeTo(uint8_t *Buf) { + auto *OutVersym = reinterpret_cast(Buf) + 1; + for (const SymbolTableEntry &S : In::DynSymTab->getSymbols()) { + OutVersym->vs_index = S.Symbol->symbol()->VersionId; + ++OutVersym; + } +} + +template +VersionNeedSection::VersionNeedSection() + : SyntheticSection(SHF_ALLOC, SHT_GNU_verneed, sizeof(uint32_t), + ".gnu.version_r") { + // Identifiers in verneed section start at 2 because 0 and 1 are reserved + // for VER_NDX_LOCAL and VER_NDX_GLOBAL. + // First identifiers are reserved by verdef section if it exist. + NextIndex = getVerDefNum() + 1; +} + +template +void VersionNeedSection::addSymbol(SharedSymbol *SS) { + if (!SS->Verdef) { + SS->symbol()->VersionId = VER_NDX_GLOBAL; + return; + } + SharedFile *F = SS->file(); + // If we don't already know that we need an Elf_Verneed for this DSO, prepare + // to create one by adding it to our needed list and creating a dynstr entry + // for the soname. + if (F->VerdefMap.empty()) + Needed.push_back({F, In::DynStrTab->addString(F->getSoName())}); + typename SharedFile::NeededVer &NV = F->VerdefMap[SS->Verdef]; + // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef, + // prepare to create one by allocating a version identifier and creating a + // dynstr entry for the version name. + if (NV.Index == 0) { + NV.StrTab = In::DynStrTab->addString( + SS->file()->getStringTable().data() + SS->Verdef->getAux()->vda_name); + NV.Index = NextIndex++; + } + SS->symbol()->VersionId = NV.Index; +} + +template void VersionNeedSection::writeTo(uint8_t *Buf) { + // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs. + auto *Verneed = reinterpret_cast(Buf); + auto *Vernaux = reinterpret_cast(Verneed + Needed.size()); + + for (std::pair *, size_t> &P : Needed) { + // Create an Elf_Verneed for this DSO. + Verneed->vn_version = 1; + Verneed->vn_cnt = P.first->VerdefMap.size(); + Verneed->vn_file = P.second; + Verneed->vn_aux = + reinterpret_cast(Vernaux) - reinterpret_cast(Verneed); + Verneed->vn_next = sizeof(Elf_Verneed); + ++Verneed; + + // Create the Elf_Vernauxs for this Elf_Verneed. The loop iterates over + // VerdefMap, which will only contain references to needed version + // definitions. Each Elf_Vernaux is based on the information contained in + // the Elf_Verdef in the source DSO. This loop iterates over a std::map of + // pointers, but is deterministic because the pointers refer to Elf_Verdef + // data structures within a single input file. + for (auto &NV : P.first->VerdefMap) { + Vernaux->vna_hash = NV.first->vd_hash; + Vernaux->vna_flags = 0; + Vernaux->vna_other = NV.second.Index; + Vernaux->vna_name = NV.second.StrTab; + Vernaux->vna_next = sizeof(Elf_Vernaux); + ++Vernaux; + } + + Vernaux[-1].vna_next = 0; + } + Verneed[-1].vn_next = 0; +} + +template void VersionNeedSection::finalize() { + this->OutSec->Link = this->Link = In::DynStrTab->OutSec->SectionIndex; + this->OutSec->Info = this->Info = Needed.size(); +} + +template size_t VersionNeedSection::getSize() const { + unsigned Size = Needed.size() * sizeof(Elf_Verneed); + for (const std::pair *, size_t> &P : Needed) + Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux); + return Size; +} + template InputSection *elf::createCommonSection(); template InputSection *elf::createCommonSection(); template InputSection *elf::createCommonSection(); @@ -1564,3 +1731,18 @@ template class elf::EhFrameHeader; template class elf::EhFrameHeader; template class elf::EhFrameHeader; template class elf::EhFrameHeader; + +template class elf::VersionTableSection; +template class elf::VersionTableSection; +template class elf::VersionTableSection; +template class elf::VersionTableSection; + +template class elf::VersionNeedSection; +template class elf::VersionNeedSection; +template class elf::VersionNeedSection; +template class elf::VersionNeedSection; + +template class elf::VersionDefinitionSection; +template class elf::VersionDefinitionSection; +template class elf::VersionDefinitionSection; +template class elf::VersionDefinitionSection; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index bb42915..164c2e5 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -557,6 +557,74 @@ private: std::vector Fdes; }; +// For more information about .gnu.version and .gnu.version_r see: +// https://www.akkadia.org/drepper/symbol-versioning + +// The .gnu.version_d section which has a section type of SHT_GNU_verdef shall +// contain symbol version definitions. The number of entries in this section +// shall be contained in the DT_VERDEFNUM entry of the .dynamic section. +// The section shall contain an array of Elf_Verdef structures, optionally +// followed by an array of Elf_Verdaux structures. +template +class VersionDefinitionSection final : public SyntheticSection { + typedef typename ELFT::Verdef Elf_Verdef; + typedef typename ELFT::Verdaux Elf_Verdaux; + +public: + VersionDefinitionSection(); + void finalize() override; + size_t getSize() const override; + void writeTo(uint8_t *Buf) override; + +private: + void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff); + + unsigned FileDefNameOff; +}; + +// The .gnu.version section specifies the required version of each symbol in the +// dynamic symbol table. It contains one Elf_Versym for each dynamic symbol +// table entry. An Elf_Versym is just a 16-bit integer that refers to a version +// identifier defined in the either .gnu.version_r or .gnu.version_d section. +// The values 0 and 1 are reserved. All other values are used for versions in +// the own object or in any of the dependencies. +template +class VersionTableSection final : public SyntheticSection { + typedef typename ELFT::Versym Elf_Versym; + +public: + VersionTableSection(); + void finalize() override; + size_t getSize() const override; + void writeTo(uint8_t *Buf) override; +}; + +// The .gnu.version_r section defines the version identifiers used by +// .gnu.version. It contains a linked list of Elf_Verneed data structures. Each +// Elf_Verneed specifies the version requirements for a single DSO, and contains +// a reference to a linked list of Elf_Vernaux data structures which define the +// mapping from version identifiers to version names. +template +class VersionNeedSection final : public SyntheticSection { + typedef typename ELFT::Verneed Elf_Verneed; + typedef typename ELFT::Vernaux Elf_Vernaux; + + // A vector of shared files that need Elf_Verneed data structures and the + // string table offsets of their sonames. + std::vector *, size_t>> Needed; + + // The next available version identifier. + unsigned NextIndex; + +public: + VersionNeedSection(); + void addSymbol(SharedSymbol *SS); + void finalize() override; + void writeTo(uint8_t *Buf) override; + size_t getSize() const override; + size_t getNeedNum() const { return Needed.size(); } +}; + template InputSection *createCommonSection(); template InputSection *createInterpSection(); template MergeInputSection *createCommentSection(); @@ -585,6 +653,9 @@ template struct In { static StringTableSection *ShStrTab; static StringTableSection *StrTab; static SymbolTableSection *SymTab; + static VersionDefinitionSection *VerDef; + static VersionTableSection *VerSym; + static VersionNeedSection *VerNeed; }; template BuildIdSection *In::BuildId; @@ -609,6 +680,9 @@ template RelocationSection *In::RelaPlt; template StringTableSection *In::ShStrTab; template StringTableSection *In::StrTab; template SymbolTableSection *In::SymTab; +template VersionDefinitionSection *In::VerDef; +template VersionTableSection *In::VerSym; +template VersionNeedSection *In::VerNeed; } // namespace elf } // namespace lld diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index ca6b76f..a5d34b5 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -241,8 +241,8 @@ template void Writer::createSyntheticSections() { In::RelaDyn = make>( Config->Rela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc); In::ShStrTab = make>(".shstrtab", false); - Out::VerSym = make>(); - Out::VerNeed = make>(); + In::VerSym = make>(); + In::VerNeed = make>(); Out::ElfHeader = make("", 0, SHF_ALLOC); Out::ElfHeader->Size = sizeof(Elf_Ehdr); @@ -288,7 +288,7 @@ template void Writer::createSyntheticSections() { Out::MipsRldMap->updateAlignment(sizeof(uintX_t)); } if (!Config->VersionDefinitions.empty()) - Out::VerDef = make>(); + In::VerDef = make>(); // Initialize linker generated sections if (!Config->Relocatable) @@ -948,7 +948,7 @@ template void Writer::finalizeSections() { In::DynSymTab->addSymbol(Body); if (auto *SS = dyn_cast>(Body)) if (SS->file()->isNeeded()) - Out::VerNeed->addSymbol(SS); + In::VerNeed->addSymbol(SS); } } @@ -976,13 +976,13 @@ template void Writer::finalizeSections() { // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. - finalizeSynthetic({In::DynSymTab, In::GnuHashTab, - In::HashTab, In::SymTab, - In::ShStrTab, In::StrTab, - In::DynStrTab, In::GdbIndex, - In::Got, In::MipsGot, In::GotPlt, - In::RelaDyn, In::RelaPlt, In::Plt, - In::EhFrameHdr, In::Dynamic}); + finalizeSynthetic( + {In::DynSymTab, In::GnuHashTab, In::HashTab, + In::SymTab, In::ShStrTab, In::StrTab, + In::DynStrTab, In::GdbIndex, In::Got, + In::MipsGot, In::GotPlt, In::RelaDyn, + In::RelaPlt, In::Plt, In::EhFrameHdr, In::VerDef, + In::VerSym, In::VerNeed, In::Dynamic}); } template bool Writer::needsGot() { @@ -1016,12 +1016,12 @@ template void Writer::addPredefinedSections() { if (In::DynSymTab) { addInputSec(In::DynSymTab); - bool HasVerNeed = Out::VerNeed->getNeedNum() != 0; - if (Out::VerDef || HasVerNeed) - Add(Out::VerSym); - Add(Out::VerDef); + bool HasVerNeed = In::VerNeed->getNeedNum() != 0; + if (In::VerDef || HasVerNeed) + addInputSec(In::VerSym); + addInputSec(In::VerDef); if (HasVerNeed) - Add(Out::VerNeed); + addInputSec(In::VerNeed); addInputSec(In::GnuHashTab); addInputSec(In::HashTab); -- 2.7.4