summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/llvm-objdump/MachODump.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
committerpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
commitb773203fb58f3ef282fb69c832d8710cab5bc82d (patch)
treee75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/llvm-objdump/MachODump.cpp
parenttweak errno in previous (diff)
downloadwireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz
wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/llvm-objdump/MachODump.cpp')
-rw-r--r--gnu/llvm/tools/llvm-objdump/MachODump.cpp407
1 files changed, 220 insertions, 187 deletions
diff --git a/gnu/llvm/tools/llvm-objdump/MachODump.cpp b/gnu/llvm/tools/llvm-objdump/MachODump.cpp
index 9908c2f2d01..bdf80c73b99 100644
--- a/gnu/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/gnu/llvm/tools/llvm-objdump/MachODump.cpp
@@ -76,11 +76,6 @@ cl::opt<bool> llvm::UniversalHeaders("universal-headers",
"(requires -macho)"));
cl::opt<bool>
- llvm::ArchiveHeaders("archive-headers",
- cl::desc("Print archive headers for Mach-O archives "
- "(requires -macho)"));
-
-cl::opt<bool>
ArchiveMemberOffsets("archive-member-offsets",
cl::desc("Print the offset to each archive member for "
"Mach-O archives (requires -macho and "
@@ -1284,14 +1279,35 @@ static void DumpLiteralPointerSection(MachOObjectFile *O,
}
}
-static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
+static void DumpInitTermPointerSection(MachOObjectFile *O,
+ const SectionRef &Section,
+ const char *sect,
uint32_t sect_size, uint64_t sect_addr,
SymbolAddressMap *AddrMap,
bool verbose) {
uint32_t stride;
stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
+
+ // Collect the external relocation symbols for the pointers.
+ std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
+ for (const RelocationRef &Reloc : Section.relocations()) {
+ DataRefImpl Rel;
+ MachO::any_relocation_info RE;
+ bool isExtern = false;
+ Rel = Reloc.getRawDataRefImpl();
+ RE = O->getRelocation(Rel);
+ isExtern = O->getPlainRelocationExternal(RE);
+ if (isExtern) {
+ uint64_t RelocOffset = Reloc.getOffset();
+ symbol_iterator RelocSym = Reloc.getSymbol();
+ Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
+ }
+ }
+ array_pod_sort(Relocs.begin(), Relocs.end());
+
for (uint32_t i = 0; i < sect_size; i += stride) {
const char *SymbolName = nullptr;
+ uint64_t p;
if (O->is64Bit()) {
outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
uint64_t pointer_value;
@@ -1299,8 +1315,7 @@ static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
if (O->isLittleEndian() != sys::IsLittleEndianHost)
sys::swapByteOrder(pointer_value);
outs() << format("0x%016" PRIx64, pointer_value);
- if (verbose)
- SymbolName = GuessSymbolName(pointer_value, AddrMap);
+ p = pointer_value;
} else {
outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
uint32_t pointer_value;
@@ -1308,11 +1323,25 @@ static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
if (O->isLittleEndian() != sys::IsLittleEndianHost)
sys::swapByteOrder(pointer_value);
outs() << format("0x%08" PRIx32, pointer_value);
- if (verbose)
- SymbolName = GuessSymbolName(pointer_value, AddrMap);
+ p = pointer_value;
+ }
+ if (verbose) {
+ // First look for an external relocation entry for this pointer.
+ auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
+ return P.first == i;
+ });
+ if (Reloc != Relocs.end()) {
+ symbol_iterator RelocSym = Reloc->second;
+ Expected<StringRef> SymName = RelocSym->getName();
+ if (!SymName)
+ report_error(O->getFileName(), SymName.takeError());
+ outs() << " " << *SymName;
+ } else {
+ SymbolName = GuessSymbolName(p, AddrMap);
+ if (SymbolName)
+ outs() << " " << SymbolName;
+ }
}
- if (SymbolName)
- outs() << " " << SymbolName;
outs() << "\n";
}
}
@@ -1463,8 +1492,8 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
break;
case MachO::S_MOD_INIT_FUNC_POINTERS:
case MachO::S_MOD_TERM_FUNC_POINTERS:
- DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap,
- verbose);
+ DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr,
+ &AddrMap, verbose);
break;
default:
outs() << "Unknown section type ("
@@ -2149,19 +2178,22 @@ void llvm::ParseInputMachO(StringRef Filename) {
// The block of info used by the Symbolizer call backs.
struct DisassembleInfo {
+ DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap,
+ std::vector<SectionRef> *Sections, bool verbose)
+ : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}
bool verbose;
MachOObjectFile *O;
SectionRef S;
SymbolAddressMap *AddrMap;
std::vector<SectionRef> *Sections;
- const char *class_name;
- const char *selector_name;
- char *method;
- char *demangled_name;
- uint64_t adrp_addr;
- uint32_t adrp_inst;
+ const char *class_name = nullptr;
+ const char *selector_name = nullptr;
+ std::unique_ptr<char[]> method = nullptr;
+ char *demangled_name = nullptr;
+ uint64_t adrp_addr = 0;
+ uint32_t adrp_inst = 0;
std::unique_ptr<SymbolAddressMap> bindtable;
- uint32_t depth;
+ uint32_t depth = 0;
};
// SymbolizerGetOpInfo() is the operand information call back function.
@@ -2756,32 +2788,33 @@ static void method_reference(struct DisassembleInfo *info,
if (*ReferenceName != nullptr) {
if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
if (info->selector_name != nullptr) {
- if (info->method != nullptr)
- free(info->method);
if (info->class_name != nullptr) {
- info->method = (char *)malloc(5 + strlen(info->class_name) +
- strlen(info->selector_name));
- if (info->method != nullptr) {
- strcpy(info->method, "+[");
- strcat(info->method, info->class_name);
- strcat(info->method, " ");
- strcat(info->method, info->selector_name);
- strcat(info->method, "]");
- *ReferenceName = info->method;
+ info->method = llvm::make_unique<char[]>(
+ 5 + strlen(info->class_name) + strlen(info->selector_name));
+ char *method = info->method.get();
+ if (method != nullptr) {
+ strcpy(method, "+[");
+ strcat(method, info->class_name);
+ strcat(method, " ");
+ strcat(method, info->selector_name);
+ strcat(method, "]");
+ *ReferenceName = method;
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
}
} else {
- info->method = (char *)malloc(9 + strlen(info->selector_name));
- if (info->method != nullptr) {
+ info->method =
+ llvm::make_unique<char[]>(9 + strlen(info->selector_name));
+ char *method = info->method.get();
+ if (method != nullptr) {
if (Arch == Triple::x86_64)
- strcpy(info->method, "-[%rdi ");
+ strcpy(method, "-[%rdi ");
else if (Arch == Triple::aarch64)
- strcpy(info->method, "-[x0 ");
+ strcpy(method, "-[x0 ");
else
- strcpy(info->method, "-[r? ");
- strcat(info->method, info->selector_name);
- strcat(info->method, "]");
- *ReferenceName = info->method;
+ strcpy(method, "-[r? ");
+ strcat(method, info->selector_name);
+ strcat(method, "]");
+ *ReferenceName = method;
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
}
}
@@ -2789,19 +2822,19 @@ static void method_reference(struct DisassembleInfo *info,
}
} else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
if (info->selector_name != nullptr) {
- if (info->method != nullptr)
- free(info->method);
- info->method = (char *)malloc(17 + strlen(info->selector_name));
- if (info->method != nullptr) {
+ info->method =
+ llvm::make_unique<char[]>(17 + strlen(info->selector_name));
+ char *method = info->method.get();
+ if (method != nullptr) {
if (Arch == Triple::x86_64)
- strcpy(info->method, "-[[%rdi super] ");
+ strcpy(method, "-[[%rdi super] ");
else if (Arch == Triple::aarch64)
- strcpy(info->method, "-[[x0 super] ");
+ strcpy(method, "-[[x0 super] ");
else
- strcpy(info->method, "-[[r? super] ");
- strcat(info->method, info->selector_name);
- strcat(info->method, "]");
- *ReferenceName = info->method;
+ strcpy(method, "-[[r? super] ");
+ strcat(method, info->selector_name);
+ strcat(method, "]");
+ *ReferenceName = method;
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
}
info->class_name = nullptr;
@@ -3196,6 +3229,8 @@ struct imageInfo_t {
/* masks for objc_image_info.flags */
#define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
#define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
+#define OBJC_IMAGE_IS_SIMULATED (1 << 5)
+#define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)
struct message_ref64 {
uint64_t imp; /* IMP (64-bit pointer) */
@@ -5557,12 +5592,24 @@ static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
outs() << " OBJC_IMAGE_IS_REPLACEMENT";
if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
outs() << " OBJC_IMAGE_SUPPORTS_GC";
+ if (o.flags & OBJC_IMAGE_IS_SIMULATED)
+ outs() << " OBJC_IMAGE_IS_SIMULATED";
+ if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES)
+ outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
swift_version = (o.flags >> 8) & 0xff;
if (swift_version != 0) {
if (swift_version == 1)
outs() << " Swift 1.0";
else if (swift_version == 2)
outs() << " Swift 1.1";
+ else if(swift_version == 3)
+ outs() << " Swift 2.0";
+ else if(swift_version == 4)
+ outs() << " Swift 3.0";
+ else if(swift_version == 5)
+ outs() << " Swift 4.0";
+ else if(swift_version == 6)
+ outs() << " Swift 4.1";
else
outs() << " unknown future Swift version (" << swift_version << ")";
}
@@ -5606,6 +5653,14 @@ static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
outs() << " Swift 1.0";
else if (swift_version == 2)
outs() << " Swift 1.1";
+ else if(swift_version == 3)
+ outs() << " Swift 2.0";
+ else if(swift_version == 4)
+ outs() << " Swift 3.0";
+ else if(swift_version == 5)
+ outs() << " Swift 4.0";
+ else if(swift_version == 6)
+ outs() << " Swift 4.1";
else
outs() << " unknown future Swift version (" << swift_version << ")";
}
@@ -5659,21 +5714,8 @@ static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
Sections.push_back(Section);
}
- struct DisassembleInfo info;
- // Set up the block of info used by the Symbolizer call backs.
- info.verbose = verbose;
- info.O = O;
- info.AddrMap = &AddrMap;
- info.Sections = &Sections;
- info.class_name = nullptr;
- info.selector_name = nullptr;
- info.method = nullptr;
- info.demangled_name = nullptr;
- info.bindtable = nullptr;
- info.adrp_addr = 0;
- info.adrp_inst = 0;
-
- info.depth = 0;
+ struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
+
SectionRef CL = get_section(O, "__OBJC2", "__class_list");
if (CL == SectionRef())
CL = get_section(O, "__DATA", "__objc_classlist");
@@ -5757,19 +5799,7 @@ static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
Sections.push_back(Section);
}
- struct DisassembleInfo info;
- // Set up the block of info used by the Symbolizer call backs.
- info.verbose = verbose;
- info.O = O;
- info.AddrMap = &AddrMap;
- info.Sections = &Sections;
- info.class_name = nullptr;
- info.selector_name = nullptr;
- info.method = nullptr;
- info.demangled_name = nullptr;
- info.bindtable = nullptr;
- info.adrp_addr = 0;
- info.adrp_inst = 0;
+ struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
SectionRef CL = get_section(O, "__OBJC2", "__class_list");
if (CL == SectionRef())
@@ -5867,19 +5897,7 @@ static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
Sections.push_back(Section);
}
- struct DisassembleInfo info;
- // Set up the block of info used by the Symbolizer call backs.
- info.verbose = verbose;
- info.O = O;
- info.AddrMap = &AddrMap;
- info.Sections = &Sections;
- info.class_name = nullptr;
- info.selector_name = nullptr;
- info.method = nullptr;
- info.demangled_name = nullptr;
- info.bindtable = nullptr;
- info.adrp_addr = 0;
- info.adrp_inst = 0;
+ struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
p = S.getAddress() + i;
@@ -6040,19 +6058,7 @@ static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
Sections.push_back(Section);
}
- struct DisassembleInfo info;
- // Set up the block of info used by the Symbolizer call backs.
- info.verbose = true;
- info.O = O;
- info.AddrMap = &AddrMap;
- info.Sections = &Sections;
- info.class_name = nullptr;
- info.selector_name = nullptr;
- info.method = nullptr;
- info.demangled_name = nullptr;
- info.bindtable = nullptr;
- info.adrp_addr = 0;
- info.adrp_inst = 0;
+ struct DisassembleInfo info(O, &AddrMap, &Sections, true);
const char *p;
struct objc_protocol_t protocol;
@@ -6748,7 +6754,7 @@ static const char *SymbolizerSymbolLookUp(void *DisInfo,
return SymbolName;
}
-/// \brief Emits the comments that are stored in the CommentStream.
+/// Emits the comments that are stored in the CommentStream.
/// Each comment in the CommentStream must end with a newline.
static void emitComments(raw_svector_ostream &CommentStream,
SmallString<128> &CommentsToEmit,
@@ -6817,7 +6823,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
std::unique_ptr<MCDisassembler> DisAsm(
TheTarget->createMCDisassembler(*STI, Ctx));
std::unique_ptr<MCSymbolizer> Symbolizer;
- struct DisassembleInfo SymbolizerInfo;
+ struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
std::unique_ptr<MCRelocationInfo> RelInfo(
TheTarget->createMCRelocationInfo(TripleName, Ctx));
if (RelInfo) {
@@ -6855,7 +6861,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
std::unique_ptr<MCInstPrinter> ThumbIP;
std::unique_ptr<MCContext> ThumbCtx;
std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
- struct DisassembleInfo ThumbSymbolizerInfo;
+ struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
if (ThumbTarget) {
ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
@@ -6904,7 +6910,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
BaseSegmentAddress);
// Sort the symbols by address, just in case they didn't come in that way.
- std::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
+ llvm::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
// Build a data in code table that is sorted on by the address of each entry.
uint64_t BaseAddress = 0;
@@ -6940,10 +6946,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';
return;
}
- DbgObj =
- ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef())
- .get()
- .release();
+ Expected<std::unique_ptr<MachOObjectFile>> DbgObjCheck =
+ ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef());
+
+ if (DbgObjCheck.takeError())
+ report_error(MachOOF->getFileName(), DbgObjCheck.takeError());
+ DbgObj = DbgObjCheck.get().release();
}
// Setup the DIContext
@@ -7003,26 +7011,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
SymbolizerInfo.S = Sections[SectIdx];
SymbolizerInfo.AddrMap = &AddrMap;
SymbolizerInfo.Sections = &Sections;
- SymbolizerInfo.class_name = nullptr;
- SymbolizerInfo.selector_name = nullptr;
- SymbolizerInfo.method = nullptr;
- SymbolizerInfo.demangled_name = nullptr;
- SymbolizerInfo.bindtable = nullptr;
- SymbolizerInfo.adrp_addr = 0;
- SymbolizerInfo.adrp_inst = 0;
// Same for the ThumbSymbolizer
ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
ThumbSymbolizerInfo.O = MachOOF;
ThumbSymbolizerInfo.S = Sections[SectIdx];
ThumbSymbolizerInfo.AddrMap = &AddrMap;
ThumbSymbolizerInfo.Sections = &Sections;
- ThumbSymbolizerInfo.class_name = nullptr;
- ThumbSymbolizerInfo.selector_name = nullptr;
- ThumbSymbolizerInfo.method = nullptr;
- ThumbSymbolizerInfo.demangled_name = nullptr;
- ThumbSymbolizerInfo.bindtable = nullptr;
- ThumbSymbolizerInfo.adrp_addr = 0;
- ThumbSymbolizerInfo.adrp_inst = 0;
unsigned int Arch = MachOOF->getArch();
@@ -7293,12 +7287,8 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
TripleName = "";
ThumbTripleName = "";
- if (SymbolizerInfo.method != nullptr)
- free(SymbolizerInfo.method);
if (SymbolizerInfo.demangled_name != nullptr)
free(SymbolizerInfo.demangled_name);
- if (ThumbSymbolizerInfo.method != nullptr)
- free(ThumbSymbolizerInfo.method);
if (ThumbSymbolizerInfo.demangled_name != nullptr)
free(ThumbSymbolizerInfo.demangled_name);
}
@@ -7310,12 +7300,25 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
namespace {
-template <typename T> static uint64_t readNext(const char *&Buf) {
+template <typename T>
+static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
using llvm::support::little;
using llvm::support::unaligned;
- uint64_t Val = support::endian::read<T, little, unaligned>(Buf);
- Buf += sizeof(T);
+ if (Offset + sizeof(T) > Contents.size()) {
+ outs() << "warning: attempt to read past end of buffer\n";
+ return T();
+ }
+
+ uint64_t Val =
+ support::endian::read<T, little, unaligned>(Contents.data() + Offset);
+ return Val;
+}
+
+template <typename T>
+static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
+ T Val = read<T>(Contents, Offset);
+ Offset += sizeof(T);
return Val;
}
@@ -7335,18 +7338,18 @@ struct CompactUnwindEntry {
CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
: OffsetInSection(Offset) {
if (Is64)
- read<uint64_t>(Contents.data() + Offset);
+ read<uint64_t>(Contents, Offset);
else
- read<uint32_t>(Contents.data() + Offset);
+ read<uint32_t>(Contents, Offset);
}
private:
- template <typename UIntPtr> void read(const char *Buf) {
- FunctionAddr = readNext<UIntPtr>(Buf);
- Length = readNext<uint32_t>(Buf);
- CompactEncoding = readNext<uint32_t>(Buf);
- PersonalityAddr = readNext<UIntPtr>(Buf);
- LSDAAddr = readNext<UIntPtr>(Buf);
+ template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
+ FunctionAddr = readNext<UIntPtr>(Contents, Offset);
+ Length = readNext<uint32_t>(Contents, Offset);
+ CompactEncoding = readNext<uint32_t>(Contents, Offset);
+ PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
+ LSDAAddr = readNext<UIntPtr>(Contents, Offset);
}
};
}
@@ -7448,7 +7451,7 @@ printMachOCompactUnwindSection(const MachOObjectFile *Obj,
// First populate the initial raw offsets, encodings and so on from the entry.
for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
- CompactUnwindEntry Entry(Contents.data(), Offset, Is64);
+ CompactUnwindEntry Entry(Contents, Offset, Is64);
CompactUnwinds.push_back(Entry);
}
@@ -7515,19 +7518,19 @@ printMachOCompactUnwindSection(const MachOObjectFile *Obj,
// __unwind_info section dumping
//===----------------------------------------------------------------------===//
-static void printRegularSecondLevelUnwindPage(const char *PageStart) {
- const char *Pos = PageStart;
- uint32_t Kind = readNext<uint32_t>(Pos);
+static void printRegularSecondLevelUnwindPage(StringRef PageData) {
+ ptrdiff_t Pos = 0;
+ uint32_t Kind = readNext<uint32_t>(PageData, Pos);
(void)Kind;
assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
- uint16_t EntriesStart = readNext<uint16_t>(Pos);
- uint16_t NumEntries = readNext<uint16_t>(Pos);
+ uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
+ uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
- Pos = PageStart + EntriesStart;
+ Pos = EntriesStart;
for (unsigned i = 0; i < NumEntries; ++i) {
- uint32_t FunctionOffset = readNext<uint32_t>(Pos);
- uint32_t Encoding = readNext<uint32_t>(Pos);
+ uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
+ uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
outs() << " [" << i << "]: "
<< "function offset=" << format("0x%08" PRIx32, FunctionOffset)
@@ -7537,24 +7540,23 @@ static void printRegularSecondLevelUnwindPage(const char *PageStart) {
}
static void printCompressedSecondLevelUnwindPage(
- const char *PageStart, uint32_t FunctionBase,
+ StringRef PageData, uint32_t FunctionBase,
const SmallVectorImpl<uint32_t> &CommonEncodings) {
- const char *Pos = PageStart;
- uint32_t Kind = readNext<uint32_t>(Pos);
+ ptrdiff_t Pos = 0;
+ uint32_t Kind = readNext<uint32_t>(PageData, Pos);
(void)Kind;
assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
- uint16_t EntriesStart = readNext<uint16_t>(Pos);
- uint16_t NumEntries = readNext<uint16_t>(Pos);
+ uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
+ uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
- uint16_t EncodingsStart = readNext<uint16_t>(Pos);
- readNext<uint16_t>(Pos);
- const auto *PageEncodings = reinterpret_cast<const support::ulittle32_t *>(
- PageStart + EncodingsStart);
+ uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos);
+ readNext<uint16_t>(PageData, Pos);
+ StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos);
- Pos = PageStart + EntriesStart;
+ Pos = EntriesStart;
for (unsigned i = 0; i < NumEntries; ++i) {
- uint32_t Entry = readNext<uint32_t>(Pos);
+ uint32_t Entry = readNext<uint32_t>(PageData, Pos);
uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
uint32_t EncodingIdx = Entry >> 24;
@@ -7562,7 +7564,9 @@ static void printCompressedSecondLevelUnwindPage(
if (EncodingIdx < CommonEncodings.size())
Encoding = CommonEncodings[EncodingIdx];
else
- Encoding = PageEncodings[EncodingIdx - CommonEncodings.size()];
+ Encoding = read<uint32_t>(PageEncodings,
+ sizeof(uint32_t) *
+ (EncodingIdx - CommonEncodings.size()));
outs() << " [" << i << "]: "
<< "function offset=" << format("0x%08" PRIx32, FunctionOffset)
@@ -7585,13 +7589,13 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
StringRef Contents;
UnwindInfo.getContents(Contents);
- const char *Pos = Contents.data();
+ ptrdiff_t Pos = 0;
//===----------------------------------
// Section header
//===----------------------------------
- uint32_t Version = readNext<uint32_t>(Pos);
+ uint32_t Version = readNext<uint32_t>(Contents, Pos);
outs() << " Version: "
<< format("0x%" PRIx32, Version) << '\n';
if (Version != 1) {
@@ -7599,24 +7603,24 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
return;
}
- uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos);
+ uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
outs() << " Common encodings array section offset: "
<< format("0x%" PRIx32, CommonEncodingsStart) << '\n';
- uint32_t NumCommonEncodings = readNext<uint32_t>(Pos);
+ uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
outs() << " Number of common encodings in array: "
<< format("0x%" PRIx32, NumCommonEncodings) << '\n';
- uint32_t PersonalitiesStart = readNext<uint32_t>(Pos);
+ uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
outs() << " Personality function array section offset: "
<< format("0x%" PRIx32, PersonalitiesStart) << '\n';
- uint32_t NumPersonalities = readNext<uint32_t>(Pos);
+ uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
outs() << " Number of personality functions in array: "
<< format("0x%" PRIx32, NumPersonalities) << '\n';
- uint32_t IndicesStart = readNext<uint32_t>(Pos);
+ uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
outs() << " Index array section offset: "
<< format("0x%" PRIx32, IndicesStart) << '\n';
- uint32_t NumIndices = readNext<uint32_t>(Pos);
+ uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
outs() << " Number of indices in array: "
<< format("0x%" PRIx32, NumIndices) << '\n';
@@ -7631,9 +7635,9 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
SmallVector<uint32_t, 64> CommonEncodings;
outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n";
- Pos = Contents.data() + CommonEncodingsStart;
+ Pos = CommonEncodingsStart;
for (unsigned i = 0; i < NumCommonEncodings; ++i) {
- uint32_t Encoding = readNext<uint32_t>(Pos);
+ uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
CommonEncodings.push_back(Encoding);
outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
@@ -7648,9 +7652,9 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
// roughly). Particularly since they only get 2 bits in the compact encoding.
outs() << " Personality functions: (count = " << NumPersonalities << ")\n";
- Pos = Contents.data() + PersonalitiesStart;
+ Pos = PersonalitiesStart;
for (unsigned i = 0; i < NumPersonalities; ++i) {
- uint32_t PersonalityFn = readNext<uint32_t>(Pos);
+ uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
outs() << " personality[" << i + 1
<< "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
}
@@ -7671,13 +7675,13 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
SmallVector<IndexEntry, 4> IndexEntries;
outs() << " Top level indices: (count = " << NumIndices << ")\n";
- Pos = Contents.data() + IndicesStart;
+ Pos = IndicesStart;
for (unsigned i = 0; i < NumIndices; ++i) {
IndexEntry Entry;
- Entry.FunctionOffset = readNext<uint32_t>(Pos);
- Entry.SecondLevelPageStart = readNext<uint32_t>(Pos);
- Entry.LSDAStart = readNext<uint32_t>(Pos);
+ Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
+ Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
+ Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
IndexEntries.push_back(Entry);
outs() << " [" << i << "]: "
@@ -7696,12 +7700,14 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
// the first top-level index's LSDAOffset to the last (sentinel).
outs() << " LSDA descriptors:\n";
- Pos = Contents.data() + IndexEntries[0].LSDAStart;
- int NumLSDAs = (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) /
- (2 * sizeof(uint32_t));
+ Pos = IndexEntries[0].LSDAStart;
+ const uint32_t LSDASize = 2 * sizeof(uint32_t);
+ int NumLSDAs =
+ (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
+
for (int i = 0; i < NumLSDAs; ++i) {
- uint32_t FunctionOffset = readNext<uint32_t>(Pos);
- uint32_t LSDAOffset = readNext<uint32_t>(Pos);
+ uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
+ uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
outs() << " [" << i << "]: "
<< "function offset=" << format("0x%08" PRIx32, FunctionOffset)
<< ", "
@@ -7729,12 +7735,19 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
<< "base function offset="
<< format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
- Pos = Contents.data() + IndexEntries[i].SecondLevelPageStart;
- uint32_t Kind = *reinterpret_cast<const support::ulittle32_t *>(Pos);
+ Pos = IndexEntries[i].SecondLevelPageStart;
+ if (Pos + sizeof(uint32_t) > Contents.size()) {
+ outs() << "warning: invalid offset for second level page: " << Pos << '\n';
+ continue;
+ }
+
+ uint32_t Kind =
+ *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
if (Kind == 2)
- printRegularSecondLevelUnwindPage(Pos);
+ printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
else if (Kind == 3)
- printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset,
+ printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
+ IndexEntries[i].FunctionOffset,
CommonEncodings);
else
outs() << " Skipping 2nd level page with unknown kind " << Kind
@@ -9352,6 +9365,26 @@ static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
outs() << "\t esh.flavor " << es.esh.flavor << " esh.count "
<< es.esh.count << "\n";
}
+ } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
+ outs() << " flavor x86_EXCEPTION_STATE64\n";
+ if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
+ outs() << " count x86_EXCEPTION_STATE64_COUNT\n";
+ else
+ outs() << " count " << count
+ << " (not x86_EXCEPTION_STATE64_COUNT)\n";
+ struct MachO::x86_exception_state64_t es64;
+ left = end - begin;
+ if (left >= sizeof(MachO::x86_exception_state64_t)) {
+ memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
+ begin += sizeof(MachO::x86_exception_state64_t);
+ } else {
+ memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
+ memcpy(&es64, begin, left);
+ begin += left;
+ }
+ if (isLittleEndian != sys::IsLittleEndianHost)
+ swapStruct(es64);
+ Print_x86_exception_state_t(es64);
} else {
outs() << " flavor " << flavor << " (unknown)\n";
outs() << " count " << count << "\n";