Revert "[Object, ELF] Fix segmentation fault in ELFFile::getSectionName()."
[oota-llvm.git] / include / llvm / Object / ELF.h
index a6774c11503029f4660ebc15b627e63f060033ea..e87737dcce7a65f32df728a3d0ab6222d519bea7 100644 (file)
@@ -40,19 +40,20 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type);
 
 // Subclasses of ELFFile may need this for template instantiation
 inline std::pair<unsigned char, unsigned char>
-getElfArchType(MemoryBuffer *Object) {
-  if (Object->getBufferSize() < ELF::EI_NIDENT)
-    return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE);
-  return std::make_pair((uint8_t) Object->getBufferStart()[ELF::EI_CLASS],
-                        (uint8_t) Object->getBufferStart()[ELF::EI_DATA]);
+getElfArchType(StringRef Object) {
+  if (Object.size() < ELF::EI_NIDENT)
+    return std::make_pair((uint8_t)ELF::ELFCLASSNONE,
+                          (uint8_t)ELF::ELFDATANONE);
+  return std::make_pair((uint8_t)Object[ELF::EI_CLASS],
+                        (uint8_t)Object[ELF::EI_DATA]);
 }
 
 template <class ELFT>
 class ELFFile {
 public:
   LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
-  typedef typename conditional<ELFT::Is64Bits,
-                               uint64_t, uint32_t>::type uintX_t;
+  typedef typename std::conditional<ELFT::Is64Bits,
+                                    uint64_t, uint32_t>::type uintX_t;
 
   /// \brief Iterate over constant sized entities.
   template <class EntT>
@@ -60,12 +61,12 @@ public:
   public:
     typedef ptrdiff_t difference_type;
     typedef EntT value_type;
-    typedef std::random_access_iterator_tag iterator_category;
+    typedef std::forward_iterator_tag iterator_category;
     typedef value_type &reference;
     typedef value_type *pointer;
 
     /// \brief Default construct iterator.
-    ELFEntityIterator() : EntitySize(0), Current(0) {}
+    ELFEntityIterator() : EntitySize(0), Current(nullptr) {}
     ELFEntityIterator(uintX_t EntSize, const char *Start)
         : EntitySize(EntSize), Current(Start) {}
 
@@ -93,18 +94,24 @@ public:
       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;
     }
 
-    ELFEntityIterator &operator =(const ELFEntityIterator &Other) {
-      EntitySize = Other.EntitySize;
-      Current = Other.Current;
-      return *this;
-    }
-
     difference_type operator -(const ELFEntityIterator &Other) const {
       assert(EntitySize == Other.EntitySize &&
              "Subtracting iterators of different EntitySize!");
@@ -133,9 +140,11 @@ public:
   typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux;
   typedef Elf_Versym_Impl<ELFT> Elf_Versym;
   typedef ELFEntityIterator<const Elf_Dyn> Elf_Dyn_Iter;
+  typedef iterator_range<Elf_Dyn_Iter> Elf_Dyn_Range;
   typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter;
   typedef ELFEntityIterator<const Elf_Rel> Elf_Rel_Iter;
   typedef ELFEntityIterator<const Elf_Shdr> Elf_Shdr_Iter;
+  typedef iterator_range<Elf_Shdr_Iter> Elf_Shdr_Range;
 
   /// \brief Archive files are 2 byte aligned, so we need this for
   ///     PointerIntPair to work.
@@ -200,12 +209,6 @@ public:
       return *this;
     }
 
-    Elf_Sym_Iter &operator=(const Elf_Sym_Iter &Other) {
-      EntitySize = Other.EntitySize;
-      Current = Other.Current;
-      return *this;
-    }
-
     difference_type operator-(const Elf_Sym_Iter &Other) const {
       assert(EntitySize == Other.EntitySize &&
              "Subtracting iterators of different EntitySize!");
@@ -228,10 +231,10 @@ private:
   typedef SmallVector<const Elf_Shdr *, 2> Sections_t;
   typedef DenseMap<unsigned, unsigned> IndexMap_t;
 
-  MemoryBuffer *Buf;
+  StringRef Buf;
 
   const uint8_t *base() const {
-    return reinterpret_cast<const uint8_t *>(Buf->getBufferStart());
+    return reinterpret_cast<const uint8_t *>(Buf.data());
   }
 
   const Elf_Ehdr *Header;
@@ -249,7 +252,7 @@ private:
 
   /// \brief Represents a region described by entries in the .dynamic table.
   struct DynRegionInfo {
-    DynRegionInfo() : Addr(0), Size(0), EntSize(0) {}
+    DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {}
     /// \brief Address in current address space.
     const void *Addr;
     /// \brief Size in bytes of the region.
@@ -273,19 +276,19 @@ private:
     public:
     // If the integer is 0, this is an Elf_Verdef*.
     // If the integer is 1, this is an Elf_Vernaux*.
-    VersionMapEntry() : PointerIntPair<const void*, 1>(NULL, 0) { }
+    VersionMapEntry() : PointerIntPair<const void*, 1>(nullptr, 0) { }
     VersionMapEntry(const Elf_Verdef *verdef)
         : PointerIntPair<const void*, 1>(verdef, 0) { }
     VersionMapEntry(const Elf_Vernaux *vernaux)
         : PointerIntPair<const void*, 1>(vernaux, 1) { }
-    bool isNull() const { return getPointer() == NULL; }
+    bool isNull() const { return getPointer() == nullptr; }
     bool isVerdef() const { return !isNull() && getInt() == 0; }
     bool isVernaux() const { return !isNull() && getInt() == 1; }
     const Elf_Verdef *getVerdef() const {
-      return isVerdef() ? (const Elf_Verdef*)getPointer() : NULL;
+      return isVerdef() ? (const Elf_Verdef*)getPointer() : nullptr;
     }
     const Elf_Vernaux *getVernaux() const {
-      return isVernaux() ? (const Elf_Vernaux*)getPointer() : NULL;
+      return isVernaux() ? (const Elf_Vernaux*)getPointer() : nullptr;
     }
   };
   mutable SmallVector<VersionMapEntry, 16> VersionMap;
@@ -315,7 +318,12 @@ public:
   std::pair<const Elf_Shdr *, const Elf_Sym *>
   getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const;
 
-  ELFFile(MemoryBuffer *Object, error_code &ec);
+  ELFFile(StringRef Object, std::error_code &EC);
+
+  bool isMipsELF64() const {
+    return Header->e_machine == ELF::EM_MIPS &&
+      Header->getFileClass() == ELF::ELFCLASS64;
+  }
 
   bool isMips64EL() const {
     return Header->e_machine == ELF::EM_MIPS &&
@@ -325,6 +333,9 @@ public:
 
   Elf_Shdr_Iter begin_sections() const;
   Elf_Shdr_Iter end_sections() const;
+  Elf_Shdr_Range sections() const {
+    return make_range(begin_sections(), end_sections());
+  }
 
   Elf_Sym_Iter begin_symbols() const;
   Elf_Sym_Iter end_symbols() const;
@@ -333,12 +344,15 @@ public:
   /// \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));
+  }
 
   Elf_Sym_Iter begin_dynamic_symbols() const {
     if (DynSymRegion.Addr)
       return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr,
                           true);
-    return Elf_Sym_Iter(0, 0, true);
+    return Elf_Sym_Iter(0, nullptr, true);
   }
 
   Elf_Sym_Iter end_dynamic_symbols() const {
@@ -346,7 +360,7 @@ public:
       return Elf_Sym_Iter(DynSymRegion.EntSize,
                           (const char *)DynSymRegion.Addr + DynSymRegion.Size,
                           true);
-    return Elf_Sym_Iter(0, 0, true);
+    return Elf_Sym_Iter(0, nullptr, true);
   }
 
   Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const {
@@ -409,12 +423,10 @@ public:
   StringRef getLoadName() const;
 };
 
-// Use an alignment of 2 for the typedefs since that is the worst case for
-// ELF files in archives.
-typedef ELFFile<ELFType<support::little, 2, false> > ELF32LEFile;
-typedef ELFFile<ELFType<support::little, 2, true> > ELF64LEFile;
-typedef ELFFile<ELFType<support::big, 2, false> > ELF32BEFile;
-typedef ELFFile<ELFType<support::big, 2, true> > ELF64BEFile;
+typedef ELFFile<ELFType<support::little, false>> ELF32LEFile;
+typedef ELFFile<ELFType<support::little, true>> ELF64LEFile;
+typedef ELFFile<ELFType<support::big, false>> ELF32BEFile;
+typedef ELFFile<ELFType<support::big, true>> ELF64BEFile;
 
 // Iterate through the version definitions, and place each Elf_Verdef
 // in the VersionMap according to its index.
@@ -478,7 +490,7 @@ void ELFFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const {
 template <class ELFT>
 void ELFFile<ELFT>::LoadVersionMap() const {
   // If there is no dynamic symtab or version table, there is nothing to do.
-  if (DynSymRegion.Addr == NULL || dot_gnu_version_sec == NULL)
+  if (!DynSymRegion.Addr || !dot_gnu_version_sec)
     return;
 
   // Has the VersionMap already been loaded?
@@ -510,7 +522,7 @@ ELFFile<ELFT>::getSection(const Elf_Sym *symb) const {
   if (symb->st_shndx == ELF::SHN_XINDEX)
     return getSection(ExtendedSymbolTable.lookup(symb));
   if (symb->st_shndx >= ELF::SHN_LORESERVE)
-    return 0;
+    return nullptr;
   return getSection(symb->st_shndx);
 }
 
@@ -523,10 +535,10 @@ ELFFile<ELFT>::getSymbol(uint32_t Index) const {
 template <class ELFT>
 ErrorOr<ArrayRef<uint8_t> >
 ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const {
-  if (Sec->sh_offset + Sec->sh_size > Buf->getBufferSize())
+  if (Sec->sh_offset + Sec->sh_size > Buf.size())
     return object_error::parse_failed;
   const uint8_t *Start = base() + Sec->sh_offset;
-  return ArrayRef<uint8_t>(Start, Sec->sh_size);
+  return makeArrayRef(Start, Sec->sh_size);
 }
 
 template <class ELFT>
@@ -537,10 +549,16 @@ StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const {
 template <class ELFT>
 void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type,
                                           SmallVectorImpl<char> &Result) const {
-  if (!isMips64EL()) {
+  if (!isMipsELF64()) {
     StringRef Name = getRelocationTypeName(Type);
     Result.append(Name.begin(), Name.end());
   } else {
+    // The Mips N64 ABI allows up to three operations to be specified per
+    // relocation record. Unfortunately there's no easy way to test for the
+    // presence of N64 ELFs as they have no special flag that identifies them
+    // as being N64. We can safely assume at the moment that all Mips
+    // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough
+    // information to disambiguate between old vs new ABIs.
     uint8_t Type1 = (Type >> 0) & 0xFF;
     uint8_t Type2 = (Type >> 8) & 0xFF;
     uint8_t Type3 = (Type >> 16) & 0xFF;
@@ -565,7 +583,7 @@ std::pair<const typename ELFFile<ELFT>::Elf_Shdr *,
           const typename ELFFile<ELFT>::Elf_Sym *>
 ELFFile<ELFT>::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const {
   if (!Sec->sh_link)
-    return std::make_pair((const Elf_Shdr *)0, (const Elf_Sym *)0);
+    return std::make_pair(nullptr, nullptr);
   const Elf_Shdr *SymTable = getSection(Sec->sh_link);
   return std::make_pair(
       SymTable, getEntry<Elf_Sym>(SymTable, Rel->getSymbol(isMips64EL())));
@@ -583,7 +601,7 @@ void ELFFile<ELFT>::VerifyStrTab(const Elf_Shdr *sh) const {
 template <class ELFT>
 uint64_t ELFFile<ELFT>::getNumSections() const {
   assert(Header && "Header not initialized!");
-  if (Header->e_shnum == ELF::SHN_UNDEF) {
+  if (Header->e_shnum == ELF::SHN_UNDEF && Header->e_shoff > 0) {
     assert(SectionHeaderTable && "SectionHeaderTable not initialized!");
     return SectionHeaderTable->sh_size;
   }
@@ -602,22 +620,19 @@ typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const {
 }
 
 template <class ELFT>
-ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec)
-    : Buf(Object),
-      SectionHeaderTable(0),
-      dot_shstrtab_sec(0),
-      dot_strtab_sec(0),
-      dot_symtab_sec(0),
-      SymbolTableSectionHeaderIndex(0),
-      dot_gnu_version_sec(0),
-      dot_gnu_version_r_sec(0),
-      dot_gnu_version_d_sec(0),
-      dt_soname(0) {
-  const uint64_t FileSize = Buf->getBufferSize();
-
-  if (sizeof(Elf_Ehdr) > FileSize)
-    // FIXME: Proper error handling.
-    report_fatal_error("File too short!");
+ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
+    : Buf(Object), SectionHeaderTable(nullptr), dot_shstrtab_sec(nullptr),
+      dot_strtab_sec(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) {
+  const uint64_t FileSize = Buf.size();
+
+  if (sizeof(Elf_Ehdr) > FileSize) {
+    // File too short!
+    EC = object_error::parse_failed;
+    return;
+  }
 
   Header = reinterpret_cast<const Elf_Ehdr *>(base());
 
@@ -626,75 +641,92 @@ ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec)
 
   const uint64_t SectionTableOffset = Header->e_shoff;
 
-  if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)
-    // FIXME: Proper error handling.
-    report_fatal_error("Section header table goes past end of file!");
+  if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) {
+    // Section header table goes past end of file!
+    EC = object_error::parse_failed;
+    return;
+  }
 
   // The getNumSections() call below depends on SectionHeaderTable being set.
   SectionHeaderTable =
     reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
   const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize;
 
-  if (SectionTableOffset + SectionTableSize > FileSize)
-    // FIXME: Proper error handling.
-    report_fatal_error("Section table goes past end of file!");
+  if (SectionTableOffset + SectionTableSize > FileSize) {
+    // Section table goes past end of file!
+    EC = object_error::parse_failed;
+    return;
+  }
 
   // Scan sections for special sections.
 
-  for (Elf_Shdr_Iter SecI = begin_sections(), SecE = end_sections();
-       SecI != SecE; ++SecI) {
-    switch (SecI->sh_type) {
+  for (const Elf_Shdr &Sec : sections()) {
+    switch (Sec.sh_type) {
     case ELF::SHT_SYMTAB_SHNDX:
-      if (SymbolTableSectionHeaderIndex)
-        // FIXME: Proper error handling.
-        report_fatal_error("More than one .symtab_shndx!");
-      SymbolTableSectionHeaderIndex = &*SecI;
+      if (SymbolTableSectionHeaderIndex) {
+        // More than one .symtab_shndx!
+        EC = object_error::parse_failed;
+        return;
+      }
+      SymbolTableSectionHeaderIndex = &Sec;
       break;
     case ELF::SHT_SYMTAB:
-      if (dot_symtab_sec)
-        // FIXME: Proper error handling.
-        report_fatal_error("More than one .symtab!");
-      dot_symtab_sec = &*SecI;
-      dot_strtab_sec = getSection(SecI->sh_link);
+      if (dot_symtab_sec) {
+        // More than one .symtab!
+        EC = object_error::parse_failed;
+        return;
+      }
+      dot_symtab_sec = &Sec;
+      dot_strtab_sec = getSection(Sec.sh_link);
       break;
     case ELF::SHT_DYNSYM: {
-      if (DynSymRegion.Addr)
-        // FIXME: Proper error handling.
-        report_fatal_error("More than one .dynsym!");
-      DynSymRegion.Addr = base() + SecI->sh_offset;
-      DynSymRegion.Size = SecI->sh_size;
-      DynSymRegion.EntSize = SecI->sh_entsize;
-      const Elf_Shdr *DynStr = getSection(SecI->sh_link);
+      if (DynSymRegion.Addr) {
+        // 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;
       break;
     }
     case ELF::SHT_DYNAMIC:
-      if (DynamicRegion.Addr)
-        // FIXME: Proper error handling.
-        report_fatal_error("More than one .dynamic!");
-      DynamicRegion.Addr = base() + SecI->sh_offset;
-      DynamicRegion.Size = SecI->sh_size;
-      DynamicRegion.EntSize = SecI->sh_entsize;
+      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 != NULL)
-        // FIXME: Proper error handling.
-        report_fatal_error("More than one .gnu.version section!");
-      dot_gnu_version_sec = &*SecI;
+      if (dot_gnu_version_sec != nullptr) {
+        // More than one .gnu.version section!
+        EC = object_error::parse_failed;
+        return;
+      }
+      dot_gnu_version_sec = &Sec;
       break;
     case ELF::SHT_GNU_verdef:
-      if (dot_gnu_version_d_sec != NULL)
-        // FIXME: Proper error handling.
-        report_fatal_error("More than one .gnu.version_d section!");
-      dot_gnu_version_d_sec = &*SecI;
+      if (dot_gnu_version_d_sec != nullptr) {
+        // More than one .gnu.version_d section!
+        EC = object_error::parse_failed;
+        return;
+      }
+      dot_gnu_version_d_sec = &Sec;
       break;
     case ELF::SHT_GNU_verneed:
-      if (dot_gnu_version_r_sec != NULL)
-        // FIXME: Proper error handling.
-        report_fatal_error("More than one .gnu.version_r section!");
-      dot_gnu_version_r_sec = &*SecI;
+      if (dot_gnu_version_r_sec != nullptr) {
+        // More than one .gnu.version_r section!
+        EC = object_error::parse_failed;
+        return;
+      }
+      dot_gnu_version_r_sec = &Sec;
       break;
     }
   }
@@ -730,7 +762,7 @@ ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec)
     }
   }
 
-  ec = error_code::success();
+  EC = std::error_code();
 }
 
 // Get the symbol table index in the symtab section given a symbol
@@ -761,7 +793,7 @@ typename ELFFile<ELFT>::Elf_Shdr_Iter ELFFile<ELFT>::end_sections() const {
 template <class ELFT>
 typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::begin_symbols() const {
   if (!dot_symtab_sec)
-    return Elf_Sym_Iter(0, 0, false);
+    return Elf_Sym_Iter(0, nullptr, false);
   return Elf_Sym_Iter(dot_symtab_sec->sh_entsize,
                       (const char *)base() + dot_symtab_sec->sh_offset, false);
 }
@@ -769,7 +801,7 @@ typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::begin_symbols() const {
 template <class ELFT>
 typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::end_symbols() const {
   if (!dot_symtab_sec)
-    return Elf_Sym_Iter(0, 0, false);
+    return Elf_Sym_Iter(0, nullptr, false);
   return Elf_Sym_Iter(dot_symtab_sec->sh_entsize,
                       (const char *)base() + dot_symtab_sec->sh_offset +
                           dot_symtab_sec->sh_size,
@@ -782,14 +814,14 @@ ELFFile<ELFT>::begin_dynamic_table() const {
   if (DynamicRegion.Addr)
     return Elf_Dyn_Iter(DynamicRegion.EntSize,
                         (const char *)DynamicRegion.Addr);
-  return Elf_Dyn_Iter(0, 0);
+  return Elf_Dyn_Iter(0, nullptr);
 }
 
 template <class ELFT>
 typename ELFFile<ELFT>::Elf_Dyn_Iter
 ELFFile<ELFT>::end_dynamic_table(bool NULLEnd) const {
   if (!DynamicRegion.Addr)
-    return Elf_Dyn_Iter(0, 0);
+    return Elf_Dyn_Iter(0, nullptr);
   Elf_Dyn_Iter Ret(DynamicRegion.EntSize,
                     (const char *)DynamicRegion.Addr + DynamicRegion.Size);
 
@@ -809,17 +841,13 @@ ELFFile<ELFT>::end_dynamic_table(bool NULLEnd) const {
 template <class ELFT>
 StringRef ELFFile<ELFT>::getLoadName() const {
   if (!dt_soname) {
+    dt_soname = "";
     // Find the DT_SONAME entry
-    Elf_Dyn_Iter it = begin_dynamic_table();
-    Elf_Dyn_Iter ie = end_dynamic_table();
-    while (it != ie && it->getTag() != ELF::DT_SONAME)
-      ++it;
-
-    if (it != ie) {
-      dt_soname = getDynamicString(it->getVal());
-    } else {
-      dt_soname = "";
-    }
+    for (const auto &Entry : dynamic_table())
+      if (Entry.getTag() == ELF::DT_SONAME) {
+        dt_soname = getDynamicString(Entry.getVal());
+        break;
+      }
   }
   return dt_soname;
 }
@@ -842,7 +870,7 @@ template <class ELFT>
 const typename ELFFile<ELFT>::Elf_Shdr *
 ELFFile<ELFT>::getSection(uint32_t index) const {
   if (index == 0)
-    return 0;
+    return nullptr;
   if (!SectionHeaderTable || index >= getNumSections())
     // FIXME: Proper error handling.
     report_fatal_error("Invalid section index!");
@@ -871,7 +899,7 @@ const char *ELFFile<ELFT>::getString(const Elf_Shdr *section,
 template <class ELFT>
 const char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const {
   if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size)
-    return 0;
+    return nullptr;
   return (const char *)DynStrRegion.Addr + Offset;
 }
 
@@ -888,11 +916,8 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(Elf_Sym_Iter Sym) const {
 template <class ELFT>
 ErrorOr<StringRef> ELFFile<ELFT>::getSymbolName(const Elf_Shdr *Section,
                                                 const Elf_Sym *Symb) const {
-  if (Symb->st_name == 0) {
-    const Elf_Shdr *ContainingSec = getSection(Symb);
-    if (ContainingSec)
-      return getSectionName(ContainingSec);
-  }
+  if (Symb->st_name == 0)
+    return StringRef("");
 
   const Elf_Shdr *StrTab = getSection(Section->sh_link);
   if (Symb->st_name >= StrTab->sh_size)
@@ -913,7 +938,7 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section,
                                                    const Elf_Sym *symb,
                                                    bool &IsDefault) const {
   // Handle non-dynamic symbols.
-  if (section != DynSymRegion.Addr && section != 0) {
+  if (section != DynSymRegion.Addr && 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.
@@ -937,7 +962,7 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section,
   }
 
   // This is a dynamic symbol. Look in the GNU symbol version table.
-  if (dot_gnu_version_sec == NULL) {
+  if (!dot_gnu_version_sec) {
     // No version table.
     IsDefault = false;
     return StringRef("");