diff options
| -rw-r--r-- | lld/ELF/InputFiles.cpp | 130 | ||||
| -rw-r--r-- | lld/ELF/InputFiles.h | 18 |
2 files changed, 70 insertions, 78 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 0581f35893b..2b89533191a 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -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 = diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index a51ba64aac3..e506b9eb87b 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -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. |

