Binary(const Binary &other) = delete;
virtual ~Binary();
+ virtual Error initContent() { return Error::success(); };
+
StringRef getData() const;
StringRef getFileName() const;
MemoryBufferRef getMemoryBufferRef() const;
///
/// @param Source The data to create the Binary from.
Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
- LLVMContext *Context = nullptr);
+ LLVMContext *Context = nullptr,
+ bool InitContent = true);
template <typename T> class OwningBinary {
std::unique_ptr<T> Bin;
}
Expected<OwningBinary<Binary>> createBinary(StringRef Path,
- LLVMContext *Context = nullptr);
+ LLVMContext *Context = nullptr,
+ bool InitContent = true);
} // end namespace object
return SectionRef(toDRI(Sec), this);
}
+ bool IsContentValid() const { return ContentValid; }
+
private:
ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF,
const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec,
const Elf_Shdr *DotSymtabShndxSec);
+ bool ContentValid = false;
+
protected:
ELFFile<ELFT> EF;
const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section.
const Elf_Shdr *DotSymtabShndxSec = nullptr; // SHT_SYMTAB_SHNDX section.
+ Error initContent() override;
+
void moveSymbolNext(DataRefImpl &Symb) const override;
Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
public:
ELFObjectFile(ELFObjectFile<ELFT> &&Other);
- static Expected<ELFObjectFile<ELFT>> create(MemoryBufferRef Object);
+ static Expected<ELFObjectFile<ELFT>> create(MemoryBufferRef Object,
+ bool InitContent = true);
const Elf_Rel *getRel(DataRefImpl Rel) const;
const Elf_Rela *getRela(DataRefImpl Rela) const;
++Sym.d.b;
}
+template <class ELFT> Error ELFObjectFile<ELFT>::initContent() {
+ auto SectionsOrErr = EF.sections();
+ if (!SectionsOrErr)
+ return SectionsOrErr.takeError();
+
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ switch (Sec.sh_type) {
+ case ELF::SHT_DYNSYM: {
+ if (!DotDynSymSec)
+ DotDynSymSec = &Sec;
+ break;
+ }
+ case ELF::SHT_SYMTAB: {
+ if (!DotSymtabSec)
+ DotSymtabSec = &Sec;
+ break;
+ }
+ case ELF::SHT_SYMTAB_SHNDX: {
+ if (!DotSymtabShndxSec)
+ DotSymtabShndxSec = &Sec;
+ break;
+ }
+ }
+ }
+
+ ContentValid = true;
+ return Error::success();
+}
+
template <class ELFT>
Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const {
const Elf_Sym *ESym = getSymbol(Sym);
template <class ELFT>
Expected<ELFObjectFile<ELFT>>
-ELFObjectFile<ELFT>::create(MemoryBufferRef Object) {
+ELFObjectFile<ELFT>::create(MemoryBufferRef Object, bool InitContent) {
auto EFOrErr = ELFFile<ELFT>::create(Object.getBuffer());
if (Error E = EFOrErr.takeError())
return std::move(E);
- auto EF = std::move(*EFOrErr);
-
- auto SectionsOrErr = EF.sections();
- if (!SectionsOrErr)
- return SectionsOrErr.takeError();
- const Elf_Shdr *DotDynSymSec = nullptr;
- const Elf_Shdr *DotSymtabSec = nullptr;
- const Elf_Shdr *DotSymtabShndxSec = nullptr;
- for (const Elf_Shdr &Sec : *SectionsOrErr) {
- switch (Sec.sh_type) {
- case ELF::SHT_DYNSYM: {
- if (!DotDynSymSec)
- DotDynSymSec = &Sec;
- break;
- }
- case ELF::SHT_SYMTAB: {
- if (!DotSymtabSec)
- DotSymtabSec = &Sec;
- break;
- }
- case ELF::SHT_SYMTAB_SHNDX: {
- if (!DotSymtabShndxSec)
- DotSymtabShndxSec = &Sec;
- break;
- }
- }
- }
- return ELFObjectFile<ELFT>(Object, EF, DotDynSymSec, DotSymtabSec,
- DotSymtabShndxSec);
+ ELFObjectFile<ELFT> Obj = {Object, std::move(*EFOrErr), nullptr, nullptr,
+ nullptr};
+ if (InitContent)
+ if (Error E = Obj.initContent())
+ return std::move(E);
+ return std::move(Obj);
}
template <class ELFT>
createObjectFile(StringRef ObjectPath);
static Expected<std::unique_ptr<ObjectFile>>
- createObjectFile(MemoryBufferRef Object, llvm::file_magic Type);
+ createObjectFile(MemoryBufferRef Object, llvm::file_magic Type,
+ bool InitContent = true);
static Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object) {
return createObjectFile(Object, llvm::file_magic::unknown);
createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
static Expected<std::unique_ptr<ObjectFile>>
- createELFObjectFile(MemoryBufferRef Object);
+ createELFObjectFile(MemoryBufferRef Object, bool InitContent = true);
static Expected<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Object,
// construction aux.
static Expected<std::unique_ptr<SymbolicFile>>
createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type,
- LLVMContext *Context);
+ LLVMContext *Context, bool InitContent = true);
static Expected<std::unique_ptr<SymbolicFile>>
createSymbolicFile(MemoryBufferRef Object) {
return createSymbolicFile(Object, llvm::file_magic::unknown, nullptr);
}
- static Expected<OwningBinary<SymbolicFile>>
- createSymbolicFile(StringRef ObjectPath);
static bool classof(const Binary *v) {
return v->isSymbolic();
MemoryBufferRef Binary::getMemoryBufferRef() const { return Data; }
Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
- LLVMContext *Context) {
+ LLVMContext *Context,
+ bool InitContent) {
file_magic Type = identify_magic(Buffer.getBuffer());
switch (Type) {
case file_magic::xcoff_object_32:
case file_magic::xcoff_object_64:
case file_magic::wasm_object:
- return ObjectFile::createSymbolicFile(Buffer, Type, Context);
+ return ObjectFile::createSymbolicFile(Buffer, Type, Context, InitContent);
case file_magic::macho_universal_binary:
return MachOUniversalBinary::create(Buffer);
case file_magic::windows_resource:
llvm_unreachable("Unexpected Binary File Type");
}
-Expected<OwningBinary<Binary>> object::createBinary(StringRef Path,
- LLVMContext *Context) {
+Expected<OwningBinary<Binary>>
+object::createBinary(StringRef Path, LLVMContext *Context, bool InitContent) {
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
/*RequiresNullTerminator=*/false);
std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
Expected<std::unique_ptr<Binary>> BinOrErr =
- createBinary(Buffer->getMemBufferRef(), Context);
+ createBinary(Buffer->getMemBufferRef(), Context, InitContent);
if (!BinOrErr)
return BinOrErr.takeError();
std::unique_ptr<Binary> &Bin = BinOrErr.get();
template <class ELFT>
static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
-createPtr(MemoryBufferRef Object) {
- auto Ret = ELFObjectFile<ELFT>::create(Object);
+createPtr(MemoryBufferRef Object, bool InitContent) {
+ auto Ret = ELFObjectFile<ELFT>::create(Object, InitContent);
if (Error E = Ret.takeError())
return std::move(E);
return std::make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
}
Expected<std::unique_ptr<ObjectFile>>
-ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
+ObjectFile::createELFObjectFile(MemoryBufferRef Obj, bool InitContent) {
std::pair<unsigned char, unsigned char> Ident =
getElfArchType(Obj.getBuffer());
std::size_t MaxAlignment =
if (Ident.first == ELF::ELFCLASS32) {
if (Ident.second == ELF::ELFDATA2LSB)
- return createPtr<ELF32LE>(Obj);
+ return createPtr<ELF32LE>(Obj, InitContent);
else if (Ident.second == ELF::ELFDATA2MSB)
- return createPtr<ELF32BE>(Obj);
+ return createPtr<ELF32BE>(Obj, InitContent);
else
return createError("Invalid ELF data");
} else if (Ident.first == ELF::ELFCLASS64) {
if (Ident.second == ELF::ELFDATA2LSB)
- return createPtr<ELF64LE>(Obj);
+ return createPtr<ELF64LE>(Obj, InitContent);
else if (Ident.second == ELF::ELFDATA2MSB)
- return createPtr<ELF64BE>(Obj);
+ return createPtr<ELF64BE>(Obj, InitContent);
else
return createError("Invalid ELF data");
}
}
Expected<std::unique_ptr<ObjectFile>>
-ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) {
+ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
+ bool InitContent) {
StringRef Data = Object.getBuffer();
if (Type == file_magic::unknown)
Type = identify_magic(Data);
case file_magic::elf_executable:
case file_magic::elf_shared_object:
case file_magic::elf_core:
- return createELFObjectFile(Object);
+ return createELFObjectFile(Object, InitContent);
case file_magic::macho_object:
case file_magic::macho_executable:
case file_magic::macho_fixed_virtual_memory_shared_lib:
Expected<std::unique_ptr<SymbolicFile>>
SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type,
- LLVMContext *Context) {
+ LLVMContext *Context, bool InitContent) {
StringRef Data = Object.getBuffer();
if (Type == file_magic::unknown)
Type = identify_magic(Data);
case file_magic::xcoff_object_32:
case file_magic::xcoff_object_64:
case file_magic::wasm_object:
- return ObjectFile::createObjectFile(Object, Type);
+ return ObjectFile::createObjectFile(Object, Type, InitContent);
case file_magic::coff_import_library:
return std::unique_ptr<SymbolicFile>(new COFFImportFile(Object));
case file_magic::elf_relocatable:
case file_magic::macho_object:
case file_magic::coff_object: {
Expected<std::unique_ptr<ObjectFile>> Obj =
- ObjectFile::createObjectFile(Object, Type);
+ ObjectFile::createObjectFile(Object, Type, InitContent);
if (!Obj || !Context)
return std::move(Obj);
## when the e_shentsize field is broken.
# RUN: yaml2obj %s --docnum=9 -o %t9
-# RUN: not llvm-readobj -S %t9 2>&1 | FileCheck --check-prefix=INVALID-SH-ENTSIZE %s
+# RUN: not llvm-readobj -S %t9 2>&1 | \
+# RUN: FileCheck -DFILE=%t9 --implicit-check-not=warning: --check-prefix=INVALID-SH-ENTSIZE %s
-# INVALID-SH-ENTSIZE: error: {{.*}}: invalid e_shentsize in ELF header: 1
+# INVALID-SH-ENTSIZE: LoadName: <Not found>
+# INVALID-SH-ENTSIZE-NEXT: error: '[[FILE]]': unable to continue dumping, the file is corrupt: invalid e_shentsize in ELF header: 1
--- !ELF
FileHeader:
## when the e_shnum field is broken (is greater than the actual number of sections).
# RUN: yaml2obj %s --docnum=15 -o %t15
-# RUN: not llvm-readobj -S %t15 2>&1 | FileCheck --check-prefix=INVALID-SECTION-NUM %s
+# RUN: not llvm-readobj -S %t15 2>&1 | \
+# RUN: FileCheck -DFILE=%t15 --implicit-check-not=warning: --check-prefix=INVALID-SECTION-NUM %s
+
+# INVALID-SECTION-NUM: LoadName: <Not found>
+# INVALID-SECTION-NUM-NEXT: error: '[[FILE]]': unable to continue dumping, the file is corrupt: section table goes past the end of file
-# INVALID-SECTION-NUM: error: {{.*}}: section table goes past the end of file
-
--- !ELF
FileHeader:
Class: ELFCLASS64
# RUN: yaml2obj --docnum=25 %s -o %t25
# RUN: not llvm-readobj -h %t25 2>&1 | FileCheck -DFILE=%t25 --check-prefix=INVALID-SEC-NUM1 %s
-# INVALID-SEC-NUM1: error: '[[FILE]]': invalid section header table offset (e_shoff = 0x58) or invalid number of sections specified in the first section header's sh_size field (0x3ffffffffffffff)
+# INVALID-SEC-NUM1: error: '[[FILE]]': unable to continue dumping, the file is corrupt: invalid section header table offset (e_shoff = 0x58) or invalid number of sections specified in the first section header's sh_size field (0x3ffffffffffffff)
--- !ELF
FileHeader:
# RUN: yaml2obj --docnum=26 %s -o %t26
# RUN: not llvm-readobj -h %t26 2>&1 | FileCheck -DFILE=%t26 --check-prefix=INVALID-SEC-NUM2 %s
-# INVALID-SEC-NUM2: error: '[[FILE]]': invalid number of sections specified in the NULL section's sh_size field (288230376151711744)
+# INVALID-SEC-NUM2: error: '[[FILE]]': unable to continue dumping, the file is corrupt: invalid number of sections specified in the NULL section's sh_size field (288230376151711744)
--- !ELF
FileHeader:
# RUN: yaml2obj --docnum=27 %s -o %t27
# RUN: not llvm-readobj -h %t27 2>&1 | FileCheck -DFILE=%t27 --check-prefix=INVALID-SEC-NUM3 %s
-# INVALID-SEC-NUM3: error: '[[FILE]]': section header table goes past the end of the file: e_shoff = 0xffffffffffffffff
-
+# INVALID-SEC-NUM3: error: '[[FILE]]': unable to continue dumping, the file is corrupt: section header table goes past the end of the file: e_shoff = 0xffffffffffffffff
+
--- !ELF
FileHeader:
Class: ELFCLASS64
# LANAI-NEXT: StringTableSectionIndex: 2
# LANAI-NEXT:}
# LANAI-NOT:{{.}}
+
+## Check we are able to dump the file header when the section header table can't be read.
+
+# RUN: yaml2obj %s --docnum=4 -o %t.invalid1
+# RUN: not llvm-readobj --file-headers %t.invalid1 2>&1 \
+# RUN: | FileCheck %s --implicit-check-not=warning: -DFILE=%t.invalid1 \
+# RUN: -DSECHDRCOUNT=8192 -DSECHDRSTRTABINDEX=12288 --check-prefix=INVALID-LLVM
+# RUN: not llvm-readelf --file-headers %t.invalid1 2>&1 \
+# RUN: | FileCheck %s --implicit-check-not=warning: -DFILE=%t.invalid1 \
+# RUN: -DSECHDRCOUNT=8192 -DSECHDRSTRTABINDEX=12288 --check-prefix=INVALID-GNU
+
+# INVALID-LLVM: File: [[FILE]]
+# INVALID-LLVM-NEXT: Format: elf64-unknown
+# INVALID-LLVM-NEXT: Arch: unknown
+# INVALID-LLVM-NEXT: AddressSize: 64bit
+# INVALID-LLVM-NEXT: LoadName: <Not found>
+# INVALID-LLVM-NEXT: ElfHeader {
+# INVALID-LLVM-NEXT: Ident {
+# INVALID-LLVM-NEXT: Magic: (7F 45 4C 46)
+# INVALID-LLVM-NEXT: Class: 64-bit (0x2)
+# INVALID-LLVM-NEXT: DataEncoding: LittleEndian (0x1)
+# INVALID-LLVM-NEXT: FileVersion: 1
+# INVALID-LLVM-NEXT: OS/ABI: SystemV (0x0)
+# INVALID-LLVM-NEXT: ABIVersion: 0
+# INVALID-LLVM-NEXT: Unused: (00 00 00 00 00 00 00)
+# INVALID-LLVM-NEXT: }
+# INVALID-LLVM-NEXT: Type: Relocatable (0x1)
+# INVALID-LLVM-NEXT: Machine: EM_NONE (0x0)
+# INVALID-LLVM-NEXT: Version: 1
+# INVALID-LLVM-NEXT: Entry: 0x0
+# INVALID-LLVM-NEXT: ProgramHeaderOffset: 0x0
+# INVALID-LLVM-NEXT: SectionHeaderOffset: 0x1000
+# INVALID-LLVM-NEXT: Flags [ (0x0)
+# INVALID-LLVM-NEXT: ]
+# INVALID-LLVM-NEXT: HeaderSize: 64
+# INVALID-LLVM-NEXT: ProgramHeaderEntrySize: 0
+# INVALID-LLVM-NEXT: ProgramHeaderCount: 0
+# INVALID-LLVM-NEXT: SectionHeaderEntrySize: 64
+# INVALID-LLVM-NEXT: SectionHeaderCount: [[SECHDRCOUNT]]
+# INVALID-LLVM-NEXT: StringTableSectionIndex: [[SECHDRSTRTABINDEX]]
+# INVALID-LLVM-NEXT: }
+# INVALID-LLVM-NEXT: error: '[[FILE]]': unable to continue dumping, the file is corrupt: section header table goes past the end of the file: e_shoff = 0x1000
+
+# INVALID-GNU: ELF Header:
+# INVALID-GNU-NEXT: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
+# INVALID-GNU-NEXT: Class: ELF64
+# INVALID-GNU-NEXT: Data: 2's complement, little endian
+# INVALID-GNU-NEXT: Version: 1 (current)
+# INVALID-GNU-NEXT: OS/ABI: UNIX - System V
+# INVALID-GNU-NEXT: ABI Version: 0
+# INVALID-GNU-NEXT: Type: REL (Relocatable file)
+# INVALID-GNU-NEXT: Machine: None
+# INVALID-GNU-NEXT: Version: 0x1
+# INVALID-GNU-NEXT: Entry point address: 0x0
+# INVALID-GNU-NEXT: Start of program headers: 0 (bytes into file)
+# INVALID-GNU-NEXT: Start of section headers: 4096 (bytes into file)
+# INVALID-GNU-NEXT: Flags: 0x0
+# INVALID-GNU-NEXT: Size of this header: 64 (bytes)
+# INVALID-GNU-NEXT: Size of program headers: 0 (bytes)
+# INVALID-GNU-NEXT: Number of program headers: 0
+# INVALID-GNU-NEXT: Size of section headers: 64 (bytes)
+# INVALID-GNU-NEXT: Number of section headers: [[SECHDRCOUNT]]
+# INVALID-GNU-NEXT: Section header string table index: [[SECHDRSTRTABINDEX]]
+# INVALID-GNU-NEXT: error: '[[FILE]]': unable to continue dumping, the file is corrupt: section header table goes past the end of the file: e_shoff = 0x1000
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+## The section header table offset goes past the EOF.
+ EShOff: 0x1000
+## The number of section headers is too large, the file is
+## too little to contain so many sections.
+ EShNum: [[SHNUM=0x2000]]
+## The index of the section name string table is too large.
+## The section would be past the EOF.
+ EShStrNdx: [[SHSTRNDX=0x3000]]
+SectionHeaderTable:
+ NoHeaders: true
+
+## Check we don't dump anything except the file header when the section header table can't be read.
+
+# RUN: not llvm-readobj -a %t.invalid1 2>&1 \
+# RUN: | FileCheck %s -DFILE=%t.invalid1 -DSECHDRCOUNT=8192 -DSECHDRSTRTABINDEX=12288 --check-prefix=INVALID-LLVM
+# RUN: not llvm-readelf -a %t.invalid1 2>&1 \
+# RUN: | FileCheck %s -DFILE=%t.invalid1 -DSECHDRCOUNT=8192 -DSECHDRSTRTABINDEX=12288 --check-prefix=INVALID-GNU
+
+## Check what we print when e_shnum == 0, e_shstrndx == SHN_XINDEX and the section header table can't be read.
+
+# RUN: yaml2obj %s -DSHNUM=0 -DSHSTRNDX=0xffff --docnum=4 -o %t.invalid2
+# RUN: not llvm-readobj --file-headers %t.invalid2 2>&1 \
+# RUN: | FileCheck %s -DFILE=%t.invalid2 -DSECHDRCOUNT="<?>" -DSECHDRSTRTABINDEX="<?>" --check-prefix=INVALID-LLVM
+# RUN: not llvm-readelf --file-headers %t.invalid2 2>&1 \
+# RUN: | FileCheck %s -DFILE=%t.invalid2 -DSECHDRCOUNT="<?>" -DSECHDRSTRTABINDEX="<?>" --check-prefix=INVALID-GNU
## Test that we are still able to override e_shoff, e_shnum and e_shstrndx
## fields even when we do not produce section headers.
# RUN: yaml2obj %s --docnum=6 -o %t4
-# RUN: llvm-readelf --file-headers %t4 | FileCheck %s --check-prefix=NO-HEADERS-OVERRIDE
+# RUN: not llvm-readelf --file-headers %t4 | FileCheck %s --check-prefix=NO-HEADERS-OVERRIDE
# NO-HEADERS-OVERRIDE: Start of section headers: 2 (bytes into file)
# NO-HEADERS-OVERRIDE: Number of section headers: 3
EShOff: 0x2
EShNum: 0x3
EShStrNdx: 0x4
-Sections:
- - Name: .foo
- Type: SHT_PROGBITS
-## FIXME: we have to set an arbitrary size to create a
-## piece of dummy data to make llvm-readelf happy.
-## See: https://bugs.llvm.org/show_bug.cgi?id=40804
- Size: 0x100
SectionHeaderTable:
NoHeaders: true
else
ELFDumperStyle.reset(new LLVMStyle<ELFT>(Writer, *this));
+ if (!O.IsContentValid())
+ return;
+
typename ELFT::ShdrRange Sections = cantFail(Obj.sections());
for (const Elf_Shdr &Sec : Sections) {
switch (Sec.sh_type) {
if (ElfHeader.e_shnum != 0)
return to_string(ElfHeader.e_shnum);
- ArrayRef<typename ELFT::Shdr> Arr = cantFail(Obj.sections());
- if (Arr.empty())
+ Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections();
+ if (!ArrOrErr) {
+ // In this case we can ignore an error, because we have already reported a
+ // warning about the broken section header table earlier.
+ consumeError(ArrOrErr.takeError());
+ return "<?>";
+ }
+
+ if (ArrOrErr->empty())
return "0";
- return "0 (" + to_string(Arr[0].sh_size) + ")";
+ return "0 (" + to_string((*ArrOrErr)[0].sh_size) + ")";
}
template <class ELFT>
if (ElfHeader.e_shstrndx != SHN_XINDEX)
return to_string(ElfHeader.e_shstrndx);
- ArrayRef<typename ELFT::Shdr> Arr = cantFail(Obj.sections());
- if (Arr.empty())
+ Expected<ArrayRef<typename ELFT::Shdr>> ArrOrErr = Obj.sections();
+ if (!ArrOrErr) {
+ // In this case we can ignore an error, because we have already reported a
+ // warning about the broken section header table earlier.
+ consumeError(ArrOrErr.takeError());
+ return "<?>";
+ }
+
+ if (ArrOrErr->empty())
return "65535 (corrupt: out of range)";
- return to_string(ElfHeader.e_shstrndx) + " (" + to_string(Arr[0].sh_link) +
- ")";
+ return to_string(ElfHeader.e_shstrndx) + " (" +
+ to_string((*ArrOrErr)[0].sh_link) + ")";
}
template <class ELFT> void GNUStyle<ELFT>::printFileHeaders() {
ObjDumper(ScopedPrinter &Writer);
virtual ~ObjDumper();
+ virtual bool canDumpContent() { return true; }
+
virtual void printFileHeaders() = 0;
virtual void printSectionHeaders() = 0;
virtual void printRelocations() = 0;
}
/// Dumps the specified object file.
-static void dumpObject(const ObjectFile &Obj, ScopedPrinter &Writer,
+static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
const Archive *A = nullptr) {
std::string FileStr =
A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str()
: Obj.getFileName().str();
+ std::string ContentErrString;
+ if (Error ContentErr = Obj.initContent())
+ ContentErrString = "unable to continue dumping, the file is corrupt: " +
+ toString(std::move(ContentErr));
+
ObjDumper *Dumper;
Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
if (!DumperOrErr)
if (opts::FileHeaders)
Dumper->printFileHeaders();
+ // This is only used for ELF currently. In some cases, when an object is
+ // corrupt (e.g. truncated), we can't dump anything except the file header.
+ if (!ContentErrString.empty())
+ reportError(createError(ContentErrString), FileStr);
+
if (opts::SectionDetails || opts::SectionHeaders) {
if (opts::Output == opts::GNU && opts::SectionDetails)
Dumper->printSectionDetails();
/// Opens \a File and dumps it.
static void dumpInput(StringRef File, ScopedPrinter &Writer) {
// Attempt to open the binary.
- Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(File);
+ Expected<OwningBinary<Binary>> BinaryOrErr =
+ createBinary(File, /*Context=*/nullptr, /*InitContent=*/false);
if (!BinaryOrErr)
reportError(BinaryOrErr.takeError(), File);
Binary &Binary = *BinaryOrErr.get().getBinary();