[lld] r330966 - Replace SharedSymbols with Defined when creating copy relocations.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 26 10:58:58 PDT 2018


Author: rafael
Date: Thu Apr 26 10:58:58 2018
New Revision: 330966

URL: http://llvm.org/viewvc/llvm-project?rev=330966&view=rev
Log:
Replace SharedSymbols with Defined when creating copy relocations.

This is slightly simpler to read IMHO. Now if a symbol has a position
in the file, it is Defined.

The main motivation is that with this a SharedSymbol doesn't need a
section, which reduces the size of SymbolUnion.

With this the peak allocation when linking chromium goes from 568.1 to
564.2 MB.

Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/MapFile.cpp
    lld/trunk/ELF/Relocations.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
    lld/trunk/test/ELF/map-file.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=330966&r1=330965&r2=330966&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Apr 26 10:58:58 2018
@@ -1111,8 +1111,8 @@ ExprValue LinkerScript::getSymbolValue(S
     if (auto *DS = dyn_cast<Defined>(Sym))
       return {DS->Section, false, DS->Value, Loc};
     if (auto *SS = dyn_cast<SharedSymbol>(Sym))
-      if (!ErrorOnMissingSection || SS->CopyRelSec)
-        return {SS->CopyRelSec, false, 0, Loc};
+      if (!ErrorOnMissingSection)
+        return {nullptr, false, 0, Loc};
   }
 
   error(Loc + ": symbol not found: " + Name);

Modified: lld/trunk/ELF/MapFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MapFile.cpp?rev=330966&r1=330965&r2=330966&view=diff
==============================================================================
--- lld/trunk/ELF/MapFile.cpp (original)
+++ lld/trunk/ELF/MapFile.cpp Thu Apr 26 10:58:58 2018
@@ -38,7 +38,7 @@ using namespace llvm::object;
 using namespace lld;
 using namespace lld::elf;
 
-typedef DenseMap<const SectionBase *, SmallVector<Symbol *, 4>> SymbolMapTy;
+typedef DenseMap<const SectionBase *, SmallVector<Defined *, 4>> SymbolMapTy;
 
 static const std::string Indent8 = "        ";          // 8 spaces
 static const std::string Indent16 = "                "; // 16 spaces
@@ -53,44 +53,29 @@ static void writeHeader(raw_ostream &OS,
 }
 
 // Returns a list of all symbols that we want to print out.
-static std::vector<Symbol *> getSymbols() {
-  std::vector<Symbol *> V;
-  for (InputFile *File : ObjectFiles) {
-    for (Symbol *B : File->getSymbols()) {
-      if (auto *SS = dyn_cast<SharedSymbol>(B))
-        if (SS->CopyRelSec || SS->NeedsPltAddr)
-          V.push_back(SS);
+static std::vector<Defined *> getSymbols() {
+  std::vector<Defined *> V;
+  for (InputFile *File : ObjectFiles)
+    for (Symbol *B : File->getSymbols())
       if (auto *DR = dyn_cast<Defined>(B))
-        if (DR->File == File && !DR->isSection() && DR->Section &&
-            DR->Section->Live)
+        if (!DR->isSection() && DR->Section && DR->Section->Live &&
+            (DR->File == File || DR->NeedsPltAddr || DR->Section->Bss))
           V.push_back(DR);
-    }
-  }
   return V;
 }
 
 // Returns a map from sections to their symbols.
-static SymbolMapTy getSectionSyms(ArrayRef<Symbol *> Syms) {
+static SymbolMapTy getSectionSyms(ArrayRef<Defined *> Syms) {
   SymbolMapTy Ret;
-  for (Symbol *S : Syms) {
-    if (auto *DR = dyn_cast<Defined>(S)) {
-      Ret[DR->Section].push_back(S);
-      continue;
-    }
-
-    SharedSymbol *SS = cast<SharedSymbol>(S);
-    if (SS->CopyRelSec)
-      Ret[SS->CopyRelSec].push_back(S);
-    else
-      Ret[InX::Plt].push_back(S);
-  }
+  for (Defined *DR : Syms)
+    Ret[DR->Section].push_back(DR);
 
   // Sort symbols by address. We want to print out symbols in the
   // order in the output file rather than the order they appeared
   // in the input files.
   for (auto &It : Ret) {
-    SmallVectorImpl<Symbol *> &V = It.second;
-    std::stable_sort(V.begin(), V.end(), [](Symbol *A, Symbol *B) {
+    SmallVectorImpl<Defined *> &V = It.second;
+    std::stable_sort(V.begin(), V.end(), [](Defined *A, Defined *B) {
       return A->getVA() < B->getVA();
     });
   }
@@ -101,7 +86,7 @@ static SymbolMapTy getSectionSyms(ArrayR
 // Demangling symbols (which is what toString() does) is slow, so
 // we do that in batch using parallel-for.
 static DenseMap<Symbol *, std::string>
-getSymbolStrings(ArrayRef<Symbol *> Syms) {
+getSymbolStrings(ArrayRef<Defined *> Syms) {
   std::vector<std::string> Str(Syms.size());
   parallelForEachN(0, Syms.size(), [&](size_t I) {
     raw_string_ostream OS(Str[I]);
@@ -169,7 +154,7 @@ void elf::writeMapFile() {
   }
 
   // Collect symbol info that we want to print out.
-  std::vector<Symbol *> Syms = getSymbols();
+  std::vector<Defined *> Syms = getSymbols();
   SymbolMapTy SectionSyms = getSectionSyms(Syms);
   DenseMap<Symbol *, std::string> SymStr = getSymbolStrings(Syms);
 

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=330966&r1=330965&r2=330966&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Thu Apr 26 10:58:58 2018
@@ -461,6 +461,21 @@ static std::vector<SharedSymbol *> getSy
   return Ret;
 }
 
+static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value,
+                               uint64_t Size) {
+  Symbol Old = Sym;
+  replaceSymbol<Defined>(&Sym, Sym.File, Sym.getName(), Sym.Binding,
+                         Sym.StOther, Sym.Type, Value, Size, Sec);
+  Sym.PltIndex = Old.PltIndex;
+  Sym.GotIndex = Old.GotIndex;
+  Sym.VerdefIndex = Old.VerdefIndex;
+  Sym.IsInGlobalMipsGot = Old.IsInGlobalMipsGot;
+  Sym.IsPreemptible = true;
+  Sym.ExportDynamic = true;
+  Sym.IsUsedInRegularObj = true;
+  Sym.Used = true;
+}
+
 // Reserve space in .bss or .bss.rel.ro for copy relocation.
 //
 // The copy relocation is pretty much a hack. If you use a copy relocation
@@ -522,11 +537,8 @@ template <class ELFT> static void addCop
   // Look through the DSO's dynamic symbol table for aliases and create a
   // dynamic symbol for each one. This causes the copy relocation to correctly
   // interpose any aliases.
-  for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) {
-    Sym->CopyRelSec = Sec;
-    Sym->IsUsedInRegularObj = true;
-    Sym->Used = true;
-  }
+  for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS))
+    replaceWithDefined(*Sym, Sec, 0, Sym->Size);
 
   InX::RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS);
 }
@@ -828,10 +840,8 @@ static void processRelocAux(InputSection
   }
 
   // If the symbol is undefined we already reported any relevant errors.
-  if (!Sym.isShared()) {
-    assert(Sym.isUndefined());
+  if (Sym.isUndefined())
     return;
-  }
 
   if (!canDefineSymbolInExecutable(Sym)) {
     error("cannot preempt symbol: " + toString(Sym) +
@@ -841,14 +851,13 @@ static void processRelocAux(InputSection
 
   if (Sym.isObject()) {
     // Produce a copy relocation.
-    auto &SS = cast<SharedSymbol>(Sym);
-    if (!SS.CopyRelSec) {
+    if (auto *SS = dyn_cast<SharedSymbol>(&Sym)) {
       if (!Config->ZCopyreloc)
         error("unresolvable relocation " + toString(Type) +
-              " against symbol '" + toString(SS) +
+              " against symbol '" + toString(*SS) +
               "'; recompile with -fPIC or remove '-z nocopyreloc'" +
               getLocation(Sec, Sym, Offset));
-      addCopyRelSymbol<ELFT>(SS);
+      addCopyRelSymbol<ELFT>(*SS);
     }
     Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
     return;
@@ -889,8 +898,10 @@ static void processRelocAux(InputSection
     if (!Sym.isInPlt())
       addPltEntry<ELFT>(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel,
                         Sym);
+    if (!Sym.isDefined())
+      replaceWithDefined(Sym, InX::Plt, Sym.getPltOffset(), 0);
     Sym.NeedsPltAddr = true;
-    Sec.Relocations.push_back({toPlt(Expr), Type, Offset, Addend, &Sym});
+    Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
     return;
   }
 

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=330966&r1=330965&r2=330966&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Thu Apr 26 10:58:58 2018
@@ -97,14 +97,7 @@ static uint64_t getSymVA(const Symbol &S
     }
     return VA;
   }
-  case Symbol::SharedKind: {
-    auto &SS = cast<SharedSymbol>(Sym);
-    if (SS.CopyRelSec)
-      return SS.CopyRelSec->getVA(0);
-    if (SS.NeedsPltAddr)
-      return Sym.getPltVA();
-    return 0;
-  }
+  case Symbol::SharedKind:
   case Symbol::UndefinedKind:
     return 0;
   case Symbol::LazyArchiveKind:
@@ -143,6 +136,11 @@ uint64_t Symbol::getPltVA() const {
   return InX::Plt->getVA() + Target->getPltEntryOffset(PltIndex);
 }
 
+uint64_t Symbol::getPltOffset() const {
+  assert(!this->IsInIplt);
+  return Target->getPltEntryOffset(PltIndex);
+}
+
 uint64_t Symbol::getSize() const {
   if (const auto *DR = dyn_cast<Defined>(this))
     return DR->Size;
@@ -157,13 +155,6 @@ OutputSection *Symbol::getOutputSection(
       return Sec->Repl->getOutputSection();
     return nullptr;
   }
-
-  if (auto *S = dyn_cast<SharedSymbol>(this)) {
-    if (S->CopyRelSec)
-      return S->CopyRelSec->getParent();
-    return nullptr;
-  }
-
   return nullptr;
 }
 

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=330966&r1=330965&r2=330966&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Thu Apr 26 10:58:58 2018
@@ -72,6 +72,9 @@ public:
   uint32_t PltIndex = -1;
   uint32_t GlobalDynIndex = -1;
 
+  // This field is a index to the symbol's version definition.
+  uint32_t VerdefIndex = -1;
+
   // Version definition index.
   uint16_t VersionId;
 
@@ -146,6 +149,7 @@ public:
   uint64_t getGotPltOffset() const;
   uint64_t getGotPltVA() const;
   uint64_t getPltVA() const;
+  uint64_t getPltOffset() const;
   uint64_t getSize() const;
   OutputSection *getOutputSection() const;
 
@@ -225,8 +229,9 @@ public:
   SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding,
                uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size,
                uint32_t Alignment, uint32_t VerdefIndex)
-      : Symbol(SharedKind, &File, Name, Binding, StOther, Type), Value(Value),
-        Size(Size), VerdefIndex(VerdefIndex), Alignment(Alignment) {
+      : Symbol(SharedKind, &File, Name, Binding, StOther, Type),
+        Alignment(Alignment), Value(Value), Size(Size) {
+    this->VerdefIndex = VerdefIndex;
     // GNU ifunc is a mechanism to allow user-supplied functions to
     // resolve PLT slot values at load-time. This is contrary to the
     // regular symbol resolution scheme in which symbols are resolved just
@@ -251,16 +256,10 @@ public:
     return *cast<SharedFile<ELFT>>(File);
   }
 
-  // If not null, there is a copy relocation to this section.
-  InputSection *CopyRelSec = nullptr;
+  uint32_t Alignment;
 
   uint64_t Value; // st_value
   uint64_t Size;  // st_size
-
-  // This field is a index to the symbol's version definition.
-  uint32_t VerdefIndex;
-
-  uint32_t Alignment;
 };
 
 // LazyArchive and LazyObject represent a symbols that is not yet in the link,

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=330966&r1=330965&r2=330966&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Apr 26 10:58:58 2018
@@ -1646,6 +1646,8 @@ template <class ELFT> void SymbolTableSe
         CommonSec = dyn_cast_or_null<BssSection>(D->Section);
     if (CommonSec)
       ESym->st_shndx = SHN_COMMON;
+    else if (Sym->NeedsPltAddr)
+      ESym->st_shndx = SHN_UNDEF;
     else if (const OutputSection *OutSec = Sym->getOutputSection())
       ESym->st_shndx = OutSec->SectionIndex;
     else if (isa<Defined>(Sym))
@@ -1688,8 +1690,7 @@ template <class ELFT> void SymbolTableSe
       if (isMicroMips()) {
         // Set STO_MIPS_MICROMIPS flag and less-significant bit for
         // defined microMIPS symbols and shared symbols with PLT record.
-        if ((Sym->isDefined() && (Sym->StOther & STO_MIPS_MICROMIPS)) ||
-            (Sym->isShared() && Sym->NeedsPltAddr)) {
+        if (Sym->isDefined() && (Sym->StOther & STO_MIPS_MICROMIPS)) {
           if (StrTabSec.isDynamic())
             ESym->st_value |= 1;
           ESym->st_other |= STO_MIPS_MICROMIPS;
@@ -1831,10 +1832,6 @@ void GnuHashTableSection::addSymbols(std
   // its type correctly.
   std::vector<SymbolTableEntry>::iterator Mid =
       std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) {
-        // Shared symbols that this executable preempts are special. The dynamic
-        // linker has to look them up, so they have to be in the hash table.
-        if (auto *SS = dyn_cast<SharedSymbol>(S.Sym))
-          return SS->CopyRelSec == nullptr && !SS->NeedsPltAddr;
         return !S.Sym->isDefined();
       });
 
@@ -2359,9 +2356,8 @@ VersionNeedSection<ELFT>::VersionNeedSec
   NextIndex = getVerDefNum() + 1;
 }
 
-template <class ELFT>
-void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) {
-  SharedFile<ELFT> &File = SS->getFile<ELFT>();
+template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) {
+  auto &File = cast<SharedFile<ELFT>>(*SS->File);
   if (SS->VerdefIndex == VER_NDX_GLOBAL) {
     SS->VersionId = VER_NDX_GLOBAL;
     return;

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=330966&r1=330965&r2=330966&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Apr 26 10:58:58 2018
@@ -670,7 +670,7 @@ template <class ELFT> class VersionNeedS
 
 public:
   VersionNeedSection();
-  void addSymbol(SharedSymbol *SS);
+  void addSymbol(Symbol *Sym);
   void finalizeContents() override;
   void writeTo(uint8_t *Buf) override;
   size_t getSize() const override;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=330966&r1=330965&r2=330966&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Apr 26 10:58:58 2018
@@ -1570,9 +1570,9 @@ template <class ELFT> void Writer<ELFT>:
 
     if (InX::DynSymTab && Sym->includeInDynsym()) {
       InX::DynSymTab->addSymbol(Sym);
-      if (auto *SS = dyn_cast<SharedSymbol>(Sym))
-        if (cast<SharedFile<ELFT>>(Sym->File)->IsNeeded)
-          In<ELFT>::VerNeed->addSymbol(SS);
+      if (auto *File = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File))
+        if (File->IsNeeded && !Sym->isUndefined())
+          In<ELFT>::VerNeed->addSymbol(Sym);
     }
   }
 

Modified: lld/trunk/test/ELF/map-file.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/map-file.s?rev=330966&r1=330965&r2=330966&view=diff
==============================================================================
--- lld/trunk/test/ELF/map-file.s (original)
+++ lld/trunk/test/ELF/map-file.s Thu Apr 26 10:58:58 2018
@@ -73,8 +73,8 @@ labs = 0x1AB5
 // CHECK-NEXT: 20102c           20102c        0     1                 baz
 // CHECK-NEXT: 201030           201030       30    16 .plt
 // CHECK-NEXT: 201030           201030       30    16         <internal>:(.plt)
-// CHECK-NEXT: 201040                0        0     1                 sharedFunc1
-// CHECK-NEXT: 201050                0        0     1                 sharedFunc2
+// CHECK-NEXT: 201040           201040        0     1                 sharedFunc1
+// CHECK-NEXT: 201050           201050        0     1                 sharedFunc2
 // CHECK-NEXT: 202000           202000       28     8 .got.plt
 // CHECK-NEXT: 202000           202000       28     8         <internal>:(.got.plt)
 // CHECK-NEXT: 203000           203000      100     8 .dynamic




More information about the llvm-commits mailing list