diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2017-10-10 21:21:16 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2017-10-10 21:21:16 +0000 |
commit | 5c1b4435094258dd2c8a560fe1e583b1bf03b8d8 (patch) | |
tree | c7e6a9720131a311461fdf25b0d34509e609196b | |
parent | 668e1d7984126e64dffbcbcac95508d239fd3187 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315371 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Object/ELFObjectFile.h | 63 | ||||
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 31 | ||||
-rw-r--r-- | lib/Object/ELFObjectFile.cpp | 26 | ||||
-rw-r--r-- | test/Object/invalid.test | 8 |
4 files changed, 80 insertions, 48 deletions
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 6d4a3808392..260e2ffbdca 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -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 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); return basic_symbol_iterator(SymbolRef(Sym, this)); diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 873d0c6a0e2..d4f22ad05b5 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -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,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 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(); diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 4bca7cb6d8d..0aad1c89a2d 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -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 { diff --git a/test/Object/invalid.test b/test/Object/invalid.test index dcbac32f719..8d2cb72ae7d 100644 --- a/test/Object/invalid.test +++ b/test/Object/invalid.test @@ -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 |