[lld] r256289 - Split Undefined and UndefinedElf.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 22 15:00:51 PST 2015


Author: rafael
Date: Tue Dec 22 17:00:50 2015
New Revision: 256289

URL: http://llvm.org/viewvc/llvm-project?rev=256289&view=rev
Log:
Split Undefined and UndefinedElf.

I am working on adding LTO support to the new ELF lld.

In order to do that, it will be necessary to represent defined and
undefined symbols that are not from ELF files. One way to do it is to
change the symbol hierarchy to look like

Defined : SymbolBody
Undefined : SymbolBody

DefinedElf<ELFT> : Defined
UndefinedElf<ELFT> : Undefined

Another option would be to use bogus Elf_Sym, but I think that is
getting a bit too hackish.

This patch does the Undefined/UndefinedElf. Split. The next one
will do the Defined/DefinedElf split.

Modified:
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=256289&r1=256288&r2=256289&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Tue Dec 22 17:00:50 2015
@@ -275,7 +275,7 @@ SymbolBody *elf2::ObjectFile<ELFT>::crea
   case SHN_ABS:
     return new (this->Alloc) DefinedAbsolute<ELFT>(Name, *Sym);
   case SHN_UNDEF:
-    return new (this->Alloc) Undefined<ELFT>(Name, *Sym);
+    return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym);
   case SHN_COMMON:
     return new (this->Alloc) DefinedCommon<ELFT>(Name, *Sym);
   }
@@ -288,7 +288,7 @@ SymbolBody *elf2::ObjectFile<ELFT>::crea
   case STB_GNU_UNIQUE: {
     InputSectionBase<ELFT> *Sec = getSection(*Sym);
     if (Sec == &InputSection<ELFT>::Discarded)
-      return new (this->Alloc) Undefined<ELFT>(Name, *Sym);
+      return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym);
     return new (this->Alloc) DefinedRegular<ELFT>(Name, *Sym, *Sec);
   }
   }

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=256289&r1=256288&r2=256289&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Dec 22 17:00:50 2015
@@ -807,6 +807,7 @@ typename ELFFile<ELFT>::uintX_t lld::elf
       return Out<ELFT>::Bss->getVA() + SS.OffsetInBSS;
     return 0;
   }
+  case SymbolBody::UndefinedElfKind:
   case SymbolBody::UndefinedKind:
     return 0;
   case SymbolBody::LazyKind:
@@ -1329,6 +1330,16 @@ void SymbolTableSection<ELFT>::writeLoca
 }
 
 template <class ELFT>
+static const typename llvm::object::ELFFile<ELFT>::Elf_Sym *
+getElfSym(SymbolBody &Body) {
+  if (auto *EBody = dyn_cast<Defined<ELFT>>(&Body))
+    return &EBody->Sym;
+  if (auto *EBody = dyn_cast<UndefinedElf<ELFT>>(&Body))
+    return &EBody->Sym;
+  return nullptr;
+}
+
+template <class ELFT>
 void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
   // Write the internal symbol table contents to the output symbol table
   // pointed by Buf.
@@ -1355,6 +1366,7 @@ void SymbolTableSection<ELFT>::writeGlob
         OutSec = Out<ELFT>::Bss;
       break;
     }
+    case SymbolBody::UndefinedElfKind:
     case SymbolBody::UndefinedKind:
     case SymbolBody::DefinedAbsoluteKind:
     case SymbolBody::LazyKind:
@@ -1366,10 +1378,9 @@ void SymbolTableSection<ELFT>::writeGlob
 
     unsigned char Type = STT_NOTYPE;
     uintX_t Size = 0;
-    if (const auto *EBody = dyn_cast<ELFSymbolBody<ELFT>>(Body)) {
-      const Elf_Sym &InputSym = EBody->Sym;
-      Type = InputSym.getType();
-      Size = InputSym.st_size;
+    if (const Elf_Sym *InputSym = getElfSym<ELFT>(*Body)) {
+      Type = InputSym->getType();
+      Size = InputSym->st_size;
     }
 
     ESym->setBindingAndType(getSymbolBinding(Body), Type);
@@ -1391,8 +1402,8 @@ uint8_t SymbolTableSection<ELFT>::getSym
   uint8_t Visibility = Body->getVisibility();
   if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
     return STB_LOCAL;
-  if (const auto *EBody = dyn_cast<ELFSymbolBody<ELFT>>(Body))
-    return EBody->Sym.getBinding();
+  if (const Elf_Sym *ESym = getElfSym<ELFT>(*Body))
+    return ESym->getBinding();
   return Body->isWeak() ? STB_WEAK : STB_GLOBAL;
 }
 

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=256289&r1=256288&r2=256289&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Tue Dec 22 17:00:50 2015
@@ -35,7 +35,6 @@ template <class ELFT> class MipsReginfoI
 template <class ELFT> class OutputSection;
 template <class ELFT> class ObjectFile;
 template <class ELFT> class DefinedRegular;
-template <class ELFT> class ELFSymbolBody;
 
 // Flag to force GOT to be in output if we have relocations
 // that relies on its address.

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=256289&r1=256288&r2=256289&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Dec 22 17:00:50 2015
@@ -80,14 +80,14 @@ void SymbolTable<ELFT>::addFile(std::uni
 
 template <class ELFT>
 SymbolBody *SymbolTable<ELFT>::addUndefined(StringRef Name) {
-  auto *Sym = new (Alloc) Undefined<ELFT>(Name, Undefined<ELFT>::Required);
+  auto *Sym = new (Alloc) Undefined(Name, false, STV_DEFAULT, false);
   resolve(Sym);
   return Sym;
 }
 
 template <class ELFT>
 SymbolBody *SymbolTable<ELFT>::addUndefinedOpt(StringRef Name) {
-  auto *Sym = new (Alloc) Undefined<ELFT>(Name, Undefined<ELFT>::Optional);
+  auto *Sym = new (Alloc) Undefined(Name, false, STV_HIDDEN, true);
   resolve(Sym);
   return Sym;
 }
@@ -130,13 +130,9 @@ template <class ELFT>
 ELFFileBase<ELFT> *
 elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles,
                const SymbolBody *B) {
-  typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
-  typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
-
-  const Elf_Sym *Sym = &cast<ELFSymbolBody<ELFT>>(*B).Sym;
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : ObjectFiles) {
-    Elf_Sym_Range R = F->getObj().symbols(F->getSymbolTable());
-    if (R.begin() <= Sym && Sym < R.end())
+    ArrayRef<SymbolBody *> Syms = F->getSymbols();
+    if (std::find(Syms.begin(), Syms.end(), B) != Syms.end())
       return F.get();
   }
   return nullptr;
@@ -163,7 +159,7 @@ template <class ELFT> void SymbolTable<E
   SymbolBody *Existing = Sym->Body;
 
   if (Lazy *L = dyn_cast<Lazy>(Existing)) {
-    if (auto *Undef = dyn_cast<Undefined<ELFT>>(New)) {
+    if (auto *Undef = dyn_cast<Undefined>(New)) {
       addMemberFile(Undef, L);
       return;
     }
@@ -211,14 +207,14 @@ template <class ELFT> void SymbolTable<E
   Symbol *Sym = insert(L);
   if (Sym->Body == L)
     return;
-  if (auto *Undef = dyn_cast<Undefined<ELFT>>(Sym->Body)) {
+  if (auto *Undef = dyn_cast<Undefined>(Sym->Body)) {
     Sym->Body = L;
     addMemberFile(Undef, L);
   }
 }
 
 template <class ELFT>
-void SymbolTable<ELFT>::addMemberFile(Undefined<ELFT> *Undef, Lazy *L) {
+void SymbolTable<ELFT>::addMemberFile(Undefined *Undef, Lazy *L) {
   // 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.

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=256289&r1=256288&r2=256289&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Tue Dec 22 17:00:50 2015
@@ -16,9 +16,9 @@
 namespace lld {
 namespace elf2 {
 class Lazy;
-struct Symbol;
 template <class ELFT> class OutputSectionBase;
-template <class ELFT> class Undefined;
+struct Symbol;
+class Undefined;
 
 // SymbolTable is a bucket of all known symbols, including defined,
 // undefined, or lazy symbols (the last one is symbols in archive
@@ -62,7 +62,7 @@ public:
 private:
   Symbol *insert(SymbolBody *New);
   void addLazy(Lazy *New);
-  void addMemberFile(Undefined<ELFT> *Undef, Lazy *L);
+  void addMemberFile(Undefined *Undef, Lazy *L);
   void resolve(SymbolBody *Body);
   std::string conflictMsg(SymbolBody *Old, SymbolBody *New);
 

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=256289&r1=256288&r2=256289&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Tue Dec 22 17:00:50 2015
@@ -73,6 +73,24 @@ template <class ELFT> int SymbolBody::co
   return 0;
 }
 
+Undefined::Undefined(SymbolBody::Kind K, StringRef N, bool IsWeak,
+                     uint8_t Visibility, bool IsTls)
+    : SymbolBody(K, N, IsWeak, Visibility, IsTls), CanKeepUndefined(false) {}
+
+Undefined::Undefined(StringRef N, bool IsWeak, uint8_t Visibility,
+                     bool CanKeepUndefined)
+    : Undefined(SymbolBody::UndefinedKind, N, IsWeak, Visibility,
+                /*IsTls*/ false) {
+  this->CanKeepUndefined = CanKeepUndefined;
+}
+
+template <typename ELFT>
+UndefinedElf<ELFT>::UndefinedElf(StringRef N, const Elf_Sym &Sym)
+    : Undefined(SymbolBody::UndefinedElfKind, N,
+                Sym.getBinding() == llvm::ELF::STB_WEAK, Sym.getVisibility(),
+                Sym.getType() == llvm::ELF::STT_TLS),
+      Sym(Sym) {}
+
 std::unique_ptr<InputFile> Lazy::getMember() {
   MemoryBufferRef MBRef = File->getMember(&Sym);
 
@@ -88,7 +106,6 @@ template <class ELFT> static void doInit
   DefinedAbsolute<ELFT>::End.setBinding(STB_GLOBAL);
   DefinedAbsolute<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
   DefinedAbsolute<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
-  Undefined<ELFT>::Optional.setVisibility(STV_HIDDEN);
 }
 
 void lld::elf2::initSymbols() {
@@ -102,3 +119,8 @@ template int SymbolBody::compare<ELF32LE
 template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
 template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
 template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
+
+template class lld::elf2::UndefinedElf<ELF32LE>;
+template class lld::elf2::UndefinedElf<ELF32BE>;
+template class lld::elf2::UndefinedElf<ELF64LE>;
+template class lld::elf2::UndefinedElf<ELF64BE>;

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=256289&r1=256288&r2=256289&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue Dec 22 17:00:50 2015
@@ -62,6 +62,7 @@ public:
     DefinedSyntheticKind,
     SharedKind,
     DefinedLast = SharedKind,
+    UndefinedElfKind,
     UndefinedKind,
     LazyKind
   };
@@ -69,7 +70,9 @@ public:
   Kind kind() const { return static_cast<Kind>(SymbolKind); }
 
   bool isWeak() const { return IsWeak; }
-  bool isUndefined() const { return SymbolKind == UndefinedKind; }
+  bool isUndefined() const {
+    return SymbolKind == UndefinedKind || SymbolKind == UndefinedElfKind;
+  }
   bool isDefined() const { return SymbolKind <= DefinedLast; }
   bool isCommon() const { return SymbolKind == DefinedCommonKind; }
   bool isLazy() const { return SymbolKind == LazyKind; }
@@ -127,40 +130,18 @@ protected:
   Symbol *Backref = nullptr;
 };
 
-// This is for symbols created from elf files and not from the command line.
-// Since they come from object files, they have a Elf_Sym.
-//
-// FIXME: Another alternative is to give every symbol an Elf_Sym. To do that
-// we have to delay creating the symbol table until the output format is
-// known and some of its methods will be templated. We should experiment with
-// that once we have a bit more code.
-template <class ELFT> class ELFSymbolBody : public SymbolBody {
-protected:
-  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
-  ELFSymbolBody(Kind K, StringRef Name, const Elf_Sym &Sym)
-      : SymbolBody(K, Name, Sym.getBinding() == llvm::ELF::STB_WEAK,
-                   Sym.getVisibility(), Sym.getType() == llvm::ELF::STT_TLS),
-        Sym(Sym) {}
-
-public:
-  const Elf_Sym &Sym;
-
-  static bool classof(const SymbolBody *S) {
-    Kind K = S->kind();
-    return K >= DefinedFirst && K <= UndefinedKind;
-  }
-};
-
 // The base class for any defined symbols, including absolute symbols, etc.
-template <class ELFT> class Defined : public ELFSymbolBody<ELFT> {
+template <class ELFT> class Defined : public SymbolBody {
 protected:
-  typedef typename SymbolBody::Kind Kind;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
 
 public:
   Defined(Kind K, StringRef N, const Elf_Sym &Sym)
-      : ELFSymbolBody<ELFT>(K, N, Sym) {}
+      : SymbolBody(K, N, Sym.getBinding() == llvm::ELF::STB_WEAK,
+                   Sym.getVisibility(), Sym.getType() == llvm::ELF::STT_TLS),
+        Sym(Sym) {}
 
+  const Elf_Sym &Sym;
   static bool classof(const SymbolBody *S) { return S->isDefined(); }
 };
 
@@ -267,27 +248,29 @@ public:
 };
 
 // Undefined symbol.
-template <class ELFT> class Undefined : public ELFSymbolBody<ELFT> {
-  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+class Undefined : public SymbolBody {
+  typedef SymbolBody::Kind Kind;
+  bool CanKeepUndefined;
 
-public:
-  static Elf_Sym Required;
-  static Elf_Sym Optional;
+protected:
+  Undefined(Kind K, StringRef N, bool IsWeak, uint8_t Visibility, bool IsTls);
 
-  Undefined(StringRef N, const Elf_Sym &Sym)
-      : ELFSymbolBody<ELFT>(SymbolBody::UndefinedKind, N, Sym) {}
+public:
+  Undefined(StringRef N, bool IsWeak, uint8_t Visibility,
+            bool CanKeepUndefined);
 
-  static bool classof(const SymbolBody *S) {
-    return S->kind() == SymbolBody::UndefinedKind;
-  }
+  static bool classof(const SymbolBody *S) { return S->isUndefined(); }
 
-  bool canKeepUndefined() const { return &this->Sym == &Optional; }
+  bool canKeepUndefined() const { return CanKeepUndefined; }
 };
 
-template <class ELFT>
-typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Required;
-template <class ELFT>
-typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Optional;
+template <class ELFT> class UndefinedElf : public Undefined {
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+
+public:
+  UndefinedElf(StringRef N, const Elf_Sym &Sym);
+  const Elf_Sym &Sym;
+};
 
 template <class ELFT> class SharedSymbol : public Defined<ELFT> {
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=256289&r1=256288&r2=256289&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Dec 22 17:00:50 2015
@@ -745,7 +745,7 @@ template <class ELFT> void Writer<ELFT>:
   std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
   for (auto &P : Symtab.getSymbols()) {
     SymbolBody *Body = P.second->Body;
-    if (auto *U = dyn_cast<Undefined<ELFT>>(Body))
+    if (auto *U = dyn_cast<Undefined>(Body))
       if (!U->isWeak() && !U->canKeepUndefined())
         reportUndefined<ELFT>(Symtab, *Body);
 




More information about the llvm-commits mailing list