aboutsummaryrefslogtreecommitdiff
path: root/tools/llvm-objdump
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llvm-objdump')
-rw-r--r--tools/llvm-objdump/CMakeLists.txt5
-rw-r--r--tools/llvm-objdump/COFFDump.cpp85
-rw-r--r--tools/llvm-objdump/ELFDump.cpp32
-rw-r--r--tools/llvm-objdump/MachODump.cpp814
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp562
-rw-r--r--tools/llvm-objdump/llvm-objdump.h8
6 files changed, 926 insertions, 580 deletions
diff --git a/tools/llvm-objdump/CMakeLists.txt b/tools/llvm-objdump/CMakeLists.txt
index 1f2721ab5452..d0dd4ac0182c 100644
--- a/tools/llvm-objdump/CMakeLists.txt
+++ b/tools/llvm-objdump/CMakeLists.txt
@@ -1,5 +1,8 @@
set(LLVM_LINK_COMPONENTS
- ${LLVM_TARGETS_TO_BUILD}
+ AllTargetsAsmPrinters
+ AllTargetsDescs
+ AllTargetsDisassemblers
+ AllTargetsInfos
CodeGen
DebugInfoDWARF
MC
diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp
index 8b94a50ea28b..f286351614ac 100644
--- a/tools/llvm-objdump/COFFDump.cpp
+++ b/tools/llvm-objdump/COFFDump.cpp
@@ -151,7 +151,7 @@ static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) {
<< " remaining in buffer";
return ;
}
- printUnwindCode(ArrayRef<UnwindCode>(I, E));
+ printUnwindCode(makeArrayRef(I, E));
I += UsedSlots;
}
}
@@ -165,10 +165,10 @@ resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym,
if (std::error_code EC = ResolvedAddrOrErr.getError())
return EC;
ResolvedAddr = *ResolvedAddrOrErr;
- section_iterator iter(Obj->section_begin());
- if (std::error_code EC = Sym.getSection(iter))
+ ErrorOr<section_iterator> Iter = Sym.getSection();
+ if (std::error_code EC = Iter.getError())
return EC;
- ResolvedSection = Obj->getCOFFSection(*iter);
+ ResolvedSection = Obj->getCOFFSection(**Iter);
return std::error_code();
}
@@ -241,12 +241,10 @@ printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
return;
const pe32_header *PE32Header;
- if (error(Obj->getPE32Header(PE32Header)))
- return;
+ error(Obj->getPE32Header(PE32Header));
uint32_t ImageBase = PE32Header->ImageBase;
uintptr_t IntPtr = 0;
- if (error(Obj->getVaPtr(TableVA, IntPtr)))
- return;
+ error(Obj->getVaPtr(TableVA, IntPtr));
const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr;
outs() << "SEH Table:";
for (int I = 0; I < Count; ++I)
@@ -257,8 +255,7 @@ printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
static void printLoadConfiguration(const COFFObjectFile *Obj) {
// Skip if it's not executable.
const pe32_header *PE32Header;
- if (error(Obj->getPE32Header(PE32Header)))
- return;
+ error(Obj->getPE32Header(PE32Header));
if (!PE32Header)
return;
@@ -267,13 +264,11 @@ static void printLoadConfiguration(const COFFObjectFile *Obj) {
return;
const data_directory *DataDir;
- if (error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir)))
- return;
+ error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir));
uintptr_t IntPtr = 0;
if (DataDir->RelativeVirtualAddress == 0)
return;
- if (error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr)))
- return;
+ error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr));
auto *LoadConf = reinterpret_cast<const coff_load_configuration32 *>(IntPtr);
outs() << "Load configuration:"
@@ -381,8 +376,7 @@ static bool getPDataSection(const COFFObjectFile *Obj,
const RuntimeFunction *&RFStart, int &NumRFs) {
for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
- if (error(Section.getName(Name)))
- continue;
+ error(Section.getName(Name));
if (Name != ".pdata")
continue;
@@ -394,8 +388,7 @@ static bool getPDataSection(const COFFObjectFile *Obj,
std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
ArrayRef<uint8_t> Contents;
- if (error(Obj->getSectionContents(Pdata, Contents)))
- continue;
+ error(Obj->getSectionContents(Pdata, Contents));
if (Contents.empty())
continue;
@@ -440,7 +433,7 @@ static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) {
if (UI->NumCodes)
outs() << " Unwind Codes:\n";
- printAllUnwindCodes(ArrayRef<UnwindCode>(&UI->UnwindCodes[0], UI->NumCodes));
+ printAllUnwindCodes(makeArrayRef(&UI->UnwindCodes[0], UI->NumCodes));
outs() << "\n";
outs().flush();
@@ -499,11 +492,10 @@ static void printRuntimeFunctionRels(const COFFObjectFile *Obj,
ArrayRef<uint8_t> XContents;
uint64_t UnwindInfoOffset = 0;
- if (error(getSectionContents(
+ error(getSectionContents(
Obj, Rels, SectionOffset +
/*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
- XContents, UnwindInfoOffset)))
- return;
+ XContents, UnwindInfoOffset));
if (XContents.empty())
return;
@@ -550,3 +542,52 @@ void llvm::printCOFFFileHeader(const object::ObjectFile *Obj) {
printImportTables(file);
printExportTable(file);
}
+
+void llvm::printCOFFSymbolTable(const COFFObjectFile *coff) {
+ for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) {
+ ErrorOr<COFFSymbolRef> Symbol = coff->getSymbol(SI);
+ StringRef Name;
+ error(Symbol.getError());
+ error(coff->getSymbolName(*Symbol, Name));
+
+ outs() << "[" << format("%2d", SI) << "]"
+ << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")"
+ << "(fl 0x00)" // Flag bits, which COFF doesn't have.
+ << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")"
+ << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") "
+ << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") "
+ << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
+ << Name << "\n";
+
+ for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) {
+ if (Symbol->isSectionDefinition()) {
+ const coff_aux_section_definition *asd;
+ error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd));
+
+ int32_t AuxNumber = asd->getNumber(Symbol->isBigObj());
+
+ outs() << "AUX "
+ << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
+ , unsigned(asd->Length)
+ , unsigned(asd->NumberOfRelocations)
+ , unsigned(asd->NumberOfLinenumbers)
+ , unsigned(asd->CheckSum))
+ << format("assoc %d comdat %d\n"
+ , unsigned(AuxNumber)
+ , unsigned(asd->Selection));
+ } else if (Symbol->isFileRecord()) {
+ const char *FileName;
+ error(coff->getAuxSymbol<char>(SI + 1, FileName));
+
+ StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() *
+ coff->getSymbolTableEntrySize());
+ outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n';
+
+ SI = SI + Symbol->getNumberOfAuxSymbols();
+ break;
+ } else {
+ outs() << "AUX Unknown\n";
+ }
+ }
+ }
+}
diff --git a/tools/llvm-objdump/ELFDump.cpp b/tools/llvm-objdump/ELFDump.cpp
index 2d0d7d7db0f3..7b44e3916c48 100644
--- a/tools/llvm-objdump/ELFDump.cpp
+++ b/tools/llvm-objdump/ELFDump.cpp
@@ -24,10 +24,8 @@ using namespace llvm::object;
template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) {
typedef ELFFile<ELFT> ELFO;
outs() << "Program Header:\n";
- for (typename ELFO::Elf_Phdr_Iter pi = o->program_header_begin(),
- pe = o->program_header_end();
- pi != pe; ++pi) {
- switch (pi->p_type) {
+ for (const typename ELFO::Elf_Phdr &Phdr : o->program_headers()) {
+ switch (Phdr.p_type) {
case ELF::PT_LOAD:
outs() << " LOAD ";
break;
@@ -55,22 +53,16 @@ template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) {
const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " ";
- outs() << "off "
- << format(Fmt, (uint64_t)pi->p_offset)
- << "vaddr "
- << format(Fmt, (uint64_t)pi->p_vaddr)
- << "paddr "
- << format(Fmt, (uint64_t)pi->p_paddr)
- << format("align 2**%u\n", countTrailingZeros<uint64_t>(pi->p_align))
- << " filesz "
- << format(Fmt, (uint64_t)pi->p_filesz)
- << "memsz "
- << format(Fmt, (uint64_t)pi->p_memsz)
- << "flags "
- << ((pi->p_flags & ELF::PF_R) ? "r" : "-")
- << ((pi->p_flags & ELF::PF_W) ? "w" : "-")
- << ((pi->p_flags & ELF::PF_X) ? "x" : "-")
- << "\n";
+ outs() << "off " << format(Fmt, (uint64_t)Phdr.p_offset) << "vaddr "
+ << format(Fmt, (uint64_t)Phdr.p_vaddr) << "paddr "
+ << format(Fmt, (uint64_t)Phdr.p_paddr)
+ << format("align 2**%u\n",
+ countTrailingZeros<uint64_t>(Phdr.p_align))
+ << " filesz " << format(Fmt, (uint64_t)Phdr.p_filesz)
+ << "memsz " << format(Fmt, (uint64_t)Phdr.p_memsz) << "flags "
+ << ((Phdr.p_flags & ELF::PF_R) ? "r" : "-")
+ << ((Phdr.p_flags & ELF::PF_W) ? "w" : "-")
+ << ((Phdr.p_flags & ELF::PF_X) ? "x" : "-") << "\n";
}
outs() << "\n";
}
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp
index 04c72f4856c8..a2f3bc8e8a7c 100644
--- a/tools/llvm-objdump/MachODump.cpp
+++ b/tools/llvm-objdump/MachODump.cpp
@@ -13,6 +13,7 @@
#include "llvm-objdump.h"
#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
@@ -97,11 +98,6 @@ cl::opt<bool>
cl::desc("Print the linker optimization hints for "
"Mach-O objects (requires -macho)"));
-cl::list<std::string>
- llvm::DumpSections("section",
- cl::desc("Prints the specified segment,section for "
- "Mach-O objects (requires -macho)"));
-
cl::opt<bool>
llvm::InfoPlist("info-plist",
cl::desc("Print the info plist section as strings for "
@@ -138,6 +134,7 @@ static cl::opt<bool> NoSymbolicOperands(
static cl::list<std::string>
ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
cl::ZeroOrMore);
+
bool ArchAll = false;
static std::string ThumbTripleName;
@@ -210,19 +207,19 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
case MachO::DICE_KIND_DATA:
if (Length >= 4) {
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 4), outs());
+ dumpBytes(makeArrayRef(bytes, 4), outs());
Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
outs() << "\t.long " << Value;
Size = 4;
} else if (Length >= 2) {
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs());
+ dumpBytes(makeArrayRef(bytes, 2), outs());
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << Value;
Size = 2;
} else {
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs());
+ dumpBytes(makeArrayRef(bytes, 2), outs());
Value = bytes[0];
outs() << "\t.byte " << Value;
Size = 1;
@@ -234,14 +231,14 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
break;
case MachO::DICE_KIND_JUMP_TABLE8:
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 1), outs());
+ dumpBytes(makeArrayRef(bytes, 1), outs());
Value = bytes[0];
outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
Size = 1;
break;
case MachO::DICE_KIND_JUMP_TABLE16:
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs());
+ dumpBytes(makeArrayRef(bytes, 2), outs());
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << format("%5u", Value & 0xffff)
<< "\t@ KIND_JUMP_TABLE16\n";
@@ -250,7 +247,7 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
case MachO::DICE_KIND_JUMP_TABLE32:
case MachO::DICE_KIND_ABS_JUMP_TABLE32:
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 4), outs());
+ dumpBytes(makeArrayRef(bytes, 4), outs());
Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
outs() << "\t.long " << Value;
if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
@@ -670,13 +667,9 @@ static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
double d) {
outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
uint32_t Hi, Lo;
- if (O->isLittleEndian()) {
- Hi = l1;
- Lo = l0;
- } else {
- Hi = l0;
- Lo = l1;
- }
+ Hi = (O->isLittleEndian()) ? l1 : l0;
+ Lo = (O->isLittleEndian()) ? l0 : l1;
+
// Hi is the high word, so this is equivalent to if(isfinite(d))
if ((Hi & 0x7ff00000) != 0x7ff00000)
outs() << format(" (%.16e)\n", d);
@@ -921,10 +914,7 @@ static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
SymbolAddressMap *AddrMap,
bool verbose) {
uint32_t stride;
- if (O->is64Bit())
- stride = sizeof(uint64_t);
- else
- stride = sizeof(uint32_t);
+ stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
for (uint32_t i = 0; i < sect_size; i += stride) {
const char *SymbolName = nullptr;
if (O->is64Bit()) {
@@ -1006,8 +996,8 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
if (verbose)
CreateSymbolAddressMap(O, &AddrMap);
- for (unsigned i = 0; i < DumpSections.size(); ++i) {
- StringRef DumpSection = DumpSections[i];
+ for (unsigned i = 0; i < FilterSections.size(); ++i) {
+ StringRef DumpSection = FilterSections[i];
std::pair<StringRef, StringRef> DumpSegSectName;
DumpSegSectName = DumpSection.split(',');
StringRef DumpSegName, DumpSectName;
@@ -1171,7 +1161,7 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
// UniversalHeaders or ArchiveHeaders.
if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
- DylibsUsed || DylibId || ObjcMetaData || (DumpSections.size() != 0)) {
+ DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) {
outs() << Filename;
if (!ArchiveMemberName.empty())
outs() << '(' << ArchiveMemberName << ')';
@@ -1194,7 +1184,7 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
PrintSectionHeaders(MachOOF);
if (SectionContents)
PrintSectionContents(MachOOF);
- if (DumpSections.size() != 0)
+ if (FilterSections.size() != 0)
DumpSectionContents(Filename, MachOOF, !NonVerbose);
if (InfoPlist)
DumpInfoPlistSectionContents(Filename, MachOOF);
@@ -1395,7 +1385,7 @@ static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
}
}
-static void printArchiveChild(Archive::Child &C, bool verbose,
+static void printArchiveChild(const Archive::Child &C, bool verbose,
bool print_offset) {
if (print_offset)
outs() << C.getChildOffset() << "\t";
@@ -1404,42 +1394,15 @@ static void printArchiveChild(Archive::Child &C, bool verbose,
// FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
// But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
outs() << "-";
- if (Mode & sys::fs::owner_read)
- outs() << "r";
- else
- outs() << "-";
- if (Mode & sys::fs::owner_write)
- outs() << "w";
- else
- outs() << "-";
- if (Mode & sys::fs::owner_exe)
- outs() << "x";
- else
- outs() << "-";
- if (Mode & sys::fs::group_read)
- outs() << "r";
- else
- outs() << "-";
- if (Mode & sys::fs::group_write)
- outs() << "w";
- else
- outs() << "-";
- if (Mode & sys::fs::group_exe)
- outs() << "x";
- else
- outs() << "-";
- if (Mode & sys::fs::others_read)
- outs() << "r";
- else
- outs() << "-";
- if (Mode & sys::fs::others_write)
- outs() << "w";
- else
- outs() << "-";
- if (Mode & sys::fs::others_exe)
- outs() << "x";
- else
- outs() << "-";
+ outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
+ outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
+ outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
+ outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
+ outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
+ outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
+ outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
+ outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
+ outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
} else {
outs() << format("0%o ", Mode);
}
@@ -1448,8 +1411,10 @@ static void printArchiveChild(Archive::Child &C, bool verbose,
outs() << format("%3d/", UID);
unsigned GID = C.getGID();
outs() << format("%-3d ", GID);
- uint64_t Size = C.getRawSize();
- outs() << format("%5" PRId64, Size) << " ";
+ ErrorOr<uint64_t> Size = C.getRawSize();
+ if (std::error_code EC = Size.getError())
+ report_fatal_error(EC.message());
+ outs() << format("%5" PRId64, Size.get()) << " ";
StringRef RawLastModified = C.getRawLastModified();
if (verbose) {
@@ -1483,14 +1448,11 @@ static void printArchiveChild(Archive::Child &C, bool verbose,
}
static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) {
- if (A->hasSymbolTable()) {
- Archive::child_iterator S = A->getSymbolTableChild();
- Archive::Child C = *S;
- printArchiveChild(C, verbose, print_offset);
- }
- for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E;
- ++I) {
- Archive::Child C = *I;
+ for (Archive::child_iterator I = A->child_begin(false), E = A->child_end();
+ I != E; ++I) {
+ if (std::error_code EC = I->getError())
+ report_fatal_error(EC.message());
+ const Archive::Child &C = **I;
printArchiveChild(C, verbose, print_offset);
}
}
@@ -1527,7 +1489,10 @@ void llvm::ParseInputMachO(StringRef Filename) {
printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
I != E; ++I) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = I->getAsBinary();
+ if (std::error_code EC = I->getError())
+ report_error(Filename, EC);
+ auto &C = I->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
@@ -1575,7 +1540,10 @@ void llvm::ParseInputMachO(StringRef Filename) {
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
+ if (std::error_code EC = AI->getError())
+ report_error(Filename, EC);
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O =
@@ -1617,7 +1585,10 @@ void llvm::ParseInputMachO(StringRef Filename) {
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
+ if (std::error_code EC = AI->getError())
+ report_error(Filename, EC);
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O =
@@ -1653,7 +1624,10 @@ void llvm::ParseInputMachO(StringRef Filename) {
printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
+ if (std::error_code EC = AI->getError())
+ report_error(Filename, EC);
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O =
@@ -1676,8 +1650,7 @@ void llvm::ParseInputMachO(StringRef Filename) {
errs() << "llvm-objdump: '" << Filename << "': "
<< "Object is not a Mach-O file type.\n";
} else
- errs() << "llvm-objdump: '" << Filename << "': "
- << "Unrecognized file type.\n";
+ report_error(Filename, object_error::invalid_file_type);
}
typedef std::pair<uint64_t, const char *> BindInfoEntry;
@@ -1698,6 +1671,7 @@ struct DisassembleInfo {
uint64_t adrp_addr;
uint32_t adrp_inst;
BindTable *bindtable;
+ uint32_t depth;
};
// SymbolizerGetOpInfo() is the operand information call back function.
@@ -1735,8 +1709,15 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
if (Arch == Triple::x86) {
if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
return 0;
- // First search the section's relocation entries (if any) for an entry
- // for this section offset.
+ if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
+ // TODO:
+ // Search the external relocation entries of a fully linked image
+ // (if any) for an entry that matches this segment offset.
+ // uint32_t seg_offset = (Pc + Offset);
+ return 0;
+ }
+ // In MH_OBJECT filetypes search the section's relocation entries (if any)
+ // for an entry for this section offset.
uint32_t sect_addr = info->S.getAddress();
uint32_t sect_offset = (Pc + Offset) - sect_addr;
bool reloc_found = false;
@@ -1806,17 +1787,20 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
op_info->Value = offset;
return 1;
}
- // TODO:
- // Second search the external relocation entries of a fully linked image
- // (if any) for an entry that matches this segment offset.
- // uint32_t seg_offset = (Pc + Offset);
return 0;
}
if (Arch == Triple::x86_64) {
if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
return 0;
- // First search the section's relocation entries (if any) for an entry
- // for this section offset.
+ if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
+ // TODO:
+ // Search the external relocation entries of a fully linked image
+ // (if any) for an entry that matches this segment offset.
+ // uint64_t seg_offset = (Pc + Offset);
+ return 0;
+ }
+ // In MH_OBJECT filetypes search the section's relocation entries (if any)
+ // for an entry for this section offset.
uint64_t sect_addr = info->S.getAddress();
uint64_t sect_offset = (Pc + Offset) - sect_addr;
bool reloc_found = false;
@@ -1874,17 +1858,20 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
op_info->AddSymbol.Name = name;
return 1;
}
- // TODO:
- // Second search the external relocation entries of a fully linked image
- // (if any) for an entry that matches this segment offset.
- // uint64_t seg_offset = (Pc + Offset);
return 0;
}
if (Arch == Triple::arm) {
if (Offset != 0 || (Size != 4 && Size != 2))
return 0;
- // First search the section's relocation entries (if any) for an entry
- // for this section offset.
+ if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
+ // TODO:
+ // Search the external relocation entries of a fully linked image
+ // (if any) for an entry that matches this segment offset.
+ // uint32_t seg_offset = (Pc + Offset);
+ return 0;
+ }
+ // In MH_OBJECT filetypes search the section's relocation entries (if any)
+ // for an entry for this section offset.
uint32_t sect_addr = info->S.getAddress();
uint32_t sect_offset = (Pc + Offset) - sect_addr;
DataRefImpl Rel;
@@ -2016,8 +2003,15 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
if (Arch == Triple::aarch64) {
if (Offset != 0 || Size != 4)
return 0;
- // First search the section's relocation entries (if any) for an entry
- // for this section offset.
+ if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
+ // TODO:
+ // Search the external relocation entries of a fully linked image
+ // (if any) for an entry that matches this segment offset.
+ // uint64_t seg_offset = (Pc + Offset);
+ return 0;
+ }
+ // In MH_OBJECT filetypes search the section's relocation entries (if any)
+ // for an entry for this section offset.
uint64_t sect_addr = info->S.getAddress();
uint64_t sect_offset = (Pc + Offset) - sect_addr;
auto Reloc =
@@ -2370,6 +2364,8 @@ static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
+ if (SectSize == 0)
+ continue;
if (objc_only) {
StringRef SectName;
((*(info->Sections))[SectIdx]).getName(SectName);
@@ -3267,6 +3263,8 @@ walk_pointer_list_32(const char *listname, const SectionRef S,
}
static void print_layout_map(const char *layout_map, uint32_t left) {
+ if (layout_map == nullptr)
+ return;
outs() << " layout map: ";
do {
outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
@@ -3330,8 +3328,8 @@ static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
return;
memset(&m, '\0', sizeof(struct method64_t));
if (left < sizeof(struct method64_t)) {
- memcpy(&ml, r, left);
- outs() << indent << " (method_t entends past the end of the section)\n";
+ memcpy(&m, r, left);
+ outs() << indent << " (method_t extends past the end of the section)\n";
} else
memcpy(&m, r, sizeof(struct method64_t));
if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
@@ -4222,7 +4220,7 @@ static void print_objc_property_list32(uint32_t p,
}
}
-static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
+static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
bool &is_meta_class) {
struct class_ro64_t cro;
const char *r;
@@ -4233,7 +4231,7 @@ static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
r = get_pointer_64(p, offset, left, S, info);
if (r == nullptr || left < sizeof(struct class_ro64_t))
- return;
+ return false;
memset(&cro, '\0', sizeof(struct class_ro64_t));
if (left < sizeof(struct class_ro64_t)) {
memcpy(&cro, r, left);
@@ -4357,10 +4355,11 @@ static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
if (cro.baseProperties + n_value != 0)
print_objc_property_list64(cro.baseProperties + n_value, info);
- is_meta_class = (cro.flags & RO_META) ? true : false;
+ is_meta_class = (cro.flags & RO_META) != 0;
+ return true;
}
-static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
+static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
bool &is_meta_class) {
struct class_ro32_t cro;
const char *r;
@@ -4370,7 +4369,7 @@ static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
r = get_pointer_32(p, offset, left, S, info);
if (r == nullptr)
- return;
+ return false;
memset(&cro, '\0', sizeof(struct class_ro32_t));
if (left < sizeof(struct class_ro32_t)) {
memcpy(&cro, r, left);
@@ -4420,7 +4419,8 @@ static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
<< format("0x%" PRIx32, cro.baseProperties) << "\n";
if (cro.baseProperties != 0)
print_objc_property_list32(cro.baseProperties, info);
- is_meta_class = (cro.flags & RO_META) ? true : false;
+ is_meta_class = (cro.flags & RO_META) != 0;
+ return true;
}
static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
@@ -4490,11 +4490,16 @@ static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
outs() << " Swift class";
outs() << "\n";
bool is_meta_class;
- print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class);
+ if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
+ return;
- if (is_meta_class == false) {
- outs() << "Meta Class\n";
- print_class64_t(c.isa + isa_n_value, info);
+ if (!is_meta_class &&
+ c.isa + isa_n_value != p &&
+ c.isa + isa_n_value != 0 &&
+ info->depth < 100) {
+ info->depth++;
+ outs() << "Meta Class\n";
+ print_class64_t(c.isa + isa_n_value, info);
}
}
@@ -4555,9 +4560,10 @@ static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
outs() << " Swift class";
outs() << "\n";
bool is_meta_class;
- print_class_ro32_t(c.data & ~0x3, info, is_meta_class);
+ if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
+ return;
- if (is_meta_class == false) {
+ if (!is_meta_class) {
outs() << "Meta Class\n";
print_class32_t(c.isa, info);
}
@@ -4865,7 +4871,7 @@ static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
outs() << " name " << format("0x%" PRIx32, c.name);
name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
c.name);
- if (name != NULL)
+ if (name)
outs() << " " << name;
outs() << "\n";
@@ -5006,6 +5012,9 @@ static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
struct objc_image_info64 o;
const char *r;
+ if (S == SectionRef())
+ return;
+
StringRef SectName;
S.getName(SectName);
DataRefImpl Ref = S.getRawDataRefImpl();
@@ -5142,75 +5151,48 @@ static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
info.adrp_addr = 0;
info.adrp_inst = 0;
- const SectionRef CL = get_section(O, "__OBJC2", "__class_list");
- if (CL != SectionRef()) {
- info.S = CL;
- walk_pointer_list_64("class", CL, O, &info, print_class64_t);
- } else {
- const SectionRef CL = get_section(O, "__DATA", "__objc_classlist");
- info.S = CL;
- walk_pointer_list_64("class", CL, O, &info, print_class64_t);
- }
-
- const SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
- if (CR != SectionRef()) {
- info.S = CR;
- walk_pointer_list_64("class refs", CR, O, &info, nullptr);
- } else {
- const SectionRef CR = get_section(O, "__DATA", "__objc_classrefs");
- info.S = CR;
- walk_pointer_list_64("class refs", CR, O, &info, nullptr);
- }
-
- const SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
- if (SR != SectionRef()) {
- info.S = SR;
- walk_pointer_list_64("super refs", SR, O, &info, nullptr);
- } else {
- const SectionRef SR = get_section(O, "__DATA", "__objc_superrefs");
- info.S = SR;
- walk_pointer_list_64("super refs", SR, O, &info, nullptr);
- }
-
- const SectionRef CA = get_section(O, "__OBJC2", "__category_list");
- if (CA != SectionRef()) {
- info.S = CA;
- walk_pointer_list_64("category", CA, O, &info, print_category64_t);
- } else {
- const SectionRef CA = get_section(O, "__DATA", "__objc_catlist");
- info.S = CA;
- walk_pointer_list_64("category", CA, O, &info, print_category64_t);
- }
-
- const SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
- if (PL != SectionRef()) {
- info.S = PL;
- walk_pointer_list_64("protocol", PL, O, &info, nullptr);
- } else {
- const SectionRef PL = get_section(O, "__DATA", "__objc_protolist");
- info.S = PL;
- walk_pointer_list_64("protocol", PL, O, &info, nullptr);
- }
-
- const SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
- if (MR != SectionRef()) {
- info.S = MR;
- print_message_refs64(MR, &info);
- } else {
- const SectionRef MR = get_section(O, "__DATA", "__objc_msgrefs");
- info.S = MR;
- print_message_refs64(MR, &info);
- }
-
- const SectionRef II = get_section(O, "__OBJC2", "__image_info");
- if (II != SectionRef()) {
- info.S = II;
- print_image_info64(II, &info);
- } else {
- const SectionRef II = get_section(O, "__DATA", "__objc_imageinfo");
- info.S = II;
- print_image_info64(II, &info);
- }
+ info.depth = 0;
+ SectionRef CL = get_section(O, "__OBJC2", "__class_list");
+ if (CL == SectionRef())
+ CL = get_section(O, "__DATA", "__objc_classlist");
+ info.S = CL;
+ walk_pointer_list_64("class", CL, O, &info, print_class64_t);
+
+ SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
+ if (CR == SectionRef())
+ CR = get_section(O, "__DATA", "__objc_classrefs");
+ info.S = CR;
+ walk_pointer_list_64("class refs", CR, O, &info, nullptr);
+
+ SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
+ if (SR == SectionRef())
+ SR = get_section(O, "__DATA", "__objc_superrefs");
+ info.S = SR;
+ walk_pointer_list_64("super refs", SR, O, &info, nullptr);
+
+ SectionRef CA = get_section(O, "__OBJC2", "__category_list");
+ if (CA == SectionRef())
+ CA = get_section(O, "__DATA", "__objc_catlist");
+ info.S = CA;
+ walk_pointer_list_64("category", CA, O, &info, print_category64_t);
+
+ SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
+ if (PL == SectionRef())
+ PL = get_section(O, "__DATA", "__objc_protolist");
+ info.S = PL;
+ walk_pointer_list_64("protocol", PL, O, &info, nullptr);
+
+ SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
+ if (MR == SectionRef())
+ MR = get_section(O, "__DATA", "__objc_msgrefs");
+ info.S = MR;
+ print_message_refs64(MR, &info);
+
+ SectionRef II = get_section(O, "__OBJC2", "__image_info");
+ if (II == SectionRef())
+ II = get_section(O, "__DATA", "__objc_imageinfo");
+ info.S = II;
+ print_image_info64(II, &info);
if (info.bindtable != nullptr)
delete info.bindtable;
@@ -5559,7 +5541,7 @@ static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
// binary for the iOS simulator which is the second Objective-C
// ABI. In that case printObjc1_32bit_MetaData() will determine that
// and return false.
- if (printObjc1_32bit_MetaData(O, verbose) == false)
+ if (!printObjc1_32bit_MetaData(O, verbose))
printObjc2_32bit_MetaData(O, verbose);
}
}
@@ -5588,36 +5570,38 @@ static const char *GuessLiteralPointer(uint64_t ReferenceValue,
uint64_t *ReferenceType,
struct DisassembleInfo *info) {
// First see if there is an external relocation entry at the ReferencePC.
- uint64_t sect_addr = info->S.getAddress();
- uint64_t sect_offset = ReferencePC - sect_addr;
- bool reloc_found = false;
- DataRefImpl Rel;
- MachO::any_relocation_info RE;
- bool isExtern = false;
- SymbolRef Symbol;
- for (const RelocationRef &Reloc : info->S.relocations()) {
- uint64_t RelocOffset = Reloc.getOffset();
- if (RelocOffset == sect_offset) {
- Rel = Reloc.getRawDataRefImpl();
- RE = info->O->getRelocation(Rel);
- if (info->O->isRelocationScattered(RE))
- continue;
- isExtern = info->O->getPlainRelocationExternal(RE);
- if (isExtern) {
- symbol_iterator RelocSym = Reloc.getSymbol();
- Symbol = *RelocSym;
+ if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
+ uint64_t sect_addr = info->S.getAddress();
+ uint64_t sect_offset = ReferencePC - sect_addr;
+ bool reloc_found = false;
+ DataRefImpl Rel;
+ MachO::any_relocation_info RE;
+ bool isExtern = false;
+ SymbolRef Symbol;
+ for (const RelocationRef &Reloc : info->S.relocations()) {
+ uint64_t RelocOffset = Reloc.getOffset();
+ if (RelocOffset == sect_offset) {
+ Rel = Reloc.getRawDataRefImpl();
+ RE = info->O->getRelocation(Rel);
+ if (info->O->isRelocationScattered(RE))
+ continue;
+ isExtern = info->O->getPlainRelocationExternal(RE);
+ if (isExtern) {
+ symbol_iterator RelocSym = Reloc.getSymbol();
+ Symbol = *RelocSym;
+ }
+ reloc_found = true;
+ break;
}
- reloc_found = true;
- break;
}
- }
- // If there is an external relocation entry for a symbol in a section
- // then used that symbol's value for the value of the reference.
- if (reloc_found && isExtern) {
- if (info->O->getAnyRelocationPCRel(RE)) {
- unsigned Type = info->O->getAnyRelocationType(RE);
- if (Type == MachO::X86_64_RELOC_SIGNED) {
- ReferenceValue = Symbol.getValue();
+ // If there is an external relocation entry for a symbol in a section
+ // then used that symbol's value for the value of the reference.
+ if (reloc_found && isExtern) {
+ if (info->O->getAnyRelocationPCRel(RE)) {
+ unsigned Type = info->O->getAnyRelocationType(RE);
+ if (Type == MachO::X86_64_RELOC_SIGNED) {
+ ReferenceValue = Symbol.getValue();
+ }
}
}
}
@@ -5872,7 +5856,6 @@ static void emitComments(raw_svector_ostream &CommentStream,
formatted_raw_ostream &FormattedOS,
const MCAsmInfo &MAI) {
// Flush the stream before taking its content.
- CommentStream.flush();
StringRef Comments = CommentsToEmit.str();
// Get the default information for printing a comment.
const char *CommentBegin = MAI.getCommentString();
@@ -5893,7 +5876,6 @@ static void emitComments(raw_svector_ostream &CommentStream,
// Tell the comment stream that the vector changed underneath it.
CommentsToEmit.clear();
- CommentStream.resync();
}
static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
@@ -6065,7 +6047,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
diContext.reset(new DWARFContextInMemory(*DbgObj));
}
- if (DumpSections.size() == 0)
+ if (FilterSections.size() == 0)
outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
@@ -6087,19 +6069,6 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
bool symbolTableWorked = false;
- // Parse relocations.
- std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
- for (const RelocationRef &Reloc : Sections[SectIdx].relocations()) {
- uint64_t RelocOffset = Reloc.getOffset();
- uint64_t SectionAddress = Sections[SectIdx].getAddress();
- RelocOffset -= SectionAddress;
-
- symbol_iterator RelocSym = Reloc.getSymbol();
-
- Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
- }
- array_pod_sort(Relocs.begin(), Relocs.end());
-
// Create a map of symbol addresses to symbol names for use by
// the SymbolizerSymbolLookUp() routine.
SymbolAddressMap AddrMap;
@@ -6157,7 +6126,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
StringRef SymName = *SymNameOrErr;
SymbolRef::Type ST = Symbols[SymIdx].getType();
- if (ST != SymbolRef::ST_Function)
+ if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
continue;
// Make sure the symbol is defined in this section.
@@ -6251,10 +6220,9 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
DebugOut, Annotations);
if (gotInst) {
if (!NoShowRawInsn) {
- dumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size), outs());
+ dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
}
formatted_raw_ostream FormattedOS(outs());
- Annotations.flush();
StringRef AnnotationsStr = Annotations.str();
if (isThumb)
ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
@@ -6316,7 +6284,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
}
if (!NoShowRawInsn) {
outs() << "\t";
- dumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, InstSize), outs());
+ dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
}
IP->printInst(&Inst, outs(), "", *STI);
outs() << "\n";
@@ -6441,8 +6409,7 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
// Go back one so that SymbolAddress <= Addr.
--Sym;
- section_iterator SymSection = Obj->section_end();
- Sym->second.getSection(SymSection);
+ section_iterator SymSection = *Sym->second.getSection();
if (RelocSection == *SymSection) {
// There's a valid symbol in the same section before this reference.
ErrorOr<StringRef> NameOrErr = Sym->second.getName();
@@ -6780,13 +6747,268 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
}
}
+static unsigned getSizeForEncoding(bool is64Bit,
+ unsigned symbolEncoding) {
+ unsigned format = symbolEncoding & 0x0f;
+ switch (format) {
+ default: llvm_unreachable("Unknown Encoding");
+ case dwarf::DW_EH_PE_absptr:
+ case dwarf::DW_EH_PE_signed:
+ return is64Bit ? 8 : 4;
+ case dwarf::DW_EH_PE_udata2:
+ case dwarf::DW_EH_PE_sdata2:
+ return 2;
+ case dwarf::DW_EH_PE_udata4:
+ case dwarf::DW_EH_PE_sdata4:
+ return 4;
+ case dwarf::DW_EH_PE_udata8:
+ case dwarf::DW_EH_PE_sdata8:
+ return 8;
+ }
+}
+
+static uint64_t readPointer(const char *&Pos, bool is64Bit, unsigned Encoding) {
+ switch (getSizeForEncoding(is64Bit, Encoding)) {
+ case 2:
+ return readNext<uint16_t>(Pos);
+ break;
+ case 4:
+ return readNext<uint32_t>(Pos);
+ break;
+ case 8:
+ return readNext<uint64_t>(Pos);
+ break;
+ default:
+ llvm_unreachable("Illegal data size");
+ }
+}
+
+static void printMachOEHFrameSection(const MachOObjectFile *Obj,
+ std::map<uint64_t, SymbolRef> &Symbols,
+ const SectionRef &EHFrame) {
+ if (!Obj->isLittleEndian()) {
+ outs() << "warning: cannot handle big endian __eh_frame section\n";
+ return;
+ }
+
+ bool is64Bit = Obj->is64Bit();
+
+ outs() << "Contents of __eh_frame section:\n";
+
+ StringRef Contents;
+ EHFrame.getContents(Contents);
+
+ /// A few fields of the CIE are used when decoding the FDE's. This struct
+ /// will cache those fields we need so that we don't have to decode it
+ /// repeatedly for each FDE that references it.
+ struct DecodedCIE {
+ Optional<uint32_t> FDEPointerEncoding;
+ Optional<uint32_t> LSDAPointerEncoding;
+ bool hasAugmentationLength;
+ };
+
+ // Map from the start offset of the CIE to the cached data for that CIE.
+ DenseMap<uint64_t, DecodedCIE> CachedCIEs;
+
+ for (const char *Pos = Contents.data(), *End = Contents.end(); Pos != End; ) {
+
+ const char *EntryStartPos = Pos;
+
+ uint64_t Length = readNext<uint32_t>(Pos);
+ if (Length == 0xffffffff)
+ Length = readNext<uint64_t>(Pos);
+
+ // Save the Pos so that we can check the length we encoded against what we
+ // end up decoding.
+ const char *PosAfterLength = Pos;
+ const char *EntryEndPos = PosAfterLength + Length;
+
+ assert(EntryEndPos <= End &&
+ "__eh_frame entry length exceeds section size");
+
+ uint32_t ID = readNext<uint32_t>(Pos);
+ if (ID == 0) {
+ // This is a CIE.
+
+ uint32_t Version = readNext<uint8_t>(Pos);
+
+ // Parse a null terminated augmentation string
+ SmallString<8> AugmentationString;
+ for (uint8_t Char = readNext<uint8_t>(Pos); Char;
+ Char = readNext<uint8_t>(Pos))
+ AugmentationString.push_back(Char);
+
+ // Optionally parse the EH data if the augmentation string says it's there.
+ Optional<uint64_t> EHData;
+ if (StringRef(AugmentationString).count("eh"))
+ EHData = is64Bit ? readNext<uint64_t>(Pos) : readNext<uint32_t>(Pos);
+
+ unsigned ULEBByteCount;
+ uint64_t CodeAlignmentFactor = decodeULEB128((const uint8_t *)Pos,
+ &ULEBByteCount);
+ Pos += ULEBByteCount;
+
+ int64_t DataAlignmentFactor = decodeSLEB128((const uint8_t *)Pos,
+ &ULEBByteCount);
+ Pos += ULEBByteCount;
+
+ uint32_t ReturnAddressRegister = readNext<uint8_t>(Pos);
+
+ Optional<uint64_t> AugmentationLength;
+ Optional<uint32_t> LSDAPointerEncoding;
+ Optional<uint32_t> PersonalityEncoding;
+ Optional<uint64_t> Personality;
+ Optional<uint32_t> FDEPointerEncoding;
+ if (!AugmentationString.empty() && AugmentationString.front() == 'z') {
+ AugmentationLength = decodeULEB128((const uint8_t *)Pos,
+ &ULEBByteCount);
+ Pos += ULEBByteCount;
+
+ // Walk the augmentation string to get all the augmentation data.
+ for (unsigned i = 1, e = AugmentationString.size(); i != e; ++i) {
+ char Char = AugmentationString[i];
+ switch (Char) {
+ case 'e':
+ assert((i + 1) != e && AugmentationString[i + 1] == 'h' &&
+ "Expected 'eh' in augmentation string");
+ break;
+ case 'L':
+ assert(!LSDAPointerEncoding && "Duplicate LSDA encoding");
+ LSDAPointerEncoding = readNext<uint8_t>(Pos);
+ break;
+ case 'P': {
+ assert(!Personality && "Duplicate personality");
+ PersonalityEncoding = readNext<uint8_t>(Pos);
+ Personality = readPointer(Pos, is64Bit, *PersonalityEncoding);
+ break;
+ }
+ case 'R':
+ assert(!FDEPointerEncoding && "Duplicate FDE encoding");
+ FDEPointerEncoding = readNext<uint8_t>(Pos);
+ break;
+ case 'z':
+ llvm_unreachable("'z' must be first in the augmentation string");
+ }
+ }
+ }
+
+ outs() << "CIE:\n";
+ outs() << " Length: " << Length << "\n";
+ outs() << " CIE ID: " << ID << "\n";
+ outs() << " Version: " << Version << "\n";
+ outs() << " Augmentation String: " << AugmentationString << "\n";
+ if (EHData)
+ outs() << " EHData: " << *EHData << "\n";
+ outs() << " Code Alignment Factor: " << CodeAlignmentFactor << "\n";
+ outs() << " Data Alignment Factor: " << DataAlignmentFactor << "\n";
+ outs() << " Return Address Register: " << ReturnAddressRegister << "\n";
+ if (AugmentationLength) {
+ outs() << " Augmentation Data Length: " << *AugmentationLength << "\n";
+ if (LSDAPointerEncoding) {
+ outs() << " FDE LSDA Pointer Encoding: "
+ << *LSDAPointerEncoding << "\n";
+ }
+ if (Personality) {
+ outs() << " Personality Encoding: " << *PersonalityEncoding << "\n";
+ outs() << " Personality: " << *Personality << "\n";
+ }
+ if (FDEPointerEncoding) {
+ outs() << " FDE Address Pointer Encoding: "
+ << *FDEPointerEncoding << "\n";
+ }
+ }
+ // FIXME: Handle instructions.
+ // For now just emit some bytes
+ outs() << " Instructions:\n ";
+ dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos),
+ outs());
+ outs() << "\n";
+ Pos = EntryEndPos;
+
+ // Cache this entry.
+ uint64_t Offset = EntryStartPos - Contents.data();
+ CachedCIEs[Offset] = { FDEPointerEncoding, LSDAPointerEncoding,
+ AugmentationLength.hasValue() };
+ continue;
+ }
+
+ // This is an FDE.
+ // The CIE pointer for an FDE is the same location as the ID which we
+ // already read.
+ uint32_t CIEPointer = ID;
+
+ const char *CIEStart = PosAfterLength - CIEPointer;
+ assert(CIEStart >= Contents.data() &&
+ "FDE points to CIE before the __eh_frame start");
+
+ uint64_t CIEOffset = CIEStart - Contents.data();
+ auto CIEIt = CachedCIEs.find(CIEOffset);
+ if (CIEIt == CachedCIEs.end())
+ llvm_unreachable("Couldn't find CIE at offset in to __eh_frame section");
+
+ const DecodedCIE &CIE = CIEIt->getSecond();
+ assert(CIE.FDEPointerEncoding &&
+ "FDE references CIE which did not set pointer encoding");
+
+ uint64_t PCPointerSize = getSizeForEncoding(is64Bit,
+ *CIE.FDEPointerEncoding);
+
+ uint64_t PCBegin = readPointer(Pos, is64Bit, *CIE.FDEPointerEncoding);
+ uint64_t PCRange = readPointer(Pos, is64Bit, *CIE.FDEPointerEncoding);
+
+ Optional<uint64_t> AugmentationLength;
+ uint32_t LSDAPointerSize;
+ Optional<uint64_t> LSDAPointer;
+ if (CIE.hasAugmentationLength) {
+ unsigned ULEBByteCount;
+ AugmentationLength = decodeULEB128((const uint8_t *)Pos,
+ &ULEBByteCount);
+ Pos += ULEBByteCount;
+
+ // Decode the LSDA if the CIE augmentation string said we should.
+ if (CIE.LSDAPointerEncoding) {
+ LSDAPointerSize = getSizeForEncoding(is64Bit, *CIE.LSDAPointerEncoding);
+ LSDAPointer = readPointer(Pos, is64Bit, *CIE.LSDAPointerEncoding);
+ }
+ }
+
+ outs() << "FDE:\n";
+ outs() << " Length: " << Length << "\n";
+ outs() << " CIE Offset: " << CIEOffset << "\n";
+
+ if (PCPointerSize == 8) {
+ outs() << format(" PC Begin: %016" PRIx64, PCBegin) << "\n";
+ outs() << format(" PC Range: %016" PRIx64, PCRange) << "\n";
+ } else {
+ outs() << format(" PC Begin: %08" PRIx64, PCBegin) << "\n";
+ outs() << format(" PC Range: %08" PRIx64, PCRange) << "\n";
+ }
+ if (AugmentationLength) {
+ outs() << " Augmentation Data Length: " << *AugmentationLength << "\n";
+ if (LSDAPointer) {
+ if (LSDAPointerSize == 8)
+ outs() << format(" LSDA Pointer: %016\n" PRIx64, *LSDAPointer);
+ else
+ outs() << format(" LSDA Pointer: %08\n" PRIx64, *LSDAPointer);
+ }
+ }
+
+ // FIXME: Handle instructions.
+ // For now just emit some bytes
+ outs() << " Instructions:\n ";
+ dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos),
+ outs());
+ outs() << "\n";
+ Pos = EntryEndPos;
+ }
+}
+
void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
std::map<uint64_t, SymbolRef> Symbols;
for (const SymbolRef &SymRef : Obj->symbols()) {
// Discard any undefined or absolute symbols. They're not going to take part
// in the convenience lookup for unwind info and just take up resources.
- section_iterator Section = Obj->section_end();
- SymRef.getSection(Section);
+ section_iterator Section = *SymRef.getSection();
if (Section == Obj->section_end())
continue;
@@ -6802,7 +7024,7 @@ void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
else if (SectName == "__unwind_info")
printMachOUnwindInfoSection(Obj, Symbols, Section);
else if (SectName == "__eh_frame")
- outs() << "llvm-objdump: warning: unhandled __eh_frame section\n";
+ printMachOEHFrameSection(Obj, Symbols, Section);
}
}
@@ -7128,36 +7350,20 @@ static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
MachO::VM_PROT_EXECUTE)) != 0)
outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
else {
- if (maxprot & MachO::VM_PROT_READ)
- outs() << " maxprot r";
- else
- outs() << " maxprot -";
- if (maxprot & MachO::VM_PROT_WRITE)
- outs() << "w";
- else
- outs() << "-";
- if (maxprot & MachO::VM_PROT_EXECUTE)
- outs() << "x\n";
- else
- outs() << "-\n";
+ outs() << " maxprot ";
+ outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
+ outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
+ outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
}
if ((initprot &
~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
MachO::VM_PROT_EXECUTE)) != 0)
outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
else {
- if (initprot & MachO::VM_PROT_READ)
- outs() << " initprot r";
- else
- outs() << " initprot -";
- if (initprot & MachO::VM_PROT_WRITE)
- outs() << "w";
- else
- outs() << "-";
- if (initprot & MachO::VM_PROT_EXECUTE)
- outs() << "x\n";
- else
- outs() << "-\n";
+ outs() << " initprot ";
+ outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
+ outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
+ outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
}
} else {
outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
@@ -7611,26 +7817,11 @@ static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
else
outs() << "\n";
outs() << " uuid ";
- outs() << format("%02" PRIX32, uuid.uuid[0]);
- outs() << format("%02" PRIX32, uuid.uuid[1]);
- outs() << format("%02" PRIX32, uuid.uuid[2]);
- outs() << format("%02" PRIX32, uuid.uuid[3]);
- outs() << "-";
- outs() << format("%02" PRIX32, uuid.uuid[4]);
- outs() << format("%02" PRIX32, uuid.uuid[5]);
- outs() << "-";
- outs() << format("%02" PRIX32, uuid.uuid[6]);
- outs() << format("%02" PRIX32, uuid.uuid[7]);
- outs() << "-";
- outs() << format("%02" PRIX32, uuid.uuid[8]);
- outs() << format("%02" PRIX32, uuid.uuid[9]);
- outs() << "-";
- outs() << format("%02" PRIX32, uuid.uuid[10]);
- outs() << format("%02" PRIX32, uuid.uuid[11]);
- outs() << format("%02" PRIX32, uuid.uuid[12]);
- outs() << format("%02" PRIX32, uuid.uuid[13]);
- outs() << format("%02" PRIX32, uuid.uuid[14]);
- outs() << format("%02" PRIX32, uuid.uuid[15]);
+ for (int i = 0; i < 16; ++i) {
+ outs() << format("%02" PRIX32, uuid.uuid[i]);
+ if (i == 3 || i == 5 || i == 7 || i == 9)
+ outs() << "-";
+ }
outs() << "\n";
}
@@ -7650,30 +7841,47 @@ static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
}
static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
- if (vd.cmd == MachO::LC_VERSION_MIN_MACOSX)
- outs() << " cmd LC_VERSION_MIN_MACOSX\n";
- else if (vd.cmd == MachO::LC_VERSION_MIN_IPHONEOS)
- outs() << " cmd LC_VERSION_MIN_IPHONEOS\n";
- else
- outs() << " cmd " << vd.cmd << " (?)\n";
+ StringRef LoadCmdName;
+ switch (vd.cmd) {
+ case MachO::LC_VERSION_MIN_MACOSX:
+ LoadCmdName = "LC_VERSION_MIN_MACOSX";
+ break;
+ case MachO::LC_VERSION_MIN_IPHONEOS:
+ LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
+ break;
+ case MachO::LC_VERSION_MIN_TVOS:
+ LoadCmdName = "LC_VERSION_MIN_TVOS";
+ break;
+ case MachO::LC_VERSION_MIN_WATCHOS:
+ LoadCmdName = "LC_VERSION_MIN_WATCHOS";
+ break;
+ default:
+ llvm_unreachable("Unknown version min load command");
+ }
+
+ outs() << " cmd " << LoadCmdName << '\n';
outs() << " cmdsize " << vd.cmdsize;
if (vd.cmdsize != sizeof(struct MachO::version_min_command))
outs() << " Incorrect size\n";
else
outs() << "\n";
- outs() << " version " << ((vd.version >> 16) & 0xffff) << "."
- << ((vd.version >> 8) & 0xff);
- if ((vd.version & 0xff) != 0)
- outs() << "." << (vd.version & 0xff);
+ outs() << " version "
+ << MachOObjectFile::getVersionMinMajor(vd, false) << "."
+ << MachOObjectFile::getVersionMinMinor(vd, false);
+ uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
+ if (Update != 0)
+ outs() << "." << Update;
outs() << "\n";
if (vd.sdk == 0)
outs() << " sdk n/a";
else {
- outs() << " sdk " << ((vd.sdk >> 16) & 0xffff) << "."
- << ((vd.sdk >> 8) & 0xff);
+ outs() << " sdk "
+ << MachOObjectFile::getVersionMinMajor(vd, true) << "."
+ << MachOObjectFile::getVersionMinMinor(vd, true);
}
- if ((vd.sdk & 0xff) != 0)
- outs() << "." << (vd.sdk & 0xff);
+ Update = MachOObjectFile::getVersionMinUpdate(vd, true);
+ if (Update != 0)
+ outs() << "." << Update;
outs() << "\n";
}
@@ -8366,7 +8574,9 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
PrintRpathLoadCommand(Rpath, Command.Ptr);
} else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
- Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
+ Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
+ Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
+ Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
PrintVersionMinLoadCommand(Vd);
} else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
@@ -8536,6 +8746,7 @@ public:
StringRef segmentName(uint32_t SegIndex);
StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset);
uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
+ bool isValidSegIndexAndOffset(uint32_t SegIndex, uint64_t SegOffset);
private:
struct SectionInfo {
@@ -8559,8 +8770,7 @@ SegInfo::SegInfo(const object::MachOObjectFile *Obj) {
uint64_t CurSegAddress;
for (const SectionRef &Section : Obj->sections()) {
SectionInfo Info;
- if (error(Section.getName(Info.SectionName)))
- return;
+ error(Section.getName(Info.SectionName));
Info.Address = Section.getAddress();
Info.Size = Section.getSize();
Info.SegmentName =
@@ -8585,6 +8795,20 @@ StringRef SegInfo::segmentName(uint32_t SegIndex) {
llvm_unreachable("invalid segIndex");
}
+bool SegInfo::isValidSegIndexAndOffset(uint32_t SegIndex,
+ uint64_t OffsetInSeg) {
+ for (const SectionInfo &SI : Sections) {
+ if (SI.SegmentIndex != SegIndex)
+ continue;
+ if (SI.OffsetInSegment > OffsetInSeg)
+ continue;
+ if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
+ continue;
+ return true;
+ }
+ return false;
+}
+
const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex,
uint64_t OffsetInSeg) {
for (const SectionInfo &SI : Sections) {
@@ -8753,6 +8977,8 @@ static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) {
uint32_t SegIndex = Entry.segmentIndex();
uint64_t OffsetInSeg = Entry.segmentOffset();
+ if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg))
+ continue;
uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
const char *SymbolName = nullptr;
StringRef name = Entry.symbolName();
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index 275eb9c6a454..22167c788901 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -73,6 +73,13 @@ Disassembled("d", cl::desc("Alias for --disassemble"),
cl::aliasopt(Disassemble));
cl::opt<bool>
+llvm::DisassembleAll("disassemble-all",
+ cl::desc("Display assembler mnemonics for the machine instructions"));
+static cl::alias
+DisassembleAlld("D", cl::desc("Alias for --disassemble-all"),
+ cl::aliasopt(DisassembleAll));
+
+cl::opt<bool>
llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));
cl::opt<bool>
@@ -130,6 +137,13 @@ SectionHeadersShorter("h", cl::desc("Alias for --section-headers"),
cl::aliasopt(SectionHeaders));
cl::list<std::string>
+llvm::FilterSections("section", cl::desc("Operate on the specified sections only. "
+ "With -macho dump segment,section"));
+cl::alias
+static FilterSectionsj("j", cl::desc("Alias for --section"),
+ cl::aliasopt(llvm::FilterSections));
+
+cl::list<std::string>
llvm::MAttrs("mattr",
cl::CommaSeparated,
cl::desc("Target specific attributes"),
@@ -163,22 +177,86 @@ cl::opt<bool> PrintFaultMaps("fault-map-section",
cl::desc("Display contents of faultmap section"));
static StringRef ToolName;
-static int ReturnValue = EXIT_SUCCESS;
-bool llvm::error(std::error_code EC) {
+namespace {
+typedef std::function<bool(llvm::object::SectionRef const &)> FilterPredicate;
+
+class SectionFilterIterator {
+public:
+ SectionFilterIterator(FilterPredicate P,
+ llvm::object::section_iterator const &I,
+ llvm::object::section_iterator const &E)
+ : Predicate(P), Iterator(I), End(E) {
+ ScanPredicate();
+ }
+ const llvm::object::SectionRef &operator*() const { return *Iterator; }
+ SectionFilterIterator &operator++() {
+ ++Iterator;
+ ScanPredicate();
+ return *this;
+ }
+ bool operator!=(SectionFilterIterator const &Other) const {
+ return Iterator != Other.Iterator;
+ }
+
+private:
+ void ScanPredicate() {
+ while (Iterator != End && !Predicate(*Iterator)) {
+ ++Iterator;
+ }
+ }
+ FilterPredicate Predicate;
+ llvm::object::section_iterator Iterator;
+ llvm::object::section_iterator End;
+};
+
+class SectionFilter {
+public:
+ SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O)
+ : Predicate(P), Object(O) {}
+ SectionFilterIterator begin() {
+ return SectionFilterIterator(Predicate, Object.section_begin(),
+ Object.section_end());
+ }
+ SectionFilterIterator end() {
+ return SectionFilterIterator(Predicate, Object.section_end(),
+ Object.section_end());
+ }
+
+private:
+ FilterPredicate Predicate;
+ llvm::object::ObjectFile const &Object;
+};
+SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O) {
+ return SectionFilter([](llvm::object::SectionRef const &S) {
+ if(FilterSections.empty())
+ return true;
+ llvm::StringRef String;
+ std::error_code error = S.getName(String);
+ if (error)
+ return false;
+ return std::find(FilterSections.begin(),
+ FilterSections.end(),
+ String) != FilterSections.end();
+ },
+ O);
+}
+}
+
+void llvm::error(std::error_code EC) {
if (!EC)
- return false;
+ return;
- outs() << ToolName << ": error reading file: " << EC.message() << ".\n";
- outs().flush();
- ReturnValue = EXIT_FAILURE;
- return true;
+ errs() << ToolName << ": error reading file: " << EC.message() << ".\n";
+ errs().flush();
+ exit(1);
}
-static void report_error(StringRef File, std::error_code EC) {
+LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File,
+ std::error_code EC) {
assert(EC);
errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n";
- ReturnValue = EXIT_FAILURE;
+ exit(1);
}
static const Target *getTarget(const ObjectFile *Obj = nullptr) {
@@ -205,10 +283,8 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) {
std::string Error;
const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
Error);
- if (!TheTarget) {
- errs() << ToolName << ": " << Error;
- return nullptr;
- }
+ if (!TheTarget)
+ report_fatal_error("can't find target: " + Error);
// Update the triple name and return the found target.
TripleName = TheTriple.getTriple();
@@ -301,11 +377,12 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
template <class ELFT>
static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
- DataRefImpl Rel,
+ const RelocationRef &RelRef,
SmallVectorImpl<char> &Result) {
+ DataRefImpl Rel = RelRef.getRawDataRefImpl();
+
typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename ELFObjectFile<ELFT>::Elf_Rel Elf_Rel;
typedef typename ELFObjectFile<ELFT>::Elf_Rela Elf_Rela;
const ELFFile<ELFT> &EF = *Obj->getELFFile();
@@ -327,36 +404,31 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
if (std::error_code EC = StrTabOrErr.getError())
return EC;
StringRef StrTab = *StrTabOrErr;
- uint8_t type;
+ uint8_t type = RelRef.getType();
StringRef res;
int64_t addend = 0;
- uint16_t symbol_index = 0;
switch (Sec->sh_type) {
default:
return object_error::parse_failed;
case ELF::SHT_REL: {
- const Elf_Rel *ERel = Obj->getRel(Rel);
- type = ERel->getType(EF.isMips64EL());
- symbol_index = ERel->getSymbol(EF.isMips64EL());
// TODO: Read implicit addend from section data.
break;
}
case ELF::SHT_RELA: {
const Elf_Rela *ERela = Obj->getRela(Rel);
- type = ERela->getType(EF.isMips64EL());
- symbol_index = ERela->getSymbol(EF.isMips64EL());
addend = ERela->r_addend;
break;
}
}
- const Elf_Sym *symb =
- EF.template getEntry<Elf_Sym>(Sec->sh_link, symbol_index);
+ symbol_iterator SI = RelRef.getSymbol();
+ const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl());
StringRef Target;
- ErrorOr<const Elf_Shdr *> SymSec = EF.getSection(symb);
- if (std::error_code EC = SymSec.getError())
- return EC;
if (symb->getType() == ELF::STT_SECTION) {
- ErrorOr<StringRef> SecName = EF.getSectionName(*SymSec);
+ ErrorOr<section_iterator> SymSI = SI->getSection();
+ if (std::error_code EC = SymSI.getError())
+ return EC;
+ const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl());
+ ErrorOr<StringRef> SecName = EF.getSectionName(SymSec);
if (std::error_code EC = SecName.getError())
return EC;
Target = *SecName;
@@ -404,6 +476,7 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
break;
}
case ELF::EM_386:
+ case ELF::EM_IAMCU:
case ELF::EM_ARM:
case ELF::EM_HEXAGON:
case ELF::EM_MIPS:
@@ -418,9 +491,8 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
}
static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj,
- const RelocationRef &RelRef,
+ const RelocationRef &Rel,
SmallVectorImpl<char> &Result) {
- DataRefImpl Rel = RelRef.getRawDataRefImpl();
if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj))
return getRelocationValueString(ELF32LE, Rel, Result);
if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj))
@@ -471,7 +543,7 @@ static void printRelocationTargetName(const MachOObjectFile *O,
// If we couldn't find a symbol that this relocation refers to, try
// to find a section beginning instead.
- for (const SectionRef &Section : O->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*O)) {
std::error_code ec;
StringRef Name;
@@ -496,8 +568,8 @@ static void printRelocationTargetName(const MachOObjectFile *O,
symbol_iterator SI = O->symbol_begin();
advance(SI, Val);
ErrorOr<StringRef> SOrErr = SI->getName();
- if (!error(SOrErr.getError()))
- S = *SOrErr;
+ error(SOrErr.getError());
+ S = *SOrErr;
} else {
section_iterator SI = O->section_begin();
// Adjust for the fact that sections are 1-indexed.
@@ -732,10 +804,6 @@ static bool getHidden(RelocationRef RelRef) {
static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
const Target *TheTarget = getTarget(Obj);
- // getTarget() will have already issued a diagnostic if necessary, so
- // just bail here if it failed.
- if (!TheTarget)
- return;
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
@@ -748,42 +816,28 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
std::unique_ptr<const MCRegisterInfo> MRI(
TheTarget->createMCRegInfo(TripleName));
- if (!MRI) {
- errs() << "error: no register info for target " << TripleName << "\n";
- return;
- }
+ if (!MRI)
+ report_fatal_error("error: no register info for target " + TripleName);
// Set up disassembler.
std::unique_ptr<const MCAsmInfo> AsmInfo(
TheTarget->createMCAsmInfo(*MRI, TripleName));
- if (!AsmInfo) {
- errs() << "error: no assembly info for target " << TripleName << "\n";
- return;
- }
-
+ if (!AsmInfo)
+ report_fatal_error("error: no assembly info for target " + TripleName);
std::unique_ptr<const MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
- if (!STI) {
- errs() << "error: no subtarget info for target " << TripleName << "\n";
- return;
- }
-
+ if (!STI)
+ report_fatal_error("error: no subtarget info for target " + TripleName);
std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
- if (!MII) {
- errs() << "error: no instruction info for target " << TripleName << "\n";
- return;
- }
-
+ if (!MII)
+ report_fatal_error("error: no instruction info for target " + TripleName);
std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);
MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());
std::unique_ptr<MCDisassembler> DisAsm(
TheTarget->createMCDisassembler(*STI, Ctx));
-
- if (!DisAsm) {
- errs() << "error: no disassembler for target " << TripleName << "\n";
- return;
- }
+ if (!DisAsm)
+ report_fatal_error("error: no disassembler for target " + TripleName);
std::unique_ptr<const MCInstrAnalysis> MIA(
TheTarget->createMCInstrAnalysis(MII.get()));
@@ -791,11 +845,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
- if (!IP) {
- errs() << "error: no instruction printer for target " << TripleName
- << '\n';
- return;
- }
+ if (!IP)
+ report_fatal_error("error: no instruction printer for target " +
+ TripleName);
IP->setPrintImmHex(PrintImmHex);
PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName));
@@ -806,38 +858,75 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// in RelocSecs contain the relocations for section S.
std::error_code EC;
std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
section_iterator Sec2 = Section.getRelocatedSection();
if (Sec2 != Obj->section_end())
SectionRelocMap[*Sec2].push_back(Section);
}
// Create a mapping from virtual address to symbol name. This is used to
- // pretty print the target of a call.
- std::vector<std::pair<uint64_t, StringRef>> AllSymbols;
- if (MIA) {
- for (const SymbolRef &Symbol : Obj->symbols()) {
- if (Symbol.getType() != SymbolRef::ST_Function)
- continue;
+ // pretty print the symbols while disassembling.
+ typedef std::vector<std::pair<uint64_t, StringRef>> SectionSymbolsTy;
+ std::map<SectionRef, SectionSymbolsTy> AllSymbols;
+ for (const SymbolRef &Symbol : Obj->symbols()) {
+ ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
+ error(AddressOrErr.getError());
+ uint64_t Address = *AddressOrErr;
+
+ ErrorOr<StringRef> Name = Symbol.getName();
+ error(Name.getError());
+ if (Name->empty())
+ continue;
- ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
- if (error(AddressOrErr.getError()))
- break;
- uint64_t Address = *AddressOrErr;
+ ErrorOr<section_iterator> SectionOrErr = Symbol.getSection();
+ error(SectionOrErr.getError());
+ section_iterator SecI = *SectionOrErr;
+ if (SecI == Obj->section_end())
+ continue;
- ErrorOr<StringRef> Name = Symbol.getName();
- if (error(Name.getError()))
- break;
- if (Name->empty())
+ AllSymbols[*SecI].emplace_back(Address, *Name);
+ }
+
+ // Create a mapping from virtual address to section.
+ std::vector<std::pair<uint64_t, SectionRef>> SectionAddresses;
+ for (SectionRef Sec : Obj->sections())
+ SectionAddresses.emplace_back(Sec.getAddress(), Sec);
+ array_pod_sort(SectionAddresses.begin(), SectionAddresses.end());
+
+ // Linked executables (.exe and .dll files) typically don't include a real
+ // symbol table but they might contain an export table.
+ if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Obj)) {
+ for (const auto &ExportEntry : COFFObj->export_directories()) {
+ StringRef Name;
+ error(ExportEntry.getSymbolName(Name));
+ if (Name.empty())
continue;
- AllSymbols.push_back(std::make_pair(Address, *Name));
- }
+ uint32_t RVA;
+ error(ExportEntry.getExportRVA(RVA));
+
+ uint64_t VA = COFFObj->getImageBase() + RVA;
+ auto Sec = std::upper_bound(
+ SectionAddresses.begin(), SectionAddresses.end(), VA,
+ [](uint64_t LHS, const std::pair<uint64_t, SectionRef> &RHS) {
+ return LHS < RHS.first;
+ });
+ if (Sec != SectionAddresses.begin())
+ --Sec;
+ else
+ Sec = SectionAddresses.end();
- array_pod_sort(AllSymbols.begin(), AllSymbols.end());
+ if (Sec != SectionAddresses.end())
+ AllSymbols[Sec->second].emplace_back(VA, Name);
+ }
}
- for (const SectionRef &Section : Obj->sections()) {
- if (!Section.isText() || Section.isVirtual())
+ // Sort all the symbols, this allows us to use a simple binary search to find
+ // a symbol near an address.
+ for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)
+ array_pod_sort(SecSyms.second.begin(), SecSyms.second.end());
+
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
+ if (!DisassembleAll && (!Section.isText() || Section.isVirtual()))
continue;
uint64_t SectionAddr = Section.getAddress();
@@ -845,27 +934,23 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (!SectSize)
continue;
- // Make a list of all the symbols in this section.
- std::vector<std::pair<uint64_t, StringRef>> Symbols;
- for (const SymbolRef &Symbol : Obj->symbols()) {
- if (Section.containsSymbol(Symbol)) {
- ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
- if (error(AddressOrErr.getError()))
- break;
- uint64_t Address = *AddressOrErr;
- Address -= SectionAddr;
- if (Address >= SectSize)
- continue;
-
- ErrorOr<StringRef> Name = Symbol.getName();
- if (error(Name.getError()))
- break;
- Symbols.push_back(std::make_pair(Address, *Name));
+ // Get the list of all the symbols in this section.
+ SectionSymbolsTy &Symbols = AllSymbols[Section];
+ std::vector<uint64_t> DataMappingSymsAddr;
+ std::vector<uint64_t> TextMappingSymsAddr;
+ if (Obj->isELF() && Obj->getArch() == Triple::aarch64) {
+ for (const auto &Symb : Symbols) {
+ uint64_t Address = Symb.first;
+ StringRef Name = Symb.second;
+ if (Name.startswith("$d"))
+ DataMappingSymsAddr.push_back(Address - SectionAddr);
+ if (Name.startswith("$x"))
+ TextMappingSymsAddr.push_back(Address - SectionAddr);
}
}
- // Sort the symbols by address, just in case they didn't come in that way.
- array_pod_sort(Symbols.begin(), Symbols.end());
+ std::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end());
+ std::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end());
// Make a list of all the relocations for this section.
std::vector<RelocationRef> Rels;
@@ -886,8 +971,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
SegmentName = MachO->getSectionFinalSegmentName(DR);
}
StringRef name;
- if (error(Section.getName(name)))
- break;
+ error(Section.getName(name));
outs() << "Disassembly of section ";
if (!SegmentName.empty())
outs() << SegmentName << ",";
@@ -895,14 +979,13 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// If the section has no symbol at the start, just insert a dummy one.
if (Symbols.empty() || Symbols[0].first != 0)
- Symbols.insert(Symbols.begin(), std::make_pair(0, name));
+ Symbols.insert(Symbols.begin(), std::make_pair(SectionAddr, name));
SmallString<40> Comments;
raw_svector_ostream CommentStream(Comments);
StringRef BytesStr;
- if (error(Section.getContents(BytesStr)))
- break;
+ error(Section.getContents(BytesStr));
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
BytesStr.size());
@@ -914,11 +997,16 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// Disassemble symbol by symbol.
for (unsigned si = 0, se = Symbols.size(); si != se; ++si) {
- uint64_t Start = Symbols[si].first;
- // The end is either the section end or the beginning of the next symbol.
- uint64_t End = (si == se - 1) ? SectSize : Symbols[si + 1].first;
+ uint64_t Start = Symbols[si].first - SectionAddr;
+ // The end is either the section end or the beginning of the next
+ // symbol.
+ uint64_t End =
+ (si == se - 1) ? SectSize : Symbols[si + 1].first - SectionAddr;
+ // Don't try to disassemble beyond the end of section contents.
+ if (End > SectSize)
+ End = SectSize;
// If this symbol has the same address as the next symbol, then skip it.
- if (Start == End)
+ if (Start >= End)
continue;
outs() << '\n' << Symbols[si].second << ":\n";
@@ -932,6 +1020,45 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
for (Index = Start; Index < End; Index += Size) {
MCInst Inst;
+ // AArch64 ELF binaries can interleave data and text in the
+ // same section. We rely on the markers introduced to
+ // understand what we need to dump.
+ if (Obj->isELF() && Obj->getArch() == Triple::aarch64) {
+ uint64_t Stride = 0;
+
+ auto DAI = std::lower_bound(DataMappingSymsAddr.begin(),
+ DataMappingSymsAddr.end(), Index);
+ if (DAI != DataMappingSymsAddr.end() && *DAI == Index) {
+ // Switch to data.
+ while (Index < End) {
+ outs() << format("%8" PRIx64 ":", SectionAddr + Index);
+ outs() << "\t";
+ if (Index + 4 <= End) {
+ Stride = 4;
+ dumpBytes(Bytes.slice(Index, 4), outs());
+ outs() << "\t.word";
+ } else if (Index + 2 <= End) {
+ Stride = 2;
+ dumpBytes(Bytes.slice(Index, 2), outs());
+ outs() << "\t.short";
+ } else {
+ Stride = 1;
+ dumpBytes(Bytes.slice(Index, 1), outs());
+ outs() << "\t.byte";
+ }
+ Index += Stride;
+ outs() << "\n";
+ auto TAI = std::lower_bound(TextMappingSymsAddr.begin(),
+ TextMappingSymsAddr.end(), Index);
+ if (TAI != TextMappingSymsAddr.end() && *TAI == Index)
+ break;
+ }
+ }
+ }
+
+ if (Index >= End)
+ break;
+
if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
SectionAddr + Index, DebugOut,
CommentStream)) {
@@ -940,26 +1067,55 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
SectionAddr + Index, outs(), "", *STI);
outs() << CommentStream.str();
Comments.clear();
+
+ // Try to resolve the target of a call, tail call, etc. to a specific
+ // symbol.
if (MIA && (MIA->isCall(Inst) || MIA->isUnconditionalBranch(Inst) ||
MIA->isConditionalBranch(Inst))) {
uint64_t Target;
if (MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target)) {
- auto TargetSym = std::upper_bound(
- AllSymbols.begin(), AllSymbols.end(), Target,
- [](uint64_t LHS, const std::pair<uint64_t, StringRef> &RHS) {
- return LHS < RHS.first;
- });
- if (TargetSym != AllSymbols.begin())
- --TargetSym;
- else
- TargetSym = AllSymbols.end();
-
- if (TargetSym != AllSymbols.end()) {
- outs() << " <" << TargetSym->second;
- uint64_t Disp = Target - TargetSym->first;
- if (Disp)
- outs() << '+' << utohexstr(Disp);
- outs() << '>';
+ // In a relocatable object, the target's section must reside in
+ // the same section as the call instruction or it is accessed
+ // through a relocation.
+ //
+ // In a non-relocatable object, the target may be in any section.
+ //
+ // N.B. We don't walk the relocations in the relocatable case yet.
+ auto *TargetSectionSymbols = &Symbols;
+ if (!Obj->isRelocatableObject()) {
+ auto SectionAddress = std::upper_bound(
+ SectionAddresses.begin(), SectionAddresses.end(), Target,
+ [](uint64_t LHS,
+ const std::pair<uint64_t, SectionRef> &RHS) {
+ return LHS < RHS.first;
+ });
+ if (SectionAddress != SectionAddresses.begin()) {
+ --SectionAddress;
+ TargetSectionSymbols = &AllSymbols[SectionAddress->second];
+ } else {
+ TargetSectionSymbols = nullptr;
+ }
+ }
+
+ // Find the first symbol in the section whose offset is less than
+ // or equal to the target.
+ if (TargetSectionSymbols) {
+ auto TargetSym = std::upper_bound(
+ TargetSectionSymbols->begin(), TargetSectionSymbols->end(),
+ Target, [](uint64_t LHS,
+ const std::pair<uint64_t, StringRef> &RHS) {
+ return LHS < RHS.first;
+ });
+ if (TargetSym != TargetSectionSymbols->begin()) {
+ --TargetSym;
+ uint64_t TargetAddress = std::get<0>(*TargetSym);
+ StringRef TargetName = std::get<1>(*TargetSym);
+ outs() << " <" << TargetName;
+ uint64_t Disp = Target - TargetAddress;
+ if (Disp)
+ outs() << '+' << utohexstr(Disp);
+ outs() << '>';
+ }
}
}
}
@@ -983,8 +1139,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// Stop when rel_cur's address is past the current instruction.
if (addr >= Index + Size) break;
rel_cur->getTypeName(name);
- if (error(getRelocationValueString(*rel_cur, val)))
- goto skip_print_rel;
+ error(getRelocationValueString(*rel_cur, val));
outs() << format(Fmt.data(), SectionAddr + addr) << name
<< "\t" << val << "\n";
@@ -1004,12 +1159,11 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {
if (!Obj->isRelocatableObject())
return;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
if (Section.relocation_begin() == Section.relocation_end())
continue;
StringRef secname;
- if (error(Section.getName(secname)))
- continue;
+ error(Section.getName(secname));
outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n";
for (const RelocationRef &Reloc : Section.relocations()) {
bool hidden = getHidden(Reloc);
@@ -1019,8 +1173,7 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {
if (hidden)
continue;
Reloc.getTypeName(relocname);
- if (error(getRelocationValueString(Reloc, valuestr)))
- continue;
+ error(getRelocationValueString(Reloc, valuestr));
outs() << format(Fmt.data(), address) << " " << relocname << " "
<< valuestr << "\n";
}
@@ -1032,10 +1185,9 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
outs() << "Sections:\n"
"Idx Name Size Address Type\n";
unsigned i = 0;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
StringRef Name;
- if (error(Section.getName(Name)))
- return;
+ error(Section.getName(Name));
uint64_t Address = Section.getAddress();
uint64_t Size = Section.getSize();
bool Text = Section.isText();
@@ -1051,11 +1203,10 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
void llvm::PrintSectionContents(const ObjectFile *Obj) {
std::error_code EC;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
StringRef Name;
StringRef Contents;
- if (error(Section.getName(Name)))
- continue;
+ error(Section.getName(Name));
uint64_t BaseAddr = Section.getAddress();
uint64_t Size = Section.getSize();
if (!Size)
@@ -1069,8 +1220,7 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) {
continue;
}
- if (error(Section.getContents(Contents)))
- continue;
+ error(Section.getContents(Contents));
// Dump out the content as hex and printable ascii characters.
for (std::size_t addr = 0, end = Contents.size(); addr < end; addr += 16) {
@@ -1098,84 +1248,28 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) {
}
}
-static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
- for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) {
- ErrorOr<COFFSymbolRef> Symbol = coff->getSymbol(SI);
- StringRef Name;
- if (error(Symbol.getError()))
- return;
-
- if (error(coff->getSymbolName(*Symbol, Name)))
- return;
-
- outs() << "[" << format("%2d", SI) << "]"
- << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")"
- << "(fl 0x00)" // Flag bits, which COFF doesn't have.
- << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")"
- << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") "
- << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") "
- << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
- << Name << "\n";
-
- for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) {
- if (Symbol->isSectionDefinition()) {
- const coff_aux_section_definition *asd;
- if (error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd)))
- return;
-
- int32_t AuxNumber = asd->getNumber(Symbol->isBigObj());
-
- outs() << "AUX "
- << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
- , unsigned(asd->Length)
- , unsigned(asd->NumberOfRelocations)
- , unsigned(asd->NumberOfLinenumbers)
- , unsigned(asd->CheckSum))
- << format("assoc %d comdat %d\n"
- , unsigned(AuxNumber)
- , unsigned(asd->Selection));
- } else if (Symbol->isFileRecord()) {
- const char *FileName;
- if (error(coff->getAuxSymbol<char>(SI + 1, FileName)))
- return;
-
- StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() *
- coff->getSymbolTableEntrySize());
- outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n';
-
- SI = SI + Symbol->getNumberOfAuxSymbols();
- break;
- } else {
- outs() << "AUX Unknown\n";
- }
- }
- }
-}
-
void llvm::PrintSymbolTable(const ObjectFile *o) {
outs() << "SYMBOL TABLE:\n";
if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
- PrintCOFFSymbolTable(coff);
+ printCOFFSymbolTable(coff);
return;
}
for (const SymbolRef &Symbol : o->symbols()) {
ErrorOr<uint64_t> AddressOrError = Symbol.getAddress();
- if (error(AddressOrError.getError()))
- continue;
+ error(AddressOrError.getError());
uint64_t Address = *AddressOrError;
SymbolRef::Type Type = Symbol.getType();
uint32_t Flags = Symbol.getFlags();
- section_iterator Section = o->section_end();
- if (error(Symbol.getSection(Section)))
- continue;
+ ErrorOr<section_iterator> SectionOrErr = Symbol.getSection();
+ error(SectionOrErr.getError());
+ section_iterator Section = *SectionOrErr;
StringRef Name;
if (Type == SymbolRef::ST_Debug && Section != o->section_end()) {
Section->getName(Name);
} else {
ErrorOr<StringRef> NameOrErr = Symbol.getName();
- if (error(NameOrErr.getError()))
- continue;
+ error(NameOrErr.getError());
Name = *NameOrErr;
}
@@ -1222,8 +1316,7 @@ void llvm::PrintSymbolTable(const ObjectFile *o) {
outs() << SegmentName << ",";
}
StringRef SectionName;
- if (error(Section->getName(SectionName)))
- SectionName = "";
+ error(Section->getName(SectionName));
outs() << SectionName;
}
@@ -1329,7 +1422,7 @@ void llvm::printRawClangAST(const ObjectFile *Obj) {
}
Optional<object::SectionRef> ClangASTSection;
- for (auto Sec : Obj->sections()) {
+ for (auto Sec : ToolSectionFilter(*Obj)) {
StringRef Name;
Sec.getName(Name);
if (Name == ClangASTSectionName) {
@@ -1341,11 +1434,7 @@ void llvm::printRawClangAST(const ObjectFile *Obj) {
return;
StringRef ClangASTContents;
- if (error(ClangASTSection.getValue().getContents(ClangASTContents))) {
- errs() << "Could not read the " << ClangASTSectionName << " section!\n";
- return;
- }
-
+ error(ClangASTSection.getValue().getContents(ClangASTContents));
outs().write(ClangASTContents.data(), ClangASTContents.size());
}
@@ -1364,7 +1453,7 @@ static void printFaultMaps(const ObjectFile *Obj) {
Optional<object::SectionRef> FaultMapSection;
- for (auto Sec : Obj->sections()) {
+ for (auto Sec : ToolSectionFilter(*Obj)) {
StringRef Name;
Sec.getName(Name);
if (Name == FaultMapSectionName) {
@@ -1381,10 +1470,7 @@ static void printFaultMaps(const ObjectFile *Obj) {
}
StringRef FaultMapContents;
- if (error(FaultMapSection.getValue().getContents(FaultMapContents))) {
- errs() << "Could not read the " << FaultMapContents << " section!\n";
- return;
- }
+ error(FaultMapSection.getValue().getContents(FaultMapContents));
FaultMapParser FMP(FaultMapContents.bytes_begin(),
FaultMapContents.bytes_end());
@@ -1393,13 +1479,14 @@ static void printFaultMaps(const ObjectFile *Obj) {
}
static void printPrivateFileHeader(const ObjectFile *o) {
- if (o->isELF()) {
+ if (o->isELF())
printELFFileHeader(o);
- } else if (o->isCOFF()) {
+ else if (o->isCOFF())
printCOFFFileHeader(o);
- } else if (o->isMachO()) {
+ else if (o->isMachO())
printMachOFileHeader(o);
- }
+ else
+ report_fatal_error("Invalid/Unsupported object file format");
}
static void DumpObject(const ObjectFile *o) {
@@ -1442,15 +1529,14 @@ static void DumpObject(const ObjectFile *o) {
/// @brief Dump each object file in \a a;
static void DumpArchive(const Archive *a) {
- for (Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e;
- ++i) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
- if (std::error_code EC = ChildOrErr.getError()) {
- // Ignore non-object files.
+ for (auto &ErrorOrChild : a->children()) {
+ if (std::error_code EC = ErrorOrChild.getError())
+ report_error(a->getFileName(), EC);
+ const Archive::Child &C = *ErrorOrChild;
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
+ if (std::error_code EC = ChildOrErr.getError())
if (EC != object_error::invalid_file_type)
report_error(a->getFileName(), EC);
- continue;
- }
if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
DumpObject(o);
else
@@ -1460,11 +1546,6 @@ static void DumpArchive(const Archive *a) {
/// @brief Open file and figure out how to dump it.
static void DumpInput(StringRef file) {
- // If file isn't stdin, check that it exists.
- if (file != "-" && !sys::fs::exists(file)) {
- report_error(file, errc::no_such_file_or_directory);
- return;
- }
// If we are using the Mach-O specific object file parser, then let it parse
// the file and process the command line options. So the -arch flags can
@@ -1476,10 +1557,8 @@ static void DumpInput(StringRef file) {
// Attempt to open the binary.
ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
- if (std::error_code EC = BinaryOrErr.getError()) {
+ if (std::error_code EC = BinaryOrErr.getError())
report_error(file, EC);
- return;
- }
Binary &Binary = *BinaryOrErr.get().getBinary();
if (Archive *a = dyn_cast<Archive>(&Binary))
@@ -1499,7 +1578,6 @@ int main(int argc, char **argv) {
// Initialize targets and assembly printers/parsers.
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
- llvm::InitializeAllAsmParsers();
llvm::InitializeAllDisassemblers();
// Register the target printer for --version.
@@ -1514,6 +1592,8 @@ int main(int argc, char **argv) {
if (InputFilenames.size() == 0)
InputFilenames.push_back("a.out");
+ if (DisassembleAll)
+ Disassemble = true;
if (!Disassemble
&& !Relocations
&& !SectionHeaders
@@ -1536,7 +1616,7 @@ int main(int argc, char **argv) {
&& !(DylibsUsed && MachOOpt)
&& !(DylibId && MachOOpt)
&& !(ObjcMetaData && MachOOpt)
- && !(DumpSections.size() != 0 && MachOOpt)
+ && !(FilterSections.size() != 0 && MachOOpt)
&& !PrintFaultMaps) {
cl::PrintHelpMessage();
return 2;
@@ -1545,5 +1625,5 @@ int main(int argc, char **argv) {
std::for_each(InputFilenames.begin(), InputFilenames.end(),
DumpInput);
- return ReturnValue;
+ return EXIT_SUCCESS;
}
diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h
index eb10d8344f71..6e8ad6bda156 100644
--- a/tools/llvm-objdump/llvm-objdump.h
+++ b/tools/llvm-objdump/llvm-objdump.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@@ -25,8 +26,9 @@ extern cl::opt<std::string> TripleName;
extern cl::opt<std::string> ArchName;
extern cl::opt<std::string> MCPU;
extern cl::list<std::string> MAttrs;
-extern cl::list<std::string> DumpSections;
+extern cl::list<std::string> FilterSections;
extern cl::opt<bool> Disassemble;
+extern cl::opt<bool> DisassembleAll;
extern cl::opt<bool> NoShowRawInsn;
extern cl::opt<bool> PrivateHeaders;
extern cl::opt<bool> ExportsTrie;
@@ -54,7 +56,7 @@ extern cl::opt<bool> UnwindInfo;
extern cl::opt<bool> PrintImmHex;
// Various helper functions.
-bool error(std::error_code ec);
+void error(std::error_code ec);
bool RelocAddressLess(object::RelocationRef a, object::RelocationRef b);
void ParseInputMachO(StringRef Filename);
void printCOFFUnwindInfo(const object::COFFObjectFile* o);
@@ -66,6 +68,7 @@ void printMachOLazyBindTable(const object::MachOObjectFile* o);
void printMachOWeakBindTable(const object::MachOObjectFile* o);
void printELFFileHeader(const object::ObjectFile *o);
void printCOFFFileHeader(const object::ObjectFile *o);
+void printCOFFSymbolTable(const object::COFFObjectFile *o);
void printMachOFileHeader(const object::ObjectFile *o);
void printExportsTrie(const object::ObjectFile *o);
void printRebaseTable(const object::ObjectFile *o);
@@ -77,6 +80,7 @@ void PrintRelocations(const object::ObjectFile *o);
void PrintSectionHeaders(const object::ObjectFile *o);
void PrintSectionContents(const object::ObjectFile *o);
void PrintSymbolTable(const object::ObjectFile *o);
+LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, std::error_code EC);
} // end namespace llvm