summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/llvm-objdump
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/llvm-objdump')
-rw-r--r--contrib/llvm/tools/llvm-objdump/COFFDump.cpp102
-rw-r--r--contrib/llvm/tools/llvm-objdump/MachODump.cpp1156
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp383
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.h22
4 files changed, 1130 insertions, 533 deletions
diff --git a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
index 5d21b33..3ec6a1f 100644
--- a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -161,13 +161,13 @@ static std::error_code
resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym,
const coff_section *&ResolvedSection,
uint64_t &ResolvedAddr) {
- ErrorOr<uint64_t> ResolvedAddrOrErr = Sym.getAddress();
- if (std::error_code EC = ResolvedAddrOrErr.getError())
- return EC;
+ Expected<uint64_t> ResolvedAddrOrErr = Sym.getAddress();
+ if (!ResolvedAddrOrErr)
+ return errorToErrorCode(ResolvedAddrOrErr.takeError());
ResolvedAddr = *ResolvedAddrOrErr;
- ErrorOr<section_iterator> Iter = Sym.getSection();
- if (std::error_code EC = Iter.getError())
- return EC;
+ Expected<section_iterator> Iter = Sym.getSection();
+ if (!Iter)
+ return errorToErrorCode(Iter.takeError());
ResolvedSection = Obj->getCOFFSection(**Iter);
return std::error_code();
}
@@ -215,9 +215,9 @@ static std::error_code resolveSymbolName(const std::vector<RelocationRef> &Rels,
SymbolRef Sym;
if (std::error_code EC = resolveSymbol(Rels, Offset, Sym))
return EC;
- ErrorOr<StringRef> NameOrErr = Sym.getName();
- if (std::error_code EC = NameOrErr.getError())
- return EC;
+ Expected<StringRef> NameOrErr = Sym.getName();
+ if (!NameOrErr)
+ return errorToErrorCode(NameOrErr.takeError());
Name = *NameOrErr;
return std::error_code();
}
@@ -252,6 +252,56 @@ printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
outs() << "\n\n";
}
+template <typename T>
+static void printTLSDirectoryT(const coff_tls_directory<T> *TLSDir) {
+ size_t FormatWidth = sizeof(T) * 2;
+ outs() << "TLS directory:"
+ << "\n StartAddressOfRawData: "
+ << format_hex(TLSDir->StartAddressOfRawData, FormatWidth)
+ << "\n EndAddressOfRawData: "
+ << format_hex(TLSDir->EndAddressOfRawData, FormatWidth)
+ << "\n AddressOfIndex: "
+ << format_hex(TLSDir->AddressOfIndex, FormatWidth)
+ << "\n AddressOfCallBacks: "
+ << format_hex(TLSDir->AddressOfCallBacks, FormatWidth)
+ << "\n SizeOfZeroFill: "
+ << TLSDir->SizeOfZeroFill
+ << "\n Characteristics: "
+ << TLSDir->Characteristics
+ << "\n Alignment: "
+ << TLSDir->getAlignment()
+ << "\n\n";
+}
+
+static void printTLSDirectory(const COFFObjectFile *Obj) {
+ const pe32_header *PE32Header;
+ error(Obj->getPE32Header(PE32Header));
+
+ const pe32plus_header *PE32PlusHeader;
+ error(Obj->getPE32PlusHeader(PE32PlusHeader));
+
+ // Skip if it's not executable.
+ if (!PE32Header && !PE32PlusHeader)
+ return;
+
+ const data_directory *DataDir;
+ error(Obj->getDataDirectory(COFF::TLS_TABLE, DataDir));
+ uintptr_t IntPtr = 0;
+ if (DataDir->RelativeVirtualAddress == 0)
+ return;
+ error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr));
+
+ if (PE32Header) {
+ auto *TLSDir = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
+ printTLSDirectoryT(TLSDir);
+ } else {
+ auto *TLSDir = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
+ printTLSDirectoryT(TLSDir);
+ }
+
+ outs() << "\n";
+}
+
static void printLoadConfiguration(const COFFObjectFile *Obj) {
// Skip if it's not executable.
const pe32_header *PE32Header;
@@ -302,11 +352,11 @@ static void printImportTables(const COFFObjectFile *Obj) {
if (I == E)
return;
outs() << "The Import Tables:\n";
- for (; I != E; I = ++I) {
+ for (const ImportDirectoryEntryRef &DirRef : Obj->import_directories()) {
const import_directory_table_entry *Dir;
StringRef Name;
- if (I->getImportTableEntry(Dir)) return;
- if (I->getName(Name)) return;
+ if (DirRef.getImportTableEntry(Dir)) return;
+ if (DirRef.getName(Name)) return;
outs() << format(" lookup %08x time %08x fwd %08x name %08x addr %08x\n\n",
static_cast<uint32_t>(Dir->ImportLookupTableRVA),
@@ -316,17 +366,23 @@ static void printImportTables(const COFFObjectFile *Obj) {
static_cast<uint32_t>(Dir->ImportAddressTableRVA));
outs() << " DLL Name: " << Name << "\n";
outs() << " Hint/Ord Name\n";
- const import_lookup_table_entry32 *entry;
- if (I->getImportLookupEntry(entry))
- return;
- for (; entry->Data; ++entry) {
- if (entry->isOrdinal()) {
- outs() << format(" % 6d\n", entry->getOrdinal());
+ for (const ImportedSymbolRef &Entry : DirRef.imported_symbols()) {
+ bool IsOrdinal;
+ if (Entry.isOrdinal(IsOrdinal))
+ return;
+ if (IsOrdinal) {
+ uint16_t Ordinal;
+ if (Entry.getOrdinal(Ordinal))
+ return;
+ outs() << format(" % 6d\n", Ordinal);
continue;
}
+ uint32_t HintNameRVA;
+ if (Entry.getHintNameRVA(HintNameRVA))
+ return;
uint16_t Hint;
StringRef Name;
- if (Obj->getHintName(entry->getHintNameRVA(), Hint, Name))
+ if (Obj->getHintName(HintNameRVA, Hint, Name))
return;
outs() << format(" % 6d ", Hint) << Name << "\n";
}
@@ -555,6 +611,7 @@ void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
void llvm::printCOFFFileHeader(const object::ObjectFile *Obj) {
const COFFObjectFile *file = dyn_cast<const COFFObjectFile>(Obj);
+ printTLSDirectory(file);
printLoadConfiguration(file);
printImportTables(file);
printExportTable(file);
@@ -602,6 +659,13 @@ void llvm::printCOFFSymbolTable(const COFFObjectFile *coff) {
SI = SI + Symbol->getNumberOfAuxSymbols();
break;
+ } else if (Symbol->isWeakExternal()) {
+ const coff_aux_weak_external *awe;
+ error(coff->getAuxSymbol<coff_aux_weak_external>(SI + 1, awe));
+
+ outs() << "AUX " << format("indx %d srch %d\n",
+ static_cast<uint32_t>(awe->TagIndex),
+ static_cast<uint32_t>(awe->Characteristics));
} else {
outs() << "AUX Unknown\n";
}
diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
index 258c0b5..4d950f1 100644
--- a/contrib/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
@@ -11,9 +11,9 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/Object/MachO.h"
#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"
@@ -22,14 +22,13 @@
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Object/MachO.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
@@ -43,6 +42,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
@@ -52,6 +52,12 @@
#include <cxxabi.h>
#endif
+#ifdef HAVE_LIBXAR
+extern "C" {
+#include <xar/xar.h>
+}
+#endif
+
using namespace llvm;
using namespace object;
@@ -143,11 +149,18 @@ static const Target *GetTarget(const MachOObjectFile *MachOObj,
const char **McpuDefault,
const Target **ThumbTarget) {
// Figure out the target triple.
+ llvm::Triple TT(TripleName);
if (TripleName.empty()) {
- llvm::Triple TT("unknown-unknown-unknown");
- llvm::Triple ThumbTriple = Triple();
- TT = MachOObj->getArch(McpuDefault, &ThumbTriple);
+ TT = MachOObj->getArchTriple(McpuDefault);
TripleName = TT.str();
+ }
+
+ if (TT.getArch() == Triple::arm) {
+ // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
+ // that support ARM are also capable of Thumb mode.
+ llvm::Triple ThumbTriple = TT;
+ std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
+ ThumbTriple.setArchName(ThumbName);
ThumbTripleName = ThumbTriple.str();
}
@@ -172,8 +185,26 @@ static const Target *GetTarget(const MachOObjectFile *MachOObj,
struct SymbolSorter {
bool operator()(const SymbolRef &A, const SymbolRef &B) {
- uint64_t AAddr = (A.getType() != SymbolRef::ST_Function) ? 0 : A.getValue();
- uint64_t BAddr = (B.getType() != SymbolRef::ST_Function) ? 0 : B.getValue();
+ Expected<SymbolRef::Type> ATypeOrErr = A.getType();
+ if (!ATypeOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(ATypeOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
+ SymbolRef::Type AType = *ATypeOrErr;
+ Expected<SymbolRef::Type> BTypeOrErr = B.getType();
+ if (!BTypeOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(BTypeOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
+ SymbolRef::Type BType = *BTypeOrErr;
+ uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue();
+ uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue();
return AAddr < BAddr;
}
};
@@ -266,9 +297,14 @@ static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
SmallVectorImpl<uint64_t> &FoundFns,
uint64_t &BaseSegmentAddress) {
for (const SymbolRef &Symbol : MachOObj->symbols()) {
- ErrorOr<StringRef> SymName = Symbol.getName();
- if (std::error_code EC = SymName.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymName = Symbol.getName();
+ if (!SymName) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymName.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
if (!SymName->startswith("ltmp"))
Symbols.push_back(Symbol);
}
@@ -324,7 +360,7 @@ static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
if (cputype & MachO::CPU_ARCH_ABI64)
outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
else
- outs() << format("0x%08" PRIx32, addr + j * stride) << " ";
+ outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
@@ -346,9 +382,14 @@ static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
if (indirect_symbol < Symtab.nsyms) {
symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
SymbolRef Symbol = *Sym;
- ErrorOr<StringRef> SymName = Symbol.getName();
- if (std::error_code EC = SymName.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymName = Symbol.getName();
+ if (!SymName) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymName.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
outs() << *SymName;
} else {
outs() << "?";
@@ -573,13 +614,26 @@ static void CreateSymbolAddressMap(MachOObjectFile *O,
SymbolAddressMap *AddrMap) {
// Create a map of symbol addresses to symbol names.
for (const SymbolRef &Symbol : O->symbols()) {
- SymbolRef::Type ST = Symbol.getType();
+ Expected<SymbolRef::Type> STOrErr = Symbol.getType();
+ if (!STOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(STOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
+ SymbolRef::Type ST = *STOrErr;
if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
ST == SymbolRef::ST_Other) {
uint64_t Address = Symbol.getValue();
- ErrorOr<StringRef> SymNameOrErr = Symbol.getName();
- if (std::error_code EC = SymNameOrErr.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymNameOrErr = Symbol.getName();
+ if (!SymNameOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
StringRef SymName = *SymNameOrErr;
if (!SymName.startswith(".objc"))
(*AddrMap)[Address] = SymName;
@@ -813,9 +867,14 @@ static void DumpLiteralPointerSection(MachOObjectFile *O,
[&](const std::pair<uint64_t, SymbolRef> &P) { return P.first == i; });
if (Reloc != Relocs.end()) {
symbol_iterator RelocSym = Reloc->second;
- ErrorOr<StringRef> SymName = RelocSym->getName();
- if (std::error_code EC = SymName.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymName = RelocSym->getName();
+ if (!SymName) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymName.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
outs() << "external relocation entry for symbol:" << *SymName << "\n";
continue;
}
@@ -964,10 +1023,10 @@ static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
if (O->is64Bit())
outs() << format("%016" PRIx64, addr) << "\t";
else
- outs() << format("%08" PRIx64, sect) << "\t";
+ outs() << format("%08" PRIx64, addr) << "\t";
for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
j += sizeof(int32_t)) {
- if (i + j + sizeof(int32_t) < size) {
+ if (i + j + sizeof(int32_t) <= size) {
uint32_t long_word;
memcpy(&long_word, sect + i + j, sizeof(int32_t));
if (O->isLittleEndian() != sys::IsLittleEndianHost)
@@ -975,7 +1034,7 @@ static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
outs() << format("%08" PRIx32, long_word) << " ";
} else {
for (uint32_t k = 0; i + j + k < size; k++) {
- uint8_t byte_word = *(sect + i + j);
+ uint8_t byte_word = *(sect + i + j + k);
outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
}
}
@@ -989,6 +1048,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
StringRef DisSegName, StringRef DisSectName);
static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
uint32_t size, uint32_t addr);
+#ifdef HAVE_LIBXAR
+static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
+ uint32_t size, bool verbose,
+ bool PrintXarHeader, bool PrintXarFileHeaders,
+ std::string XarMemberName);
+#endif // defined(HAVE_LIBXAR)
static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
bool verbose) {
@@ -1050,6 +1115,13 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
DumpProtocolSection(O, sect, sect_size, sect_addr);
continue;
}
+#ifdef HAVE_LIBXAR
+ if (SegName == "__LLVM" && SectName == "__bundle") {
+ DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands,
+ ArchiveHeaders, "");
+ continue;
+ }
+#endif // defined(HAVE_LIBXAR)
switch (section_type) {
case MachO::S_REGULAR:
DumpRawSectionContents(O, sect, sect_size, sect_addr);
@@ -1127,10 +1199,10 @@ static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
Triple T;
if (MachO->is64Bit()) {
H_64 = MachO->MachOObjectFile::getHeader64();
- T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype);
+ T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype);
} else {
H = MachO->MachOObjectFile::getHeader();
- T = MachOObjectFile::getArch(H.cputype, H.cpusubtype);
+ T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype);
}
unsigned i;
for (i = 0; i < ArchFlags.size(); ++i) {
@@ -1159,7 +1231,7 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
// If we are doing some processing here on the Mach-O file print the header
// info. And don't print it otherwise like in the case of printing the
// UniversalHeaders or ArchiveHeaders.
- if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
+ if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable ||
LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) {
outs() << Filename;
@@ -1192,8 +1264,10 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
PrintDylibs(MachOOF, false);
if (DylibId)
PrintDylibs(MachOOF, true);
- if (SymbolTable)
- PrintSymbolTable(MachOOF);
+ if (SymbolTable) {
+ StringRef ArchiveName = ArchiveMemberName == StringRef() ? "" : Filename;
+ PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName);
+ }
if (UnwindInfo)
printMachOUnwindInfo(MachOOF);
if (PrivateHeaders) {
@@ -1214,6 +1288,12 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
printLazyBindTable(MachOOF);
if (WeakBind)
printWeakBindTable(MachOOF);
+
+ if (DwarfDumpType != DIDT_Null) {
+ std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*MachOOF));
+ // Dump the complete DWARF structure.
+ DICtx->dump(outs(), DwarfDumpType, true /* DumpEH */);
+ }
}
// printUnknownCPUType() helps print_fat_headers for unknown CPU's.
@@ -1323,9 +1403,12 @@ static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
bool verbose) {
outs() << "Fat headers\n";
- if (verbose)
- outs() << "fat_magic FAT_MAGIC\n";
- else
+ if (verbose) {
+ if (UB->getMagic() == MachO::FAT_MAGIC)
+ outs() << "fat_magic FAT_MAGIC\n";
+ else // UB->getMagic() == MachO::FAT_MAGIC_64
+ outs() << "fat_magic FAT_MAGIC_64\n";
+ } else
outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
uint32_t nfat_arch = UB->getNumberOfObjects();
@@ -1452,13 +1535,11 @@ static void printArchiveChild(const Archive::Child &C, bool verbose,
}
static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) {
- 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;
+ Error Err;
+ for (const auto &C : A->children(Err, false))
printArchiveChild(C, verbose, print_offset);
- }
+ if (Err)
+ report_fatal_error(std::move(Err));
}
// ParseInputMachO() parses the named Mach-O file in Filename and handles the
@@ -1480,29 +1561,31 @@ void llvm::ParseInputMachO(StringRef Filename) {
}
// Attempt to open the binary.
- ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
- if (std::error_code EC = BinaryOrErr.getError())
- report_error(Filename, EC);
+ Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
+ if (!BinaryOrErr)
+ report_error(Filename, BinaryOrErr.takeError());
Binary &Bin = *BinaryOrErr.get().getBinary();
if (Archive *A = dyn_cast<Archive>(&Bin)) {
outs() << "Archive : " << Filename << "\n";
if (ArchiveHeaders)
printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets);
- for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
- I != E; ++I) {
- 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())
+ Error Err;
+ for (auto &C : A->children(Err)) {
+ Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
+ if (!ChildOrErr) {
+ if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
+ report_error(Filename, C, std::move(E));
continue;
+ }
if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
if (!checkMachOAndArchFlags(O, Filename))
return;
ProcessMachO(Filename, O, O->getFileName());
}
}
+ if (Err)
+ report_error(Filename, std::move(Err));
return;
}
if (UniversalHeaders) {
@@ -1521,7 +1604,7 @@ void llvm::ParseInputMachO(StringRef Filename) {
I != E; ++I) {
if (ArchFlags[i] == I->getArchTypeName()) {
ArchFound = true;
- ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
+ Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
I->getAsObjectFile();
std::string ArchitectureName = "";
if (ArchFlags.size() > 1)
@@ -1530,7 +1613,12 @@ void llvm::ParseInputMachO(StringRef Filename) {
ObjectFile &O = *ObjOrErr.get();
if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
ProcessMachO(Filename, MachOOF, "", ArchitectureName);
- } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
+ } else if (auto E = isNotObjectErrorInvalidFileType(
+ ObjOrErr.takeError())) {
+ report_error(Filename, StringRef(), std::move(E),
+ ArchitectureName);
+ continue;
+ } else if (Expected<std::unique_ptr<Archive>> AOrErr =
I->getAsArchive()) {
std::unique_ptr<Archive> &A = *AOrErr;
outs() << "Archive : " << Filename;
@@ -1539,19 +1627,25 @@ void llvm::ParseInputMachO(StringRef Filename) {
outs() << "\n";
if (ArchiveHeaders)
printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
- for (Archive::child_iterator AI = A->child_begin(),
- AE = A->child_end();
- AI != AE; ++AI) {
- 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())
+ Error Err;
+ for (auto &C : A->children(Err)) {
+ Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
+ if (!ChildOrErr) {
+ if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
+ report_error(Filename, C, std::move(E), ArchitectureName);
continue;
+ }
if (MachOObjectFile *O =
dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
}
+ if (Err)
+ report_error(Filename, std::move(Err));
+ } else {
+ consumeError(AOrErr.takeError());
+ error("Mach-O universal file: " + Filename + " for " +
+ "architecture " + StringRef(I->getArchTypeName()) +
+ " is not a Mach-O file or an archive file");
}
}
}
@@ -1571,32 +1665,42 @@ void llvm::ParseInputMachO(StringRef Filename) {
I != E; ++I) {
if (MachOObjectFile::getHostArch().getArchName() ==
I->getArchTypeName()) {
- ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
+ Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
std::string ArchiveName;
ArchiveName.clear();
if (ObjOrErr) {
ObjectFile &O = *ObjOrErr.get();
if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
ProcessMachO(Filename, MachOOF);
- } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
+ } else if (auto E = isNotObjectErrorInvalidFileType(
+ ObjOrErr.takeError())) {
+ report_error(Filename, std::move(E));
+ continue;
+ } else if (Expected<std::unique_ptr<Archive>> AOrErr =
I->getAsArchive()) {
std::unique_ptr<Archive> &A = *AOrErr;
outs() << "Archive : " << Filename << "\n";
if (ArchiveHeaders)
printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
- for (Archive::child_iterator AI = A->child_begin(),
- AE = A->child_end();
- AI != AE; ++AI) {
- 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())
+ Error Err;
+ for (auto &C : A->children(Err)) {
+ Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
+ if (!ChildOrErr) {
+ if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
+ report_error(Filename, C, std::move(E));
continue;
+ }
if (MachOObjectFile *O =
dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
ProcessMachO(Filename, O, O->getFileName());
}
+ if (Err)
+ report_error(Filename, std::move(Err));
+ } else {
+ consumeError(AOrErr.takeError());
+ error("Mach-O universal file: " + Filename + " for architecture " +
+ StringRef(I->getArchTypeName()) +
+ " is not a Mach-O file or an archive file");
}
return;
}
@@ -1608,7 +1712,7 @@ void llvm::ParseInputMachO(StringRef Filename) {
for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
E = UB->end_objects();
I != E; ++I) {
- ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
+ Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
std::string ArchitectureName = "";
if (moreThanOneArch)
ArchitectureName = I->getArchTypeName();
@@ -1616,7 +1720,12 @@ void llvm::ParseInputMachO(StringRef Filename) {
ObjectFile &Obj = *ObjOrErr.get();
if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
ProcessMachO(Filename, MachOOF, "", ArchitectureName);
- } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
+ } else if (auto E = isNotObjectErrorInvalidFileType(
+ ObjOrErr.takeError())) {
+ report_error(StringRef(), Filename, std::move(E), ArchitectureName);
+ continue;
+ } else if (Expected<std::unique_ptr<Archive>> AOrErr =
+ I->getAsArchive()) {
std::unique_ptr<Archive> &A = *AOrErr;
outs() << "Archive : " << Filename;
if (!ArchitectureName.empty())
@@ -1624,14 +1733,14 @@ void llvm::ParseInputMachO(StringRef Filename) {
outs() << "\n";
if (ArchiveHeaders)
printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
- for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
- AI != AE; ++AI) {
- 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())
+ Error Err;
+ for (auto &C : A->children(Err)) {
+ Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
+ if (!ChildOrErr) {
+ if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
+ report_error(Filename, C, std::move(E), ArchitectureName);
continue;
+ }
if (MachOObjectFile *O =
dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
@@ -1639,6 +1748,13 @@ void llvm::ParseInputMachO(StringRef Filename) {
ArchitectureName);
}
}
+ if (Err)
+ report_error(Filename, std::move(Err));
+ } else {
+ consumeError(AOrErr.takeError());
+ error("Mach-O universal file: " + Filename + " for architecture " +
+ StringRef(I->getArchTypeName()) +
+ " is not a Mach-O file or an archive file");
}
}
return;
@@ -1762,9 +1878,14 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
}
}
if (reloc_found && isExtern) {
- ErrorOr<StringRef> SymName = Symbol.getName();
- if (std::error_code EC = SymName.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymName = Symbol.getName();
+ if (!SymName) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymName.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
const char *name = SymName->data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
@@ -1832,9 +1953,14 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
// is the offset from the external symbol.
if (info->O->getAnyRelocationPCRel(RE))
op_info->Value -= Pc + Offset + Size;
- ErrorOr<StringRef> SymName = Symbol.getName();
- if (std::error_code EC = SymName.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymName = Symbol.getName();
+ if (!SymName) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymName.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
const char *name = SymName->data();
unsigned Type = info->O->getAnyRelocationType(RE);
if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
@@ -1849,9 +1975,14 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
op_info->SubtractSymbol.Name = name;
symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
Symbol = *RelocSymNext;
- ErrorOr<StringRef> SymNameNext = Symbol.getName();
- if (std::error_code EC = SymNameNext.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymNameNext = Symbol.getName();
+ if (!SymNameNext) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymNameNext.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
name = SymNameNext->data();
}
}
@@ -1922,9 +2053,14 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
}
if (isExtern) {
- ErrorOr<StringRef> SymName = Symbol.getName();
- if (std::error_code EC = SymName.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymName = Symbol.getName();
+ if (!SymName) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymName.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
const char *name = SymName->data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
@@ -2042,9 +2178,14 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
// NOTE: Scattered relocations don't exist on arm64.
if (!info->O->getPlainRelocationExternal(RE))
return 0;
- ErrorOr<StringRef> SymName = Reloc->getSymbol()->getName();
- if (std::error_code EC = SymName.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymName = Reloc->getSymbol()->getName();
+ if (!SymName) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymName.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
const char *name = SymName->data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
@@ -2172,9 +2313,14 @@ static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
if (indirect_symbol < Symtab.nsyms) {
symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
SymbolRef Symbol = *Sym;
- ErrorOr<StringRef> SymName = Symbol.getName();
- if (std::error_code EC = SymName.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymName = Symbol.getName();
+ if (!SymName) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymName.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
const char *name = SymName->data();
return name;
}
@@ -2207,9 +2353,14 @@ static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
if (indirect_symbol < Symtab.nsyms) {
symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
SymbolRef Symbol = *Sym;
- ErrorOr<StringRef> SymName = Symbol.getName();
- if (std::error_code EC = SymName.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymName = Symbol.getName();
+ if (!SymName) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymName.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
const char *name = SymName->data();
return name;
}
@@ -2436,9 +2587,14 @@ static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
const char *SymbolName = nullptr;
if (reloc_found && isExtern) {
n_value = Symbol.getValue();
- ErrorOr<StringRef> NameOrError = Symbol.getName();
- if (std::error_code EC = NameOrError.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> NameOrError = Symbol.getName();
+ if (!NameOrError) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(NameOrError.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
StringRef Name = *NameOrError;
if (!Name.empty()) {
SymbolName = Name.data();
@@ -5058,6 +5214,9 @@ static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
struct objc_image_info32 o;
const char *r;
+ if (S == SectionRef())
+ return;
+
StringRef SectName;
S.getName(SectName);
DataRefImpl Ref = S.getRawDataRefImpl();
@@ -5530,6 +5689,373 @@ static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
}
}
+#ifdef HAVE_LIBXAR
+inline void swapStruct(struct xar_header &xar) {
+ sys::swapByteOrder(xar.magic);
+ sys::swapByteOrder(xar.size);
+ sys::swapByteOrder(xar.version);
+ sys::swapByteOrder(xar.toc_length_compressed);
+ sys::swapByteOrder(xar.toc_length_uncompressed);
+ sys::swapByteOrder(xar.cksum_alg);
+}
+
+static void PrintModeVerbose(uint32_t mode) {
+ switch(mode & S_IFMT){
+ case S_IFDIR:
+ outs() << "d";
+ break;
+ case S_IFCHR:
+ outs() << "c";
+ break;
+ case S_IFBLK:
+ outs() << "b";
+ break;
+ case S_IFREG:
+ outs() << "-";
+ break;
+ case S_IFLNK:
+ outs() << "l";
+ break;
+ case S_IFSOCK:
+ outs() << "s";
+ break;
+ default:
+ outs() << "?";
+ break;
+ }
+
+ /* owner permissions */
+ if(mode & S_IREAD)
+ outs() << "r";
+ else
+ outs() << "-";
+ if(mode & S_IWRITE)
+ outs() << "w";
+ else
+ outs() << "-";
+ if(mode & S_ISUID)
+ outs() << "s";
+ else if(mode & S_IEXEC)
+ outs() << "x";
+ else
+ outs() << "-";
+
+ /* group permissions */
+ if(mode & (S_IREAD >> 3))
+ outs() << "r";
+ else
+ outs() << "-";
+ if(mode & (S_IWRITE >> 3))
+ outs() << "w";
+ else
+ outs() << "-";
+ if(mode & S_ISGID)
+ outs() << "s";
+ else if(mode & (S_IEXEC >> 3))
+ outs() << "x";
+ else
+ outs() << "-";
+
+ /* other permissions */
+ if(mode & (S_IREAD >> 6))
+ outs() << "r";
+ else
+ outs() << "-";
+ if(mode & (S_IWRITE >> 6))
+ outs() << "w";
+ else
+ outs() << "-";
+ if(mode & S_ISVTX)
+ outs() << "t";
+ else if(mode & (S_IEXEC >> 6))
+ outs() << "x";
+ else
+ outs() << "-";
+}
+
+static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
+ xar_iter_t xi;
+ xar_file_t xf;
+ xar_iter_t xp;
+ const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
+ char *endp;
+ uint32_t mode_value;
+
+ xi = xar_iter_new();
+ if (!xi) {
+ errs() << "Can't obtain an xar iterator for xar archive "
+ << XarFilename << "\n";
+ return;
+ }
+
+ // Go through the xar's files.
+ for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
+ xp = xar_iter_new();
+ if(!xp){
+ errs() << "Can't obtain an xar iterator for xar archive "
+ << XarFilename << "\n";
+ return;
+ }
+ type = nullptr;
+ mode = nullptr;
+ user = nullptr;
+ group = nullptr;
+ size = nullptr;
+ mtime = nullptr;
+ name = nullptr;
+ for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
+ const char *val = nullptr;
+ xar_prop_get(xf, key, &val);
+#if 0 // Useful for debugging.
+ outs() << "key: " << key << " value: " << val << "\n";
+#endif
+ if(strcmp(key, "type") == 0)
+ type = val;
+ if(strcmp(key, "mode") == 0)
+ mode = val;
+ if(strcmp(key, "user") == 0)
+ user = val;
+ if(strcmp(key, "group") == 0)
+ group = val;
+ if(strcmp(key, "data/size") == 0)
+ size = val;
+ if(strcmp(key, "mtime") == 0)
+ mtime = val;
+ if(strcmp(key, "name") == 0)
+ name = val;
+ }
+ if(mode != nullptr){
+ mode_value = strtoul(mode, &endp, 8);
+ if(*endp != '\0')
+ outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
+ if(strcmp(type, "file") == 0)
+ mode_value |= S_IFREG;
+ PrintModeVerbose(mode_value);
+ outs() << " ";
+ }
+ if(user != nullptr)
+ outs() << format("%10s/", user);
+ if(group != nullptr)
+ outs() << format("%-10s ", group);
+ if(size != nullptr)
+ outs() << format("%7s ", size);
+ if(mtime != nullptr){
+ for(m = mtime; *m != 'T' && *m != '\0'; m++)
+ outs() << *m;
+ if(*m == 'T')
+ m++;
+ outs() << " ";
+ for( ; *m != 'Z' && *m != '\0'; m++)
+ outs() << *m;
+ outs() << " ";
+ }
+ if(name != nullptr)
+ outs() << name;
+ outs() << "\n";
+ }
+}
+
+static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
+ uint32_t size, bool verbose,
+ bool PrintXarHeader, bool PrintXarFileHeaders,
+ std::string XarMemberName) {
+ if(size < sizeof(struct xar_header)) {
+ outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
+ "of struct xar_header)\n";
+ return;
+ }
+ struct xar_header XarHeader;
+ memcpy(&XarHeader, sect, sizeof(struct xar_header));
+ if (sys::IsLittleEndianHost)
+ swapStruct(XarHeader);
+ if (PrintXarHeader) {
+ if (!XarMemberName.empty())
+ outs() << "In xar member " << XarMemberName << ": ";
+ else
+ outs() << "For (__LLVM,__bundle) section: ";
+ outs() << "xar header\n";
+ if (XarHeader.magic == XAR_HEADER_MAGIC)
+ outs() << " magic XAR_HEADER_MAGIC\n";
+ else
+ outs() << " magic "
+ << format_hex(XarHeader.magic, 10, true)
+ << " (not XAR_HEADER_MAGIC)\n";
+ outs() << " size " << XarHeader.size << "\n";
+ outs() << " version " << XarHeader.version << "\n";
+ outs() << " toc_length_compressed " << XarHeader.toc_length_compressed
+ << "\n";
+ outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
+ << "\n";
+ outs() << " cksum_alg ";
+ switch (XarHeader.cksum_alg) {
+ case XAR_CKSUM_NONE:
+ outs() << "XAR_CKSUM_NONE\n";
+ break;
+ case XAR_CKSUM_SHA1:
+ outs() << "XAR_CKSUM_SHA1\n";
+ break;
+ case XAR_CKSUM_MD5:
+ outs() << "XAR_CKSUM_MD5\n";
+ break;
+#ifdef XAR_CKSUM_SHA256
+ case XAR_CKSUM_SHA256:
+ outs() << "XAR_CKSUM_SHA256\n";
+ break;
+#endif
+#ifdef XAR_CKSUM_SHA512
+ case XAR_CKSUM_SHA512:
+ outs() << "XAR_CKSUM_SHA512\n";
+ break;
+#endif
+ default:
+ outs() << XarHeader.cksum_alg << "\n";
+ }
+ }
+
+ SmallString<128> XarFilename;
+ int FD;
+ std::error_code XarEC =
+ sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
+ if (XarEC) {
+ errs() << XarEC.message() << "\n";
+ return;
+ }
+ tool_output_file XarFile(XarFilename, FD);
+ raw_fd_ostream &XarOut = XarFile.os();
+ StringRef XarContents(sect, size);
+ XarOut << XarContents;
+ XarOut.close();
+ if (XarOut.has_error())
+ return;
+
+ xar_t xar = xar_open(XarFilename.c_str(), READ);
+ if (!xar) {
+ errs() << "Can't create temporary xar archive " << XarFilename << "\n";
+ return;
+ }
+
+ SmallString<128> TocFilename;
+ std::error_code TocEC =
+ sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
+ if (TocEC) {
+ errs() << TocEC.message() << "\n";
+ return;
+ }
+ xar_serialize(xar, TocFilename.c_str());
+
+ if (PrintXarFileHeaders) {
+ if (!XarMemberName.empty())
+ outs() << "In xar member " << XarMemberName << ": ";
+ else
+ outs() << "For (__LLVM,__bundle) section: ";
+ outs() << "xar archive files:\n";
+ PrintXarFilesSummary(XarFilename.c_str(), xar);
+ }
+
+ ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
+ MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
+ if (std::error_code EC = FileOrErr.getError()) {
+ errs() << EC.message() << "\n";
+ return;
+ }
+ std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
+
+ if (!XarMemberName.empty())
+ outs() << "In xar member " << XarMemberName << ": ";
+ else
+ outs() << "For (__LLVM,__bundle) section: ";
+ outs() << "xar table of contents:\n";
+ outs() << Buffer->getBuffer() << "\n";
+
+ // TODO: Go through the xar's files.
+ xar_iter_t xi = xar_iter_new();
+ if(!xi){
+ errs() << "Can't obtain an xar iterator for xar archive "
+ << XarFilename.c_str() << "\n";
+ xar_close(xar);
+ return;
+ }
+ for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
+ const char *key;
+ xar_iter_t xp;
+ const char *member_name, *member_type, *member_size_string;
+ size_t member_size;
+
+ xp = xar_iter_new();
+ if(!xp){
+ errs() << "Can't obtain an xar iterator for xar archive "
+ << XarFilename.c_str() << "\n";
+ xar_close(xar);
+ return;
+ }
+ member_name = NULL;
+ member_type = NULL;
+ member_size_string = NULL;
+ for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
+ const char *val = nullptr;
+ xar_prop_get(xf, key, &val);
+#if 0 // Useful for debugging.
+ outs() << "key: " << key << " value: " << val << "\n";
+#endif
+ if(strcmp(key, "name") == 0)
+ member_name = val;
+ if(strcmp(key, "type") == 0)
+ member_type = val;
+ if(strcmp(key, "data/size") == 0)
+ member_size_string = val;
+ }
+ /*
+ * If we find a file with a name, date/size and type properties
+ * and with the type being "file" see if that is a xar file.
+ */
+ if (member_name != NULL && member_type != NULL &&
+ strcmp(member_type, "file") == 0 &&
+ member_size_string != NULL){
+ // Extract the file into a buffer.
+ char *endptr;
+ member_size = strtoul(member_size_string, &endptr, 10);
+ if (*endptr == '\0' && member_size != 0) {
+ char *buffer = (char *) ::operator new (member_size);
+ if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
+#if 0 // Useful for debugging.
+ outs() << "xar member: " << member_name << " extracted\n";
+#endif
+ // Set the XarMemberName we want to see printed in the header.
+ std::string OldXarMemberName;
+ // If XarMemberName is already set this is nested. So
+ // save the old name and create the nested name.
+ if (!XarMemberName.empty()) {
+ OldXarMemberName = XarMemberName;
+ XarMemberName =
+ (Twine("[") + XarMemberName + "]" + member_name).str();
+ } else {
+ OldXarMemberName = "";
+ XarMemberName = member_name;
+ }
+ // See if this is could be a xar file (nested).
+ if (member_size >= sizeof(struct xar_header)) {
+#if 0 // Useful for debugging.
+ outs() << "could be a xar file: " << member_name << "\n";
+#endif
+ memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
+ if (sys::IsLittleEndianHost)
+ swapStruct(XarHeader);
+ if(XarHeader.magic == XAR_HEADER_MAGIC)
+ DumpBitcodeSection(O, buffer, member_size, verbose,
+ PrintXarHeader, PrintXarFileHeaders,
+ XarMemberName);
+ }
+ XarMemberName = OldXarMemberName;
+ }
+ delete buffer;
+ }
+ }
+ xar_iter_free(xp);
+ }
+ xar_close(xar);
+}
+#endif // defined(HAVE_LIBXAR)
+
static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
if (O->is64Bit())
printObjc2_64bit_MetaData(O, verbose);
@@ -5948,7 +6474,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
return;
}
- // Set up thumb disassembler.
+ // Set up separate thumb disassembler if needed.
std::unique_ptr<const MCRegisterInfo> ThumbMRI;
std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
@@ -6077,13 +6603,26 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
SymbolAddressMap AddrMap;
bool DisSymNameFound = false;
for (const SymbolRef &Symbol : MachOOF->symbols()) {
- SymbolRef::Type ST = Symbol.getType();
+ Expected<SymbolRef::Type> STOrErr = Symbol.getType();
+ if (!STOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(STOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
+ SymbolRef::Type ST = *STOrErr;
if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
ST == SymbolRef::ST_Other) {
uint64_t Address = Symbol.getValue();
- ErrorOr<StringRef> SymNameOrErr = Symbol.getName();
- if (std::error_code EC = SymNameOrErr.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymNameOrErr = Symbol.getName();
+ if (!SymNameOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
StringRef SymName = *SymNameOrErr;
AddrMap[Address] = SymName;
if (!DisSymName.empty() && DisSymName == SymName)
@@ -6121,20 +6660,61 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
ThumbSymbolizerInfo.adrp_addr = 0;
ThumbSymbolizerInfo.adrp_inst = 0;
+ unsigned int Arch = MachOOF->getArch();
+
+ // Skip all symbols if this is a stubs file.
+ if (Bytes.size() == 0)
+ return;
+
// Disassemble symbol by symbol.
for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
- ErrorOr<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
- if (std::error_code EC = SymNameOrErr.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
+ if (!SymNameOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
StringRef SymName = *SymNameOrErr;
- SymbolRef::Type ST = Symbols[SymIdx].getType();
+ Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType();
+ if (!STOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(STOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
+ SymbolRef::Type ST = *STOrErr;
if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
continue;
// Make sure the symbol is defined in this section.
bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
- if (!containsSym)
+ if (!containsSym) {
+ if (!DisSymName.empty() && DisSymName == SymName) {
+ outs() << "-dis-symname: " << DisSymName << " not in the section\n";
+ return;
+ }
+ continue;
+ }
+ // The __mh_execute_header is special and we need to deal with that fact
+ // this symbol is before the start of the (__TEXT,__text) section and at the
+ // address of the start of the __TEXT segment. This is because this symbol
+ // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
+ // start of the section in a standard MH_EXECUTE filetype.
+ if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
+ outs() << "-dis-symname: __mh_execute_header not in any section\n";
+ return;
+ }
+ // When this code is trying to disassemble a symbol at a time and in the
+ // case there is only the __mh_execute_header symbol left as in a stripped
+ // executable, we need to deal with this by ignoring this symbol so the
+ // whole section is disassembled and this symbol is then not displayed.
+ if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
+ SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
+ SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
continue;
// If we are only disassembling one symbol see if this is that symbol.
@@ -6142,17 +6722,32 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
continue;
// Start at the address of the symbol relative to the section's address.
+ uint64_t SectSize = Sections[SectIdx].getSize();
uint64_t Start = Symbols[SymIdx].getValue();
uint64_t SectionAddress = Sections[SectIdx].getAddress();
Start -= SectionAddress;
+ if (Start > SectSize) {
+ outs() << "section data ends, " << SymName
+ << " lies outside valid range\n";
+ return;
+ }
+
// Stop disassembling either at the beginning of the next symbol or at
// the end of the section.
bool containsNextSym = false;
uint64_t NextSym = 0;
uint64_t NextSymIdx = SymIdx + 1;
while (Symbols.size() > NextSymIdx) {
- SymbolRef::Type NextSymType = Symbols[NextSymIdx].getType();
+ Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType();
+ if (!STOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(STOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
+ SymbolRef::Type NextSymType = *STOrErr;
if (NextSymType == SymbolRef::ST_Function) {
containsNextSym =
Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
@@ -6163,15 +6758,17 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
++NextSymIdx;
}
- uint64_t SectSize = Sections[SectIdx].getSize();
- uint64_t End = containsNextSym ? NextSym : SectSize;
+ uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
uint64_t Size;
symbolTableWorked = true;
DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
- bool isThumb =
- (MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb) && ThumbTarget;
+ bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb;
+
+ // We only need the dedicated Thumb target if there's a real choice
+ // (i.e. we're not targeting M-class) and the function is Thumb.
+ bool UseThumbTarget = IsThumb && ThumbTarget;
outs() << SymName << ":\n";
DILineInfo lastLine;
@@ -6189,7 +6786,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
outs() << format("%8" PRIx64 ":", PC);
}
}
- if (!NoShowRawInsn)
+ if (!NoShowRawInsn || Arch == Triple::arm)
outs() << "\t";
// Check the data in code table here to see if this is data not an
@@ -6215,19 +6812,19 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
raw_svector_ostream Annotations(AnnotationsBytes);
bool gotInst;
- if (isThumb)
+ if (UseThumbTarget)
gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
PC, DebugOut, Annotations);
else
gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
DebugOut, Annotations);
if (gotInst) {
- if (!NoShowRawInsn) {
+ if (!NoShowRawInsn || Arch == Triple::arm) {
dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
}
formatted_raw_ostream FormattedOS(outs());
StringRef AnnotationsStr = Annotations.str();
- if (isThumb)
+ if (UseThumbTarget)
ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
else
IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI);
@@ -6249,14 +6846,21 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
outs() << format("\t.byte 0x%02x #bad opcode\n",
*(Bytes.data() + Index) & 0xff);
Size = 1; // skip exactly one illegible byte and move on.
- } else if (Arch == Triple::aarch64) {
+ } else if (Arch == Triple::aarch64 ||
+ (Arch == Triple::arm && !IsThumb)) {
uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
(*(Bytes.data() + Index + 1) & 0xff) << 8 |
(*(Bytes.data() + Index + 2) & 0xff) << 16 |
(*(Bytes.data() + Index + 3) & 0xff) << 24;
outs() << format("\t.long\t0x%08x\n", opcode);
Size = 4;
- } else {
+ } else if (Arch == Triple::arm) {
+ assert(IsThumb && "ARM mode should have been dealt with above");
+ uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
+ (*(Bytes.data() + Index + 1) & 0xff) << 8;
+ outs() << format("\t.short\t0x%04x\n", opcode);
+ Size = 2;
+ } else{
errs() << "llvm-objdump: warning: invalid instruction encoding\n";
if (Size == 0)
Size = 1; // skip illegible bytes
@@ -6285,7 +6889,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
outs() << format("%8" PRIx64 ":", PC);
}
}
- if (!NoShowRawInsn) {
+ if (!NoShowRawInsn || Arch == Triple::arm) {
outs() << "\t";
dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
}
@@ -6387,9 +6991,14 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
const RelocationRef &Reloc, uint64_t Addr,
StringRef &Name, uint64_t &Addend) {
if (Reloc.getSymbol() != Obj->symbol_end()) {
- ErrorOr<StringRef> NameOrErr = Reloc.getSymbol()->getName();
- if (std::error_code EC = NameOrErr.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName();
+ if (!NameOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(NameOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
Name = *NameOrErr;
Addend = Addr;
return;
@@ -6412,12 +7021,25 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
// Go back one so that SymbolAddress <= Addr.
--Sym;
- section_iterator SymSection = *Sym->second.getSection();
+ auto SectOrErr = Sym->second.getSection();
+ if (!SectOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(SectOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
+ section_iterator SymSection = *SectOrErr;
if (RelocSection == *SymSection) {
// There's a valid symbol in the same section before this reference.
- ErrorOr<StringRef> NameOrErr = Sym->second.getName();
- if (std::error_code EC = NameOrErr.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> NameOrErr = Sym->second.getName();
+ if (!NameOrErr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(NameOrErr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
Name = *NameOrErr;
Addend = Addr - Sym->first;
return;
@@ -6750,268 +7372,18 @@ 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 = *SymRef.getSection();
+ auto SectOrErr = SymRef.getSection();
+ if (!SectOrErr) {
+ // TODO: Actually report errors helpfully.
+ consumeError(SectOrErr.takeError());
+ continue;
+ }
+ section_iterator Section = *SectOrErr;
if (Section == Obj->section_end())
continue;
@@ -7026,8 +7398,6 @@ void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
printMachOCompactUnwindSection(Obj, Symbols, Section);
else if (SectName == "__unwind_info")
printMachOUnwindInfoSection(Obj, Symbols, Section);
- else if (SectName == "__eh_frame")
- printMachOEHFrameSection(Obj, Symbols, Section);
}
}
@@ -7145,6 +7515,10 @@ static void PrintMachHeader(uint32_t magic, uint32_t cputype,
break;
}
break;
+ default:
+ outs() << format(" %7d", cputype);
+ outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
+ break;
}
if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
outs() << " LIB64";
@@ -8488,7 +8862,7 @@ static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
uint32_t object_size) {
if (ld.cmd == MachO::LC_CODE_SIGNATURE)
- outs() << " cmd LC_FUNCTION_STARTS\n";
+ outs() << " cmd LC_CODE_SIGNATURE\n";
else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
outs() << " cmd LC_SEGMENT_SPLIT_INFO\n";
else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
index d5ae5de..ed55c91 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -22,20 +22,21 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/FaultMaps.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/Archive.h"
-#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Casting.h"
@@ -58,6 +59,7 @@
#include <cctype>
#include <cstring>
#include <system_error>
+#include <utility>
using namespace llvm;
using namespace object;
@@ -181,6 +183,11 @@ cl::opt<bool>
cl::opt<bool> PrintFaultMaps("fault-map-section",
cl::desc("Display contents of faultmap section"));
+cl::opt<DIDumpType> llvm::DwarfDumpType(
+ "dwarf", cl::init(DIDT_Null), cl::desc("Dump of dwarf debug sections:"),
+ cl::values(clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
+ clEnumValEnd));
+
static StringRef ToolName;
namespace {
@@ -191,7 +198,7 @@ public:
SectionFilterIterator(FilterPredicate P,
llvm::object::section_iterator const &I,
llvm::object::section_iterator const &E)
- : Predicate(P), Iterator(I), End(E) {
+ : Predicate(std::move(P)), Iterator(I), End(E) {
ScanPredicate();
}
const llvm::object::SectionRef &operator*() const { return *Iterator; }
@@ -218,7 +225,7 @@ private:
class SectionFilter {
public:
SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O)
- : Predicate(P), Object(O) {}
+ : Predicate(std::move(P)), Object(O) {}
SectionFilterIterator begin() {
return SectionFilterIterator(Predicate, Object.section_begin(),
Object.section_end());
@@ -257,6 +264,12 @@ void llvm::error(std::error_code EC) {
exit(1);
}
+LLVM_ATTRIBUTE_NORETURN void llvm::error(Twine Message) {
+ errs() << ToolName << ": " << Message << ".\n";
+ errs().flush();
+ exit(1);
+}
+
LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File,
std::error_code EC) {
assert(EC);
@@ -264,6 +277,52 @@ LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File,
exit(1);
}
+LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File,
+ llvm::Error E) {
+ assert(E);
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(std::move(E), OS, "");
+ OS.flush();
+ errs() << ToolName << ": '" << File << "': " << Buf;
+ exit(1);
+}
+
+LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef ArchiveName,
+ StringRef FileName,
+ llvm::Error E,
+ StringRef ArchitectureName) {
+ assert(E);
+ errs() << ToolName << ": ";
+ if (ArchiveName != "")
+ errs() << ArchiveName << "(" << FileName << ")";
+ else
+ errs() << FileName;
+ if (!ArchitectureName.empty())
+ errs() << " (for architecture " << ArchitectureName << ")";
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(std::move(E), OS, "");
+ OS.flush();
+ errs() << " " << Buf;
+ exit(1);
+}
+
+LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef ArchiveName,
+ const object::Archive::Child &C,
+ llvm::Error E,
+ StringRef ArchitectureName) {
+ ErrorOr<StringRef> NameOrErr = C.getName();
+ // TODO: if we have a error getting the name then it would be nice to print
+ // the index of which archive member this is and or its offset in the
+ // archive instead of "???" as the name.
+ if (NameOrErr.getError())
+ llvm::report_error(ArchiveName, "???", std::move(E), ArchitectureName);
+ else
+ llvm::report_error(ArchiveName, NameOrErr.get(), std::move(E),
+ ArchitectureName);
+}
+
static const Target *getTarget(const ObjectFile *Obj = nullptr) {
// Figure out the target triple.
llvm::Triple TheTriple("unknown-unknown-unknown");
@@ -308,12 +367,15 @@ public:
ArrayRef<uint8_t> Bytes, uint64_t Address,
raw_ostream &OS, StringRef Annot,
MCSubtargetInfo const &STI) {
- outs() << format("%8" PRIx64 ":", Address);
+ OS << format("%8" PRIx64 ":", Address);
if (!NoShowRawInsn) {
- outs() << "\t";
- dumpBytes(Bytes, outs());
+ OS << "\t";
+ dumpBytes(Bytes, OS);
}
- IP.printInst(MI, outs(), "", STI);
+ if (MI)
+ IP.printInst(MI, OS, "", STI);
+ else
+ OS << " <unknown>";
}
};
PrettyPrinter PrettyPrinterInst;
@@ -334,6 +396,11 @@ public:
ArrayRef<uint8_t> Bytes, uint64_t Address,
raw_ostream &OS, StringRef Annot,
MCSubtargetInfo const &STI) override {
+ if (!MI) {
+ printLead(Bytes, Address, OS);
+ OS << " <unknown>";
+ return;
+ }
std::string Buffer;
{
raw_string_ostream TempStream(Buffer);
@@ -370,12 +437,48 @@ public:
}
};
HexagonPrettyPrinter HexagonPrettyPrinterInst;
+
+class AMDGCNPrettyPrinter : public PrettyPrinter {
+public:
+ void printInst(MCInstPrinter &IP,
+ const MCInst *MI,
+ ArrayRef<uint8_t> Bytes,
+ uint64_t Address,
+ raw_ostream &OS,
+ StringRef Annot,
+ MCSubtargetInfo const &STI) override {
+ if (!MI) {
+ OS << " <unknown>";
+ return;
+ }
+
+ SmallString<40> InstStr;
+ raw_svector_ostream IS(InstStr);
+
+ IP.printInst(MI, IS, "", STI);
+
+ OS << left_justify(IS.str(), 60) << format("// %012" PRIX64 ": ", Address);
+ typedef support::ulittle32_t U32;
+ for (auto D : makeArrayRef(reinterpret_cast<const U32*>(Bytes.data()),
+ Bytes.size() / sizeof(U32)))
+ // D should be explicitly casted to uint32_t here as it is passed
+ // by format to snprintf as vararg.
+ OS << format("%08" PRIX32 " ", static_cast<uint32_t>(D));
+
+ if (!Annot.empty())
+ OS << "// " << Annot;
+ }
+};
+AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst;
+
PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
switch(Triple.getArch()) {
default:
return PrettyPrinterInst;
case Triple::hexagon:
return HexagonPrettyPrinterInst;
+ case Triple::amdgcn:
+ return AMDGCNPrettyPrinterInst;
}
}
}
@@ -429,18 +532,18 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl());
StringRef Target;
if (symb->getType() == ELF::STT_SECTION) {
- ErrorOr<section_iterator> SymSI = SI->getSection();
- if (std::error_code EC = SymSI.getError())
- return EC;
+ Expected<section_iterator> SymSI = SI->getSection();
+ if (!SymSI)
+ return errorToErrorCode(SymSI.takeError());
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;
} else {
- ErrorOr<StringRef> SymName = symb->getName(StrTab);
+ Expected<StringRef> SymName = symb->getName(StrTab);
if (!SymName)
- return SymName.getError();
+ return errorToErrorCode(SymName.takeError());
Target = *SymName;
}
switch (EF.getHeader()->e_machine) {
@@ -470,6 +573,7 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
res = "Unknown";
}
break;
+ case ELF::EM_LANAI:
case ELF::EM_AARCH64: {
std::string fmtbuf;
raw_string_ostream fmt(fmtbuf);
@@ -485,6 +589,7 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
case ELF::EM_ARM:
case ELF::EM_HEXAGON:
case ELF::EM_MIPS:
+ case ELF::EM_BPF:
res = Target;
break;
case ELF::EM_WEBASSEMBLY:
@@ -529,9 +634,9 @@ static std::error_code getRelocationValueString(const COFFObjectFile *Obj,
const RelocationRef &Rel,
SmallVectorImpl<char> &Result) {
symbol_iterator SymI = Rel.getSymbol();
- ErrorOr<StringRef> SymNameOrErr = SymI->getName();
- if (std::error_code EC = SymNameOrErr.getError())
- return EC;
+ Expected<StringRef> SymNameOrErr = SymI->getName();
+ if (!SymNameOrErr)
+ return errorToErrorCode(SymNameOrErr.takeError());
StringRef SymName = *SymNameOrErr;
Result.append(SymName.begin(), SymName.end());
return std::error_code();
@@ -551,14 +656,24 @@ static void printRelocationTargetName(const MachOObjectFile *O,
for (const SymbolRef &Symbol : O->symbols()) {
std::error_code ec;
- ErrorOr<uint64_t> Addr = Symbol.getAddress();
- if ((ec = Addr.getError()))
- report_fatal_error(ec.message());
+ Expected<uint64_t> Addr = Symbol.getAddress();
+ if (!Addr) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(Addr.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
if (*Addr != Val)
continue;
- ErrorOr<StringRef> Name = Symbol.getName();
- if (std::error_code EC = Name.getError())
- report_fatal_error(EC.message());
+ Expected<StringRef> Name = Symbol.getName();
+ if (!Name) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ logAllUnhandledErrors(Name.takeError(), OS, "");
+ OS.flush();
+ report_fatal_error(Buf);
+ }
fmt << *Name;
return;
}
@@ -589,8 +704,8 @@ static void printRelocationTargetName(const MachOObjectFile *O,
if (isExtern) {
symbol_iterator SI = O->symbol_begin();
advance(SI, Val);
- ErrorOr<StringRef> SOrErr = SI->getName();
- error(SOrErr.getError());
+ Expected<StringRef> SOrErr = SI->getName();
+ error(errorToErrorCode(SOrErr.takeError()));
S = *SOrErr;
} else {
section_iterator SI = O->section_begin();
@@ -828,12 +943,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
const Target *TheTarget = getTarget(Obj);
// Package up features to be passed to target/subtarget
- std::string FeaturesStr;
+ SubtargetFeatures Features = Obj->getFeatures();
if (MAttrs.size()) {
- SubtargetFeatures Features;
for (unsigned i = 0; i != MAttrs.size(); ++i)
Features.AddFeature(MAttrs[i]);
- FeaturesStr = Features.getString();
}
std::unique_ptr<const MCRegisterInfo> MRI(
@@ -847,7 +960,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (!AsmInfo)
report_fatal_error("error: no assembly info for target " + TripleName);
std::unique_ptr<const MCSubtargetInfo> STI(
- TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
+ TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
if (!STI)
report_fatal_error("error: no subtarget info for target " + TripleName);
std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
@@ -891,17 +1004,17 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
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());
+ Expected<uint64_t> AddressOrErr = Symbol.getAddress();
+ error(errorToErrorCode(AddressOrErr.takeError()));
uint64_t Address = *AddressOrErr;
- ErrorOr<StringRef> Name = Symbol.getName();
- error(Name.getError());
+ Expected<StringRef> Name = Symbol.getName();
+ error(errorToErrorCode(Name.takeError()));
if (Name->empty())
continue;
- ErrorOr<section_iterator> SectionOrErr = Symbol.getSection();
- error(SectionOrErr.getError());
+ Expected<section_iterator> SectionOrErr = Symbol.getSection();
+ error(errorToErrorCode(SectionOrErr.takeError()));
section_iterator SecI = *SectionOrErr;
if (SecI == Obj->section_end())
continue;
@@ -1031,6 +1144,18 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (Start >= End)
continue;
+ if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) {
+ // make size 4 bytes folded
+ End = Start + ((End - Start) & ~0x3ull);
+ Start += 256; // add sizeof(amd_kernel_code_t)
+ // cut trailing zeroes - up to 256 bytes (align)
+ const uint64_t EndAlign = 256;
+ const auto Limit = End - (std::min)(EndAlign, End - Start);
+ while (End > Limit &&
+ *reinterpret_cast<const support::ulittle32_t*>(&Bytes[End - 4]) == 0)
+ End -= 4;
+ }
+
outs() << '\n' << Symbols[si].second << ":\n";
#ifndef NDEBUG
@@ -1081,72 +1206,69 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (Index >= End)
break;
- if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
- SectionAddr + Index, DebugOut,
- CommentStream)) {
- PIP.printInst(*IP, &Inst,
- Bytes.slice(Index, Size),
- 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)) {
- // 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;
- }
+ bool Disassembled = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
+ SectionAddr + Index, DebugOut,
+ CommentStream);
+ if (Size == 0)
+ Size = 1;
+ PIP.printInst(*IP, Disassembled ? &Inst : nullptr,
+ Bytes.slice(Index, Size),
+ 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)) {
+ // 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() << '>';
- }
+ // 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() << "+0x" << utohexstr(Disp);
+ outs() << '>';
}
}
}
- outs() << "\n";
- } else {
- errs() << ToolName << ": warning: invalid instruction encoding\n";
- if (Size == 0)
- Size = 1; // skip illegible bytes
}
+ outs() << "\n";
// Print relocation for instruction.
while (rel_cur != rel_end) {
@@ -1270,7 +1392,8 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) {
}
}
-void llvm::PrintSymbolTable(const ObjectFile *o) {
+void llvm::PrintSymbolTable(const ObjectFile *o, StringRef ArchiveName,
+ StringRef ArchitectureName) {
outs() << "SYMBOL TABLE:\n";
if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
@@ -1278,20 +1401,26 @@ void llvm::PrintSymbolTable(const ObjectFile *o) {
return;
}
for (const SymbolRef &Symbol : o->symbols()) {
- ErrorOr<uint64_t> AddressOrError = Symbol.getAddress();
- error(AddressOrError.getError());
+ Expected<uint64_t> AddressOrError = Symbol.getAddress();
+ if (!AddressOrError)
+ report_error(ArchiveName, o->getFileName(), AddressOrError.takeError());
uint64_t Address = *AddressOrError;
- SymbolRef::Type Type = Symbol.getType();
+ Expected<SymbolRef::Type> TypeOrError = Symbol.getType();
+ if (!TypeOrError)
+ report_error(ArchiveName, o->getFileName(), TypeOrError.takeError());
+ SymbolRef::Type Type = *TypeOrError;
uint32_t Flags = Symbol.getFlags();
- ErrorOr<section_iterator> SectionOrErr = Symbol.getSection();
- error(SectionOrErr.getError());
+ Expected<section_iterator> SectionOrErr = Symbol.getSection();
+ error(errorToErrorCode(SectionOrErr.takeError()));
section_iterator Section = *SectionOrErr;
StringRef Name;
if (Type == SymbolRef::ST_Debug && Section != o->section_end()) {
Section->getName(Name);
} else {
- ErrorOr<StringRef> NameOrErr = Symbol.getName();
- error(NameOrErr.getError());
+ Expected<StringRef> NameOrErr = Symbol.getName();
+ if (!NameOrErr)
+ report_error(ArchiveName, o->getFileName(), NameOrErr.takeError(),
+ ArchitectureName);
Name = *NameOrErr;
}
@@ -1523,12 +1652,16 @@ static void printFirstPrivateFileHeader(const ObjectFile *o) {
report_fatal_error("Invalid/Unsupported object file format");
}
-static void DumpObject(const ObjectFile *o) {
+static void DumpObject(const ObjectFile *o, const Archive *a = nullptr) {
+ StringRef ArchiveName = a != nullptr ? a->getFileName() : "";
// Avoid other output when using a raw option.
if (!RawClangAST) {
outs() << '\n';
- outs() << o->getFileName()
- << ":\tfile format " << o->getFileFormatName() << "\n\n";
+ if (a)
+ outs() << a->getFileName() << "(" << o->getFileName() << ")";
+ else
+ outs() << o->getFileName();
+ outs() << ":\tfile format " << o->getFileFormatName() << "\n\n";
}
if (Disassemble)
@@ -1540,7 +1673,7 @@ static void DumpObject(const ObjectFile *o) {
if (SectionContents)
PrintSectionContents(o);
if (SymbolTable)
- PrintSymbolTable(o);
+ PrintSymbolTable(o, ArchiveName);
if (UnwindInfo)
PrintUnwindInfo(o);
if (PrivateHeaders)
@@ -1561,23 +1694,30 @@ static void DumpObject(const ObjectFile *o) {
printRawClangAST(o);
if (PrintFaultMaps)
printFaultMaps(o);
+ if (DwarfDumpType != DIDT_Null) {
+ std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*o));
+ // Dump the complete DWARF structure.
+ DICtx->dump(outs(), DwarfDumpType, true /* DumpEH */);
+ }
}
/// @brief Dump each object file in \a a;
static void DumpArchive(const Archive *a) {
- 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);
+ Error Err;
+ for (auto &C : a->children(Err)) {
+ Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
+ if (!ChildOrErr) {
+ if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
+ report_error(a->getFileName(), C, std::move(E));
+ continue;
+ }
if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
- DumpObject(o);
+ DumpObject(o, a);
else
report_error(a->getFileName(), object_error::invalid_file_type);
}
+ if (Err)
+ report_error(a->getFileName(), std::move(Err));
}
/// @brief Open file and figure out how to dump it.
@@ -1592,9 +1732,9 @@ static void DumpInput(StringRef file) {
}
// Attempt to open the binary.
- ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
- if (std::error_code EC = BinaryOrErr.getError())
- report_error(file, EC);
+ Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
+ if (!BinaryOrErr)
+ report_error(file, BinaryOrErr.takeError());
Binary &Binary = *BinaryOrErr.get().getBinary();
if (Archive *a = dyn_cast<Archive>(&Binary))
@@ -1607,7 +1747,7 @@ static void DumpInput(StringRef file) {
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal();
+ sys::PrintStackTraceOnErrorSignal(argv[0]);
PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
@@ -1654,7 +1794,8 @@ int main(int argc, char **argv) {
&& !(DylibId && MachOOpt)
&& !(ObjcMetaData && MachOOpt)
&& !(FilterSections.size() != 0 && MachOOpt)
- && !PrintFaultMaps) {
+ && !PrintFaultMaps
+ && DwarfDumpType == DIDT_Null) {
cl::PrintHelpMessage();
return 2;
}
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
index 60cabbc..5b10ee8 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -9,16 +9,20 @@
#ifndef LLVM_TOOLS_LLVM_OBJDUMP_LLVM_OBJDUMP_H
#define LLVM_TOOLS_LLVM_OBJDUMP_LLVM_OBJDUMP_H
-#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Object/Archive.h"
namespace llvm {
+class StringRef;
+
namespace object {
class COFFObjectFile;
class MachOObjectFile;
class ObjectFile;
+ class Archive;
class RelocationRef;
}
@@ -55,6 +59,7 @@ extern cl::opt<bool> SectionContents;
extern cl::opt<bool> SymbolTable;
extern cl::opt<bool> UnwindInfo;
extern cl::opt<bool> PrintImmHex;
+extern cl::opt<DIDumpType> DwarfDumpType;
// Various helper functions.
void error(std::error_code ec);
@@ -81,8 +86,21 @@ void printRawClangAST(const object::ObjectFile *o);
void PrintRelocations(const object::ObjectFile *o);
void PrintSectionHeaders(const object::ObjectFile *o);
void PrintSectionContents(const object::ObjectFile *o);
-void PrintSymbolTable(const object::ObjectFile *o);
+void PrintSymbolTable(const object::ObjectFile *o, StringRef ArchiveName,
+ StringRef ArchitectureName = StringRef());
+LLVM_ATTRIBUTE_NORETURN void error(Twine Message);
LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, std::error_code EC);
+LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, llvm::Error E);
+LLVM_ATTRIBUTE_NORETURN void report_error(StringRef FileName,
+ StringRef ArchiveName,
+ llvm::Error E,
+ StringRef ArchitectureName
+ = StringRef());
+LLVM_ATTRIBUTE_NORETURN void report_error(StringRef ArchiveName,
+ const object::Archive::Child &C,
+ llvm::Error E,
+ StringRef ArchitectureName
+ = StringRef());
} // end namespace llvm
OpenPOWER on IntegriCloud