diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -350,7 +350,7 @@ if (Type != R_MIPS_26 && Type != R_MIPS_PC26_S2 && Type != R_MICROMIPS_26_S1 && Type != R_MICROMIPS_PC26_S1) return false; - auto *F = dyn_cast_or_null>(File); + auto *F = dyn_cast_or_null>(File); if (!F) return false; // If current file has PIC code, LA25 stub is not required. diff --git a/lld/ELF/Arch/MipsArchTree.cpp b/lld/ELF/Arch/MipsArchTree.cpp --- a/lld/ELF/Arch/MipsArchTree.cpp +++ b/lld/ELF/Arch/MipsArchTree.cpp @@ -356,8 +356,8 @@ } template static bool isN32Abi(const InputFile *F) { - if (auto *EF = dyn_cast>(F)) - return EF->getObj().getHeader()->e_flags & EF_MIPS_ABI2; + if (auto *EF = dyn_cast(F)) + return EF->template getObj().getHeader()->e_flags & EF_MIPS_ABI2; return false; } diff --git a/lld/ELF/DWARF.cpp b/lld/ELF/DWARF.cpp --- a/lld/ELF/DWARF.cpp +++ b/lld/ELF/DWARF.cpp @@ -90,7 +90,7 @@ const ObjFile *File = Sec.getFile(); uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); - const typename ELFT::Sym &Sym = File->getELFSyms()[SymIndex]; + const typename ELFT::Sym &Sym = File->template getELFSyms()[SymIndex]; uint32_t SecIndex = File->getSectionIndex(Sym); // Broken debug info can point to a non-Defined symbol. diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -145,35 +145,38 @@ const Kind FileKind; }; -template class ELFFileBase : public InputFile { +class ELFFileBase : public InputFile { public: - using Elf_Shdr = typename ELFT::Shdr; - using Elf_Sym = typename ELFT::Sym; - using Elf_Word = typename ELFT::Word; - using Elf_Sym_Range = typename ELFT::SymRange; - ELFFileBase(Kind K, MemoryBufferRef M); + template void parseHeader(); static bool classof(const InputFile *F) { return F->isElf(); } - llvm::object::ELFFile getObj() const { + template llvm::object::ELFFile getObj() const { return check(llvm::object::ELFFile::create(MB.getBuffer())); } StringRef getStringTable() const { return StringTable; } - Elf_Sym_Range getGlobalELFSyms(); - Elf_Sym_Range getELFSyms() const { return ELFSyms; } + template typename ELFT::SymRange getELFSyms() const { + return typename ELFT::SymRange( + reinterpret_cast(ELFSyms), NumELFSyms); + } + template typename ELFT::SymRange getGlobalELFSyms() const { + return getELFSyms().slice(FirstGlobal); + } protected: - ArrayRef ELFSyms; + const void *ELFSyms = nullptr; + size_t NumELFSyms = 0; uint32_t FirstGlobal = 0; StringRef StringTable; - void initSymtab(ArrayRef Sections, const Elf_Shdr *Symtab); + template + void initSymtab(ArrayRef Sections, + const typename ELFT::Shdr *Symtab); }; // .o file. -template class ObjFile : public ELFFileBase { - using Base = ELFFileBase; +template class ObjFile : public ELFFileBase { using Elf_Rel = typename ELFT::Rel; using Elf_Rela = typename ELFT::Rela; using Elf_Sym = typename ELFT::Sym; @@ -185,7 +188,11 @@ const Elf_Shdr &Sec); public: - static bool classof(const InputFile *F) { return F->kind() == Base::ObjKind; } + static bool classof(const InputFile *F) { return F->kind() == ObjKind; } + + llvm::object::ELFFile getObj() const { + return this->ELFFileBase::getObj(); + } ArrayRef getLocalSymbols(); ArrayRef getGlobalSymbols(); @@ -321,8 +328,7 @@ }; // .so file. -template class SharedFile : public ELFFileBase { - using Base = ELFFileBase; +template class SharedFile : public ELFFileBase { using Elf_Dyn = typename ELFT::Dyn; using Elf_Shdr = typename ELFT::Shdr; using Elf_Sym = typename ELFT::Sym; @@ -338,9 +344,7 @@ std::vector DtNeeded; std::string SoName; - static bool classof(const InputFile *F) { - return F->kind() == Base::SharedKind; - } + static bool classof(const InputFile *F) { return F->kind() == SharedKind; } SharedFile(MemoryBufferRef M, StringRef DefaultSoName); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -241,45 +241,46 @@ return F->ToStringCache; } -template -ELFFileBase::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) { +ELFFileBase::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) {} + +template void ELFFileBase::parseHeader() { if (ELFT::TargetEndianness == support::little) EKind = ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind; else EKind = ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind; - EMachine = getObj().getHeader()->e_machine; - OSABI = getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI]; - ABIVersion = getObj().getHeader()->e_ident[llvm::ELF::EI_ABIVERSION]; + EMachine = getObj().getHeader()->e_machine; + OSABI = getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI]; + ABIVersion = getObj().getHeader()->e_ident[llvm::ELF::EI_ABIVERSION]; } template -typename ELFT::SymRange ELFFileBase::getGlobalELFSyms() { - return makeArrayRef(ELFSyms.begin() + FirstGlobal, ELFSyms.end()); -} - -template -void ELFFileBase::initSymtab(ArrayRef Sections, - const Elf_Shdr *Symtab) { +void ELFFileBase::initSymtab(ArrayRef Sections, + const typename ELFT::Shdr *Symtab) { FirstGlobal = Symtab->sh_info; - ELFSyms = CHECK(getObj().symbols(Symtab), this); + ArrayRef ELFSyms = + CHECK(getObj().symbols(Symtab), this); if (FirstGlobal == 0 || FirstGlobal > ELFSyms.size()) fatal(toString(this) + ": invalid sh_info in symbol table"); + this->ELFSyms = reinterpret_cast(ELFSyms.data()); + this->NumELFSyms = ELFSyms.size(); StringTable = - CHECK(getObj().getStringTableForSymtab(*Symtab, Sections), this); + CHECK(getObj().getStringTableForSymtab(*Symtab, Sections), this); } template ObjFile::ObjFile(MemoryBufferRef M, StringRef ArchiveName) - : ELFFileBase(Base::ObjKind, M) { + : ELFFileBase(ObjKind, M) { + parseHeader(); this->ArchiveName = ArchiveName; } template uint32_t ObjFile::getSectionIndex(const Elf_Sym &Sym) const { - return CHECK(this->getObj().getSectionIndex(&Sym, this->ELFSyms, SymtabSHNDX), - this); + return CHECK( + this->getObj().getSectionIndex(&Sym, getELFSyms(), SymtabSHNDX), + this); } template ArrayRef ObjFile::getLocalSymbols() { @@ -312,12 +313,12 @@ 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->ELFSyms.empty()) - this->initSymtab( + if (this->getELFSyms().empty()) + this->initSymtab( Sections, CHECK(object::getSection(Sections, Sec.sh_link), this)); const Elf_Sym *Sym = - CHECK(object::getSymbol(this->ELFSyms, Sec.sh_info), this); + CHECK(object::getSymbol(this->getELFSyms(), Sec.sh_info), this); StringRef Signature = CHECK(Sym->getName(this->StringTable), this); // As a special case, if a symbol is a section symbol and has no name, @@ -392,7 +393,7 @@ for (const Elf_Shdr &Sec : ObjSections) { if (Sec.sh_type != SHT_SYMTAB) continue; - this->initSymtab(ObjSections, &Sec); + this->initSymtab(ObjSections, &Sec); return; } } @@ -475,10 +476,10 @@ break; } case SHT_SYMTAB: - this->initSymtab(ObjSections, &Sec); + this->initSymtab(ObjSections, &Sec); break; case SHT_SYMTAB_SHNDX: - this->SymtabSHNDX = CHECK(Obj.getSHNDXTable(Sec, ObjSections), this); + SymtabSHNDX = CHECK(Obj.getSHNDXTable(Sec, ObjSections), this); break; case SHT_STRTAB: case SHT_NULL: @@ -678,12 +679,12 @@ } if (Sec.sh_type == SHT_RELA) { - ArrayRef Rels = CHECK(this->getObj().relas(&Sec), this); + ArrayRef Rels = CHECK(getObj().relas(&Sec), this); Target->FirstRelocation = Rels.begin(); Target->NumRelocations = Rels.size(); Target->AreRelocsRela = true; } else { - ArrayRef Rels = CHECK(this->getObj().rels(&Sec), this); + ArrayRef Rels = CHECK(getObj().rels(&Sec), this); Target->FirstRelocation = Rels.begin(); Target->NumRelocations = Rels.size(); Target->AreRelocsRela = false; @@ -771,19 +772,19 @@ template StringRef ObjFile::getSectionName(const Elf_Shdr &Sec) { - return CHECK(this->getObj().getSectionName(&Sec, SectionStringTable), this); + return CHECK(getObj().getSectionName(&Sec, SectionStringTable), this); } template void ObjFile::initializeSymbols() { - this->Symbols.reserve(this->ELFSyms.size()); - for (const Elf_Sym &Sym : this->ELFSyms) + this->Symbols.reserve(this->getELFSyms().size()); + for (const Elf_Sym &Sym : this->getELFSyms()) this->Symbols.push_back(createSymbol(&Sym)); } template Symbol *ObjFile::createSymbol(const Elf_Sym *Sym) { int Binding = Sym->getBinding(); - uint32_t SecIdx = this->getSectionIndex(*Sym); + uint32_t SecIdx = getSectionIndex(*Sym); if (SecIdx >= this->Sections.size()) fatal(toString(this) + ": invalid section index: " + Twine(SecIdx)); @@ -870,14 +871,16 @@ template SharedFile::SharedFile(MemoryBufferRef M, StringRef DefaultSoName) - : ELFFileBase(Base::SharedKind, M), SoName(DefaultSoName), - IsNeeded(!Config->AsNeeded) {} + : ELFFileBase(SharedKind, M), SoName(DefaultSoName), + IsNeeded(!Config->AsNeeded) { + parseHeader(); +} // Partially parse the shared object file so that we can call // getSoName on this object. template void SharedFile::parseDynamic() { ArrayRef DynamicTags; - const ELFFile Obj = this->getObj(); + const ELFFile Obj = this->getObj(); ArrayRef Sections = CHECK(Obj.sections(), this); // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d. @@ -886,7 +889,7 @@ default: continue; case SHT_DYNSYM: - this->initSymtab(Sections, &Sec); + this->initSymtab(Sections, &Sec); break; case SHT_DYNAMIC: DynamicTags = @@ -901,7 +904,7 @@ } } - if (this->VersymSec && this->ELFSyms.empty()) + if (this->VersymSec && this->getELFSyms().empty()) error("SHT_GNU_versym should be associated with symbol table"); // Search for a DT_SONAME tag to initialize this->SoName. @@ -923,7 +926,7 @@ // Parses ".gnu.version" section which is a parallel array for the symbol table. // If a given file doesn't have ".gnu.version" section, returns VER_NDX_GLOBAL. template std::vector SharedFile::parseVersyms() { - size_t Size = this->ELFSyms.size() - this->FirstGlobal; + size_t Size = this->getELFSyms().size() - this->FirstGlobal; if (!VersymSec) return std::vector(Size, VER_NDX_GLOBAL); @@ -1001,7 +1004,7 @@ template void SharedFile::parseRest() { Verdefs = parseVerdefs(); // parse .gnu.version_d std::vector Versyms = parseVersyms(); // parse .gnu.version - ArrayRef Sections = CHECK(this->getObj().sections(), this); + ArrayRef Sections = CHECK(this->getObj().sections(), this); // System libraries can have a lot of symbols with versions. Using a // fixed buffer for computing the versions name (foo@ver) can save a @@ -1009,7 +1012,7 @@ SmallString<0> VersionedNameBuffer; // Add symbols to the symbol table. - ArrayRef Syms = this->getGlobalELFSyms(); + ArrayRef Syms = this->getGlobalELFSyms(); for (size_t I = 0; I < Syms.size(); ++I) { const Elf_Sym &Sym = Syms[I]; @@ -1347,11 +1350,6 @@ template void LazyObjFile::parse(); template void LazyObjFile::parse(); -template class elf::ELFFileBase; -template class elf::ELFFileBase; -template class elf::ELFFileBase; -template class elf::ELFFileBase; - template class elf::ObjFile; template class elf::ObjFile; template class elf::ObjFile; diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -483,7 +483,8 @@ // Determine if the symbol is read-only by scanning the DSO's program headers. const SharedFile &File = SS.getFile(); - for (const Elf_Phdr &Phdr : check(File.getObj().program_headers())) + for (const Elf_Phdr &Phdr : + check(File.template getObj().program_headers())) if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) && !(Phdr.p_flags & ELF::PF_W) && SS.Value >= Phdr.p_vaddr && SS.Value < Phdr.p_vaddr + Phdr.p_memsz) @@ -503,7 +504,7 @@ SharedFile &File = SS.getFile(); SmallSet Ret; - for (const Elf_Sym &S : File.getGlobalELFSyms()) { + for (const Elf_Sym &S : File.template getGlobalELFSyms()) { if (S.st_shndx == SHN_UNDEF || S.st_shndx == SHN_ABS || S.getType() == STT_TLS || S.st_value != SS.Value) continue;