[lld] r249902 - ELF2: Make SymbolTable a template class.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 9 14:07:26 PDT 2015


Author: ruiu
Date: Fri Oct  9 16:07:25 2015
New Revision: 249902

URL: http://llvm.org/viewvc/llvm-project?rev=249902&view=rev
Log:
ELF2: Make SymbolTable a template class.

SymbolTable was not a template class. Instead we had switch-case-based
type dispatch to call desired functions. We had to do that because
SymbolTable was created before we know what ELF type objects had been
passed.

Every time I tried to add a new function to the symbol table, I had to
define a dispatcher which consist of a single switch statement.

It also brought an restriction what the driver can do. For example,
we cannot add undefined symbols before any files are added to the symbol
table. That's because no symbols can be added until the symbol table
knows the ELF type, but when it knows about that, it's too late.

In this patch, the driver makes a decision on what ELF type objects
are being handled. Then the driver creates a SymbolTable object for
an appropriate ELF type.

http://reviews.llvm.org/D13544

Added:
    lld/trunk/test/elf2/no-obj.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Driver.h
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/ELF/Writer.h
    lld/trunk/test/elf2/incompatible.s

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Fri Oct  9 16:07:25 2015
@@ -46,7 +46,6 @@ struct Configuration {
   bool NoUndefined;
   bool Shared;
   bool Static = false;
-  bool WholeArchive = false;
   bool ZNow = false;
   ELFKind ElfKind = ELFNoneKind;
   uint16_t EMachine = llvm::ELF::EM_NONE;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Fri Oct  9 16:07:25 2015
@@ -20,6 +20,7 @@
 
 using namespace llvm;
 using namespace llvm::ELF;
+using namespace llvm::object;
 
 using namespace lld;
 using namespace lld::elf2;
@@ -32,7 +33,7 @@ void lld::elf2::link(ArrayRef<const char
   LinkerDriver D;
   Config = &C;
   Driver = &D;
-  Driver->link(Args.slice(1));
+  Driver->main(Args.slice(1));
 }
 
 static void setELFType(StringRef Emul) {
@@ -102,28 +103,6 @@ static std::string searchLibrary(StringR
   error(Twine("Unable to find library -l") + Path);
 }
 
-template <template <class> class T>
-std::unique_ptr<ELFFileBase>
-LinkerDriver::createELFInputFile(MemoryBufferRef MB) {
-  std::unique_ptr<ELFFileBase> File = createELFFile<T>(MB);
-  const ELFKind ElfKind = File->getELFKind();
-  const uint16_t EMachine = File->getEMachine();
-
-  // Grab target from the first input file if wasn't set by -m option.
-  if (Config->ElfKind == ELFNoneKind) {
-    Config->ElfKind = ElfKind;
-    Config->EMachine = EMachine;
-    return File;
-  }
-  if (ElfKind == Config->ElfKind && EMachine == Config->EMachine)
-    return File;
-
-  if (const ELFFileBase *First = Symtab.getFirstELF())
-    error(MB.getBufferIdentifier() + " is incompatible with " +
-          First->getName());
-  error(MB.getBufferIdentifier() + " is incompatible with target architecture");
-}
-
 // Opens and parses a file. Path has to be resolved already.
 // Newly created memory buffers are owned by this driver.
 void LinkerDriver::addFile(StringRef Path) {
@@ -139,13 +118,20 @@ void LinkerDriver::addFile(StringRef Pat
     readLinkerScript(MBRef);
     return;
   case file_magic::archive:
-    Symtab.addFile(make_unique<ArchiveFile>(MBRef));
+    if (WholeArchive) {
+      auto File = make_unique<ArchiveFile>(MBRef);
+      for (MemoryBufferRef &MB : File->getMembers())
+        Files.push_back(createELFFile<ObjectFile>(MB));
+      OwningArchives.emplace_back(std::move(File));
+      return;
+    }
+    Files.push_back(make_unique<ArchiveFile>(MBRef));
     return;
   case file_magic::elf_shared_object:
-    Symtab.addFile(createELFInputFile<SharedFile>(MBRef));
+    Files.push_back(createELFFile<SharedFile>(MBRef));
     return;
   default:
-    Symtab.addFile(createELFInputFile<ObjectFile>(MBRef));
+    Files.push_back(createELFFile<ObjectFile>(MBRef));
   }
 }
 
@@ -156,12 +142,31 @@ getString(opt::InputArgList &Args, unsig
   return Default;
 }
 
-void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
+void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
   initSymbols();
 
-  // Parse command line options.
   opt::InputArgList Args = Parser.parse(ArgsArr);
+  createFiles(Args);
 
+  switch (Config->ElfKind) {
+  case ELF32LEKind:
+    link<ELF32LE>(Args);
+    return;
+  case ELF32BEKind:
+    link<ELF32BE>(Args);
+    return;
+  case ELF64LEKind:
+    link<ELF64LE>(Args);
+    return;
+  case ELF64BEKind:
+    link<ELF64BE>(Args);
+    return;
+  default:
+    error("-m or at least a .o file required");
+  }
+}
+
+void LinkerDriver::createFiles(opt::InputArgList &Args) {
   for (auto *Arg : Args.filtered(OPT_L))
     Config->InputSearchPaths.push_back(Arg->getValue());
 
@@ -211,17 +216,51 @@ void LinkerDriver::link(ArrayRef<const c
       Config->Static = false;
       break;
     case OPT_whole_archive:
-      Config->WholeArchive = true;
+      WholeArchive = true;
       break;
     case OPT_no_whole_archive:
-      Config->WholeArchive = false;
+      WholeArchive = false;
       break;
     }
   }
 
-  if (Symtab.getObjectFiles().empty())
+  if (Files.empty())
     error("no input files.");
 
+  // Set machine type if -m is not given.
+  if (Config->ElfKind == ELFNoneKind) {
+    for (std::unique_ptr<InputFile> &File : Files) {
+      auto *F = dyn_cast<ELFFileBase>(File.get());
+      if (!F)
+        continue;
+      Config->ElfKind = F->getELFKind();
+      Config->EMachine = F->getEMachine();
+      break;
+    }
+  }
+
+  // Check if all files are for the same machine type.
+  for (std::unique_ptr<InputFile> &File : Files) {
+    auto *F = dyn_cast<ELFFileBase>(File.get());
+    if (!F)
+      continue;
+    if (F->getELFKind() == Config->ElfKind &&
+        F->getEMachine() == Config->EMachine)
+      continue;
+    StringRef A = F->getName();
+    StringRef B = Files[0]->getName();
+    if (auto *Arg = Args.getLastArg(OPT_m))
+      B = Arg->getValue();
+    error(A + " is incompatible with " + B);
+  }
+}
+
+template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
+  SymbolTable<ELFT> Symtab;
+
+  for (std::unique_ptr<InputFile> &F : Files)
+    Symtab.addFile(std::move(F));
+
   for (auto *Arg : Args.filtered(OPT_undefined))
     Symtab.addUndefinedSym(Arg->getValue());
 
@@ -229,5 +268,5 @@ void LinkerDriver::link(ArrayRef<const c
     Config->OutputFile = "a.out";
 
   // Write the result to the file.
-  writeResult(&Symtab);
+  writeResult<ELFT>(&Symtab);
 }

Modified: lld/trunk/ELF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.h?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.h (original)
+++ lld/trunk/ELF/Driver.h Fri Oct  9 16:07:25 2015
@@ -34,15 +34,20 @@ private:
 
 class LinkerDriver {
 public:
-  void link(ArrayRef<const char *> Args);
+  void main(ArrayRef<const char *> Args);
+  void createFiles(llvm::opt::InputArgList &Args);
+  template <class ELFT> void link(llvm::opt::InputArgList &Args);
+
   void addFile(StringRef Path);
 
 private:
   template <template <class> class T>
   std::unique_ptr<ELFFileBase> createELFInputFile(MemoryBufferRef MB);
 
-  SymbolTable Symtab;
   ArgParser Parser;
+  bool WholeArchive = false;
+  std::vector<std::unique_ptr<InputFile>> Files;
+  std::vector<std::unique_ptr<ArchiveFile>> OwningArchives;
   std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
 };
 

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Fri Oct  9 16:07:25 2015
@@ -232,7 +232,7 @@ template <class ELFT> void HashTableSect
 }
 
 template <class ELFT>
-DynamicSection<ELFT>::DynamicSection(SymbolTable &SymTab)
+DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab)
     : OutputSectionBase<ELFT::Is64Bits>(".dynamic", llvm::ELF::SHT_DYNAMIC,
                                         llvm::ELF::SHF_ALLOC |
                                             llvm::ELF::SHF_WRITE),
@@ -278,7 +278,7 @@ template <class ELFT> void DynamicSectio
   if (FiniArraySec)
     NumEntries += 2;
 
-  for (const std::unique_ptr<SharedFileBase> &F : SymTab.getSharedFiles()) {
+  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) {
     Out<ELFT>::DynStrTab->add(F->getSoName());
     ++NumEntries;
   }
@@ -355,7 +355,7 @@ template <class ELFT> void DynamicSectio
   WriteArray(DT_INIT_ARRAY, DT_INIT_ARRAYSZ, InitArraySec);
   WriteArray(DT_FINI_ARRAY, DT_FINI_ARRAYSZ, FiniArraySec);
 
-  for (const std::unique_ptr<SharedFileBase> &F : SymTab.getSharedFiles())
+  for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
     WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->getFileOff(F->getSoName()));
 
   if (InitSym)
@@ -521,7 +521,7 @@ bool lld::elf2::shouldKeepInSymtab(const
 
 template <class ELFT>
 SymbolTableSection<ELFT>::SymbolTableSection(
-    SymbolTable &Table, StringTableSection<ELFT::Is64Bits> &StrTabSec)
+    SymbolTable<ELFT> &Table, StringTableSection<ELFT::Is64Bits> &StrTabSec)
     : OutputSectionBase<ELFT::Is64Bits>(
           StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
           StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM : llvm::ELF::SHT_SYMTAB,
@@ -563,14 +563,13 @@ template <class ELFT>
 void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
   // Iterate over all input object files to copy their local symbols
   // to the output symbol table pointed by Buf.
-  for (const std::unique_ptr<ObjectFileBase> &FileB : Table.getObjectFiles()) {
-    auto &File = cast<ObjectFile<ELFT>>(*FileB);
-    Elf_Sym_Range Syms = File.getLocalSymbols();
+  for (const std::unique_ptr<ObjectFile<ELFT>> &File : Table.getObjectFiles()) {
+    Elf_Sym_Range Syms = File->getLocalSymbols();
     for (const Elf_Sym &Sym : Syms) {
-      ErrorOr<StringRef> SymNameOrErr = Sym.getName(File.getStringTable());
+      ErrorOr<StringRef> SymNameOrErr = Sym.getName(File->getStringTable());
       error(SymNameOrErr);
       StringRef SymName = *SymNameOrErr;
-      if (!shouldKeepInSymtab<ELFT>(File, SymName, Sym))
+      if (!shouldKeepInSymtab<ELFT>(*File, SymName, Sym))
         continue;
 
       auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
@@ -584,9 +583,9 @@ void SymbolTableSection<ELFT>::writeLoca
         ESym->st_shndx = SHN_ABS;
       } else {
         if (SecIndex == SHN_XINDEX)
-          SecIndex = File.getObj().getExtendedSymbolTableIndex(
-              &Sym, File.getSymbolTable(), File.getSymbolTableShndx());
-        ArrayRef<InputSection<ELFT> *> Sections = File.getSections();
+          SecIndex = File->getObj().getExtendedSymbolTableIndex(
+              &Sym, File->getSymbolTable(), File->getSymbolTableShndx());
+        ArrayRef<InputSection<ELFT> *> Sections = File->getSections();
         const InputSection<ELFT> *Section = Sections[SecIndex];
         const OutputSection<ELFT> *OutSec = Section->getOutputSection();
         ESym->st_shndx = OutSec->getSectionIndex();

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Fri Oct  9 16:07:25 2015
@@ -23,7 +23,7 @@ namespace lld {
 namespace elf2 {
 
 class SymbolBody;
-class SymbolTable;
+template <class ELFT> class SymbolTable;
 template <class ELFT> class SymbolTableSection;
 template <bool Is64Bits> class StringTableSection;
 template <class ELFT> class InputSection;
@@ -146,7 +146,7 @@ public:
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
   typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
-  SymbolTableSection(SymbolTable &Table,
+  SymbolTableSection(SymbolTable<ELFT> &Table,
                      StringTableSection<ELFT::Is64Bits> &StrTabSec);
 
   void finalize() override;
@@ -159,7 +159,7 @@ private:
   void writeLocalSymbols(uint8_t *&Buf);
   void writeGlobalSymbols(uint8_t *&Buf);
 
-  SymbolTable &Table;
+  SymbolTable<ELFT> &Table;
   StringTableSection<ELFT::Is64Bits> &StrTabSec;
   unsigned NumVisible = 0;
   unsigned NumLocals = 0;
@@ -265,7 +265,7 @@ class DynamicSection final : public Outp
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Dyn Elf_Dyn;
 
 public:
-  DynamicSection(SymbolTable &SymTab);
+  DynamicSection(SymbolTable<ELFT> &SymTab);
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
 
@@ -274,7 +274,7 @@ public:
   OutputSection<ELFT> *FiniArraySec = nullptr;
 
 private:
-  SymbolTable &SymTab;
+  SymbolTable<ELFT> &SymTab;
   const ELFSymbolBody<ELFT> *InitSym = nullptr;
   const ELFSymbolBody<ELFT> *FiniSym = nullptr;
 };

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Fri Oct  9 16:07:25 2015
@@ -20,22 +20,17 @@ using namespace llvm::ELF;
 using namespace lld;
 using namespace lld::elf2;
 
-SymbolTable::SymbolTable() {}
+template <class ELFT> SymbolTable<ELFT>::SymbolTable() {}
 
-bool SymbolTable::shouldUseRela() const {
+template <class ELFT> bool SymbolTable<ELFT>::shouldUseRela() const {
   ELFKind K = getFirstELF()->getELFKind();
   return K == ELF64LEKind || K == ELF64BEKind;
 }
 
-void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
+template <class ELFT>
+void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
   if (auto *AF = dyn_cast<ArchiveFile>(File.get())) {
-    File.release();
-    ArchiveFiles.emplace_back(AF);
-    if (Config->WholeArchive) {
-      for (MemoryBufferRef &MBRef : AF->getMembers())
-        addFile(createELFFile<ObjectFile>(MBRef));
-      return;
-    }
+    ArchiveFiles.emplace_back(std::move(File));
     AF->parse();
     for (Lazy &Sym : AF->getLazySymbols())
       addLazy(&Sym);
@@ -72,54 +67,36 @@ static TargetInfo *createTarget(uint16_t
   error("Unknown target machine");
 }
 
-void SymbolTable::addUndefinedSym(StringRef Name) {
-  switch (getFirstELF()->getELFKind()) {
-  case ELF32LEKind:
-    addUndefinedSym<ELF32LE>(Name);
-    break;
-  case ELF32BEKind:
-    addUndefinedSym<ELF32BE>(Name);
-    break;
-  case ELF64LEKind:
-    addUndefinedSym<ELF64LE>(Name);
-    break;
-  case ELF64BEKind:
-    addUndefinedSym<ELF64BE>(Name);
-    break;
-  default:
-    llvm_unreachable("Invalid kind");
-  }
-}
-
-template <class ELFT> void SymbolTable::addUndefinedSym(StringRef Name) {
-  resolve<ELFT>(new (Alloc) Undefined<ELFT>(Name, Undefined<ELFT>::Optional));
+template <class ELFT> void SymbolTable<ELFT>::addUndefinedSym(StringRef Name) {
+  resolve(new (Alloc) Undefined<ELFT>(Name, Undefined<ELFT>::Optional));
 }
 
 template <class ELFT>
-void SymbolTable::addSyntheticSym(StringRef Name, OutputSection<ELFT> &Section,
-                                  typename ELFFile<ELFT>::uintX_t Value) {
+void SymbolTable<ELFT>::addSyntheticSym(StringRef Name,
+                                        OutputSection<ELFT> &Section,
+                                        typename ELFFile<ELFT>::uintX_t Value) {
   typedef typename DefinedSynthetic<ELFT>::Elf_Sym Elf_Sym;
   auto ESym = new (Alloc) Elf_Sym;
   memset(ESym, 0, sizeof(Elf_Sym));
   ESym->st_value = Value;
   auto Sym = new (Alloc) DefinedSynthetic<ELFT>(Name, *ESym, Section);
-  resolve<ELFT>(Sym);
+  resolve(Sym);
 }
 
-template <class ELFT> void SymbolTable::addIgnoredSym(StringRef Name) {
+template <class ELFT> void SymbolTable<ELFT>::addIgnoredSym(StringRef Name) {
   auto Sym = new (Alloc)
       DefinedAbsolute<ELFT>(Name, DefinedAbsolute<ELFT>::IgnoreUndef);
-  resolve<ELFT>(Sym);
+  resolve(Sym);
 }
 
-template <class ELFT> void SymbolTable::init(uint16_t EMachine) {
+template <class ELFT> void SymbolTable<ELFT>::init(uint16_t EMachine) {
   Target.reset(createTarget(EMachine));
   if (Config->Shared)
     return;
   EntrySym = new (Alloc) Undefined<ELFT>(
       Config->Entry.empty() ? Target->getDefaultEntry() : Config->Entry,
       Undefined<ELFT>::Required);
-  resolve<ELFT>(EntrySym);
+  resolve(EntrySym);
 
   // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol is magical
   // and is used to produce a R_386_GOTPC relocation.
@@ -133,52 +110,34 @@ template <class ELFT> void SymbolTable::
   // an undefined symbol in the .o files.
   // Given that the symbol is effectively unused, we just create a dummy
   // hidden one to avoid the undefined symbol error.
-  addIgnoredSym<ELFT>("_GLOBAL_OFFSET_TABLE_");
+  addIgnoredSym("_GLOBAL_OFFSET_TABLE_");
 }
 
-template <class ELFT> void SymbolTable::addELFFile(ELFFileBase *File) {
+template <class ELFT> void SymbolTable<ELFT>::addELFFile(ELFFileBase *File) {
   const ELFFileBase *Old = getFirstELF();
-  if (auto *O = dyn_cast<ObjectFileBase>(File))
+  if (auto *O = dyn_cast<ObjectFile<ELFT>>(File))
     ObjectFiles.emplace_back(O);
   else if (auto *S = dyn_cast<SharedFile<ELFT>>(File))
     SharedFiles.emplace_back(S);
 
   if (!Old)
-    init<ELFT>(File->getEMachine());
+    init(File->getEMachine());
 
   if (auto *O = dyn_cast<ObjectFileBase>(File)) {
     for (SymbolBody *Body : O->getSymbols())
-      resolve<ELFT>(Body);
+      resolve(Body);
   }
 
   if (auto *S = dyn_cast<SharedFile<ELFT>>(File)) {
     for (SharedSymbol<ELFT> &Body : S->getSharedSymbols())
-      resolve<ELFT>(&Body);
-  }
-}
-
-void SymbolTable::addELFFile(ELFFileBase *File) {
-  switch (File->getELFKind()) {
-  case ELF32LEKind:
-    addELFFile<ELF32LE>(File);
-    break;
-  case ELF32BEKind:
-    addELFFile<ELF32BE>(File);
-    break;
-  case ELF64LEKind:
-    addELFFile<ELF64LE>(File);
-    break;
-  case ELF64BEKind:
-    addELFFile<ELF64BE>(File);
-    break;
-  default:
-    llvm_unreachable("Invalid kind");
+      resolve(&Body);
   }
 }
 
 template <class ELFT>
-void SymbolTable::reportConflict(const Twine &Message, const SymbolBody &Old,
-                                 const SymbolBody &New, bool Warning) {
+void SymbolTable<ELFT>::reportConflict(const Twine &Message,
+                                       const SymbolBody &Old,
+                                       const SymbolBody &New, bool Warning) {
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
 
@@ -187,13 +146,12 @@ void SymbolTable::reportConflict(const T
   ELFFileBase *OldFile = nullptr;
   ELFFileBase *NewFile = nullptr;
 
-  for (const std::unique_ptr<ObjectFileBase> &F : ObjectFiles) {
-    const auto &File = cast<ObjectFile<ELFT>>(*F);
-    Elf_Sym_Range Syms = File.getObj().symbols(File.getSymbolTable());
+  for (const std::unique_ptr<ObjectFile<ELFT>> &File : ObjectFiles) {
+    Elf_Sym_Range Syms = File->getObj().symbols(File->getSymbolTable());
     if (&OldE > Syms.begin() && &OldE < Syms.end())
-      OldFile = F.get();
+      OldFile = File.get();
     if (&NewE > Syms.begin() && &NewE < Syms.end())
-      NewFile = F.get();
+      NewFile = File.get();
   }
 
   std::string Msg = (Message + ": " + Old.getName() + " in " +
@@ -207,7 +165,7 @@ void SymbolTable::reportConflict(const T
 
 // This function resolves conflicts if there's an existing symbol with
 // the same name. Decisions are made based on symbol type.
-template <class ELFT> void SymbolTable::resolve(SymbolBody *New) {
+template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
   Symbol *Sym = insert(New);
   if (Sym->Body == New)
     return;
@@ -233,8 +191,7 @@ template <class ELFT> void SymbolTable::
   }
 
   if (New->isTLS() != Existing->isTLS())
-    reportConflict<ELFT>("TLS attribute mismatch for symbol", *Existing, *New,
-                         false);
+    reportConflict("TLS attribute mismatch for symbol", *Existing, *New, false);
 
   // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
   // equivalent (conflicting), or more preferable, respectively.
@@ -242,11 +199,11 @@ template <class ELFT> void SymbolTable::
   if (comp < 0)
     Sym->Body = New;
   else if (comp == 0)
-    reportConflict<ELFT>("duplicate symbol", *Existing, *New,
-                         Config->AllowMultipleDefinition);
+    reportConflict("duplicate symbol", *Existing, *New,
+                   Config->AllowMultipleDefinition);
 }
 
-Symbol *SymbolTable::insert(SymbolBody *New) {
+template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
   // Find an existing Symbol or create and insert a new one.
   StringRef Name = New->getName();
   Symbol *&Sym = Symtab[Name];
@@ -259,7 +216,7 @@ Symbol *SymbolTable::insert(SymbolBody *
   return Sym;
 }
 
-void SymbolTable::addLazy(Lazy *New) {
+template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *New) {
   Symbol *Sym = insert(New);
   if (Sym->Body == New)
     return;
@@ -284,7 +241,7 @@ void SymbolTable::addLazy(Lazy *New) {
   addMemberFile(New);
 }
 
-void SymbolTable::addMemberFile(Lazy *Body) {
+template <class ELFT> void SymbolTable<ELFT>::addMemberFile(Lazy *Body) {
   std::unique_ptr<InputFile> File = Body->getMember();
 
   // getMember returns nullptr if the member was already read from the library.
@@ -294,20 +251,7 @@ void SymbolTable::addMemberFile(Lazy *Bo
   addFile(std::move(File));
 }
 
-namespace lld {
-namespace elf2 {
-template void SymbolTable::addSyntheticSym(StringRef, OutputSection<ELF32LE> &,
-                                           ELFFile<ELF32LE>::uintX_t);
-template void SymbolTable::addSyntheticSym(StringRef, OutputSection<ELF32BE> &,
-                                           ELFFile<ELF32BE>::uintX_t);
-template void SymbolTable::addSyntheticSym(StringRef, OutputSection<ELF64LE> &,
-                                           ELFFile<ELF64LE>::uintX_t);
-template void SymbolTable::addSyntheticSym(StringRef, OutputSection<ELF64BE> &,
-                                           ELFFile<ELF64BE>::uintX_t);
-
-template void SymbolTable::addIgnoredSym<ELF32LE>(StringRef);
-template void SymbolTable::addIgnoredSym<ELF32BE>(StringRef);
-template void SymbolTable::addIgnoredSym<ELF64LE>(StringRef);
-template void SymbolTable::addIgnoredSym<ELF64BE>(StringRef);
-}
-}
+template class lld::elf2::SymbolTable<ELF32LE>;
+template class lld::elf2::SymbolTable<ELF32BE>;
+template class lld::elf2::SymbolTable<ELF64LE>;
+template class lld::elf2::SymbolTable<ELF64BE>;

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Fri Oct  9 16:07:25 2015
@@ -27,7 +27,7 @@ struct Symbol;
 // an undefined symbol. Or, if there's a conflict between a lazy and a
 // undefined, it'll read an archive member to read a real definition
 // to replace the lazy symbol. The logic is implemented in resolve().
-class SymbolTable {
+template <class ELFT> class SymbolTable {
 public:
   SymbolTable();
 
@@ -47,11 +47,11 @@ public:
     return Symtab;
   }
 
-  const std::vector<std::unique_ptr<ObjectFileBase>> &getObjectFiles() const {
+  const std::vector<std::unique_ptr<ObjectFile<ELFT>>> &getObjectFiles() const {
     return ObjectFiles;
   }
 
-  const std::vector<std::unique_ptr<SharedFileBase>> &getSharedFiles() const {
+  const std::vector<std::unique_ptr<SharedFile<ELFT>>> &getSharedFiles() const {
     return SharedFiles;
   }
 
@@ -63,27 +63,22 @@ public:
 
   void addUndefinedSym(StringRef Name);
 
-  template <class ELFT>
   void addSyntheticSym(StringRef Name, OutputSection<ELFT> &Section,
                        typename llvm::object::ELFFile<ELFT>::uintX_t Value);
 
-  template <class ELFT> void addIgnoredSym(StringRef Name);
+  void addIgnoredSym(StringRef Name);
 
 private:
   Symbol *insert(SymbolBody *New);
-  template <class ELFT> void addELFFile(ELFFileBase *File);
   void addELFFile(ELFFileBase *File);
   void addLazy(Lazy *New);
   void addMemberFile(Lazy *Body);
-  template <class ELFT> void addUndefinedSym(StringRef Name);
-
-  template <class ELFT> void init(uint16_t EMachine);
-  template <class ELFT> void resolve(SymbolBody *Body);
-  template <class ELFT>
+  void init(uint16_t EMachine);
+  void resolve(SymbolBody *Body);
   void reportConflict(const Twine &Message, const SymbolBody &Old,
                       const SymbolBody &New, bool Warning);
 
-  std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
+  std::vector<std::unique_ptr<InputFile>> ArchiveFiles;
 
   // The order the global symbols are in is not defined. We can use an arbitrary
   // order, but it has to be reproducible. That is true even when cross linking.
@@ -98,9 +93,9 @@ private:
   llvm::DenseSet<StringRef> Comdats;
 
   // The writer needs to infer the machine type from the object files.
-  std::vector<std::unique_ptr<ObjectFileBase>> ObjectFiles;
+  std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;
 
-  std::vector<std::unique_ptr<SharedFileBase>> SharedFiles;
+  std::vector<std::unique_ptr<SharedFile<ELFT>>> SharedFiles;
   llvm::DenseSet<StringRef> IncludedSoNames;
 
   SymbolBody *EntrySym = nullptr;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Oct  9 16:07:25 2015
@@ -71,7 +71,7 @@ public:
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
   typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
-  Writer(SymbolTable &S) : Symtab(S) {}
+  Writer(SymbolTable<ELFT> &S) : Symtab(S) {}
   void run();
 
 private:
@@ -101,7 +101,7 @@ private:
   unsigned getNumSections() const { return OutputSections.size() + 1; }
 
   llvm::BumpPtrAllocator PAlloc;
-  SymbolTable &Symtab;
+  SymbolTable<ELFT> &Symtab;
   std::vector<ProgramHeader<ELFT> *> PHDRs;
   ProgramHeader<ELFT> PhdrPHDR{PT_PHDR, PF_R, 0, 0};
   ProgramHeader<ELFT> FileHeaderPHDR{PT_LOAD, PF_R, 0, 0};
@@ -114,7 +114,7 @@ private:
 };
 } // anonymous namespace
 
-template <class ELFT> static void doWriteResult(SymbolTable *Symtab) {
+template <class ELFT> void lld::elf2::writeResult(SymbolTable<ELFT> *Symtab) {
   // Initialize output sections that are handled by Writer specially.
   // Don't reorder because the order of initialization matters.
   InterpSection<ELFT::Is64Bits> Interp;
@@ -143,25 +143,6 @@ template <class ELFT> static void doWrit
   Writer<ELFT>(*Symtab).run();
 }
 
-void lld::elf2::writeResult(SymbolTable *Symtab) {
-  switch (Symtab->getFirstELF()->getELFKind()) {
-  case ELF32LEKind:
-    doWriteResult<object::ELF32LE>(Symtab);
-    return;
-  case ELF32BEKind:
-    doWriteResult<object::ELF32BE>(Symtab);
-    return;
-  case ELF64LEKind:
-    doWriteResult<object::ELF64LE>(Symtab);
-    return;
-  case ELF64BEKind:
-    doWriteResult<object::ELF64BE>(Symtab);
-    return;
-  default:
-    llvm_unreachable("Invalid kind");
-  }
-}
-
 // The main function of the writer.
 template <class ELFT> void Writer<ELFT>::run() {
   if (!Config->DiscardAll)
@@ -260,7 +241,7 @@ void Writer<ELFT>::scanRelocs(const Inpu
 }
 
 template <class ELFT>
-static void reportUndefined(const SymbolTable &S, const SymbolBody &Sym) {
+static void reportUndefined(const SymbolTable<ELFT> &S, const SymbolBody &Sym) {
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
 
@@ -270,11 +251,10 @@ static void reportUndefined(const Symbol
   const Elf_Sym &SymE = cast<ELFSymbolBody<ELFT>>(Sym).Sym;
   ELFFileBase *SymFile = nullptr;
 
-  for (const std::unique_ptr<ObjectFileBase> &F : S.getObjectFiles()) {
-    const auto &File = cast<ObjectFile<ELFT>>(*F);
-    Elf_Sym_Range Syms = File.getObj().symbols(File.getSymbolTable());
+  for (const std::unique_ptr<ObjectFile<ELFT>> &File : S.getObjectFiles()) {
+    Elf_Sym_Range Syms = File->getObj().symbols(File->getSymbolTable());
     if (&SymE > Syms.begin() && &SymE < Syms.end())
-      SymFile = F.get();
+      SymFile = File.get();
   }
 
   std::string Message = "undefined symbol: " + Sym.getName().str();
@@ -289,13 +269,12 @@ static void reportUndefined(const Symbol
 // Local symbols are not in the linker's symbol table. This function scans
 // each object file's symbol table to copy local symbols to the output.
 template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
-  for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.getObjectFiles()) {
-    auto &File = cast<ObjectFile<ELFT>>(*FileB);
-    for (const Elf_Sym &Sym : File.getLocalSymbols()) {
-      ErrorOr<StringRef> SymNameOrErr = Sym.getName(File.getStringTable());
+  for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
+    for (const Elf_Sym &Sym : F->getLocalSymbols()) {
+      ErrorOr<StringRef> SymNameOrErr = Sym.getName(F->getStringTable());
       error(SymNameOrErr);
       StringRef SymName = *SymNameOrErr;
-      if (!shouldKeepInSymtab<ELFT>(File, SymName, Sym))
+      if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym))
         continue;
       Out<ELFT>::SymTab->addSymbol(SymName, true);
     }
@@ -387,18 +366,17 @@ template <class ELFT> void Writer<ELFT>:
   for (StringRef Name :
        {"__preinit_array_start", "__preinit_array_end", "__init_array_start",
         "__init_array_end", "__fini_array_start", "__fini_array_end"})
-    Symtab.addIgnoredSym<ELFT>(Name);
+    Symtab.addIgnoredSym(Name);
 
   // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For
   // static linking the linker is required to optimize away any references to
   // __tls_get_addr, so it's not defined anywhere. Create a hidden definition
   // to avoid the undefined symbol error.
   if (!isOutputDynamic())
-    Symtab.addIgnoredSym<ELFT>("__tls_get_addr");
+    Symtab.addIgnoredSym("__tls_get_addr");
 
-  for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.getObjectFiles()) {
-    auto &File = cast<ObjectFile<ELFT>>(*FileB);
-    for (InputSection<ELFT> *C : File.getSections()) {
+  for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
+    for (InputSection<ELFT> *C : F->getSections()) {
       if (!C || C == &InputSection<ELFT>::Discarded)
         continue;
       const Elf_Shdr *H = C->getSectionHdr();
@@ -425,8 +403,8 @@ template <class ELFT> void Writer<ELFT>:
   auto AddStartEnd = [&](StringRef Start, StringRef End,
                          OutputSection<ELFT> *OS) {
     if (OS) {
-      Symtab.addSyntheticSym<ELFT>(Start, *OS, 0);
-      Symtab.addSyntheticSym<ELFT>(End, *OS, OS->getSize());
+      Symtab.addSyntheticSym(Start, *OS, 0);
+      Symtab.addSyntheticSym(End, *OS, OS->getSize());
     }
   };
 
@@ -651,3 +629,8 @@ template <class ELFT> void Writer<ELFT>:
   for (OutputSectionBase<ELFT::Is64Bits> *Sec : OutputSections)
     Sec->writeTo(Buf + Sec->getFileOff());
 }
+
+template void lld::elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
+template void lld::elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
+template void lld::elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
+template void lld::elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);

Modified: lld/trunk/ELF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.h?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.h (original)
+++ lld/trunk/ELF/Writer.h Fri Oct  9 16:07:25 2015
@@ -13,10 +13,9 @@
 namespace lld {
 namespace elf2 {
 
-class SymbolTable;
-
-void writeResult(SymbolTable *Symtab);
+template <class ELFT> class SymbolTable;
 
+template <class ELFT> void writeResult(SymbolTable<ELFT> *Symtab);
 }
 }
 

Modified: lld/trunk/test/elf2/incompatible.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/incompatible.s?rev=249902&r1=249901&r2=249902&view=diff
==============================================================================
--- lld/trunk/test/elf2/incompatible.s (original)
+++ lld/trunk/test/elf2/incompatible.s Fri Oct  9 16:07:25 2015
@@ -25,22 +25,22 @@
 
 // RUN: not ld.lld2 -m elf64ppc %ta.o -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=A-ONLY %s
-// A-ONLY: a.o is incompatible with target architecture
+// A-ONLY: a.o is incompatible with elf64ppc
 
 // RUN: not ld.lld2 -m elf64ppc %tb.o -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=B-ONLY %s
-// B-ONLY: b.o is incompatible with target architecture
+// B-ONLY: b.o is incompatible with elf64ppc
 
 // RUN: not ld.lld2 -m elf64ppc %tc.o -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=C-ONLY %s
-// C-ONLY: c.o is incompatible with target architecture
+// C-ONLY: c.o is incompatible with elf64ppc
 
 // RUN: not ld.lld2 -m elf_i386 %tc.o %ti686.so -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=C-AND-SO-I386 %s
-// C-AND-SO-I386: c.o is incompatible with target architecture
+// C-AND-SO-I386: c.o is incompatible with elf_i386
 
 // RUN: not ld.lld2 -m elf_i386 %ti686.so %tc.o -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=SO-AND-C-I386 %s
-// SO-AND-C-I386: c.o is incompatible with {{.*}}i686.so
+// SO-AND-C-I386: c.o is incompatible with elf_i386
 
 // REQUIRES: x86,arm

Added: lld/trunk/test/elf2/no-obj.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/no-obj.s?rev=249902&view=auto
==============================================================================
--- lld/trunk/test/elf2/no-obj.s (added)
+++ lld/trunk/test/elf2/no-obj.s Fri Oct  9 16:07:25 2015
@@ -0,0 +1,8 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-ar rcs %t.a %t.o
+// RUN: not ld.lld2 -o %t2 -u _start %t.a 2>&1 | FileCheck %s
+
+// CHECK: -m or at least a .o file required
+
+.global _start
+_start:




More information about the llvm-commits mailing list