]> granicus.if.org Git - llvm/commitdiff
Make the ELFObjectFile constructor private.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 10 Oct 2017 21:21:16 +0000 (21:21 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 10 Oct 2017 21:21:16 +0000 (21:21 +0000)
This forces every user to use the new create method that returns an
Expected. This in turn propagates better error messages.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315371 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 6d4a3808392276836fb6fdcac3de664c76485bda..260e2ffbdcab4a1ac65e98dc2a0b8acb47dc17ab 100644 (file)
@@ -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,49 +849,59 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
 }
 
 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);
index 873d0c6a0e2eb2602cf572f3c71df9e6eb094dec..d4f22ad05b5ff6822d6ac139164f1132f3a067dd 100644 (file)
@@ -69,8 +69,11 @@ template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
 
   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,11 +95,22 @@ 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) {
@@ -139,11 +153,12 @@ createRTDyldELFObject(MemoryBufferRef Buffer, const ObjectFile &SourceObject,
   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();
index 4bca7cb6d8d2fc19394f2e625164b44a67d35aae..0aad1c89a2d8b8f0535eff40b84240eb1c74538b 100644 (file)
@@ -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(MemoryBufferRef Obj) {
   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 {
index dcbac32f71966dea38cf6753bff13434cbd7d874..8d2cb72ae7d72e572937ae5f4bd23e331f39d947 100644 (file)
@@ -45,7 +45,7 @@ RUN: not llvm-readobj -t %p/Inputs/invalid-section-index.elf 2>&1 | FileCheck --
 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 multiple of sh_entsize
 
 
 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 offset
 
 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