diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index 6d4a38083922..260e2ffbdcab 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -210,6 +210,10 @@ public: using Elf_Rela = typename ELFFile::Elf_Rela; using Elf_Dyn = typename ELFFile::Elf_Dyn; +private: + ELFObjectFile(MemoryBufferRef Object, const Elf_Shdr *DotDynSymSec, + const Elf_Shdr *DotSymtabSec, ArrayRef ShndxTable); + protected: ELFFile EF; @@ -328,7 +332,8 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(MemoryBufferRef Object, std::error_code &EC); + ELFObjectFile(ELFObjectFile &&Other); + static Expected> create(MemoryBufferRef Object); const Elf_Rel *getRel(DataRefImpl Rel) const; const Elf_Rela *getRela(DataRefImpl Rela) const; @@ -844,49 +849,59 @@ ELFObjectFile::getRela(DataRefImpl Rela) const { } template -ELFObjectFile::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) - : ELFObjectFileBase( - getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), - Object), - EF(Data.getBuffer()) { +Expected> +ELFObjectFile::create(MemoryBufferRef Object) { + ELFFile 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 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(Object, DotDynSymSec, DotSymtabSec, ShndxTable); } +template +ELFObjectFile::ELFObjectFile(MemoryBufferRef Object, + const Elf_Shdr *DotDynSymSec, + const Elf_Shdr *DotSymtabSec, + ArrayRef ShndxTable) + : ELFObjectFileBase( + getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), + Object), + EF(Data.getBuffer()), DotDynSymSec(DotDynSymSec), + DotSymtabSec(DotSymtabSec), ShndxTable(ShndxTable) {} + +template +ELFObjectFile::ELFObjectFile(ELFObjectFile &&Other) + : ELFObjectFile(Other.Data, Other.DotDynSymSec, Other.DotSymtabSec, + Other.ShndxTable) {} + template basic_symbol_iterator ELFObjectFile::symbol_begin() const { DataRefImpl Sym = toDRI(DotSymtabSec, 0); diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 873d0c6a0e2e..d4f22ad05b5f 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -69,8 +69,11 @@ template class DyldELFObject : public ELFObjectFile { typedef typename ELFDataTypeTypedefHelper::value_type addr_type; + DyldELFObject(ELFObjectFile &&Obj); + public: - DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec); + static Expected> + 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 -DyldELFObject::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC) - : ELFObjectFile(Wrapper, EC) { +DyldELFObject::DyldELFObject(ELFObjectFile &&Obj) + : ELFObjectFile(std::move(Obj)) { this->isDyldELFObject = true; } +template +Expected>> +DyldELFObject::create(MemoryBufferRef Wrapper) { + auto Obj = ELFObjectFile::create(Wrapper); + if (auto E = Obj.takeError()) + return std::move(E); + std::unique_ptr> Ret( + new DyldELFObject(std::move(*Obj))); + return std::move(Ret); +} + template void DyldELFObject::updateSectionAddress(const SectionRef &Sec, uint64_t Addr) { @@ -139,11 +153,12 @@ createRTDyldELFObject(MemoryBufferRef Buffer, const ObjectFile &SourceObject, typedef typename ELFFile::Elf_Shdr Elf_Shdr; typedef typename ELFDataTypeTypedefHelper::value_type addr_type; - std::error_code EC; - std::unique_ptr> Obj = - llvm::make_unique>(Buffer, EC); - if (EC) - return errorCodeToError(EC); + Expected>> ObjOrErr = + DyldELFObject::create(Buffer); + if (Error E = ObjOrErr.takeError()) + return std::move(E); + + std::unique_ptr> Obj = std::move(*ObjOrErr); // Iterate over all sections in the object. auto SI = SourceObject.section_begin(); diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index 4bca7cb6d8d2..0aad1c89a2d8 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -37,6 +37,15 @@ using namespace object; ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) : ObjectFile(Type, Source) {} +template +static Expected>> +createPtr(MemoryBufferRef Object) { + auto Ret = ELFObjectFile::create(Object); + if (Error E = Ret.takeError()) + return std::move(E); + return make_unique>(std::move(*Ret)); +} + Expected> ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { std::pair Ident = @@ -47,29 +56,22 @@ ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { if (MaxAlignment < 2) return createError("Insufficient alignment"); - std::error_code EC; - std::unique_ptr R; if (Ident.first == ELF::ELFCLASS32) { if (Ident.second == ELF::ELFDATA2LSB) - R.reset(new ELFObjectFile(Obj, EC)); + return createPtr(Obj); else if (Ident.second == ELF::ELFDATA2MSB) - R.reset(new ELFObjectFile(Obj, EC)); + return createPtr(Obj); else return createError("Invalid ELF data"); } else if (Ident.first == ELF::ELFCLASS64) { if (Ident.second == ELF::ELFDATA2LSB) - R.reset(new ELFObjectFile(Obj, EC)); + return createPtr(Obj); else if (Ident.second == ELF::ELFDATA2MSB) - R.reset(new ELFObjectFile(Obj, EC)); + return createPtr(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/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test index dcbac32f7196..8d2cb72ae7d7 100644 --- a/llvm/test/Object/invalid.test +++ b/llvm/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