[lld] r314495 - [ELF] Simpler scheme for handling common symbols
Rafael Avila de Espindola via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 12 12:33:37 PDT 2017
This is awesome. Thanks!
Cheers,
Rafael
Ben Dunbobbin via llvm-commits <llvm-commits at lists.llvm.org> writes:
> Author: bd1976llvm
> Date: Fri Sep 29 02:08:26 2017
> New Revision: 314495
>
> URL: http://llvm.org/viewvc/llvm-project?rev=314495&view=rev
> Log:
> [ELF] Simpler scheme for handling common symbols
>
> Convert all common symbols to regular symbols after scan.
> This means that the downstream code does not to handle common symbols as a special case.
>
> Differential Revision: https://reviews.llvm.org/D38137
>
> Added:
> lld/trunk/ELF/SyntheticSections.cpp~RF2791d30b.TMP
> - copied, changed from r314440, lld/trunk/ELF/SyntheticSections.cpp
> Modified:
> lld/trunk/ELF/Driver.cpp
> lld/trunk/ELF/MarkLive.cpp
> lld/trunk/ELF/Symbols.cpp
> lld/trunk/ELF/Symbols.h
> lld/trunk/ELF/SyntheticSections.cpp
> lld/trunk/ELF/SyntheticSections.h
> lld/trunk/ELF/Writer.cpp
>
> Modified: lld/trunk/ELF/Driver.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=314495&r1=314494&r2=314495&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Driver.cpp (original)
> +++ lld/trunk/ELF/Driver.cpp Fri Sep 29 02:08:26 2017
> @@ -1086,6 +1086,14 @@ template <class ELFT> void LinkerDriver:
> if (!Config->Relocatable)
> InputSections.push_back(createCommentSection<ELFT>());
>
> + // Create a .bss section for each common symbol and then replace the common
> + // symbol with a DefinedRegular symbol. As a result, all common symbols are
> + // "instantiated" as regular defined symbols, so that we don't need to care
> + // about common symbols beyond this point. Note that if -r is given, we just
> + // need to pass through common symbols as-is.
> + if (Config->DefineCommon)
> + createCommonSections<ELFT>();
> +
> // Do size optimizations: garbage collection, merging of SHF_MERGE sections
> // and identical code folding.
> if (Config->GcSections)
>
> Modified: lld/trunk/ELF/MarkLive.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=314495&r1=314494&r2=314495&view=diff
> ==============================================================================
> --- lld/trunk/ELF/MarkLive.cpp (original)
> +++ lld/trunk/ELF/MarkLive.cpp Fri Sep 29 02:08:26 2017
> @@ -64,11 +64,6 @@ static void resolveReloc(InputSectionBas
> std::function<void(InputSectionBase *, uint64_t)> Fn) {
> SymbolBody &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel);
>
> - if (auto *Sym = dyn_cast<DefinedCommon>(&B)) {
> - Sym->Live = true;
> - return;
> - }
> -
> if (auto *D = dyn_cast<DefinedRegular>(&B)) {
> if (!D->Section)
> return;
> @@ -223,13 +218,9 @@ template <class ELFT> void elf::markLive
> };
>
> auto MarkSymbol = [&](SymbolBody *Sym) {
> - if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym)) {
> + if (auto *D = dyn_cast_or_null<DefinedRegular>(Sym))
> if (auto *IS = cast_or_null<InputSectionBase>(D->Section))
> Enqueue(IS, D->Value);
> - return;
> - }
> - if (auto *S = dyn_cast_or_null<DefinedCommon>(Sym))
> - S->Live = true;
> };
>
> // Add GC root symbols.
>
> Modified: lld/trunk/ELF/Symbols.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=314495&r1=314494&r2=314495&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Symbols.cpp (original)
> +++ lld/trunk/ELF/Symbols.cpp Fri Sep 29 02:08:26 2017
> @@ -99,14 +99,8 @@ static uint64_t getSymVA(const SymbolBod
> }
> return VA;
> }
> - case SymbolBody::DefinedCommonKind: {
> - if (!Config->DefineCommon)
> - return 0;
> - auto DC = cast<DefinedCommon>(Body);
> - if (!DC.Live)
> - return 0;
> - return DC.Section->getParent()->Addr + DC.Section->OutSecOff;
> - }
> + case SymbolBody::DefinedCommonKind:
> + llvm_unreachable("common are converted to bss");
> case SymbolBody::SharedKind: {
> auto &SS = cast<SharedSymbol>(Body);
> if (SS.CopyRelSec)
> @@ -286,7 +280,7 @@ DefinedCommon::DefinedCommon(StringRef N
> uint8_t StOther, uint8_t Type)
> : Defined(SymbolBody::DefinedCommonKind, Name, /*IsLocal=*/false, StOther,
> Type),
> - Live(!Config->GcSections), Alignment(Alignment), Size(Size) {}
> + Alignment(Alignment), Size(Size) {}
>
> // If a shared symbol is referred via a copy relocation, its alignment
> // becomes part of the ABI. This function returns a symbol alignment.
>
> Modified: lld/trunk/ELF/Symbols.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=314495&r1=314494&r2=314495&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Symbols.h (original)
> +++ lld/trunk/ELF/Symbols.h Fri Sep 29 02:08:26 2017
> @@ -167,11 +167,6 @@ public:
> return S->kind() == SymbolBody::DefinedCommonKind;
> }
>
> - // True if this symbol is not GC'ed. Liveness is usually a notion of
> - // input sections and not of symbols, but since common symbols don't
> - // belong to any input section, their liveness is managed by this bit.
> - bool Live;
> -
> // The maximum alignment we have seen for this symbol.
> uint32_t Alignment;
>
>
> Modified: lld/trunk/ELF/SyntheticSections.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=314495&r1=314494&r2=314495&view=diff
> ==============================================================================
> --- lld/trunk/ELF/SyntheticSections.cpp (original)
> +++ lld/trunk/ELF/SyntheticSections.cpp Fri Sep 29 02:08:26 2017
> @@ -54,24 +54,28 @@ uint64_t SyntheticSection::getVA() const
> return 0;
> }
>
> -std::vector<InputSection *> elf::createCommonSections() {
> - if (!Config->DefineCommon)
> - return {};
> -
> - std::vector<InputSection *> Ret;
> +// Create a .bss section for each common section and replace the common symbol
> +// with a DefinedRegular symbol.
> +template <class ELFT> void elf::createCommonSections() {
> for (Symbol *S : Symtab->getSymbols()) {
> auto *Sym = dyn_cast<DefinedCommon>(S->body());
> - if (!Sym || !Sym->Live)
> +
> + if (!Sym)
> continue;
>
> - Sym->Section = make<BssSection>("COMMON");
> - size_t Pos = Sym->Section->reserveSpace(Sym->Size, Sym->Alignment);
> - assert(Pos == 0);
> - (void)Pos;
> - Sym->Section->File = Sym->getFile();
> - Ret.push_back(Sym->Section);
> + // Create a synthetic section for the common data.
> + auto *Section = make<BssSection>("COMMON");
> + Section->File = Sym->getFile();
> + Section->Live = !Config->GcSections;
> + Section->reserveSpace(Sym->Size, Sym->Alignment);
> + InputSections.push_back(Section);
> +
> + // Replace all DefinedCommon symbols with DefinedRegular symbols so that we
> + // don't have to care about DefinedCommon symbols beyond this point.
> + replaceBody<DefinedRegular>(S, Sym->getFile(), Sym->getName(),
> + static_cast<bool>(Sym->IsLocal), Sym->StOther,
> + Sym->Type, 0, Sym->getSize<ELFT>(), Section);
> }
> - return Ret;
> }
>
> // Returns an LLD version string.
> @@ -2378,6 +2382,11 @@ template void PltSection::addEntry<ELF32
> template void PltSection::addEntry<ELF64LE>(SymbolBody &Sym);
> template void PltSection::addEntry<ELF64BE>(SymbolBody &Sym);
>
> +template void elf::createCommonSections<ELF32LE>();
> +template void elf::createCommonSections<ELF32BE>();
> +template void elf::createCommonSections<ELF64LE>();
> +template void elf::createCommonSections<ELF64BE>();
> +
> template MergeInputSection *elf::createCommentSection<ELF32LE>();
> template MergeInputSection *elf::createCommentSection<ELF32BE>();
> template MergeInputSection *elf::createCommentSection<ELF64LE>();
>
> Copied: lld/trunk/ELF/SyntheticSections.cpp~RF2791d30b.TMP (from r314440, lld/trunk/ELF/SyntheticSections.cpp)
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp%7ERF2791d30b.TMP?p2=lld/trunk/ELF/SyntheticSections.cpp%7ERF2791d30b.TMP&p1=lld/trunk/ELF/SyntheticSections.cpp&r1=314440&r2=314495&rev=314495&view=diff
> ==============================================================================
> --- lld/trunk/ELF/SyntheticSections.cpp (original)
> +++ lld/trunk/ELF/SyntheticSections.cpp~RF2791d30b.TMP Fri Sep 29 02:08:26 2017
> @@ -54,24 +54,28 @@ uint64_t SyntheticSection::getVA() const
> return 0;
> }
>
> -std::vector<InputSection *> elf::createCommonSections() {
> - if (!Config->DefineCommon)
> - return {};
> -
> - std::vector<InputSection *> Ret;
> +// Create a .bss section for each common section and replace the common symbol
> +// with a DefinedRegular symbol.
> +template <class ELFT> void elf::createCommonSections() {
> for (Symbol *S : Symtab->getSymbols()) {
> auto *Sym = dyn_cast<DefinedCommon>(S->body());
> - if (!Sym || !Sym->Live)
> +
> + if (!Sym)
> continue;
>
> - Sym->Section = make<BssSection>("COMMON");
> - size_t Pos = Sym->Section->reserveSpace(Sym->Size, Sym->Alignment);
> - assert(Pos == 0);
> - (void)Pos;
> - Sym->Section->File = Sym->getFile();
> - Ret.push_back(Sym->Section);
> + // Create a synthetic section for the common data.
> + auto *Section = make<BssSection>("COMMON");
> + Section->File = Sym->getFile();
> + Section->Live = !Config->GcSections;
> + Section->reserveSpace(Sym->Size, Sym->Alignment);
> + InputSections.push_back(Section);
> +
> + // Replace all DefinedCommon symbols with DefinedRegular symbols so that we
> + // don't have to care about DefinedCommon symbols beyond this point.
> + replaceBody<DefinedRegular>(S, Sym->getFile(), Sym->getName(), Sym->IsLocal,
> + Sym->StOther, Sym->Type, 0,
> + Sym->getSize<ELFT>(), Section);
> }
> - return Ret;
> }
>
> // Returns an LLD version string.
> @@ -1119,8 +1123,8 @@ template <class ELFT> void DynamicSectio
> add({DT_TEXTREL, (uint64_t)0});
> if (InX::GnuHashTab)
> add({DT_GNU_HASH, InX::GnuHashTab});
> - if (InX::HashTab)
> - add({DT_HASH, InX::HashTab});
> + if (In<ELFT>::HashTab)
> + add({DT_HASH, In<ELFT>::HashTab});
>
> if (Out::PreinitArray) {
> add({DT_PREINIT_ARRAY, Out::PreinitArray});
> @@ -1355,24 +1359,18 @@ void SymbolTableBaseSection::addSymbol(S
> }
>
> size_t SymbolTableBaseSection::getSymbolIndex(SymbolBody *Body) {
> - // Initializes symbol lookup tables lazily. This is used only
> - // for -r or -emit-relocs.
> - llvm::call_once(OnceFlag, [&] {
> - SymbolIndexMap.reserve(Symbols.size());
> - size_t I = 0;
> - for (const SymbolTableEntry &E : Symbols) {
> - if (E.Symbol->Type == STT_SECTION)
> - SectionIndexMap[E.Symbol->getOutputSection()] = ++I;
> - else
> - SymbolIndexMap[E.Symbol] = ++I;
> - }
> + auto I = llvm::find_if(Symbols, [&](const SymbolTableEntry &E) {
> + if (E.Symbol == Body)
> + return true;
> + // This is used for -r, so we have to handle multiple section
> + // symbols being combined.
> + if (Body->Type == STT_SECTION && E.Symbol->Type == STT_SECTION)
> + return Body->getOutputSection() == E.Symbol->getOutputSection();
> + return false;
> });
> -
> - // Section symbols are mapped based on their output sections
> - // to maintain their semantics.
> - if (Body->Type == STT_SECTION)
> - return SectionIndexMap.lookup(Body->getOutputSection());
> - return SymbolIndexMap.lookup(Body);
> + if (I == Symbols.end())
> + return 0;
> + return I - Symbols.begin() + 1;
> }
>
> template <class ELFT>
> @@ -1612,12 +1610,13 @@ void GnuHashTableSection::addSymbols(std
> V.push_back({Ent.Body, Ent.StrTabOffset});
> }
>
> -HashTableSection::HashTableSection()
> +template <class ELFT>
> +HashTableSection<ELFT>::HashTableSection()
> : SyntheticSection(SHF_ALLOC, SHT_HASH, 4, ".hash") {
> this->Entsize = 4;
> }
>
> -void HashTableSection::finalizeContents() {
> +template <class ELFT> void HashTableSection<ELFT>::finalizeContents() {
> getParent()->Link = InX::DynSymTab->getParent()->SectionIndex;
>
> unsigned NumEntries = 2; // nbucket and nchain.
> @@ -1630,15 +1629,18 @@ void HashTableSection::finalizeContents(
> this->Size = NumEntries * 4;
> }
>
> -void HashTableSection::writeTo(uint8_t *Buf) {
> +template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
> + // A 32-bit integer type in the target endianness.
> + typedef typename ELFT::Word Elf_Word;
> +
> unsigned NumSymbols = InX::DynSymTab->getNumSymbols();
>
> - uint32_t *P = reinterpret_cast<uint32_t *>(Buf);
> - write32(P++, NumSymbols, Config->Endianness); // nbucket
> - write32(P++, NumSymbols, Config->Endianness); // nchain
> + auto *P = reinterpret_cast<Elf_Word *>(Buf);
> + *P++ = NumSymbols; // nbucket
> + *P++ = NumSymbols; // nchain
>
> - uint32_t *Buckets = P;
> - uint32_t *Chains = P + NumSymbols;
> + Elf_Word *Buckets = P;
> + Elf_Word *Chains = P + NumSymbols;
>
> for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) {
> SymbolBody *Body = S.Symbol;
> @@ -1646,7 +1648,7 @@ void HashTableSection::writeTo(uint8_t *
> unsigned I = Body->DynsymIndex;
> uint32_t Hash = hashSysV(Name) % NumSymbols;
> Chains[I] = Buckets[Hash];
> - write32(Buckets + Hash, I, Config->Endianness);
> + Buckets[Hash] = I;
> }
> }
>
> @@ -2187,11 +2189,13 @@ void MergeSyntheticSection::addSection(M
> Sections.push_back(MS);
> }
>
> -size_t MergeSyntheticSection::getSize() const { return Builder.getSize(); }
> -
> void MergeSyntheticSection::writeTo(uint8_t *Buf) { Builder.write(Buf); }
>
> -void MergeTailSection::finalizeContents() {
> +bool MergeSyntheticSection::shouldTailMerge() const {
> + return (this->Flags & SHF_STRINGS) && Config->Optimize >= 2;
> +}
> +
> +void MergeSyntheticSection::finalizeTailMerge() {
> // Add all string pieces to the string table builder to create section
> // contents.
> for (MergeInputSection *Sec : Sections)
> @@ -2211,7 +2215,7 @@ void MergeTailSection::finalizeContents(
> Sec->Pieces[I].OutputOff = Builder.getOffset(Sec->getData(I));
> }
>
> -void MergeNoTailSection::finalizeContents() {
> +void MergeSyntheticSection::finalizeNoTailMerge() {
> // Add all string pieces to the string table builder to create section
> // contents. Because we are not tail-optimizing, offsets of strings are
> // fixed when they are added to the builder (string table builder contains
> @@ -2224,16 +2228,15 @@ void MergeNoTailSection::finalizeContent
> Builder.finalizeInOrder();
> }
>
> -static MergeSyntheticSection *createMergeSynthetic(StringRef Name,
> - uint32_t Type,
> - uint64_t Flags,
> - uint32_t Alignment) {
> - bool ShouldTailMerge = (Flags & SHF_STRINGS) && Config->Optimize >= 2;
> - if (ShouldTailMerge)
> - return make<MergeTailSection>(Name, Type, Flags, Alignment);
> - return make<MergeNoTailSection>(Name, Type, Flags, Alignment);
> +void MergeSyntheticSection::finalizeContents() {
> + if (shouldTailMerge())
> + finalizeTailMerge();
> + else
> + finalizeNoTailMerge();
> }
>
> +size_t MergeSyntheticSection::getSize() const { return Builder.getSize(); }
> +
> // This function decompresses compressed sections and scans over the input
> // sections to create mergeable synthetic sections. It removes
> // MergeInputSections from the input section array and adds new synthetic
> @@ -2271,8 +2274,8 @@ void elf::decompressAndMergeSections() {
> Sec->Alignment == Alignment;
> });
> if (I == MergeSections.end()) {
> - MergeSyntheticSection *Syn =
> - createMergeSynthetic(OutsecName, MS->Type, MS->Flags, Alignment);
> + MergeSyntheticSection *Syn = make<MergeSyntheticSection>(
> + OutsecName, MS->Type, MS->Flags, Alignment);
> MergeSections.push_back(Syn);
> I = std::prev(MergeSections.end());
> S = Syn;
> @@ -2358,7 +2361,6 @@ GdbIndexSection *InX::GdbIndex;
> GotSection *InX::Got;
> GotPltSection *InX::GotPlt;
> GnuHashTableSection *InX::GnuHashTab;
> -HashTableSection *InX::HashTab;
> IgotPltSection *InX::IgotPlt;
> MipsGotSection *InX::MipsGot;
> MipsRldMapSection *InX::MipsRldMap;
> @@ -2378,6 +2380,11 @@ template void PltSection::addEntry<ELF32
> template void PltSection::addEntry<ELF64LE>(SymbolBody &Sym);
> template void PltSection::addEntry<ELF64BE>(SymbolBody &Sym);
>
> +template void elf::createCommonSections<ELF32LE>();
> +template void elf::createCommonSections<ELF32BE>();
> +template void elf::createCommonSections<ELF64LE>();
> +template void elf::createCommonSections<ELF64BE>();
> +
> template MergeInputSection *elf::createCommentSection<ELF32LE>();
> template MergeInputSection *elf::createCommentSection<ELF32BE>();
> template MergeInputSection *elf::createCommentSection<ELF64LE>();
> @@ -2413,6 +2420,11 @@ template class elf::SymbolTableSection<E
> template class elf::SymbolTableSection<ELF64LE>;
> template class elf::SymbolTableSection<ELF64BE>;
>
> +template class elf::HashTableSection<ELF32LE>;
> +template class elf::HashTableSection<ELF32BE>;
> +template class elf::HashTableSection<ELF64LE>;
> +template class elf::HashTableSection<ELF64BE>;
> +
> template class elf::EhFrameHeader<ELF32LE>;
> template class elf::EhFrameHeader<ELF32BE>;
> template class elf::EhFrameHeader<ELF64LE>;
>
> Modified: lld/trunk/ELF/SyntheticSections.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=314495&r1=314494&r2=314495&view=diff
> ==============================================================================
> --- lld/trunk/ELF/SyntheticSections.h (original)
> +++ lld/trunk/ELF/SyntheticSections.h Fri Sep 29 02:08:26 2017
> @@ -786,7 +786,7 @@ private:
> size_t Size = 0;
> };
>
> -std::vector<InputSection *> createCommonSections();
> +template <class ELFT> void createCommonSections();
> InputSection *createInterpSection();
> template <class ELFT> MergeInputSection *createCommentSection();
> void decompressAndMergeSections();
>
> Modified: lld/trunk/ELF/Writer.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=314495&r1=314494&r2=314495&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Writer.cpp (original)
> +++ lld/trunk/ELF/Writer.cpp Fri Sep 29 02:08:26 2017
> @@ -290,9 +290,6 @@ template <class ELFT> void Writer<ELFT>:
> Add(InX::BuildId);
> }
>
> - for (InputSection *S : createCommonSections())
> - Add(S);
> -
> InX::Bss = make<BssSection>(".bss");
> Add(InX::Bss);
> InX::BssRelRo = make<BssSection>(".bss.rel.ro");
> @@ -441,11 +438,7 @@ static bool includeInSymtab(const Symbol
> if (auto *S = dyn_cast<MergeInputSection>(Sec))
> if (!S->getSectionPiece(D->Value)->Live)
> return false;
> - return true;
> }
> -
> - if (auto *Sym = dyn_cast<DefinedCommon>(&B))
> - return Sym->Live;
> return true;
> }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list