[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