From 1ef75e55b9402e1ac5e105fc0299a01eba09304b Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Thu, 7 Feb 2013 01:17:23 +0000 Subject: [PATCH] [Object][ELF] Devirtualize and simplify dynamic table iteration. llvm-svn: 174566 --- llvm/include/llvm/Object/ELF.h | 252 ++++++++++++----------------------------- 1 file changed, 70 insertions(+), 182 deletions(-) diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h index 919c229..79f0112 100644 --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -319,35 +319,6 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base { uint64_t getPtr() const { return d_un.ptr; } }; -template -class ELFObjectFile; - -// DynRefImpl: Reference to an entry in the dynamic table -// This is an ELF-specific interface. -template -class DynRefImpl { - typedef Elf_Dyn_Impl Elf_Dyn; - typedef ELFObjectFile OwningType; - - DataRefImpl DynPimpl; - const OwningType *OwningObject; - -public: - DynRefImpl() : OwningObject(NULL) { } - - DynRefImpl(DataRefImpl DynP, const OwningType *Owner); - - bool operator==(const DynRefImpl &Other) const; - bool operator <(const DynRefImpl &Other) const; - - error_code getNext(DynRefImpl &Result) const; - int64_t getTag() const; - uint64_t getVal() const; - uint64_t getPtr() const; - - DataRefImpl getRawDataRefImpl() const; -}; - // Elf_Rel: Elf Relocation template struct Elf_Rel_Base; @@ -495,53 +466,6 @@ template class ELFObjectFile : public ObjectFile { LLVM_ELF_IMPORT_TYPES(ELFT) - typedef Elf_Ehdr_Impl Elf_Ehdr; - typedef Elf_Shdr_Impl Elf_Shdr; - typedef Elf_Sym_Impl Elf_Sym; - typedef Elf_Dyn_Impl Elf_Dyn; - typedef Elf_Phdr_Impl Elf_Phdr; - typedef Elf_Rel_Impl Elf_Rel; - typedef Elf_Rel_Impl Elf_Rela; - typedef Elf_Verdef_Impl Elf_Verdef; - typedef Elf_Verdaux_Impl Elf_Verdaux; - typedef Elf_Verneed_Impl Elf_Verneed; - typedef Elf_Vernaux_Impl Elf_Vernaux; - typedef Elf_Versym_Impl Elf_Versym; - typedef DynRefImpl DynRef; - typedef content_iterator dyn_iterator; - -protected: - // This flag is used for classof, to distinguish ELFObjectFile from - // its subclass. If more subclasses will be created, this flag will - // have to become an enum. - bool isDyldELFObject; - -private: - typedef SmallVector Sections_t; - typedef DenseMap IndexMap_t; - typedef DenseMap > RelocMap_t; - - const Elf_Ehdr *Header; - const Elf_Shdr *SectionHeaderTable; - const Elf_Shdr *dot_shstrtab_sec; // Section header string table. - const Elf_Shdr *dot_strtab_sec; // Symbol header string table. - const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. - - // SymbolTableSections[0] always points to the dynamic string table section - // header, or NULL if there is no dynamic string table. - Sections_t SymbolTableSections; - IndexMap_t SymbolTableSectionsIndexMap; - DenseMap ExtendedSymbolTable; - - const Elf_Shdr *dot_dynamic_sec; // .dynamic - const Elf_Shdr *dot_gnu_version_sec; // .gnu.version - const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r - const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d - - // Pointer to SONAME entry in dynamic string table - // This is set the first time getLoadName is called. - mutable const char *dt_soname; - public: /// \brief Iterate over constant sized entities. template @@ -595,6 +519,53 @@ public: }; private: + typedef Elf_Ehdr_Impl Elf_Ehdr; + typedef Elf_Shdr_Impl Elf_Shdr; + typedef Elf_Sym_Impl Elf_Sym; + typedef Elf_Dyn_Impl Elf_Dyn; + typedef Elf_Phdr_Impl Elf_Phdr; + typedef Elf_Rel_Impl Elf_Rel; + typedef Elf_Rel_Impl Elf_Rela; + typedef Elf_Verdef_Impl Elf_Verdef; + typedef Elf_Verdaux_Impl Elf_Verdaux; + typedef Elf_Verneed_Impl Elf_Verneed; + typedef Elf_Vernaux_Impl Elf_Vernaux; + typedef Elf_Versym_Impl Elf_Versym; + typedef ELFEntityIterator dyn_iterator; + +protected: + // This flag is used for classof, to distinguish ELFObjectFile from + // its subclass. If more subclasses will be created, this flag will + // have to become an enum. + bool isDyldELFObject; + +private: + typedef SmallVector Sections_t; + typedef DenseMap IndexMap_t; + typedef DenseMap > RelocMap_t; + + const Elf_Ehdr *Header; + const Elf_Shdr *SectionHeaderTable; + const Elf_Shdr *dot_shstrtab_sec; // Section header string table. + const Elf_Shdr *dot_strtab_sec; // Symbol header string table. + const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. + + // SymbolTableSections[0] always points to the dynamic string table section + // header, or NULL if there is no dynamic string table. + Sections_t SymbolTableSections; + IndexMap_t SymbolTableSectionsIndexMap; + DenseMap ExtendedSymbolTable; + + const Elf_Shdr *dot_dynamic_sec; // .dynamic + const Elf_Shdr *dot_gnu_version_sec; // .gnu.version + const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r + const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d + + // Pointer to SONAME entry in dynamic string table + // This is set the first time getLoadName is called. + mutable const char *dt_soname; + +private: // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. class VersionMapEntry : public PointerIntPair { @@ -674,9 +645,6 @@ protected: section_iterator &Res) const; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - friend class DynRefImpl; - virtual error_code getDynNext(DataRefImpl DynData, DynRef &Result) const; - virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; @@ -2277,52 +2245,28 @@ section_iterator ELFObjectFile::end_sections() const { template typename ELFObjectFile::dyn_iterator ELFObjectFile::begin_dynamic_table() const { - DataRefImpl DynData; - if (dot_dynamic_sec == NULL || dot_dynamic_sec->sh_size == 0) { - DynData.d.a = std::numeric_limits::max(); - } else { - DynData.d.a = 0; - } - return dyn_iterator(DynRef(DynData, this)); + if (dot_dynamic_sec) + return dyn_iterator(dot_dynamic_sec->sh_entsize, (const char *)base() + dot_dynamic_sec->sh_offset); + return dyn_iterator(0, 0); } template typename ELFObjectFile::dyn_iterator ELFObjectFile::end_dynamic_table() const { - DataRefImpl DynData; - DynData.d.a = std::numeric_limits::max(); - return dyn_iterator(DynRef(DynData, this)); -} - -template -error_code ELFObjectFile::getDynNext(DataRefImpl DynData, - DynRef &Result) const { - ++DynData.d.a; - - // Check to see if we are at the end of .dynamic - if (DynData.d.a >= dot_dynamic_sec->getEntityCount()) { - // We are at the end. Return the terminator. - DynData.d.a = std::numeric_limits::max(); - } - - Result = DynRef(DynData, this); - return object_error::success; + if (dot_dynamic_sec) + return dyn_iterator(dot_dynamic_sec->sh_entsize, (const char *)base() + dot_dynamic_sec->sh_offset + dot_dynamic_sec->sh_size); + return dyn_iterator(0, 0); } template -StringRef -ELFObjectFile::getLoadName() const { +StringRef ELFObjectFile::getLoadName() const { if (!dt_soname) { // Find the DT_SONAME entry dyn_iterator it = begin_dynamic_table(); dyn_iterator ie = end_dynamic_table(); - error_code ec; - while (it != ie) { + for (; it != ie; ++it) { if (it->getTag() == ELF::DT_SONAME) break; - it.increment(ec); - if (ec) - report_fatal_error("dynamic table iteration failed"); } if (it != ie) { if (dot_dynstr_sec == NULL) @@ -2340,50 +2284,39 @@ library_iterator ELFObjectFile::begin_libraries_needed() const { // Find the first DT_NEEDED entry dyn_iterator i = begin_dynamic_table(); dyn_iterator e = end_dynamic_table(); - error_code ec; while (i != e) { if (i->getTag() == ELF::DT_NEEDED) break; - i.increment(ec); - if (ec) - report_fatal_error("dynamic table iteration failed"); } - // Use the same DataRefImpl format as DynRef. - return library_iterator(LibraryRef(i->getRawDataRefImpl(), this)); + + DataRefImpl DRI; + DRI.p = reinterpret_cast(&*i); + return library_iterator(LibraryRef(DRI, this)); } template error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, LibraryRef &Result) const { // Use the same DataRefImpl format as DynRef. - dyn_iterator i = dyn_iterator(DynRef(Data, this)); + dyn_iterator i = dyn_iterator(dot_dynamic_sec->sh_entsize, reinterpret_cast(Data.p)); dyn_iterator e = end_dynamic_table(); // Skip the current dynamic table entry. - error_code ec; - if (i != e) { - i.increment(ec); - // TODO: proper error handling - if (ec) - report_fatal_error("dynamic table iteration failed"); - } + ++i; // Find the next DT_NEEDED entry. - while (i != e) { - if (i->getTag() == ELF::DT_NEEDED) - break; - i.increment(ec); - if (ec) - report_fatal_error("dynamic table iteration failed"); - } - Result = LibraryRef(i->getRawDataRefImpl(), this); + for (; i != e && i->getTag() != ELF::DT_NEEDED; ++i); + + DataRefImpl DRI; + DRI.p = reinterpret_cast(&*i); + Result = LibraryRef(DRI, this); return object_error::success; } template error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, StringRef &Res) const { - dyn_iterator i = dyn_iterator(DynRef(Data, this)); + dyn_iterator i = dyn_iterator(dot_dynamic_sec->sh_entsize, reinterpret_cast(Data.p)); if (i == end_dynamic_table()) report_fatal_error("getLibraryPath() called on iterator end"); @@ -2404,8 +2337,9 @@ error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, template library_iterator ELFObjectFile::end_libraries_needed() const { dyn_iterator e = end_dynamic_table(); - // Use the same DataRefImpl format as DynRef. - return library_iterator(LibraryRef(e->getRawDataRefImpl(), this)); + DataRefImpl DRI; + DRI.p = reinterpret_cast(&*e); + return library_iterator(LibraryRef(DRI, this)); } template @@ -2519,12 +2453,6 @@ ELFObjectFile::getSymbol(DataRefImpl Symb) const { } template -const typename ELFObjectFile::Elf_Dyn * -ELFObjectFile::getDyn(DataRefImpl DynData) const { - return getEntry(dot_dynamic_sec, DynData.d.a); -} - -template const typename ELFObjectFile::Elf_Rel * ELFObjectFile::getRel(DataRefImpl Rel) const { return getEntry(Rel.w.b, Rel.w.c); @@ -2688,46 +2616,6 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, return object_error::success; } -template -inline DynRefImpl::DynRefImpl(DataRefImpl DynP, const OwningType *Owner) - : DynPimpl(DynP) - , OwningObject(Owner) {} - -template -inline bool DynRefImpl::operator==(const DynRefImpl &Other) const { - return DynPimpl == Other.DynPimpl; -} - -template -inline bool DynRefImpl::operator <(const DynRefImpl &Other) const { - return DynPimpl < Other.DynPimpl; -} - -template -inline error_code DynRefImpl::getNext(DynRefImpl &Result) const { - return OwningObject->getDynNext(DynPimpl, Result); -} - -template -inline int64_t DynRefImpl::getTag() const { - return OwningObject->getDyn(DynPimpl)->d_tag; -} - -template -inline uint64_t DynRefImpl::getVal() const { - return OwningObject->getDyn(DynPimpl)->d_un.d_val; -} - -template -inline uint64_t DynRefImpl::getPtr() const { - return OwningObject->getDyn(DynPimpl)->d_un.d_ptr; -} - -template -inline DataRefImpl DynRefImpl::getRawDataRefImpl() const { - return DynPimpl; -} - /// This is a generic interface for retrieving GNU symbol version /// information from an ELFObjectFile. static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, -- 2.7.4