X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FObject%2FELF.h;h=6ebb92f7ee8caf97317c117e42babc1fe3c03a2a;hb=9ed0d629ce9ee7a1a8d7231347ad3050d1f98732;hp=35d414899ecc1141715fc3544bc4398040d8b7f3;hpb=3d176ae165aacd23ff4a68bca966ad2d89e26024;p=oota-llvm.git diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 35d414899ec..6ebb92f7ee8 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -139,12 +139,9 @@ public: typedef Elf_Verneed_Impl Elf_Verneed; typedef Elf_Vernaux_Impl Elf_Vernaux; typedef Elf_Versym_Impl Elf_Versym; - typedef ELFEntityIterator Elf_Dyn_Iter; - typedef iterator_range Elf_Dyn_Range; - typedef ELFEntityIterator Elf_Rela_Iter; - typedef ELFEntityIterator Elf_Rel_Iter; - typedef ELFEntityIterator Elf_Shdr_Iter; - typedef iterator_range Elf_Shdr_Range; + typedef Elf_Hash_Impl Elf_Hash; + typedef iterator_range Elf_Dyn_Range; + typedef iterator_range Elf_Shdr_Range; /// \brief Archive files are 2 byte aligned, so we need this for /// PointerIntPair to work. @@ -171,17 +168,19 @@ private: } const Elf_Ehdr *Header; - const Elf_Shdr *SectionHeaderTable; - StringRef DotShstrtab; // Section header string table. - StringRef DotStrtab; // Symbol header string table. - const Elf_Shdr *dot_symtab_sec; // Symbol table section. - - const Elf_Shdr *SymbolTableSectionHeaderIndex; + 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; - 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 + const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version + 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 { @@ -195,14 +194,11 @@ private: }; DynRegionInfo DynamicRegion; - DynRegionInfo DynHashRegion; DynRegionInfo DynStrRegion; - DynRegionInfo DynSymRegion; DynRegionInfo DynRelaRegion; - // Pointer to SONAME entry in dynamic string table - // This is set the first time getLoadName is called. - mutable const char *dt_soname; + // 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. @@ -230,12 +226,24 @@ 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; template const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; + + const Elf_Shdr *getDotSymtabSec() const { return dot_symtab_sec; } + const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; } + const Elf_Hash *getHashTable() const { return HashTable; } + StringRef getDynamicStringTable() const { + return StringRef((const char *)DynStrRegion.Addr, DynStrRegion.Size); + } + ErrorOr getStringTable(const Elf_Shdr *Section) const; + ErrorOr getStringTableForSymtab(const Elf_Shdr &Section) const; + const char *getDynamicString(uintX_t Offset) const; ErrorOr getSymbolVersion(const Elf_Shdr *section, const Elf_Sym *Symb, @@ -264,115 +272,125 @@ public: Header->getDataEncoding() == ELF::ELFDATA2LSB; } - Elf_Shdr_Iter begin_sections() const; - Elf_Shdr_Iter end_sections() const; + const Elf_Shdr *section_begin() const; + const Elf_Shdr *section_end() const; Elf_Shdr_Range sections() const { - return make_range(begin_sections(), end_sections()); + return make_range(section_begin(), section_end()); } - const Elf_Sym *begin_symbols() const; - const Elf_Sym *end_symbols() const; + const Elf_Sym *symbol_begin() const; + const Elf_Sym *symbol_end() const; Elf_Sym_Range symbols() const { - return make_range(begin_symbols(), end_symbols()); + return make_range(symbol_begin(), symbol_end()); } - Elf_Dyn_Iter begin_dynamic_table() const; - /// \param NULLEnd use one past the first DT_NULL entry as the end instead of - /// the section size. - Elf_Dyn_Iter end_dynamic_table(bool NULLEnd = false) const; - Elf_Dyn_Range dynamic_table(bool NULLEnd = false) const { - return make_range(begin_dynamic_table(), end_dynamic_table(NULLEnd)); + 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 *begin_dynamic_symbols() const { - if (DynSymRegion.Addr) - return reinterpret_cast(DynSymRegion.Addr); - return nullptr; + const Elf_Sym *dynamic_symbol_begin() const { + if (!DotDynSymSec) + return nullptr; + if (DotDynSymSec->sh_entsize != sizeof(Elf_Sym)) + report_fatal_error("Invalid symbol size"); + return reinterpret_cast(base() + DotDynSymSec->sh_offset); } - const Elf_Sym *end_dynamic_symbols() const { - if (DynSymRegion.Addr) - return reinterpret_cast( - ((const char *)DynSymRegion.Addr + DynSymRegion.Size)); - - return nullptr; + const Elf_Sym *dynamic_symbol_end() const { + if (!DotDynSymSec) + return nullptr; + return reinterpret_cast(base() + DotDynSymSec->sh_offset + + DotDynSymSec->sh_size); } Elf_Sym_Range dynamic_symbols() const { - return make_range(begin_dynamic_symbols(), end_dynamic_symbols()); + return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); } - Elf_Rela_Iter begin_dyn_rela() const { - if (DynRelaRegion.Addr) - return Elf_Rela_Iter(DynRelaRegion.EntSize, - (const char *)DynRelaRegion.Addr); - return Elf_Rela_Iter(0, nullptr); + 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); } - Elf_Rela_Iter end_dyn_rela() const { - if (DynRelaRegion.Addr) - return Elf_Rela_Iter( - DynRelaRegion.EntSize, - (const char *)DynRelaRegion.Addr + DynRelaRegion.Size); - return Elf_Rela_Iter(0, nullptr); + 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); } - Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const { - return Elf_Rela_Iter(sec->sh_entsize, - (const char *)(base() + sec->sh_offset)); + 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"); + return reinterpret_cast(base() + sec->sh_offset); + } + + const Elf_Rela *rela_end(const Elf_Shdr *sec) const { + uint64_t Size = sec->sh_size; + if (Size % sizeof(Elf_Rela)) + report_fatal_error("Invalid relocation table size"); + return rela_begin(sec) + Size / sizeof(Elf_Rela); } - Elf_Rela_Iter end_rela(const Elf_Shdr *sec) const { - return Elf_Rela_Iter( - sec->sh_entsize, - (const char *)(base() + sec->sh_offset + sec->sh_size)); + Elf_Rela_Range relas(const Elf_Shdr *Sec) const { + return make_range(rela_begin(Sec), rela_end(Sec)); } - Elf_Rel_Iter begin_rel(const Elf_Shdr *sec) const { - return Elf_Rel_Iter(sec->sh_entsize, - (const char *)(base() + sec->sh_offset)); + const Elf_Rel *rel_begin(const Elf_Shdr *sec) const { + if (sec->sh_entsize != sizeof(Elf_Rel)) + report_fatal_error("Invalid relocation entry size"); + return reinterpret_cast(base() + sec->sh_offset); } - Elf_Rel_Iter end_rel(const Elf_Shdr *sec) const { - return Elf_Rel_Iter(sec->sh_entsize, - (const char *)(base() + sec->sh_offset + sec->sh_size)); + const Elf_Rel *rel_end(const Elf_Shdr *sec) const { + uint64_t Size = sec->sh_size; + if (Size % sizeof(Elf_Rel)) + report_fatal_error("Invalid relocation table size"); + return rel_begin(sec) + Size / sizeof(Elf_Rel); + } + + typedef iterator_range Elf_Rel_Range; + Elf_Rel_Range rels(const Elf_Shdr *Sec) const { + return make_range(rel_begin(Sec), rel_end(Sec)); } /// \brief Iterate over program header table. - typedef ELFEntityIterator Elf_Phdr_Iter; + const Elf_Phdr *program_header_begin() const { + if (Header->e_phnum && Header->e_phentsize != sizeof(Elf_Phdr)) + report_fatal_error("Invalid program header size"); + return reinterpret_cast(base() + Header->e_phoff); + } - Elf_Phdr_Iter begin_program_headers() const { - return Elf_Phdr_Iter(Header->e_phentsize, - (const char*)base() + Header->e_phoff); + const Elf_Phdr *program_header_end() const { + return program_header_begin() + Header->e_phnum; } - Elf_Phdr_Iter end_program_headers() const { - return Elf_Phdr_Iter(Header->e_phentsize, - (const char*)base() + - Header->e_phoff + - (Header->e_phnum * Header->e_phentsize)); + typedef iterator_range Elf_Phdr_Range; + + const Elf_Phdr_Range program_headers() const { + return make_range(program_header_begin(), program_header_end()); } uint64_t getNumSections() const; uintX_t getStringTableIndex() const; ELF::Elf64_Word getExtendedSymbolTableIndex(const Elf_Sym *symb) const; const Elf_Ehdr *getHeader() const { return Header; } - const Elf_Shdr *getSection(const Elf_Sym *symb) const; - const Elf_Shdr *getSection(uint32_t Index) const; + 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; - - /// \brief Get the name of \p Symb. - /// \param SymTab The symbol table section \p Symb is contained in. - /// \param Symb The symbol to get the name of. - /// - /// \p SymTab is used to lookup the string table to use to get the symbol's - /// name. + ErrorOr getSectionName(const Elf_Shdr *Section) const; - uint64_t getSymbolIndex(const Elf_Sym *sym) const; ErrorOr > getSectionContents(const Elf_Shdr *Sec) const; StringRef getLoadName() const; }; @@ -444,7 +462,7 @@ void ELFFile::LoadVersionNeeds(const Elf_Shdr *sec) const { template void ELFFile::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (!DynSymRegion.Addr || !dot_gnu_version_sec) + if (!DotDynSymSec || !dot_gnu_version_sec) return; // Has the VersionMap already been loaded? @@ -471,11 +489,12 @@ ELFFile::getExtendedSymbolTableIndex(const Elf_Sym *symb) const { } template -const typename ELFFile::Elf_Shdr * +ErrorOr::Elf_Shdr *> ELFFile::getSection(const Elf_Sym *symb) const { - if (symb->st_shndx == ELF::SHN_XINDEX) + uint32_t Index = symb->st_shndx; + if (Index == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); - if (symb->st_shndx >= ELF::SHN_LORESERVE) + if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) return nullptr; return getSection(symb->st_shndx); } @@ -483,7 +502,7 @@ ELFFile::getSection(const Elf_Sym *symb) const { template const typename ELFFile::Elf_Sym * ELFFile::getSymbol(uint32_t Index) const { - return &*(begin_symbols() + Index); + return &*(symbol_begin() + Index); } template @@ -538,7 +557,10 @@ std::pair::Elf_Shdr *, ELFFile::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { if (!Sec->sh_link) return std::make_pair(nullptr, nullptr); - const Elf_Shdr *SymTable = getSection(Sec->sh_link); + ErrorOr SymTableOrErr = getSection(Sec->sh_link); + if (std::error_code EC = SymTableOrErr.getError()) + report_fatal_error(EC.message()); + const Elf_Shdr *SymTable = *SymTableOrErr; return std::make_pair( SymTable, getEntry(SymTable, Rel->getSymbol(isMips64EL()))); } @@ -566,10 +588,7 @@ typename ELFFile::uintX_t ELFFile::getStringTableIndex() const { template ELFFile::ELFFile(StringRef Object, std::error_code &EC) - : Buf(Object), SectionHeaderTable(nullptr), dot_symtab_sec(nullptr), - SymbolTableSectionHeaderIndex(nullptr), dot_gnu_version_sec(nullptr), - dot_gnu_version_r_sec(nullptr), dot_gnu_version_d_sec(nullptr), - dt_soname(nullptr) { + : Buf(Object) { const uint64_t FileSize = Buf.size(); if (sizeof(Elf_Ehdr) > FileSize) { @@ -580,8 +599,10 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) Header = reinterpret_cast(base()); - if (Header->e_shoff == 0) + if (Header->e_shoff == 0) { + scanDynamicTable(); return; + } const uint64_t SectionTableOffset = Header->e_shoff; @@ -606,6 +627,13 @@ 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! @@ -621,36 +649,20 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) return; } dot_symtab_sec = &Sec; - ErrorOr SymtabOrErr = getStringTable(getSection(Sec.sh_link)); + ErrorOr SymtabOrErr = getStringTableForSymtab(Sec); if ((EC = SymtabOrErr.getError())) return; DotStrtab = *SymtabOrErr; } break; case ELF::SHT_DYNSYM: { - if (DynSymRegion.Addr) { + if (DotDynSymSec) { // More than one .dynsym! EC = object_error::parse_failed; return; } - DynSymRegion.Addr = base() + Sec.sh_offset; - DynSymRegion.Size = Sec.sh_size; - DynSymRegion.EntSize = Sec.sh_entsize; - const Elf_Shdr *DynStr = getSection(Sec.sh_link); - DynStrRegion.Addr = base() + DynStr->sh_offset; - DynStrRegion.Size = DynStr->sh_size; - DynStrRegion.EntSize = DynStr->sh_entsize; + DotDynSymSec = &Sec; break; } - case ELF::SHT_DYNAMIC: - if (DynamicRegion.Addr) { - // More than one .dynamic! - EC = object_error::parse_failed; - return; - } - DynamicRegion.Addr = base() + Sec.sh_offset; - DynamicRegion.Size = Sec.sh_size; - DynamicRegion.EntSize = Sec.sh_entsize; - break; case ELF::SHT_GNU_versym: if (dot_gnu_version_sec != nullptr) { // More than one .gnu.version section! @@ -679,8 +691,11 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) } // Get string table sections. - ErrorOr SymtabOrErr = - getStringTable(getSection(getStringTableIndex())); + ErrorOr StrTabSecOrErr = getSection(getStringTableIndex()); + if ((EC = StrTabSecOrErr.getError())) + return; + + ErrorOr SymtabOrErr = getStringTable(*StrTabSecOrErr); if ((EC = SymtabOrErr.getError())) return; DotShstrtab = *SymtabOrErr; @@ -696,87 +711,102 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) } } - // Scan program headers. - for (Elf_Phdr_Iter PhdrI = begin_program_headers(), - PhdrE = end_program_headers(); - PhdrI != PhdrE; ++PhdrI) { - if (PhdrI->p_type == ELF::PT_DYNAMIC) { - DynamicRegion.Addr = base() + PhdrI->p_offset; - DynamicRegion.Size = PhdrI->p_filesz; - DynamicRegion.EntSize = sizeof(Elf_Dyn); - break; + scanDynamicTable(); + + EC = std::error_code(); +} + +template +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; + }; - // Scan dynamic table. - for (Elf_Dyn_Iter DynI = begin_dynamic_table(), DynE = end_dynamic_table(); - DynI != DynE; ++DynI) { - switch (DynI->d_tag) { - case ELF::DT_RELA: { - uint64_t VBase = 0; - const uint8_t *FBase = nullptr; - for (Elf_Phdr_Iter PhdrI = begin_program_headers(), - PhdrE = end_program_headers(); - PhdrI != PhdrE; ++PhdrI) { - if (PhdrI->p_type != ELF::PT_LOAD) - continue; - if (DynI->getPtr() >= PhdrI->p_vaddr && - DynI->getPtr() < PhdrI->p_vaddr + PhdrI->p_memsz) { - VBase = PhdrI->p_vaddr; - FBase = base() + PhdrI->p_offset; - break; - } - } - if (!VBase) - return; - DynRelaRegion.Addr = FBase + DynI->getPtr() - VBase; + 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 = DynI->getVal(); + DynRelaRegion.Size = Dyn.getVal(); break; case ELF::DT_RELAENT: - DynRelaRegion.EntSize = DynI->getVal(); + DynRelaRegion.EntSize = Dyn.getVal(); + break; + case ELF::DT_SONAME: + SONameOffset = Dyn.getVal(); + break; } } - - EC = std::error_code(); -} - -// Get the symbol table index in the symtab section given a symbol -template -uint64_t ELFFile::getSymbolIndex(const Elf_Sym *Sym) const { - uintptr_t SymLoc = uintptr_t(Sym); - uintptr_t SymTabLoc = uintptr_t(base() + dot_symtab_sec->sh_offset); - assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); - uint64_t SymOffset = SymLoc - SymTabLoc; - assert(SymOffset % dot_symtab_sec->sh_entsize == 0 && - "Symbol not multiple of symbol size!"); - return SymOffset / dot_symtab_sec->sh_entsize; + if (SONameOffset) + DTSoname = getDynamicString(SONameOffset); } template -typename ELFFile::Elf_Shdr_Iter ELFFile::begin_sections() const { - return Elf_Shdr_Iter(Header->e_shentsize, - (const char *)base() + Header->e_shoff); +const typename ELFFile::Elf_Shdr *ELFFile::section_begin() const { + if (Header->e_shentsize != sizeof(Elf_Shdr)) + report_fatal_error( + "Invalid section header entry size (e_shentsize) in ELF header"); + return reinterpret_cast(base() + Header->e_shoff); } template -typename ELFFile::Elf_Shdr_Iter ELFFile::end_sections() const { - return Elf_Shdr_Iter(Header->e_shentsize, - (const char *)base() + Header->e_shoff + - (getNumSections() * Header->e_shentsize)); +const typename ELFFile::Elf_Shdr *ELFFile::section_end() const { + return section_begin() + getNumSections(); } template -const typename ELFFile::Elf_Sym *ELFFile::begin_symbols() const { +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::end_symbols() const { +const typename ELFFile::Elf_Sym *ELFFile::symbol_end() const { if (!dot_symtab_sec) return nullptr; return reinterpret_cast(base() + dot_symtab_sec->sh_offset + @@ -784,53 +814,33 @@ const typename ELFFile::Elf_Sym *ELFFile::end_symbols() const { } template -typename ELFFile::Elf_Dyn_Iter -ELFFile::begin_dynamic_table() const { - if (DynamicRegion.Addr) - return Elf_Dyn_Iter(DynamicRegion.EntSize, - (const char *)DynamicRegion.Addr); - return Elf_Dyn_Iter(0, nullptr); +const typename ELFFile::Elf_Dyn * +ELFFile::dynamic_table_begin() const { + return reinterpret_cast(DynamicRegion.Addr); } template -typename ELFFile::Elf_Dyn_Iter -ELFFile::end_dynamic_table(bool NULLEnd) const { - if (!DynamicRegion.Addr) - return Elf_Dyn_Iter(0, nullptr); - Elf_Dyn_Iter Ret(DynamicRegion.EntSize, - (const char *)DynamicRegion.Addr + DynamicRegion.Size); +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"); - if (NULLEnd) { - Elf_Dyn_Iter Start = begin_dynamic_table(); - while (Start != Ret && Start->getTag() != ELF::DT_NULL) - ++Start; - - // Include the DT_NULL. - if (Start != Ret) - ++Start; - Ret = Start; - } - return Ret; + return dynamic_table_begin() + Size / sizeof(Elf_Dyn); } template StringRef ELFFile::getLoadName() const { - if (!dt_soname) { - dt_soname = ""; - // Find the DT_SONAME entry - for (const auto &Entry : dynamic_table()) - if (Entry.getTag() == ELF::DT_SONAME) { - dt_soname = getDynamicString(Entry.getVal()); - break; - } - } - return dt_soname; + return DTSoname; } template template const T *ELFFile::getEntry(uint32_t Section, uint32_t Entry) const { - return getEntry(getSection(Section), Entry); + ErrorOr Sec = getSection(Section); + if (std::error_code EC = Sec.getError()) + report_fatal_error(EC.message()); + return getEntry(*Sec, Entry); } template @@ -842,17 +852,15 @@ const T *ELFFile::getEntry(const Elf_Shdr *Section, } template -const typename ELFFile::Elf_Shdr * -ELFFile::getSection(uint32_t index) const { - if (index == 0) - return nullptr; - if (!SectionHeaderTable || index >= getNumSections()) - // FIXME: Proper error handling. - report_fatal_error("Invalid section index!"); +ErrorOr::Elf_Shdr *> +ELFFile::getSection(uint32_t Index) const { + assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); + if (Index >= getNumSections()) + return object_error::invalid_section_index; return reinterpret_cast( - reinterpret_cast(SectionHeaderTable) - + (index * Header->e_shentsize)); + reinterpret_cast(SectionHeaderTable) + + (Index * Header->e_shentsize)); } template @@ -871,16 +879,21 @@ ELFFile::getStringTable(const Elf_Shdr *Section) const { } template -const char *ELFFile::getDynamicString(uintX_t Offset) const { - if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size) - return nullptr; - return (const char *)DynStrRegion.Addr + Offset; +ErrorOr +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::getStaticSymbolName(const Elf_Sym *Symb) const { - return Symb->getName(DotStrtab); +const char *ELFFile::getDynamicString(uintX_t Offset) const { + if (Offset >= DynStrRegion.Size) + return nullptr; + return (const char *)DynStrRegion.Addr + Offset; } template @@ -889,14 +902,6 @@ 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); -} - template ErrorOr ELFFile::getSectionName(const Elf_Shdr *Section) const { @@ -918,7 +923,7 @@ ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, StrTab = *StrTabOrErr; } // Handle non-dynamic symbols. - if (section != DynSymRegion.Addr && section != nullptr) { + 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. @@ -949,8 +954,10 @@ ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, } // Determine the position in the symbol table of this entry. - size_t entry_index = ((const char *)symb - (const char *)DynSymRegion.Addr) / - DynSymRegion.EntSize; + size_t entry_index = + (reinterpret_cast(symb) - DotDynSymSec->sh_offset - + reinterpret_cast(base())) / + sizeof(Elf_Sym); // Get the corresponding version index entry const Elf_Versym *vs = getEntry(dot_gnu_version_sec, entry_index);