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.

llvm-svn: 315371
This commit is contained in:
Rafael Espindola 2017-10-10 21:21:16 +00:00
parent a45919f54d
commit ef421f9c18
4 changed files with 80 additions and 48 deletions

View 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);

View 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();

View 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 {

View 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