[lld] r287216 - [ELF] Convert SymbolTableSection to input section
Eugene Leviant via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 17 01:16:34 PST 2016
Author: evgeny777
Date: Thu Nov 17 03:16:34 2016
New Revision: 287216
URL: http://llvm.org/viewvc/llvm-project?rev=287216&view=rev
Log:
[ELF] Convert SymbolTableSection to input section
Differential revision: https://reviews.llvm.org/D26740
Modified:
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
lld/trunk/ELF/SyntheticSections.cpp
lld/trunk/ELF/SyntheticSections.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Nov 17 03:16:34 2016
@@ -148,20 +148,20 @@ HashTableSection<ELFT>::HashTableSection
}
template <class ELFT> void HashTableSection<ELFT>::finalize() {
- this->Link = Out<ELFT>::DynSymTab->SectionIndex;
+ this->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex;
unsigned NumEntries = 2; // nbucket and nchain.
- NumEntries += Out<ELFT>::DynSymTab->getNumSymbols(); // The chain entries.
+ NumEntries += In<ELFT>::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<ELFT>::DynSymTab->getNumSymbols();
+ NumEntries += In<ELFT>::DynSymTab->getNumSymbols();
this->Size = NumEntries * sizeof(Elf_Word);
}
template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
- unsigned NumSymbols = Out<ELFT>::DynSymTab->getNumSymbols();
+ unsigned NumSymbols = In<ELFT>::DynSymTab->getNumSymbols();
auto *P = reinterpret_cast<Elf_Word *>(Buf);
*P++ = NumSymbols; // nbucket
*P++ = NumSymbols; // nchain
@@ -169,7 +169,7 @@ template <class ELFT> void HashTableSect
Elf_Word *Buckets = P;
Elf_Word *Chains = P + NumSymbols;
- for (const SymbolTableEntry &S : Out<ELFT>::DynSymTab->getSymbols()) {
+ for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) {
SymbolBody *Body = S.Symbol;
StringRef Name = Body->getName();
unsigned I = Body->DynsymIndex;
@@ -234,7 +234,7 @@ template <class ELFT> void GnuHashTableS
// Second hash shift estimation: just predefined values.
Shift2 = ELFT::Is64Bits ? 6 : 5;
- this->Link = Out<ELFT>::DynSymTab->SectionIndex;
+ this->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex;
this->Size = sizeof(Elf_Word) * 4 // Header
+ sizeof(Elf_Off) * MaskWords // Bloom Filter
+ sizeof(Elf_Word) * NBuckets // Hash Buckets
@@ -253,7 +253,7 @@ template <class ELFT>
void GnuHashTableSection<ELFT>::writeHeader(uint8_t *&Buf) {
auto *P = reinterpret_cast<Elf_Word *>(Buf);
*P++ = NBuckets;
- *P++ = Out<ELFT>::DynSymTab->getNumSymbols() - Symbols.size();
+ *P++ = In<ELFT>::DynSymTab->getNumSymbols() - Symbols.size();
*P++ = MaskWords;
*P++ = Shift2;
Buf = reinterpret_cast<uint8_t *>(P);
@@ -419,7 +419,7 @@ template <class ELFT> void OutputSection
if (Type != SHT_RELA && Type != SHT_REL)
return;
- this->Link = Out<ELFT>::SymTab->SectionIndex;
+ this->Link = In<ELFT>::SymTab->OutSec->SectionIndex;
// sh_info for SHT_REL[A] sections should contain the section header index of
// the section to which the relocation applies.
InputSectionBase<ELFT> *S = Sections[0]->getRelocatedSection();
@@ -819,188 +819,6 @@ template <class ELFT> void MergeOutputSe
}
template <class ELFT>
-SymbolTableSection<ELFT>::SymbolTableSection(
- StringTableSection<ELFT> &StrTabSec)
- : OutputSectionBase(StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
- StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
- StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
- StrTabSec(StrTabSec) {
- this->Entsize = sizeof(Elf_Sym);
- this->Addralign = sizeof(uintX_t);
-}
-
-// Orders symbols according to their positions in the GOT,
-// in compliance with MIPS ABI rules.
-// See "Global Offset Table" in Chapter 5 in the following document
-// for detailed description:
-// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-static bool sortMipsSymbols(const SymbolBody *L, const SymbolBody *R) {
- // Sort entries related to non-local preemptible symbols by GOT indexes.
- // All other entries go to the first part of GOT in arbitrary order.
- bool LIsInLocalGot = !L->IsInGlobalMipsGot;
- bool RIsInLocalGot = !R->IsInGlobalMipsGot;
- if (LIsInLocalGot || RIsInLocalGot)
- return !RIsInLocalGot;
- return L->GotIndex < R->GotIndex;
-}
-
-static uint8_t getSymbolBinding(SymbolBody *Body) {
- Symbol *S = Body->symbol();
- if (Config->Relocatable)
- return S->Binding;
- uint8_t Visibility = S->Visibility;
- if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
- return STB_LOCAL;
- if (Config->NoGnuUnique && S->Binding == STB_GNU_UNIQUE)
- return STB_GLOBAL;
- return S->Binding;
-}
-
-template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
- if (this->Size)
- return; // Already finalized.
-
- this->Size = getNumSymbols() * sizeof(Elf_Sym);
- this->Link = StrTabSec.OutSec->SectionIndex;
- this->Info = NumLocals + 1;
-
- if (Config->Relocatable) {
- size_t I = NumLocals;
- for (const SymbolTableEntry &S : Symbols)
- S.Symbol->DynsymIndex = ++I;
- return;
- }
-
- if (!StrTabSec.isDynamic()) {
- std::stable_sort(Symbols.begin(), Symbols.end(),
- [](const SymbolTableEntry &L, const SymbolTableEntry &R) {
- return getSymbolBinding(L.Symbol) == STB_LOCAL &&
- getSymbolBinding(R.Symbol) != STB_LOCAL;
- });
- return;
- }
- if (Out<ELFT>::GnuHashTab)
- // NB: It also sorts Symbols to meet the GNU hash table requirements.
- Out<ELFT>::GnuHashTab->addSymbols(Symbols);
- else if (Config->EMachine == EM_MIPS)
- std::stable_sort(Symbols.begin(), Symbols.end(),
- [](const SymbolTableEntry &L, const SymbolTableEntry &R) {
- return sortMipsSymbols(L.Symbol, R.Symbol);
- });
- size_t I = 0;
- for (const SymbolTableEntry &S : Symbols)
- S.Symbol->DynsymIndex = ++I;
-}
-
-template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) {
- Symbols.push_back({B, StrTabSec.addString(B->getName(), false)});
-}
-
-template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
- Buf += sizeof(Elf_Sym);
-
- // All symbols with STB_LOCAL binding precede the weak and global symbols.
- // .dynsym only contains global symbols.
- if (Config->Discard != DiscardPolicy::All && !StrTabSec.isDynamic())
- writeLocalSymbols(Buf);
-
- writeGlobalSymbols(Buf);
-}
-
-template <class ELFT>
-void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
- // Iterate over all input object files to copy their local symbols
- // to the output symbol table pointed by Buf.
- for (ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
- for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P :
- File->KeptLocalSyms) {
- const DefinedRegular<ELFT> &Body = *P.first;
- InputSectionBase<ELFT> *Section = Body.Section;
- auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
-
- if (!Section) {
- ESym->st_shndx = SHN_ABS;
- ESym->st_value = Body.Value;
- } else {
- const OutputSectionBase *OutSec = Section->OutSec;
- ESym->st_shndx = OutSec->SectionIndex;
- ESym->st_value = OutSec->Addr + Section->getOffset(Body);
- }
- ESym->st_name = P.second;
- ESym->st_size = Body.template getSize<ELFT>();
- ESym->setBindingAndType(STB_LOCAL, Body.Type);
- Buf += sizeof(*ESym);
- }
- }
-}
-
-template <class ELFT>
-void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
- // Write the internal symbol table contents to the output symbol table
- // pointed by Buf.
- auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
- for (const SymbolTableEntry &S : Symbols) {
- SymbolBody *Body = S.Symbol;
- size_t StrOff = S.StrTabOffset;
-
- uint8_t Type = Body->Type;
- uintX_t Size = Body->getSize<ELFT>();
-
- ESym->setBindingAndType(getSymbolBinding(Body), Type);
- ESym->st_size = Size;
- ESym->st_name = StrOff;
- ESym->setVisibility(Body->symbol()->Visibility);
- ESym->st_value = Body->getVA<ELFT>();
-
- if (const OutputSectionBase *OutSec = getOutputSection(Body))
- ESym->st_shndx = OutSec->SectionIndex;
- else if (isa<DefinedRegular<ELFT>>(Body))
- ESym->st_shndx = SHN_ABS;
-
- if (Config->EMachine == EM_MIPS) {
- // On MIPS we need to mark symbol which has a PLT entry and requires
- // pointer equality by STO_MIPS_PLT flag. That is necessary to help
- // dynamic linker distinguish such symbols and MIPS lazy-binding stubs.
- // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
- if (Body->isInPlt() && Body->NeedsCopyOrPltAddr)
- ESym->st_other |= STO_MIPS_PLT;
- if (Config->Relocatable) {
- auto *D = dyn_cast<DefinedRegular<ELFT>>(Body);
- if (D && D->isMipsPIC())
- ESym->st_other |= STO_MIPS_PIC;
- }
- }
- ++ESym;
- }
-}
-
-template <class ELFT>
-const OutputSectionBase *
-SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
- switch (Sym->kind()) {
- case SymbolBody::DefinedSyntheticKind:
- return cast<DefinedSynthetic<ELFT>>(Sym)->Section;
- case SymbolBody::DefinedRegularKind: {
- auto &D = cast<DefinedRegular<ELFT>>(*Sym);
- if (D.Section)
- return D.Section->OutSec;
- break;
- }
- case SymbolBody::DefinedCommonKind:
- return In<ELFT>::Common->OutSec;
- case SymbolBody::SharedKind:
- if (cast<SharedSymbol<ELFT>>(Sym)->needsCopy())
- return Out<ELFT>::Bss;
- break;
- case SymbolBody::UndefinedKind:
- case SymbolBody::LazyArchiveKind:
- case SymbolBody::LazyObjectKind:
- break;
- }
- return nullptr;
-}
-
-template <class ELFT>
VersionDefinitionSection<ELFT>::VersionDefinitionSection()
: OutputSectionBase(".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC) {
this->Addralign = sizeof(uint32_t);
@@ -1065,16 +883,16 @@ VersionTableSection<ELFT>::VersionTableS
template <class ELFT> void VersionTableSection<ELFT>::finalize() {
this->Size =
- sizeof(Elf_Versym) * (Out<ELFT>::DynSymTab->getSymbols().size() + 1);
+ 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 = Out<ELFT>::DynSymTab->SectionIndex;
+ 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 : Out<ELFT>::DynSymTab->getSymbols()) {
+ for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) {
OutVersym->vs_index = S.Symbol->symbol()->VersionId;
++OutVersym;
}
@@ -1293,11 +1111,6 @@ template class MergeOutputSection<ELF32B
template class MergeOutputSection<ELF64LE>;
template class MergeOutputSection<ELF64BE>;
-template class SymbolTableSection<ELF32LE>;
-template class SymbolTableSection<ELF32BE>;
-template class SymbolTableSection<ELF64LE>;
-template class SymbolTableSection<ELF64BE>;
-
template class VersionTableSection<ELF32LE>;
template class VersionTableSection<ELF32BE>;
template class VersionTableSection<ELF64LE>;
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Thu Nov 17 03:16:34 2016
@@ -52,7 +52,6 @@ public:
Merge,
Plt,
Regular,
- SymTable,
VersDef,
VersNeed,
VersTable
@@ -160,40 +159,6 @@ struct SymbolTableEntry {
size_t StrTabOffset;
};
-template <class ELFT>
-class SymbolTableSection final : public OutputSectionBase {
- typedef OutputSectionBase Base;
-
-public:
- typedef typename ELFT::Shdr Elf_Shdr;
- typedef typename ELFT::Sym Elf_Sym;
- typedef typename ELFT::SymRange Elf_Sym_Range;
- typedef typename ELFT::uint uintX_t;
- SymbolTableSection(StringTableSection<ELFT> &StrTabSec);
-
- void finalize() override;
- void writeTo(uint8_t *Buf) override;
- void addSymbol(SymbolBody *Body);
- StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
- unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; }
- typename Base::Kind getKind() const override { return Base::SymTable; }
- static bool classof(const Base *B) { return B->getKind() == Base::SymTable; }
-
- ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; }
-
- unsigned NumLocals = 0;
- StringTableSection<ELFT> &StrTabSec;
-
-private:
- void writeLocalSymbols(uint8_t *&Buf);
- void writeGlobalSymbols(uint8_t *Buf);
-
- const OutputSectionBase *getOutputSection(SymbolBody *Sym);
-
- // A vector of symbols and their string table offsets.
- std::vector<SymbolTableEntry> Symbols;
-};
-
// For more information about .gnu.version and .gnu.version_r see:
// https://www.akkadia.org/drepper/symbol-versioning
@@ -468,8 +433,6 @@ template <class ELFT> struct Out {
static OutputSectionBase *Opd;
static uint8_t *OpdBuf;
static PltSection<ELFT> *Plt;
- static SymbolTableSection<ELFT> *DynSymTab;
- static SymbolTableSection<ELFT> *SymTab;
static VersionDefinitionSection<ELFT> *VerDef;
static VersionTableSection<ELFT> *VerSym;
static VersionNeedSection<ELFT> *VerNeed;
@@ -526,8 +489,6 @@ template <class ELFT> OutputSection<ELFT
template <class ELFT> OutputSectionBase *Out<ELFT>::Opd;
template <class ELFT> uint8_t *Out<ELFT>::OpdBuf;
template <class ELFT> PltSection<ELFT> *Out<ELFT>::Plt;
-template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
-template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab;
template <class ELFT> VersionDefinitionSection<ELFT> *Out<ELFT>::VerDef;
template <class ELFT> VersionTableSection<ELFT> *Out<ELFT>::VerSym;
template <class ELFT> VersionNeedSection<ELFT> *Out<ELFT>::VerNeed;
Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Nov 17 03:16:34 2016
@@ -788,7 +788,7 @@ template <class ELFT> void DynamicSectio
add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)});
}
- add({DT_SYMTAB, Out<ELFT>::DynSymTab});
+ add({DT_SYMTAB, In<ELFT>::DynSymTab});
add({DT_SYMENT, sizeof(Elf_Sym)});
add({DT_STRTAB, In<ELFT>::DynStrTab});
add({DT_STRSZ, In<ELFT>::DynStrTab->getSize()});
@@ -831,12 +831,12 @@ template <class ELFT> void DynamicSectio
add({DT_MIPS_RLD_VERSION, 1});
add({DT_MIPS_FLAGS, RHF_NOTPOT});
add({DT_MIPS_BASE_ADDRESS, Config->ImageBase});
- add({DT_MIPS_SYMTABNO, Out<ELFT>::DynSymTab->getNumSymbols()});
+ add({DT_MIPS_SYMTABNO, In<ELFT>::DynSymTab->getNumSymbols()});
add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::MipsGot->getMipsLocalEntriesNum()});
if (const SymbolBody *B = In<ELFT>::MipsGot->getMipsFirstGlobalEntry())
add({DT_MIPS_GOTSYM, B->DynsymIndex});
else
- add({DT_MIPS_GOTSYM, Out<ELFT>::DynSymTab->getNumSymbols()});
+ add({DT_MIPS_GOTSYM, In<ELFT>::DynSymTab->getNumSymbols()});
add({DT_PLTGOT, In<ELFT>::MipsGot});
if (Out<ELFT>::MipsRldMap)
add({DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap});
@@ -953,14 +953,193 @@ template <class ELFT> unsigned Relocatio
}
template <class ELFT> void RelocationSection<ELFT>::finalize() {
- this->Link = Out<ELFT>::DynSymTab ? Out<ELFT>::DynSymTab->SectionIndex
- : Out<ELFT>::SymTab->SectionIndex;
+ this->Link = In<ELFT>::DynSymTab ? In<ELFT>::DynSymTab->OutSec->SectionIndex
+ : In<ELFT>::SymTab->OutSec->SectionIndex;
// Set required output section properties.
this->OutSec->Link = this->Link;
this->OutSec->Entsize = this->Entsize;
}
+template <class ELFT>
+SymbolTableSection<ELFT>::SymbolTableSection(
+ StringTableSection<ELFT> &StrTabSec)
+ : SyntheticSection<ELFT>(StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0,
+ StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
+ sizeof(uintX_t),
+ StrTabSec.isDynamic() ? ".dynsym" : ".symtab"),
+ StrTabSec(StrTabSec) {
+ this->Entsize = sizeof(Elf_Sym);
+}
+
+// Orders symbols according to their positions in the GOT,
+// in compliance with MIPS ABI rules.
+// See "Global Offset Table" in Chapter 5 in the following document
+// for detailed description:
+// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+static bool sortMipsSymbols(const SymbolBody *L, const SymbolBody *R) {
+ // Sort entries related to non-local preemptible symbols by GOT indexes.
+ // All other entries go to the first part of GOT in arbitrary order.
+ bool LIsInLocalGot = !L->IsInGlobalMipsGot;
+ bool RIsInLocalGot = !R->IsInGlobalMipsGot;
+ if (LIsInLocalGot || RIsInLocalGot)
+ return !RIsInLocalGot;
+ return L->GotIndex < R->GotIndex;
+}
+
+static uint8_t getSymbolBinding(SymbolBody *Body) {
+ Symbol *S = Body->symbol();
+ if (Config->Relocatable)
+ return S->Binding;
+ uint8_t Visibility = S->Visibility;
+ if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
+ return STB_LOCAL;
+ if (Config->NoGnuUnique && S->Binding == STB_GNU_UNIQUE)
+ return STB_GLOBAL;
+ return S->Binding;
+}
+
+template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
+ this->OutSec->Link = this->Link = StrTabSec.OutSec->SectionIndex;
+ this->OutSec->Info = this->Info = NumLocals + 1;
+ this->OutSec->Entsize = this->Entsize;
+
+ if (Config->Relocatable) {
+ size_t I = NumLocals;
+ for (const SymbolTableEntry &S : Symbols)
+ S.Symbol->DynsymIndex = ++I;
+ return;
+ }
+
+ if (!StrTabSec.isDynamic()) {
+ std::stable_sort(Symbols.begin(), Symbols.end(),
+ [](const SymbolTableEntry &L, const SymbolTableEntry &R) {
+ return getSymbolBinding(L.Symbol) == STB_LOCAL &&
+ getSymbolBinding(R.Symbol) != STB_LOCAL;
+ });
+ return;
+ }
+ if (Out<ELFT>::GnuHashTab)
+ // NB: It also sorts Symbols to meet the GNU hash table requirements.
+ Out<ELFT>::GnuHashTab->addSymbols(Symbols);
+ else if (Config->EMachine == EM_MIPS)
+ std::stable_sort(Symbols.begin(), Symbols.end(),
+ [](const SymbolTableEntry &L, const SymbolTableEntry &R) {
+ return sortMipsSymbols(L.Symbol, R.Symbol);
+ });
+ size_t I = 0;
+ for (const SymbolTableEntry &S : Symbols)
+ S.Symbol->DynsymIndex = ++I;
+}
+
+template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) {
+ Symbols.push_back({B, StrTabSec.addString(B->getName(), false)});
+}
+
+template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
+ Buf += sizeof(Elf_Sym);
+
+ // All symbols with STB_LOCAL binding precede the weak and global symbols.
+ // .dynsym only contains global symbols.
+ if (Config->Discard != DiscardPolicy::All && !StrTabSec.isDynamic())
+ writeLocalSymbols(Buf);
+
+ writeGlobalSymbols(Buf);
+}
+
+template <class ELFT>
+void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
+ // Iterate over all input object files to copy their local symbols
+ // to the output symbol table pointed by Buf.
+ for (ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
+ for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P :
+ File->KeptLocalSyms) {
+ const DefinedRegular<ELFT> &Body = *P.first;
+ InputSectionBase<ELFT> *Section = Body.Section;
+ auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
+
+ if (!Section) {
+ ESym->st_shndx = SHN_ABS;
+ ESym->st_value = Body.Value;
+ } else {
+ const OutputSectionBase *OutSec = Section->OutSec;
+ ESym->st_shndx = OutSec->SectionIndex;
+ ESym->st_value = OutSec->Addr + Section->getOffset(Body);
+ }
+ ESym->st_name = P.second;
+ ESym->st_size = Body.template getSize<ELFT>();
+ ESym->setBindingAndType(STB_LOCAL, Body.Type);
+ Buf += sizeof(*ESym);
+ }
+ }
+}
+
+template <class ELFT>
+void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
+ // Write the internal symbol table contents to the output symbol table
+ // pointed by Buf.
+ auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
+ for (const SymbolTableEntry &S : Symbols) {
+ SymbolBody *Body = S.Symbol;
+ size_t StrOff = S.StrTabOffset;
+
+ uint8_t Type = Body->Type;
+ uintX_t Size = Body->getSize<ELFT>();
+
+ ESym->setBindingAndType(getSymbolBinding(Body), Type);
+ ESym->st_size = Size;
+ ESym->st_name = StrOff;
+ ESym->setVisibility(Body->symbol()->Visibility);
+ ESym->st_value = Body->getVA<ELFT>();
+
+ if (const OutputSectionBase *OutSec = getOutputSection(Body))
+ ESym->st_shndx = OutSec->SectionIndex;
+ else if (isa<DefinedRegular<ELFT>>(Body))
+ ESym->st_shndx = SHN_ABS;
+
+ if (Config->EMachine == EM_MIPS) {
+ // On MIPS we need to mark symbol which has a PLT entry and requires
+ // pointer equality by STO_MIPS_PLT flag. That is necessary to help
+ // dynamic linker distinguish such symbols and MIPS lazy-binding stubs.
+ // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
+ if (Body->isInPlt() && Body->NeedsCopyOrPltAddr)
+ ESym->st_other |= STO_MIPS_PLT;
+ if (Config->Relocatable) {
+ auto *D = dyn_cast<DefinedRegular<ELFT>>(Body);
+ if (D && D->isMipsPIC())
+ ESym->st_other |= STO_MIPS_PIC;
+ }
+ }
+ ++ESym;
+ }
+}
+
+template <class ELFT>
+const OutputSectionBase *
+SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
+ switch (Sym->kind()) {
+ case SymbolBody::DefinedSyntheticKind:
+ return cast<DefinedSynthetic<ELFT>>(Sym)->Section;
+ case SymbolBody::DefinedRegularKind: {
+ auto &D = cast<DefinedRegular<ELFT>>(*Sym);
+ if (D.Section)
+ return D.Section->OutSec;
+ break;
+ }
+ case SymbolBody::DefinedCommonKind:
+ return In<ELFT>::Common->OutSec;
+ case SymbolBody::SharedKind:
+ if (cast<SharedSymbol<ELFT>>(Sym)->needsCopy())
+ return Out<ELFT>::Bss;
+ break;
+ case SymbolBody::UndefinedKind:
+ case SymbolBody::LazyArchiveKind:
+ case SymbolBody::LazyObjectKind:
+ break;
+ }
+ return nullptr;
+}
+
template InputSection<ELF32LE> *elf::createCommonSection();
template InputSection<ELF32BE> *elf::createCommonSection();
template InputSection<ELF64LE> *elf::createCommonSection();
@@ -1050,3 +1229,8 @@ template class elf::RelocationSection<EL
template class elf::RelocationSection<ELF32BE>;
template class elf::RelocationSection<ELF64LE>;
template class elf::RelocationSection<ELF64BE>;
+
+template class elf::SymbolTableSection<ELF32LE>;
+template class elf::SymbolTableSection<ELF32BE>;
+template class elf::SymbolTableSection<ELF64LE>;
+template class elf::SymbolTableSection<ELF64BE>;
Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Nov 17 03:16:34 2016
@@ -11,6 +11,7 @@
#define LLD_ELF_SYNTHETIC_SECTION_H
#include "InputSection.h"
+#include "OutputSections.h"
#include "llvm/ADT/SmallPtrSet.h"
namespace lld {
@@ -360,6 +361,37 @@ private:
std::vector<DynamicReloc<ELFT>> Relocs;
};
+template <class ELFT>
+class SymbolTableSection final : public SyntheticSection<ELFT> {
+public:
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::SymRange Elf_Sym_Range;
+ typedef typename ELFT::uint uintX_t;
+ SymbolTableSection(StringTableSection<ELFT> &StrTabSec);
+
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+ size_t getSize() const override { return getNumSymbols() * sizeof(Elf_Sym); }
+ void addSymbol(SymbolBody *Body);
+ StringTableSection<ELFT> &getStrTabSec() const { return StrTabSec; }
+ unsigned getNumSymbols() const { return NumLocals + Symbols.size() + 1; }
+
+ ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; }
+
+ unsigned NumLocals = 0;
+ StringTableSection<ELFT> &StrTabSec;
+
+private:
+ void writeLocalSymbols(uint8_t *&Buf);
+ void writeGlobalSymbols(uint8_t *Buf);
+
+ const OutputSectionBase *getOutputSection(SymbolBody *Sym);
+
+ // A vector of symbols and their string table offsets.
+ std::vector<SymbolTableEntry> Symbols;
+};
+
template <class ELFT> InputSection<ELFT> *createCommonSection();
template <class ELFT> InputSection<ELFT> *createInterpSection();
template <class ELFT> MergeInputSection<ELFT> *createCommentSection();
@@ -370,6 +402,7 @@ template <class ELFT> struct In {
static InputSection<ELFT> *Common;
static DynamicSection<ELFT> *Dynamic;
static StringTableSection<ELFT> *DynStrTab;
+ static SymbolTableSection<ELFT> *DynSymTab;
static GotSection<ELFT> *Got;
static MipsGotSection<ELFT> *MipsGot;
static GotPltSection<ELFT> *GotPlt;
@@ -381,12 +414,14 @@ template <class ELFT> struct In {
static RelocationSection<ELFT> *RelaPlt;
static StringTableSection<ELFT> *ShStrTab;
static StringTableSection<ELFT> *StrTab;
+ static SymbolTableSection<ELFT> *SymTab;
};
template <class ELFT> BuildIdSection<ELFT> *In<ELFT>::BuildId;
template <class ELFT> InputSection<ELFT> *In<ELFT>::Common;
template <class ELFT> DynamicSection<ELFT> *In<ELFT>::Dynamic;
template <class ELFT> StringTableSection<ELFT> *In<ELFT>::DynStrTab;
+template <class ELFT> SymbolTableSection<ELFT> *In<ELFT>::DynSymTab;
template <class ELFT> GotSection<ELFT> *In<ELFT>::Got;
template <class ELFT> MipsGotSection<ELFT> *In<ELFT>::MipsGot;
template <class ELFT> GotPltSection<ELFT> *In<ELFT>::GotPlt;
@@ -398,6 +433,7 @@ template <class ELFT> RelocationSection<
template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaPlt;
template <class ELFT> StringTableSection<ELFT> *In<ELFT>::ShStrTab;
template <class ELFT> StringTableSection<ELFT> *In<ELFT>::StrTab;
+template <class ELFT> SymbolTableSection<ELFT> *In<ELFT>::SymTab;
} // namespace elf
} // namespace lld
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=287216&r1=287215&r2=287216&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Nov 17 03:16:34 2016
@@ -232,7 +232,7 @@ template <class ELFT> void Writer<ELFT>:
}
if (!Symtab<ELFT>::X->getSharedFiles().empty() || Config->Pic) {
- Out<ELFT>::DynSymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::DynStrTab);
+ In<ELFT>::DynSymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::DynStrTab);
}
if (Config->EhFrameHdr)
@@ -249,7 +249,7 @@ template <class ELFT> void Writer<ELFT>:
Config->Rela ? ".rela.plt" : ".rel.plt", false /*Sort*/);
if (Config->Strip != StripPolicy::All) {
In<ELFT>::StrTab = make<StringTableSection<ELFT>>(".strtab", false);
- Out<ELFT>::SymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::StrTab);
+ In<ELFT>::SymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::StrTab);
}
if (Config->EMachine == EM_MIPS && !Config->Shared) {
@@ -372,7 +372,7 @@ template <class ELFT> static bool includ
// Local symbols are not in the linker's symbol table. This function scans
// each object file's symbol table to copy local symbols to the output.
template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
- if (!Out<ELFT>::SymTab)
+ if (!In<ELFT>::SymTab)
return;
for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
StringRef StrTab = F->getStringTable();
@@ -392,11 +392,11 @@ template <class ELFT> void Writer<ELFT>:
InputSectionBase<ELFT> *Sec = DR->Section;
if (!shouldKeepInSymtab<ELFT>(Sec, SymName, *B))
continue;
- ++Out<ELFT>::SymTab->NumLocals;
+ ++In<ELFT>::SymTab->NumLocals;
if (Config->Relocatable)
- B->DynsymIndex = Out<ELFT>::SymTab->NumLocals;
+ B->DynsymIndex = In<ELFT>::SymTab->NumLocals;
F->KeptLocalSyms.push_back(
- std::make_pair(DR, Out<ELFT>::SymTab->StrTabSec.addString(SymName)));
+ std::make_pair(DR, In<ELFT>::SymTab->StrTabSec.addString(SymName)));
}
}
}
@@ -594,7 +594,7 @@ static Symbol *addOptionalRegular(String
// need these symbols, since IRELATIVE relocs are resolved through GOT
// and PLT. For details, see http://www.airs.com/blog/archives/403.
template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
- if (Out<ELFT>::DynSymTab)
+ if (In<ELFT>::DynSymTab)
return;
StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";
addOptionalRegular<ELFT>(S, In<ELFT>::RelaPlt, 0);
@@ -647,7 +647,7 @@ template <class ELFT> void Writer<ELFT>:
// to avoid the undefined symbol error. As usual special cases are ARM and
// MIPS - the libc for these targets defines __tls_get_addr itself because
// there are no TLS optimizations for these targets.
- if (!Out<ELFT>::DynSymTab &&
+ if (!In<ELFT>::DynSymTab &&
(Config->EMachine != EM_MIPS && Config->EMachine != EM_ARM))
Symtab<ELFT>::X->addIgnored("__tls_get_addr");
@@ -893,7 +893,7 @@ template <class ELFT> void Writer<ELFT>:
// It should be okay as no one seems to care about the type.
// Even the author of gold doesn't remember why gold behaves that way.
// https://sourceware.org/ml/binutils/2002-03/msg00360.html
- if (Out<ELFT>::DynSymTab)
+ if (In<ELFT>::DynSymTab)
addRegular("_DYNAMIC", In<ELFT>::Dynamic, 0);
// Define __rel[a]_iplt_{start,end} symbols if needed.
@@ -915,11 +915,11 @@ template <class ELFT> void Writer<ELFT>:
if (!includeInSymtab<ELFT>(*Body))
continue;
- if (Out<ELFT>::SymTab)
- Out<ELFT>::SymTab->addSymbol(Body);
+ if (In<ELFT>::SymTab)
+ In<ELFT>::SymTab->addSymbol(Body);
- if (Out<ELFT>::DynSymTab && S->includeInDynsym()) {
- Out<ELFT>::DynSymTab->addSymbol(Body);
+ if (In<ELFT>::DynSymTab && S->includeInDynsym()) {
+ In<ELFT>::DynSymTab->addSymbol(Body);
if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
if (SS->file()->isNeeded())
Out<ELFT>::VerNeed->addSymbol(SS);
@@ -942,10 +942,11 @@ template <class ELFT> void Writer<ELFT>:
Sec->ShName = In<ELFT>::ShStrTab->addString(Sec->getName());
}
+ // FIXME: this should be removed after converting GnuHashTableSection
+ // to input section.
// Finalizers fix each section's size.
// .dynsym is finalized early since that may fill up .gnu.hash.
- if (Out<ELFT>::DynSymTab)
- Out<ELFT>::DynSymTab->finalize();
+ finalizeSynthetic<ELFT>({In<ELFT>::DynSymTab});
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
@@ -955,9 +956,9 @@ template <class ELFT> void Writer<ELFT>:
// Dynamic section must be the last one in this list.
finalizeSynthetic<ELFT>(
- {In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::DynStrTab, In<ELFT>::Got,
- In<ELFT>::MipsGot, In<ELFT>::GotPlt, In<ELFT>::RelaDyn,
- In<ELFT>::RelaPlt, In<ELFT>::Dynamic});
+ {In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab,
+ In<ELFT>::DynStrTab, In<ELFT>::Got, In<ELFT>::MipsGot, In<ELFT>::GotPlt,
+ In<ELFT>::RelaDyn, In<ELFT>::RelaPlt, In<ELFT>::Dynamic});
// Now that all output offsets are fixed. Finalize mergeable sections
// to fix their maps from input offsets to output offsets.
@@ -990,11 +991,11 @@ template <class ELFT> void Writer<ELFT>:
// because we sort the sections using their attributes below.
if (Out<ELFT>::GdbIndex && Out<ELFT>::DebugInfo)
Add(Out<ELFT>::GdbIndex);
- Add(Out<ELFT>::SymTab);
+ addInputSec(In<ELFT>::SymTab);
addInputSec(In<ELFT>::ShStrTab);
addInputSec(In<ELFT>::StrTab);
- if (Out<ELFT>::DynSymTab) {
- Add(Out<ELFT>::DynSymTab);
+ if (In<ELFT>::DynSymTab) {
+ addInputSec(In<ELFT>::DynSymTab);
bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
if (Out<ELFT>::VerDef || HasVerNeed)
@@ -1172,7 +1173,7 @@ template <class ELFT> std::vector<PhdrEn
Ret.push_back(std::move(TlsHdr));
// Add an entry for .dynamic.
- if (Out<ELFT>::DynSymTab) {
+ if (In<ELFT>::DynSymTab) {
Phdr &H = *AddHdr(PT_DYNAMIC, In<ELFT>::Dynamic->OutSec->getPhdrFlags());
H.add(In<ELFT>::Dynamic->OutSec);
}
More information about the llvm-commits
mailing list