aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2017-10-10 21:21:16 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2017-10-10 21:21:16 +0000
commit5c1b4435094258dd2c8a560fe1e583b1bf03b8d8 (patch)
treec7e6a9720131a311461fdf25b0d34509e609196b
parent668e1d7984126e64dffbcbcac95508d239fd3187 (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.h63
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp31
-rw-r--r--lib/Object/ELFObjectFile.cpp26
-rw-r--r--test/Object/invalid.test8
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