Merge ELFFileBase::{initSymtab,parseHeader} as ELFFileBase:init. NFC.

This patch simplifies ELFFile instance initialization by merging
two similar functions into a single function and call it from the
ctor.

llvm-svn: 361789
This commit is contained in:
Rui Ueyama 2019-05-28 05:17:21 +00:00
parent 50d502826b
commit 92069605bf
2 changed files with 71 additions and 79 deletions

View 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;
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];
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");
}
}
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())
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::init() {
using Elf_Shdr = typename ELFT::Shdr;
using Elf_Sym = typename ELFT::Sym;
// 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];
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");
this->ELFSyms = reinterpret_cast<const void *>(ELFSyms.data());
this->NumELFSyms = ELFSyms.size();
StringTable =
CHECK(getObj<ELFT>().getStringTableForSymtab(*Symtab, Sections), this);
}
template <class ELFT>
ObjFile<ELFT>::ObjFile(MemoryBufferRef M, StringRef ArchiveName)
: ELFFileBase(ObjKind, M) {
parseHeader<ELFT>();
this->ArchiveName = ArchiveName;
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 =

View 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.