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;
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;
}
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);
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);
// 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) {
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();
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 =
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 {
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
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
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