Merge ELFFileBase::{initSymtab,parseHeader} as ELFFileBase:init. NFC.
authorRui Ueyama <ruiu@google.com>
Tue, 28 May 2019 05:17:21 +0000 (05:17 +0000)
committerRui Ueyama <ruiu@google.com>
Tue, 28 May 2019 05:17:21 +0000 (05:17 +0000)
This patch simplifies ELFFile instance initialization by merging
two similar functions into a single function and call it from the
ctor.

llvm-svn: 361789

lld/ELF/InputFiles.cpp
lld/ELF/InputFiles.h

index 0581f35..2b89533 100644 (file)
@@ -368,39 +368,66 @@ std::string lld::toString(const InputFile *F) {
   return F->ToStringCache;
 }
 
-ELFFileBase::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) {}
+ELFFileBase::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) {
+  EKind = getELFKind(MB, "");
 
-template <class ELFT> void ELFFileBase::parseHeader() {
-  if (ELFT::TargetEndianness == support::little)
-    EKind = ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind;
-  else
-    EKind = ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind;
+  switch (EKind) {
+  case ELF32LEKind:
+    init<ELF32LE>();
+    break;
+  case ELF32BEKind:
+    init<ELF32BE>();
+    break;
+  case ELF64LEKind:
+    init<ELF64LE>();
+    break;
+  case ELF64BEKind:
+    init<ELF64BE>();
+    break;
+  default:
+    llvm_unreachable("getELFKind");
+  }
+}
 
-  EMachine = getObj<ELFT>().getHeader()->e_machine;
-  OSABI = getObj<ELFT>().getHeader()->e_ident[llvm::ELF::EI_OSABI];
-  ABIVersion = getObj<ELFT>().getHeader()->e_ident[llvm::ELF::EI_ABIVERSION];
+template <typename Elf_Shdr>
+static const Elf_Shdr *findSection(ArrayRef<Elf_Shdr> Sections, uint32_t Type) {
+  for (const Elf_Shdr &Sec : Sections)
+    if (Sec.sh_type == Type)
+      return &Sec;
+  return nullptr;
 }
 
-template <class ELFT>
-void ELFFileBase::initSymtab(ArrayRef<typename ELFT::Shdr> Sections,
-                             const typename ELFT::Shdr *Symtab) {
-  FirstGlobal = Symtab->sh_info;
-  ArrayRef<typename ELFT::Sym> ELFSyms =
-      CHECK(getObj<ELFT>().symbols(Symtab), this);
-  if (FirstGlobal == 0 || FirstGlobal > ELFSyms.size())
-    fatal(toString(this) + ": invalid sh_info in symbol table");
-  this->ELFSyms = reinterpret_cast<const void *>(ELFSyms.data());
-  this->NumELFSyms = ELFSyms.size();
+template <class ELFT> void ELFFileBase::init() {
+  using Elf_Shdr = typename ELFT::Shdr;
+  using Elf_Sym = typename ELFT::Sym;
 
-  StringTable =
-      CHECK(getObj<ELFT>().getStringTableForSymtab(*Symtab, Sections), this);
-}
+  // Initialize trivial attributes.
+  const ELFFile<ELFT> &Obj = getObj<ELFT>();
+  EMachine = Obj.getHeader()->e_machine;
+  OSABI = Obj.getHeader()->e_ident[llvm::ELF::EI_OSABI];
+  ABIVersion = Obj.getHeader()->e_ident[llvm::ELF::EI_ABIVERSION];
 
-template <class ELFT>
-ObjFile<ELFT>::ObjFile(MemoryBufferRef M, StringRef ArchiveName)
-    : ELFFileBase(ObjKind, M) {
-  parseHeader<ELFT>();
-  this->ArchiveName = ArchiveName;
+  ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this);
+
+  // Find a symbol table.
+  bool IsDSO =
+      (identify_magic(MB.getBuffer()) == file_magic::elf_shared_object);
+  const Elf_Shdr *SymtabSec =
+      findSection(Sections, IsDSO ? SHT_DYNSYM : SHT_SYMTAB);
+
+  if (!SymtabSec)
+    return;
+
+  // Initialize members corresponding to a symbol table.
+  FirstGlobal = SymtabSec->sh_info;
+
+  ArrayRef<Elf_Sym> ESyms = CHECK(Obj.symbols(SymtabSec), this);
+  if (FirstGlobal == 0 || FirstGlobal > ESyms.size())
+    fatal(toString(this) + ": invalid sh_info in symbol table");
+
+  ELFSyms = reinterpret_cast<const void *>(ESyms.data());
+  NumELFSyms = ESyms.size();
+  StringTable = CHECK(Obj.getStringTableForSymtab(*SymtabSec, Sections), this);
 }
 
 template <class ELFT>
@@ -439,12 +466,6 @@ void ObjFile<ELFT>::parse(
 template <class ELFT>
 StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
                                               const Elf_Shdr &Sec) {
-  // Group signatures are stored as symbol names in object files.
-  // sh_info contains a symbol index, so we fetch a symbol and read its name.
-  if (this->getELFSyms<ELFT>().empty())
-    this->initSymtab<ELFT>(
-        Sections, CHECK(object::getSection<ELFT>(Sections, Sec.sh_link), this));
-
   const Elf_Sym *Sym =
       CHECK(object::getSymbol<ELFT>(this->getELFSyms<ELFT>(), Sec.sh_info), this);
   StringRef Signature = CHECK(Sym->getName(this->StringTable), this);
@@ -515,15 +536,8 @@ template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
 // When the option is given, we link "just symbols". The section table is
 // initialized with null pointers.
 template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
-  ArrayRef<Elf_Shdr> ObjSections = CHECK(this->getObj().sections(), this);
-  this->Sections.resize(ObjSections.size());
-
-  for (const Elf_Shdr &Sec : ObjSections) {
-    if (Sec.sh_type != SHT_SYMTAB)
-      continue;
-    this->initSymtab<ELFT>(ObjSections, &Sec);
-    return;
-  }
+  ArrayRef<Elf_Shdr> Sections = CHECK(this->getObj().sections(), this);
+  this->Sections.resize(Sections.size());
 }
 
 // An ELF object file may contain a `.deplibs` section. If it exists, the
@@ -625,12 +639,10 @@ void ObjFile<ELFT>::initializeSections(
       }
       break;
     }
-    case SHT_SYMTAB:
-      this->initSymtab<ELFT>(ObjSections, &Sec);
-      break;
     case SHT_SYMTAB_SHNDX:
       ShndxTable = CHECK(Obj.getSHNDXTable(Sec, ObjSections), this);
       break;
+    case SHT_SYMTAB:
     case SHT_STRTAB:
     case SHT_NULL:
       break;
@@ -1066,27 +1078,6 @@ void ArchiveFile::fetch(const Archive::Symbol &Sym) {
 
 unsigned SharedFile::VernauxNum;
 
-SharedFile::SharedFile(MemoryBufferRef M, StringRef DefaultSoName)
-    : ELFFileBase(SharedKind, M), SoName(DefaultSoName),
-      IsNeeded(!Config->AsNeeded) {
-  switch (getELFKind(MB, "")) {
-  case ELF32LEKind:
-    parseHeader<ELF32LE>();
-    break;
-  case ELF32BEKind:
-    parseHeader<ELF32BE>();
-    break;
-  case ELF64LEKind:
-    parseHeader<ELF64LE>();
-    break;
-  case ELF64BEKind:
-    parseHeader<ELF64BE>();
-    break;
-  default:
-    llvm_unreachable("getELFKind");
-  }
-}
-
 // Parse the version definitions in the object file if present, and return a
 // vector whose nth element contains a pointer to the Elf_Verdef for version
 // identifier n. Version identifiers that are not definitions map to nullptr.
@@ -1165,9 +1156,6 @@ template <class ELFT> void SharedFile::parse() {
     switch (Sec.sh_type) {
     default:
       continue;
-    case SHT_DYNSYM:
-      this->initSymtab<ELFT>(Sections, &Sec);
-      break;
     case SHT_DYNAMIC:
       DynamicTags =
           CHECK(Obj.template getSectionContentsAsArray<Elf_Dyn>(&Sec), this);
@@ -1181,7 +1169,7 @@ template <class ELFT> void SharedFile::parse() {
     }
   }
 
-  if (VersymSec && this->getELFSyms<ELFT>().empty()) {
+  if (VersymSec && NumELFSyms == 0) {
     error("SHT_GNU_versym should be associated with symbol table");
     return;
   }
@@ -1221,7 +1209,7 @@ template <class ELFT> void SharedFile::parse() {
   // Parse ".gnu.version" section which is a parallel array for the symbol
   // table. If a given file doesn't have a ".gnu.version" section, we use
   // VER_NDX_GLOBAL.
-  size_t Size = this->getELFSyms<ELFT>().size() - this->FirstGlobal;
+  size_t Size = NumELFSyms - FirstGlobal;
   std::vector<uint32_t> Versyms(Size, VER_NDX_GLOBAL);
   if (VersymSec) {
     ArrayRef<Elf_Versym> Versym =
index a51ba64..e506b9e 100644 (file)
@@ -152,7 +152,6 @@ private:
 class ELFFileBase : public InputFile {
 public:
   ELFFileBase(Kind K, MemoryBufferRef M);
-  template <typename ELFT> void parseHeader();
   static bool classof(const InputFile *F) { return F->isElf(); }
 
   template <typename ELFT> llvm::object::ELFFile<ELFT> getObj() const {
@@ -170,13 +169,13 @@ public:
   }
 
 protected:
+  // Initializes this class's member variables.
+  template <typename ELFT> void init();
+
   const void *ELFSyms = nullptr;
   size_t NumELFSyms = 0;
   uint32_t FirstGlobal = 0;
   StringRef StringTable;
-  template <typename ELFT>
-  void initSymtab(ArrayRef<typename ELFT::Shdr> Sections,
-                  const typename ELFT::Shdr *Symtab);
 };
 
 // .o file.
@@ -198,7 +197,10 @@ public:
   ArrayRef<Symbol *> getLocalSymbols();
   ArrayRef<Symbol *> getGlobalSymbols();
 
-  ObjFile(MemoryBufferRef M, StringRef ArchiveName);
+  ObjFile(MemoryBufferRef M, StringRef ArchiveName) : ELFFileBase(ObjKind, M) {
+    this->ArchiveName = ArchiveName;
+  }
+
   void parse(llvm::DenseMap<llvm::CachedHashStringRef, const InputFile *>
                  &ComdatGroups);
 
@@ -345,6 +347,10 @@ public:
 // .so file.
 class SharedFile : public ELFFileBase {
 public:
+  SharedFile(MemoryBufferRef M, StringRef DefaultSoName)
+      : ELFFileBase(SharedKind, M), SoName(DefaultSoName),
+        IsNeeded(!Config->AsNeeded) {}
+
   // This is actually a vector of Elf_Verdef pointers.
   std::vector<const void *> Verdefs;
 
@@ -360,8 +366,6 @@ public:
 
   static bool classof(const InputFile *F) { return F->kind() == SharedKind; }
 
-  SharedFile(MemoryBufferRef M, StringRef DefaultSoName);
-
   template <typename ELFT> void parse();
 
   // Used for --no-allow-shlib-undefined.