[lld] r314495 - [ELF] Simpler scheme for handling common symbols

Ben Dunbobbin via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 29 02:08:26 PDT 2017


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;
 }
 




More information about the llvm-commits mailing list