[llvm] r315371 - Make the ELFObjectFile constructor private.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 10 14:21:16 PDT 2017


Author: rafael
Date: Tue Oct 10 14:21:16 2017
New Revision: 315371

URL: http://llvm.org/viewvc/llvm-project?rev=315371&view=rev
Log:
Make the ELFObjectFile constructor private.

This forces every user to use the new create method that returns an
Expected. This in turn propagates better error messages.

Modified:
    llvm/trunk/include/llvm/Object/ELFObjectFile.h
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
    llvm/trunk/lib/Object/ELFObjectFile.cpp
    llvm/trunk/test/Object/invalid.test

Modified: llvm/trunk/include/llvm/Object/ELFObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFObjectFile.h?rev=315371&r1=315370&r2=315371&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELFObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/ELFObjectFile.h Tue Oct 10 14:21:16 2017
@@ -210,6 +210,10 @@ public:
   using Elf_Rela = typename ELFFile<ELFT>::Elf_Rela;
   using Elf_Dyn = typename ELFFile<ELFT>::Elf_Dyn;
 
+private:
+  ELFObjectFile(MemoryBufferRef Object, const Elf_Shdr *DotDynSymSec,
+                const Elf_Shdr *DotSymtabSec, ArrayRef<Elf_Word> ShndxTable);
+
 protected:
   ELFFile<ELFT> EF;
 
@@ -328,7 +332,8 @@ protected:
   bool isDyldELFObject;
 
 public:
-  ELFObjectFile(MemoryBufferRef Object, std::error_code &EC);
+  ELFObjectFile(ELFObjectFile<ELFT> &&Other);
+  static Expected<ELFObjectFile<ELFT>> create(MemoryBufferRef Object);
 
   const Elf_Rel *getRel(DataRefImpl Rel) const;
   const Elf_Rela *getRela(DataRefImpl Rela) const;
@@ -844,50 +849,60 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl
 }
 
 template <class ELFT>
-ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC)
-    : ELFObjectFileBase(
-          getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits),
-          Object),
-      EF(Data.getBuffer()) {
+Expected<ELFObjectFile<ELFT>>
+ELFObjectFile<ELFT>::create(MemoryBufferRef Object) {
+  ELFFile<ELFT> EF(Object.getBuffer());
+
   auto SectionsOrErr = EF.sections();
-  if (!SectionsOrErr) {
-    EC = errorToErrorCode(SectionsOrErr.takeError());
-    return;
-  }
+  if (!SectionsOrErr)
+    return SectionsOrErr.takeError();
+
+  const Elf_Shdr *DotDynSymSec = nullptr;
+  const Elf_Shdr *DotSymtabSec = nullptr;
+  ArrayRef<Elf_Word> ShndxTable;
   for (const Elf_Shdr &Sec : *SectionsOrErr) {
     switch (Sec.sh_type) {
     case ELF::SHT_DYNSYM: {
-      if (DotDynSymSec) {
-        // More than one .dynsym!
-        EC = object_error::parse_failed;
-        return;
-      }
+      if (DotDynSymSec)
+        return createError("More than one dynamic symbol table!");
       DotDynSymSec = &Sec;
       break;
     }
     case ELF::SHT_SYMTAB: {
-      if (DotSymtabSec) {
-        // More than one .dynsym!
-        EC = object_error::parse_failed;
-        return;
-      }
+      if (DotSymtabSec)
+        return createError("More than one static symbol table!");
       DotSymtabSec = &Sec;
       break;
     }
     case ELF::SHT_SYMTAB_SHNDX: {
       auto TableOrErr = EF.getSHNDXTable(Sec);
-      if (!TableOrErr) {
-        EC = errorToErrorCode(TableOrErr.takeError());
-        return;
-      }
+      if (!TableOrErr)
+        return TableOrErr.takeError();
       ShndxTable = *TableOrErr;
       break;
     }
     }
   }
+  return ELFObjectFile<ELFT>(Object, DotDynSymSec, DotSymtabSec, ShndxTable);
 }
 
 template <class ELFT>
+ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object,
+                                   const Elf_Shdr *DotDynSymSec,
+                                   const Elf_Shdr *DotSymtabSec,
+                                   ArrayRef<Elf_Word> ShndxTable)
+    : ELFObjectFileBase(
+          getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits),
+          Object),
+      EF(Data.getBuffer()), DotDynSymSec(DotDynSymSec),
+      DotSymtabSec(DotSymtabSec), ShndxTable(ShndxTable) {}
+
+template <class ELFT>
+ELFObjectFile<ELFT>::ELFObjectFile(ELFObjectFile<ELFT> &&Other)
+    : ELFObjectFile(Other.Data, Other.DotDynSymSec, Other.DotSymtabSec,
+                    Other.ShndxTable) {}
+
+template <class ELFT>
 basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const {
   DataRefImpl Sym = toDRI(DotSymtabSec, 0);
   return basic_symbol_iterator(SymbolRef(Sym, this));

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp?rev=315371&r1=315370&r2=315371&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp Tue Oct 10 14:21:16 2017
@@ -69,8 +69,11 @@ template <class ELFT> class DyldELFObjec
 
   typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type;
 
+  DyldELFObject(ELFObjectFile<ELFT> &&Obj);
+
 public:
-  DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec);
+  static Expected<std::unique_ptr<DyldELFObject>>
+  create(MemoryBufferRef Wrapper);
 
   void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);
 
@@ -92,12 +95,23 @@ public:
 // actual memory.  Ultimately, the Binary parent class will take ownership of
 // this MemoryBuffer object but not the underlying memory.
 template <class ELFT>
-DyldELFObject<ELFT>::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC)
-    : ELFObjectFile<ELFT>(Wrapper, EC) {
+DyldELFObject<ELFT>::DyldELFObject(ELFObjectFile<ELFT> &&Obj)
+    : ELFObjectFile<ELFT>(std::move(Obj)) {
   this->isDyldELFObject = true;
 }
 
 template <class ELFT>
+Expected<std::unique_ptr<DyldELFObject<ELFT>>>
+DyldELFObject<ELFT>::create(MemoryBufferRef Wrapper) {
+  auto Obj = ELFObjectFile<ELFT>::create(Wrapper);
+  if (auto E = Obj.takeError())
+    return std::move(E);
+  std::unique_ptr<DyldELFObject<ELFT>> Ret(
+      new DyldELFObject<ELFT>(std::move(*Obj)));
+  return std::move(Ret);
+}
+
+template <class ELFT>
 void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec,
                                                uint64_t Addr) {
   DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
@@ -139,11 +153,12 @@ createRTDyldELFObject(MemoryBufferRef Bu
   typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type;
 
-  std::error_code EC;
-  std::unique_ptr<DyldELFObject<ELFT>> Obj =
-      llvm::make_unique<DyldELFObject<ELFT>>(Buffer, EC);
-  if (EC)
-    return errorCodeToError(EC);
+  Expected<std::unique_ptr<DyldELFObject<ELFT>>> ObjOrErr =
+      DyldELFObject<ELFT>::create(Buffer);
+  if (Error E = ObjOrErr.takeError())
+    return std::move(E);
+
+  std::unique_ptr<DyldELFObject<ELFT>> Obj = std::move(*ObjOrErr);
 
   // Iterate over all sections in the object.
   auto SI = SourceObject.section_begin();

Modified: llvm/trunk/lib/Object/ELFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ELFObjectFile.cpp?rev=315371&r1=315370&r2=315371&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ELFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/ELFObjectFile.cpp Tue Oct 10 14:21:16 2017
@@ -37,6 +37,15 @@ using namespace object;
 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
     : ObjectFile(Type, Source) {}
 
+template <class ELFT>
+static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
+createPtr(MemoryBufferRef Object) {
+  auto Ret = ELFObjectFile<ELFT>::create(Object);
+  if (Error E = Ret.takeError())
+    return std::move(E);
+  return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
+}
+
 Expected<std::unique_ptr<ObjectFile>>
 ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
   std::pair<unsigned char, unsigned char> Ident =
@@ -47,29 +56,22 @@ ObjectFile::createELFObjectFile(MemoryBu
   if (MaxAlignment < 2)
     return createError("Insufficient alignment");
 
-  std::error_code EC;
-  std::unique_ptr<ObjectFile> R;
   if (Ident.first == ELF::ELFCLASS32) {
     if (Ident.second == ELF::ELFDATA2LSB)
-      R.reset(new ELFObjectFile<ELF32LE>(Obj, EC));
+      return createPtr<ELF32LE>(Obj);
     else if (Ident.second == ELF::ELFDATA2MSB)
-      R.reset(new ELFObjectFile<ELF32BE>(Obj, EC));
+      return createPtr<ELF32BE>(Obj);
     else
       return createError("Invalid ELF data");
   } else if (Ident.first == ELF::ELFCLASS64) {
     if (Ident.second == ELF::ELFDATA2LSB)
-      R.reset(new ELFObjectFile<ELF64LE>(Obj, EC));
+      return createPtr<ELF64LE>(Obj);
     else if (Ident.second == ELF::ELFDATA2MSB)
-      R.reset(new ELFObjectFile<ELF64BE>(Obj, EC));
+      return createPtr<ELF64BE>(Obj);
     else
       return createError("Invalid ELF data");
-  } else {
-    return createError("Invalid ELF class");
   }
-
-  if (EC)
-    return errorCodeToError(EC);
-  return std::move(R);
+  return createError("Invalid ELF class");
 }
 
 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {

Modified: llvm/trunk/test/Object/invalid.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/invalid.test?rev=315371&r1=315370&r2=315371&view=diff
==============================================================================
--- llvm/trunk/test/Object/invalid.test (original)
+++ llvm/trunk/test/Object/invalid.test Tue Oct 10 14:21:16 2017
@@ -45,7 +45,7 @@ RUN: not llvm-readobj -t %p/Inputs/inval
 INVALID-SECTION-INDEX: invalid section index
 
 RUN: not llvm-readobj -s %p/Inputs/invalid-section-size.elf 2>&1 | FileCheck --check-prefix=INVALID-SECTION-SIZE %s
-INVALID-SECTION-SIZE: Invalid data was encountered while parsing the file
+INVALID-SECTION-SIZE: invalid section header entry size (e_shentsize) in ELF header
 
 
 RUN: not llvm-readobj -t %p/Inputs/invalid-symbol-table-size.elf 2>&1 | FileCheck --check-prefix=INVALID-SYMTAB-SIZE %s
@@ -53,7 +53,7 @@ INVALID-SYMTAB-SIZE: size is not a multi
 
 
 RUN: not llvm-readobj -t %p/Inputs/invalid-xindex-size.elf 2>&1 | FileCheck --check-prefix=INVALID-XINDEX-SIZE %s
-INVALID-XINDEX-SIZE: Invalid data was encountered while parsing the file
+INVALID-XINDEX-SIZE: invalid section contents size
 
 RUN: not llvm-readobj -t %p/Inputs/invalid-e_shnum.elf 2>&1 | FileCheck --check-prefix=INVALID-SH-NUM %s
 INVALID-SH-NUM: invalid e_phentsize
@@ -70,14 +70,14 @@ INVALID-RELOC-SH-OFFSET: invalid section
 
 RUN: not llvm-readobj -t %p/Inputs/invalid-sections-address-alignment.x86-64 2>&1 | \
 RUN:   FileCheck --check-prefix=INVALID-SEC-ADDRESS-ALIGNMENT %s
-INVALID-SEC-ADDRESS-ALIGNMENT: Invalid data was encountered while parsing the file
+INVALID-SEC-ADDRESS-ALIGNMENT: invalid alignment of section headers
 
 RUN: not llvm-readobj -t %p/Inputs/invalid-section-size2.elf 2>&1 | \
 RUN:   FileCheck --check-prefix=INVALID-SECTION-SIZE2 %s
 INVALID-SECTION-SIZE2: invalid section offset
 
 RUN: not llvm-readobj -t %p/Inputs/invalid-sections-num.elf 2>&1 | FileCheck --check-prefix=INVALID-SECTION-NUM %s
-INVALID-SECTION-NUM: Invalid data was encountered while parsing the file
+INVALID-SECTION-NUM: section table goes past the end of file
 
 RUN: not llvm-readobj -r %p/Inputs/invalid-rel-sym.elf 2>&1 | FileCheck --check-prefix=INVALID-REL-SYM %s
 INVALID-REL-SYM: invalid section offset




More information about the llvm-commits mailing list