diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index e5a419cd650..82fc19bc626 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -140,8 +140,7 @@ public: typedef Elf_Vernaux_Impl Elf_Vernaux; typedef Elf_Versym_Impl Elf_Versym; typedef Elf_Hash_Impl Elf_Hash; - typedef ELFEntityIterator Elf_Dyn_Iter; - typedef iterator_range Elf_Dyn_Range; + typedef iterator_range Elf_Dyn_Range; typedef iterator_range Elf_Shdr_Range; /// \brief Archive files are 2 byte aligned, so we need this for @@ -282,10 +281,10 @@ public: return make_range(symbol_begin(), symbol_end()); } - Elf_Dyn_Iter dynamic_table_begin() const; + const Elf_Dyn *dynamic_table_begin() const; /// \param NULLEnd use one past the first DT_NULL entry as the end instead of /// the section size. - Elf_Dyn_Iter dynamic_table_end(bool NULLEnd = false) const; + const Elf_Dyn *dynamic_table_end(bool NULLEnd = false) const; Elf_Dyn_Range dynamic_table(bool NULLEnd = false) const { return make_range(dynamic_table_begin(), dynamic_table_end(NULLEnd)); } @@ -668,16 +667,6 @@ ELFFile::ELFFile(StringRef Object, std::error_code &EC) 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! @@ -742,7 +731,6 @@ template void ELFFile::scanDynamicTable() { if (Phdr.p_type == ELF::PT_DYNAMIC) { DynamicRegion.Addr = base() + Phdr.p_offset; DynamicRegion.Size = Phdr.p_filesz; - DynamicRegion.EntSize = sizeof(Elf_Dyn); continue; } if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0) @@ -763,32 +751,31 @@ template void ELFFile::scanDynamicTable() { return this->base() + Phdr.p_offset + Delta; }; - for (Elf_Dyn_Iter DynI = dynamic_table_begin(), DynE = dynamic_table_end(); - DynI != DynE; ++DynI) { - switch (DynI->d_tag) { + for (const Elf_Dyn &Dyn : dynamic_table()) { + switch (Dyn.d_tag) { case ELF::DT_HASH: if (HashTable) continue; HashTable = - reinterpret_cast(toMappedAddr(DynI->getPtr())); + reinterpret_cast(toMappedAddr(Dyn.getPtr())); break; case ELF::DT_STRTAB: if (!DynStrRegion.Addr) - DynStrRegion.Addr = toMappedAddr(DynI->getPtr()); + DynStrRegion.Addr = toMappedAddr(Dyn.getPtr()); break; case ELF::DT_STRSZ: if (!DynStrRegion.Size) - DynStrRegion.Size = DynI->getVal(); + DynStrRegion.Size = Dyn.getVal(); break; case ELF::DT_RELA: if (!DynRelaRegion.Addr) - DynRelaRegion.Addr = toMappedAddr(DynI->getPtr()); + 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(); } } } @@ -824,24 +811,22 @@ const typename ELFFile::Elf_Sym *ELFFile::symbol_end() const { } template -typename ELFFile::Elf_Dyn_Iter +const typename ELFFile::Elf_Dyn * ELFFile::dynamic_table_begin() const { - if (DynamicRegion.Addr) - return Elf_Dyn_Iter(DynamicRegion.EntSize, - (const char *)DynamicRegion.Addr); - return Elf_Dyn_Iter(0, nullptr); + return reinterpret_cast(DynamicRegion.Addr); } template -typename ELFFile::Elf_Dyn_Iter +const typename ELFFile::Elf_Dyn * ELFFile::dynamic_table_end(bool NULLEnd) const { - if (!DynamicRegion.Addr) - return Elf_Dyn_Iter(0, nullptr); - Elf_Dyn_Iter Ret(DynamicRegion.EntSize, - (const char *)DynamicRegion.Addr + DynamicRegion.Size); + uint64_t Size = DynamicRegion.Size; + if (Size % sizeof(Elf_Dyn)) + report_fatal_error("Invalid dynamic table size"); + + const Elf_Dyn *Ret = dynamic_table_begin() + Size / sizeof(Elf_Dyn); if (NULLEnd) { - Elf_Dyn_Iter Start = dynamic_table_begin(); + const Elf_Dyn *Start = dynamic_table_begin(); while (Start != Ret && Start->getTag() != ELF::DT_NULL) ++Start; diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 6e8ace427a2..cd334d5e06f 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -189,8 +189,6 @@ public: typedef typename ELFFile::Elf_Rela Elf_Rela; typedef typename ELFFile::Elf_Dyn Elf_Dyn; - typedef typename ELFFile::Elf_Dyn_Iter Elf_Dyn_Iter; - protected: ELFFile EF; @@ -273,9 +271,9 @@ protected: return DRI; } - DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { + DataRefImpl toDRI(const Elf_Dyn *Dyn) const { DataRefImpl DRI; - DRI.p = reinterpret_cast(Dyn.get()); + DRI.p = reinterpret_cast(Dyn); return DRI; } @@ -783,8 +781,8 @@ section_iterator ELFObjectFile::section_end() const { template StringRef ELFObjectFile::getLoadName() const { - Elf_Dyn_Iter DI = EF.dynamic_table_begin(); - Elf_Dyn_Iter DE = EF.dynamic_table_end(); + const Elf_Dyn *DI = EF.dynamic_table_begin(); + const Elf_Dyn *DE = EF.dynamic_table_end(); while (DI != DE && DI->getTag() != ELF::DT_SONAME) ++DI; diff --git a/test/Object/Inputs/corrupt-invalid-dynamic-table-size.elf.x86-64 b/test/Object/Inputs/corrupt-invalid-dynamic-table-size.elf.x86-64 new file mode 100755 index 00000000000..ee29a4162e3 Binary files /dev/null and b/test/Object/Inputs/corrupt-invalid-dynamic-table-size.elf.x86-64 differ diff --git a/test/Object/corrupt.test b/test/Object/corrupt.test index 843cc247523..05a8d0fab5c 100644 --- a/test/Object/corrupt.test +++ b/test/Object/corrupt.test @@ -50,3 +50,9 @@ RUN: %p/Inputs/corrupt-invalid-relocation-size.elf.x86-64 2>&1 | \ RUN: FileCheck --check-prefix=RELOC %s RELOC: Invalid relocation entry size + +RUN: not llvm-readobj -dyn-relocations \ +RUN: %p/Inputs/corrupt-invalid-dynamic-table-size.elf.x86-64 2>&1 | \ +RUN: FileCheck --check-prefix=DYN-TABLE-SIZE %s + +DYN-TABLE-SIZE: Invalid dynamic table size