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 <class ELFT>
void EhFrameHeader<ELFT>::addFde(uint32_t Pc, uint32_t FdeVA) {
Fdes.push_back({Pc, FdeVA});
}
template <class ELFT>
-VersionDefinitionSection<ELFT>::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 <class ELFT> void VersionDefinitionSection<ELFT>::finalize() {
- FileDefNameOff = In<ELFT>::DynStrTab->addString(getFileDefName());
- for (VersionDefinition &V : Config->VersionDefinitions)
- V.NameOff = In<ELFT>::DynStrTab->addString(V.Name);
-
- this->Size = (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum();
- this->Link = In<ELFT>::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 <class ELFT>
-void VersionDefinitionSection<ELFT>::writeOne(uint8_t *Buf, uint32_t Index,
- StringRef Name, size_t NameOff) {
- auto *Verdef = reinterpret_cast<Elf_Verdef *>(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<Elf_Verdaux *>(Buf + sizeof(Elf_Verdef));
- Verdaux->vda_name = NameOff;
- Verdaux->vda_next = 0;
-}
-
-template <class ELFT>
-void VersionDefinitionSection<ELFT>::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<Elf_Verdef *>(Buf);
- Verdef->vd_next = 0;
-}
-
-template <class ELFT>
-VersionTableSection<ELFT>::VersionTableSection()
- : OutputSectionBase(".gnu.version", SHT_GNU_versym, SHF_ALLOC) {
- this->Addralign = sizeof(uint16_t);
-}
-
-template <class ELFT> void VersionTableSection<ELFT>::finalize() {
- this->Size =
- sizeof(Elf_Versym) * (In<ELFT>::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<ELFT>::DynSymTab->OutSec->SectionIndex;
-}
-
-template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
- auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1;
- for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) {
- OutVersym->vs_index = S.Symbol->symbol()->VersionId;
- ++OutVersym;
- }
-}
-
-template <class ELFT>
-VersionNeedSection<ELFT>::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 <class ELFT>
-void VersionNeedSection<ELFT>::addSymbol(SharedSymbol<ELFT> *SS) {
- if (!SS->Verdef) {
- SS->symbol()->VersionId = VER_NDX_GLOBAL;
- return;
- }
- SharedFile<ELFT> *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<ELFT>::DynStrTab->addString(F->getSoName())});
- typename SharedFile<ELFT>::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<ELFT>::DynStrTab->addString(
- SS->file()->getStringTable().data() + SS->Verdef->getAux()->vda_name);
- NV.Index = NextIndex++;
- }
- SS->symbol()->VersionId = NV.Index;
-}
-
-template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {
- // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs.
- auto *Verneed = reinterpret_cast<Elf_Verneed *>(Buf);
- auto *Vernaux = reinterpret_cast<Elf_Vernaux *>(Verneed + Needed.size());
-
- for (std::pair<SharedFile<ELFT> *, 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<char *>(Vernaux) - reinterpret_cast<char *>(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 <class ELFT> void VersionNeedSection<ELFT>::finalize() {
- this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex;
- this->Info = Needed.size();
- unsigned Size = Needed.size() * sizeof(Elf_Verneed);
- for (std::pair<SharedFile<ELFT> *, size_t> &P : Needed)
- Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux);
- this->Size = Size;
-}
-
-template <class ELFT>
static typename ELFT::uint getOutFlags(InputSectionBase<ELFT> *S) {
return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED;
}
template class MergeOutputSection<ELF64LE>;
template class MergeOutputSection<ELF64BE>;
-template class VersionTableSection<ELF32LE>;
-template class VersionTableSection<ELF32BE>;
-template class VersionTableSection<ELF64LE>;
-template class VersionTableSection<ELF64BE>;
-
-template class VersionNeedSection<ELF32LE>;
-template class VersionNeedSection<ELF32BE>;
-template class VersionNeedSection<ELF64LE>;
-template class VersionNeedSection<ELF64BE>;
-
-template class VersionDefinitionSection<ELF32LE>;
-template class VersionDefinitionSection<ELF32BE>;
-template class VersionDefinitionSection<ELF64LE>;
-template class VersionDefinitionSection<ELF64BE>;
-
template class OutputSectionFactory<ELF32LE>;
template class OutputSectionFactory<ELF32BE>;
template class OutputSectionFactory<ELF64LE>;
EHFrame,
Merge,
Regular,
- VersDef,
- VersNeed,
- VersTable
};
OutputSectionBase(StringRef Name, uint32_t Type, uint64_t Flags);
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 ELFT>
-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 ELFT>
-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 ELFT>
-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<std::pair<SharedFile<ELFT> *, size_t>> Needed;
-
- // The next available version identifier.
- unsigned NextIndex;
-
-public:
- VersionNeedSection();
- void addSymbol(SharedSymbol<ELFT> *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 ELFT> class OutputSection final : public OutputSectionBase {
public:
static OutputSection<ELFT> *MipsRldMap;
static OutputSectionBase *Opd;
static uint8_t *OpdBuf;
- static VersionDefinitionSection<ELFT> *VerDef;
- static VersionTableSection<ELFT> *VerSym;
- static VersionNeedSection<ELFT> *VerNeed;
static Elf_Phdr *TlsPhdr;
static OutputSectionBase *DebugInfo;
static OutputSectionBase *ElfHeader;
template <class ELFT> OutputSection<ELFT> *Out<ELFT>::MipsRldMap;
template <class ELFT> OutputSectionBase *Out<ELFT>::Opd;
template <class ELFT> uint8_t *Out<ELFT>::OpdBuf;
-template <class ELFT> VersionDefinitionSection<ELFT> *Out<ELFT>::VerDef;
-template <class ELFT> VersionTableSection<ELFT> *Out<ELFT>::VerSym;
-template <class ELFT> VersionNeedSection<ELFT> *Out<ELFT>::VerNeed;
template <class ELFT> typename ELFT::Phdr *Out<ELFT>::TlsPhdr;
template <class ELFT> OutputSectionBase *Out<ELFT>::DebugInfo;
template <class ELFT> OutputSectionBase *Out<ELFT>::ElfHeader;
}
}
+// 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 <class ELFT>
if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Fini))
add({DT_FINI, B});
- bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
- if (HasVerNeed || Out<ELFT>::VerDef)
- add({DT_VERSYM, Out<ELFT>::VerSym});
- if (Out<ELFT>::VerDef) {
- add({DT_VERDEF, Out<ELFT>::VerDef});
+ bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0;
+ if (HasVerNeed || In<ELFT>::VerDef)
+ add({DT_VERSYM, In<ELFT>::VerSym});
+ if (In<ELFT>::VerDef) {
+ add({DT_VERDEF, In<ELFT>::VerDef});
add({DT_VERDEFNUM, getVerDefNum()});
}
if (HasVerNeed) {
- add({DT_VERNEED, Out<ELFT>::VerNeed});
- add({DT_VERNEEDNUM, Out<ELFT>::VerNeed->getNeedNum()});
+ add({DT_VERNEED, In<ELFT>::VerNeed});
+ add({DT_VERNEEDNUM, In<ELFT>::VerNeed->getNeedNum()});
}
if (Config->EMachine == EM_MIPS) {
return 12 + Out<ELFT>::EhFrame->NumFdes * 8;
}
+template <class ELFT>
+VersionDefinitionSection<ELFT>::VersionDefinitionSection()
+ : SyntheticSection<ELFT>(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 <class ELFT> void VersionDefinitionSection<ELFT>::finalize() {
+ FileDefNameOff = In<ELFT>::DynStrTab->addString(getFileDefName());
+ for (VersionDefinition &V : Config->VersionDefinitions)
+ V.NameOff = In<ELFT>::DynStrTab->addString(V.Name);
+
+ this->OutSec->Link = this->Link = In<ELFT>::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 <class ELFT>
+void VersionDefinitionSection<ELFT>::writeOne(uint8_t *Buf, uint32_t Index,
+ StringRef Name, size_t NameOff) {
+ auto *Verdef = reinterpret_cast<Elf_Verdef *>(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<Elf_Verdaux *>(Buf + sizeof(Elf_Verdef));
+ Verdaux->vda_name = NameOff;
+ Verdaux->vda_next = 0;
+}
+
+template <class ELFT>
+void VersionDefinitionSection<ELFT>::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<Elf_Verdef *>(Buf);
+ Verdef->vd_next = 0;
+}
+
+template <class ELFT> size_t VersionDefinitionSection<ELFT>::getSize() const {
+ return (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum();
+}
+
+template <class ELFT>
+VersionTableSection<ELFT>::VersionTableSection()
+ : SyntheticSection<ELFT>(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t),
+ ".gnu.version") {}
+
+template <class ELFT> void VersionTableSection<ELFT>::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<ELFT>::DynSymTab->OutSec->SectionIndex;
+}
+
+template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const {
+ return sizeof(Elf_Versym) * (In<ELFT>::DynSymTab->getSymbols().size() + 1);
+}
+
+template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
+ auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1;
+ for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) {
+ OutVersym->vs_index = S.Symbol->symbol()->VersionId;
+ ++OutVersym;
+ }
+}
+
+template <class ELFT>
+VersionNeedSection<ELFT>::VersionNeedSection()
+ : SyntheticSection<ELFT>(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 <class ELFT>
+void VersionNeedSection<ELFT>::addSymbol(SharedSymbol<ELFT> *SS) {
+ if (!SS->Verdef) {
+ SS->symbol()->VersionId = VER_NDX_GLOBAL;
+ return;
+ }
+ SharedFile<ELFT> *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<ELFT>::DynStrTab->addString(F->getSoName())});
+ typename SharedFile<ELFT>::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<ELFT>::DynStrTab->addString(
+ SS->file()->getStringTable().data() + SS->Verdef->getAux()->vda_name);
+ NV.Index = NextIndex++;
+ }
+ SS->symbol()->VersionId = NV.Index;
+}
+
+template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {
+ // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs.
+ auto *Verneed = reinterpret_cast<Elf_Verneed *>(Buf);
+ auto *Vernaux = reinterpret_cast<Elf_Vernaux *>(Verneed + Needed.size());
+
+ for (std::pair<SharedFile<ELFT> *, 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<char *>(Vernaux) - reinterpret_cast<char *>(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 <class ELFT> void VersionNeedSection<ELFT>::finalize() {
+ this->OutSec->Link = this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex;
+ this->OutSec->Info = this->Info = Needed.size();
+}
+
+template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const {
+ unsigned Size = Needed.size() * sizeof(Elf_Verneed);
+ for (const std::pair<SharedFile<ELFT> *, size_t> &P : Needed)
+ Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux);
+ return Size;
+}
+
template InputSection<ELF32LE> *elf::createCommonSection();
template InputSection<ELF32BE> *elf::createCommonSection();
template InputSection<ELF64LE> *elf::createCommonSection();
template class elf::EhFrameHeader<ELF32BE>;
template class elf::EhFrameHeader<ELF64LE>;
template class elf::EhFrameHeader<ELF64BE>;
+
+template class elf::VersionTableSection<ELF32LE>;
+template class elf::VersionTableSection<ELF32BE>;
+template class elf::VersionTableSection<ELF64LE>;
+template class elf::VersionTableSection<ELF64BE>;
+
+template class elf::VersionNeedSection<ELF32LE>;
+template class elf::VersionNeedSection<ELF32BE>;
+template class elf::VersionNeedSection<ELF64LE>;
+template class elf::VersionNeedSection<ELF64BE>;
+
+template class elf::VersionDefinitionSection<ELF32LE>;
+template class elf::VersionDefinitionSection<ELF32BE>;
+template class elf::VersionDefinitionSection<ELF64LE>;
+template class elf::VersionDefinitionSection<ELF64BE>;
std::vector<FdeData> 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 ELFT>
+class VersionDefinitionSection final : public SyntheticSection<ELFT> {
+ 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 ELFT>
+class VersionTableSection final : public SyntheticSection<ELFT> {
+ 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 ELFT>
+class VersionNeedSection final : public SyntheticSection<ELFT> {
+ 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<std::pair<SharedFile<ELFT> *, size_t>> Needed;
+
+ // The next available version identifier.
+ unsigned NextIndex;
+
+public:
+ VersionNeedSection();
+ void addSymbol(SharedSymbol<ELFT> *SS);
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+ size_t getSize() const override;
+ size_t getNeedNum() const { return Needed.size(); }
+};
+
template <class ELFT> InputSection<ELFT> *createCommonSection();
template <class ELFT> InputSection<ELFT> *createInterpSection();
template <class ELFT> MergeInputSection<ELFT> *createCommentSection();
static StringTableSection<ELFT> *ShStrTab;
static StringTableSection<ELFT> *StrTab;
static SymbolTableSection<ELFT> *SymTab;
+ static VersionDefinitionSection<ELFT> *VerDef;
+ static VersionTableSection<ELFT> *VerSym;
+ static VersionNeedSection<ELFT> *VerNeed;
};
template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId;
template <class ELFT> StringTableSection<ELFT> *In<ELFT>::ShStrTab;
template <class ELFT> StringTableSection<ELFT> *In<ELFT>::StrTab;
template <class ELFT> SymbolTableSection<ELFT> *In<ELFT>::SymTab;
+template <class ELFT> VersionDefinitionSection<ELFT> *In<ELFT>::VerDef;
+template <class ELFT> VersionTableSection<ELFT> *In<ELFT>::VerSym;
+template <class ELFT> VersionNeedSection<ELFT> *In<ELFT>::VerNeed;
} // namespace elf
} // namespace lld
In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>(
Config->Rela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc);
In<ELFT>::ShStrTab = make<StringTableSection<ELFT>>(".shstrtab", false);
- Out<ELFT>::VerSym = make<VersionTableSection<ELFT>>();
- Out<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
+ In<ELFT>::VerSym = make<VersionTableSection<ELFT>>();
+ In<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
Out<ELFT>::ElfHeader = make<OutputSectionBase>("", 0, SHF_ALLOC);
Out<ELFT>::ElfHeader->Size = sizeof(Elf_Ehdr);
Out<ELFT>::MipsRldMap->updateAlignment(sizeof(uintX_t));
}
if (!Config->VersionDefinitions.empty())
- Out<ELFT>::VerDef = make<VersionDefinitionSection<ELFT>>();
+ In<ELFT>::VerDef = make<VersionDefinitionSection<ELFT>>();
// Initialize linker generated sections
if (!Config->Relocatable)
In<ELFT>::DynSymTab->addSymbol(Body);
if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
if (SS->file()->isNeeded())
- Out<ELFT>::VerNeed->addSymbol(SS);
+ In<ELFT>::VerNeed->addSymbol(SS);
}
}
// Dynamic section must be the last one in this list and dynamic
// symbol table section (DynSymTab) must be the first one.
- finalizeSynthetic<ELFT>({In<ELFT>::DynSymTab, In<ELFT>::GnuHashTab,
- In<ELFT>::HashTab, In<ELFT>::SymTab,
- In<ELFT>::ShStrTab, In<ELFT>::StrTab,
- In<ELFT>::DynStrTab, In<ELFT>::GdbIndex,
- In<ELFT>::Got, In<ELFT>::MipsGot, In<ELFT>::GotPlt,
- In<ELFT>::RelaDyn, In<ELFT>::RelaPlt, In<ELFT>::Plt,
- In<ELFT>::EhFrameHdr, In<ELFT>::Dynamic});
+ finalizeSynthetic<ELFT>(
+ {In<ELFT>::DynSymTab, In<ELFT>::GnuHashTab, In<ELFT>::HashTab,
+ In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab,
+ In<ELFT>::DynStrTab, In<ELFT>::GdbIndex, In<ELFT>::Got,
+ In<ELFT>::MipsGot, In<ELFT>::GotPlt, In<ELFT>::RelaDyn,
+ In<ELFT>::RelaPlt, In<ELFT>::Plt, In<ELFT>::EhFrameHdr, In<ELFT>::VerDef,
+ In<ELFT>::VerSym, In<ELFT>::VerNeed, In<ELFT>::Dynamic});
}
template <class ELFT> bool Writer<ELFT>::needsGot() {
if (In<ELFT>::DynSymTab) {
addInputSec(In<ELFT>::DynSymTab);
- bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
- if (Out<ELFT>::VerDef || HasVerNeed)
- Add(Out<ELFT>::VerSym);
- Add(Out<ELFT>::VerDef);
+ bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0;
+ if (In<ELFT>::VerDef || HasVerNeed)
+ addInputSec(In<ELFT>::VerSym);
+ addInputSec(In<ELFT>::VerDef);
if (HasVerNeed)
- Add(Out<ELFT>::VerNeed);
+ addInputSec(In<ELFT>::VerNeed);
addInputSec(In<ELFT>::GnuHashTab);
addInputSec(In<ELFT>::HashTab);