X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FObject%2FELF.h;h=2c3d841553e033145ac470fd61b0a961050be430;hb=a7616cd14c243957d674b0444e50f5d43152f803;hp=4ac49d419beb425bc0da5cca28cb7e40cc427a31;hpb=04d208815c496cc530270707fbfd3e1991dce01d;p=oota-llvm.git diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 4ac49d419be..2c3d841553e 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -55,78 +55,6 @@ public: typedef typename std::conditional::type uintX_t; - /// \brief Iterate over constant sized entities. - template - class ELFEntityIterator { - public: - typedef ptrdiff_t difference_type; - typedef EntT value_type; - typedef std::forward_iterator_tag iterator_category; - typedef value_type &reference; - typedef value_type *pointer; - - /// \brief Default construct iterator. - ELFEntityIterator() : EntitySize(0), Current(nullptr) {} - ELFEntityIterator(uintX_t EntSize, const char *Start) - : EntitySize(EntSize), Current(Start) {} - - reference operator *() { - assert(Current && "Attempted to dereference an invalid iterator!"); - return *reinterpret_cast(Current); - } - - pointer operator ->() { - assert(Current && "Attempted to dereference an invalid iterator!"); - return reinterpret_cast(Current); - } - - bool operator ==(const ELFEntityIterator &Other) { - return Current == Other.Current; - } - - bool operator !=(const ELFEntityIterator &Other) { - return !(*this == Other); - } - - ELFEntityIterator &operator ++() { - assert(Current && "Attempted to increment an invalid iterator!"); - Current += EntitySize; - return *this; - } - - ELFEntityIterator &operator+(difference_type n) { - assert(Current && "Attempted to increment an invalid iterator!"); - Current += (n * EntitySize); - return *this; - } - - ELFEntityIterator &operator-(difference_type n) { - assert(Current && "Attempted to subtract an invalid iterator!"); - Current -= (n * EntitySize); - return *this; - } - - ELFEntityIterator operator ++(int) { - ELFEntityIterator Tmp = *this; - ++*this; - return Tmp; - } - - difference_type operator -(const ELFEntityIterator &Other) const { - assert(EntitySize == Other.EntitySize && - "Subtracting iterators of different EntitySize!"); - return (Current - Other.Current) / EntitySize; - } - - const char *get() const { return Current; } - - uintX_t getEntSize() const { return EntitySize; } - - private: - uintX_t EntitySize; - const char *Current; - }; - typedef Elf_Ehdr_Impl Elf_Ehdr; typedef Elf_Shdr_Impl Elf_Shdr; typedef Elf_Sym_Impl Elf_Sym; @@ -157,23 +85,22 @@ public: typedef iterator_range Elf_Sym_Range; + const uint8_t *base() const { + return reinterpret_cast(Buf.data()); + } + private: typedef SmallVector Sections_t; typedef DenseMap IndexMap_t; StringRef Buf; - const uint8_t *base() const { - return reinterpret_cast(Buf.data()); - } - const Elf_Ehdr *Header; const Elf_Shdr *SectionHeaderTable = nullptr; StringRef DotShstrtab; // Section header string table. StringRef DotStrtab; // Symbol header string table. const Elf_Shdr *dot_symtab_sec = nullptr; // Symbol table section. const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section. - const Elf_Hash *HashTable = nullptr; const Elf_Shdr *SymbolTableSectionHeaderIndex = nullptr; DenseMap ExtendedSymbolTable; @@ -182,25 +109,6 @@ private: const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d - /// \brief Represents a region described by entries in the .dynamic table. - struct DynRegionInfo { - DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} - /// \brief Address in current address space. - const void *Addr; - /// \brief Size in bytes of the region. - uintX_t Size; - /// \brief Size of each entity in the region. - uintX_t EntSize; - }; - - DynRegionInfo DynamicRegion; - DynRegionInfo DynHashRegion; - DynRegionInfo DynStrRegion; - DynRegionInfo DynRelaRegion; - - // SONAME entry in dynamic string table - StringRef DTSoname; - // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. class VersionMapEntry : public PointerIntPair { @@ -227,8 +135,6 @@ private: void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionMap() const; - void scanDynamicTable(); - public: template const T *getEntry(uint32_t Section, uint32_t Entry) const; @@ -237,12 +143,11 @@ public: const Elf_Shdr *getDotSymtabSec() const { return dot_symtab_sec; } const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; } - const Elf_Hash *getHashTable() const { return HashTable; } ErrorOr getStringTable(const Elf_Shdr *Section) const; - const char *getDynamicString(uintX_t Offset) const; - ErrorOr getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *Symb, + ErrorOr getStringTableForSymtab(const Elf_Shdr &Section) const; + + ErrorOr getSymbolVersion(StringRef StrTab, const Elf_Sym *Symb, bool &IsDefault) const; void VerifyStrTab(const Elf_Shdr *sh) const; @@ -274,56 +179,37 @@ public: return make_range(section_begin(), section_end()); } - const Elf_Sym *symbol_begin() const; - const Elf_Sym *symbol_end() const; - Elf_Sym_Range symbols() const { - return make_range(symbol_begin(), symbol_end()); - } - - const Elf_Dyn *dynamic_table_begin() const; - const Elf_Dyn *dynamic_table_end() const; - Elf_Dyn_Range dynamic_table() const { - return make_range(dynamic_table_begin(), dynamic_table_end()); - } - - const Elf_Sym *dynamic_symbol_begin() const { - if (!DotDynSymSec) + const Elf_Sym *symbol_begin(const Elf_Shdr *Sec) const { + if (!Sec) return nullptr; - if (DotDynSymSec->sh_entsize != sizeof(Elf_Sym)) + if (Sec->sh_entsize != sizeof(Elf_Sym)) report_fatal_error("Invalid symbol size"); - return reinterpret_cast(base() + DotDynSymSec->sh_offset); + return reinterpret_cast(base() + Sec->sh_offset); } - - const Elf_Sym *dynamic_symbol_end() const { - if (!DotDynSymSec) + const Elf_Sym *symbol_end(const Elf_Shdr *Sec) const { + if (!Sec) return nullptr; - return reinterpret_cast(base() + DotDynSymSec->sh_offset + - DotDynSymSec->sh_size); + uint64_t Size = Sec->sh_size; + if (Size % sizeof(Elf_Sym)) + report_fatal_error("Invalid symbol table size"); + return symbol_begin(Sec) + Size / sizeof(Elf_Sym); } - - Elf_Sym_Range dynamic_symbols() const { - return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); + Elf_Sym_Range symbols(const Elf_Shdr *Sec) const { + return make_range(symbol_begin(Sec), symbol_end(Sec)); } - const Elf_Rela *dyn_rela_begin() const { - if (DynRelaRegion.Size && DynRelaRegion.EntSize != sizeof(Elf_Rela)) - report_fatal_error("Invalid relocation entry size"); - return reinterpret_cast(DynRelaRegion.Addr); - } + const Elf_Sym *symbol_begin() const { return symbol_begin(dot_symtab_sec); } + const Elf_Sym *symbol_end() const { return symbol_end(dot_symtab_sec); } + Elf_Sym_Range symbols() const { return symbols(dot_symtab_sec); } - const Elf_Rela *dyn_rela_end() const { - uint64_t Size = DynRelaRegion.Size; - if (Size % sizeof(Elf_Rela)) - report_fatal_error("Invalid relocation table size"); - return dyn_rela_begin() + Size / sizeof(Elf_Rela); + const Elf_Sym *dynamic_symbol_begin() const { + return symbol_begin(DotDynSymSec); } + const Elf_Sym *dynamic_symbol_end() const { return symbol_end(DotDynSymSec); } + Elf_Sym_Range dynamic_symbols() const { return symbols(DotDynSymSec); } typedef iterator_range Elf_Rela_Range; - Elf_Rela_Range dyn_relas() const { - return make_range(dyn_rela_begin(), dyn_rela_end()); - } - const Elf_Rela *rela_begin(const Elf_Shdr *sec) const { if (sec->sh_entsize != sizeof(Elf_Rela)) report_fatal_error("Invalid relocation entry size"); @@ -382,15 +268,16 @@ public: const Elf_Ehdr *getHeader() const { return Header; } ErrorOr getSection(const Elf_Sym *symb) const; ErrorOr getSection(uint32_t Index) const; - const Elf_Sym *getSymbol(uint32_t index) const; - ErrorOr getStaticSymbolName(const Elf_Sym *Symb) const; - ErrorOr getDynamicSymbolName(const Elf_Sym *Symb) const; - ErrorOr getSymbolName(const Elf_Sym *Symb, bool IsDynamic) const; + const Elf_Sym *getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { + return &*(symbol_begin(Sec) + Index); + } + const Elf_Sym *getSymbol(uint32_t Index) const { + return getSymbol(dot_symtab_sec, Index); + } ErrorOr getSectionName(const Elf_Shdr *Section) const; ErrorOr > getSectionContents(const Elf_Shdr *Sec) const; - StringRef getLoadName() const; }; typedef ELFFile> ELF32LEFile; @@ -497,12 +384,6 @@ ELFFile::getSection(const Elf_Sym *symb) const { return getSection(symb->st_shndx); } -template -const typename ELFFile::Elf_Sym * -ELFFile::getSymbol(uint32_t Index) const { - return &*(symbol_begin() + Index); -} - template ErrorOr > ELFFile::getSectionContents(const Elf_Shdr *Sec) const { @@ -597,10 +478,8 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) Header = reinterpret_cast(base()); - if (Header->e_shoff == 0) { - scanDynamicTable(); + if (Header->e_shoff == 0) return; - } const uint64_t SectionTableOffset = Header->e_shoff; @@ -625,13 +504,6 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) for (const Elf_Shdr &Sec : sections()) { switch (Sec.sh_type) { - case ELF::SHT_HASH: - if (HashTable) { - EC = object_error::parse_failed; - return; - } - HashTable = reinterpret_cast(base() + Sec.sh_offset); - break; case ELF::SHT_SYMTAB_SHNDX: if (SymbolTableSectionHeaderIndex) { // More than one .symtab_shndx! @@ -647,10 +519,7 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) return; } dot_symtab_sec = &Sec; - ErrorOr SectionOrErr = getSection(Sec.sh_link); - if ((EC = SectionOrErr.getError())) - return; - ErrorOr SymtabOrErr = getStringTable(*SectionOrErr); + ErrorOr SymtabOrErr = getStringTableForSymtab(Sec); if ((EC = SymtabOrErr.getError())) return; DotStrtab = *SymtabOrErr; @@ -692,14 +561,18 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) } // Get string table sections. - ErrorOr StrTabSecOrErr = getSection(getStringTableIndex()); - if ((EC = StrTabSecOrErr.getError())) - return; + uintX_t StringTableIndex = getStringTableIndex(); + if (StringTableIndex) { + ErrorOr StrTabSecOrErr = + getSection(getStringTableIndex()); + if ((EC = StrTabSecOrErr.getError())) + return; - ErrorOr SymtabOrErr = getStringTable(*StrTabSecOrErr); - if ((EC = SymtabOrErr.getError())) - return; - DotShstrtab = *SymtabOrErr; + ErrorOr SymtabOrErr = getStringTable(*StrTabSecOrErr); + if ((EC = SymtabOrErr.getError())) + return; + DotShstrtab = *SymtabOrErr; + } // Build symbol name side-mapping if there is one. if (SymbolTableSectionHeaderIndex) { @@ -712,8 +585,6 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) } } - scanDynamicTable(); - EC = std::error_code(); } @@ -722,68 +593,6 @@ static bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl *Phdr) { return VAddr < Phdr->p_vaddr; } -template void ELFFile::scanDynamicTable() { - SmallVector LoadSegments; - for (const Elf_Phdr &Phdr : program_headers()) { - if (Phdr.p_type == ELF::PT_DYNAMIC) { - DynamicRegion.Addr = base() + Phdr.p_offset; - DynamicRegion.Size = Phdr.p_filesz; - continue; - } - if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0) - continue; - LoadSegments.push_back(&Phdr); - } - - auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * { - const Elf_Phdr **I = std::upper_bound( - LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr); - if (I == LoadSegments.begin()) - report_fatal_error("Virtual address is not in any segment"); - --I; - const Elf_Phdr &Phdr = **I; - uint64_t Delta = VAddr - Phdr.p_vaddr; - if (Delta >= Phdr.p_filesz) - report_fatal_error("Virtual address is not in any segment"); - return this->base() + Phdr.p_offset + Delta; - }; - - uint64_t SONameOffset = 0; - for (const Elf_Dyn &Dyn : dynamic_table()) { - switch (Dyn.d_tag) { - case ELF::DT_HASH: - if (HashTable) - continue; - HashTable = - reinterpret_cast(toMappedAddr(Dyn.getPtr())); - break; - case ELF::DT_STRTAB: - if (!DynStrRegion.Addr) - DynStrRegion.Addr = toMappedAddr(Dyn.getPtr()); - break; - case ELF::DT_STRSZ: - if (!DynStrRegion.Size) - DynStrRegion.Size = Dyn.getVal(); - break; - case ELF::DT_RELA: - if (!DynRelaRegion.Addr) - DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr()); - break; - case ELF::DT_RELASZ: - DynRelaRegion.Size = Dyn.getVal(); - break; - case ELF::DT_RELAENT: - DynRelaRegion.EntSize = Dyn.getVal(); - break; - case ELF::DT_SONAME: - SONameOffset = Dyn.getVal(); - break; - } - } - if (SONameOffset) - DTSoname = getDynamicString(SONameOffset); -} - template const typename ELFFile::Elf_Shdr *ELFFile::section_begin() const { if (Header->e_shentsize != sizeof(Elf_Shdr)) @@ -797,44 +606,6 @@ const typename ELFFile::Elf_Shdr *ELFFile::section_end() const { return section_begin() + getNumSections(); } -template -const typename ELFFile::Elf_Sym *ELFFile::symbol_begin() const { - if (!dot_symtab_sec) - return nullptr; - if (dot_symtab_sec->sh_entsize != sizeof(Elf_Sym)) - report_fatal_error("Invalid symbol size"); - return reinterpret_cast(base() + dot_symtab_sec->sh_offset); -} - -template -const typename ELFFile::Elf_Sym *ELFFile::symbol_end() const { - if (!dot_symtab_sec) - return nullptr; - return reinterpret_cast(base() + dot_symtab_sec->sh_offset + - dot_symtab_sec->sh_size); -} - -template -const typename ELFFile::Elf_Dyn * -ELFFile::dynamic_table_begin() const { - return reinterpret_cast(DynamicRegion.Addr); -} - -template -const typename ELFFile::Elf_Dyn * -ELFFile::dynamic_table_end() const { - uint64_t Size = DynamicRegion.Size; - if (Size % sizeof(Elf_Dyn)) - report_fatal_error("Invalid dynamic table size"); - - return dynamic_table_begin() + Size / sizeof(Elf_Dyn); -} - -template -StringRef ELFFile::getLoadName() const { - return DTSoname; -} - template template const T *ELFFile::getEntry(uint32_t Section, uint32_t Entry) const { @@ -879,77 +650,32 @@ ELFFile::getStringTable(const Elf_Shdr *Section) const { return Data; } -template -const char *ELFFile::getDynamicString(uintX_t Offset) const { - if (Offset >= DynStrRegion.Size) - return nullptr; - return (const char *)DynStrRegion.Addr + Offset; -} - template ErrorOr -ELFFile::getStaticSymbolName(const Elf_Sym *Symb) const { - return Symb->getName(DotStrtab); -} - -template -ErrorOr -ELFFile::getDynamicSymbolName(const Elf_Sym *Symb) const { - return StringRef(getDynamicString(Symb->st_name)); -} - -template -ErrorOr ELFFile::getSymbolName(const Elf_Sym *Symb, - bool IsDynamic) const { - if (IsDynamic) - return getDynamicSymbolName(Symb); - return getStaticSymbolName(Symb); +ELFFile::getStringTableForSymtab(const Elf_Shdr &Sec) const { + if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) + return object_error::parse_failed; + ErrorOr SectionOrErr = getSection(Sec.sh_link); + if (std::error_code EC = SectionOrErr.getError()) + return EC; + return getStringTable(*SectionOrErr); } template ErrorOr ELFFile::getSectionName(const Elf_Shdr *Section) const { uint32_t Offset = Section->sh_name; + if (Offset == 0) + return StringRef(); if (Offset >= DotShstrtab.size()) return object_error::parse_failed; return StringRef(DotShstrtab.data() + Offset); } template -ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, +ErrorOr ELFFile::getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, bool &IsDefault) const { - StringRef StrTab; - if (section) { - ErrorOr StrTabOrErr = getStringTable(section); - if (std::error_code EC = StrTabOrErr.getError()) - return EC; - StrTab = *StrTabOrErr; - } - // Handle non-dynamic symbols. - if (section != DotDynSymSec && section != nullptr) { - // Non-dynamic symbols can have versions in their names - // A name of the form 'foo@V1' indicates version 'V1', non-default. - // A name of the form 'foo@@V2' indicates version 'V2', default version. - ErrorOr SymName = symb->getName(StrTab); - if (!SymName) - return SymName; - StringRef Name = *SymName; - size_t atpos = Name.find('@'); - if (atpos == StringRef::npos) { - IsDefault = false; - return StringRef(""); - } - ++atpos; - if (atpos < Name.size() && Name[atpos] == '@') { - IsDefault = true; - ++atpos; - } else { - IsDefault = false; - } - return Name.substr(atpos); - } - // This is a dynamic symbol. Look in the GNU symbol version table. if (!dot_gnu_version_sec) { // No version table. @@ -996,9 +722,9 @@ ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, IsDefault = false; } - if (name_offset >= DynStrRegion.Size) + if (name_offset >= StrTab.size()) return object_error::parse_failed; - return StringRef(getDynamicString(name_offset)); + return StringRef(StrTab.data() + name_offset); } /// This function returns the hash value for a symbol in the .dynsym section