forked from OSchip/llvm-project
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:
parent
a45919f54d
commit
ef421f9c18
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue