1 //===-- MachODump.cpp - Object file dumping utility for llvm --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the MachO-specific dumper for llvm-objdump.
12 //===----------------------------------------------------------------------===//
14 #include "llvm-objdump.h"
15 #include "llvm-c/Disassembler.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/BinaryFormat/MachO.h"
20 #include "llvm/Config/config.h"
21 #include "llvm/DebugInfo/DIContext.h"
22 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
23 #include "llvm/Demangle/Demangle.h"
24 #include "llvm/MC/MCAsmInfo.h"
25 #include "llvm/MC/MCContext.h"
26 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCInstPrinter.h"
29 #include "llvm/MC/MCInstrDesc.h"
30 #include "llvm/MC/MCInstrInfo.h"
31 #include "llvm/MC/MCRegisterInfo.h"
32 #include "llvm/MC/MCSubtargetInfo.h"
33 #include "llvm/Object/MachO.h"
34 #include "llvm/Object/MachOUniversal.h"
35 #include "llvm/Support/Casting.h"
36 #include "llvm/Support/CommandLine.h"
37 #include "llvm/Support/Debug.h"
38 #include "llvm/Support/Endian.h"
39 #include "llvm/Support/Format.h"
40 #include "llvm/Support/FormattedStream.h"
41 #include "llvm/Support/GraphWriter.h"
42 #include "llvm/Support/LEB128.h"
43 #include "llvm/Support/MemoryBuffer.h"
44 #include "llvm/Support/TargetRegistry.h"
45 #include "llvm/Support/TargetSelect.h"
46 #include "llvm/Support/ToolOutputFile.h"
47 #include "llvm/Support/WithColor.h"
48 #include "llvm/Support/raw_ostream.h"
51 #include <system_error>
60 using namespace object;
64 cl::desc("Print line information from debug info if available"));
66 static cl::opt<std::string> DSYMFile("dsym",
67 cl::desc("Use .dSYM file for debug info"));
69 static cl::opt<bool> FullLeadingAddr("full-leading-addr",
70 cl::desc("Print full leading address"));
72 static cl::opt<bool> NoLeadingHeaders("no-leading-headers",
73 cl::desc("Print no leading headers"));
75 cl::opt<bool> llvm::UniversalHeaders("universal-headers",
76 cl::desc("Print Mach-O universal headers "
77 "(requires -macho)"));
80 ArchiveMemberOffsets("archive-member-offsets",
81 cl::desc("Print the offset to each archive member for "
82 "Mach-O archives (requires -macho and "
83 "-archive-headers)"));
86 llvm::IndirectSymbols("indirect-symbols",
87 cl::desc("Print indirect symbol table for Mach-O "
88 "objects (requires -macho)"));
91 llvm::DataInCode("data-in-code",
92 cl::desc("Print the data in code table for Mach-O objects "
93 "(requires -macho)"));
96 llvm::LinkOptHints("link-opt-hints",
97 cl::desc("Print the linker optimization hints for "
98 "Mach-O objects (requires -macho)"));
101 llvm::InfoPlist("info-plist",
102 cl::desc("Print the info plist section as strings for "
103 "Mach-O objects (requires -macho)"));
106 llvm::DylibsUsed("dylibs-used",
107 cl::desc("Print the shared libraries used for linked "
108 "Mach-O files (requires -macho)"));
111 llvm::DylibId("dylib-id",
112 cl::desc("Print the shared library's id for the dylib Mach-O "
113 "file (requires -macho)"));
116 llvm::NonVerbose("non-verbose",
117 cl::desc("Print the info for Mach-O objects in "
118 "non-verbose or numeric form (requires -macho)"));
121 llvm::ObjcMetaData("objc-meta-data",
122 cl::desc("Print the Objective-C runtime meta data for "
123 "Mach-O files (requires -macho)"));
125 cl::opt<std::string> llvm::DisSymName(
127 cl::desc("disassemble just this symbol's instructions (requires -macho)"));
129 static cl::opt<bool> NoSymbolicOperands(
130 "no-symbolic-operands",
131 cl::desc("do not symbolic operands when disassembling (requires -macho)"));
133 static cl::list<std::string>
134 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
137 bool ArchAll = false;
139 static std::string ThumbTripleName;
141 static const Target *GetTarget(const MachOObjectFile *MachOObj,
142 const char **McpuDefault,
143 const Target **ThumbTarget) {
144 // Figure out the target triple.
145 llvm::Triple TT(TripleName);
146 if (TripleName.empty()) {
147 TT = MachOObj->getArchTriple(McpuDefault);
148 TripleName = TT.str();
151 if (TT.getArch() == Triple::arm) {
152 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
153 // that support ARM are also capable of Thumb mode.
154 llvm::Triple ThumbTriple = TT;
155 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
156 ThumbTriple.setArchName(ThumbName);
157 ThumbTripleName = ThumbTriple.str();
160 // Get the target specific parser.
162 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
163 if (TheTarget && ThumbTripleName.empty())
166 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
170 WithColor::error(errs(), "llvm-objdump") << "unable to get target for '";
172 errs() << TripleName;
174 errs() << ThumbTripleName;
175 errs() << "', see --version and --triple.\n";
179 struct SymbolSorter {
180 bool operator()(const SymbolRef &A, const SymbolRef &B) {
181 Expected<SymbolRef::Type> ATypeOrErr = A.getType();
183 report_error(A.getObject()->getFileName(), ATypeOrErr.takeError());
184 SymbolRef::Type AType = *ATypeOrErr;
185 Expected<SymbolRef::Type> BTypeOrErr = B.getType();
187 report_error(B.getObject()->getFileName(), BTypeOrErr.takeError());
188 SymbolRef::Type BType = *BTypeOrErr;
189 uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue();
190 uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue();
191 return AAddr < BAddr;
195 // Types for the storted data in code table that is built before disassembly
196 // and the predicate function to sort them.
197 typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
198 typedef std::vector<DiceTableEntry> DiceTable;
199 typedef DiceTable::iterator dice_table_iterator;
203 struct ScopedXarFile {
205 ScopedXarFile(const char *filename, int32_t flags)
206 : xar(xar_open(filename, flags)) {}
211 ScopedXarFile(const ScopedXarFile &) = delete;
212 ScopedXarFile &operator=(const ScopedXarFile &) = delete;
213 operator xar_t() { return xar; }
216 struct ScopedXarIter {
218 ScopedXarIter() : iter(xar_iter_new()) {}
223 ScopedXarIter(const ScopedXarIter &) = delete;
224 ScopedXarIter &operator=(const ScopedXarIter &) = delete;
225 operator xar_iter_t() { return iter; }
228 #endif // defined(HAVE_LIBXAR)
230 // This is used to search for a data in code table entry for the PC being
231 // disassembled. The j parameter has the PC in j.first. A single data in code
232 // table entry can cover many bytes for each of its Kind's. So if the offset,
233 // aka the i.first value, of the data in code table entry plus its Length
234 // covers the PC being searched for this will return true. If not it will
236 static bool compareDiceTableEntries(const DiceTableEntry &i,
237 const DiceTableEntry &j) {
239 i.second.getLength(Length);
241 return j.first >= i.first && j.first < i.first + Length;
244 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
245 unsigned short Kind) {
246 uint32_t Value, Size = 1;
250 case MachO::DICE_KIND_DATA:
253 dumpBytes(makeArrayRef(bytes, 4), outs());
254 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
255 outs() << "\t.long " << Value;
257 } else if (Length >= 2) {
259 dumpBytes(makeArrayRef(bytes, 2), outs());
260 Value = bytes[1] << 8 | bytes[0];
261 outs() << "\t.short " << Value;
265 dumpBytes(makeArrayRef(bytes, 2), outs());
267 outs() << "\t.byte " << Value;
270 if (Kind == MachO::DICE_KIND_DATA)
271 outs() << "\t@ KIND_DATA\n";
273 outs() << "\t@ data in code kind = " << Kind << "\n";
275 case MachO::DICE_KIND_JUMP_TABLE8:
277 dumpBytes(makeArrayRef(bytes, 1), outs());
279 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
282 case MachO::DICE_KIND_JUMP_TABLE16:
284 dumpBytes(makeArrayRef(bytes, 2), outs());
285 Value = bytes[1] << 8 | bytes[0];
286 outs() << "\t.short " << format("%5u", Value & 0xffff)
287 << "\t@ KIND_JUMP_TABLE16\n";
290 case MachO::DICE_KIND_JUMP_TABLE32:
291 case MachO::DICE_KIND_ABS_JUMP_TABLE32:
293 dumpBytes(makeArrayRef(bytes, 4), outs());
294 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
295 outs() << "\t.long " << Value;
296 if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
297 outs() << "\t@ KIND_JUMP_TABLE32\n";
299 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
306 static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
307 std::vector<SectionRef> &Sections,
308 std::vector<SymbolRef> &Symbols,
309 SmallVectorImpl<uint64_t> &FoundFns,
310 uint64_t &BaseSegmentAddress) {
311 for (const SymbolRef &Symbol : MachOObj->symbols()) {
312 Expected<StringRef> SymName = Symbol.getName();
314 report_error(MachOObj->getFileName(), SymName.takeError());
315 if (!SymName->startswith("ltmp"))
316 Symbols.push_back(Symbol);
319 for (const SectionRef &Section : MachOObj->sections()) {
321 Section.getName(SectName);
322 Sections.push_back(Section);
325 bool BaseSegmentAddressSet = false;
326 for (const auto &Command : MachOObj->load_commands()) {
327 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
328 // We found a function starts segment, parse the addresses for later
330 MachO::linkedit_data_command LLC =
331 MachOObj->getLinkeditDataLoadCommand(Command);
333 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
334 } else if (Command.C.cmd == MachO::LC_SEGMENT) {
335 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
336 StringRef SegName = SLC.segname;
337 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
338 BaseSegmentAddressSet = true;
339 BaseSegmentAddress = SLC.vmaddr;
345 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
346 uint32_t n, uint32_t count,
347 uint32_t stride, uint64_t addr) {
348 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
349 uint32_t nindirectsyms = Dysymtab.nindirectsyms;
350 if (n > nindirectsyms)
351 outs() << " (entries start past the end of the indirect symbol "
352 "table) (reserved1 field greater than the table size)";
353 else if (n + count > nindirectsyms)
354 outs() << " (entries extends past the end of the indirect symbol "
357 uint32_t cputype = O->getHeader().cputype;
358 if (cputype & MachO::CPU_ARCH_ABI64)
359 outs() << "address index";
361 outs() << "address index";
366 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
367 if (cputype & MachO::CPU_ARCH_ABI64)
368 outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
370 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
371 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
372 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
373 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
377 if (indirect_symbol ==
378 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
379 outs() << "LOCAL ABSOLUTE\n";
382 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
383 outs() << "ABSOLUTE\n";
386 outs() << format("%5u ", indirect_symbol);
388 MachO::symtab_command Symtab = O->getSymtabLoadCommand();
389 if (indirect_symbol < Symtab.nsyms) {
390 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
391 SymbolRef Symbol = *Sym;
392 Expected<StringRef> SymName = Symbol.getName();
394 report_error(O->getFileName(), SymName.takeError());
404 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
405 for (const auto &Load : O->load_commands()) {
406 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
407 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
408 for (unsigned J = 0; J < Seg.nsects; ++J) {
409 MachO::section_64 Sec = O->getSection64(Load, J);
410 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
411 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
412 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
413 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
414 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
415 section_type == MachO::S_SYMBOL_STUBS) {
417 if (section_type == MachO::S_SYMBOL_STUBS)
418 stride = Sec.reserved2;
422 outs() << "Can't print indirect symbols for (" << Sec.segname << ","
423 << Sec.sectname << ") "
424 << "(size of stubs in reserved2 field is zero)\n";
427 uint32_t count = Sec.size / stride;
428 outs() << "Indirect symbols for (" << Sec.segname << ","
429 << Sec.sectname << ") " << count << " entries";
430 uint32_t n = Sec.reserved1;
431 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
434 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
435 MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
436 for (unsigned J = 0; J < Seg.nsects; ++J) {
437 MachO::section Sec = O->getSection(Load, J);
438 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
439 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
440 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
441 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
442 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
443 section_type == MachO::S_SYMBOL_STUBS) {
445 if (section_type == MachO::S_SYMBOL_STUBS)
446 stride = Sec.reserved2;
450 outs() << "Can't print indirect symbols for (" << Sec.segname << ","
451 << Sec.sectname << ") "
452 << "(size of stubs in reserved2 field is zero)\n";
455 uint32_t count = Sec.size / stride;
456 outs() << "Indirect symbols for (" << Sec.segname << ","
457 << Sec.sectname << ") " << count << " entries";
458 uint32_t n = Sec.reserved1;
459 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
466 static void PrintRType(const uint64_t cputype, const unsigned r_type) {
467 static char const *generic_r_types[] = {
468 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ",
469 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ",
470 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
472 static char const *x86_64_r_types[] = {
473 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ",
474 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ",
475 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
477 static char const *arm_r_types[] = {
478 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ",
479 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ",
480 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
482 static char const *arm64_r_types[] = {
483 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ",
484 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF",
485 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
489 outs() << format("%-7u", r_type) << " ";
493 case MachO::CPU_TYPE_I386:
494 outs() << generic_r_types[r_type];
496 case MachO::CPU_TYPE_X86_64:
497 outs() << x86_64_r_types[r_type];
499 case MachO::CPU_TYPE_ARM:
500 outs() << arm_r_types[r_type];
502 case MachO::CPU_TYPE_ARM64:
503 outs() << arm64_r_types[r_type];
506 outs() << format("%-7u ", r_type);
510 static void PrintRLength(const uint64_t cputype, const unsigned r_type,
511 const unsigned r_length, const bool previous_arm_half){
512 if (cputype == MachO::CPU_TYPE_ARM &&
513 (r_type == llvm::MachO::ARM_RELOC_HALF ||
514 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF ||
515 previous_arm_half == true)) {
516 if ((r_length & 0x1) == 0)
520 if ((r_length & 0x1) == 0)
536 if (cputype == MachO::CPU_TYPE_X86_64)
539 outs() << format("?(%2d) ", r_length);
542 outs() << format("?(%2d) ", r_length);
547 static void PrintRelocationEntries(const MachOObjectFile *O,
548 const relocation_iterator Begin,
549 const relocation_iterator End,
550 const uint64_t cputype,
551 const bool verbose) {
552 const MachO::symtab_command Symtab = O->getSymtabLoadCommand();
553 bool previous_arm_half = false;
554 bool previous_sectdiff = false;
555 uint32_t sectdiff_r_type = 0;
557 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) {
558 const DataRefImpl Rel = Reloc->getRawDataRefImpl();
559 const MachO::any_relocation_info RE = O->getRelocation(Rel);
560 const unsigned r_type = O->getAnyRelocationType(RE);
561 const bool r_scattered = O->isRelocationScattered(RE);
562 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE);
563 const unsigned r_length = O->getAnyRelocationLength(RE);
564 const unsigned r_address = O->getAnyRelocationAddress(RE);
565 const bool r_extern = (r_scattered ? false :
566 O->getPlainRelocationExternal(RE));
567 const uint32_t r_value = (r_scattered ?
568 O->getScatteredRelocationValue(RE) : 0);
569 const unsigned r_symbolnum = (r_scattered ? 0 :
570 O->getPlainRelocationSymbolNum(RE));
572 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) {
574 // scattered: address
575 if ((cputype == MachO::CPU_TYPE_I386 &&
576 r_type == llvm::MachO::GENERIC_RELOC_PAIR) ||
577 (cputype == MachO::CPU_TYPE_ARM &&
578 r_type == llvm::MachO::ARM_RELOC_PAIR))
581 outs() << format("%08x ", (unsigned int)r_address);
590 PrintRLength(cputype, r_type, r_length, previous_arm_half);
592 // scattered: extern & type
594 PrintRType(cputype, r_type);
596 // scattered: scattered & value
597 outs() << format("True 0x%08x", (unsigned int)r_value);
598 if (previous_sectdiff == false) {
599 if ((cputype == MachO::CPU_TYPE_ARM &&
600 r_type == llvm::MachO::ARM_RELOC_PAIR))
601 outs() << format(" half = 0x%04x ", (unsigned int)r_address);
603 else if (cputype == MachO::CPU_TYPE_ARM &&
604 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)
605 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address);
606 if ((cputype == MachO::CPU_TYPE_I386 &&
607 (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF ||
608 r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) ||
609 (cputype == MachO::CPU_TYPE_ARM &&
610 (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF ||
611 sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF ||
612 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) {
613 previous_sectdiff = true;
614 sectdiff_r_type = r_type;
617 previous_sectdiff = false;
620 if (cputype == MachO::CPU_TYPE_ARM &&
621 (r_type == llvm::MachO::ARM_RELOC_HALF ||
622 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
623 previous_arm_half = true;
625 previous_arm_half = false;
629 // scattered: address pcrel length extern type scattered value
630 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n",
631 (unsigned int)r_address, r_pcrel, r_length, r_type,
632 (unsigned int)r_value);
638 if (cputype == MachO::CPU_TYPE_ARM &&
639 r_type == llvm::MachO::ARM_RELOC_PAIR)
642 outs() << format("%08x ", (unsigned int)r_address);
651 PrintRLength(cputype, r_type, r_length, previous_arm_half);
654 // plain: extern & type & scattered
656 PrintRType(cputype, r_type);
659 // plain: symbolnum/value
660 if (r_symbolnum > Symtab.nsyms)
661 outs() << format("?(%d)\n", r_symbolnum);
663 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum);
664 Expected<StringRef> SymNameNext = Symbol.getName();
665 const char *name = NULL;
667 name = SymNameNext->data();
669 outs() << format("?(%d)\n", r_symbolnum);
671 outs() << name << "\n";
675 // plain: extern & type & scattered
677 PrintRType(cputype, r_type);
680 // plain: symbolnum/value
681 if (cputype == MachO::CPU_TYPE_ARM &&
682 r_type == llvm::MachO::ARM_RELOC_PAIR)
683 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
684 else if (cputype == MachO::CPU_TYPE_ARM64 &&
685 r_type == llvm::MachO::ARM64_RELOC_ADDEND)
686 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
688 outs() << format("%d ", r_symbolnum);
689 if (r_symbolnum == llvm::MachO::R_ABS)
692 // in this case, r_symbolnum is actually a 1-based section number
693 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a;
694 if (r_symbolnum > 0 && r_symbolnum <= nsects) {
695 llvm::object::DataRefImpl DRI;
696 DRI.d.a = r_symbolnum-1;
697 StringRef SegName = O->getSectionFinalSegmentName(DRI);
699 if (O->getSectionName(DRI, SectName))
702 outs() << "(" << SegName << "," << SectName << ")\n";
710 if (cputype == MachO::CPU_TYPE_ARM &&
711 (r_type == llvm::MachO::ARM_RELOC_HALF ||
712 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
713 previous_arm_half = true;
715 previous_arm_half = false;
718 // plain: address pcrel length extern type scattered symbolnum/section
719 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n",
720 (unsigned int)r_address, r_pcrel, r_length, r_extern,
721 r_type, r_symbolnum);
727 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
728 const uint64_t cputype = O->getHeader().cputype;
729 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
730 if (Dysymtab.nextrel != 0) {
731 outs() << "External relocation information " << Dysymtab.nextrel
733 outs() << "\naddress pcrel length extern type scattered "
735 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype,
738 if (Dysymtab.nlocrel != 0) {
739 outs() << format("Local relocation information %u entries",
741 outs() << "\naddress pcrel length extern type scattered "
743 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype,
746 for (const auto &Load : O->load_commands()) {
747 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
748 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
749 for (unsigned J = 0; J < Seg.nsects; ++J) {
750 const MachO::section_64 Sec = O->getSection64(Load, J);
751 if (Sec.nreloc != 0) {
754 const StringRef SegName = O->getSectionFinalSegmentName(DRI);
756 if (O->getSectionName(DRI, SectName))
757 outs() << "Relocation information (" << SegName << ",?) "
758 << format("%u entries", Sec.nreloc);
760 outs() << "Relocation information (" << SegName << ","
761 << SectName << format(") %u entries", Sec.nreloc);
762 outs() << "\naddress pcrel length extern type scattered "
764 PrintRelocationEntries(O, O->section_rel_begin(DRI),
765 O->section_rel_end(DRI), cputype, verbose);
768 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
769 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
770 for (unsigned J = 0; J < Seg.nsects; ++J) {
771 const MachO::section Sec = O->getSection(Load, J);
772 if (Sec.nreloc != 0) {
775 const StringRef SegName = O->getSectionFinalSegmentName(DRI);
777 if (O->getSectionName(DRI, SectName))
778 outs() << "Relocation information (" << SegName << ",?) "
779 << format("%u entries", Sec.nreloc);
781 outs() << "Relocation information (" << SegName << ","
782 << SectName << format(") %u entries", Sec.nreloc);
783 outs() << "\naddress pcrel length extern type scattered "
785 PrintRelocationEntries(O, O->section_rel_begin(DRI),
786 O->section_rel_end(DRI), cputype, verbose);
793 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
794 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
795 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
796 outs() << "Data in code table (" << nentries << " entries)\n";
797 outs() << "offset length kind\n";
798 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
801 DI->getOffset(Offset);
802 outs() << format("0x%08" PRIx32, Offset) << " ";
804 DI->getLength(Length);
805 outs() << format("%6u", Length) << " ";
810 case MachO::DICE_KIND_DATA:
813 case MachO::DICE_KIND_JUMP_TABLE8:
814 outs() << "JUMP_TABLE8";
816 case MachO::DICE_KIND_JUMP_TABLE16:
817 outs() << "JUMP_TABLE16";
819 case MachO::DICE_KIND_JUMP_TABLE32:
820 outs() << "JUMP_TABLE32";
822 case MachO::DICE_KIND_ABS_JUMP_TABLE32:
823 outs() << "ABS_JUMP_TABLE32";
826 outs() << format("0x%04" PRIx32, Kind);
830 outs() << format("0x%04" PRIx32, Kind);
835 static void PrintLinkOptHints(MachOObjectFile *O) {
836 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
837 const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
838 uint32_t nloh = LohLC.datasize;
839 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
840 for (uint32_t i = 0; i < nloh;) {
842 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
844 outs() << " identifier " << identifier << " ";
847 switch (identifier) {
849 outs() << "AdrpAdrp\n";
852 outs() << "AdrpLdr\n";
855 outs() << "AdrpAddLdr\n";
858 outs() << "AdrpLdrGotLdr\n";
861 outs() << "AdrpAddStr\n";
864 outs() << "AdrpLdrGotStr\n";
867 outs() << "AdrpAdd\n";
870 outs() << "AdrpLdrGot\n";
873 outs() << "Unknown identifier value\n";
876 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
878 outs() << " narguments " << narguments << "\n";
882 for (uint32_t j = 0; j < narguments; j++) {
883 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
885 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
892 static void PrintDylibs(MachOObjectFile *O, bool JustId) {
894 for (const auto &Load : O->load_commands()) {
895 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
896 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
897 Load.C.cmd == MachO::LC_LOAD_DYLIB ||
898 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
899 Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
900 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
901 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
902 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
903 if (dl.dylib.name < dl.cmdsize) {
904 const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
909 outs() << " (compatibility version "
910 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
911 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
912 << (dl.dylib.compatibility_version & 0xff) << ",";
913 outs() << " current version "
914 << ((dl.dylib.current_version >> 16) & 0xffff) << "."
915 << ((dl.dylib.current_version >> 8) & 0xff) << "."
916 << (dl.dylib.current_version & 0xff) << ")\n";
919 outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
920 if (Load.C.cmd == MachO::LC_ID_DYLIB)
921 outs() << "LC_ID_DYLIB ";
922 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
923 outs() << "LC_LOAD_DYLIB ";
924 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
925 outs() << "LC_LOAD_WEAK_DYLIB ";
926 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
927 outs() << "LC_LAZY_LOAD_DYLIB ";
928 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
929 outs() << "LC_REEXPORT_DYLIB ";
930 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
931 outs() << "LC_LOAD_UPWARD_DYLIB ";
934 outs() << "command " << Index++ << "\n";
940 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
942 static void CreateSymbolAddressMap(MachOObjectFile *O,
943 SymbolAddressMap *AddrMap) {
944 // Create a map of symbol addresses to symbol names.
945 for (const SymbolRef &Symbol : O->symbols()) {
946 Expected<SymbolRef::Type> STOrErr = Symbol.getType();
948 report_error(O->getFileName(), STOrErr.takeError());
949 SymbolRef::Type ST = *STOrErr;
950 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
951 ST == SymbolRef::ST_Other) {
952 uint64_t Address = Symbol.getValue();
953 Expected<StringRef> SymNameOrErr = Symbol.getName();
955 report_error(O->getFileName(), SymNameOrErr.takeError());
956 StringRef SymName = *SymNameOrErr;
957 if (!SymName.startswith(".objc"))
958 (*AddrMap)[Address] = SymName;
963 // GuessSymbolName is passed the address of what might be a symbol and a
964 // pointer to the SymbolAddressMap. It returns the name of a symbol
965 // with that address or nullptr if no symbol is found with that address.
966 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
967 const char *SymbolName = nullptr;
968 // A DenseMap can't lookup up some values.
969 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
970 StringRef name = AddrMap->lookup(value);
972 SymbolName = name.data();
977 static void DumpCstringChar(const char c) {
981 outs().write_escaped(p);
984 static void DumpCstringSection(MachOObjectFile *O, const char *sect,
985 uint32_t sect_size, uint64_t sect_addr,
986 bool print_addresses) {
987 for (uint32_t i = 0; i < sect_size; i++) {
988 if (print_addresses) {
990 outs() << format("%016" PRIx64, sect_addr + i) << " ";
992 outs() << format("%08" PRIx64, sect_addr + i) << " ";
994 for (; i < sect_size && sect[i] != '\0'; i++)
995 DumpCstringChar(sect[i]);
996 if (i < sect_size && sect[i] == '\0')
1001 static void DumpLiteral4(uint32_t l, float f) {
1002 outs() << format("0x%08" PRIx32, l);
1003 if ((l & 0x7f800000) != 0x7f800000)
1004 outs() << format(" (%.16e)\n", f);
1006 if (l == 0x7f800000)
1007 outs() << " (+Infinity)\n";
1008 else if (l == 0xff800000)
1009 outs() << " (-Infinity)\n";
1010 else if ((l & 0x00400000) == 0x00400000)
1011 outs() << " (non-signaling Not-a-Number)\n";
1013 outs() << " (signaling Not-a-Number)\n";
1017 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
1018 uint32_t sect_size, uint64_t sect_addr,
1019 bool print_addresses) {
1020 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
1021 if (print_addresses) {
1023 outs() << format("%016" PRIx64, sect_addr + i) << " ";
1025 outs() << format("%08" PRIx64, sect_addr + i) << " ";
1028 memcpy(&f, sect + i, sizeof(float));
1029 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1030 sys::swapByteOrder(f);
1032 memcpy(&l, sect + i, sizeof(uint32_t));
1033 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1034 sys::swapByteOrder(l);
1039 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
1041 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
1043 Hi = (O->isLittleEndian()) ? l1 : l0;
1044 Lo = (O->isLittleEndian()) ? l0 : l1;
1046 // Hi is the high word, so this is equivalent to if(isfinite(d))
1047 if ((Hi & 0x7ff00000) != 0x7ff00000)
1048 outs() << format(" (%.16e)\n", d);
1050 if (Hi == 0x7ff00000 && Lo == 0)
1051 outs() << " (+Infinity)\n";
1052 else if (Hi == 0xfff00000 && Lo == 0)
1053 outs() << " (-Infinity)\n";
1054 else if ((Hi & 0x00080000) == 0x00080000)
1055 outs() << " (non-signaling Not-a-Number)\n";
1057 outs() << " (signaling Not-a-Number)\n";
1061 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
1062 uint32_t sect_size, uint64_t sect_addr,
1063 bool print_addresses) {
1064 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
1065 if (print_addresses) {
1067 outs() << format("%016" PRIx64, sect_addr + i) << " ";
1069 outs() << format("%08" PRIx64, sect_addr + i) << " ";
1072 memcpy(&d, sect + i, sizeof(double));
1073 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1074 sys::swapByteOrder(d);
1076 memcpy(&l0, sect + i, sizeof(uint32_t));
1077 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1078 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1079 sys::swapByteOrder(l0);
1080 sys::swapByteOrder(l1);
1082 DumpLiteral8(O, l0, l1, d);
1086 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
1087 outs() << format("0x%08" PRIx32, l0) << " ";
1088 outs() << format("0x%08" PRIx32, l1) << " ";
1089 outs() << format("0x%08" PRIx32, l2) << " ";
1090 outs() << format("0x%08" PRIx32, l3) << "\n";
1093 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
1094 uint32_t sect_size, uint64_t sect_addr,
1095 bool print_addresses) {
1096 for (uint32_t i = 0; i < sect_size; i += 16) {
1097 if (print_addresses) {
1099 outs() << format("%016" PRIx64, sect_addr + i) << " ";
1101 outs() << format("%08" PRIx64, sect_addr + i) << " ";
1103 uint32_t l0, l1, l2, l3;
1104 memcpy(&l0, sect + i, sizeof(uint32_t));
1105 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1106 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
1107 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
1108 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1109 sys::swapByteOrder(l0);
1110 sys::swapByteOrder(l1);
1111 sys::swapByteOrder(l2);
1112 sys::swapByteOrder(l3);
1114 DumpLiteral16(l0, l1, l2, l3);
1118 static void DumpLiteralPointerSection(MachOObjectFile *O,
1119 const SectionRef &Section,
1120 const char *sect, uint32_t sect_size,
1122 bool print_addresses) {
1123 // Collect the literal sections in this Mach-O file.
1124 std::vector<SectionRef> LiteralSections;
1125 for (const SectionRef &Section : O->sections()) {
1126 DataRefImpl Ref = Section.getRawDataRefImpl();
1127 uint32_t section_type;
1129 const MachO::section_64 Sec = O->getSection64(Ref);
1130 section_type = Sec.flags & MachO::SECTION_TYPE;
1132 const MachO::section Sec = O->getSection(Ref);
1133 section_type = Sec.flags & MachO::SECTION_TYPE;
1135 if (section_type == MachO::S_CSTRING_LITERALS ||
1136 section_type == MachO::S_4BYTE_LITERALS ||
1137 section_type == MachO::S_8BYTE_LITERALS ||
1138 section_type == MachO::S_16BYTE_LITERALS)
1139 LiteralSections.push_back(Section);
1142 // Set the size of the literal pointer.
1143 uint32_t lp_size = O->is64Bit() ? 8 : 4;
1145 // Collect the external relocation symbols for the literal pointers.
1146 std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1147 for (const RelocationRef &Reloc : Section.relocations()) {
1149 MachO::any_relocation_info RE;
1150 bool isExtern = false;
1151 Rel = Reloc.getRawDataRefImpl();
1152 RE = O->getRelocation(Rel);
1153 isExtern = O->getPlainRelocationExternal(RE);
1155 uint64_t RelocOffset = Reloc.getOffset();
1156 symbol_iterator RelocSym = Reloc.getSymbol();
1157 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1160 array_pod_sort(Relocs.begin(), Relocs.end());
1162 // Dump each literal pointer.
1163 for (uint32_t i = 0; i < sect_size; i += lp_size) {
1164 if (print_addresses) {
1166 outs() << format("%016" PRIx64, sect_addr + i) << " ";
1168 outs() << format("%08" PRIx64, sect_addr + i) << " ";
1172 memcpy(&lp, sect + i, sizeof(uint64_t));
1173 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1174 sys::swapByteOrder(lp);
1177 memcpy(&li, sect + i, sizeof(uint32_t));
1178 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1179 sys::swapByteOrder(li);
1183 // First look for an external relocation entry for this literal pointer.
1184 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1185 return P.first == i;
1187 if (Reloc != Relocs.end()) {
1188 symbol_iterator RelocSym = Reloc->second;
1189 Expected<StringRef> SymName = RelocSym->getName();
1191 report_error(O->getFileName(), SymName.takeError());
1192 outs() << "external relocation entry for symbol:" << *SymName << "\n";
1196 // For local references see what the section the literal pointer points to.
1197 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
1198 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
1200 if (Sect == LiteralSections.end()) {
1201 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
1205 uint64_t SectAddress = Sect->getAddress();
1206 uint64_t SectSize = Sect->getSize();
1209 Sect->getName(SectName);
1210 DataRefImpl Ref = Sect->getRawDataRefImpl();
1211 StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
1212 outs() << SegmentName << ":" << SectName << ":";
1214 uint32_t section_type;
1216 const MachO::section_64 Sec = O->getSection64(Ref);
1217 section_type = Sec.flags & MachO::SECTION_TYPE;
1219 const MachO::section Sec = O->getSection(Ref);
1220 section_type = Sec.flags & MachO::SECTION_TYPE;
1224 Sect->getContents(BytesStr);
1225 const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
1227 switch (section_type) {
1228 case MachO::S_CSTRING_LITERALS:
1229 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
1231 DumpCstringChar(Contents[i]);
1235 case MachO::S_4BYTE_LITERALS:
1237 memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
1239 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
1240 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1241 sys::swapByteOrder(f);
1242 sys::swapByteOrder(l);
1246 case MachO::S_8BYTE_LITERALS: {
1248 memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
1250 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1251 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1253 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1254 sys::swapByteOrder(f);
1255 sys::swapByteOrder(l0);
1256 sys::swapByteOrder(l1);
1258 DumpLiteral8(O, l0, l1, d);
1261 case MachO::S_16BYTE_LITERALS: {
1262 uint32_t l0, l1, l2, l3;
1263 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1264 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1266 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
1268 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
1270 if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1271 sys::swapByteOrder(l0);
1272 sys::swapByteOrder(l1);
1273 sys::swapByteOrder(l2);
1274 sys::swapByteOrder(l3);
1276 DumpLiteral16(l0, l1, l2, l3);
1283 static void DumpInitTermPointerSection(MachOObjectFile *O,
1284 const SectionRef &Section,
1286 uint32_t sect_size, uint64_t sect_addr,
1287 SymbolAddressMap *AddrMap,
1290 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
1292 // Collect the external relocation symbols for the pointers.
1293 std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1294 for (const RelocationRef &Reloc : Section.relocations()) {
1296 MachO::any_relocation_info RE;
1297 bool isExtern = false;
1298 Rel = Reloc.getRawDataRefImpl();
1299 RE = O->getRelocation(Rel);
1300 isExtern = O->getPlainRelocationExternal(RE);
1302 uint64_t RelocOffset = Reloc.getOffset();
1303 symbol_iterator RelocSym = Reloc.getSymbol();
1304 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1307 array_pod_sort(Relocs.begin(), Relocs.end());
1309 for (uint32_t i = 0; i < sect_size; i += stride) {
1310 const char *SymbolName = nullptr;
1313 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
1314 uint64_t pointer_value;
1315 memcpy(&pointer_value, sect + i, stride);
1316 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1317 sys::swapByteOrder(pointer_value);
1318 outs() << format("0x%016" PRIx64, pointer_value);
1321 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
1322 uint32_t pointer_value;
1323 memcpy(&pointer_value, sect + i, stride);
1324 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1325 sys::swapByteOrder(pointer_value);
1326 outs() << format("0x%08" PRIx32, pointer_value);
1330 // First look for an external relocation entry for this pointer.
1331 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1332 return P.first == i;
1334 if (Reloc != Relocs.end()) {
1335 symbol_iterator RelocSym = Reloc->second;
1336 Expected<StringRef> SymName = RelocSym->getName();
1338 report_error(O->getFileName(), SymName.takeError());
1339 outs() << " " << *SymName;
1341 SymbolName = GuessSymbolName(p, AddrMap);
1343 outs() << " " << SymbolName;
1350 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
1351 uint32_t size, uint64_t addr) {
1352 uint32_t cputype = O->getHeader().cputype;
1353 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
1355 for (uint32_t i = 0; i < size; i += j, addr += j) {
1357 outs() << format("%016" PRIx64, addr) << "\t";
1359 outs() << format("%08" PRIx64, addr) << "\t";
1360 for (j = 0; j < 16 && i + j < size; j++) {
1361 uint8_t byte_word = *(sect + i + j);
1362 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1368 for (uint32_t i = 0; i < size; i += j, addr += j) {
1370 outs() << format("%016" PRIx64, addr) << "\t";
1372 outs() << format("%08" PRIx64, addr) << "\t";
1373 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
1374 j += sizeof(int32_t)) {
1375 if (i + j + sizeof(int32_t) <= size) {
1377 memcpy(&long_word, sect + i + j, sizeof(int32_t));
1378 if (O->isLittleEndian() != sys::IsLittleEndianHost)
1379 sys::swapByteOrder(long_word);
1380 outs() << format("%08" PRIx32, long_word) << " ";
1382 for (uint32_t k = 0; i + j + k < size; k++) {
1383 uint8_t byte_word = *(sect + i + j + k);
1384 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1393 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
1394 StringRef DisSegName, StringRef DisSectName);
1395 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
1396 uint32_t size, uint32_t addr);
1398 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
1399 uint32_t size, bool verbose,
1400 bool PrintXarHeader, bool PrintXarFileHeaders,
1401 std::string XarMemberName);
1402 #endif // defined(HAVE_LIBXAR)
1404 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
1406 SymbolAddressMap AddrMap;
1408 CreateSymbolAddressMap(O, &AddrMap);
1410 for (unsigned i = 0; i < FilterSections.size(); ++i) {
1411 StringRef DumpSection = FilterSections[i];
1412 std::pair<StringRef, StringRef> DumpSegSectName;
1413 DumpSegSectName = DumpSection.split(',');
1414 StringRef DumpSegName, DumpSectName;
1415 if (!DumpSegSectName.second.empty()) {
1416 DumpSegName = DumpSegSectName.first;
1417 DumpSectName = DumpSegSectName.second;
1420 DumpSectName = DumpSegSectName.first;
1422 for (const SectionRef &Section : O->sections()) {
1424 Section.getName(SectName);
1425 DataRefImpl Ref = Section.getRawDataRefImpl();
1426 StringRef SegName = O->getSectionFinalSegmentName(Ref);
1427 if ((DumpSegName.empty() || SegName == DumpSegName) &&
1428 (SectName == DumpSectName)) {
1430 uint32_t section_flags;
1432 const MachO::section_64 Sec = O->getSection64(Ref);
1433 section_flags = Sec.flags;
1436 const MachO::section Sec = O->getSection(Ref);
1437 section_flags = Sec.flags;
1439 uint32_t section_type = section_flags & MachO::SECTION_TYPE;
1442 Section.getContents(BytesStr);
1443 const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1444 uint32_t sect_size = BytesStr.size();
1445 uint64_t sect_addr = Section.getAddress();
1447 outs() << "Contents of (" << SegName << "," << SectName
1451 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
1452 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
1453 DisassembleMachO(Filename, O, SegName, SectName);
1456 if (SegName == "__TEXT" && SectName == "__info_plist") {
1460 if (SegName == "__OBJC" && SectName == "__protocol") {
1461 DumpProtocolSection(O, sect, sect_size, sect_addr);
1465 if (SegName == "__LLVM" && SectName == "__bundle") {
1466 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands,
1467 ArchiveHeaders, "");
1470 #endif // defined(HAVE_LIBXAR)
1471 switch (section_type) {
1472 case MachO::S_REGULAR:
1473 DumpRawSectionContents(O, sect, sect_size, sect_addr);
1475 case MachO::S_ZEROFILL:
1476 outs() << "zerofill section and has no contents in the file\n";
1478 case MachO::S_CSTRING_LITERALS:
1479 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1481 case MachO::S_4BYTE_LITERALS:
1482 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1484 case MachO::S_8BYTE_LITERALS:
1485 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1487 case MachO::S_16BYTE_LITERALS:
1488 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1490 case MachO::S_LITERAL_POINTERS:
1491 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
1494 case MachO::S_MOD_INIT_FUNC_POINTERS:
1495 case MachO::S_MOD_TERM_FUNC_POINTERS:
1496 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr,
1500 outs() << "Unknown section type ("
1501 << format("0x%08" PRIx32, section_type) << ")\n";
1502 DumpRawSectionContents(O, sect, sect_size, sect_addr);
1506 if (section_type == MachO::S_ZEROFILL)
1507 outs() << "zerofill section and has no contents in the file\n";
1509 DumpRawSectionContents(O, sect, sect_size, sect_addr);
1516 static void DumpInfoPlistSectionContents(StringRef Filename,
1517 MachOObjectFile *O) {
1518 for (const SectionRef &Section : O->sections()) {
1520 Section.getName(SectName);
1521 DataRefImpl Ref = Section.getRawDataRefImpl();
1522 StringRef SegName = O->getSectionFinalSegmentName(Ref);
1523 if (SegName == "__TEXT" && SectName == "__info_plist") {
1524 if (!NoLeadingHeaders)
1525 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
1527 Section.getContents(BytesStr);
1528 const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1529 outs() << format("%.*s", BytesStr.size(), sect) << "\n";
1535 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
1536 // and if it is and there is a list of architecture flags is specified then
1537 // check to make sure this Mach-O file is one of those architectures or all
1538 // architectures were specified. If not then an error is generated and this
1539 // routine returns false. Else it returns true.
1540 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
1541 auto *MachO = dyn_cast<MachOObjectFile>(O);
1543 if (!MachO || ArchAll || ArchFlags.empty())
1546 MachO::mach_header H;
1547 MachO::mach_header_64 H_64;
1549 const char *McpuDefault, *ArchFlag;
1550 if (MachO->is64Bit()) {
1551 H_64 = MachO->MachOObjectFile::getHeader64();
1552 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
1553 &McpuDefault, &ArchFlag);
1555 H = MachO->MachOObjectFile::getHeader();
1556 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
1557 &McpuDefault, &ArchFlag);
1559 const std::string ArchFlagName(ArchFlag);
1560 if (none_of(ArchFlags, [&](const std::string &Name) {
1561 return Name == ArchFlagName;
1563 WithColor::error(errs(), "llvm-objdump")
1564 << Filename << ": no architecture specified.\n";
1570 static void printObjcMetaData(MachOObjectFile *O, bool verbose);
1572 // ProcessMachO() is passed a single opened Mach-O file, which may be an
1573 // archive member and or in a slice of a universal file. It prints the
1574 // the file name and header info and then processes it according to the
1575 // command line options.
1576 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
1577 StringRef ArchiveMemberName = StringRef(),
1578 StringRef ArchitectureName = StringRef()) {
1579 // If we are doing some processing here on the Mach-O file print the header
1580 // info. And don't print it otherwise like in the case of printing the
1581 // UniversalHeaders or ArchiveHeaders.
1582 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
1583 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
1584 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData ||
1585 (!FilterSections.empty())) {
1586 if (!NoLeadingHeaders) {
1588 if (!ArchiveMemberName.empty())
1589 outs() << '(' << ArchiveMemberName << ')';
1590 if (!ArchitectureName.empty())
1591 outs() << " (architecture " << ArchitectureName << ")";
1595 // To use the report_error() form with an ArchiveName and FileName set
1596 // these up based on what is passed for Name and ArchiveMemberName.
1597 StringRef ArchiveName;
1599 if (!ArchiveMemberName.empty()) {
1601 FileName = ArchiveMemberName;
1603 ArchiveName = StringRef();
1607 // If we need the symbol table to do the operation then check it here to
1608 // produce a good error message as to where the Mach-O file comes from in
1609 // the error message.
1610 if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo)
1611 if (Error Err = MachOOF->checkSymbolTable())
1612 report_error(ArchiveName, FileName, std::move(Err), ArchitectureName);
1614 if (DisassembleAll) {
1615 for (const SectionRef &Section : MachOOF->sections()) {
1617 Section.getName(SectName);
1618 if (SectName.equals("__text")) {
1619 DataRefImpl Ref = Section.getRawDataRefImpl();
1620 StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref);
1621 DisassembleMachO(FileName, MachOOF, SegName, SectName);
1625 else if (Disassemble) {
1626 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE &&
1627 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64)
1628 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text");
1630 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
1632 if (IndirectSymbols)
1633 PrintIndirectSymbols(MachOOF, !NonVerbose);
1635 PrintDataInCodeTable(MachOOF, !NonVerbose);
1637 PrintLinkOptHints(MachOOF);
1639 PrintRelocations(MachOOF, !NonVerbose);
1641 printSectionHeaders(MachOOF);
1642 if (SectionContents)
1643 printSectionContents(MachOOF);
1644 if (!FilterSections.empty())
1645 DumpSectionContents(FileName, MachOOF, !NonVerbose);
1647 DumpInfoPlistSectionContents(FileName, MachOOF);
1649 PrintDylibs(MachOOF, false);
1651 PrintDylibs(MachOOF, true);
1653 printSymbolTable(MachOOF, ArchiveName, ArchitectureName);
1655 printMachOUnwindInfo(MachOOF);
1656 if (PrivateHeaders) {
1657 printMachOFileHeader(MachOOF);
1658 printMachOLoadCommands(MachOOF);
1660 if (FirstPrivateHeader)
1661 printMachOFileHeader(MachOOF);
1663 printObjcMetaData(MachOOF, !NonVerbose);
1665 printExportsTrie(MachOOF);
1667 printRebaseTable(MachOOF);
1669 printBindTable(MachOOF);
1671 printLazyBindTable(MachOOF);
1673 printWeakBindTable(MachOOF);
1675 if (DwarfDumpType != DIDT_Null) {
1676 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF);
1677 // Dump the complete DWARF structure.
1678 DIDumpOptions DumpOpts;
1679 DumpOpts.DumpType = DwarfDumpType;
1680 DICtx->dump(outs(), DumpOpts);
1684 // printUnknownCPUType() helps print_fat_headers for unknown CPU's.
1685 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
1686 outs() << " cputype (" << cputype << ")\n";
1687 outs() << " cpusubtype (" << cpusubtype << ")\n";
1690 // printCPUType() helps print_fat_headers by printing the cputype and
1691 // pusubtype (symbolically for the one's it knows about).
1692 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
1694 case MachO::CPU_TYPE_I386:
1695 switch (cpusubtype) {
1696 case MachO::CPU_SUBTYPE_I386_ALL:
1697 outs() << " cputype CPU_TYPE_I386\n";
1698 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n";
1701 printUnknownCPUType(cputype, cpusubtype);
1705 case MachO::CPU_TYPE_X86_64:
1706 switch (cpusubtype) {
1707 case MachO::CPU_SUBTYPE_X86_64_ALL:
1708 outs() << " cputype CPU_TYPE_X86_64\n";
1709 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
1711 case MachO::CPU_SUBTYPE_X86_64_H:
1712 outs() << " cputype CPU_TYPE_X86_64\n";
1713 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n";
1716 printUnknownCPUType(cputype, cpusubtype);
1720 case MachO::CPU_TYPE_ARM:
1721 switch (cpusubtype) {
1722 case MachO::CPU_SUBTYPE_ARM_ALL:
1723 outs() << " cputype CPU_TYPE_ARM\n";
1724 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n";
1726 case MachO::CPU_SUBTYPE_ARM_V4T:
1727 outs() << " cputype CPU_TYPE_ARM\n";
1728 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n";
1730 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1731 outs() << " cputype CPU_TYPE_ARM\n";
1732 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
1734 case MachO::CPU_SUBTYPE_ARM_XSCALE:
1735 outs() << " cputype CPU_TYPE_ARM\n";
1736 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
1738 case MachO::CPU_SUBTYPE_ARM_V6:
1739 outs() << " cputype CPU_TYPE_ARM\n";
1740 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n";
1742 case MachO::CPU_SUBTYPE_ARM_V6M:
1743 outs() << " cputype CPU_TYPE_ARM\n";
1744 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n";
1746 case MachO::CPU_SUBTYPE_ARM_V7:
1747 outs() << " cputype CPU_TYPE_ARM\n";
1748 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n";
1750 case MachO::CPU_SUBTYPE_ARM_V7EM:
1751 outs() << " cputype CPU_TYPE_ARM\n";
1752 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
1754 case MachO::CPU_SUBTYPE_ARM_V7K:
1755 outs() << " cputype CPU_TYPE_ARM\n";
1756 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n";
1758 case MachO::CPU_SUBTYPE_ARM_V7M:
1759 outs() << " cputype CPU_TYPE_ARM\n";
1760 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n";
1762 case MachO::CPU_SUBTYPE_ARM_V7S:
1763 outs() << " cputype CPU_TYPE_ARM\n";
1764 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n";
1767 printUnknownCPUType(cputype, cpusubtype);
1771 case MachO::CPU_TYPE_ARM64:
1772 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
1773 case MachO::CPU_SUBTYPE_ARM64_ALL:
1774 outs() << " cputype CPU_TYPE_ARM64\n";
1775 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
1778 printUnknownCPUType(cputype, cpusubtype);
1783 printUnknownCPUType(cputype, cpusubtype);
1788 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
1790 outs() << "Fat headers\n";
1792 if (UB->getMagic() == MachO::FAT_MAGIC)
1793 outs() << "fat_magic FAT_MAGIC\n";
1794 else // UB->getMagic() == MachO::FAT_MAGIC_64
1795 outs() << "fat_magic FAT_MAGIC_64\n";
1797 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
1799 uint32_t nfat_arch = UB->getNumberOfObjects();
1800 StringRef Buf = UB->getData();
1801 uint64_t size = Buf.size();
1802 uint64_t big_size = sizeof(struct MachO::fat_header) +
1803 nfat_arch * sizeof(struct MachO::fat_arch);
1804 outs() << "nfat_arch " << UB->getNumberOfObjects();
1806 outs() << " (malformed, contains zero architecture types)\n";
1807 else if (big_size > size)
1808 outs() << " (malformed, architectures past end of file)\n";
1812 for (uint32_t i = 0; i < nfat_arch; ++i) {
1813 MachOUniversalBinary::ObjectForArch OFA(UB, i);
1814 uint32_t cputype = OFA.getCPUType();
1815 uint32_t cpusubtype = OFA.getCPUSubType();
1816 outs() << "architecture ";
1817 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
1818 MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
1819 uint32_t other_cputype = other_OFA.getCPUType();
1820 uint32_t other_cpusubtype = other_OFA.getCPUSubType();
1821 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
1822 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
1823 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
1824 outs() << "(illegal duplicate architecture) ";
1829 outs() << OFA.getArchFlagName() << "\n";
1830 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
1832 outs() << i << "\n";
1833 outs() << " cputype " << cputype << "\n";
1834 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
1838 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
1839 outs() << " capabilities CPU_SUBTYPE_LIB64\n";
1841 outs() << " capabilities "
1842 << format("0x%" PRIx32,
1843 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
1844 outs() << " offset " << OFA.getOffset();
1845 if (OFA.getOffset() > size)
1846 outs() << " (past end of file)";
1847 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0)
1848 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
1850 outs() << " size " << OFA.getSize();
1851 big_size = OFA.getOffset() + OFA.getSize();
1852 if (big_size > size)
1853 outs() << " (past end of file)";
1855 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
1860 static void printArchiveChild(StringRef Filename, const Archive::Child &C,
1861 bool verbose, bool print_offset,
1862 StringRef ArchitectureName = StringRef()) {
1864 outs() << C.getChildOffset() << "\t";
1865 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();
1867 report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName);
1868 sys::fs::perms Mode = ModeOrErr.get();
1870 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
1871 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
1873 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
1874 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
1875 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
1876 outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
1877 outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
1878 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
1879 outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
1880 outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
1881 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
1883 outs() << format("0%o ", Mode);
1886 Expected<unsigned> UIDOrErr = C.getUID();
1888 report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName);
1889 unsigned UID = UIDOrErr.get();
1890 outs() << format("%3d/", UID);
1891 Expected<unsigned> GIDOrErr = C.getGID();
1893 report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName);
1894 unsigned GID = GIDOrErr.get();
1895 outs() << format("%-3d ", GID);
1896 Expected<uint64_t> Size = C.getRawSize();
1898 report_error(Filename, C, Size.takeError(), ArchitectureName);
1899 outs() << format("%5" PRId64, Size.get()) << " ";
1901 StringRef RawLastModified = C.getRawLastModified();
1904 if (RawLastModified.getAsInteger(10, Seconds))
1905 outs() << "(date: \"" << RawLastModified
1906 << "\" contains non-decimal chars) ";
1908 // Since cime(3) returns a 26 character string of the form:
1909 // "Sun Sep 16 01:03:52 1973\n\0"
1910 // just print 24 characters.
1912 outs() << format("%.24s ", ctime(&t));
1915 outs() << RawLastModified << " ";
1919 Expected<StringRef> NameOrErr = C.getName();
1921 consumeError(NameOrErr.takeError());
1922 Expected<StringRef> NameOrErr = C.getRawName();
1924 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
1925 StringRef RawName = NameOrErr.get();
1926 outs() << RawName << "\n";
1928 StringRef Name = NameOrErr.get();
1929 outs() << Name << "\n";
1932 Expected<StringRef> NameOrErr = C.getRawName();
1934 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
1935 StringRef RawName = NameOrErr.get();
1936 outs() << RawName << "\n";
1940 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
1942 StringRef ArchitectureName = StringRef()) {
1943 Error Err = Error::success();
1945 for (const auto &C : A->children(Err, false))
1946 printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName);
1949 report_error(StringRef(), Filename, std::move(Err), ArchitectureName);
1952 static bool ValidateArchFlags() {
1953 // Check for -arch all and verifiy the -arch flags are valid.
1954 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
1955 if (ArchFlags[i] == "all") {
1958 if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
1959 WithColor::error(errs(), "llvm-objdump")
1960 << "unknown architecture named '" + ArchFlags[i] +
1961 "'for the -arch option\n";
1969 // ParseInputMachO() parses the named Mach-O file in Filename and handles the
1970 // -arch flags selecting just those slices as specified by them and also parses
1971 // archive files. Then for each individual Mach-O file ProcessMachO() is
1972 // called to process the file based on the command line options.
1973 void llvm::parseInputMachO(StringRef Filename) {
1974 if (!ValidateArchFlags())
1977 // Attempt to open the binary.
1978 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
1980 if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError()))
1981 report_error(Filename, std::move(E));
1983 outs() << Filename << ": is not an object file\n";
1986 Binary &Bin = *BinaryOrErr.get().getBinary();
1988 if (Archive *A = dyn_cast<Archive>(&Bin)) {
1989 outs() << "Archive : " << Filename << "\n";
1991 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets);
1993 Error Err = Error::success();
1994 for (auto &C : A->children(Err)) {
1995 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
1997 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
1998 report_error(Filename, C, std::move(E));
2001 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2002 if (!checkMachOAndArchFlags(O, Filename))
2004 ProcessMachO(Filename, O, O->getFileName());
2008 report_error(Filename, std::move(Err));
2011 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
2012 parseInputMachO(UB);
2015 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
2016 if (!checkMachOAndArchFlags(O, Filename))
2018 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O))
2019 ProcessMachO(Filename, MachOOF);
2021 WithColor::error(errs(), "llvm-objdump")
2022 << Filename << "': "
2023 << "object is not a Mach-O file type.\n";
2026 llvm_unreachable("Input object can't be invalid at this point");
2029 void llvm::parseInputMachO(MachOUniversalBinary *UB) {
2030 if (!ValidateArchFlags())
2033 auto Filename = UB->getFileName();
2035 if (UniversalHeaders)
2036 printMachOUniversalHeaders(UB, !NonVerbose);
2038 // If we have a list of architecture flags specified dump only those.
2039 if (!ArchAll && !ArchFlags.empty()) {
2040 // Look for a slice in the universal binary that matches each ArchFlag.
2042 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2044 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2045 E = UB->end_objects();
2047 if (ArchFlags[i] == I->getArchFlagName()) {
2049 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
2050 I->getAsObjectFile();
2051 std::string ArchitectureName = "";
2052 if (ArchFlags.size() > 1)
2053 ArchitectureName = I->getArchFlagName();
2055 ObjectFile &O = *ObjOrErr.get();
2056 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2057 ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2058 } else if (auto E = isNotObjectErrorInvalidFileType(
2059 ObjOrErr.takeError())) {
2060 report_error(Filename, StringRef(), std::move(E),
2063 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2064 I->getAsArchive()) {
2065 std::unique_ptr<Archive> &A = *AOrErr;
2066 outs() << "Archive : " << Filename;
2067 if (!ArchitectureName.empty())
2068 outs() << " (architecture " << ArchitectureName << ")";
2071 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2072 ArchiveMemberOffsets, ArchitectureName);
2073 Error Err = Error::success();
2074 for (auto &C : A->children(Err)) {
2075 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2077 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2078 report_error(Filename, C, std::move(E), ArchitectureName);
2081 if (MachOObjectFile *O =
2082 dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2083 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
2086 report_error(Filename, std::move(Err));
2088 consumeError(AOrErr.takeError());
2089 error("Mach-O universal file: " + Filename + " for " +
2090 "architecture " + StringRef(I->getArchFlagName()) +
2091 " is not a Mach-O file or an archive file");
2096 WithColor::error(errs(), "llvm-objdump")
2097 << "file: " + Filename + " does not contain "
2098 << "architecture: " + ArchFlags[i] + "\n";
2104 // No architecture flags were specified so if this contains a slice that
2105 // matches the host architecture dump only that.
2107 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2108 E = UB->end_objects();
2110 if (MachOObjectFile::getHostArch().getArchName() ==
2111 I->getArchFlagName()) {
2112 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2113 std::string ArchiveName;
2114 ArchiveName.clear();
2116 ObjectFile &O = *ObjOrErr.get();
2117 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2118 ProcessMachO(Filename, MachOOF);
2119 } else if (auto E = isNotObjectErrorInvalidFileType(
2120 ObjOrErr.takeError())) {
2121 report_error(Filename, std::move(E));
2122 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2123 I->getAsArchive()) {
2124 std::unique_ptr<Archive> &A = *AOrErr;
2125 outs() << "Archive : " << Filename << "\n";
2127 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2128 ArchiveMemberOffsets);
2129 Error Err = Error::success();
2130 for (auto &C : A->children(Err)) {
2131 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2133 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2134 report_error(Filename, C, std::move(E));
2137 if (MachOObjectFile *O =
2138 dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2139 ProcessMachO(Filename, O, O->getFileName());
2142 report_error(Filename, std::move(Err));
2144 consumeError(AOrErr.takeError());
2145 error("Mach-O universal file: " + Filename + " for architecture " +
2146 StringRef(I->getArchFlagName()) +
2147 " is not a Mach-O file or an archive file");
2153 // Either all architectures have been specified or none have been specified
2154 // and this does not contain the host architecture so dump all the slices.
2155 bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2156 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2157 E = UB->end_objects();
2159 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2160 std::string ArchitectureName = "";
2161 if (moreThanOneArch)
2162 ArchitectureName = I->getArchFlagName();
2164 ObjectFile &Obj = *ObjOrErr.get();
2165 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
2166 ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2167 } else if (auto E = isNotObjectErrorInvalidFileType(
2168 ObjOrErr.takeError())) {
2169 report_error(StringRef(), Filename, std::move(E), ArchitectureName);
2170 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2171 I->getAsArchive()) {
2172 std::unique_ptr<Archive> &A = *AOrErr;
2173 outs() << "Archive : " << Filename;
2174 if (!ArchitectureName.empty())
2175 outs() << " (architecture " << ArchitectureName << ")";
2178 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2179 ArchiveMemberOffsets, ArchitectureName);
2180 Error Err = Error::success();
2181 for (auto &C : A->children(Err)) {
2182 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2184 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2185 report_error(Filename, C, std::move(E), ArchitectureName);
2188 if (MachOObjectFile *O =
2189 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2190 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
2191 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
2196 report_error(Filename, std::move(Err));
2198 consumeError(AOrErr.takeError());
2199 error("Mach-O universal file: " + Filename + " for architecture " +
2200 StringRef(I->getArchFlagName()) +
2201 " is not a Mach-O file or an archive file");
2206 // The block of info used by the Symbolizer call backs.
2207 struct DisassembleInfo {
2208 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap,
2209 std::vector<SectionRef> *Sections, bool verbose)
2210 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}
2214 SymbolAddressMap *AddrMap;
2215 std::vector<SectionRef> *Sections;
2216 const char *class_name = nullptr;
2217 const char *selector_name = nullptr;
2218 std::unique_ptr<char[]> method = nullptr;
2219 char *demangled_name = nullptr;
2220 uint64_t adrp_addr = 0;
2221 uint32_t adrp_inst = 0;
2222 std::unique_ptr<SymbolAddressMap> bindtable;
2226 // SymbolizerGetOpInfo() is the operand information call back function.
2227 // This is called to get the symbolic information for operand(s) of an
2228 // instruction when it is being done. This routine does this from
2229 // the relocation information, symbol table, etc. That block of information
2230 // is a pointer to the struct DisassembleInfo that was passed when the
2231 // disassembler context was created and passed to back to here when
2232 // called back by the disassembler for instruction operands that could have
2233 // relocation information. The address of the instruction containing operand is
2234 // at the Pc parameter. The immediate value the operand has is passed in
2235 // op_info->Value and is at Offset past the start of the instruction and has a
2236 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
2237 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
2238 // names and addends of the symbolic expression to add for the operand. The
2239 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
2240 // information is returned then this function returns 1 else it returns 0.
2241 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
2242 uint64_t Size, int TagType, void *TagBuf) {
2243 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
2244 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
2245 uint64_t value = op_info->Value;
2247 // Make sure all fields returned are zero if we don't set them.
2248 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
2249 op_info->Value = value;
2251 // If the TagType is not the value 1 which it code knows about or if no
2252 // verbose symbolic information is wanted then just return 0, indicating no
2253 // information is being returned.
2254 if (TagType != 1 || !info->verbose)
2257 unsigned int Arch = info->O->getArch();
2258 if (Arch == Triple::x86) {
2259 if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
2261 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2263 // Search the external relocation entries of a fully linked image
2264 // (if any) for an entry that matches this segment offset.
2265 // uint32_t seg_offset = (Pc + Offset);
2268 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2269 // for an entry for this section offset.
2270 uint32_t sect_addr = info->S.getAddress();
2271 uint32_t sect_offset = (Pc + Offset) - sect_addr;
2272 bool reloc_found = false;
2274 MachO::any_relocation_info RE;
2275 bool isExtern = false;
2277 bool r_scattered = false;
2278 uint32_t r_value, pair_r_value, r_type;
2279 for (const RelocationRef &Reloc : info->S.relocations()) {
2280 uint64_t RelocOffset = Reloc.getOffset();
2281 if (RelocOffset == sect_offset) {
2282 Rel = Reloc.getRawDataRefImpl();
2283 RE = info->O->getRelocation(Rel);
2284 r_type = info->O->getAnyRelocationType(RE);
2285 r_scattered = info->O->isRelocationScattered(RE);
2287 r_value = info->O->getScatteredRelocationValue(RE);
2288 if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2289 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
2290 DataRefImpl RelNext = Rel;
2291 info->O->moveRelocationNext(RelNext);
2292 MachO::any_relocation_info RENext;
2293 RENext = info->O->getRelocation(RelNext);
2294 if (info->O->isRelocationScattered(RENext))
2295 pair_r_value = info->O->getScatteredRelocationValue(RENext);
2300 isExtern = info->O->getPlainRelocationExternal(RE);
2302 symbol_iterator RelocSym = Reloc.getSymbol();
2310 if (reloc_found && isExtern) {
2311 Expected<StringRef> SymName = Symbol.getName();
2313 report_error(info->O->getFileName(), SymName.takeError());
2314 const char *name = SymName->data();
2315 op_info->AddSymbol.Present = 1;
2316 op_info->AddSymbol.Name = name;
2317 // For i386 extern relocation entries the value in the instruction is
2318 // the offset from the symbol, and value is already set in op_info->Value.
2321 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2322 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
2323 const char *add = GuessSymbolName(r_value, info->AddrMap);
2324 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2325 uint32_t offset = value - (r_value - pair_r_value);
2326 op_info->AddSymbol.Present = 1;
2328 op_info->AddSymbol.Name = add;
2330 op_info->AddSymbol.Value = r_value;
2331 op_info->SubtractSymbol.Present = 1;
2333 op_info->SubtractSymbol.Name = sub;
2335 op_info->SubtractSymbol.Value = pair_r_value;
2336 op_info->Value = offset;
2341 if (Arch == Triple::x86_64) {
2342 if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
2344 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external
2345 // relocation entries of a linked image (if any) for an entry that matches
2346 // this segment offset.
2347 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2348 uint64_t seg_offset = Pc + Offset;
2349 bool reloc_found = false;
2351 MachO::any_relocation_info RE;
2352 bool isExtern = false;
2354 for (const RelocationRef &Reloc : info->O->external_relocations()) {
2355 uint64_t RelocOffset = Reloc.getOffset();
2356 if (RelocOffset == seg_offset) {
2357 Rel = Reloc.getRawDataRefImpl();
2358 RE = info->O->getRelocation(Rel);
2359 // external relocation entries should always be external.
2360 isExtern = info->O->getPlainRelocationExternal(RE);
2362 symbol_iterator RelocSym = Reloc.getSymbol();
2369 if (reloc_found && isExtern) {
2370 // The Value passed in will be adjusted by the Pc if the instruction
2371 // adds the Pc. But for x86_64 external relocation entries the Value
2372 // is the offset from the external symbol.
2373 if (info->O->getAnyRelocationPCRel(RE))
2374 op_info->Value -= Pc + Offset + Size;
2375 Expected<StringRef> SymName = Symbol.getName();
2377 report_error(info->O->getFileName(), SymName.takeError());
2378 const char *name = SymName->data();
2379 op_info->AddSymbol.Present = 1;
2380 op_info->AddSymbol.Name = name;
2385 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2386 // for an entry for this section offset.
2387 uint64_t sect_addr = info->S.getAddress();
2388 uint64_t sect_offset = (Pc + Offset) - sect_addr;
2389 bool reloc_found = false;
2391 MachO::any_relocation_info RE;
2392 bool isExtern = false;
2394 for (const RelocationRef &Reloc : info->S.relocations()) {
2395 uint64_t RelocOffset = Reloc.getOffset();
2396 if (RelocOffset == sect_offset) {
2397 Rel = Reloc.getRawDataRefImpl();
2398 RE = info->O->getRelocation(Rel);
2399 // NOTE: Scattered relocations don't exist on x86_64.
2400 isExtern = info->O->getPlainRelocationExternal(RE);
2402 symbol_iterator RelocSym = Reloc.getSymbol();
2409 if (reloc_found && isExtern) {
2410 // The Value passed in will be adjusted by the Pc if the instruction
2411 // adds the Pc. But for x86_64 external relocation entries the Value
2412 // is the offset from the external symbol.
2413 if (info->O->getAnyRelocationPCRel(RE))
2414 op_info->Value -= Pc + Offset + Size;
2415 Expected<StringRef> SymName = Symbol.getName();
2417 report_error(info->O->getFileName(), SymName.takeError());
2418 const char *name = SymName->data();
2419 unsigned Type = info->O->getAnyRelocationType(RE);
2420 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
2421 DataRefImpl RelNext = Rel;
2422 info->O->moveRelocationNext(RelNext);
2423 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2424 unsigned TypeNext = info->O->getAnyRelocationType(RENext);
2425 bool isExternNext = info->O->getPlainRelocationExternal(RENext);
2426 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
2427 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
2428 op_info->SubtractSymbol.Present = 1;
2429 op_info->SubtractSymbol.Name = name;
2430 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
2431 Symbol = *RelocSymNext;
2432 Expected<StringRef> SymNameNext = Symbol.getName();
2434 report_error(info->O->getFileName(), SymNameNext.takeError());
2435 name = SymNameNext->data();
2438 // TODO: add the VariantKinds to op_info->VariantKind for relocation types
2439 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
2440 op_info->AddSymbol.Present = 1;
2441 op_info->AddSymbol.Name = name;
2446 if (Arch == Triple::arm) {
2447 if (Offset != 0 || (Size != 4 && Size != 2))
2449 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2451 // Search the external relocation entries of a fully linked image
2452 // (if any) for an entry that matches this segment offset.
2453 // uint32_t seg_offset = (Pc + Offset);
2456 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2457 // for an entry for this section offset.
2458 uint32_t sect_addr = info->S.getAddress();
2459 uint32_t sect_offset = (Pc + Offset) - sect_addr;
2461 MachO::any_relocation_info RE;
2462 bool isExtern = false;
2464 bool r_scattered = false;
2465 uint32_t r_value, pair_r_value, r_type, r_length, other_half;
2467 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
2468 uint64_t RelocOffset = Reloc.getOffset();
2469 return RelocOffset == sect_offset;
2472 if (Reloc == info->S.relocations().end())
2475 Rel = Reloc->getRawDataRefImpl();
2476 RE = info->O->getRelocation(Rel);
2477 r_length = info->O->getAnyRelocationLength(RE);
2478 r_scattered = info->O->isRelocationScattered(RE);
2480 r_value = info->O->getScatteredRelocationValue(RE);
2481 r_type = info->O->getScatteredRelocationType(RE);
2483 r_type = info->O->getAnyRelocationType(RE);
2484 isExtern = info->O->getPlainRelocationExternal(RE);
2486 symbol_iterator RelocSym = Reloc->getSymbol();
2490 if (r_type == MachO::ARM_RELOC_HALF ||
2491 r_type == MachO::ARM_RELOC_SECTDIFF ||
2492 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
2493 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2494 DataRefImpl RelNext = Rel;
2495 info->O->moveRelocationNext(RelNext);
2496 MachO::any_relocation_info RENext;
2497 RENext = info->O->getRelocation(RelNext);
2498 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
2499 if (info->O->isRelocationScattered(RENext))
2500 pair_r_value = info->O->getScatteredRelocationValue(RENext);
2504 Expected<StringRef> SymName = Symbol.getName();
2506 report_error(info->O->getFileName(), SymName.takeError());
2507 const char *name = SymName->data();
2508 op_info->AddSymbol.Present = 1;
2509 op_info->AddSymbol.Name = name;
2511 case MachO::ARM_RELOC_HALF:
2512 if ((r_length & 0x1) == 1) {
2513 op_info->Value = value << 16 | other_half;
2514 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
2516 op_info->Value = other_half << 16 | value;
2517 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
2525 // If we have a branch that is not an external relocation entry then
2526 // return 0 so the code in tryAddingSymbolicOperand() can use the
2527 // SymbolLookUp call back with the branch target address to look up the
2528 // symbol and possibility add an annotation for a symbol stub.
2529 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
2530 r_type == MachO::ARM_THUMB_RELOC_BR22))
2533 uint32_t offset = 0;
2534 if (r_type == MachO::ARM_RELOC_HALF ||
2535 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2536 if ((r_length & 0x1) == 1)
2537 value = value << 16 | other_half;
2539 value = other_half << 16 | value;
2541 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
2542 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
2543 offset = value - r_value;
2547 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2548 if ((r_length & 0x1) == 1)
2549 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
2551 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
2552 const char *add = GuessSymbolName(r_value, info->AddrMap);
2553 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2554 int32_t offset = value - (r_value - pair_r_value);
2555 op_info->AddSymbol.Present = 1;
2557 op_info->AddSymbol.Name = add;
2559 op_info->AddSymbol.Value = r_value;
2560 op_info->SubtractSymbol.Present = 1;
2562 op_info->SubtractSymbol.Name = sub;
2564 op_info->SubtractSymbol.Value = pair_r_value;
2565 op_info->Value = offset;
2569 op_info->AddSymbol.Present = 1;
2570 op_info->Value = offset;
2571 if (r_type == MachO::ARM_RELOC_HALF) {
2572 if ((r_length & 0x1) == 1)
2573 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
2575 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
2577 const char *add = GuessSymbolName(value, info->AddrMap);
2578 if (add != nullptr) {
2579 op_info->AddSymbol.Name = add;
2582 op_info->AddSymbol.Value = value;
2585 if (Arch == Triple::aarch64) {
2586 if (Offset != 0 || Size != 4)
2588 if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2590 // Search the external relocation entries of a fully linked image
2591 // (if any) for an entry that matches this segment offset.
2592 // uint64_t seg_offset = (Pc + Offset);
2595 // In MH_OBJECT filetypes search the section's relocation entries (if any)
2596 // for an entry for this section offset.
2597 uint64_t sect_addr = info->S.getAddress();
2598 uint64_t sect_offset = (Pc + Offset) - sect_addr;
2600 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
2601 uint64_t RelocOffset = Reloc.getOffset();
2602 return RelocOffset == sect_offset;
2605 if (Reloc == info->S.relocations().end())
2608 DataRefImpl Rel = Reloc->getRawDataRefImpl();
2609 MachO::any_relocation_info RE = info->O->getRelocation(Rel);
2610 uint32_t r_type = info->O->getAnyRelocationType(RE);
2611 if (r_type == MachO::ARM64_RELOC_ADDEND) {
2612 DataRefImpl RelNext = Rel;
2613 info->O->moveRelocationNext(RelNext);
2614 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2616 value = info->O->getPlainRelocationSymbolNum(RENext);
2617 op_info->Value = value;
2620 // NOTE: Scattered relocations don't exist on arm64.
2621 if (!info->O->getPlainRelocationExternal(RE))
2623 Expected<StringRef> SymName = Reloc->getSymbol()->getName();
2625 report_error(info->O->getFileName(), SymName.takeError());
2626 const char *name = SymName->data();
2627 op_info->AddSymbol.Present = 1;
2628 op_info->AddSymbol.Name = name;
2631 case MachO::ARM64_RELOC_PAGE21:
2633 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
2635 case MachO::ARM64_RELOC_PAGEOFF12:
2637 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
2639 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
2641 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
2643 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
2645 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
2647 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
2648 /* @tvlppage is not implemented in llvm-mc */
2649 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
2651 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
2652 /* @tvlppageoff is not implemented in llvm-mc */
2653 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
2656 case MachO::ARM64_RELOC_BRANCH26:
2657 op_info->VariantKind = LLVMDisassembler_VariantKind_None;
2665 // GuessCstringPointer is passed the address of what might be a pointer to a
2666 // literal string in a cstring section. If that address is in a cstring section
2667 // it returns a pointer to that string. Else it returns nullptr.
2668 static const char *GuessCstringPointer(uint64_t ReferenceValue,
2669 struct DisassembleInfo *info) {
2670 for (const auto &Load : info->O->load_commands()) {
2671 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2672 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2673 for (unsigned J = 0; J < Seg.nsects; ++J) {
2674 MachO::section_64 Sec = info->O->getSection64(Load, J);
2675 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2676 if (section_type == MachO::S_CSTRING_LITERALS &&
2677 ReferenceValue >= Sec.addr &&
2678 ReferenceValue < Sec.addr + Sec.size) {
2679 uint64_t sect_offset = ReferenceValue - Sec.addr;
2680 uint64_t object_offset = Sec.offset + sect_offset;
2681 StringRef MachOContents = info->O->getData();
2682 uint64_t object_size = MachOContents.size();
2683 const char *object_addr = (const char *)MachOContents.data();
2684 if (object_offset < object_size) {
2685 const char *name = object_addr + object_offset;
2692 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2693 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2694 for (unsigned J = 0; J < Seg.nsects; ++J) {
2695 MachO::section Sec = info->O->getSection(Load, J);
2696 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2697 if (section_type == MachO::S_CSTRING_LITERALS &&
2698 ReferenceValue >= Sec.addr &&
2699 ReferenceValue < Sec.addr + Sec.size) {
2700 uint64_t sect_offset = ReferenceValue - Sec.addr;
2701 uint64_t object_offset = Sec.offset + sect_offset;
2702 StringRef MachOContents = info->O->getData();
2703 uint64_t object_size = MachOContents.size();
2704 const char *object_addr = (const char *)MachOContents.data();
2705 if (object_offset < object_size) {
2706 const char *name = object_addr + object_offset;
2718 // GuessIndirectSymbol returns the name of the indirect symbol for the
2719 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe
2720 // an address of a symbol stub or a lazy or non-lazy pointer to associate the
2721 // symbol name being referenced by the stub or pointer.
2722 static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
2723 struct DisassembleInfo *info) {
2724 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
2725 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
2726 for (const auto &Load : info->O->load_commands()) {
2727 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2728 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2729 for (unsigned J = 0; J < Seg.nsects; ++J) {
2730 MachO::section_64 Sec = info->O->getSection64(Load, J);
2731 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2732 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2733 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2734 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2735 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2736 section_type == MachO::S_SYMBOL_STUBS) &&
2737 ReferenceValue >= Sec.addr &&
2738 ReferenceValue < Sec.addr + Sec.size) {
2740 if (section_type == MachO::S_SYMBOL_STUBS)
2741 stride = Sec.reserved2;
2746 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2747 if (index < Dysymtab.nindirectsyms) {
2748 uint32_t indirect_symbol =
2749 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2750 if (indirect_symbol < Symtab.nsyms) {
2751 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2752 SymbolRef Symbol = *Sym;
2753 Expected<StringRef> SymName = Symbol.getName();
2755 report_error(info->O->getFileName(), SymName.takeError());
2756 const char *name = SymName->data();
2762 } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2763 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2764 for (unsigned J = 0; J < Seg.nsects; ++J) {
2765 MachO::section Sec = info->O->getSection(Load, J);
2766 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2767 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2768 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2769 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2770 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2771 section_type == MachO::S_SYMBOL_STUBS) &&
2772 ReferenceValue >= Sec.addr &&
2773 ReferenceValue < Sec.addr + Sec.size) {
2775 if (section_type == MachO::S_SYMBOL_STUBS)
2776 stride = Sec.reserved2;
2781 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2782 if (index < Dysymtab.nindirectsyms) {
2783 uint32_t indirect_symbol =
2784 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2785 if (indirect_symbol < Symtab.nsyms) {
2786 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2787 SymbolRef Symbol = *Sym;
2788 Expected<StringRef> SymName = Symbol.getName();
2790 report_error(info->O->getFileName(), SymName.takeError());
2791 const char *name = SymName->data();
2802 // method_reference() is called passing it the ReferenceName that might be
2803 // a reference it to an Objective-C method call. If so then it allocates and
2804 // assembles a method call string with the values last seen and saved in
2805 // the DisassembleInfo's class_name and selector_name fields. This is saved
2806 // into the method field of the info and any previous string is free'ed.
2807 // Then the class_name field in the info is set to nullptr. The method call
2808 // string is set into ReferenceName and ReferenceType is set to
2809 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call
2810 // then both ReferenceType and ReferenceName are left unchanged.
2811 static void method_reference(struct DisassembleInfo *info,
2812 uint64_t *ReferenceType,
2813 const char **ReferenceName) {
2814 unsigned int Arch = info->O->getArch();
2815 if (*ReferenceName != nullptr) {
2816 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
2817 if (info->selector_name != nullptr) {
2818 if (info->class_name != nullptr) {
2819 info->method = llvm::make_unique<char[]>(
2820 5 + strlen(info->class_name) + strlen(info->selector_name));
2821 char *method = info->method.get();
2822 if (method != nullptr) {
2823 strcpy(method, "+[");
2824 strcat(method, info->class_name);
2825 strcat(method, " ");
2826 strcat(method, info->selector_name);
2827 strcat(method, "]");
2828 *ReferenceName = method;
2829 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
2833 llvm::make_unique<char[]>(9 + strlen(info->selector_name));
2834 char *method = info->method.get();
2835 if (method != nullptr) {
2836 if (Arch == Triple::x86_64)
2837 strcpy(method, "-[%rdi ");
2838 else if (Arch == Triple::aarch64)
2839 strcpy(method, "-[x0 ");
2841 strcpy(method, "-[r? ");
2842 strcat(method, info->selector_name);
2843 strcat(method, "]");
2844 *ReferenceName = method;
2845 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
2848 info->class_name = nullptr;
2850 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
2851 if (info->selector_name != nullptr) {
2853 llvm::make_unique<char[]>(17 + strlen(info->selector_name));
2854 char *method = info->method.get();
2855 if (method != nullptr) {
2856 if (Arch == Triple::x86_64)
2857 strcpy(method, "-[[%rdi super] ");
2858 else if (Arch == Triple::aarch64)
2859 strcpy(method, "-[[x0 super] ");
2861 strcpy(method, "-[[r? super] ");
2862 strcat(method, info->selector_name);
2863 strcat(method, "]");
2864 *ReferenceName = method;
2865 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
2867 info->class_name = nullptr;
2873 // GuessPointerPointer() is passed the address of what might be a pointer to
2874 // a reference to an Objective-C class, selector, message ref or cfstring.
2875 // If so the value of the pointer is returned and one of the booleans are set
2876 // to true. If not zero is returned and all the booleans are set to false.
2877 static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
2878 struct DisassembleInfo *info,
2879 bool &classref, bool &selref, bool &msgref,
2885 for (const auto &Load : info->O->load_commands()) {
2886 if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2887 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2888 for (unsigned J = 0; J < Seg.nsects; ++J) {
2889 MachO::section_64 Sec = info->O->getSection64(Load, J);
2890 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
2891 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2892 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
2893 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
2894 strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
2895 ReferenceValue >= Sec.addr &&
2896 ReferenceValue < Sec.addr + Sec.size) {
2897 uint64_t sect_offset = ReferenceValue - Sec.addr;
2898 uint64_t object_offset = Sec.offset + sect_offset;
2899 StringRef MachOContents = info->O->getData();
2900 uint64_t object_size = MachOContents.size();
2901 const char *object_addr = (const char *)MachOContents.data();
2902 if (object_offset < object_size) {
2903 uint64_t pointer_value;
2904 memcpy(&pointer_value, object_addr + object_offset,
2906 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2907 sys::swapByteOrder(pointer_value);
2908 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
2910 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2911 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
2913 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
2914 ReferenceValue + 8 < Sec.addr + Sec.size) {
2916 memcpy(&pointer_value, object_addr + object_offset + 8,
2918 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2919 sys::swapByteOrder(pointer_value);
2920 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
2922 return pointer_value;
2929 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
2934 // get_pointer_64 returns a pointer to the bytes in the object file at the
2935 // Address from a section in the Mach-O file. And indirectly returns the
2936 // offset into the section, number of bytes left in the section past the offset
2937 // and which section is was being referenced. If the Address is not in a
2938 // section nullptr is returned.
2939 static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
2940 uint32_t &left, SectionRef &S,
2941 DisassembleInfo *info,
2942 bool objc_only = false) {
2946 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
2947 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
2948 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
2953 ((*(info->Sections))[SectIdx]).getName(SectName);
2954 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
2955 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
2956 if (SegName != "__OBJC" && SectName != "__cstring")
2959 if (Address >= SectAddress && Address < SectAddress + SectSize) {
2960 S = (*(info->Sections))[SectIdx];
2961 offset = Address - SectAddress;
2962 left = SectSize - offset;
2963 StringRef SectContents;
2964 ((*(info->Sections))[SectIdx]).getContents(SectContents);
2965 return SectContents.data() + offset;
2971 static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
2972 uint32_t &left, SectionRef &S,
2973 DisassembleInfo *info,
2974 bool objc_only = false) {
2975 return get_pointer_64(Address, offset, left, S, info, objc_only);
2978 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of
2979 // the symbol indirectly through n_value. Based on the relocation information
2980 // for the specified section offset in the specified section reference.
2981 // If no relocation information is found and a non-zero ReferenceValue for the
2982 // symbol is passed, look up that address in the info's AddrMap.
2983 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
2984 DisassembleInfo *info, uint64_t &n_value,
2985 uint64_t ReferenceValue = 0) {
2990 // See if there is an external relocation entry at the sect_offset.
2991 bool reloc_found = false;
2993 MachO::any_relocation_info RE;
2994 bool isExtern = false;
2996 for (const RelocationRef &Reloc : S.relocations()) {
2997 uint64_t RelocOffset = Reloc.getOffset();
2998 if (RelocOffset == sect_offset) {
2999 Rel = Reloc.getRawDataRefImpl();
3000 RE = info->O->getRelocation(Rel);
3001 if (info->O->isRelocationScattered(RE))
3003 isExtern = info->O->getPlainRelocationExternal(RE);
3005 symbol_iterator RelocSym = Reloc.getSymbol();
3012 // If there is an external relocation entry for a symbol in this section
3013 // at this section_offset then use that symbol's value for the n_value
3014 // and return its name.
3015 const char *SymbolName = nullptr;
3016 if (reloc_found && isExtern) {
3017 n_value = Symbol.getValue();
3018 Expected<StringRef> NameOrError = Symbol.getName();
3020 report_error(info->O->getFileName(), NameOrError.takeError());
3021 StringRef Name = *NameOrError;
3022 if (!Name.empty()) {
3023 SymbolName = Name.data();
3028 // TODO: For fully linked images, look through the external relocation
3029 // entries off the dynamic symtab command. For these the r_offset is from the
3030 // start of the first writeable segment in the Mach-O file. So the offset
3031 // to this section from that segment is passed to this routine by the caller,
3032 // as the database_offset. Which is the difference of the section's starting
3033 // address and the first writable segment.
3035 // NOTE: need add passing the database_offset to this routine.
3037 // We did not find an external relocation entry so look up the ReferenceValue
3038 // as an address of a symbol and if found return that symbol's name.
3039 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
3044 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
3045 DisassembleInfo *info,
3046 uint32_t ReferenceValue) {
3048 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
3051 // These are structs in the Objective-C meta data and read to produce the
3052 // comments for disassembly. While these are part of the ABI they are no
3053 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h
3056 // The cfstring object in a 64-bit Mach-O file.
3057 struct cfstring64_t {
3058 uint64_t isa; // class64_t * (64-bit pointer)
3059 uint64_t flags; // flag bits
3060 uint64_t characters; // char * (64-bit pointer)
3061 uint64_t length; // number of non-NULL characters in above
3064 // The class object in a 64-bit Mach-O file.
3066 uint64_t isa; // class64_t * (64-bit pointer)
3067 uint64_t superclass; // class64_t * (64-bit pointer)
3068 uint64_t cache; // Cache (64-bit pointer)
3069 uint64_t vtable; // IMP * (64-bit pointer)
3070 uint64_t data; // class_ro64_t * (64-bit pointer)
3074 uint32_t isa; /* class32_t * (32-bit pointer) */
3075 uint32_t superclass; /* class32_t * (32-bit pointer) */
3076 uint32_t cache; /* Cache (32-bit pointer) */
3077 uint32_t vtable; /* IMP * (32-bit pointer) */
3078 uint32_t data; /* class_ro32_t * (32-bit pointer) */
3081 struct class_ro64_t {
3083 uint32_t instanceStart;
3084 uint32_t instanceSize;
3086 uint64_t ivarLayout; // const uint8_t * (64-bit pointer)
3087 uint64_t name; // const char * (64-bit pointer)
3088 uint64_t baseMethods; // const method_list_t * (64-bit pointer)
3089 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer)
3090 uint64_t ivars; // const ivar_list_t * (64-bit pointer)
3091 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
3092 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
3095 struct class_ro32_t {
3097 uint32_t instanceStart;
3098 uint32_t instanceSize;
3099 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */
3100 uint32_t name; /* const char * (32-bit pointer) */
3101 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */
3102 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */
3103 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */
3104 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
3105 uint32_t baseProperties; /* const struct objc_property_list *
3109 /* Values for class_ro{64,32}_t->flags */
3110 #define RO_META (1 << 0)
3111 #define RO_ROOT (1 << 1)
3112 #define RO_HAS_CXX_STRUCTORS (1 << 2)
3114 struct method_list64_t {
3117 /* struct method64_t first; These structures follow inline */
3120 struct method_list32_t {
3123 /* struct method32_t first; These structures follow inline */
3127 uint64_t name; /* SEL (64-bit pointer) */
3128 uint64_t types; /* const char * (64-bit pointer) */
3129 uint64_t imp; /* IMP (64-bit pointer) */
3133 uint32_t name; /* SEL (32-bit pointer) */
3134 uint32_t types; /* const char * (32-bit pointer) */
3135 uint32_t imp; /* IMP (32-bit pointer) */
3138 struct protocol_list64_t {
3139 uint64_t count; /* uintptr_t (a 64-bit value) */
3140 /* struct protocol64_t * list[0]; These pointers follow inline */
3143 struct protocol_list32_t {
3144 uint32_t count; /* uintptr_t (a 32-bit value) */
3145 /* struct protocol32_t * list[0]; These pointers follow inline */
3148 struct protocol64_t {
3149 uint64_t isa; /* id * (64-bit pointer) */
3150 uint64_t name; /* const char * (64-bit pointer) */
3151 uint64_t protocols; /* struct protocol_list64_t *
3153 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */
3154 uint64_t classMethods; /* method_list_t * (64-bit pointer) */
3155 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
3156 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */
3157 uint64_t instanceProperties; /* struct objc_property_list *
3161 struct protocol32_t {
3162 uint32_t isa; /* id * (32-bit pointer) */
3163 uint32_t name; /* const char * (32-bit pointer) */
3164 uint32_t protocols; /* struct protocol_list_t *
3166 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */
3167 uint32_t classMethods; /* method_list_t * (32-bit pointer) */
3168 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
3169 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */
3170 uint32_t instanceProperties; /* struct objc_property_list *
3174 struct ivar_list64_t {
3177 /* struct ivar64_t first; These structures follow inline */
3180 struct ivar_list32_t {
3183 /* struct ivar32_t first; These structures follow inline */
3187 uint64_t offset; /* uintptr_t * (64-bit pointer) */
3188 uint64_t name; /* const char * (64-bit pointer) */
3189 uint64_t type; /* const char * (64-bit pointer) */
3195 uint32_t offset; /* uintptr_t * (32-bit pointer) */
3196 uint32_t name; /* const char * (32-bit pointer) */
3197 uint32_t type; /* const char * (32-bit pointer) */
3202 struct objc_property_list64 {
3205 /* struct objc_property64 first; These structures follow inline */
3208 struct objc_property_list32 {
3211 /* struct objc_property32 first; These structures follow inline */
3214 struct objc_property64 {
3215 uint64_t name; /* const char * (64-bit pointer) */
3216 uint64_t attributes; /* const char * (64-bit pointer) */
3219 struct objc_property32 {
3220 uint32_t name; /* const char * (32-bit pointer) */
3221 uint32_t attributes; /* const char * (32-bit pointer) */
3224 struct category64_t {
3225 uint64_t name; /* const char * (64-bit pointer) */
3226 uint64_t cls; /* struct class_t * (64-bit pointer) */
3227 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */
3228 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */
3229 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */
3230 uint64_t instanceProperties; /* struct objc_property_list *
3234 struct category32_t {
3235 uint32_t name; /* const char * (32-bit pointer) */
3236 uint32_t cls; /* struct class_t * (32-bit pointer) */
3237 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */
3238 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */
3239 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */
3240 uint32_t instanceProperties; /* struct objc_property_list *
3244 struct objc_image_info64 {
3248 struct objc_image_info32 {
3252 struct imageInfo_t {
3256 /* masks for objc_image_info.flags */
3257 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
3258 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
3259 #define OBJC_IMAGE_IS_SIMULATED (1 << 5)
3260 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)
3262 struct message_ref64 {
3263 uint64_t imp; /* IMP (64-bit pointer) */
3264 uint64_t sel; /* SEL (64-bit pointer) */
3267 struct message_ref32 {
3268 uint32_t imp; /* IMP (32-bit pointer) */
3269 uint32_t sel; /* SEL (32-bit pointer) */
3272 // Objective-C 1 (32-bit only) meta data structs.
3274 struct objc_module_t {
3277 uint32_t name; /* char * (32-bit pointer) */
3278 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
3281 struct objc_symtab_t {
3282 uint32_t sel_ref_cnt;
3283 uint32_t refs; /* SEL * (32-bit pointer) */
3284 uint16_t cls_def_cnt;
3285 uint16_t cat_def_cnt;
3286 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */
3289 struct objc_class_t {
3290 uint32_t isa; /* struct objc_class * (32-bit pointer) */
3291 uint32_t super_class; /* struct objc_class * (32-bit pointer) */
3292 uint32_t name; /* const char * (32-bit pointer) */
3295 int32_t instance_size;
3296 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */
3297 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
3298 uint32_t cache; /* struct objc_cache * (32-bit pointer) */
3299 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */
3302 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
3303 // class is not a metaclass
3304 #define CLS_CLASS 0x1
3305 // class is a metaclass
3306 #define CLS_META 0x2
3308 struct objc_category_t {
3309 uint32_t category_name; /* char * (32-bit pointer) */
3310 uint32_t class_name; /* char * (32-bit pointer) */
3311 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
3312 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */
3313 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */
3316 struct objc_ivar_t {
3317 uint32_t ivar_name; /* char * (32-bit pointer) */
3318 uint32_t ivar_type; /* char * (32-bit pointer) */
3319 int32_t ivar_offset;
3322 struct objc_ivar_list_t {
3324 // struct objc_ivar_t ivar_list[1]; /* variable length structure */
3327 struct objc_method_list_t {
3328 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
3329 int32_t method_count;
3330 // struct objc_method_t method_list[1]; /* variable length structure */
3333 struct objc_method_t {
3334 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */
3335 uint32_t method_types; /* char * (32-bit pointer) */
3336 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
3340 struct objc_protocol_list_t {
3341 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
3343 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t *
3344 // (32-bit pointer) */
3347 struct objc_protocol_t {
3348 uint32_t isa; /* struct objc_class * (32-bit pointer) */
3349 uint32_t protocol_name; /* char * (32-bit pointer) */
3350 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */
3351 uint32_t instance_methods; /* struct objc_method_description_list *
3353 uint32_t class_methods; /* struct objc_method_description_list *
3357 struct objc_method_description_list_t {
3359 // struct objc_method_description_t list[1];
3362 struct objc_method_description_t {
3363 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */
3364 uint32_t types; /* char * (32-bit pointer) */
3367 inline void swapStruct(struct cfstring64_t &cfs) {
3368 sys::swapByteOrder(cfs.isa);
3369 sys::swapByteOrder(cfs.flags);
3370 sys::swapByteOrder(cfs.characters);
3371 sys::swapByteOrder(cfs.length);
3374 inline void swapStruct(struct class64_t &c) {
3375 sys::swapByteOrder(c.isa);
3376 sys::swapByteOrder(c.superclass);
3377 sys::swapByteOrder(c.cache);
3378 sys::swapByteOrder(c.vtable);
3379 sys::swapByteOrder(c.data);
3382 inline void swapStruct(struct class32_t &c) {
3383 sys::swapByteOrder(c.isa);
3384 sys::swapByteOrder(c.superclass);
3385 sys::swapByteOrder(c.cache);
3386 sys::swapByteOrder(c.vtable);
3387 sys::swapByteOrder(c.data);
3390 inline void swapStruct(struct class_ro64_t &cro) {
3391 sys::swapByteOrder(cro.flags);
3392 sys::swapByteOrder(cro.instanceStart);
3393 sys::swapByteOrder(cro.instanceSize);
3394 sys::swapByteOrder(cro.reserved);
3395 sys::swapByteOrder(cro.ivarLayout);
3396 sys::swapByteOrder(cro.name);
3397 sys::swapByteOrder(cro.baseMethods);
3398 sys::swapByteOrder(cro.baseProtocols);
3399 sys::swapByteOrder(cro.ivars);
3400 sys::swapByteOrder(cro.weakIvarLayout);
3401 sys::swapByteOrder(cro.baseProperties);
3404 inline void swapStruct(struct class_ro32_t &cro) {
3405 sys::swapByteOrder(cro.flags);
3406 sys::swapByteOrder(cro.instanceStart);
3407 sys::swapByteOrder(cro.instanceSize);
3408 sys::swapByteOrder(cro.ivarLayout);
3409 sys::swapByteOrder(cro.name);
3410 sys::swapByteOrder(cro.baseMethods);
3411 sys::swapByteOrder(cro.baseProtocols);
3412 sys::swapByteOrder(cro.ivars);
3413 sys::swapByteOrder(cro.weakIvarLayout);
3414 sys::swapByteOrder(cro.baseProperties);
3417 inline void swapStruct(struct method_list64_t &ml) {
3418 sys::swapByteOrder(ml.entsize);
3419 sys::swapByteOrder(ml.count);
3422 inline void swapStruct(struct method_list32_t &ml) {
3423 sys::swapByteOrder(ml.entsize);
3424 sys::swapByteOrder(ml.count);
3427 inline void swapStruct(struct method64_t &m) {
3428 sys::swapByteOrder(m.name);
3429 sys::swapByteOrder(m.types);
3430 sys::swapByteOrder(m.imp);
3433 inline void swapStruct(struct method32_t &m) {
3434 sys::swapByteOrder(m.name);
3435 sys::swapByteOrder(m.types);
3436 sys::swapByteOrder(m.imp);
3439 inline void swapStruct(struct protocol_list64_t &pl) {
3440 sys::swapByteOrder(pl.count);
3443 inline void swapStruct(struct protocol_list32_t &pl) {
3444 sys::swapByteOrder(pl.count);
3447 inline void swapStruct(struct protocol64_t &p) {
3448 sys::swapByteOrder(p.isa);
3449 sys::swapByteOrder(p.name);
3450 sys::swapByteOrder(p.protocols);
3451 sys::swapByteOrder(p.instanceMethods);
3452 sys::swapByteOrder(p.classMethods);
3453 sys::swapByteOrder(p.optionalInstanceMethods);
3454 sys::swapByteOrder(p.optionalClassMethods);
3455 sys::swapByteOrder(p.instanceProperties);
3458 inline void swapStruct(struct protocol32_t &p) {
3459 sys::swapByteOrder(p.isa);
3460 sys::swapByteOrder(p.name);
3461 sys::swapByteOrder(p.protocols);
3462 sys::swapByteOrder(p.instanceMethods);
3463 sys::swapByteOrder(p.classMethods);
3464 sys::swapByteOrder(p.optionalInstanceMethods);
3465 sys::swapByteOrder(p.optionalClassMethods);
3466 sys::swapByteOrder(p.instanceProperties);
3469 inline void swapStruct(struct ivar_list64_t &il) {
3470 sys::swapByteOrder(il.entsize);
3471 sys::swapByteOrder(il.count);
3474 inline void swapStruct(struct ivar_list32_t &il) {
3475 sys::swapByteOrder(il.entsize);
3476 sys::swapByteOrder(il.count);
3479 inline void swapStruct(struct ivar64_t &i) {
3480 sys::swapByteOrder(i.offset);
3481 sys::swapByteOrder(i.name);
3482 sys::swapByteOrder(i.type);
3483 sys::swapByteOrder(i.alignment);
3484 sys::swapByteOrder(i.size);
3487 inline void swapStruct(struct ivar32_t &i) {
3488 sys::swapByteOrder(i.offset);
3489 sys::swapByteOrder(i.name);
3490 sys::swapByteOrder(i.type);
3491 sys::swapByteOrder(i.alignment);
3492 sys::swapByteOrder(i.size);
3495 inline void swapStruct(struct objc_property_list64 &pl) {
3496 sys::swapByteOrder(pl.entsize);
3497 sys::swapByteOrder(pl.count);
3500 inline void swapStruct(struct objc_property_list32 &pl) {
3501 sys::swapByteOrder(pl.entsize);
3502 sys::swapByteOrder(pl.count);
3505 inline void swapStruct(struct objc_property64 &op) {
3506 sys::swapByteOrder(op.name);
3507 sys::swapByteOrder(op.attributes);
3510 inline void swapStruct(struct objc_property32 &op) {
3511 sys::swapByteOrder(op.name);
3512 sys::swapByteOrder(op.attributes);
3515 inline void swapStruct(struct category64_t &c) {
3516 sys::swapByteOrder(c.name);
3517 sys::swapByteOrder(c.cls);
3518 sys::swapByteOrder(c.instanceMethods);
3519 sys::swapByteOrder(c.classMethods);
3520 sys::swapByteOrder(c.protocols);
3521 sys::swapByteOrder(c.instanceProperties);
3524 inline void swapStruct(struct category32_t &c) {
3525 sys::swapByteOrder(c.name);
3526 sys::swapByteOrder(c.cls);
3527 sys::swapByteOrder(c.instanceMethods);
3528 sys::swapByteOrder(c.classMethods);
3529 sys::swapByteOrder(c.protocols);
3530 sys::swapByteOrder(c.instanceProperties);
3533 inline void swapStruct(struct objc_image_info64 &o) {
3534 sys::swapByteOrder(o.version);
3535 sys::swapByteOrder(o.flags);
3538 inline void swapStruct(struct objc_image_info32 &o) {
3539 sys::swapByteOrder(o.version);
3540 sys::swapByteOrder(o.flags);
3543 inline void swapStruct(struct imageInfo_t &o) {
3544 sys::swapByteOrder(o.version);
3545 sys::swapByteOrder(o.flags);
3548 inline void swapStruct(struct message_ref64 &mr) {
3549 sys::swapByteOrder(mr.imp);
3550 sys::swapByteOrder(mr.sel);
3553 inline void swapStruct(struct message_ref32 &mr) {
3554 sys::swapByteOrder(mr.imp);
3555 sys::swapByteOrder(mr.sel);
3558 inline void swapStruct(struct objc_module_t &module) {
3559 sys::swapByteOrder(module.version);
3560 sys::swapByteOrder(module.size);
3561 sys::swapByteOrder(module.name);
3562 sys::swapByteOrder(module.symtab);
3565 inline void swapStruct(struct objc_symtab_t &symtab) {
3566 sys::swapByteOrder(symtab.sel_ref_cnt);
3567 sys::swapByteOrder(symtab.refs);
3568 sys::swapByteOrder(symtab.cls_def_cnt);
3569 sys::swapByteOrder(symtab.cat_def_cnt);
3572 inline void swapStruct(struct objc_class_t &objc_class) {
3573 sys::swapByteOrder(objc_class.isa);
3574 sys::swapByteOrder(objc_class.super_class);
3575 sys::swapByteOrder(objc_class.name);
3576 sys::swapByteOrder(objc_class.version);
3577 sys::swapByteOrder(objc_class.info);
3578 sys::swapByteOrder(objc_class.instance_size);
3579 sys::swapByteOrder(objc_class.ivars);
3580 sys::swapByteOrder(objc_class.methodLists);
3581 sys::swapByteOrder(objc_class.cache);
3582 sys::swapByteOrder(objc_class.protocols);
3585 inline void swapStruct(struct objc_category_t &objc_category) {
3586 sys::swapByteOrder(objc_category.category_name);
3587 sys::swapByteOrder(objc_category.class_name);
3588 sys::swapByteOrder(objc_category.instance_methods);
3589 sys::swapByteOrder(objc_category.class_methods);
3590 sys::swapByteOrder(objc_category.protocols);
3593 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
3594 sys::swapByteOrder(objc_ivar_list.ivar_count);
3597 inline void swapStruct(struct objc_ivar_t &objc_ivar) {
3598 sys::swapByteOrder(objc_ivar.ivar_name);
3599 sys::swapByteOrder(objc_ivar.ivar_type);
3600 sys::swapByteOrder(objc_ivar.ivar_offset);
3603 inline void swapStruct(struct objc_method_list_t &method_list) {
3604 sys::swapByteOrder(method_list.obsolete);
3605 sys::swapByteOrder(method_list.method_count);
3608 inline void swapStruct(struct objc_method_t &method) {
3609 sys::swapByteOrder(method.method_name);
3610 sys::swapByteOrder(method.method_types);
3611 sys::swapByteOrder(method.method_imp);
3614 inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
3615 sys::swapByteOrder(protocol_list.next);
3616 sys::swapByteOrder(protocol_list.count);
3619 inline void swapStruct(struct objc_protocol_t &protocol) {
3620 sys::swapByteOrder(protocol.isa);
3621 sys::swapByteOrder(protocol.protocol_name);
3622 sys::swapByteOrder(protocol.protocol_list);
3623 sys::swapByteOrder(protocol.instance_methods);
3624 sys::swapByteOrder(protocol.class_methods);
3627 inline void swapStruct(struct objc_method_description_list_t &mdl) {
3628 sys::swapByteOrder(mdl.count);
3631 inline void swapStruct(struct objc_method_description_t &md) {
3632 sys::swapByteOrder(md.name);
3633 sys::swapByteOrder(md.types);
3636 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
3637 struct DisassembleInfo *info);
3639 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
3640 // to an Objective-C class and returns the class name. It is also passed the
3641 // address of the pointer, so when the pointer is zero as it can be in an .o
3642 // file, that is used to look for an external relocation entry with a symbol
3644 static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
3645 uint64_t ReferenceValue,
3646 struct DisassembleInfo *info) {
3648 uint32_t offset, left;
3651 // The pointer_value can be 0 in an object file and have a relocation
3652 // entry for the class symbol at the ReferenceValue (the address of the
3654 if (pointer_value == 0) {
3655 r = get_pointer_64(ReferenceValue, offset, left, S, info);
3656 if (r == nullptr || left < sizeof(uint64_t))
3659 const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3660 if (symbol_name == nullptr)
3662 const char *class_name = strrchr(symbol_name, '$');
3663 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
3664 return class_name + 2;
3669 // The case were the pointer_value is non-zero and points to a class defined
3670 // in this Mach-O file.
3671 r = get_pointer_64(pointer_value, offset, left, S, info);
3672 if (r == nullptr || left < sizeof(struct class64_t))
3675 memcpy(&c, r, sizeof(struct class64_t));
3676 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3680 r = get_pointer_64(c.data, offset, left, S, info);
3681 if (r == nullptr || left < sizeof(struct class_ro64_t))
3683 struct class_ro64_t cro;
3684 memcpy(&cro, r, sizeof(struct class_ro64_t));
3685 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3689 const char *name = get_pointer_64(cro.name, offset, left, S, info);
3693 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a
3694 // pointer to a cfstring and returns its name or nullptr.
3695 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
3696 struct DisassembleInfo *info) {
3697 const char *r, *name;
3698 uint32_t offset, left;
3700 struct cfstring64_t cfs;
3701 uint64_t cfs_characters;
3703 r = get_pointer_64(ReferenceValue, offset, left, S, info);
3704 if (r == nullptr || left < sizeof(struct cfstring64_t))
3706 memcpy(&cfs, r, sizeof(struct cfstring64_t));
3707 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3709 if (cfs.characters == 0) {
3711 const char *symbol_name = get_symbol_64(
3712 offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
3713 if (symbol_name == nullptr)
3715 cfs_characters = n_value;
3717 cfs_characters = cfs.characters;
3718 name = get_pointer_64(cfs_characters, offset, left, S, info);
3723 // get_objc2_64bit_selref() is used for disassembly and is passed a the address
3724 // of a pointer to an Objective-C selector reference when the pointer value is
3725 // zero as in a .o file and is likely to have a external relocation entry with
3726 // who's symbol's n_value is the real pointer to the selector name. If that is
3727 // the case the real pointer to the selector name is returned else 0 is
3729 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
3730 struct DisassembleInfo *info) {
3731 uint32_t offset, left;
3734 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
3735 if (r == nullptr || left < sizeof(uint64_t))
3738 const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3739 if (symbol_name == nullptr)
3744 static const SectionRef get_section(MachOObjectFile *O, const char *segname,
3745 const char *sectname) {
3746 for (const SectionRef &Section : O->sections()) {
3748 Section.getName(SectName);
3749 DataRefImpl Ref = Section.getRawDataRefImpl();
3750 StringRef SegName = O->getSectionFinalSegmentName(Ref);
3751 if (SegName == segname && SectName == sectname)
3754 return SectionRef();
3758 walk_pointer_list_64(const char *listname, const SectionRef S,
3759 MachOObjectFile *O, struct DisassembleInfo *info,
3760 void (*func)(uint64_t, struct DisassembleInfo *info)) {
3761 if (S == SectionRef())
3765 S.getName(SectName);
3766 DataRefImpl Ref = S.getRawDataRefImpl();
3767 StringRef SegName = O->getSectionFinalSegmentName(Ref);
3768 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3771 S.getContents(BytesStr);
3772 const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3774 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
3775 uint32_t left = S.getSize() - i;
3776 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
3778 memcpy(&p, Contents + i, size);
3779 if (i + sizeof(uint64_t) > S.getSize())
3780 outs() << listname << " list pointer extends past end of (" << SegName
3781 << "," << SectName << ") section\n";
3782 outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
3784 if (O->isLittleEndian() != sys::IsLittleEndianHost)
3785 sys::swapByteOrder(p);
3787 uint64_t n_value = 0;
3788 const char *name = get_symbol_64(i, S, info, n_value, p);
3789 if (name == nullptr)
3790 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
3793 outs() << format("0x%" PRIx64, n_value);
3795 outs() << " + " << format("0x%" PRIx64, p);
3797 outs() << format("0x%" PRIx64, p);
3798 if (name != nullptr)
3799 outs() << " " << name;
3809 walk_pointer_list_32(const char *listname, const SectionRef S,
3810 MachOObjectFile *O, struct DisassembleInfo *info,
3811 void (*func)(uint32_t, struct DisassembleInfo *info)) {
3812 if (S == SectionRef())
3816 S.getName(SectName);
3817 DataRefImpl Ref = S.getRawDataRefImpl();
3818 StringRef SegName = O->getSectionFinalSegmentName(Ref);
3819 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3822 S.getContents(BytesStr);
3823 const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3825 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
3826 uint32_t left = S.getSize() - i;
3827 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
3829 memcpy(&p, Contents + i, size);
3830 if (i + sizeof(uint32_t) > S.getSize())
3831 outs() << listname << " list pointer extends past end of (" << SegName
3832 << "," << SectName << ") section\n";
3833 uint32_t Address = S.getAddress() + i;
3834 outs() << format("%08" PRIx32, Address) << " ";
3836 if (O->isLittleEndian() != sys::IsLittleEndianHost)
3837 sys::swapByteOrder(p);
3838 outs() << format("0x%" PRIx32, p);
3840 const char *name = get_symbol_32(i, S, info, p);
3841 if (name != nullptr)
3842 outs() << " " << name;
3850 static void print_layout_map(const char *layout_map, uint32_t left) {
3851 if (layout_map == nullptr)
3853 outs() << " layout map: ";
3855 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
3858 } while (*layout_map != '\0' && left != 0);
3862 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
3863 uint32_t offset, left;
3865 const char *layout_map;
3869 layout_map = get_pointer_64(p, offset, left, S, info);
3870 print_layout_map(layout_map, left);
3873 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
3874 uint32_t offset, left;
3876 const char *layout_map;
3880 layout_map = get_pointer_32(p, offset, left, S, info);
3881 print_layout_map(layout_map, left);
3884 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
3885 const char *indent) {
3886 struct method_list64_t ml;
3887 struct method64_t m;
3889 uint32_t offset, xoffset, left, i;
3891 const char *name, *sym_name;
3894 r = get_pointer_64(p, offset, left, S, info);
3897 memset(&ml, '\0', sizeof(struct method_list64_t));
3898 if (left < sizeof(struct method_list64_t)) {
3899 memcpy(&ml, r, left);
3900 outs() << " (method_list_t entends past the end of the section)\n";
3902 memcpy(&ml, r, sizeof(struct method_list64_t));
3903 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3905 outs() << indent << "\t\t entsize " << ml.entsize << "\n";
3906 outs() << indent << "\t\t count " << ml.count << "\n";
3908 p += sizeof(struct method_list64_t);
3909 offset += sizeof(struct method_list64_t);
3910 for (i = 0; i < ml.count; i++) {
3911 r = get_pointer_64(p, offset, left, S, info);
3914 memset(&m, '\0', sizeof(struct method64_t));
3915 if (left < sizeof(struct method64_t)) {
3916 memcpy(&m, r, left);
3917 outs() << indent << " (method_t extends past the end of the section)\n";
3919 memcpy(&m, r, sizeof(struct method64_t));
3920 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3923 outs() << indent << "\t\t name ";
3924 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
3925 info, n_value, m.name);
3927 if (info->verbose && sym_name != nullptr)
3930 outs() << format("0x%" PRIx64, n_value);
3932 outs() << " + " << format("0x%" PRIx64, m.name);
3934 outs() << format("0x%" PRIx64, m.name);
3935 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
3936 if (name != nullptr)
3937 outs() << format(" %.*s", left, name);
3940 outs() << indent << "\t\t types ";
3941 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
3942 info, n_value, m.types);
3944 if (info->verbose && sym_name != nullptr)
3947 outs() << format("0x%" PRIx64, n_value);
3949 outs() << " + " << format("0x%" PRIx64, m.types);
3951 outs() << format("0x%" PRIx64, m.types);
3952 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
3953 if (name != nullptr)
3954 outs() << format(" %.*s", left, name);
3957 outs() << indent << "\t\t imp ";
3958 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
3960 if (info->verbose && name == nullptr) {
3962 outs() << format("0x%" PRIx64, n_value) << " ";
3964 outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
3966 outs() << format("0x%" PRIx64, m.imp) << " ";
3968 if (name != nullptr)
3972 p += sizeof(struct method64_t);
3973 offset += sizeof(struct method64_t);
3977 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
3978 const char *indent) {
3979 struct method_list32_t ml;
3980 struct method32_t m;
3981 const char *r, *name;
3982 uint32_t offset, xoffset, left, i;
3985 r = get_pointer_32(p, offset, left, S, info);
3988 memset(&ml, '\0', sizeof(struct method_list32_t));
3989 if (left < sizeof(struct method_list32_t)) {
3990 memcpy(&ml, r, left);
3991 outs() << " (method_list_t entends past the end of the section)\n";
3993 memcpy(&ml, r, sizeof(struct method_list32_t));
3994 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3996 outs() << indent << "\t\t entsize " << ml.entsize << "\n";
3997 outs() << indent << "\t\t count " << ml.count << "\n";
3999 p += sizeof(struct method_list32_t);
4000 offset += sizeof(struct method_list32_t);
4001 for (i = 0; i < ml.count; i++) {
4002 r = get_pointer_32(p, offset, left, S, info);
4005 memset(&m, '\0', sizeof(struct method32_t));
4006 if (left < sizeof(struct method32_t)) {
4007 memcpy(&ml, r, left);
4008 outs() << indent << " (method_t entends past the end of the section)\n";
4010 memcpy(&m, r, sizeof(struct method32_t));
4011 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4014 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name);
4015 name = get_pointer_32(m.name, xoffset, left, xS, info);
4016 if (name != nullptr)
4017 outs() << format(" %.*s", left, name);
4020 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types);
4021 name = get_pointer_32(m.types, xoffset, left, xS, info);
4022 if (name != nullptr)
4023 outs() << format(" %.*s", left, name);
4026 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp);
4027 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
4029 if (name != nullptr)
4030 outs() << " " << name;
4033 p += sizeof(struct method32_t);
4034 offset += sizeof(struct method32_t);
4038 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
4039 uint32_t offset, left, xleft;
4041 struct objc_method_list_t method_list;
4042 struct objc_method_t method;
4043 const char *r, *methods, *name, *SymbolName;
4046 r = get_pointer_32(p, offset, left, S, info, true);
4051 if (left > sizeof(struct objc_method_list_t)) {
4052 memcpy(&method_list, r, sizeof(struct objc_method_list_t));
4054 outs() << "\t\t objc_method_list extends past end of the section\n";
4055 memset(&method_list, '\0', sizeof(struct objc_method_list_t));
4056 memcpy(&method_list, r, left);
4058 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4059 swapStruct(method_list);
4061 outs() << "\t\t obsolete "
4062 << format("0x%08" PRIx32, method_list.obsolete) << "\n";
4063 outs() << "\t\t method_count " << method_list.method_count << "\n";
4065 methods = r + sizeof(struct objc_method_list_t);
4066 for (i = 0; i < method_list.method_count; i++) {
4067 if ((i + 1) * sizeof(struct objc_method_t) > left) {
4068 outs() << "\t\t remaining method's extend past the of the section\n";
4071 memcpy(&method, methods + i * sizeof(struct objc_method_t),
4072 sizeof(struct objc_method_t));
4073 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4076 outs() << "\t\t method_name "
4077 << format("0x%08" PRIx32, method.method_name);
4078 if (info->verbose) {
4079 name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
4080 if (name != nullptr)
4081 outs() << format(" %.*s", xleft, name);
4083 outs() << " (not in an __OBJC section)";
4087 outs() << "\t\t method_types "
4088 << format("0x%08" PRIx32, method.method_types);
4089 if (info->verbose) {
4090 name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
4091 if (name != nullptr)
4092 outs() << format(" %.*s", xleft, name);
4094 outs() << " (not in an __OBJC section)";
4098 outs() << "\t\t method_imp "
4099 << format("0x%08" PRIx32, method.method_imp) << " ";
4100 if (info->verbose) {
4101 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
4102 if (SymbolName != nullptr)
4103 outs() << SymbolName;
4110 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
4111 struct protocol_list64_t pl;
4112 uint64_t q, n_value;
4113 struct protocol64_t pc;
4115 uint32_t offset, xoffset, left, i;
4117 const char *name, *sym_name;
4119 r = get_pointer_64(p, offset, left, S, info);
4122 memset(&pl, '\0', sizeof(struct protocol_list64_t));
4123 if (left < sizeof(struct protocol_list64_t)) {
4124 memcpy(&pl, r, left);
4125 outs() << " (protocol_list_t entends past the end of the section)\n";
4127 memcpy(&pl, r, sizeof(struct protocol_list64_t));
4128 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4130 outs() << " count " << pl.count << "\n";
4132 p += sizeof(struct protocol_list64_t);
4133 offset += sizeof(struct protocol_list64_t);
4134 for (i = 0; i < pl.count; i++) {
4135 r = get_pointer_64(p, offset, left, S, info);
4139 if (left < sizeof(uint64_t)) {
4140 memcpy(&q, r, left);
4141 outs() << " (protocol_t * entends past the end of the section)\n";
4143 memcpy(&q, r, sizeof(uint64_t));
4144 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4145 sys::swapByteOrder(q);
4147 outs() << "\t\t list[" << i << "] ";
4148 sym_name = get_symbol_64(offset, S, info, n_value, q);
4150 if (info->verbose && sym_name != nullptr)
4153 outs() << format("0x%" PRIx64, n_value);
4155 outs() << " + " << format("0x%" PRIx64, q);
4157 outs() << format("0x%" PRIx64, q);
4158 outs() << " (struct protocol_t *)\n";
4160 r = get_pointer_64(q + n_value, offset, left, S, info);
4163 memset(&pc, '\0', sizeof(struct protocol64_t));
4164 if (left < sizeof(struct protocol64_t)) {
4165 memcpy(&pc, r, left);
4166 outs() << " (protocol_t entends past the end of the section)\n";
4168 memcpy(&pc, r, sizeof(struct protocol64_t));
4169 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4172 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n";
4174 outs() << "\t\t\t name ";
4175 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
4176 info, n_value, pc.name);
4178 if (info->verbose && sym_name != nullptr)
4181 outs() << format("0x%" PRIx64, n_value);
4183 outs() << " + " << format("0x%" PRIx64, pc.name);
4185 outs() << format("0x%" PRIx64, pc.name);
4186 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
4187 if (name != nullptr)
4188 outs() << format(" %.*s", left, name);
4191 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
4193 outs() << "\t\t instanceMethods ";
4195 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
4196 S, info, n_value, pc.instanceMethods);
4198 if (info->verbose && sym_name != nullptr)
4201 outs() << format("0x%" PRIx64, n_value);
4202 if (pc.instanceMethods != 0)
4203 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
4205 outs() << format("0x%" PRIx64, pc.instanceMethods);
4206 outs() << " (struct method_list_t *)\n";
4207 if (pc.instanceMethods + n_value != 0)
4208 print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
4210 outs() << "\t\t classMethods ";
4212 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
4213 info, n_value, pc.classMethods);
4215 if (info->verbose && sym_name != nullptr)
4218 outs() << format("0x%" PRIx64, n_value);
4219 if (pc.classMethods != 0)
4220 outs() << " + " << format("0x%" PRIx64, pc.classMethods);
4222 outs() << format("0x%" PRIx64, pc.classMethods);
4223 outs() << " (struct method_list_t *)\n";
4224 if (pc.classMethods + n_value != 0)
4225 print_method_list64_t(pc.classMethods + n_value, info, "\t");
4227 outs() << "\t optionalInstanceMethods "
4228 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
4229 outs() << "\t optionalClassMethods "
4230 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
4231 outs() << "\t instanceProperties "
4232 << format("0x%" PRIx64, pc.instanceProperties) << "\n";
4234 p += sizeof(uint64_t);
4235 offset += sizeof(uint64_t);
4239 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
4240 struct protocol_list32_t pl;
4242 struct protocol32_t pc;
4244 uint32_t offset, xoffset, left, i;
4248 r = get_pointer_32(p, offset, left, S, info);
4251 memset(&pl, '\0', sizeof(struct protocol_list32_t));
4252 if (left < sizeof(struct protocol_list32_t)) {
4253 memcpy(&pl, r, left);
4254 outs() << " (protocol_list_t entends past the end of the section)\n";
4256 memcpy(&pl, r, sizeof(struct protocol_list32_t));
4257 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4259 outs() << " count " << pl.count << "\n";
4261 p += sizeof(struct protocol_list32_t);
4262 offset += sizeof(struct protocol_list32_t);
4263 for (i = 0; i < pl.count; i++) {
4264 r = get_pointer_32(p, offset, left, S, info);
4268 if (left < sizeof(uint32_t)) {
4269 memcpy(&q, r, left);
4270 outs() << " (protocol_t * entends past the end of the section)\n";
4272 memcpy(&q, r, sizeof(uint32_t));
4273 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4274 sys::swapByteOrder(q);
4275 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q)
4276 << " (struct protocol_t *)\n";
4277 r = get_pointer_32(q, offset, left, S, info);
4280 memset(&pc, '\0', sizeof(struct protocol32_t));
4281 if (left < sizeof(struct protocol32_t)) {
4282 memcpy(&pc, r, left);
4283 outs() << " (protocol_t entends past the end of the section)\n";
4285 memcpy(&pc, r, sizeof(struct protocol32_t));
4286 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4288 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n";
4289 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name);
4290 name = get_pointer_32(pc.name, xoffset, left, xS, info);
4291 if (name != nullptr)
4292 outs() << format(" %.*s", left, name);
4294 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
4295 outs() << "\t\t instanceMethods "
4296 << format("0x%" PRIx32, pc.instanceMethods)
4297 << " (struct method_list_t *)\n";
4298 if (pc.instanceMethods != 0)
4299 print_method_list32_t(pc.instanceMethods, info, "\t");
4300 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods)
4301 << " (struct method_list_t *)\n";
4302 if (pc.classMethods != 0)
4303 print_method_list32_t(pc.classMethods, info, "\t");
4304 outs() << "\t optionalInstanceMethods "
4305 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
4306 outs() << "\t optionalClassMethods "
4307 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
4308 outs() << "\t instanceProperties "
4309 << format("0x%" PRIx32, pc.instanceProperties) << "\n";
4310 p += sizeof(uint32_t);
4311 offset += sizeof(uint32_t);
4315 static void print_indent(uint32_t indent) {
4316 for (uint32_t i = 0; i < indent;) {
4317 if (indent - i >= 8) {
4321 for (uint32_t j = i; j < indent; j++)
4328 static bool print_method_description_list(uint32_t p, uint32_t indent,
4329 struct DisassembleInfo *info) {
4330 uint32_t offset, left, xleft;
4332 struct objc_method_description_list_t mdl;
4333 struct objc_method_description_t md;
4334 const char *r, *list, *name;
4337 r = get_pointer_32(p, offset, left, S, info, true);
4342 if (left > sizeof(struct objc_method_description_list_t)) {
4343 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
4345 print_indent(indent);
4346 outs() << " objc_method_description_list extends past end of the section\n";
4347 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
4348 memcpy(&mdl, r, left);
4350 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4353 print_indent(indent);
4354 outs() << " count " << mdl.count << "\n";
4356 list = r + sizeof(struct objc_method_description_list_t);
4357 for (i = 0; i < mdl.count; i++) {
4358 if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
4359 print_indent(indent);
4360 outs() << " remaining list entries extend past the of the section\n";
4363 print_indent(indent);
4364 outs() << " list[" << i << "]\n";
4365 memcpy(&md, list + i * sizeof(struct objc_method_description_t),
4366 sizeof(struct objc_method_description_t));
4367 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4370 print_indent(indent);
4371 outs() << " name " << format("0x%08" PRIx32, md.name);
4372 if (info->verbose) {
4373 name = get_pointer_32(md.name, offset, xleft, S, info, true);
4374 if (name != nullptr)
4375 outs() << format(" %.*s", xleft, name);
4377 outs() << " (not in an __OBJC section)";
4381 print_indent(indent);
4382 outs() << " types " << format("0x%08" PRIx32, md.types);
4383 if (info->verbose) {
4384 name = get_pointer_32(md.types, offset, xleft, S, info, true);
4385 if (name != nullptr)
4386 outs() << format(" %.*s", xleft, name);
4388 outs() << " (not in an __OBJC section)";
4395 static bool print_protocol_list(uint32_t p, uint32_t indent,
4396 struct DisassembleInfo *info);
4398 static bool print_protocol(uint32_t p, uint32_t indent,
4399 struct DisassembleInfo *info) {
4400 uint32_t offset, left;
4402 struct objc_protocol_t protocol;
4403 const char *r, *name;
4405 r = get_pointer_32(p, offset, left, S, info, true);
4410 if (left >= sizeof(struct objc_protocol_t)) {
4411 memcpy(&protocol, r, sizeof(struct objc_protocol_t));
4413 print_indent(indent);
4414 outs() << " Protocol extends past end of the section\n";
4415 memset(&protocol, '\0', sizeof(struct objc_protocol_t));
4416 memcpy(&protocol, r, left);
4418 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4419 swapStruct(protocol);
4421 print_indent(indent);
4422 outs() << " isa " << format("0x%08" PRIx32, protocol.isa)
4425 print_indent(indent);
4426 outs() << " protocol_name "
4427 << format("0x%08" PRIx32, protocol.protocol_name);
4428 if (info->verbose) {
4429 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
4430 if (name != nullptr)
4431 outs() << format(" %.*s", left, name);
4433 outs() << " (not in an __OBJC section)";
4437 print_indent(indent);
4438 outs() << " protocol_list "
4439 << format("0x%08" PRIx32, protocol.protocol_list);
4440 if (print_protocol_list(protocol.protocol_list, indent + 4, info))
4441 outs() << " (not in an __OBJC section)\n";
4443 print_indent(indent);
4444 outs() << " instance_methods "
4445 << format("0x%08" PRIx32, protocol.instance_methods);
4446 if (print_method_description_list(protocol.instance_methods, indent, info))
4447 outs() << " (not in an __OBJC section)\n";
4449 print_indent(indent);
4450 outs() << " class_methods "
4451 << format("0x%08" PRIx32, protocol.class_methods);
4452 if (print_method_description_list(protocol.class_methods, indent, info))
4453 outs() << " (not in an __OBJC section)\n";
4458 static bool print_protocol_list(uint32_t p, uint32_t indent,
4459 struct DisassembleInfo *info) {
4460 uint32_t offset, left, l;
4462 struct objc_protocol_list_t protocol_list;
4463 const char *r, *list;
4466 r = get_pointer_32(p, offset, left, S, info, true);
4471 if (left > sizeof(struct objc_protocol_list_t)) {
4472 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
4474 outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
4475 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
4476 memcpy(&protocol_list, r, left);
4478 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4479 swapStruct(protocol_list);
4481 print_indent(indent);
4482 outs() << " next " << format("0x%08" PRIx32, protocol_list.next)
4484 print_indent(indent);
4485 outs() << " count " << protocol_list.count << "\n";
4487 list = r + sizeof(struct objc_protocol_list_t);
4488 for (i = 0; i < protocol_list.count; i++) {
4489 if ((i + 1) * sizeof(uint32_t) > left) {
4490 outs() << "\t\t remaining list entries extend past the of the section\n";
4493 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
4494 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4495 sys::swapByteOrder(l);
4497 print_indent(indent);
4498 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l);
4499 if (print_protocol(l, indent, info))
4500 outs() << "(not in an __OBJC section)\n";
4505 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
4506 struct ivar_list64_t il;
4509 uint32_t offset, xoffset, left, j;
4511 const char *name, *sym_name, *ivar_offset_p;
4512 uint64_t ivar_offset, n_value;
4514 r = get_pointer_64(p, offset, left, S, info);
4517 memset(&il, '\0', sizeof(struct ivar_list64_t));
4518 if (left < sizeof(struct ivar_list64_t)) {
4519 memcpy(&il, r, left);
4520 outs() << " (ivar_list_t entends past the end of the section)\n";
4522 memcpy(&il, r, sizeof(struct ivar_list64_t));
4523 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4525 outs() << " entsize " << il.entsize << "\n";
4526 outs() << " count " << il.count << "\n";
4528 p += sizeof(struct ivar_list64_t);
4529 offset += sizeof(struct ivar_list64_t);
4530 for (j = 0; j < il.count; j++) {
4531 r = get_pointer_64(p, offset, left, S, info);
4534 memset(&i, '\0', sizeof(struct ivar64_t));
4535 if (left < sizeof(struct ivar64_t)) {
4536 memcpy(&i, r, left);
4537 outs() << " (ivar_t entends past the end of the section)\n";
4539 memcpy(&i, r, sizeof(struct ivar64_t));
4540 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4543 outs() << "\t\t\t offset ";
4544 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
4545 info, n_value, i.offset);
4547 if (info->verbose && sym_name != nullptr)
4550 outs() << format("0x%" PRIx64, n_value);
4552 outs() << " + " << format("0x%" PRIx64, i.offset);
4554 outs() << format("0x%" PRIx64, i.offset);
4555 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
4556 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4557 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4558 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4559 sys::swapByteOrder(ivar_offset);
4560 outs() << " " << ivar_offset << "\n";
4564 outs() << "\t\t\t name ";
4565 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
4568 if (info->verbose && sym_name != nullptr)
4571 outs() << format("0x%" PRIx64, n_value);
4573 outs() << " + " << format("0x%" PRIx64, i.name);
4575 outs() << format("0x%" PRIx64, i.name);
4576 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
4577 if (name != nullptr)
4578 outs() << format(" %.*s", left, name);
4581 outs() << "\t\t\t type ";
4582 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
4584 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
4586 if (info->verbose && sym_name != nullptr)
4589 outs() << format("0x%" PRIx64, n_value);
4591 outs() << " + " << format("0x%" PRIx64, i.type);
4593 outs() << format("0x%" PRIx64, i.type);
4594 if (name != nullptr)
4595 outs() << format(" %.*s", left, name);
4598 outs() << "\t\t\talignment " << i.alignment << "\n";
4599 outs() << "\t\t\t size " << i.size << "\n";
4601 p += sizeof(struct ivar64_t);
4602 offset += sizeof(struct ivar64_t);
4606 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
4607 struct ivar_list32_t il;
4610 uint32_t offset, xoffset, left, j;
4612 const char *name, *ivar_offset_p;
4613 uint32_t ivar_offset;
4615 r = get_pointer_32(p, offset, left, S, info);
4618 memset(&il, '\0', sizeof(struct ivar_list32_t));
4619 if (left < sizeof(struct ivar_list32_t)) {
4620 memcpy(&il, r, left);
4621 outs() << " (ivar_list_t entends past the end of the section)\n";
4623 memcpy(&il, r, sizeof(struct ivar_list32_t));
4624 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4626 outs() << " entsize " << il.entsize << "\n";
4627 outs() << " count " << il.count << "\n";
4629 p += sizeof(struct ivar_list32_t);
4630 offset += sizeof(struct ivar_list32_t);
4631 for (j = 0; j < il.count; j++) {
4632 r = get_pointer_32(p, offset, left, S, info);
4635 memset(&i, '\0', sizeof(struct ivar32_t));
4636 if (left < sizeof(struct ivar32_t)) {
4637 memcpy(&i, r, left);
4638 outs() << " (ivar_t entends past the end of the section)\n";
4640 memcpy(&i, r, sizeof(struct ivar32_t));
4641 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4644 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset);
4645 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
4646 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4647 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4648 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4649 sys::swapByteOrder(ivar_offset);
4650 outs() << " " << ivar_offset << "\n";
4654 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name);
4655 name = get_pointer_32(i.name, xoffset, left, xS, info);
4656 if (name != nullptr)
4657 outs() << format(" %.*s", left, name);
4660 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type);
4661 name = get_pointer_32(i.type, xoffset, left, xS, info);
4662 if (name != nullptr)
4663 outs() << format(" %.*s", left, name);
4666 outs() << "\t\t\talignment " << i.alignment << "\n";
4667 outs() << "\t\t\t size " << i.size << "\n";
4669 p += sizeof(struct ivar32_t);
4670 offset += sizeof(struct ivar32_t);
4674 static void print_objc_property_list64(uint64_t p,
4675 struct DisassembleInfo *info) {
4676 struct objc_property_list64 opl;
4677 struct objc_property64 op;
4679 uint32_t offset, xoffset, left, j;
4681 const char *name, *sym_name;
4684 r = get_pointer_64(p, offset, left, S, info);
4687 memset(&opl, '\0', sizeof(struct objc_property_list64));
4688 if (left < sizeof(struct objc_property_list64)) {
4689 memcpy(&opl, r, left);
4690 outs() << " (objc_property_list entends past the end of the section)\n";
4692 memcpy(&opl, r, sizeof(struct objc_property_list64));
4693 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4695 outs() << " entsize " << opl.entsize << "\n";
4696 outs() << " count " << opl.count << "\n";
4698 p += sizeof(struct objc_property_list64);
4699 offset += sizeof(struct objc_property_list64);
4700 for (j = 0; j < opl.count; j++) {
4701 r = get_pointer_64(p, offset, left, S, info);
4704 memset(&op, '\0', sizeof(struct objc_property64));
4705 if (left < sizeof(struct objc_property64)) {
4706 memcpy(&op, r, left);
4707 outs() << " (objc_property entends past the end of the section)\n";
4709 memcpy(&op, r, sizeof(struct objc_property64));
4710 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4713 outs() << "\t\t\t name ";
4714 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
4715 info, n_value, op.name);
4717 if (info->verbose && sym_name != nullptr)
4720 outs() << format("0x%" PRIx64, n_value);
4722 outs() << " + " << format("0x%" PRIx64, op.name);
4724 outs() << format("0x%" PRIx64, op.name);
4725 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
4726 if (name != nullptr)
4727 outs() << format(" %.*s", left, name);
4730 outs() << "\t\t\tattributes ";
4732 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
4733 info, n_value, op.attributes);
4735 if (info->verbose && sym_name != nullptr)
4738 outs() << format("0x%" PRIx64, n_value);
4739 if (op.attributes != 0)
4740 outs() << " + " << format("0x%" PRIx64, op.attributes);
4742 outs() << format("0x%" PRIx64, op.attributes);
4743 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
4744 if (name != nullptr)
4745 outs() << format(" %.*s", left, name);
4748 p += sizeof(struct objc_property64);
4749 offset += sizeof(struct objc_property64);
4753 static void print_objc_property_list32(uint32_t p,
4754 struct DisassembleInfo *info) {
4755 struct objc_property_list32 opl;
4756 struct objc_property32 op;
4758 uint32_t offset, xoffset, left, j;
4762 r = get_pointer_32(p, offset, left, S, info);
4765 memset(&opl, '\0', sizeof(struct objc_property_list32));
4766 if (left < sizeof(struct objc_property_list32)) {
4767 memcpy(&opl, r, left);
4768 outs() << " (objc_property_list entends past the end of the section)\n";
4770 memcpy(&opl, r, sizeof(struct objc_property_list32));
4771 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4773 outs() << " entsize " << opl.entsize << "\n";
4774 outs() << " count " << opl.count << "\n";
4776 p += sizeof(struct objc_property_list32);
4777 offset += sizeof(struct objc_property_list32);
4778 for (j = 0; j < opl.count; j++) {
4779 r = get_pointer_32(p, offset, left, S, info);
4782 memset(&op, '\0', sizeof(struct objc_property32));
4783 if (left < sizeof(struct objc_property32)) {
4784 memcpy(&op, r, left);
4785 outs() << " (objc_property entends past the end of the section)\n";
4787 memcpy(&op, r, sizeof(struct objc_property32));
4788 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4791 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name);
4792 name = get_pointer_32(op.name, xoffset, left, xS, info);
4793 if (name != nullptr)
4794 outs() << format(" %.*s", left, name);
4797 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
4798 name = get_pointer_32(op.attributes, xoffset, left, xS, info);
4799 if (name != nullptr)
4800 outs() << format(" %.*s", left, name);
4803 p += sizeof(struct objc_property32);
4804 offset += sizeof(struct objc_property32);
4808 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
4809 bool &is_meta_class) {
4810 struct class_ro64_t cro;
4812 uint32_t offset, xoffset, left;
4814 const char *name, *sym_name;
4817 r = get_pointer_64(p, offset, left, S, info);
4818 if (r == nullptr || left < sizeof(struct class_ro64_t))
4820 memcpy(&cro, r, sizeof(struct class_ro64_t));
4821 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4823 outs() << " flags " << format("0x%" PRIx32, cro.flags);
4824 if (cro.flags & RO_META)
4825 outs() << " RO_META";
4826 if (cro.flags & RO_ROOT)
4827 outs() << " RO_ROOT";
4828 if (cro.flags & RO_HAS_CXX_STRUCTORS)
4829 outs() << " RO_HAS_CXX_STRUCTORS";
4831 outs() << " instanceStart " << cro.instanceStart << "\n";
4832 outs() << " instanceSize " << cro.instanceSize << "\n";
4833 outs() << " reserved " << format("0x%" PRIx32, cro.reserved)
4835 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
4837 print_layout_map64(cro.ivarLayout, info);
4840 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
4841 info, n_value, cro.name);
4843 if (info->verbose && sym_name != nullptr)
4846 outs() << format("0x%" PRIx64, n_value);
4848 outs() << " + " << format("0x%" PRIx64, cro.name);
4850 outs() << format("0x%" PRIx64, cro.name);
4851 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
4852 if (name != nullptr)
4853 outs() << format(" %.*s", left, name);
4856 outs() << " baseMethods ";
4857 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
4858 S, info, n_value, cro.baseMethods);
4860 if (info->verbose && sym_name != nullptr)
4863 outs() << format("0x%" PRIx64, n_value);
4864 if (cro.baseMethods != 0)
4865 outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
4867 outs() << format("0x%" PRIx64, cro.baseMethods);
4868 outs() << " (struct method_list_t *)\n";
4869 if (cro.baseMethods + n_value != 0)
4870 print_method_list64_t(cro.baseMethods + n_value, info, "");
4872 outs() << " baseProtocols ";
4874 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
4875 info, n_value, cro.baseProtocols);
4877 if (info->verbose && sym_name != nullptr)
4880 outs() << format("0x%" PRIx64, n_value);
4881 if (cro.baseProtocols != 0)
4882 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
4884 outs() << format("0x%" PRIx64, cro.baseProtocols);
4886 if (cro.baseProtocols + n_value != 0)
4887 print_protocol_list64_t(cro.baseProtocols + n_value, info);
4889 outs() << " ivars ";
4890 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
4891 info, n_value, cro.ivars);
4893 if (info->verbose && sym_name != nullptr)
4896 outs() << format("0x%" PRIx64, n_value);
4898 outs() << " + " << format("0x%" PRIx64, cro.ivars);
4900 outs() << format("0x%" PRIx64, cro.ivars);
4902 if (cro.ivars + n_value != 0)
4903 print_ivar_list64_t(cro.ivars + n_value, info);
4905 outs() << " weakIvarLayout ";
4907 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
4908 info, n_value, cro.weakIvarLayout);
4910 if (info->verbose && sym_name != nullptr)
4913 outs() << format("0x%" PRIx64, n_value);
4914 if (cro.weakIvarLayout != 0)
4915 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
4917 outs() << format("0x%" PRIx64, cro.weakIvarLayout);
4919 print_layout_map64(cro.weakIvarLayout + n_value, info);
4921 outs() << " baseProperties ";
4923 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
4924 info, n_value, cro.baseProperties);
4926 if (info->verbose && sym_name != nullptr)
4929 outs() << format("0x%" PRIx64, n_value);
4930 if (cro.baseProperties != 0)
4931 outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
4933 outs() << format("0x%" PRIx64, cro.baseProperties);
4935 if (cro.baseProperties + n_value != 0)
4936 print_objc_property_list64(cro.baseProperties + n_value, info);
4938 is_meta_class = (cro.flags & RO_META) != 0;
4942 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
4943 bool &is_meta_class) {
4944 struct class_ro32_t cro;
4946 uint32_t offset, xoffset, left;
4950 r = get_pointer_32(p, offset, left, S, info);
4953 memset(&cro, '\0', sizeof(struct class_ro32_t));
4954 if (left < sizeof(struct class_ro32_t)) {
4955 memcpy(&cro, r, left);
4956 outs() << " (class_ro_t entends past the end of the section)\n";
4958 memcpy(&cro, r, sizeof(struct class_ro32_t));
4959 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4961 outs() << " flags " << format("0x%" PRIx32, cro.flags);
4962 if (cro.flags & RO_META)
4963 outs() << " RO_META";
4964 if (cro.flags & RO_ROOT)
4965 outs() << " RO_ROOT";
4966 if (cro.flags & RO_HAS_CXX_STRUCTORS)
4967 outs() << " RO_HAS_CXX_STRUCTORS";
4969 outs() << " instanceStart " << cro.instanceStart << "\n";
4970 outs() << " instanceSize " << cro.instanceSize << "\n";
4971 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
4973 print_layout_map32(cro.ivarLayout, info);
4975 outs() << " name " << format("0x%" PRIx32, cro.name);
4976 name = get_pointer_32(cro.name, xoffset, left, xS, info);
4977 if (name != nullptr)
4978 outs() << format(" %.*s", left, name);
4981 outs() << " baseMethods "
4982 << format("0x%" PRIx32, cro.baseMethods)
4983 << " (struct method_list_t *)\n";
4984 if (cro.baseMethods != 0)
4985 print_method_list32_t(cro.baseMethods, info, "");
4987 outs() << " baseProtocols "
4988 << format("0x%" PRIx32, cro.baseProtocols) << "\n";
4989 if (cro.baseProtocols != 0)
4990 print_protocol_list32_t(cro.baseProtocols, info);
4991 outs() << " ivars " << format("0x%" PRIx32, cro.ivars)
4994 print_ivar_list32_t(cro.ivars, info);
4995 outs() << " weakIvarLayout "
4996 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
4997 print_layout_map32(cro.weakIvarLayout, info);
4998 outs() << " baseProperties "
4999 << format("0x%" PRIx32, cro.baseProperties) << "\n";
5000 if (cro.baseProperties != 0)
5001 print_objc_property_list32(cro.baseProperties, info);
5002 is_meta_class = (cro.flags & RO_META) != 0;
5006 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
5009 uint32_t offset, left;
5012 uint64_t isa_n_value, n_value;
5014 r = get_pointer_64(p, offset, left, S, info);
5015 if (r == nullptr || left < sizeof(struct class64_t))
5017 memcpy(&c, r, sizeof(struct class64_t));
5018 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5021 outs() << " isa " << format("0x%" PRIx64, c.isa);
5022 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
5023 isa_n_value, c.isa);
5024 if (name != nullptr)
5025 outs() << " " << name;
5028 outs() << " superclass " << format("0x%" PRIx64, c.superclass);
5029 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
5030 n_value, c.superclass);
5031 if (name != nullptr)
5032 outs() << " " << name;
5034 name = get_dyld_bind_info_symbolname(S.getAddress() +
5035 offset + offsetof(struct class64_t, superclass), info);
5036 if (name != nullptr)
5037 outs() << " " << name;
5041 outs() << " cache " << format("0x%" PRIx64, c.cache);
5042 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
5044 if (name != nullptr)
5045 outs() << " " << name;
5048 outs() << " vtable " << format("0x%" PRIx64, c.vtable);
5049 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
5051 if (name != nullptr)
5052 outs() << " " << name;
5055 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
5059 if (info->verbose && name != nullptr)
5062 outs() << format("0x%" PRIx64, n_value);
5064 outs() << " + " << format("0x%" PRIx64, c.data);
5066 outs() << format("0x%" PRIx64, c.data);
5067 outs() << " (struct class_ro_t *)";
5069 // This is a Swift class if some of the low bits of the pointer are set.
5070 if ((c.data + n_value) & 0x7)
5071 outs() << " Swift class";
5074 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
5077 if (!is_meta_class &&
5078 c.isa + isa_n_value != p &&
5079 c.isa + isa_n_value != 0 &&
5080 info->depth < 100) {
5082 outs() << "Meta Class\n";
5083 print_class64_t(c.isa + isa_n_value, info);
5087 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
5090 uint32_t offset, left;
5094 r = get_pointer_32(p, offset, left, S, info);
5097 memset(&c, '\0', sizeof(struct class32_t));
5098 if (left < sizeof(struct class32_t)) {
5099 memcpy(&c, r, left);
5100 outs() << " (class_t entends past the end of the section)\n";
5102 memcpy(&c, r, sizeof(struct class32_t));
5103 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5106 outs() << " isa " << format("0x%" PRIx32, c.isa);
5108 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
5109 if (name != nullptr)
5110 outs() << " " << name;
5113 outs() << " superclass " << format("0x%" PRIx32, c.superclass);
5114 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
5116 if (name != nullptr)
5117 outs() << " " << name;
5120 outs() << " cache " << format("0x%" PRIx32, c.cache);
5121 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
5123 if (name != nullptr)
5124 outs() << " " << name;
5127 outs() << " vtable " << format("0x%" PRIx32, c.vtable);
5128 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
5130 if (name != nullptr)
5131 outs() << " " << name;
5135 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
5136 outs() << " data " << format("0x%" PRIx32, c.data)
5137 << " (struct class_ro_t *)";
5139 // This is a Swift class if some of the low bits of the pointer are set.
5141 outs() << " Swift class";
5144 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
5147 if (!is_meta_class) {
5148 outs() << "Meta Class\n";
5149 print_class32_t(c.isa, info);
5153 static void print_objc_class_t(struct objc_class_t *objc_class,
5154 struct DisassembleInfo *info) {
5155 uint32_t offset, left, xleft;
5156 const char *name, *p, *ivar_list;
5159 struct objc_ivar_list_t objc_ivar_list;
5160 struct objc_ivar_t ivar;
5162 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa);
5163 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
5164 name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
5165 if (name != nullptr)
5166 outs() << format(" %.*s", left, name);
5168 outs() << " (not in an __OBJC section)";
5172 outs() << "\t super_class "
5173 << format("0x%08" PRIx32, objc_class->super_class);
5174 if (info->verbose) {
5175 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
5176 if (name != nullptr)
5177 outs() << format(" %.*s", left, name);
5179 outs() << " (not in an __OBJC section)";
5183 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name);
5184 if (info->verbose) {
5185 name = get_pointer_32(objc_class->name, offset, left, S, info, true);
5186 if (name != nullptr)
5187 outs() << format(" %.*s", left, name);
5189 outs() << " (not in an __OBJC section)";
5193 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version)
5196 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info);
5197 if (info->verbose) {
5198 if (CLS_GETINFO(objc_class, CLS_CLASS))
5199 outs() << " CLS_CLASS";
5200 else if (CLS_GETINFO(objc_class, CLS_META))
5201 outs() << " CLS_META";
5205 outs() << "\t instance_size "
5206 << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
5208 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
5209 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars);
5211 if (left > sizeof(struct objc_ivar_list_t)) {
5213 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
5215 outs() << " (entends past the end of the section)\n";
5216 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
5217 memcpy(&objc_ivar_list, p, left);
5219 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5220 swapStruct(objc_ivar_list);
5221 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n";
5222 ivar_list = p + sizeof(struct objc_ivar_list_t);
5223 for (i = 0; i < objc_ivar_list.ivar_count; i++) {
5224 if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
5225 outs() << "\t\t remaining ivar's extend past the of the section\n";
5228 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
5229 sizeof(struct objc_ivar_t));
5230 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5233 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
5234 if (info->verbose) {
5235 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
5236 if (name != nullptr)
5237 outs() << format(" %.*s", xleft, name);
5239 outs() << " (not in an __OBJC section)";
5243 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
5244 if (info->verbose) {
5245 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
5246 if (name != nullptr)
5247 outs() << format(" %.*s", xleft, name);
5249 outs() << " (not in an __OBJC section)";
5253 outs() << "\t\t ivar_offset "
5254 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
5257 outs() << " (not in an __OBJC section)\n";
5260 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists);
5261 if (print_method_list(objc_class->methodLists, info))
5262 outs() << " (not in an __OBJC section)\n";
5264 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache)
5267 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
5268 if (print_protocol_list(objc_class->protocols, 16, info))
5269 outs() << " (not in an __OBJC section)\n";
5272 static void print_objc_objc_category_t(struct objc_category_t *objc_category,
5273 struct DisassembleInfo *info) {
5274 uint32_t offset, left;
5278 outs() << "\t category name "
5279 << format("0x%08" PRIx32, objc_category->category_name);
5280 if (info->verbose) {
5281 name = get_pointer_32(objc_category->category_name, offset, left, S, info,
5283 if (name != nullptr)
5284 outs() << format(" %.*s", left, name);
5286 outs() << " (not in an __OBJC section)";
5290 outs() << "\t\t class name "
5291 << format("0x%08" PRIx32, objc_category->class_name);
5292 if (info->verbose) {
5294 get_pointer_32(objc_category->class_name, offset, left, S, info, true);
5295 if (name != nullptr)
5296 outs() << format(" %.*s", left, name);
5298 outs() << " (not in an __OBJC section)";
5302 outs() << "\t instance methods "
5303 << format("0x%08" PRIx32, objc_category->instance_methods);
5304 if (print_method_list(objc_category->instance_methods, info))
5305 outs() << " (not in an __OBJC section)\n";
5307 outs() << "\t class methods "
5308 << format("0x%08" PRIx32, objc_category->class_methods);
5309 if (print_method_list(objc_category->class_methods, info))
5310 outs() << " (not in an __OBJC section)\n";
5313 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
5314 struct category64_t c;
5316 uint32_t offset, xoffset, left;
5318 const char *name, *sym_name;
5321 r = get_pointer_64(p, offset, left, S, info);
5324 memset(&c, '\0', sizeof(struct category64_t));
5325 if (left < sizeof(struct category64_t)) {
5326 memcpy(&c, r, left);
5327 outs() << " (category_t entends past the end of the section)\n";
5329 memcpy(&c, r, sizeof(struct category64_t));
5330 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5334 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
5335 info, n_value, c.name);
5337 if (info->verbose && sym_name != nullptr)
5340 outs() << format("0x%" PRIx64, n_value);
5342 outs() << " + " << format("0x%" PRIx64, c.name);
5344 outs() << format("0x%" PRIx64, c.name);
5345 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
5346 if (name != nullptr)
5347 outs() << format(" %.*s", left, name);
5351 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
5354 if (info->verbose && sym_name != nullptr)
5357 outs() << format("0x%" PRIx64, n_value);
5359 outs() << " + " << format("0x%" PRIx64, c.cls);
5361 outs() << format("0x%" PRIx64, c.cls);
5363 if (c.cls + n_value != 0)
5364 print_class64_t(c.cls + n_value, info);
5366 outs() << " instanceMethods ";
5368 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
5369 info, n_value, c.instanceMethods);
5371 if (info->verbose && sym_name != nullptr)
5374 outs() << format("0x%" PRIx64, n_value);
5375 if (c.instanceMethods != 0)
5376 outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
5378 outs() << format("0x%" PRIx64, c.instanceMethods);
5380 if (c.instanceMethods + n_value != 0)
5381 print_method_list64_t(c.instanceMethods + n_value, info, "");
5383 outs() << " classMethods ";
5384 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
5385 S, info, n_value, c.classMethods);
5387 if (info->verbose && sym_name != nullptr)
5390 outs() << format("0x%" PRIx64, n_value);
5391 if (c.classMethods != 0)
5392 outs() << " + " << format("0x%" PRIx64, c.classMethods);
5394 outs() << format("0x%" PRIx64, c.classMethods);
5396 if (c.classMethods + n_value != 0)
5397 print_method_list64_t(c.classMethods + n_value, info, "");
5399 outs() << " protocols ";
5400 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
5401 info, n_value, c.protocols);
5403 if (info->verbose && sym_name != nullptr)
5406 outs() << format("0x%" PRIx64, n_value);
5407 if (c.protocols != 0)
5408 outs() << " + " << format("0x%" PRIx64, c.protocols);
5410 outs() << format("0x%" PRIx64, c.protocols);
5412 if (c.protocols + n_value != 0)
5413 print_protocol_list64_t(c.protocols + n_value, info);
5415 outs() << "instanceProperties ";
5417 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
5418 S, info, n_value, c.instanceProperties);
5420 if (info->verbose && sym_name != nullptr)
5423 outs() << format("0x%" PRIx64, n_value);
5424 if (c.instanceProperties != 0)
5425 outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
5427 outs() << format("0x%" PRIx64, c.instanceProperties);
5429 if (c.instanceProperties + n_value != 0)
5430 print_objc_property_list64(c.instanceProperties + n_value, info);
5433 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
5434 struct category32_t c;
5436 uint32_t offset, left;
5440 r = get_pointer_32(p, offset, left, S, info);
5443 memset(&c, '\0', sizeof(struct category32_t));
5444 if (left < sizeof(struct category32_t)) {
5445 memcpy(&c, r, left);
5446 outs() << " (category_t entends past the end of the section)\n";
5448 memcpy(&c, r, sizeof(struct category32_t));
5449 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5452 outs() << " name " << format("0x%" PRIx32, c.name);
5453 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
5456 outs() << " " << name;
5459 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n";
5461 print_class32_t(c.cls, info);
5462 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
5464 if (c.instanceMethods != 0)
5465 print_method_list32_t(c.instanceMethods, info, "");
5466 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods)
5468 if (c.classMethods != 0)
5469 print_method_list32_t(c.classMethods, info, "");
5470 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n";
5471 if (c.protocols != 0)
5472 print_protocol_list32_t(c.protocols, info);
5473 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
5475 if (c.instanceProperties != 0)
5476 print_objc_property_list32(c.instanceProperties, info);
5479 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
5480 uint32_t i, left, offset, xoffset;
5481 uint64_t p, n_value;
5482 struct message_ref64 mr;
5483 const char *name, *sym_name;
5487 if (S == SectionRef())
5491 S.getName(SectName);
5492 DataRefImpl Ref = S.getRawDataRefImpl();
5493 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5494 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5496 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5497 p = S.getAddress() + i;
5498 r = get_pointer_64(p, offset, left, S, info);
5501 memset(&mr, '\0', sizeof(struct message_ref64));
5502 if (left < sizeof(struct message_ref64)) {
5503 memcpy(&mr, r, left);
5504 outs() << " (message_ref entends past the end of the section)\n";
5506 memcpy(&mr, r, sizeof(struct message_ref64));
5507 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5511 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
5514 outs() << format("0x%" PRIx64, n_value) << " ";
5516 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
5518 outs() << format("0x%" PRIx64, mr.imp) << " ";
5519 if (name != nullptr)
5520 outs() << " " << name;
5524 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
5525 info, n_value, mr.sel);
5527 if (info->verbose && sym_name != nullptr)
5530 outs() << format("0x%" PRIx64, n_value);
5532 outs() << " + " << format("0x%" PRIx64, mr.sel);
5534 outs() << format("0x%" PRIx64, mr.sel);
5535 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
5536 if (name != nullptr)
5537 outs() << format(" %.*s", left, name);
5540 offset += sizeof(struct message_ref64);
5544 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
5545 uint32_t i, left, offset, xoffset, p;
5546 struct message_ref32 mr;
5547 const char *name, *r;
5550 if (S == SectionRef())
5554 S.getName(SectName);
5555 DataRefImpl Ref = S.getRawDataRefImpl();
5556 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5557 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5559 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5560 p = S.getAddress() + i;
5561 r = get_pointer_32(p, offset, left, S, info);
5564 memset(&mr, '\0', sizeof(struct message_ref32));
5565 if (left < sizeof(struct message_ref32)) {
5566 memcpy(&mr, r, left);
5567 outs() << " (message_ref entends past the end of the section)\n";
5569 memcpy(&mr, r, sizeof(struct message_ref32));
5570 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5573 outs() << " imp " << format("0x%" PRIx32, mr.imp);
5574 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
5576 if (name != nullptr)
5577 outs() << " " << name;
5580 outs() << " sel " << format("0x%" PRIx32, mr.sel);
5581 name = get_pointer_32(mr.sel, xoffset, left, xS, info);
5582 if (name != nullptr)
5583 outs() << " " << name;
5586 offset += sizeof(struct message_ref32);
5590 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
5591 uint32_t left, offset, swift_version;
5593 struct objc_image_info64 o;
5596 if (S == SectionRef())
5600 S.getName(SectName);
5601 DataRefImpl Ref = S.getRawDataRefImpl();
5602 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5603 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5605 r = get_pointer_64(p, offset, left, S, info);
5608 memset(&o, '\0', sizeof(struct objc_image_info64));
5609 if (left < sizeof(struct objc_image_info64)) {
5610 memcpy(&o, r, left);
5611 outs() << " (objc_image_info entends past the end of the section)\n";
5613 memcpy(&o, r, sizeof(struct objc_image_info64));
5614 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5616 outs() << " version " << o.version << "\n";
5617 outs() << " flags " << format("0x%" PRIx32, o.flags);
5618 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
5619 outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5620 if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
5621 outs() << " OBJC_IMAGE_SUPPORTS_GC";
5622 if (o.flags & OBJC_IMAGE_IS_SIMULATED)
5623 outs() << " OBJC_IMAGE_IS_SIMULATED";
5624 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES)
5625 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
5626 swift_version = (o.flags >> 8) & 0xff;
5627 if (swift_version != 0) {
5628 if (swift_version == 1)
5629 outs() << " Swift 1.0";
5630 else if (swift_version == 2)
5631 outs() << " Swift 1.1";
5632 else if(swift_version == 3)
5633 outs() << " Swift 2.0";
5634 else if(swift_version == 4)
5635 outs() << " Swift 3.0";
5636 else if(swift_version == 5)
5637 outs() << " Swift 4.0";
5638 else if(swift_version == 6)
5639 outs() << " Swift 4.1/Swift 4.2";
5640 else if(swift_version == 7)
5641 outs() << " Swift 5 or later";
5643 outs() << " unknown future Swift version (" << swift_version << ")";
5648 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
5649 uint32_t left, offset, swift_version, p;
5650 struct objc_image_info32 o;
5653 if (S == SectionRef())
5657 S.getName(SectName);
5658 DataRefImpl Ref = S.getRawDataRefImpl();
5659 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5660 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5662 r = get_pointer_32(p, offset, left, S, info);
5665 memset(&o, '\0', sizeof(struct objc_image_info32));
5666 if (left < sizeof(struct objc_image_info32)) {
5667 memcpy(&o, r, left);
5668 outs() << " (objc_image_info entends past the end of the section)\n";
5670 memcpy(&o, r, sizeof(struct objc_image_info32));
5671 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5673 outs() << " version " << o.version << "\n";
5674 outs() << " flags " << format("0x%" PRIx32, o.flags);
5675 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
5676 outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5677 if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
5678 outs() << " OBJC_IMAGE_SUPPORTS_GC";
5679 swift_version = (o.flags >> 8) & 0xff;
5680 if (swift_version != 0) {
5681 if (swift_version == 1)
5682 outs() << " Swift 1.0";
5683 else if (swift_version == 2)
5684 outs() << " Swift 1.1";
5685 else if(swift_version == 3)
5686 outs() << " Swift 2.0";
5687 else if(swift_version == 4)
5688 outs() << " Swift 3.0";
5689 else if(swift_version == 5)
5690 outs() << " Swift 4.0";
5691 else if(swift_version == 6)
5692 outs() << " Swift 4.1/Swift 4.2";
5693 else if(swift_version == 7)
5694 outs() << " Swift 5 or later";
5696 outs() << " unknown future Swift version (" << swift_version << ")";
5701 static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
5702 uint32_t left, offset, p;
5703 struct imageInfo_t o;
5707 S.getName(SectName);
5708 DataRefImpl Ref = S.getRawDataRefImpl();
5709 StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5710 outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5712 r = get_pointer_32(p, offset, left, S, info);
5715 memset(&o, '\0', sizeof(struct imageInfo_t));
5716 if (left < sizeof(struct imageInfo_t)) {
5717 memcpy(&o, r, left);
5718 outs() << " (imageInfo entends past the end of the section)\n";
5720 memcpy(&o, r, sizeof(struct imageInfo_t));
5721 if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5723 outs() << " version " << o.version << "\n";
5724 outs() << " flags " << format("0x%" PRIx32, o.flags);
5730 outs() << " GC-only";
5736 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
5737 SymbolAddressMap AddrMap;
5739 CreateSymbolAddressMap(O, &AddrMap);
5741 std::vector<SectionRef> Sections;
5742 for (const SectionRef &Section : O->sections()) {
5744 Section.getName(SectName);
5745 Sections.push_back(Section);
5748 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
5750 SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5751 if (CL == SectionRef())
5752 CL = get_section(O, "__DATA", "__objc_classlist");
5753 if (CL == SectionRef())
5754 CL = get_section(O, "__DATA_CONST", "__objc_classlist");
5755 if (CL == SectionRef())
5756 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
5758 walk_pointer_list_64("class", CL, O, &info, print_class64_t);
5760 SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5761 if (CR == SectionRef())
5762 CR = get_section(O, "__DATA", "__objc_classrefs");
5763 if (CR == SectionRef())
5764 CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
5765 if (CR == SectionRef())
5766 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
5768 walk_pointer_list_64("class refs", CR, O, &info, nullptr);
5770 SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5771 if (SR == SectionRef())
5772 SR = get_section(O, "__DATA", "__objc_superrefs");
5773 if (SR == SectionRef())
5774 SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
5775 if (SR == SectionRef())
5776 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
5778 walk_pointer_list_64("super refs", SR, O, &info, nullptr);
5780 SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5781 if (CA == SectionRef())
5782 CA = get_section(O, "__DATA", "__objc_catlist");
5783 if (CA == SectionRef())
5784 CA = get_section(O, "__DATA_CONST", "__objc_catlist");
5785 if (CA == SectionRef())
5786 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
5788 walk_pointer_list_64("category", CA, O, &info, print_category64_t);
5790 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5791 if (PL == SectionRef())
5792 PL = get_section(O, "__DATA", "__objc_protolist");
5793 if (PL == SectionRef())
5794 PL = get_section(O, "__DATA_CONST", "__objc_protolist");
5795 if (PL == SectionRef())
5796 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
5798 walk_pointer_list_64("protocol", PL, O, &info, nullptr);
5800 SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5801 if (MR == SectionRef())
5802 MR = get_section(O, "__DATA", "__objc_msgrefs");
5803 if (MR == SectionRef())
5804 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
5805 if (MR == SectionRef())
5806 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
5808 print_message_refs64(MR, &info);
5810 SectionRef II = get_section(O, "__OBJC2", "__image_info");
5811 if (II == SectionRef())
5812 II = get_section(O, "__DATA", "__objc_imageinfo");
5813 if (II == SectionRef())
5814 II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
5815 if (II == SectionRef())
5816 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
5818 print_image_info64(II, &info);
5821 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5822 SymbolAddressMap AddrMap;
5824 CreateSymbolAddressMap(O, &AddrMap);
5826 std::vector<SectionRef> Sections;
5827 for (const SectionRef &Section : O->sections()) {
5829 Section.getName(SectName);
5830 Sections.push_back(Section);
5833 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
5835 SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5836 if (CL == SectionRef())
5837 CL = get_section(O, "__DATA", "__objc_classlist");
5838 if (CL == SectionRef())
5839 CL = get_section(O, "__DATA_CONST", "__objc_classlist");
5840 if (CL == SectionRef())
5841 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
5843 walk_pointer_list_32("class", CL, O, &info, print_class32_t);
5845 SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5846 if (CR == SectionRef())
5847 CR = get_section(O, "__DATA", "__objc_classrefs");
5848 if (CR == SectionRef())
5849 CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
5850 if (CR == SectionRef())
5851 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
5853 walk_pointer_list_32("class refs", CR, O, &info, nullptr);
5855 SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5856 if (SR == SectionRef())
5857 SR = get_section(O, "__DATA", "__objc_superrefs");
5858 if (SR == SectionRef())
5859 SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
5860 if (SR == SectionRef())
5861 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
5863 walk_pointer_list_32("super refs", SR, O, &info, nullptr);
5865 SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5866 if (CA == SectionRef())
5867 CA = get_section(O, "__DATA", "__objc_catlist");
5868 if (CA == SectionRef())
5869 CA = get_section(O, "__DATA_CONST", "__objc_catlist");
5870 if (CA == SectionRef())
5871 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
5873 walk_pointer_list_32("category", CA, O, &info, print_category32_t);
5875 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5876 if (PL == SectionRef())
5877 PL = get_section(O, "__DATA", "__objc_protolist");
5878 if (PL == SectionRef())
5879 PL = get_section(O, "__DATA_CONST", "__objc_protolist");
5880 if (PL == SectionRef())
5881 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
5883 walk_pointer_list_32("protocol", PL, O, &info, nullptr);
5885 SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5886 if (MR == SectionRef())
5887 MR = get_section(O, "__DATA", "__objc_msgrefs");
5888 if (MR == SectionRef())
5889 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
5890 if (MR == SectionRef())
5891 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
5893 print_message_refs32(MR, &info);
5895 SectionRef II = get_section(O, "__OBJC2", "__image_info");
5896 if (II == SectionRef())
5897 II = get_section(O, "__DATA", "__objc_imageinfo");
5898 if (II == SectionRef())
5899 II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
5900 if (II == SectionRef())
5901 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
5903 print_image_info32(II, &info);
5906 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5907 uint32_t i, j, p, offset, xoffset, left, defs_left, def;
5908 const char *r, *name, *defs;
5909 struct objc_module_t module;
5911 struct objc_symtab_t symtab;
5912 struct objc_class_t objc_class;
5913 struct objc_category_t objc_category;
5915 outs() << "Objective-C segment\n";
5916 S = get_section(O, "__OBJC", "__module_info");
5917 if (S == SectionRef())
5920 SymbolAddressMap AddrMap;
5922 CreateSymbolAddressMap(O, &AddrMap);
5924 std::vector<SectionRef> Sections;
5925 for (const SectionRef &Section : O->sections()) {
5927 Section.getName(SectName);
5928 Sections.push_back(Section);
5931 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
5933 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
5934 p = S.getAddress() + i;
5935 r = get_pointer_32(p, offset, left, S, &info, true);
5938 memset(&module, '\0', sizeof(struct objc_module_t));
5939 if (left < sizeof(struct objc_module_t)) {
5940 memcpy(&module, r, left);
5941 outs() << " (module extends past end of __module_info section)\n";
5943 memcpy(&module, r, sizeof(struct objc_module_t));
5944 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5947 outs() << "Module " << format("0x%" PRIx32, p) << "\n";
5948 outs() << " version " << module.version << "\n";
5949 outs() << " size " << module.size << "\n";
5951 name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
5952 if (name != nullptr)
5953 outs() << format("%.*s", left, name);
5955 outs() << format("0x%08" PRIx32, module.name)
5956 << "(not in an __OBJC section)";
5959 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
5960 if (module.symtab == 0 || r == nullptr) {
5961 outs() << " symtab " << format("0x%08" PRIx32, module.symtab)
5962 << " (not in an __OBJC section)\n";
5965 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
5966 memset(&symtab, '\0', sizeof(struct objc_symtab_t));
5969 if (left < sizeof(struct objc_symtab_t)) {
5970 memcpy(&symtab, r, left);
5971 outs() << "\tsymtab extends past end of an __OBJC section)\n";
5973 memcpy(&symtab, r, sizeof(struct objc_symtab_t));
5974 if (left > sizeof(struct objc_symtab_t)) {
5975 defs_left = left - sizeof(struct objc_symtab_t);
5976 defs = r + sizeof(struct objc_symtab_t);
5979 if (O->isLittleEndian() != sys::IsLittleEndianHost)
5982 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
5983 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
5984 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
5986 outs() << " (not in an __OBJC section)";
5988 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
5989 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
5990 if (symtab.cls_def_cnt > 0)
5991 outs() << "\tClass Definitions\n";
5992 for (j = 0; j < symtab.cls_def_cnt; j++) {
5993 if ((j + 1) * sizeof(uint32_t) > defs_left) {
5994 outs() << "\t(remaining class defs entries entends past the end of the "
5998 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
5999 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6000 sys::swapByteOrder(def);
6002 r = get_pointer_32(def, xoffset, left, xS, &info, true);
6003 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
6005 if (left > sizeof(struct objc_class_t)) {
6007 memcpy(&objc_class, r, sizeof(struct objc_class_t));
6009 outs() << " (entends past the end of the section)\n";
6010 memset(&objc_class, '\0', sizeof(struct objc_class_t));
6011 memcpy(&objc_class, r, left);
6013 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6014 swapStruct(objc_class);
6015 print_objc_class_t(&objc_class, &info);
6017 outs() << "(not in an __OBJC section)\n";
6020 if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
6021 outs() << "\tMeta Class";
6022 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
6024 if (left > sizeof(struct objc_class_t)) {
6026 memcpy(&objc_class, r, sizeof(struct objc_class_t));
6028 outs() << " (entends past the end of the section)\n";
6029 memset(&objc_class, '\0', sizeof(struct objc_class_t));
6030 memcpy(&objc_class, r, left);
6032 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6033 swapStruct(objc_class);
6034 print_objc_class_t(&objc_class, &info);
6036 outs() << "(not in an __OBJC section)\n";
6040 if (symtab.cat_def_cnt > 0)
6041 outs() << "\tCategory Definitions\n";
6042 for (j = 0; j < symtab.cat_def_cnt; j++) {
6043 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
6044 outs() << "\t(remaining category defs entries entends past the end of "
6045 << "the section)\n";
6048 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
6050 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6051 sys::swapByteOrder(def);
6053 r = get_pointer_32(def, xoffset, left, xS, &info, true);
6054 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
6055 << format("0x%08" PRIx32, def);
6057 if (left > sizeof(struct objc_category_t)) {
6059 memcpy(&objc_category, r, sizeof(struct objc_category_t));
6061 outs() << " (entends past the end of the section)\n";
6062 memset(&objc_category, '\0', sizeof(struct objc_category_t));
6063 memcpy(&objc_category, r, left);
6065 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6066 swapStruct(objc_category);
6067 print_objc_objc_category_t(&objc_category, &info);
6069 outs() << "(not in an __OBJC section)\n";
6073 const SectionRef II = get_section(O, "__OBJC", "__image_info");
6074 if (II != SectionRef())
6075 print_image_info(II, &info);
6080 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
6081 uint32_t size, uint32_t addr) {
6082 SymbolAddressMap AddrMap;
6083 CreateSymbolAddressMap(O, &AddrMap);
6085 std::vector<SectionRef> Sections;
6086 for (const SectionRef &Section : O->sections()) {
6088 Section.getName(SectName);
6089 Sections.push_back(Section);
6092 struct DisassembleInfo info(O, &AddrMap, &Sections, true);
6095 struct objc_protocol_t protocol;
6096 uint32_t left, paddr;
6097 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
6098 memset(&protocol, '\0', sizeof(struct objc_protocol_t));
6099 left = size - (p - sect);
6100 if (left < sizeof(struct objc_protocol_t)) {
6101 outs() << "Protocol extends past end of __protocol section\n";
6102 memcpy(&protocol, p, left);
6104 memcpy(&protocol, p, sizeof(struct objc_protocol_t));
6105 if (O->isLittleEndian() != sys::IsLittleEndianHost)
6106 swapStruct(protocol);
6107 paddr = addr + (p - sect);
6108 outs() << "Protocol " << format("0x%" PRIx32, paddr);
6109 if (print_protocol(paddr, 0, &info))
6110 outs() << "(not in an __OBJC section)\n";
6115 inline void swapStruct(struct xar_header &xar) {
6116 sys::swapByteOrder(xar.magic);
6117 sys::swapByteOrder(xar.size);
6118 sys::swapByteOrder(xar.version);
6119 sys::swapByteOrder(xar.toc_length_compressed);
6120 sys::swapByteOrder(xar.toc_length_uncompressed);
6121 sys::swapByteOrder(xar.cksum_alg);
6124 static void PrintModeVerbose(uint32_t mode) {
6125 switch(mode & S_IFMT){
6149 /* owner permissions */
6160 else if(mode & S_IEXEC)
6165 /* group permissions */
6166 if(mode & (S_IREAD >> 3))
6170 if(mode & (S_IWRITE >> 3))
6176 else if(mode & (S_IEXEC >> 3))
6181 /* other permissions */
6182 if(mode & (S_IREAD >> 6))
6186 if(mode & (S_IWRITE >> 6))
6192 else if(mode & (S_IEXEC >> 6))
6198 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
6200 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
6202 uint32_t mode_value;
6206 WithColor::error(errs(), "llvm-objdump")
6207 << "can't obtain an xar iterator for xar archive " << XarFilename
6212 // Go through the xar's files.
6213 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
6216 WithColor::error(errs(), "llvm-objdump")
6217 << "can't obtain an xar iterator for xar archive " << XarFilename
6228 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
6229 const char *val = nullptr;
6230 xar_prop_get(xf, key, &val);
6231 #if 0 // Useful for debugging.
6232 outs() << "key: " << key << " value: " << val << "\n";
6234 if(strcmp(key, "type") == 0)
6236 if(strcmp(key, "mode") == 0)
6238 if(strcmp(key, "user") == 0)
6240 if(strcmp(key, "group") == 0)
6242 if(strcmp(key, "data/size") == 0)
6244 if(strcmp(key, "mtime") == 0)
6246 if(strcmp(key, "name") == 0)
6249 if(mode != nullptr){
6250 mode_value = strtoul(mode, &endp, 8);
6252 outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
6253 if(strcmp(type, "file") == 0)
6254 mode_value |= S_IFREG;
6255 PrintModeVerbose(mode_value);
6259 outs() << format("%10s/", user);
6260 if(group != nullptr)
6261 outs() << format("%-10s ", group);
6263 outs() << format("%7s ", size);
6264 if(mtime != nullptr){
6265 for(m = mtime; *m != 'T' && *m != '\0'; m++)
6270 for( ; *m != 'Z' && *m != '\0'; m++)
6280 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
6281 uint32_t size, bool verbose,
6282 bool PrintXarHeader, bool PrintXarFileHeaders,
6283 std::string XarMemberName) {
6284 if(size < sizeof(struct xar_header)) {
6285 outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
6286 "of struct xar_header)\n";
6289 struct xar_header XarHeader;
6290 memcpy(&XarHeader, sect, sizeof(struct xar_header));
6291 if (sys::IsLittleEndianHost)
6292 swapStruct(XarHeader);
6293 if (PrintXarHeader) {
6294 if (!XarMemberName.empty())
6295 outs() << "In xar member " << XarMemberName << ": ";
6297 outs() << "For (__LLVM,__bundle) section: ";
6298 outs() << "xar header\n";
6299 if (XarHeader.magic == XAR_HEADER_MAGIC)
6300 outs() << " magic XAR_HEADER_MAGIC\n";
6303 << format_hex(XarHeader.magic, 10, true)
6304 << " (not XAR_HEADER_MAGIC)\n";
6305 outs() << " size " << XarHeader.size << "\n";
6306 outs() << " version " << XarHeader.version << "\n";
6307 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed
6309 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
6311 outs() << " cksum_alg ";
6312 switch (XarHeader.cksum_alg) {
6313 case XAR_CKSUM_NONE:
6314 outs() << "XAR_CKSUM_NONE\n";
6316 case XAR_CKSUM_SHA1:
6317 outs() << "XAR_CKSUM_SHA1\n";
6320 outs() << "XAR_CKSUM_MD5\n";
6322 #ifdef XAR_CKSUM_SHA256
6323 case XAR_CKSUM_SHA256:
6324 outs() << "XAR_CKSUM_SHA256\n";
6327 #ifdef XAR_CKSUM_SHA512
6328 case XAR_CKSUM_SHA512:
6329 outs() << "XAR_CKSUM_SHA512\n";
6333 outs() << XarHeader.cksum_alg << "\n";
6337 SmallString<128> XarFilename;
6339 std::error_code XarEC =
6340 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
6342 WithColor::error(errs(), "llvm-objdump") << XarEC.message() << "\n";
6345 ToolOutputFile XarFile(XarFilename, FD);
6346 raw_fd_ostream &XarOut = XarFile.os();
6347 StringRef XarContents(sect, size);
6348 XarOut << XarContents;
6350 if (XarOut.has_error())
6353 ScopedXarFile xar(XarFilename.c_str(), READ);
6355 WithColor::error(errs(), "llvm-objdump")
6356 << "can't create temporary xar archive " << XarFilename << "\n";
6360 SmallString<128> TocFilename;
6361 std::error_code TocEC =
6362 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
6364 WithColor::error(errs(), "llvm-objdump") << TocEC.message() << "\n";
6367 xar_serialize(xar, TocFilename.c_str());
6369 if (PrintXarFileHeaders) {
6370 if (!XarMemberName.empty())
6371 outs() << "In xar member " << XarMemberName << ": ";
6373 outs() << "For (__LLVM,__bundle) section: ";
6374 outs() << "xar archive files:\n";
6375 PrintXarFilesSummary(XarFilename.c_str(), xar);
6378 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
6379 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
6380 if (std::error_code EC = FileOrErr.getError()) {
6381 WithColor::error(errs(), "llvm-objdump") << EC.message() << "\n";
6384 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
6386 if (!XarMemberName.empty())
6387 outs() << "In xar member " << XarMemberName << ": ";
6389 outs() << "For (__LLVM,__bundle) section: ";
6390 outs() << "xar table of contents:\n";
6391 outs() << Buffer->getBuffer() << "\n";
6393 // TODO: Go through the xar's files.
6396 WithColor::error(errs(), "llvm-objdump")
6397 << "can't obtain an xar iterator for xar archive "
6398 << XarFilename.c_str() << "\n";
6401 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
6403 const char *member_name, *member_type, *member_size_string;
6408 WithColor::error(errs(), "llvm-objdump")
6409 << "can't obtain an xar iterator for xar archive "
6410 << XarFilename.c_str() << "\n";
6415 member_size_string = NULL;
6416 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
6417 const char *val = nullptr;
6418 xar_prop_get(xf, key, &val);
6419 #if 0 // Useful for debugging.
6420 outs() << "key: " << key << " value: " << val << "\n";
6422 if (strcmp(key, "name") == 0)
6424 if (strcmp(key, "type") == 0)
6426 if (strcmp(key, "data/size") == 0)
6427 member_size_string = val;
6430 * If we find a file with a name, date/size and type properties
6431 * and with the type being "file" see if that is a xar file.
6433 if (member_name != NULL && member_type != NULL &&
6434 strcmp(member_type, "file") == 0 &&
6435 member_size_string != NULL){
6436 // Extract the file into a buffer.
6438 member_size = strtoul(member_size_string, &endptr, 10);
6439 if (*endptr == '\0' && member_size != 0) {
6441 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
6442 #if 0 // Useful for debugging.
6443 outs() << "xar member: " << member_name << " extracted\n";
6445 // Set the XarMemberName we want to see printed in the header.
6446 std::string OldXarMemberName;
6447 // If XarMemberName is already set this is nested. So
6448 // save the old name and create the nested name.
6449 if (!XarMemberName.empty()) {
6450 OldXarMemberName = XarMemberName;
6452 (Twine("[") + XarMemberName + "]" + member_name).str();
6454 OldXarMemberName = "";
6455 XarMemberName = member_name;
6457 // See if this is could be a xar file (nested).
6458 if (member_size >= sizeof(struct xar_header)) {
6459 #if 0 // Useful for debugging.
6460 outs() << "could be a xar file: " << member_name << "\n";
6462 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
6463 if (sys::IsLittleEndianHost)
6464 swapStruct(XarHeader);
6465 if (XarHeader.magic == XAR_HEADER_MAGIC)
6466 DumpBitcodeSection(O, buffer, member_size, verbose,
6467 PrintXarHeader, PrintXarFileHeaders,
6470 XarMemberName = OldXarMemberName;
6477 #endif // defined(HAVE_LIBXAR)
6479 static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
6481 printObjc2_64bit_MetaData(O, verbose);
6483 MachO::mach_header H;
6485 if (H.cputype == MachO::CPU_TYPE_ARM)
6486 printObjc2_32bit_MetaData(O, verbose);
6488 // This is the 32-bit non-arm cputype case. Which is normally
6489 // the first Objective-C ABI. But it may be the case of a
6490 // binary for the iOS simulator which is the second Objective-C
6491 // ABI. In that case printObjc1_32bit_MetaData() will determine that
6492 // and return false.
6493 if (!printObjc1_32bit_MetaData(O, verbose))
6494 printObjc2_32bit_MetaData(O, verbose);
6499 // GuessLiteralPointer returns a string which for the item in the Mach-O file
6500 // for the address passed in as ReferenceValue for printing as a comment with
6501 // the instruction and also returns the corresponding type of that item
6502 // indirectly through ReferenceType.
6504 // If ReferenceValue is an address of literal cstring then a pointer to the
6505 // cstring is returned and ReferenceType is set to
6506 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
6508 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or
6509 // Class ref that name is returned and the ReferenceType is set accordingly.
6511 // Lastly, literals which are Symbol address in a literal pool are looked for
6512 // and if found the symbol name is returned and ReferenceType is set to
6513 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
6515 // If there is no item in the Mach-O file for the address passed in as
6516 // ReferenceValue nullptr is returned and ReferenceType is unchanged.
6517 static const char *GuessLiteralPointer(uint64_t ReferenceValue,
6518 uint64_t ReferencePC,
6519 uint64_t *ReferenceType,
6520 struct DisassembleInfo *info) {
6521 // First see if there is an external relocation entry at the ReferencePC.
6522 if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
6523 uint64_t sect_addr = info->S.getAddress();
6524 uint64_t sect_offset = ReferencePC - sect_addr;
6525 bool reloc_found = false;
6527 MachO::any_relocation_info RE;
6528 bool isExtern = false;
6530 for (const RelocationRef &Reloc : info->S.relocations()) {
6531 uint64_t RelocOffset = Reloc.getOffset();
6532 if (RelocOffset == sect_offset) {
6533 Rel = Reloc.getRawDataRefImpl();
6534 RE = info->O->getRelocation(Rel);
6535 if (info->O->isRelocationScattered(RE))
6537 isExtern = info->O->getPlainRelocationExternal(RE);
6539 symbol_iterator RelocSym = Reloc.getSymbol();
6546 // If there is an external relocation entry for a symbol in a section
6547 // then used that symbol's value for the value of the reference.
6548 if (reloc_found && isExtern) {
6549 if (info->O->getAnyRelocationPCRel(RE)) {
6550 unsigned Type = info->O->getAnyRelocationType(RE);
6551 if (Type == MachO::X86_64_RELOC_SIGNED) {
6552 ReferenceValue = Symbol.getValue();
6558 // Look for literals such as Objective-C CFStrings refs, Selector refs,
6559 // Message refs and Class refs.
6560 bool classref, selref, msgref, cfstring;
6561 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
6562 selref, msgref, cfstring);
6563 if (classref && pointer_value == 0) {
6564 // Note the ReferenceValue is a pointer into the __objc_classrefs section.
6565 // And the pointer_value in that section is typically zero as it will be
6566 // set by dyld as part of the "bind information".
6567 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
6568 if (name != nullptr) {
6569 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6570 const char *class_name = strrchr(name, '$');
6571 if (class_name != nullptr && class_name[1] == '_' &&
6572 class_name[2] != '\0') {
6573 info->class_name = class_name + 2;
6580 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6582 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
6583 if (name != nullptr)
6584 info->class_name = name;
6586 name = "bad class ref";
6591 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
6592 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
6596 if (selref && pointer_value == 0)
6597 pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
6599 if (pointer_value != 0)
6600 ReferenceValue = pointer_value;
6602 const char *name = GuessCstringPointer(ReferenceValue, info);
6604 if (pointer_value != 0 && selref) {
6605 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
6606 info->selector_name = name;
6607 } else if (pointer_value != 0 && msgref) {
6608 info->class_name = nullptr;
6609 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
6610 info->selector_name = name;
6612 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
6616 // Lastly look for an indirect symbol with this ReferenceValue which is in
6617 // a literal pool. If found return that symbol name.
6618 name = GuessIndirectSymbol(ReferenceValue, info);
6620 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
6627 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
6628 // the Symbolizer. It looks up the ReferenceValue using the info passed via the
6629 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
6630 // is created and returns the symbol name that matches the ReferenceValue or
6631 // nullptr if none. The ReferenceType is passed in for the IN type of
6632 // reference the instruction is making from the values in defined in the header
6633 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific
6634 // Out type and the ReferenceName will also be set which is added as a comment
6635 // to the disassembled instruction.
6637 // If the symbol name is a C++ mangled name then the demangled name is
6638 // returned through ReferenceName and ReferenceType is set to
6639 // LLVMDisassembler_ReferenceType_DeMangled_Name .
6641 // When this is called to get a symbol name for a branch target then the
6642 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
6643 // SymbolValue will be looked for in the indirect symbol table to determine if
6644 // it is an address for a symbol stub. If so then the symbol name for that
6645 // stub is returned indirectly through ReferenceName and then ReferenceType is
6646 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
6648 // When this is called with an value loaded via a PC relative load then
6649 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
6650 // SymbolValue is checked to be an address of literal pointer, symbol pointer,
6651 // or an Objective-C meta data reference. If so the output ReferenceType is
6652 // set to correspond to that as well as setting the ReferenceName.
6653 static const char *SymbolizerSymbolLookUp(void *DisInfo,
6654 uint64_t ReferenceValue,
6655 uint64_t *ReferenceType,
6656 uint64_t ReferencePC,
6657 const char **ReferenceName) {
6658 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
6659 // If no verbose symbolic information is wanted then just return nullptr.
6660 if (!info->verbose) {
6661 *ReferenceName = nullptr;
6662 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6666 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
6668 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
6669 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
6670 if (*ReferenceName != nullptr) {
6671 method_reference(info, ReferenceType, ReferenceName);
6672 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
6673 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
6674 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6675 if (info->demangled_name != nullptr)
6676 free(info->demangled_name);
6678 info->demangled_name =
6679 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
6680 if (info->demangled_name != nullptr) {
6681 *ReferenceName = info->demangled_name;
6682 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
6684 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6686 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6687 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
6689 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6691 method_reference(info, ReferenceType, ReferenceName);
6693 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6694 // If this is arm64 and the reference is an adrp instruction save the
6695 // instruction, passed in ReferenceValue and the address of the instruction
6696 // for use later if we see and add immediate instruction.
6697 } else if (info->O->getArch() == Triple::aarch64 &&
6698 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
6699 info->adrp_inst = ReferenceValue;
6700 info->adrp_addr = ReferencePC;
6701 SymbolName = nullptr;
6702 *ReferenceName = nullptr;
6703 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6704 // If this is arm64 and reference is an add immediate instruction and we
6706 // seen an adrp instruction just before it and the adrp's Xd register
6708 // this add's Xn register reconstruct the value being referenced and look to
6709 // see if it is a literal pointer. Note the add immediate instruction is
6710 // passed in ReferenceValue.
6711 } else if (info->O->getArch() == Triple::aarch64 &&
6712 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
6713 ReferencePC - 4 == info->adrp_addr &&
6714 (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6715 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6716 uint32_t addxri_inst;
6717 uint64_t adrp_imm, addxri_imm;
6720 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6721 if (info->adrp_inst & 0x0200000)
6722 adrp_imm |= 0xfffffffffc000000LL;
6724 addxri_inst = ReferenceValue;
6725 addxri_imm = (addxri_inst >> 10) & 0xfff;
6726 if (((addxri_inst >> 22) & 0x3) == 1)
6729 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6730 (adrp_imm << 12) + addxri_imm;
6733 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6734 if (*ReferenceName == nullptr)
6735 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6736 // If this is arm64 and the reference is a load register instruction and we
6737 // have seen an adrp instruction just before it and the adrp's Xd register
6738 // matches this add's Xn register reconstruct the value being referenced and
6739 // look to see if it is a literal pointer. Note the load register
6740 // instruction is passed in ReferenceValue.
6741 } else if (info->O->getArch() == Triple::aarch64 &&
6742 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
6743 ReferencePC - 4 == info->adrp_addr &&
6744 (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6745 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6746 uint32_t ldrxui_inst;
6747 uint64_t adrp_imm, ldrxui_imm;
6750 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6751 if (info->adrp_inst & 0x0200000)
6752 adrp_imm |= 0xfffffffffc000000LL;
6754 ldrxui_inst = ReferenceValue;
6755 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
6757 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6758 (adrp_imm << 12) + (ldrxui_imm << 3);
6761 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6762 if (*ReferenceName == nullptr)
6763 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6765 // If this arm64 and is an load register (PC-relative) instruction the
6766 // ReferenceValue is the PC plus the immediate value.
6767 else if (info->O->getArch() == Triple::aarch64 &&
6768 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
6769 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
6771 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6772 if (*ReferenceName == nullptr)
6773 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6774 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6775 if (info->demangled_name != nullptr)
6776 free(info->demangled_name);
6778 info->demangled_name =
6779 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
6780 if (info->demangled_name != nullptr) {
6781 *ReferenceName = info->demangled_name;
6782 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
6786 *ReferenceName = nullptr;
6787 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6793 /// Emits the comments that are stored in the CommentStream.
6794 /// Each comment in the CommentStream must end with a newline.
6795 static void emitComments(raw_svector_ostream &CommentStream,
6796 SmallString<128> &CommentsToEmit,
6797 formatted_raw_ostream &FormattedOS,
6798 const MCAsmInfo &MAI) {
6799 // Flush the stream before taking its content.
6800 StringRef Comments = CommentsToEmit.str();
6801 // Get the default information for printing a comment.
6802 StringRef CommentBegin = MAI.getCommentString();
6803 unsigned CommentColumn = MAI.getCommentColumn();
6804 bool IsFirst = true;
6805 while (!Comments.empty()) {
6807 FormattedOS << '\n';
6808 // Emit a line of comments.
6809 FormattedOS.PadToColumn(CommentColumn);
6810 size_t Position = Comments.find('\n');
6811 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
6812 // Move after the newline character.
6813 Comments = Comments.substr(Position + 1);
6816 FormattedOS.flush();
6818 // Tell the comment stream that the vector changed underneath it.
6819 CommentsToEmit.clear();
6822 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
6823 StringRef DisSegName, StringRef DisSectName) {
6824 const char *McpuDefault = nullptr;
6825 const Target *ThumbTarget = nullptr;
6826 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
6828 // GetTarget prints out stuff.
6831 std::string MachOMCPU;
6832 if (MCPU.empty() && McpuDefault)
6833 MachOMCPU = McpuDefault;
6837 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
6838 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
6840 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
6842 // Package up features to be passed to target/subtarget
6843 std::string FeaturesStr;
6844 if (!MAttrs.empty()) {
6845 SubtargetFeatures Features;
6846 for (unsigned i = 0; i != MAttrs.size(); ++i)
6847 Features.AddFeature(MAttrs[i]);
6848 FeaturesStr = Features.getString();
6851 // Set up disassembler.
6852 std::unique_ptr<const MCRegisterInfo> MRI(
6853 TheTarget->createMCRegInfo(TripleName));
6854 std::unique_ptr<const MCAsmInfo> AsmInfo(
6855 TheTarget->createMCAsmInfo(*MRI, TripleName));
6856 std::unique_ptr<const MCSubtargetInfo> STI(
6857 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
6858 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr);
6859 std::unique_ptr<MCDisassembler> DisAsm(
6860 TheTarget->createMCDisassembler(*STI, Ctx));
6861 std::unique_ptr<MCSymbolizer> Symbolizer;
6862 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
6863 std::unique_ptr<MCRelocationInfo> RelInfo(
6864 TheTarget->createMCRelocationInfo(TripleName, Ctx));
6866 Symbolizer.reset(TheTarget->createMCSymbolizer(
6867 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6868 &SymbolizerInfo, &Ctx, std::move(RelInfo)));
6869 DisAsm->setSymbolizer(std::move(Symbolizer));
6871 int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
6872 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
6873 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
6874 // Set the display preference for hex vs. decimal immediates.
6875 IP->setPrintImmHex(PrintImmHex);
6876 // Comment stream and backing vector.
6877 SmallString<128> CommentsToEmit;
6878 raw_svector_ostream CommentStream(CommentsToEmit);
6879 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
6880 // if it is done then arm64 comments for string literals don't get printed
6881 // and some constant get printed instead and not setting it causes intel
6882 // (32-bit and 64-bit) comments printed with different spacing before the
6883 // comment causing different diffs with the 'C' disassembler library API.
6884 // IP->setCommentStream(CommentStream);
6886 if (!AsmInfo || !STI || !DisAsm || !IP) {
6887 WithColor::error(errs(), "llvm-objdump")
6888 << "couldn't initialize disassembler for target " << TripleName << '\n';
6892 // Set up separate thumb disassembler if needed.
6893 std::unique_ptr<const MCRegisterInfo> ThumbMRI;
6894 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
6895 std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
6896 std::unique_ptr<MCDisassembler> ThumbDisAsm;
6897 std::unique_ptr<MCInstPrinter> ThumbIP;
6898 std::unique_ptr<MCContext> ThumbCtx;
6899 std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
6900 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
6901 std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
6903 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
6905 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName));
6907 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
6909 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr));
6910 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
6911 MCContext *PtrThumbCtx = ThumbCtx.get();
6913 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
6915 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
6916 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6917 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
6918 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
6920 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
6921 ThumbIP.reset(ThumbTarget->createMCInstPrinter(
6922 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
6923 *ThumbInstrInfo, *ThumbMRI));
6924 // Set the display preference for hex vs. decimal immediates.
6925 ThumbIP->setPrintImmHex(PrintImmHex);
6928 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) {
6929 WithColor::error(errs(), "llvm-objdump")
6930 << "couldn't initialize disassembler for target " << ThumbTripleName
6935 MachO::mach_header Header = MachOOF->getHeader();
6937 // FIXME: Using the -cfg command line option, this code used to be able to
6938 // annotate relocations with the referenced symbol's name, and if this was
6939 // inside a __[cf]string section, the data it points to. This is now replaced
6940 // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
6941 std::vector<SectionRef> Sections;
6942 std::vector<SymbolRef> Symbols;
6943 SmallVector<uint64_t, 8> FoundFns;
6944 uint64_t BaseSegmentAddress;
6946 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
6947 BaseSegmentAddress);
6949 // Sort the symbols by address, just in case they didn't come in that way.
6950 llvm::sort(Symbols, SymbolSorter());
6952 // Build a data in code table that is sorted on by the address of each entry.
6953 uint64_t BaseAddress = 0;
6954 if (Header.filetype == MachO::MH_OBJECT)
6955 BaseAddress = Sections[0].getAddress();
6957 BaseAddress = BaseSegmentAddress;
6959 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
6962 DI->getOffset(Offset);
6963 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
6965 array_pod_sort(Dices.begin(), Dices.end());
6968 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
6970 raw_ostream &DebugOut = nulls();
6973 std::unique_ptr<DIContext> diContext;
6974 ObjectFile *DbgObj = MachOOF;
6975 std::unique_ptr<MemoryBuffer> DSYMBuf;
6976 // Try to find debug info and set up the DIContext for it.
6978 // A separate DSym file path was specified, parse it as a macho file,
6979 // get the sections and supply it to the section name parsing machinery.
6980 if (!DSYMFile.empty()) {
6981 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
6982 MemoryBuffer::getFileOrSTDIN(DSYMFile);
6983 if (std::error_code EC = BufOrErr.getError()) {
6984 report_error(DSYMFile, errorCodeToError(EC));
6988 Expected<std::unique_ptr<MachOObjectFile>> DbgObjCheck =
6989 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef());
6991 if (Error E = DbgObjCheck.takeError()) {
6992 report_error(DSYMFile, std::move(E));
6996 DbgObj = DbgObjCheck.get().release();
6997 // We need to keep the file alive, because we're replacing DbgObj with it.
6998 DSYMBuf = std::move(BufOrErr.get());
7001 // Setup the DIContext
7002 diContext = DWARFContext::create(*DbgObj);
7005 if (FilterSections.empty())
7006 outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
7008 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
7010 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName)
7013 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
7015 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
7016 if (SegmentName != DisSegName)
7020 Sections[SectIdx].getContents(BytesStr);
7021 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
7023 uint64_t SectAddress = Sections[SectIdx].getAddress();
7025 bool symbolTableWorked = false;
7027 // Create a map of symbol addresses to symbol names for use by
7028 // the SymbolizerSymbolLookUp() routine.
7029 SymbolAddressMap AddrMap;
7030 bool DisSymNameFound = false;
7031 for (const SymbolRef &Symbol : MachOOF->symbols()) {
7032 Expected<SymbolRef::Type> STOrErr = Symbol.getType();
7034 report_error(MachOOF->getFileName(), STOrErr.takeError());
7035 SymbolRef::Type ST = *STOrErr;
7036 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
7037 ST == SymbolRef::ST_Other) {
7038 uint64_t Address = Symbol.getValue();
7039 Expected<StringRef> SymNameOrErr = Symbol.getName();
7041 report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
7042 StringRef SymName = *SymNameOrErr;
7043 AddrMap[Address] = SymName;
7044 if (!DisSymName.empty() && DisSymName == SymName)
7045 DisSymNameFound = true;
7048 if (!DisSymName.empty() && !DisSymNameFound) {
7049 outs() << "Can't find -dis-symname: " << DisSymName << "\n";
7052 // Set up the block of info used by the Symbolizer call backs.
7053 SymbolizerInfo.verbose = !NoSymbolicOperands;
7054 SymbolizerInfo.O = MachOOF;
7055 SymbolizerInfo.S = Sections[SectIdx];
7056 SymbolizerInfo.AddrMap = &AddrMap;
7057 SymbolizerInfo.Sections = &Sections;
7058 // Same for the ThumbSymbolizer
7059 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
7060 ThumbSymbolizerInfo.O = MachOOF;
7061 ThumbSymbolizerInfo.S = Sections[SectIdx];
7062 ThumbSymbolizerInfo.AddrMap = &AddrMap;
7063 ThumbSymbolizerInfo.Sections = &Sections;
7065 unsigned int Arch = MachOOF->getArch();
7067 // Skip all symbols if this is a stubs file.
7071 // If the section has symbols but no symbol at the start of the section
7072 // these are used to make sure the bytes before the first symbol are
7074 bool FirstSymbol = true;
7075 bool FirstSymbolAtSectionStart = true;
7077 // Disassemble symbol by symbol.
7078 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
7079 Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
7081 report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
7082 StringRef SymName = *SymNameOrErr;
7084 Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType();
7086 report_error(MachOOF->getFileName(), STOrErr.takeError());
7087 SymbolRef::Type ST = *STOrErr;
7088 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
7091 // Make sure the symbol is defined in this section.
7092 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
7094 if (!DisSymName.empty() && DisSymName == SymName) {
7095 outs() << "-dis-symname: " << DisSymName << " not in the section\n";
7100 // The __mh_execute_header is special and we need to deal with that fact
7101 // this symbol is before the start of the (__TEXT,__text) section and at the
7102 // address of the start of the __TEXT segment. This is because this symbol
7103 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
7104 // start of the section in a standard MH_EXECUTE filetype.
7105 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
7106 outs() << "-dis-symname: __mh_execute_header not in any section\n";
7109 // When this code is trying to disassemble a symbol at a time and in the
7110 // case there is only the __mh_execute_header symbol left as in a stripped
7111 // executable, we need to deal with this by ignoring this symbol so the
7112 // whole section is disassembled and this symbol is then not displayed.
7113 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
7114 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
7115 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
7118 // If we are only disassembling one symbol see if this is that symbol.
7119 if (!DisSymName.empty() && DisSymName != SymName)
7122 // Start at the address of the symbol relative to the section's address.
7123 uint64_t SectSize = Sections[SectIdx].getSize();
7124 uint64_t Start = Symbols[SymIdx].getValue();
7125 uint64_t SectionAddress = Sections[SectIdx].getAddress();
7126 Start -= SectionAddress;
7128 if (Start > SectSize) {
7129 outs() << "section data ends, " << SymName
7130 << " lies outside valid range\n";
7134 // Stop disassembling either at the beginning of the next symbol or at
7135 // the end of the section.
7136 bool containsNextSym = false;
7137 uint64_t NextSym = 0;
7138 uint64_t NextSymIdx = SymIdx + 1;
7139 while (Symbols.size() > NextSymIdx) {
7140 Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType();
7142 report_error(MachOOF->getFileName(), STOrErr.takeError());
7143 SymbolRef::Type NextSymType = *STOrErr;
7144 if (NextSymType == SymbolRef::ST_Function) {
7146 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
7147 NextSym = Symbols[NextSymIdx].getValue();
7148 NextSym -= SectionAddress;
7154 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
7157 symbolTableWorked = true;
7159 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
7160 bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb;
7162 // We only need the dedicated Thumb target if there's a real choice
7163 // (i.e. we're not targeting M-class) and the function is Thumb.
7164 bool UseThumbTarget = IsThumb && ThumbTarget;
7166 // If we are not specifying a symbol to start disassembly with and this
7167 // is the first symbol in the section but not at the start of the section
7168 // then move the disassembly index to the start of the section and
7169 // don't print the symbol name just yet. This is so the bytes before the
7170 // first symbol are disassembled.
7171 uint64_t SymbolStart = Start;
7172 if (DisSymName.empty() && FirstSymbol && Start != 0) {
7173 FirstSymbolAtSectionStart = false;
7177 outs() << SymName << ":\n";
7179 DILineInfo lastLine;
7180 for (uint64_t Index = Start; Index < End; Index += Size) {
7183 // If this is the first symbol in the section and it was not at the
7184 // start of the section, see if we are at its Index now and if so print
7186 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart)
7187 outs() << SymName << ":\n";
7189 uint64_t PC = SectAddress + Index;
7190 if (!NoLeadingAddr) {
7191 if (FullLeadingAddr) {
7192 if (MachOOF->is64Bit())
7193 outs() << format("%016" PRIx64, PC);
7195 outs() << format("%08" PRIx64, PC);
7197 outs() << format("%8" PRIx64 ":", PC);
7200 if (!NoShowRawInsn || Arch == Triple::arm)
7203 // Check the data in code table here to see if this is data not an
7204 // instruction to be disassembled.
7206 Dice.push_back(std::make_pair(PC, DiceRef()));
7207 dice_table_iterator DTI =
7208 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
7209 compareDiceTableEntries);
7210 if (DTI != Dices.end()) {
7212 DTI->second.getLength(Length);
7214 DTI->second.getKind(Kind);
7215 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind);
7216 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
7217 (PC == (DTI->first + Length - 1)) && (Length & 1))
7222 SmallVector<char, 64> AnnotationsBytes;
7223 raw_svector_ostream Annotations(AnnotationsBytes);
7227 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
7228 PC, DebugOut, Annotations);
7230 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
7231 DebugOut, Annotations);
7233 if (!NoShowRawInsn || Arch == Triple::arm) {
7234 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
7236 formatted_raw_ostream FormattedOS(outs());
7237 StringRef AnnotationsStr = Annotations.str();
7239 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
7241 IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI);
7242 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
7244 // Print debug info.
7246 DILineInfo dli = diContext->getLineInfoForAddress(PC);
7247 // Print valid line info if it changed.
7248 if (dli != lastLine && dli.Line != 0)
7249 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
7255 unsigned int Arch = MachOOF->getArch();
7256 if (Arch == Triple::x86_64 || Arch == Triple::x86) {
7257 outs() << format("\t.byte 0x%02x #bad opcode\n",
7258 *(Bytes.data() + Index) & 0xff);
7259 Size = 1; // skip exactly one illegible byte and move on.
7260 } else if (Arch == Triple::aarch64 ||
7261 (Arch == Triple::arm && !IsThumb)) {
7262 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7263 (*(Bytes.data() + Index + 1) & 0xff) << 8 |
7264 (*(Bytes.data() + Index + 2) & 0xff) << 16 |
7265 (*(Bytes.data() + Index + 3) & 0xff) << 24;
7266 outs() << format("\t.long\t0x%08x\n", opcode);
7268 } else if (Arch == Triple::arm) {
7269 assert(IsThumb && "ARM mode should have been dealt with above");
7270 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7271 (*(Bytes.data() + Index + 1) & 0xff) << 8;
7272 outs() << format("\t.short\t0x%04x\n", opcode);
7275 WithColor::warning(errs(), "llvm-objdump")
7276 << "invalid instruction encoding\n";
7278 Size = 1; // skip illegible bytes
7282 // Now that we are done disassembled the first symbol set the bool that
7283 // were doing this to false.
7284 FirstSymbol = false;
7286 if (!symbolTableWorked) {
7287 // Reading the symbol table didn't work, disassemble the whole section.
7288 uint64_t SectAddress = Sections[SectIdx].getAddress();
7289 uint64_t SectSize = Sections[SectIdx].getSize();
7291 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
7294 uint64_t PC = SectAddress + Index;
7295 SmallVector<char, 64> AnnotationsBytes;
7296 raw_svector_ostream Annotations(AnnotationsBytes);
7297 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
7298 DebugOut, Annotations)) {
7299 if (!NoLeadingAddr) {
7300 if (FullLeadingAddr) {
7301 if (MachOOF->is64Bit())
7302 outs() << format("%016" PRIx64, PC);
7304 outs() << format("%08" PRIx64, PC);
7306 outs() << format("%8" PRIx64 ":", PC);
7309 if (!NoShowRawInsn || Arch == Triple::arm) {
7311 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
7313 StringRef AnnotationsStr = Annotations.str();
7314 IP->printInst(&Inst, outs(), AnnotationsStr, *STI);
7317 unsigned int Arch = MachOOF->getArch();
7318 if (Arch == Triple::x86_64 || Arch == Triple::x86) {
7319 outs() << format("\t.byte 0x%02x #bad opcode\n",
7320 *(Bytes.data() + Index) & 0xff);
7321 InstSize = 1; // skip exactly one illegible byte and move on.
7323 WithColor::warning(errs(), "llvm-objdump")
7324 << "invalid instruction encoding\n";
7326 InstSize = 1; // skip illegible bytes
7331 // The TripleName's need to be reset if we are called again for a different
7334 ThumbTripleName = "";
7336 if (SymbolizerInfo.demangled_name != nullptr)
7337 free(SymbolizerInfo.demangled_name);
7338 if (ThumbSymbolizerInfo.demangled_name != nullptr)
7339 free(ThumbSymbolizerInfo.demangled_name);
7343 //===----------------------------------------------------------------------===//
7344 // __compact_unwind section dumping
7345 //===----------------------------------------------------------------------===//
7349 template <typename T>
7350 static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
7351 using llvm::support::little;
7352 using llvm::support::unaligned;
7354 if (Offset + sizeof(T) > Contents.size()) {
7355 outs() << "warning: attempt to read past end of buffer\n";
7360 support::endian::read<T, little, unaligned>(Contents.data() + Offset);
7364 template <typename T>
7365 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
7366 T Val = read<T>(Contents, Offset);
7367 Offset += sizeof(T);
7371 struct CompactUnwindEntry {
7372 uint32_t OffsetInSection;
7374 uint64_t FunctionAddr;
7376 uint32_t CompactEncoding;
7377 uint64_t PersonalityAddr;
7380 RelocationRef FunctionReloc;
7381 RelocationRef PersonalityReloc;
7382 RelocationRef LSDAReloc;
7384 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
7385 : OffsetInSection(Offset) {
7387 read<uint64_t>(Contents, Offset);
7389 read<uint32_t>(Contents, Offset);
7393 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
7394 FunctionAddr = readNext<UIntPtr>(Contents, Offset);
7395 Length = readNext<uint32_t>(Contents, Offset);
7396 CompactEncoding = readNext<uint32_t>(Contents, Offset);
7397 PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
7398 LSDAAddr = readNext<UIntPtr>(Contents, Offset);
7403 /// Given a relocation from __compact_unwind, consisting of the RelocationRef
7404 /// and data being relocated, determine the best base Name and Addend to use for
7405 /// display purposes.
7407 /// 1. An Extern relocation will directly reference a symbol (and the data is
7408 /// then already an addend), so use that.
7409 /// 2. Otherwise the data is an offset in the object file's layout; try to find
7410 // a symbol before it in the same section, and use the offset from there.
7411 /// 3. Finally, if all that fails, fall back to an offset from the start of the
7412 /// referenced section.
7413 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
7414 std::map<uint64_t, SymbolRef> &Symbols,
7415 const RelocationRef &Reloc, uint64_t Addr,
7416 StringRef &Name, uint64_t &Addend) {
7417 if (Reloc.getSymbol() != Obj->symbol_end()) {
7418 Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName();
7420 report_error(Obj->getFileName(), NameOrErr.takeError());
7426 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
7427 SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
7429 uint64_t SectionAddr = RelocSection.getAddress();
7431 auto Sym = Symbols.upper_bound(Addr);
7432 if (Sym == Symbols.begin()) {
7433 // The first symbol in the object is after this reference, the best we can
7434 // do is section-relative notation.
7435 RelocSection.getName(Name);
7436 Addend = Addr - SectionAddr;
7440 // Go back one so that SymbolAddress <= Addr.
7443 auto SectOrErr = Sym->second.getSection();
7445 report_error(Obj->getFileName(), SectOrErr.takeError());
7446 section_iterator SymSection = *SectOrErr;
7447 if (RelocSection == *SymSection) {
7448 // There's a valid symbol in the same section before this reference.
7449 Expected<StringRef> NameOrErr = Sym->second.getName();
7451 report_error(Obj->getFileName(), NameOrErr.takeError());
7453 Addend = Addr - Sym->first;
7457 // There is a symbol before this reference, but it's in a different
7458 // section. Probably not helpful to mention it, so use the section name.
7459 RelocSection.getName(Name);
7460 Addend = Addr - SectionAddr;
7463 static void printUnwindRelocDest(const MachOObjectFile *Obj,
7464 std::map<uint64_t, SymbolRef> &Symbols,
7465 const RelocationRef &Reloc, uint64_t Addr) {
7469 if (!Reloc.getObject())
7472 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
7476 outs() << " + " << format("0x%" PRIx64, Addend);
7480 printMachOCompactUnwindSection(const MachOObjectFile *Obj,
7481 std::map<uint64_t, SymbolRef> &Symbols,
7482 const SectionRef &CompactUnwind) {
7484 if (!Obj->isLittleEndian()) {
7485 outs() << "Skipping big-endian __compact_unwind section\n";
7489 bool Is64 = Obj->is64Bit();
7490 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
7491 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
7494 CompactUnwind.getContents(Contents);
7496 SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
7498 // First populate the initial raw offsets, encodings and so on from the entry.
7499 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
7500 CompactUnwindEntry Entry(Contents, Offset, Is64);
7501 CompactUnwinds.push_back(Entry);
7504 // Next we need to look at the relocations to find out what objects are
7505 // actually being referred to.
7506 for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
7507 uint64_t RelocAddress = Reloc.getOffset();
7509 uint32_t EntryIdx = RelocAddress / EntrySize;
7510 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
7511 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
7513 if (OffsetInEntry == 0)
7514 Entry.FunctionReloc = Reloc;
7515 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
7516 Entry.PersonalityReloc = Reloc;
7517 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
7518 Entry.LSDAReloc = Reloc;
7520 outs() << "Invalid relocation in __compact_unwind section\n";
7525 // Finally, we're ready to print the data we've gathered.
7526 outs() << "Contents of __compact_unwind section:\n";
7527 for (auto &Entry : CompactUnwinds) {
7528 outs() << " Entry at offset "
7529 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
7531 // 1. Start of the region this entry applies to.
7532 outs() << " start: " << format("0x%" PRIx64,
7533 Entry.FunctionAddr) << ' ';
7534 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
7537 // 2. Length of the region this entry applies to.
7538 outs() << " length: " << format("0x%" PRIx32, Entry.Length)
7540 // 3. The 32-bit compact encoding.
7541 outs() << " compact encoding: "
7542 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
7544 // 4. The personality function, if present.
7545 if (Entry.PersonalityReloc.getObject()) {
7546 outs() << " personality function: "
7547 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
7548 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
7549 Entry.PersonalityAddr);
7553 // 5. This entry's language-specific data area.
7554 if (Entry.LSDAReloc.getObject()) {
7555 outs() << " LSDA: " << format("0x%" PRIx64,
7556 Entry.LSDAAddr) << ' ';
7557 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
7563 //===----------------------------------------------------------------------===//
7564 // __unwind_info section dumping
7565 //===----------------------------------------------------------------------===//
7567 static void printRegularSecondLevelUnwindPage(StringRef PageData) {
7569 uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7571 assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
7573 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7574 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7577 for (unsigned i = 0; i < NumEntries; ++i) {
7578 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
7579 uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
7581 outs() << " [" << i << "]: "
7582 << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7584 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
7588 static void printCompressedSecondLevelUnwindPage(
7589 StringRef PageData, uint32_t FunctionBase,
7590 const SmallVectorImpl<uint32_t> &CommonEncodings) {
7592 uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7594 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
7596 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7597 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7599 uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos);
7600 readNext<uint16_t>(PageData, Pos);
7601 StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos);
7604 for (unsigned i = 0; i < NumEntries; ++i) {
7605 uint32_t Entry = readNext<uint32_t>(PageData, Pos);
7606 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
7607 uint32_t EncodingIdx = Entry >> 24;
7610 if (EncodingIdx < CommonEncodings.size())
7611 Encoding = CommonEncodings[EncodingIdx];
7613 Encoding = read<uint32_t>(PageEncodings,
7615 (EncodingIdx - CommonEncodings.size()));
7617 outs() << " [" << i << "]: "
7618 << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7620 << "encoding[" << EncodingIdx
7621 << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
7625 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
7626 std::map<uint64_t, SymbolRef> &Symbols,
7627 const SectionRef &UnwindInfo) {
7629 if (!Obj->isLittleEndian()) {
7630 outs() << "Skipping big-endian __unwind_info section\n";
7634 outs() << "Contents of __unwind_info section:\n";
7637 UnwindInfo.getContents(Contents);
7640 //===----------------------------------
7642 //===----------------------------------
7644 uint32_t Version = readNext<uint32_t>(Contents, Pos);
7645 outs() << " Version: "
7646 << format("0x%" PRIx32, Version) << '\n';
7648 outs() << " Skipping section with unknown version\n";
7652 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
7653 outs() << " Common encodings array section offset: "
7654 << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
7655 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
7656 outs() << " Number of common encodings in array: "
7657 << format("0x%" PRIx32, NumCommonEncodings) << '\n';
7659 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
7660 outs() << " Personality function array section offset: "
7661 << format("0x%" PRIx32, PersonalitiesStart) << '\n';
7662 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
7663 outs() << " Number of personality functions in array: "
7664 << format("0x%" PRIx32, NumPersonalities) << '\n';
7666 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
7667 outs() << " Index array section offset: "
7668 << format("0x%" PRIx32, IndicesStart) << '\n';
7669 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
7670 outs() << " Number of indices in array: "
7671 << format("0x%" PRIx32, NumIndices) << '\n';
7673 //===----------------------------------
7674 // A shared list of common encodings
7675 //===----------------------------------
7677 // These occupy indices in the range [0, N] whenever an encoding is referenced
7678 // from a compressed 2nd level index table. In practice the linker only
7679 // creates ~128 of these, so that indices are available to embed encodings in
7680 // the 2nd level index.
7682 SmallVector<uint32_t, 64> CommonEncodings;
7683 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n";
7684 Pos = CommonEncodingsStart;
7685 for (unsigned i = 0; i < NumCommonEncodings; ++i) {
7686 uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
7687 CommonEncodings.push_back(Encoding);
7689 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
7693 //===----------------------------------
7694 // Personality functions used in this executable
7695 //===----------------------------------
7697 // There should be only a handful of these (one per source language,
7698 // roughly). Particularly since they only get 2 bits in the compact encoding.
7700 outs() << " Personality functions: (count = " << NumPersonalities << ")\n";
7701 Pos = PersonalitiesStart;
7702 for (unsigned i = 0; i < NumPersonalities; ++i) {
7703 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
7704 outs() << " personality[" << i + 1
7705 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
7708 //===----------------------------------
7709 // The level 1 index entries
7710 //===----------------------------------
7712 // These specify an approximate place to start searching for the more detailed
7713 // information, sorted by PC.
7716 uint32_t FunctionOffset;
7717 uint32_t SecondLevelPageStart;
7721 SmallVector<IndexEntry, 4> IndexEntries;
7723 outs() << " Top level indices: (count = " << NumIndices << ")\n";
7725 for (unsigned i = 0; i < NumIndices; ++i) {
7728 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
7729 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
7730 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
7731 IndexEntries.push_back(Entry);
7733 outs() << " [" << i << "]: "
7734 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
7736 << "2nd level page offset="
7737 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
7738 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
7741 //===----------------------------------
7742 // Next come the LSDA tables
7743 //===----------------------------------
7745 // The LSDA layout is rather implicit: it's a contiguous array of entries from
7746 // the first top-level index's LSDAOffset to the last (sentinel).
7748 outs() << " LSDA descriptors:\n";
7749 Pos = IndexEntries[0].LSDAStart;
7750 const uint32_t LSDASize = 2 * sizeof(uint32_t);
7752 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
7754 for (int i = 0; i < NumLSDAs; ++i) {
7755 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
7756 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
7757 outs() << " [" << i << "]: "
7758 << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7760 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
7763 //===----------------------------------
7764 // Finally, the 2nd level indices
7765 //===----------------------------------
7767 // Generally these are 4K in size, and have 2 possible forms:
7768 // + Regular stores up to 511 entries with disparate encodings
7769 // + Compressed stores up to 1021 entries if few enough compact encoding
7771 outs() << " Second level indices:\n";
7772 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
7773 // The final sentinel top-level index has no associated 2nd level page
7774 if (IndexEntries[i].SecondLevelPageStart == 0)
7777 outs() << " Second level index[" << i << "]: "
7778 << "offset in section="
7779 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
7781 << "base function offset="
7782 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
7784 Pos = IndexEntries[i].SecondLevelPageStart;
7785 if (Pos + sizeof(uint32_t) > Contents.size()) {
7786 outs() << "warning: invalid offset for second level page: " << Pos << '\n';
7791 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
7793 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
7795 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
7796 IndexEntries[i].FunctionOffset,
7799 outs() << " Skipping 2nd level page with unknown kind " << Kind
7804 void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
7805 std::map<uint64_t, SymbolRef> Symbols;
7806 for (const SymbolRef &SymRef : Obj->symbols()) {
7807 // Discard any undefined or absolute symbols. They're not going to take part
7808 // in the convenience lookup for unwind info and just take up resources.
7809 auto SectOrErr = SymRef.getSection();
7811 // TODO: Actually report errors helpfully.
7812 consumeError(SectOrErr.takeError());
7815 section_iterator Section = *SectOrErr;
7816 if (Section == Obj->section_end())
7819 uint64_t Addr = SymRef.getValue();
7820 Symbols.insert(std::make_pair(Addr, SymRef));
7823 for (const SectionRef &Section : Obj->sections()) {
7825 Section.getName(SectName);
7826 if (SectName == "__compact_unwind")
7827 printMachOCompactUnwindSection(Obj, Symbols, Section);
7828 else if (SectName == "__unwind_info")
7829 printMachOUnwindInfoSection(Obj, Symbols, Section);
7833 static void PrintMachHeader(uint32_t magic, uint32_t cputype,
7834 uint32_t cpusubtype, uint32_t filetype,
7835 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
7837 outs() << "Mach header\n";
7838 outs() << " magic cputype cpusubtype caps filetype ncmds "
7839 "sizeofcmds flags\n";
7841 if (magic == MachO::MH_MAGIC)
7842 outs() << " MH_MAGIC";
7843 else if (magic == MachO::MH_MAGIC_64)
7844 outs() << "MH_MAGIC_64";
7846 outs() << format(" 0x%08" PRIx32, magic);
7848 case MachO::CPU_TYPE_I386:
7850 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7851 case MachO::CPU_SUBTYPE_I386_ALL:
7855 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7859 case MachO::CPU_TYPE_X86_64:
7860 outs() << " X86_64";
7861 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7862 case MachO::CPU_SUBTYPE_X86_64_ALL:
7865 case MachO::CPU_SUBTYPE_X86_64_H:
7866 outs() << " Haswell";
7869 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7873 case MachO::CPU_TYPE_ARM:
7875 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7876 case MachO::CPU_SUBTYPE_ARM_ALL:
7879 case MachO::CPU_SUBTYPE_ARM_V4T:
7882 case MachO::CPU_SUBTYPE_ARM_V5TEJ:
7885 case MachO::CPU_SUBTYPE_ARM_XSCALE:
7886 outs() << " XSCALE";
7888 case MachO::CPU_SUBTYPE_ARM_V6:
7891 case MachO::CPU_SUBTYPE_ARM_V6M:
7894 case MachO::CPU_SUBTYPE_ARM_V7:
7897 case MachO::CPU_SUBTYPE_ARM_V7EM:
7900 case MachO::CPU_SUBTYPE_ARM_V7K:
7903 case MachO::CPU_SUBTYPE_ARM_V7M:
7906 case MachO::CPU_SUBTYPE_ARM_V7S:
7910 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7914 case MachO::CPU_TYPE_ARM64:
7916 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7917 case MachO::CPU_SUBTYPE_ARM64_ALL:
7921 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7925 case MachO::CPU_TYPE_POWERPC:
7927 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7928 case MachO::CPU_SUBTYPE_POWERPC_ALL:
7932 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7936 case MachO::CPU_TYPE_POWERPC64:
7938 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7939 case MachO::CPU_SUBTYPE_POWERPC_ALL:
7943 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7948 outs() << format(" %7d", cputype);
7949 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7952 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
7955 outs() << format(" 0x%02" PRIx32,
7956 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
7959 case MachO::MH_OBJECT:
7960 outs() << " OBJECT";
7962 case MachO::MH_EXECUTE:
7963 outs() << " EXECUTE";
7965 case MachO::MH_FVMLIB:
7966 outs() << " FVMLIB";
7968 case MachO::MH_CORE:
7971 case MachO::MH_PRELOAD:
7972 outs() << " PRELOAD";
7974 case MachO::MH_DYLIB:
7977 case MachO::MH_DYLIB_STUB:
7978 outs() << " DYLIB_STUB";
7980 case MachO::MH_DYLINKER:
7981 outs() << " DYLINKER";
7983 case MachO::MH_BUNDLE:
7984 outs() << " BUNDLE";
7986 case MachO::MH_DSYM:
7989 case MachO::MH_KEXT_BUNDLE:
7990 outs() << " KEXTBUNDLE";
7993 outs() << format(" %10u", filetype);
7996 outs() << format(" %5u", ncmds);
7997 outs() << format(" %10u", sizeofcmds);
7999 if (f & MachO::MH_NOUNDEFS) {
8000 outs() << " NOUNDEFS";
8001 f &= ~MachO::MH_NOUNDEFS;
8003 if (f & MachO::MH_INCRLINK) {
8004 outs() << " INCRLINK";
8005 f &= ~MachO::MH_INCRLINK;
8007 if (f & MachO::MH_DYLDLINK) {
8008 outs() << " DYLDLINK";
8009 f &= ~MachO::MH_DYLDLINK;
8011 if (f & MachO::MH_BINDATLOAD) {
8012 outs() << " BINDATLOAD";
8013 f &= ~MachO::MH_BINDATLOAD;
8015 if (f & MachO::MH_PREBOUND) {
8016 outs() << " PREBOUND";
8017 f &= ~MachO::MH_PREBOUND;
8019 if (f & MachO::MH_SPLIT_SEGS) {
8020 outs() << " SPLIT_SEGS";
8021 f &= ~MachO::MH_SPLIT_SEGS;
8023 if (f & MachO::MH_LAZY_INIT) {
8024 outs() << " LAZY_INIT";
8025 f &= ~MachO::MH_LAZY_INIT;
8027 if (f & MachO::MH_TWOLEVEL) {
8028 outs() << " TWOLEVEL";
8029 f &= ~MachO::MH_TWOLEVEL;
8031 if (f & MachO::MH_FORCE_FLAT) {
8032 outs() << " FORCE_FLAT";
8033 f &= ~MachO::MH_FORCE_FLAT;
8035 if (f & MachO::MH_NOMULTIDEFS) {
8036 outs() << " NOMULTIDEFS";
8037 f &= ~MachO::MH_NOMULTIDEFS;
8039 if (f & MachO::MH_NOFIXPREBINDING) {
8040 outs() << " NOFIXPREBINDING";
8041 f &= ~MachO::MH_NOFIXPREBINDING;
8043 if (f & MachO::MH_PREBINDABLE) {
8044 outs() << " PREBINDABLE";
8045 f &= ~MachO::MH_PREBINDABLE;
8047 if (f & MachO::MH_ALLMODSBOUND) {
8048 outs() << " ALLMODSBOUND";
8049 f &= ~MachO::MH_ALLMODSBOUND;
8051 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
8052 outs() << " SUBSECTIONS_VIA_SYMBOLS";
8053 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
8055 if (f & MachO::MH_CANONICAL) {
8056 outs() << " CANONICAL";
8057 f &= ~MachO::MH_CANONICAL;
8059 if (f & MachO::MH_WEAK_DEFINES) {
8060 outs() << " WEAK_DEFINES";
8061 f &= ~MachO::MH_WEAK_DEFINES;
8063 if (f & MachO::MH_BINDS_TO_WEAK) {
8064 outs() << " BINDS_TO_WEAK";
8065 f &= ~MachO::MH_BINDS_TO_WEAK;
8067 if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
8068 outs() << " ALLOW_STACK_EXECUTION";
8069 f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
8071 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
8072 outs() << " DEAD_STRIPPABLE_DYLIB";
8073 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
8075 if (f & MachO::MH_PIE) {
8077 f &= ~MachO::MH_PIE;
8079 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
8080 outs() << " NO_REEXPORTED_DYLIBS";
8081 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
8083 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
8084 outs() << " MH_HAS_TLV_DESCRIPTORS";
8085 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
8087 if (f & MachO::MH_NO_HEAP_EXECUTION) {
8088 outs() << " MH_NO_HEAP_EXECUTION";
8089 f &= ~MachO::MH_NO_HEAP_EXECUTION;
8091 if (f & MachO::MH_APP_EXTENSION_SAFE) {
8092 outs() << " APP_EXTENSION_SAFE";
8093 f &= ~MachO::MH_APP_EXTENSION_SAFE;
8095 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
8096 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO";
8097 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO;
8099 if (f != 0 || flags == 0)
8100 outs() << format(" 0x%08" PRIx32, f);
8102 outs() << format(" 0x%08" PRIx32, magic);
8103 outs() << format(" %7d", cputype);
8104 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8105 outs() << format(" 0x%02" PRIx32,
8106 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8107 outs() << format(" %10u", filetype);
8108 outs() << format(" %5u", ncmds);
8109 outs() << format(" %10u", sizeofcmds);
8110 outs() << format(" 0x%08" PRIx32, flags);
8115 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
8116 StringRef SegName, uint64_t vmaddr,
8117 uint64_t vmsize, uint64_t fileoff,
8118 uint64_t filesize, uint32_t maxprot,
8119 uint32_t initprot, uint32_t nsects,
8120 uint32_t flags, uint32_t object_size,
8122 uint64_t expected_cmdsize;
8123 if (cmd == MachO::LC_SEGMENT) {
8124 outs() << " cmd LC_SEGMENT\n";
8125 expected_cmdsize = nsects;
8126 expected_cmdsize *= sizeof(struct MachO::section);
8127 expected_cmdsize += sizeof(struct MachO::segment_command);
8129 outs() << " cmd LC_SEGMENT_64\n";
8130 expected_cmdsize = nsects;
8131 expected_cmdsize *= sizeof(struct MachO::section_64);
8132 expected_cmdsize += sizeof(struct MachO::segment_command_64);
8134 outs() << " cmdsize " << cmdsize;
8135 if (cmdsize != expected_cmdsize)
8136 outs() << " Inconsistent size\n";
8139 outs() << " segname " << SegName << "\n";
8140 if (cmd == MachO::LC_SEGMENT_64) {
8141 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
8142 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
8144 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
8145 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
8147 outs() << " fileoff " << fileoff;
8148 if (fileoff > object_size)
8149 outs() << " (past end of file)\n";
8152 outs() << " filesize " << filesize;
8153 if (fileoff + filesize > object_size)
8154 outs() << " (past end of file)\n";
8159 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8160 MachO::VM_PROT_EXECUTE)) != 0)
8161 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
8163 outs() << " maxprot ";
8164 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
8165 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8166 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8169 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8170 MachO::VM_PROT_EXECUTE)) != 0)
8171 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
8173 outs() << " initprot ";
8174 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
8175 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8176 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8179 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
8180 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
8182 outs() << " nsects " << nsects << "\n";
8186 outs() << " (none)\n";
8188 if (flags & MachO::SG_HIGHVM) {
8189 outs() << " HIGHVM";
8190 flags &= ~MachO::SG_HIGHVM;
8192 if (flags & MachO::SG_FVMLIB) {
8193 outs() << " FVMLIB";
8194 flags &= ~MachO::SG_FVMLIB;
8196 if (flags & MachO::SG_NORELOC) {
8197 outs() << " NORELOC";
8198 flags &= ~MachO::SG_NORELOC;
8200 if (flags & MachO::SG_PROTECTED_VERSION_1) {
8201 outs() << " PROTECTED_VERSION_1";
8202 flags &= ~MachO::SG_PROTECTED_VERSION_1;
8205 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
8210 outs() << " flags " << format("0x%" PRIx32, flags) << "\n";
8214 static void PrintSection(const char *sectname, const char *segname,
8215 uint64_t addr, uint64_t size, uint32_t offset,
8216 uint32_t align, uint32_t reloff, uint32_t nreloc,
8217 uint32_t flags, uint32_t reserved1, uint32_t reserved2,
8218 uint32_t cmd, const char *sg_segname,
8219 uint32_t filetype, uint32_t object_size,
8221 outs() << "Section\n";
8222 outs() << " sectname " << format("%.16s\n", sectname);
8223 outs() << " segname " << format("%.16s", segname);
8224 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
8225 outs() << " (does not match segment)\n";
8228 if (cmd == MachO::LC_SEGMENT_64) {
8229 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n";
8230 outs() << " size " << format("0x%016" PRIx64, size);
8232 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n";
8233 outs() << " size " << format("0x%08" PRIx64, size);
8235 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
8236 outs() << " (past end of file)\n";
8239 outs() << " offset " << offset;
8240 if (offset > object_size)
8241 outs() << " (past end of file)\n";
8244 uint32_t align_shifted = 1 << align;
8245 outs() << " align 2^" << align << " (" << align_shifted << ")\n";
8246 outs() << " reloff " << reloff;
8247 if (reloff > object_size)
8248 outs() << " (past end of file)\n";
8251 outs() << " nreloc " << nreloc;
8252 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
8253 outs() << " (past end of file)\n";
8256 uint32_t section_type = flags & MachO::SECTION_TYPE;
8259 if (section_type == MachO::S_REGULAR)
8260 outs() << " S_REGULAR\n";
8261 else if (section_type == MachO::S_ZEROFILL)
8262 outs() << " S_ZEROFILL\n";
8263 else if (section_type == MachO::S_CSTRING_LITERALS)
8264 outs() << " S_CSTRING_LITERALS\n";
8265 else if (section_type == MachO::S_4BYTE_LITERALS)
8266 outs() << " S_4BYTE_LITERALS\n";
8267 else if (section_type == MachO::S_8BYTE_LITERALS)
8268 outs() << " S_8BYTE_LITERALS\n";
8269 else if (section_type == MachO::S_16BYTE_LITERALS)
8270 outs() << " S_16BYTE_LITERALS\n";
8271 else if (section_type == MachO::S_LITERAL_POINTERS)
8272 outs() << " S_LITERAL_POINTERS\n";
8273 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
8274 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
8275 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
8276 outs() << " S_LAZY_SYMBOL_POINTERS\n";
8277 else if (section_type == MachO::S_SYMBOL_STUBS)
8278 outs() << " S_SYMBOL_STUBS\n";
8279 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
8280 outs() << " S_MOD_INIT_FUNC_POINTERS\n";
8281 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
8282 outs() << " S_MOD_TERM_FUNC_POINTERS\n";
8283 else if (section_type == MachO::S_COALESCED)
8284 outs() << " S_COALESCED\n";
8285 else if (section_type == MachO::S_INTERPOSING)
8286 outs() << " S_INTERPOSING\n";
8287 else if (section_type == MachO::S_DTRACE_DOF)
8288 outs() << " S_DTRACE_DOF\n";
8289 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
8290 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
8291 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
8292 outs() << " S_THREAD_LOCAL_REGULAR\n";
8293 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
8294 outs() << " S_THREAD_LOCAL_ZEROFILL\n";
8295 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
8296 outs() << " S_THREAD_LOCAL_VARIABLES\n";
8297 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8298 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
8299 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
8300 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
8302 outs() << format("0x%08" PRIx32, section_type) << "\n";
8303 outs() << "attributes";
8304 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
8305 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
8306 outs() << " PURE_INSTRUCTIONS";
8307 if (section_attributes & MachO::S_ATTR_NO_TOC)
8308 outs() << " NO_TOC";
8309 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
8310 outs() << " STRIP_STATIC_SYMS";
8311 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
8312 outs() << " NO_DEAD_STRIP";
8313 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
8314 outs() << " LIVE_SUPPORT";
8315 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
8316 outs() << " SELF_MODIFYING_CODE";
8317 if (section_attributes & MachO::S_ATTR_DEBUG)
8319 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
8320 outs() << " SOME_INSTRUCTIONS";
8321 if (section_attributes & MachO::S_ATTR_EXT_RELOC)
8322 outs() << " EXT_RELOC";
8323 if (section_attributes & MachO::S_ATTR_LOC_RELOC)
8324 outs() << " LOC_RELOC";
8325 if (section_attributes == 0)
8326 outs() << " (none)";
8329 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n";
8330 outs() << " reserved1 " << reserved1;
8331 if (section_type == MachO::S_SYMBOL_STUBS ||
8332 section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
8333 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
8334 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
8335 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8336 outs() << " (index into indirect symbol table)\n";
8339 outs() << " reserved2 " << reserved2;
8340 if (section_type == MachO::S_SYMBOL_STUBS)
8341 outs() << " (size of stubs)\n";
8346 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
8347 uint32_t object_size) {
8348 outs() << " cmd LC_SYMTAB\n";
8349 outs() << " cmdsize " << st.cmdsize;
8350 if (st.cmdsize != sizeof(struct MachO::symtab_command))
8351 outs() << " Incorrect size\n";
8354 outs() << " symoff " << st.symoff;
8355 if (st.symoff > object_size)
8356 outs() << " (past end of file)\n";
8359 outs() << " nsyms " << st.nsyms;
8362 big_size = st.nsyms;
8363 big_size *= sizeof(struct MachO::nlist_64);
8364 big_size += st.symoff;
8365 if (big_size > object_size)
8366 outs() << " (past end of file)\n";
8370 big_size = st.nsyms;
8371 big_size *= sizeof(struct MachO::nlist);
8372 big_size += st.symoff;
8373 if (big_size > object_size)
8374 outs() << " (past end of file)\n";
8378 outs() << " stroff " << st.stroff;
8379 if (st.stroff > object_size)
8380 outs() << " (past end of file)\n";
8383 outs() << " strsize " << st.strsize;
8384 big_size = st.stroff;
8385 big_size += st.strsize;
8386 if (big_size > object_size)
8387 outs() << " (past end of file)\n";
8392 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
8393 uint32_t nsyms, uint32_t object_size,
8395 outs() << " cmd LC_DYSYMTAB\n";
8396 outs() << " cmdsize " << dyst.cmdsize;
8397 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
8398 outs() << " Incorrect size\n";
8401 outs() << " ilocalsym " << dyst.ilocalsym;
8402 if (dyst.ilocalsym > nsyms)
8403 outs() << " (greater than the number of symbols)\n";
8406 outs() << " nlocalsym " << dyst.nlocalsym;
8408 big_size = dyst.ilocalsym;
8409 big_size += dyst.nlocalsym;
8410 if (big_size > nsyms)
8411 outs() << " (past the end of the symbol table)\n";
8414 outs() << " iextdefsym " << dyst.iextdefsym;
8415 if (dyst.iextdefsym > nsyms)
8416 outs() << " (greater than the number of symbols)\n";
8419 outs() << " nextdefsym " << dyst.nextdefsym;
8420 big_size = dyst.iextdefsym;
8421 big_size += dyst.nextdefsym;
8422 if (big_size > nsyms)
8423 outs() << " (past the end of the symbol table)\n";
8426 outs() << " iundefsym " << dyst.iundefsym;
8427 if (dyst.iundefsym > nsyms)
8428 outs() << " (greater than the number of symbols)\n";
8431 outs() << " nundefsym " << dyst.nundefsym;
8432 big_size = dyst.iundefsym;
8433 big_size += dyst.nundefsym;
8434 if (big_size > nsyms)
8435 outs() << " (past the end of the symbol table)\n";
8438 outs() << " tocoff " << dyst.tocoff;
8439 if (dyst.tocoff > object_size)
8440 outs() << " (past end of file)\n";
8443 outs() << " ntoc " << dyst.ntoc;
8444 big_size = dyst.ntoc;
8445 big_size *= sizeof(struct MachO::dylib_table_of_contents);
8446 big_size += dyst.tocoff;
8447 if (big_size > object_size)
8448 outs() << " (past end of file)\n";
8451 outs() << " modtaboff " << dyst.modtaboff;
8452 if (dyst.modtaboff > object_size)
8453 outs() << " (past end of file)\n";
8456 outs() << " nmodtab " << dyst.nmodtab;
8459 modtabend = dyst.nmodtab;
8460 modtabend *= sizeof(struct MachO::dylib_module_64);
8461 modtabend += dyst.modtaboff;
8463 modtabend = dyst.nmodtab;
8464 modtabend *= sizeof(struct MachO::dylib_module);
8465 modtabend += dyst.modtaboff;
8467 if (modtabend > object_size)
8468 outs() << " (past end of file)\n";
8471 outs() << " extrefsymoff " << dyst.extrefsymoff;
8472 if (dyst.extrefsymoff > object_size)
8473 outs() << " (past end of file)\n";
8476 outs() << " nextrefsyms " << dyst.nextrefsyms;
8477 big_size = dyst.nextrefsyms;
8478 big_size *= sizeof(struct MachO::dylib_reference);
8479 big_size += dyst.extrefsymoff;
8480 if (big_size > object_size)
8481 outs() << " (past end of file)\n";
8484 outs() << " indirectsymoff " << dyst.indirectsymoff;
8485 if (dyst.indirectsymoff > object_size)
8486 outs() << " (past end of file)\n";
8489 outs() << " nindirectsyms " << dyst.nindirectsyms;
8490 big_size = dyst.nindirectsyms;
8491 big_size *= sizeof(uint32_t);
8492 big_size += dyst.indirectsymoff;
8493 if (big_size > object_size)
8494 outs() << " (past end of file)\n";
8497 outs() << " extreloff " << dyst.extreloff;
8498 if (dyst.extreloff > object_size)
8499 outs() << " (past end of file)\n";
8502 outs() << " nextrel " << dyst.nextrel;
8503 big_size = dyst.nextrel;
8504 big_size *= sizeof(struct MachO::relocation_info);
8505 big_size += dyst.extreloff;
8506 if (big_size > object_size)
8507 outs() << " (past end of file)\n";
8510 outs() << " locreloff " << dyst.locreloff;
8511 if (dyst.locreloff > object_size)
8512 outs() << " (past end of file)\n";
8515 outs() << " nlocrel " << dyst.nlocrel;
8516 big_size = dyst.nlocrel;
8517 big_size *= sizeof(struct MachO::relocation_info);
8518 big_size += dyst.locreloff;
8519 if (big_size > object_size)
8520 outs() << " (past end of file)\n";
8525 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
8526 uint32_t object_size) {
8527 if (dc.cmd == MachO::LC_DYLD_INFO)
8528 outs() << " cmd LC_DYLD_INFO\n";
8530 outs() << " cmd LC_DYLD_INFO_ONLY\n";
8531 outs() << " cmdsize " << dc.cmdsize;
8532 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
8533 outs() << " Incorrect size\n";
8536 outs() << " rebase_off " << dc.rebase_off;
8537 if (dc.rebase_off > object_size)
8538 outs() << " (past end of file)\n";
8541 outs() << " rebase_size " << dc.rebase_size;
8543 big_size = dc.rebase_off;
8544 big_size += dc.rebase_size;
8545 if (big_size > object_size)
8546 outs() << " (past end of file)\n";
8549 outs() << " bind_off " << dc.bind_off;
8550 if (dc.bind_off > object_size)
8551 outs() << " (past end of file)\n";
8554 outs() << " bind_size " << dc.bind_size;
8555 big_size = dc.bind_off;
8556 big_size += dc.bind_size;
8557 if (big_size > object_size)
8558 outs() << " (past end of file)\n";
8561 outs() << " weak_bind_off " << dc.weak_bind_off;
8562 if (dc.weak_bind_off > object_size)
8563 outs() << " (past end of file)\n";
8566 outs() << " weak_bind_size " << dc.weak_bind_size;
8567 big_size = dc.weak_bind_off;
8568 big_size += dc.weak_bind_size;
8569 if (big_size > object_size)
8570 outs() << " (past end of file)\n";
8573 outs() << " lazy_bind_off " << dc.lazy_bind_off;
8574 if (dc.lazy_bind_off > object_size)
8575 outs() << " (past end of file)\n";
8578 outs() << " lazy_bind_size " << dc.lazy_bind_size;
8579 big_size = dc.lazy_bind_off;
8580 big_size += dc.lazy_bind_size;
8581 if (big_size > object_size)
8582 outs() << " (past end of file)\n";
8585 outs() << " export_off " << dc.export_off;
8586 if (dc.export_off > object_size)
8587 outs() << " (past end of file)\n";
8590 outs() << " export_size " << dc.export_size;
8591 big_size = dc.export_off;
8592 big_size += dc.export_size;
8593 if (big_size > object_size)
8594 outs() << " (past end of file)\n";
8599 static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
8601 if (dyld.cmd == MachO::LC_ID_DYLINKER)
8602 outs() << " cmd LC_ID_DYLINKER\n";
8603 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
8604 outs() << " cmd LC_LOAD_DYLINKER\n";
8605 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
8606 outs() << " cmd LC_DYLD_ENVIRONMENT\n";
8608 outs() << " cmd ?(" << dyld.cmd << ")\n";
8609 outs() << " cmdsize " << dyld.cmdsize;
8610 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
8611 outs() << " Incorrect size\n";
8614 if (dyld.name >= dyld.cmdsize)
8615 outs() << " name ?(bad offset " << dyld.name << ")\n";
8617 const char *P = (const char *)(Ptr) + dyld.name;
8618 outs() << " name " << P << " (offset " << dyld.name << ")\n";
8622 static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
8623 outs() << " cmd LC_UUID\n";
8624 outs() << " cmdsize " << uuid.cmdsize;
8625 if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
8626 outs() << " Incorrect size\n";
8630 for (int i = 0; i < 16; ++i) {
8631 outs() << format("%02" PRIX32, uuid.uuid[i]);
8632 if (i == 3 || i == 5 || i == 7 || i == 9)
8638 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
8639 outs() << " cmd LC_RPATH\n";
8640 outs() << " cmdsize " << rpath.cmdsize;
8641 if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
8642 outs() << " Incorrect size\n";
8645 if (rpath.path >= rpath.cmdsize)
8646 outs() << " path ?(bad offset " << rpath.path << ")\n";
8648 const char *P = (const char *)(Ptr) + rpath.path;
8649 outs() << " path " << P << " (offset " << rpath.path << ")\n";
8653 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
8654 StringRef LoadCmdName;
8656 case MachO::LC_VERSION_MIN_MACOSX:
8657 LoadCmdName = "LC_VERSION_MIN_MACOSX";
8659 case MachO::LC_VERSION_MIN_IPHONEOS:
8660 LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
8662 case MachO::LC_VERSION_MIN_TVOS:
8663 LoadCmdName = "LC_VERSION_MIN_TVOS";
8665 case MachO::LC_VERSION_MIN_WATCHOS:
8666 LoadCmdName = "LC_VERSION_MIN_WATCHOS";
8669 llvm_unreachable("Unknown version min load command");
8672 outs() << " cmd " << LoadCmdName << '\n';
8673 outs() << " cmdsize " << vd.cmdsize;
8674 if (vd.cmdsize != sizeof(struct MachO::version_min_command))
8675 outs() << " Incorrect size\n";
8678 outs() << " version "
8679 << MachOObjectFile::getVersionMinMajor(vd, false) << "."
8680 << MachOObjectFile::getVersionMinMinor(vd, false);
8681 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
8683 outs() << "." << Update;
8686 outs() << " sdk n/a";
8689 << MachOObjectFile::getVersionMinMajor(vd, true) << "."
8690 << MachOObjectFile::getVersionMinMinor(vd, true);
8692 Update = MachOObjectFile::getVersionMinUpdate(vd, true);
8694 outs() << "." << Update;
8698 static void PrintNoteLoadCommand(MachO::note_command Nt) {
8699 outs() << " cmd LC_NOTE\n";
8700 outs() << " cmdsize " << Nt.cmdsize;
8701 if (Nt.cmdsize != sizeof(struct MachO::note_command))
8702 outs() << " Incorrect size\n";
8705 const char *d = Nt.data_owner;
8706 outs() << "data_owner " << format("%.16s\n", d);
8707 outs() << " offset " << Nt.offset << "\n";
8708 outs() << " size " << Nt.size << "\n";
8711 static void PrintBuildToolVersion(MachO::build_tool_version bv) {
8712 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n";
8713 outs() << " version " << MachOObjectFile::getVersionString(bv.version)
8717 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj,
8718 MachO::build_version_command bd) {
8719 outs() << " cmd LC_BUILD_VERSION\n";
8720 outs() << " cmdsize " << bd.cmdsize;
8722 sizeof(struct MachO::build_version_command) +
8723 bd.ntools * sizeof(struct MachO::build_tool_version))
8724 outs() << " Incorrect size\n";
8727 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform)
8730 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk)
8733 outs() << " sdk n/a\n";
8734 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos)
8736 outs() << " ntools " << bd.ntools << "\n";
8737 for (unsigned i = 0; i < bd.ntools; ++i) {
8738 MachO::build_tool_version bv = obj->getBuildToolVersion(i);
8739 PrintBuildToolVersion(bv);
8743 static void PrintSourceVersionCommand(MachO::source_version_command sd) {
8744 outs() << " cmd LC_SOURCE_VERSION\n";
8745 outs() << " cmdsize " << sd.cmdsize;
8746 if (sd.cmdsize != sizeof(struct MachO::source_version_command))
8747 outs() << " Incorrect size\n";
8750 uint64_t a = (sd.version >> 40) & 0xffffff;
8751 uint64_t b = (sd.version >> 30) & 0x3ff;
8752 uint64_t c = (sd.version >> 20) & 0x3ff;
8753 uint64_t d = (sd.version >> 10) & 0x3ff;
8754 uint64_t e = sd.version & 0x3ff;
8755 outs() << " version " << a << "." << b;
8757 outs() << "." << c << "." << d << "." << e;
8759 outs() << "." << c << "." << d;
8765 static void PrintEntryPointCommand(MachO::entry_point_command ep) {
8766 outs() << " cmd LC_MAIN\n";
8767 outs() << " cmdsize " << ep.cmdsize;
8768 if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
8769 outs() << " Incorrect size\n";
8772 outs() << " entryoff " << ep.entryoff << "\n";
8773 outs() << " stacksize " << ep.stacksize << "\n";
8776 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
8777 uint32_t object_size) {
8778 outs() << " cmd LC_ENCRYPTION_INFO\n";
8779 outs() << " cmdsize " << ec.cmdsize;
8780 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
8781 outs() << " Incorrect size\n";
8784 outs() << " cryptoff " << ec.cryptoff;
8785 if (ec.cryptoff > object_size)
8786 outs() << " (past end of file)\n";
8789 outs() << " cryptsize " << ec.cryptsize;
8790 if (ec.cryptsize > object_size)
8791 outs() << " (past end of file)\n";
8794 outs() << " cryptid " << ec.cryptid << "\n";
8797 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
8798 uint32_t object_size) {
8799 outs() << " cmd LC_ENCRYPTION_INFO_64\n";
8800 outs() << " cmdsize " << ec.cmdsize;
8801 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
8802 outs() << " Incorrect size\n";
8805 outs() << " cryptoff " << ec.cryptoff;
8806 if (ec.cryptoff > object_size)
8807 outs() << " (past end of file)\n";
8810 outs() << " cryptsize " << ec.cryptsize;
8811 if (ec.cryptsize > object_size)
8812 outs() << " (past end of file)\n";
8815 outs() << " cryptid " << ec.cryptid << "\n";
8816 outs() << " pad " << ec.pad << "\n";
8819 static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
8821 outs() << " cmd LC_LINKER_OPTION\n";
8822 outs() << " cmdsize " << lo.cmdsize;
8823 if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
8824 outs() << " Incorrect size\n";
8827 outs() << " count " << lo.count << "\n";
8828 const char *string = Ptr + sizeof(struct MachO::linker_option_command);
8829 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
8832 while (*string == '\0' && left > 0) {
8838 outs() << " string #" << i << " " << format("%.*s\n", left, string);
8839 uint32_t NullPos = StringRef(string, left).find('\0');
8840 uint32_t len = std::min(NullPos, left) + 1;
8846 outs() << " count " << lo.count << " does not match number of strings "
8850 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
8852 outs() << " cmd LC_SUB_FRAMEWORK\n";
8853 outs() << " cmdsize " << sub.cmdsize;
8854 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
8855 outs() << " Incorrect size\n";
8858 if (sub.umbrella < sub.cmdsize) {
8859 const char *P = Ptr + sub.umbrella;
8860 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n";
8862 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n";
8866 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
8868 outs() << " cmd LC_SUB_UMBRELLA\n";
8869 outs() << " cmdsize " << sub.cmdsize;
8870 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
8871 outs() << " Incorrect size\n";
8874 if (sub.sub_umbrella < sub.cmdsize) {
8875 const char *P = Ptr + sub.sub_umbrella;
8876 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
8878 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
8882 static void PrintSubLibraryCommand(MachO::sub_library_command sub,
8884 outs() << " cmd LC_SUB_LIBRARY\n";
8885 outs() << " cmdsize " << sub.cmdsize;
8886 if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
8887 outs() << " Incorrect size\n";
8890 if (sub.sub_library < sub.cmdsize) {
8891 const char *P = Ptr + sub.sub_library;
8892 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n";
8894 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n";
8898 static void PrintSubClientCommand(MachO::sub_client_command sub,
8900 outs() << " cmd LC_SUB_CLIENT\n";
8901 outs() << " cmdsize " << sub.cmdsize;
8902 if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
8903 outs() << " Incorrect size\n";
8906 if (sub.client < sub.cmdsize) {
8907 const char *P = Ptr + sub.client;
8908 outs() << " client " << P << " (offset " << sub.client << ")\n";
8910 outs() << " client ?(bad offset " << sub.client << ")\n";
8914 static void PrintRoutinesCommand(MachO::routines_command r) {
8915 outs() << " cmd LC_ROUTINES\n";
8916 outs() << " cmdsize " << r.cmdsize;
8917 if (r.cmdsize != sizeof(struct MachO::routines_command))
8918 outs() << " Incorrect size\n";
8921 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
8922 outs() << " init_module " << r.init_module << "\n";
8923 outs() << " reserved1 " << r.reserved1 << "\n";
8924 outs() << " reserved2 " << r.reserved2 << "\n";
8925 outs() << " reserved3 " << r.reserved3 << "\n";
8926 outs() << " reserved4 " << r.reserved4 << "\n";
8927 outs() << " reserved5 " << r.reserved5 << "\n";
8928 outs() << " reserved6 " << r.reserved6 << "\n";
8931 static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
8932 outs() << " cmd LC_ROUTINES_64\n";
8933 outs() << " cmdsize " << r.cmdsize;
8934 if (r.cmdsize != sizeof(struct MachO::routines_command_64))
8935 outs() << " Incorrect size\n";
8938 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
8939 outs() << " init_module " << r.init_module << "\n";
8940 outs() << " reserved1 " << r.reserved1 << "\n";
8941 outs() << " reserved2 " << r.reserved2 << "\n";
8942 outs() << " reserved3 " << r.reserved3 << "\n";
8943 outs() << " reserved4 " << r.reserved4 << "\n";
8944 outs() << " reserved5 " << r.reserved5 << "\n";
8945 outs() << " reserved6 " << r.reserved6 << "\n";
8948 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) {
8949 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax);
8950 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx);
8951 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx);
8952 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n";
8953 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi);
8954 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi);
8955 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp);
8956 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n";
8957 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss);
8958 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags);
8959 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip);
8960 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n";
8961 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds);
8962 outs() << " es " << format("0x%08" PRIx32, cpu32.es);
8963 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs);
8964 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n";
8967 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
8968 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax);
8969 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
8970 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
8971 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx);
8972 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
8973 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
8974 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp);
8975 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
8976 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n";
8977 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9);
8978 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
8979 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n";
8980 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12);
8981 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
8982 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n";
8983 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15);
8984 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
8985 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags);
8986 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs);
8987 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n";
8988 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n";
8991 static void Print_mmst_reg(MachO::mmst_reg_t &r) {
8993 outs() << "\t mmst_reg ";
8994 for (f = 0; f < 10; f++)
8995 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
8997 outs() << "\t mmst_rsrv ";
8998 for (f = 0; f < 6; f++)
8999 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
9003 static void Print_xmm_reg(MachO::xmm_reg_t &r) {
9005 outs() << "\t xmm_reg ";
9006 for (f = 0; f < 16; f++)
9007 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
9011 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
9012 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0];
9013 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
9014 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid;
9015 outs() << " denorm " << fpu.fpu_fcw.denorm;
9016 outs() << " zdiv " << fpu.fpu_fcw.zdiv;
9017 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
9018 outs() << " undfl " << fpu.fpu_fcw.undfl;
9019 outs() << " precis " << fpu.fpu_fcw.precis << "\n";
9020 outs() << "\t\t pc ";
9021 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
9022 outs() << "FP_PREC_24B ";
9023 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
9024 outs() << "FP_PREC_53B ";
9025 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
9026 outs() << "FP_PREC_64B ";
9028 outs() << fpu.fpu_fcw.pc << " ";
9030 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
9031 outs() << "FP_RND_NEAR ";
9032 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
9033 outs() << "FP_RND_DOWN ";
9034 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
9035 outs() << "FP_RND_UP ";
9036 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
9037 outs() << "FP_CHOP ";
9039 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid;
9040 outs() << " denorm " << fpu.fpu_fsw.denorm;
9041 outs() << " zdiv " << fpu.fpu_fsw.zdiv;
9042 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
9043 outs() << " undfl " << fpu.fpu_fsw.undfl;
9044 outs() << " precis " << fpu.fpu_fsw.precis;
9045 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
9046 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm;
9047 outs() << " c0 " << fpu.fpu_fsw.c0;
9048 outs() << " c1 " << fpu.fpu_fsw.c1;
9049 outs() << " c2 " << fpu.fpu_fsw.c2;
9050 outs() << " tos " << fpu.fpu_fsw.tos;
9051 outs() << " c3 " << fpu.fpu_fsw.c3;
9052 outs() << " busy " << fpu.fpu_fsw.busy << "\n";
9053 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
9054 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
9055 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
9056 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
9057 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
9058 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
9059 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
9060 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
9061 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
9062 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
9063 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
9065 outs() << "\t fpu_stmm0:\n";
9066 Print_mmst_reg(fpu.fpu_stmm0);
9067 outs() << "\t fpu_stmm1:\n";
9068 Print_mmst_reg(fpu.fpu_stmm1);
9069 outs() << "\t fpu_stmm2:\n";
9070 Print_mmst_reg(fpu.fpu_stmm2);
9071 outs() << "\t fpu_stmm3:\n";
9072 Print_mmst_reg(fpu.fpu_stmm3);
9073 outs() << "\t fpu_stmm4:\n";
9074 Print_mmst_reg(fpu.fpu_stmm4);
9075 outs() << "\t fpu_stmm5:\n";
9076 Print_mmst_reg(fpu.fpu_stmm5);
9077 outs() << "\t fpu_stmm6:\n";
9078 Print_mmst_reg(fpu.fpu_stmm6);
9079 outs() << "\t fpu_stmm7:\n";
9080 Print_mmst_reg(fpu.fpu_stmm7);
9081 outs() << "\t fpu_xmm0:\n";
9082 Print_xmm_reg(fpu.fpu_xmm0);
9083 outs() << "\t fpu_xmm1:\n";
9084 Print_xmm_reg(fpu.fpu_xmm1);
9085 outs() << "\t fpu_xmm2:\n";
9086 Print_xmm_reg(fpu.fpu_xmm2);
9087 outs() << "\t fpu_xmm3:\n";
9088 Print_xmm_reg(fpu.fpu_xmm3);
9089 outs() << "\t fpu_xmm4:\n";
9090 Print_xmm_reg(fpu.fpu_xmm4);
9091 outs() << "\t fpu_xmm5:\n";
9092 Print_xmm_reg(fpu.fpu_xmm5);
9093 outs() << "\t fpu_xmm6:\n";
9094 Print_xmm_reg(fpu.fpu_xmm6);
9095 outs() << "\t fpu_xmm7:\n";
9096 Print_xmm_reg(fpu.fpu_xmm7);
9097 outs() << "\t fpu_xmm8:\n";
9098 Print_xmm_reg(fpu.fpu_xmm8);
9099 outs() << "\t fpu_xmm9:\n";
9100 Print_xmm_reg(fpu.fpu_xmm9);
9101 outs() << "\t fpu_xmm10:\n";
9102 Print_xmm_reg(fpu.fpu_xmm10);
9103 outs() << "\t fpu_xmm11:\n";
9104 Print_xmm_reg(fpu.fpu_xmm11);
9105 outs() << "\t fpu_xmm12:\n";
9106 Print_xmm_reg(fpu.fpu_xmm12);
9107 outs() << "\t fpu_xmm13:\n";
9108 Print_xmm_reg(fpu.fpu_xmm13);
9109 outs() << "\t fpu_xmm14:\n";
9110 Print_xmm_reg(fpu.fpu_xmm14);
9111 outs() << "\t fpu_xmm15:\n";
9112 Print_xmm_reg(fpu.fpu_xmm15);
9113 outs() << "\t fpu_rsrv4:\n";
9114 for (uint32_t f = 0; f < 6; f++) {
9116 for (uint32_t g = 0; g < 16; g++)
9117 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
9120 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
9124 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
9125 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno);
9126 outs() << " err " << format("0x%08" PRIx32, exc64.err);
9127 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
9130 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
9131 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]);
9132 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]);
9133 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]);
9134 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n";
9135 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]);
9136 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]);
9137 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]);
9138 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n";
9139 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]);
9140 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]);
9141 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]);
9142 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n";
9143 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]);
9144 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp);
9145 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr);
9146 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n";
9147 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n";
9150 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
9151 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]);
9152 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]);
9153 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n";
9154 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]);
9155 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]);
9156 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n";
9157 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]);
9158 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]);
9159 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n";
9160 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]);
9161 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]);
9162 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n";
9163 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]);
9164 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]);
9165 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n";
9166 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]);
9167 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]);
9168 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n";
9169 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]);
9170 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]);
9171 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n";
9172 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]);
9173 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]);
9174 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n";
9175 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]);
9176 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]);
9177 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n";
9178 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]);
9179 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]);
9180 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n";
9181 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr);
9182 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp);
9183 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n";
9184 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n";
9187 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
9188 bool isLittleEndian, uint32_t cputype) {
9189 if (t.cmd == MachO::LC_THREAD)
9190 outs() << " cmd LC_THREAD\n";
9191 else if (t.cmd == MachO::LC_UNIXTHREAD)
9192 outs() << " cmd LC_UNIXTHREAD\n";
9194 outs() << " cmd " << t.cmd << " (unknown)\n";
9195 outs() << " cmdsize " << t.cmdsize;
9196 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
9197 outs() << " Incorrect size\n";
9201 const char *begin = Ptr + sizeof(struct MachO::thread_command);
9202 const char *end = Ptr + t.cmdsize;
9203 uint32_t flavor, count, left;
9204 if (cputype == MachO::CPU_TYPE_I386) {
9205 while (begin < end) {
9206 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9207 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9208 begin += sizeof(uint32_t);
9213 if (isLittleEndian != sys::IsLittleEndianHost)
9214 sys::swapByteOrder(flavor);
9215 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9216 memcpy((char *)&count, begin, sizeof(uint32_t));
9217 begin += sizeof(uint32_t);
9222 if (isLittleEndian != sys::IsLittleEndianHost)
9223 sys::swapByteOrder(count);
9224 if (flavor == MachO::x86_THREAD_STATE32) {
9225 outs() << " flavor i386_THREAD_STATE\n";
9226 if (count == MachO::x86_THREAD_STATE32_COUNT)
9227 outs() << " count i386_THREAD_STATE_COUNT\n";
9229 outs() << " count " << count
9230 << " (not x86_THREAD_STATE32_COUNT)\n";
9231 MachO::x86_thread_state32_t cpu32;
9233 if (left >= sizeof(MachO::x86_thread_state32_t)) {
9234 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t));
9235 begin += sizeof(MachO::x86_thread_state32_t);
9237 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t));
9238 memcpy(&cpu32, begin, left);
9241 if (isLittleEndian != sys::IsLittleEndianHost)
9243 Print_x86_thread_state32_t(cpu32);
9244 } else if (flavor == MachO::x86_THREAD_STATE) {
9245 outs() << " flavor x86_THREAD_STATE\n";
9246 if (count == MachO::x86_THREAD_STATE_COUNT)
9247 outs() << " count x86_THREAD_STATE_COUNT\n";
9249 outs() << " count " << count
9250 << " (not x86_THREAD_STATE_COUNT)\n";
9251 struct MachO::x86_thread_state_t ts;
9253 if (left >= sizeof(MachO::x86_thread_state_t)) {
9254 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9255 begin += sizeof(MachO::x86_thread_state_t);
9257 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9258 memcpy(&ts, begin, left);
9261 if (isLittleEndian != sys::IsLittleEndianHost)
9263 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) {
9264 outs() << "\t tsh.flavor x86_THREAD_STATE32 ";
9265 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT)
9266 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n";
9268 outs() << "tsh.count " << ts.tsh.count
9269 << " (not x86_THREAD_STATE32_COUNT\n";
9270 Print_x86_thread_state32_t(ts.uts.ts32);
9272 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count "
9273 << ts.tsh.count << "\n";
9276 outs() << " flavor " << flavor << " (unknown)\n";
9277 outs() << " count " << count << "\n";
9278 outs() << " state (unknown)\n";
9279 begin += count * sizeof(uint32_t);
9282 } else if (cputype == MachO::CPU_TYPE_X86_64) {
9283 while (begin < end) {
9284 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9285 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9286 begin += sizeof(uint32_t);
9291 if (isLittleEndian != sys::IsLittleEndianHost)
9292 sys::swapByteOrder(flavor);
9293 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9294 memcpy((char *)&count, begin, sizeof(uint32_t));
9295 begin += sizeof(uint32_t);
9300 if (isLittleEndian != sys::IsLittleEndianHost)
9301 sys::swapByteOrder(count);
9302 if (flavor == MachO::x86_THREAD_STATE64) {
9303 outs() << " flavor x86_THREAD_STATE64\n";
9304 if (count == MachO::x86_THREAD_STATE64_COUNT)
9305 outs() << " count x86_THREAD_STATE64_COUNT\n";
9307 outs() << " count " << count
9308 << " (not x86_THREAD_STATE64_COUNT)\n";
9309 MachO::x86_thread_state64_t cpu64;
9311 if (left >= sizeof(MachO::x86_thread_state64_t)) {
9312 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
9313 begin += sizeof(MachO::x86_thread_state64_t);
9315 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
9316 memcpy(&cpu64, begin, left);
9319 if (isLittleEndian != sys::IsLittleEndianHost)
9321 Print_x86_thread_state64_t(cpu64);
9322 } else if (flavor == MachO::x86_THREAD_STATE) {
9323 outs() << " flavor x86_THREAD_STATE\n";
9324 if (count == MachO::x86_THREAD_STATE_COUNT)
9325 outs() << " count x86_THREAD_STATE_COUNT\n";
9327 outs() << " count " << count
9328 << " (not x86_THREAD_STATE_COUNT)\n";
9329 struct MachO::x86_thread_state_t ts;
9331 if (left >= sizeof(MachO::x86_thread_state_t)) {
9332 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9333 begin += sizeof(MachO::x86_thread_state_t);
9335 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9336 memcpy(&ts, begin, left);
9339 if (isLittleEndian != sys::IsLittleEndianHost)
9341 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
9342 outs() << "\t tsh.flavor x86_THREAD_STATE64 ";
9343 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
9344 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
9346 outs() << "tsh.count " << ts.tsh.count
9347 << " (not x86_THREAD_STATE64_COUNT\n";
9348 Print_x86_thread_state64_t(ts.uts.ts64);
9350 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count "
9351 << ts.tsh.count << "\n";
9353 } else if (flavor == MachO::x86_FLOAT_STATE) {
9354 outs() << " flavor x86_FLOAT_STATE\n";
9355 if (count == MachO::x86_FLOAT_STATE_COUNT)
9356 outs() << " count x86_FLOAT_STATE_COUNT\n";
9358 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
9359 struct MachO::x86_float_state_t fs;
9361 if (left >= sizeof(MachO::x86_float_state_t)) {
9362 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
9363 begin += sizeof(MachO::x86_float_state_t);
9365 memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
9366 memcpy(&fs, begin, left);
9369 if (isLittleEndian != sys::IsLittleEndianHost)
9371 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
9372 outs() << "\t fsh.flavor x86_FLOAT_STATE64 ";
9373 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
9374 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
9376 outs() << "fsh.count " << fs.fsh.count
9377 << " (not x86_FLOAT_STATE64_COUNT\n";
9378 Print_x86_float_state_t(fs.ufs.fs64);
9380 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count "
9381 << fs.fsh.count << "\n";
9383 } else if (flavor == MachO::x86_EXCEPTION_STATE) {
9384 outs() << " flavor x86_EXCEPTION_STATE\n";
9385 if (count == MachO::x86_EXCEPTION_STATE_COUNT)
9386 outs() << " count x86_EXCEPTION_STATE_COUNT\n";
9388 outs() << " count " << count
9389 << " (not x86_EXCEPTION_STATE_COUNT)\n";
9390 struct MachO::x86_exception_state_t es;
9392 if (left >= sizeof(MachO::x86_exception_state_t)) {
9393 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
9394 begin += sizeof(MachO::x86_exception_state_t);
9396 memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
9397 memcpy(&es, begin, left);
9400 if (isLittleEndian != sys::IsLittleEndianHost)
9402 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
9403 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n";
9404 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
9405 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n";
9407 outs() << "\t esh.count " << es.esh.count
9408 << " (not x86_EXCEPTION_STATE64_COUNT\n";
9409 Print_x86_exception_state_t(es.ues.es64);
9411 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count "
9412 << es.esh.count << "\n";
9414 } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
9415 outs() << " flavor x86_EXCEPTION_STATE64\n";
9416 if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
9417 outs() << " count x86_EXCEPTION_STATE64_COUNT\n";
9419 outs() << " count " << count
9420 << " (not x86_EXCEPTION_STATE64_COUNT)\n";
9421 struct MachO::x86_exception_state64_t es64;
9423 if (left >= sizeof(MachO::x86_exception_state64_t)) {
9424 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
9425 begin += sizeof(MachO::x86_exception_state64_t);
9427 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
9428 memcpy(&es64, begin, left);
9431 if (isLittleEndian != sys::IsLittleEndianHost)
9433 Print_x86_exception_state_t(es64);
9435 outs() << " flavor " << flavor << " (unknown)\n";
9436 outs() << " count " << count << "\n";
9437 outs() << " state (unknown)\n";
9438 begin += count * sizeof(uint32_t);
9441 } else if (cputype == MachO::CPU_TYPE_ARM) {
9442 while (begin < end) {
9443 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9444 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9445 begin += sizeof(uint32_t);
9450 if (isLittleEndian != sys::IsLittleEndianHost)
9451 sys::swapByteOrder(flavor);
9452 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9453 memcpy((char *)&count, begin, sizeof(uint32_t));
9454 begin += sizeof(uint32_t);
9459 if (isLittleEndian != sys::IsLittleEndianHost)
9460 sys::swapByteOrder(count);
9461 if (flavor == MachO::ARM_THREAD_STATE) {
9462 outs() << " flavor ARM_THREAD_STATE\n";
9463 if (count == MachO::ARM_THREAD_STATE_COUNT)
9464 outs() << " count ARM_THREAD_STATE_COUNT\n";
9466 outs() << " count " << count
9467 << " (not ARM_THREAD_STATE_COUNT)\n";
9468 MachO::arm_thread_state32_t cpu32;
9470 if (left >= sizeof(MachO::arm_thread_state32_t)) {
9471 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t));
9472 begin += sizeof(MachO::arm_thread_state32_t);
9474 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t));
9475 memcpy(&cpu32, begin, left);
9478 if (isLittleEndian != sys::IsLittleEndianHost)
9480 Print_arm_thread_state32_t(cpu32);
9482 outs() << " flavor " << flavor << " (unknown)\n";
9483 outs() << " count " << count << "\n";
9484 outs() << " state (unknown)\n";
9485 begin += count * sizeof(uint32_t);
9488 } else if (cputype == MachO::CPU_TYPE_ARM64) {
9489 while (begin < end) {
9490 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9491 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9492 begin += sizeof(uint32_t);
9497 if (isLittleEndian != sys::IsLittleEndianHost)
9498 sys::swapByteOrder(flavor);
9499 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9500 memcpy((char *)&count, begin, sizeof(uint32_t));
9501 begin += sizeof(uint32_t);
9506 if (isLittleEndian != sys::IsLittleEndianHost)
9507 sys::swapByteOrder(count);
9508 if (flavor == MachO::ARM_THREAD_STATE64) {
9509 outs() << " flavor ARM_THREAD_STATE64\n";
9510 if (count == MachO::ARM_THREAD_STATE64_COUNT)
9511 outs() << " count ARM_THREAD_STATE64_COUNT\n";
9513 outs() << " count " << count
9514 << " (not ARM_THREAD_STATE64_COUNT)\n";
9515 MachO::arm_thread_state64_t cpu64;
9517 if (left >= sizeof(MachO::arm_thread_state64_t)) {
9518 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
9519 begin += sizeof(MachO::arm_thread_state64_t);
9521 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
9522 memcpy(&cpu64, begin, left);
9525 if (isLittleEndian != sys::IsLittleEndianHost)
9527 Print_arm_thread_state64_t(cpu64);
9529 outs() << " flavor " << flavor << " (unknown)\n";
9530 outs() << " count " << count << "\n";
9531 outs() << " state (unknown)\n";
9532 begin += count * sizeof(uint32_t);
9536 while (begin < end) {
9537 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9538 memcpy((char *)&flavor, begin, sizeof(uint32_t));
9539 begin += sizeof(uint32_t);
9544 if (isLittleEndian != sys::IsLittleEndianHost)
9545 sys::swapByteOrder(flavor);
9546 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9547 memcpy((char *)&count, begin, sizeof(uint32_t));
9548 begin += sizeof(uint32_t);
9553 if (isLittleEndian != sys::IsLittleEndianHost)
9554 sys::swapByteOrder(count);
9555 outs() << " flavor " << flavor << "\n";
9556 outs() << " count " << count << "\n";
9557 outs() << " state (Unknown cputype/cpusubtype)\n";
9558 begin += count * sizeof(uint32_t);
9563 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
9564 if (dl.cmd == MachO::LC_ID_DYLIB)
9565 outs() << " cmd LC_ID_DYLIB\n";
9566 else if (dl.cmd == MachO::LC_LOAD_DYLIB)
9567 outs() << " cmd LC_LOAD_DYLIB\n";
9568 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
9569 outs() << " cmd LC_LOAD_WEAK_DYLIB\n";
9570 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
9571 outs() << " cmd LC_REEXPORT_DYLIB\n";
9572 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
9573 outs() << " cmd LC_LAZY_LOAD_DYLIB\n";
9574 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
9575 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n";
9577 outs() << " cmd " << dl.cmd << " (unknown)\n";
9578 outs() << " cmdsize " << dl.cmdsize;
9579 if (dl.cmdsize < sizeof(struct MachO::dylib_command))
9580 outs() << " Incorrect size\n";
9583 if (dl.dylib.name < dl.cmdsize) {
9584 const char *P = (const char *)(Ptr) + dl.dylib.name;
9585 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n";
9587 outs() << " name ?(bad offset " << dl.dylib.name << ")\n";
9589 outs() << " time stamp " << dl.dylib.timestamp << " ";
9590 time_t t = dl.dylib.timestamp;
9591 outs() << ctime(&t);
9592 outs() << " current version ";
9593 if (dl.dylib.current_version == 0xffffffff)
9596 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
9597 << ((dl.dylib.current_version >> 8) & 0xff) << "."
9598 << (dl.dylib.current_version & 0xff) << "\n";
9599 outs() << "compatibility version ";
9600 if (dl.dylib.compatibility_version == 0xffffffff)
9603 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
9604 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
9605 << (dl.dylib.compatibility_version & 0xff) << "\n";
9608 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
9609 uint32_t object_size) {
9610 if (ld.cmd == MachO::LC_CODE_SIGNATURE)
9611 outs() << " cmd LC_CODE_SIGNATURE\n";
9612 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
9613 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n";
9614 else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
9615 outs() << " cmd LC_FUNCTION_STARTS\n";
9616 else if (ld.cmd == MachO::LC_DATA_IN_CODE)
9617 outs() << " cmd LC_DATA_IN_CODE\n";
9618 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
9619 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n";
9620 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
9621 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n";
9623 outs() << " cmd " << ld.cmd << " (?)\n";
9624 outs() << " cmdsize " << ld.cmdsize;
9625 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
9626 outs() << " Incorrect size\n";
9629 outs() << " dataoff " << ld.dataoff;
9630 if (ld.dataoff > object_size)
9631 outs() << " (past end of file)\n";
9634 outs() << " datasize " << ld.datasize;
9635 uint64_t big_size = ld.dataoff;
9636 big_size += ld.datasize;
9637 if (big_size > object_size)
9638 outs() << " (past end of file)\n";
9643 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
9644 uint32_t cputype, bool verbose) {
9645 StringRef Buf = Obj->getData();
9647 for (const auto &Command : Obj->load_commands()) {
9648 outs() << "Load command " << Index++ << "\n";
9649 if (Command.C.cmd == MachO::LC_SEGMENT) {
9650 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
9651 const char *sg_segname = SLC.segname;
9652 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
9653 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
9654 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
9656 for (unsigned j = 0; j < SLC.nsects; j++) {
9657 MachO::section S = Obj->getSection(Command, j);
9658 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
9659 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
9660 SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
9662 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
9663 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
9664 const char *sg_segname = SLC_64.segname;
9665 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
9666 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
9667 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
9668 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
9669 for (unsigned j = 0; j < SLC_64.nsects; j++) {
9670 MachO::section_64 S_64 = Obj->getSection64(Command, j);
9671 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
9672 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
9673 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
9674 sg_segname, filetype, Buf.size(), verbose);
9676 } else if (Command.C.cmd == MachO::LC_SYMTAB) {
9677 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
9678 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
9679 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
9680 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
9681 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
9682 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
9684 } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
9685 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
9686 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
9687 PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
9688 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
9689 Command.C.cmd == MachO::LC_ID_DYLINKER ||
9690 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
9691 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
9692 PrintDyldLoadCommand(Dyld, Command.Ptr);
9693 } else if (Command.C.cmd == MachO::LC_UUID) {
9694 MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
9695 PrintUuidLoadCommand(Uuid);
9696 } else if (Command.C.cmd == MachO::LC_RPATH) {
9697 MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
9698 PrintRpathLoadCommand(Rpath, Command.Ptr);
9699 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
9700 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
9701 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
9702 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
9703 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
9704 PrintVersionMinLoadCommand(Vd);
9705 } else if (Command.C.cmd == MachO::LC_NOTE) {
9706 MachO::note_command Nt = Obj->getNoteLoadCommand(Command);
9707 PrintNoteLoadCommand(Nt);
9708 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) {
9709 MachO::build_version_command Bv =
9710 Obj->getBuildVersionLoadCommand(Command);
9711 PrintBuildVersionLoadCommand(Obj, Bv);
9712 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
9713 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
9714 PrintSourceVersionCommand(Sd);
9715 } else if (Command.C.cmd == MachO::LC_MAIN) {
9716 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
9717 PrintEntryPointCommand(Ep);
9718 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
9719 MachO::encryption_info_command Ei =
9720 Obj->getEncryptionInfoCommand(Command);
9721 PrintEncryptionInfoCommand(Ei, Buf.size());
9722 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
9723 MachO::encryption_info_command_64 Ei =
9724 Obj->getEncryptionInfoCommand64(Command);
9725 PrintEncryptionInfoCommand64(Ei, Buf.size());
9726 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
9727 MachO::linker_option_command Lo =
9728 Obj->getLinkerOptionLoadCommand(Command);
9729 PrintLinkerOptionCommand(Lo, Command.Ptr);
9730 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
9731 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
9732 PrintSubFrameworkCommand(Sf, Command.Ptr);
9733 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
9734 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
9735 PrintSubUmbrellaCommand(Sf, Command.Ptr);
9736 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
9737 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
9738 PrintSubLibraryCommand(Sl, Command.Ptr);
9739 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
9740 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
9741 PrintSubClientCommand(Sc, Command.Ptr);
9742 } else if (Command.C.cmd == MachO::LC_ROUTINES) {
9743 MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
9744 PrintRoutinesCommand(Rc);
9745 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
9746 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
9747 PrintRoutinesCommand64(Rc);
9748 } else if (Command.C.cmd == MachO::LC_THREAD ||
9749 Command.C.cmd == MachO::LC_UNIXTHREAD) {
9750 MachO::thread_command Tc = Obj->getThreadCommand(Command);
9751 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
9752 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
9753 Command.C.cmd == MachO::LC_ID_DYLIB ||
9754 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
9755 Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
9756 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
9757 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
9758 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
9759 PrintDylibCommand(Dl, Command.Ptr);
9760 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
9761 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
9762 Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
9763 Command.C.cmd == MachO::LC_DATA_IN_CODE ||
9764 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
9765 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
9766 MachO::linkedit_data_command Ld =
9767 Obj->getLinkeditDataLoadCommand(Command);
9768 PrintLinkEditDataCommand(Ld, Buf.size());
9770 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
9772 outs() << " cmdsize " << Command.C.cmdsize << "\n";
9773 // TODO: get and print the raw bytes of the load command.
9775 // TODO: print all the other kinds of load commands.
9779 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
9780 if (Obj->is64Bit()) {
9781 MachO::mach_header_64 H_64;
9782 H_64 = Obj->getHeader64();
9783 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
9784 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
9786 MachO::mach_header H;
9787 H = Obj->getHeader();
9788 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
9789 H.sizeofcmds, H.flags, verbose);
9793 void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
9794 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
9795 PrintMachHeader(file, !NonVerbose);
9798 void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) {
9799 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
9800 uint32_t filetype = 0;
9801 uint32_t cputype = 0;
9802 if (file->is64Bit()) {
9803 MachO::mach_header_64 H_64;
9804 H_64 = file->getHeader64();
9805 filetype = H_64.filetype;
9806 cputype = H_64.cputype;
9808 MachO::mach_header H;
9809 H = file->getHeader();
9810 filetype = H.filetype;
9811 cputype = H.cputype;
9813 PrintLoadCommands(file, filetype, cputype, !NonVerbose);
9816 //===----------------------------------------------------------------------===//
9817 // export trie dumping
9818 //===----------------------------------------------------------------------===//
9820 void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) {
9821 uint64_t BaseSegmentAddress = 0;
9822 for (const auto &Command : Obj->load_commands()) {
9823 if (Command.C.cmd == MachO::LC_SEGMENT) {
9824 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command);
9825 if (Seg.fileoff == 0 && Seg.filesize != 0) {
9826 BaseSegmentAddress = Seg.vmaddr;
9829 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
9830 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command);
9831 if (Seg.fileoff == 0 && Seg.filesize != 0) {
9832 BaseSegmentAddress = Seg.vmaddr;
9837 Error Err = Error::success();
9838 for (const llvm::object::ExportEntry &Entry : Obj->exports(Err)) {
9839 uint64_t Flags = Entry.flags();
9840 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
9841 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
9842 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
9843 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
9844 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
9845 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
9846 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
9848 outs() << "[re-export] ";
9850 outs() << format("0x%08llX ",
9851 Entry.address() + BaseSegmentAddress);
9852 outs() << Entry.name();
9853 if (WeakDef || ThreadLocal || Resolver || Abs) {
9854 bool NeedsComma = false;
9857 outs() << "weak_def";
9863 outs() << "per-thread";
9869 outs() << "absolute";
9875 outs() << format("resolver=0x%08llX", Entry.other());
9881 StringRef DylibName = "unknown";
9882 int Ordinal = Entry.other() - 1;
9883 Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
9884 if (Entry.otherName().empty())
9885 outs() << " (from " << DylibName << ")";
9887 outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
9892 report_error(Obj->getFileName(), std::move(Err));
9895 //===----------------------------------------------------------------------===//
9896 // rebase table dumping
9897 //===----------------------------------------------------------------------===//
9899 void llvm::printMachORebaseTable(object::MachOObjectFile *Obj) {
9900 outs() << "segment section address type\n";
9901 Error Err = Error::success();
9902 for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) {
9903 StringRef SegmentName = Entry.segmentName();
9904 StringRef SectionName = Entry.sectionName();
9905 uint64_t Address = Entry.address();
9907 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer
9908 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n",
9909 SegmentName.str().c_str(), SectionName.str().c_str(),
9910 Address, Entry.typeName().str().c_str());
9913 report_error(Obj->getFileName(), std::move(Err));
9916 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
9917 StringRef DylibName;
9919 case MachO::BIND_SPECIAL_DYLIB_SELF:
9920 return "this-image";
9921 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
9922 return "main-executable";
9923 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
9924 return "flat-namespace";
9927 std::error_code EC =
9928 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
9930 return "<<bad library ordinal>>";
9934 return "<<unknown special ordinal>>";
9937 //===----------------------------------------------------------------------===//
9938 // bind table dumping
9939 //===----------------------------------------------------------------------===//
9941 void llvm::printMachOBindTable(object::MachOObjectFile *Obj) {
9942 // Build table of sections so names can used in final output.
9943 outs() << "segment section address type "
9944 "addend dylib symbol\n";
9945 Error Err = Error::success();
9946 for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) {
9947 StringRef SegmentName = Entry.segmentName();
9948 StringRef SectionName = Entry.sectionName();
9949 uint64_t Address = Entry.address();
9951 // Table lines look like:
9952 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard
9954 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
9955 Attr = " (weak_import)";
9956 outs() << left_justify(SegmentName, 8) << " "
9957 << left_justify(SectionName, 18) << " "
9958 << format_hex(Address, 10, true) << " "
9959 << left_justify(Entry.typeName(), 8) << " "
9960 << format_decimal(Entry.addend(), 8) << " "
9961 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
9962 << Entry.symbolName() << Attr << "\n";
9965 report_error(Obj->getFileName(), std::move(Err));
9968 //===----------------------------------------------------------------------===//
9969 // lazy bind table dumping
9970 //===----------------------------------------------------------------------===//
9972 void llvm::printMachOLazyBindTable(object::MachOObjectFile *Obj) {
9973 outs() << "segment section address "
9975 Error Err = Error::success();
9976 for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) {
9977 StringRef SegmentName = Entry.segmentName();
9978 StringRef SectionName = Entry.sectionName();
9979 uint64_t Address = Entry.address();
9981 // Table lines look like:
9982 // __DATA __got 0x00012010 libSystem ___stack_chk_guard
9983 outs() << left_justify(SegmentName, 8) << " "
9984 << left_justify(SectionName, 18) << " "
9985 << format_hex(Address, 10, true) << " "
9986 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
9987 << Entry.symbolName() << "\n";
9990 report_error(Obj->getFileName(), std::move(Err));
9993 //===----------------------------------------------------------------------===//
9994 // weak bind table dumping
9995 //===----------------------------------------------------------------------===//
9997 void llvm::printMachOWeakBindTable(object::MachOObjectFile *Obj) {
9998 outs() << "segment section address "
9999 "type addend symbol\n";
10000 Error Err = Error::success();
10001 for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) {
10002 // Strong symbols don't have a location to update.
10003 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
10004 outs() << " strong "
10005 << Entry.symbolName() << "\n";
10008 StringRef SegmentName = Entry.segmentName();
10009 StringRef SectionName = Entry.sectionName();
10010 uint64_t Address = Entry.address();
10012 // Table lines look like:
10013 // __DATA __data 0x00001000 pointer 0 _foo
10014 outs() << left_justify(SegmentName, 8) << " "
10015 << left_justify(SectionName, 18) << " "
10016 << format_hex(Address, 10, true) << " "
10017 << left_justify(Entry.typeName(), 8) << " "
10018 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName()
10022 report_error(Obj->getFileName(), std::move(Err));
10025 // get_dyld_bind_info_symbolname() is used for disassembly and passed an
10026 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind
10027 // information for that address. If the address is found its binding symbol
10028 // name is returned. If not nullptr is returned.
10029 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
10030 struct DisassembleInfo *info) {
10031 if (info->bindtable == nullptr) {
10032 info->bindtable = llvm::make_unique<SymbolAddressMap>();
10033 Error Err = Error::success();
10034 for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) {
10035 uint64_t Address = Entry.address();
10036 StringRef name = Entry.symbolName();
10038 (*info->bindtable)[Address] = name;
10041 report_error(info->O->getFileName(), std::move(Err));
10043 auto name = info->bindtable->lookup(ReferenceValue);
10044 return !name.empty() ? name.data() : nullptr;