[llvm] r285815 - Compute the section table lazily.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 2 08:15:59 PDT 2016


Author: rafael
Date: Wed Nov  2 10:15:59 2016
New Revision: 285815

URL: http://llvm.org/viewvc/llvm-project?rev=285815&view=rev
Log:
Compute the section table lazily.

As a consequence this move a bunch of error checking out of the constructor.

Modified:
    llvm/trunk/include/llvm/Object/ELF.h

Modified: llvm/trunk/include/llvm/Object/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELF.h?rev=285815&r1=285814&r2=285815&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELF.h (original)
+++ llvm/trunk/include/llvm/Object/ELF.h Wed Nov  2 10:15:59 2016
@@ -71,7 +71,6 @@ private:
   StringRef Buf;
 
   const Elf_Ehdr *Header;
-  const Elf_Shdr *SectionHeaderTable = nullptr;
 
 public:
   template<typename T>
@@ -147,8 +146,8 @@ public:
     return makeArrayRef(program_header_begin(), program_header_end());
   }
 
-  uintX_t getNumSections() const;
   ErrorOr<StringRef> getSectionStringTable() const;
+  ErrorOr<StringRef> getSectionStringTable(Elf_Shdr_Range Sections) const;
   uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym,
                                        const Elf_Shdr *SymTab,
                                        ArrayRef<Elf_Word> ShndxTable) const;
@@ -286,26 +285,25 @@ ELFFile<ELFT>::getRelocationSymbol(const
 }
 
 template <class ELFT>
-typename ELFT::uint ELFFile<ELFT>::getNumSections() const {
-  assert(Header && "Header not initialized!");
-  if (Header->e_shnum == ELF::SHN_UNDEF && Header->e_shoff > 0) {
-    assert(SectionHeaderTable && "SectionHeaderTable not initialized!");
-    return SectionHeaderTable->sh_size;
-  }
-  return Header->e_shnum;
+ErrorOr<StringRef> ELFFile<ELFT>::getSectionStringTable() const {
+  auto SectionsOrErr = sections();
+  if (std::error_code EC = SectionsOrErr.getError())
+    return EC;
+  return getSectionStringTable(*SectionsOrErr);
 }
 
 template <class ELFT>
-ErrorOr<StringRef> ELFFile<ELFT>::getSectionStringTable() const {
+ErrorOr<StringRef>
+ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const {
   uint32_t Index = Header->e_shstrndx;
   if (Index == ELF::SHN_XINDEX)
-    Index = SectionHeaderTable->sh_link;
+    Index = Sections[0].sh_link;
+
   if (!Index) // no section string table.
     return "";
-  ErrorOr<const Elf_Shdr *> StrTabSecOrErr = getSection(Index);
-  if (std::error_code EC = StrTabSecOrErr.getError())
-    return EC;
-  return getStringTable(*StrTabSecOrErr);
+  if (Index >= Sections.size())
+    return object_error::parse_failed;
+  return getStringTable(&Sections[Index]);
 }
 
 template <class ELFT>
@@ -328,37 +326,6 @@ ELFFile<ELFT>::ELFFile(StringRef Object,
     return;
   }
 
-  const uint64_t SectionTableOffset = Header->e_shoff;
-
-  if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) {
-    // Section header table goes past end of file!
-    EC = object_error::parse_failed;
-    return;
-  }
-
-  if (SectionTableOffset & (alignof(Elf_Shdr) - 1)) {
-    // Invalid address alignment of section headers
-    EC = object_error::parse_failed;
-    return;
-  }
-
-  // The getNumSections() call below depends on SectionHeaderTable being set.
-  SectionHeaderTable =
-    reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
-  if (getNumSections() > UINT64_MAX / Header->e_shentsize) {
-    // Section table goes past end of file!
-    EC = object_error::parse_failed;
-    return;
-  }
-
-  const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize;
-
-  if (SectionTableOffset + SectionTableSize > FileSize) {
-    // Section table goes past end of file!
-    EC = object_error::parse_failed;
-    return;
-  }
-
   EC = std::error_code();
 }
 
@@ -369,11 +336,42 @@ static bool compareAddr(uint64_t VAddr,
 
 template <class ELFT>
 ErrorOr<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
+  const uintX_t SectionTableOffset = Header->e_shoff;
+  if (SectionTableOffset == 0)
+    return ArrayRef<Elf_Shdr>();
+
   // Invalid section header entry size (e_shentsize) in ELF header
   if (Header->e_shentsize != sizeof(Elf_Shdr))
     return object_error::parse_failed;
-  auto *Begin = reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff);
-  return makeArrayRef(Begin, Begin + getNumSections());
+
+  const uint64_t FileSize = Buf.size();
+
+  // Section header table goes past end of file!
+  if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)
+    return object_error::parse_failed;
+
+  // Invalid address alignment of section headers
+  if (SectionTableOffset & (alignof(Elf_Shdr) - 1))
+    return object_error::parse_failed;
+
+  const Elf_Shdr *First =
+      reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
+
+  uintX_t NumSections = Header->e_shnum;
+  if (NumSections == 0)
+    NumSections = First->sh_size;
+
+  // Section table goes past end of file!
+  if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
+    return object_error::parse_failed;
+
+  const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);
+
+  // Section table goes past end of file!
+  if (SectionTableOffset + SectionTableSize > FileSize)
+    return object_error::parse_failed;
+
+  return makeArrayRef(First, NumSections);
 }
 
 template <class ELFT>
@@ -396,14 +394,13 @@ const T *ELFFile<ELFT>::getEntry(const E
 template <class ELFT>
 ErrorOr<const typename ELFFile<ELFT>::Elf_Shdr *>
 ELFFile<ELFT>::getSection(uint32_t Index) const {
-  assert(SectionHeaderTable && "SectionHeaderTable not initialized!");
-  if (Index >= getNumSections())
-    return object_error::invalid_section_index;
-
-  const Elf_Shdr *Addr = SectionHeaderTable + Index;
-  if (reinterpret_cast<const uint8_t *>(Addr) >= base() + getBufSize())
+  auto TableOrErr = sections();
+  if (std::error_code EC = TableOrErr.getError())
+    return EC;
+  ArrayRef<Elf_Shdr> Table = *TableOrErr;
+  if (Index >= Table.size())
     return object_error::invalid_section_index;
-  return Addr;
+  return &Table[Index];
 }
 
 template <class ELFT>




More information about the llvm-commits mailing list