[lld] r267183 - ELF: Move Visibility, IsUsedInRegularObj and MustBeInDynSym flags to Symbol.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 22 11:42:49 PDT 2016


Author: pcc
Date: Fri Apr 22 13:42:48 2016
New Revision: 267183

URL: http://llvm.org/viewvc/llvm-project?rev=267183&view=rev
Log:
ELF: Move Visibility, IsUsedInRegularObj and MustBeInDynSym flags to Symbol.

These are properties of a symbol name, rather than a particular instance
of a symbol in an object file. We can simplify the code by collecting these
properties in Symbol.

The MustBeInDynSym flag has been renamed ExportDynamic, as its semantics
have been changed to be the same as those of --dynamic-list and
--export-dynamic-symbol, which do not cause hidden symbols to be exported.

Differential Revision: http://reviews.llvm.org/D19400

Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/LTO.cpp
    lld/trunk/ELF/MarkLive.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.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=267183&r1=267182&r2=267183&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Fri Apr 22 13:42:48 2016
@@ -437,7 +437,7 @@ template <class ELFT> void LinkerDriver:
     // Set either EntryAddr (if S is a number) or EntrySym (otherwise).
     StringRef S = Config->Entry;
     if (S.getAsInteger(0, Config->EntryAddr))
-      Config->EntrySym = Symtab.addUndefined(S)->getSymbol();
+      Config->EntrySym = Symtab.addUndefined(S)->Backref;
   }
 
   for (std::unique_ptr<InputFile> &F : Files)

Modified: lld/trunk/ELF/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.cpp?rev=267183&r1=267182&r2=267183&view=diff
==============================================================================
--- lld/trunk/ELF/LTO.cpp (original)
+++ lld/trunk/ELF/LTO.cpp Fri Apr 22 13:42:48 2016
@@ -76,13 +76,13 @@ static void runLTOPasses(Module &M, Targ
 
 static bool shouldInternalize(const SmallPtrSet<GlobalValue *, 8> &Used,
                               SymbolBody &B, GlobalValue *GV) {
-  if (B.isUsedInRegularObj())
+  if (B.Backref->IsUsedInRegularObj)
     return false;
 
   if (Used.count(GV))
     return false;
 
-  return !B.includeInDynsym();
+  return !B.Backref->includeInDynsym();
 }
 
 void BitcodeCompiler::add(BitcodeFile &F) {

Modified: lld/trunk/ELF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=267183&r1=267182&r2=267183&view=diff
==============================================================================
--- lld/trunk/ELF/MarkLive.cpp (original)
+++ lld/trunk/ELF/MarkLive.cpp Fri Apr 22 13:42:48 2016
@@ -128,13 +128,10 @@ template <class ELFT> void elf::markLive
 
   // Preserve externally-visible symbols if the symbols defined by this
   // file can interrupt other ELF file's symbols at runtime.
-  if (Config->Shared || Config->ExportDynamic) {
-    for (const Symbol *S : Symtab->getSymbols()) {
-      SymbolBody *B = S->Body;
-      if (B->includeInDynsym())
-        MarkSymbol(B);
-    }
-  }
+  if (Config->Shared || Config->ExportDynamic)
+    for (const Symbol *S : Symtab->getSymbols())
+      if (S->includeInDynsym())
+        MarkSymbol(S->Body);
 
   // Preserve special sections and those which are specified in linker
   // script KEEP command.

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=267183&r1=267182&r2=267183&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Fri Apr 22 13:42:48 2016
@@ -1343,7 +1343,7 @@ static bool sortMipsSymbols(const std::p
 }
 
 static uint8_t getSymbolBinding(SymbolBody *Body) {
-  uint8_t Visibility = Body->getVisibility();
+  uint8_t Visibility = Body->Backref->Visibility;
   if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
     return STB_LOCAL;
   if (Config->NoGnuUnique && Body->Binding == STB_GNU_UNIQUE)
@@ -1428,12 +1428,6 @@ void SymbolTableSection<ELFT>::writeLoca
   }
 }
 
-static uint8_t getSymbolVisibility(SymbolBody *Body) {
-  if (Body->isShared())
-    return STV_DEFAULT;
-  return Body->getVisibility();
-}
-
 template <class ELFT>
 void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
   // Write the internal symbol table contents to the output symbol table
@@ -1449,7 +1443,7 @@ void SymbolTableSection<ELFT>::writeGlob
     ESym->setBindingAndType(getSymbolBinding(Body), Type);
     ESym->st_size = Size;
     ESym->st_name = StrOff;
-    ESym->setVisibility(getSymbolVisibility(Body));
+    ESym->setVisibility(Body->Backref->Visibility);
     ESym->st_value = Body->getVA<ELFT>();
 
     if (const OutputSectionBase<ELFT> *OutSec = getOutputSection(Body))

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=267183&r1=267182&r2=267183&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Fri Apr 22 13:42:48 2016
@@ -132,11 +132,6 @@ template <class ELFT> void SymbolTable<E
     Obj->parse(DummyGroups);
     for (SymbolBody *Body : Obj->getNonLocalSymbols()) {
       Symbol *Sym = insert(Body);
-      Sym->Body->setUsedInRegularObj();
-      if (Sym->Body->isShared())
-        Sym->Body->MustBeInDynSym = true;
-      if (Sym->Body->MustBeInDynSym)
-        Body->MustBeInDynSym = true;
       if (!Sym->Body->isUndefined() && Body->isUndefined())
         continue;
       Sym->Body = Body;
@@ -198,9 +193,9 @@ template <class ELFT> void SymbolTable<E
   if (Symtab.count(Name) == 0)
     return;
   StringSaver Saver(Alloc);
-  Symbol *Sym = addUndefined(Name)->getSymbol();
-  Symbol *Real = addUndefined(Saver.save("__real_" + Name))->getSymbol();
-  Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name))->getSymbol();
+  Symbol *Sym = addUndefined(Name)->Backref;
+  Symbol *Real = addUndefined(Saver.save("__real_" + Name))->Backref;
+  Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name))->Backref;
   Real->Body = Sym->Body;
   Sym->Body = Wrap->Body;
 }
@@ -247,8 +242,6 @@ template <class ELFT> void SymbolTable<E
     }
     // Found a definition for something also in an archive.
     // Ignore the archive definition.
-    if (L->isUsedInRegularObj())
-      New->setUsedInRegularObj();
     Sym->Body = New;
     return;
   }
@@ -273,6 +266,23 @@ template <class ELFT> void SymbolTable<E
     Sym->Body = New;
 }
 
+static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
+  if (VA == STV_DEFAULT)
+    return VB;
+  if (VB == STV_DEFAULT)
+    return VA;
+  return std::min(VA, VB);
+}
+
+static bool shouldExport(SymbolBody *B) {
+  if (Config->Shared || Config->ExportDynamic) {
+    // Export most symbols except for those that do not need to be exported.
+    return !B->CanOmitFromDynSym;
+  }
+  // Make sure we preempt DSO symbols with default visibility.
+  return B->isShared() && B->getVisibility() == STV_DEFAULT;
+}
+
 // Find an existing symbol or create and insert a new one.
 template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
   StringRef Name = New->getName();
@@ -280,12 +290,24 @@ template <class ELFT> Symbol *SymbolTabl
   auto P = Symtab.insert(std::make_pair(Name, NumSyms));
   Symbol *Sym;
   if (P.second) {
-    Sym = new (Alloc) Symbol{New};
+    Sym = new (Alloc) Symbol{New, STV_DEFAULT, false, false};
     SymVector.push_back(Sym);
   } else {
     Sym = SymVector[P.first->second];
   }
-  New->setBackref(Sym);
+  New->Backref = Sym;
+
+  // Merge in the new symbol's visibility. DSO symbols do not affect visibility
+  // in the output.
+  if (!New->isShared())
+    Sym->Visibility = getMinVisibility(Sym->Visibility, New->getVisibility());
+  Sym->ExportDynamic = Sym->ExportDynamic || shouldExport(New);
+  SymbolBody::Kind K = New->kind();
+  if (K == SymbolBody::DefinedRegularKind ||
+      K == SymbolBody::DefinedCommonKind ||
+      K == SymbolBody::DefinedSyntheticKind ||
+      K == SymbolBody::UndefinedElfKind)
+    Sym->IsUsedInRegularObj = true;
   return Sym;
 }
 
@@ -309,8 +331,6 @@ template <class ELFT> void SymbolTable<E
 
 template <class ELFT>
 void SymbolTable<ELFT>::addMemberFile(SymbolBody *Undef, Lazy *L) {
-  if (Undef->isUsedInRegularObj())
-    L->setUsedInRegularObj();
   // Weak undefined symbols should not fetch members from archives.
   // If we were to keep old symbol we would not know that an archive member was
   // available if a strong undefined symbol shows up afterwards in the link.
@@ -319,7 +339,6 @@ void SymbolTable<ELFT>::addMemberFile(Sy
   // We set UsedInRegularObj in a similar way to what is done with shared
   // symbols and copy information to reduce how many special cases are needed.
   if (Undef->isWeak()) {
-    L->setUsedInRegularObj();
     L->Binding = Undef->Binding;
     L->Type = Undef->Type;
 
@@ -345,7 +364,7 @@ template <class ELFT> void SymbolTable<E
     for (StringRef U : File->getUndefinedSymbols())
       if (SymbolBody *Sym = find(U))
         if (Sym->isDefined())
-          Sym->MustBeInDynSym = true;
+          Sym->Backref->ExportDynamic = true;
 }
 
 // This function process the dynamic list option by marking all the symbols
@@ -353,7 +372,7 @@ template <class ELFT> void SymbolTable<E
 template <class ELFT> void SymbolTable<ELFT>::scanDynamicList() {
   for (StringRef S : Config->DynamicList)
     if (SymbolBody *B = find(S))
-      B->MustBeInDynSym = true;
+      B->Backref->ExportDynamic = true;
 }
 
 template class elf::SymbolTable<ELF32LE>;

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=267183&r1=267182&r2=267183&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Fri Apr 22 13:42:48 2016
@@ -80,7 +80,7 @@ static typename ELFT::uint getSymVA(cons
     return 0;
   case SymbolBody::LazyArchiveKind:
   case SymbolBody::LazyObjectKind:
-    assert(Body.isUsedInRegularObj() && "lazy symbol reached writer");
+    assert(Body.Backref->IsUsedInRegularObj && "lazy symbol reached writer");
     return 0;
   case SymbolBody::DefinedBitcodeKind:
     llvm_unreachable("should have been replaced");
@@ -104,13 +104,9 @@ SymbolBody::SymbolBody(Kind K, StringRef
 }
 
 void SymbolBody::init() {
-  Kind K = kind();
-  IsUsedInRegularObj = K == DefinedRegularKind || K == DefinedCommonKind ||
-                       K == DefinedSyntheticKind || K == UndefinedElfKind;
   CanKeepUndefined = false;
-  MustBeInDynSym = false;
-  CanOmitFromDynSym = false;
   NeedsCopyOrPltAddr = false;
+  CanOmitFromDynSym = false;
 }
 
 // Returns true if a symbol can be replaced at load-time by a symbol
@@ -122,7 +118,7 @@ bool SymbolBody::isPreemptible() const {
   if (isShared())
     return true;
 
-  if (getVisibility() != STV_DEFAULT)
+  if (Backref->Visibility != STV_DEFAULT)
     return false;
 
   if (isUndefined()) {
@@ -193,14 +189,6 @@ template <class ELFT> typename ELFT::uin
   return 0;
 }
 
-static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
-  if (VA == STV_DEFAULT)
-    return VB;
-  if (VB == STV_DEFAULT)
-    return VA;
-  return std::min(VA, VB);
-}
-
 static int compareCommons(DefinedCommon *A, DefinedCommon *B) {
   if (Config->WarnCommon)
     warning("multiple common of " + A->getName());
@@ -220,31 +208,6 @@ int SymbolBody::compare(SymbolBody *Othe
   if (L > R)
     return -Other->compare(this);
 
-  uint8_t V = getMinVisibility(getVisibility(), Other->getVisibility());
-  if (isShared() != Other->isShared()) {
-    SymbolBody *Shared = isShared() ? this : Other;
-    Shared->MustBeInDynSym = true;
-    if (Shared->getVisibility() == STV_DEFAULT &&
-        (V == STV_DEFAULT || V == STV_PROTECTED)) {
-      // We want to export all symbols that exist in the executable and are
-      // preemptable in DSOs, so that the symbols in the executable can
-      // preempt symbols in the DSO at runtime.
-      SymbolBody *NonShared = isShared() ? Other : this;
-      NonShared->MustBeInDynSym = true;
-    }
-  }
-
-  if (!isShared() && !Other->isShared()) {
-    setVisibility(V);
-    Other->setVisibility(V);
-  }
-
-  if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
-    IsUsedInRegularObj = Other->IsUsedInRegularObj = true;
-
-  if (!CanOmitFromDynSym || !Other->CanOmitFromDynSym)
-    CanOmitFromDynSym = Other->CanOmitFromDynSym = false;
-
   if (L != R)
     return -1;
   if (!isDefined() || isShared() || isWeak())
@@ -358,15 +321,10 @@ std::string elf::demangle(StringRef Name
 #endif
 }
 
-bool SymbolBody::includeInDynsym() const {
-  if (MustBeInDynSym)
-    return true;
-  uint8_t V = getVisibility();
-  if (V != STV_DEFAULT && V != STV_PROTECTED)
-    return false;
-  if (!Config->ExportDynamic && !Config->Shared)
+bool Symbol::includeInDynsym() const {
+  if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
     return false;
-  return !CanOmitFromDynSym;
+  return ExportDynamic || Body->isShared();
 }
 
 template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const;

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=267183&r1=267182&r2=267183&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Fri Apr 22 13:42:48 2016
@@ -40,8 +40,27 @@ std::string demangle(StringRef Name);
 // A real symbol object, SymbolBody, is usually accessed indirectly
 // through a Symbol. There's always one Symbol for each symbol name.
 // The resolver updates SymbolBody pointers as it resolves symbols.
+// Symbol also holds computed properties of symbol names.
 struct Symbol {
   SymbolBody *Body;
+
+  // Symbol visibility. This is the computed minimum visibility of all
+  // observed non-DSO symbols.
+  unsigned Visibility : 2;
+
+  // True if the symbol was used for linking and thus need to be added to the
+  // output file's symbol table. This is true for all symbols except for
+  // unreferenced DSO symbols and bitcode symbols that are unreferenced except
+  // by other bitcode objects.
+  unsigned IsUsedInRegularObj : 1;
+
+  // If this flag is true and the symbol has protected or default visibility, it
+  // will appear in .dynsym. This flag is set by interposable DSO symbols in
+  // executables, by most symbols in DSOs and executables built with
+  // --export-dynamic, and by dynamic lists.
+  unsigned ExportDynamic : 1;
+
+  bool includeInDynsym() const;
 };
 
 // The base class for real symbol classes.
@@ -76,7 +95,6 @@ public:
   }
   bool isShared() const { return SymbolKind == SharedKind; }
   bool isLocal() const { return Binding == llvm::ELF::STB_LOCAL; }
-  bool isUsedInRegularObj() const { return IsUsedInRegularObj; }
   bool isPreemptible() const;
 
   // Returns the symbol name.
@@ -102,8 +120,6 @@ public:
   bool isInPlt() const { return PltIndex != -1U; }
   bool hasThunk() const { return ThunkIndex != -1U; }
 
-  void setUsedInRegularObj() { IsUsedInRegularObj = true; }
-
   template <class ELFT>
   typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const;
 
@@ -121,17 +137,13 @@ public:
   // pointer P to a SymbolBody and are not sure whether the resolver
   // has chosen the object among other objects having the same name,
   // you can access P->Backref->Body to get the resolver's result.
-  void setBackref(Symbol *P) { Backref = P; }
   SymbolBody &repl() { return Backref ? *Backref->Body : *this; }
-  Symbol *getSymbol() const { return Backref; }
 
   // Decides which symbol should "win" in the symbol table, this or
   // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
   // they are duplicate (conflicting) symbols.
   int compare(SymbolBody *Other);
 
-  bool includeInDynsym() const;
-
 protected:
   SymbolBody(Kind K, StringRef Name, uint8_t Binding, uint8_t StOther,
              uint8_t Type);
@@ -140,12 +152,6 @@ protected:
 
   const unsigned SymbolKind : 8;
 
-  // True if the symbol was used for linking and thus need to be
-  // added to the output file's symbol table. It is usually true,
-  // but if it is a shared symbol that were not referenced by anyone,
-  // it can be false.
-  unsigned IsUsedInRegularObj : 1;
-
 public:
   // True if this symbol can be omitted from the symbol table if nothing else
   // requires it to be there. Right now this is only used for linkonce_odr in
@@ -153,9 +159,6 @@ public:
   // MachO's .weak_def_can_be_hidden.
   unsigned CanOmitFromDynSym : 1;
 
-  // If true, the symbol is added to .dynsym symbol table.
-  unsigned MustBeInDynSym : 1;
-
   // True if the linker has to generate a copy relocation for this shared
   // symbol or if the symbol should point to its plt entry.
   unsigned NeedsCopyOrPltAddr : 1;
@@ -173,7 +176,8 @@ public:
   bool isGnuIFunc() const { return Type == llvm::ELF::STT_GNU_IFUNC; }
   bool isObject() const { return Type == llvm::ELF::STT_OBJECT; }
   bool isFile() const { return Type == llvm::ELF::STT_FILE; }
-  void setVisibility(uint8_t V) { StOther = (StOther & ~0x3) | V; }
+
+  Symbol *Backref = nullptr;
 
 protected:
   struct Str {
@@ -184,7 +188,6 @@ protected:
     Str Name;
     uint32_t NameOffset;
   };
-  Symbol *Backref = nullptr;
 };
 
 // The base class for any defined symbols.

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=267183&r1=267182&r2=267183&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Apr 22 13:42:48 2016
@@ -977,8 +977,7 @@ void Writer<ELFT>::addCopyRelSymbol(Shar
       continue;
     S.OffsetInBss = Off;
     S.NeedsCopyOrPltAddr = true;
-    S.setUsedInRegularObj();
-    S.MustBeInDynSym = true;
+    S.Backref->IsUsedInRegularObj = true;
   }
   Out<ELFT>::RelaDyn->addReloc(
       {Target->CopyRel, Out<ELFT>::Bss, SS->OffsetInBss, false, SS, 0});
@@ -1042,7 +1041,7 @@ template <class ELFT> void Writer<ELFT>:
 }
 
 template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
-  if (!B.isUsedInRegularObj())
+  if (!B.Backref->IsUsedInRegularObj)
     return false;
 
   if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&B)) {
@@ -1326,7 +1325,7 @@ template <class ELFT> void Writer<ELFT>:
     if (Out<ELFT>::SymTab)
       Out<ELFT>::SymTab->addSymbol(Body);
 
-    if (isOutputDynamic() && Body->includeInDynsym())
+    if (isOutputDynamic() && S->includeInDynsym())
       Out<ELFT>::DynSymTab->addSymbol(Body);
   }
 




More information about the llvm-commits mailing list