1 //===-- MachODump.cpp - Object file dumping utility for llvm --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the MachO-specific dumper for llvm-objdump. 11 // 12 //===----------------------------------------------------------------------===// 13 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/raw_ostream.h" 48 #include <algorithm> 49 #include <cstring> 50 #include <system_error> 51 52 #ifdef HAVE_LIBXAR 53 extern "C" { 54 #include <xar/xar.h> 55 } 56 #endif 57 58 using namespace llvm; 59 using namespace object; 60 61 static cl::opt<bool> 62 UseDbg("g", 63 cl::desc("Print line information from debug info if available")); 64 65 static cl::opt<std::string> DSYMFile("dsym", 66 cl::desc("Use .dSYM file for debug info")); 67 68 static cl::opt<bool> FullLeadingAddr("full-leading-addr", 69 cl::desc("Print full leading address")); 70 71 static cl::opt<bool> NoLeadingHeaders("no-leading-headers", 72 cl::desc("Print no leading headers")); 73 74 cl::opt<bool> llvm::UniversalHeaders("universal-headers", 75 cl::desc("Print Mach-O universal headers " 76 "(requires -macho)")); 77 78 cl::opt<bool> 79 ArchiveMemberOffsets("archive-member-offsets", 80 cl::desc("Print the offset to each archive member for " 81 "Mach-O archives (requires -macho and " 82 "-archive-headers)")); 83 84 cl::opt<bool> 85 llvm::IndirectSymbols("indirect-symbols", 86 cl::desc("Print indirect symbol table for Mach-O " 87 "objects (requires -macho)")); 88 89 cl::opt<bool> 90 llvm::DataInCode("data-in-code", 91 cl::desc("Print the data in code table for Mach-O objects " 92 "(requires -macho)")); 93 94 cl::opt<bool> 95 llvm::LinkOptHints("link-opt-hints", 96 cl::desc("Print the linker optimization hints for " 97 "Mach-O objects (requires -macho)")); 98 99 cl::opt<bool> 100 llvm::InfoPlist("info-plist", 101 cl::desc("Print the info plist section as strings for " 102 "Mach-O objects (requires -macho)")); 103 104 cl::opt<bool> 105 llvm::DylibsUsed("dylibs-used", 106 cl::desc("Print the shared libraries used for linked " 107 "Mach-O files (requires -macho)")); 108 109 cl::opt<bool> 110 llvm::DylibId("dylib-id", 111 cl::desc("Print the shared library's id for the dylib Mach-O " 112 "file (requires -macho)")); 113 114 cl::opt<bool> 115 llvm::NonVerbose("non-verbose", 116 cl::desc("Print the info for Mach-O objects in " 117 "non-verbose or numeric form (requires -macho)")); 118 119 cl::opt<bool> 120 llvm::ObjcMetaData("objc-meta-data", 121 cl::desc("Print the Objective-C runtime meta data for " 122 "Mach-O files (requires -macho)")); 123 124 cl::opt<std::string> llvm::DisSymName( 125 "dis-symname", 126 cl::desc("disassemble just this symbol's instructions (requires -macho)")); 127 128 static cl::opt<bool> NoSymbolicOperands( 129 "no-symbolic-operands", 130 cl::desc("do not symbolic operands when disassembling (requires -macho)")); 131 132 static cl::list<std::string> 133 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 134 cl::ZeroOrMore); 135 136 bool ArchAll = false; 137 138 static std::string ThumbTripleName; 139 140 static const Target *GetTarget(const MachOObjectFile *MachOObj, 141 const char **McpuDefault, 142 const Target **ThumbTarget) { 143 // Figure out the target triple. 144 llvm::Triple TT(TripleName); 145 if (TripleName.empty()) { 146 TT = MachOObj->getArchTriple(McpuDefault); 147 TripleName = TT.str(); 148 } 149 150 if (TT.getArch() == Triple::arm) { 151 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs 152 // that support ARM are also capable of Thumb mode. 153 llvm::Triple ThumbTriple = TT; 154 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str(); 155 ThumbTriple.setArchName(ThumbName); 156 ThumbTripleName = ThumbTriple.str(); 157 } 158 159 // Get the target specific parser. 160 std::string Error; 161 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 162 if (TheTarget && ThumbTripleName.empty()) 163 return TheTarget; 164 165 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 166 if (*ThumbTarget) 167 return TheTarget; 168 169 errs() << "llvm-objdump: error: unable to get target for '"; 170 if (!TheTarget) 171 errs() << TripleName; 172 else 173 errs() << ThumbTripleName; 174 errs() << "', see --version and --triple.\n"; 175 return nullptr; 176 } 177 178 struct SymbolSorter { 179 bool operator()(const SymbolRef &A, const SymbolRef &B) { 180 Expected<SymbolRef::Type> ATypeOrErr = A.getType(); 181 if (!ATypeOrErr) 182 report_error(A.getObject()->getFileName(), ATypeOrErr.takeError()); 183 SymbolRef::Type AType = *ATypeOrErr; 184 Expected<SymbolRef::Type> BTypeOrErr = B.getType(); 185 if (!BTypeOrErr) 186 report_error(B.getObject()->getFileName(), BTypeOrErr.takeError()); 187 SymbolRef::Type BType = *BTypeOrErr; 188 uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue(); 189 uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue(); 190 return AAddr < BAddr; 191 } 192 }; 193 194 // Types for the storted data in code table that is built before disassembly 195 // and the predicate function to sort them. 196 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 197 typedef std::vector<DiceTableEntry> DiceTable; 198 typedef DiceTable::iterator dice_table_iterator; 199 200 #ifdef HAVE_LIBXAR 201 namespace { 202 struct ScopedXarFile { 203 xar_t xar; 204 ScopedXarFile(const char *filename, int32_t flags) 205 : xar(xar_open(filename, flags)) {} 206 ~ScopedXarFile() { 207 if (xar) 208 xar_close(xar); 209 } 210 ScopedXarFile(const ScopedXarFile &) = delete; 211 ScopedXarFile &operator=(const ScopedXarFile &) = delete; 212 operator xar_t() { return xar; } 213 }; 214 215 struct ScopedXarIter { 216 xar_iter_t iter; 217 ScopedXarIter() : iter(xar_iter_new()) {} 218 ~ScopedXarIter() { 219 if (iter) 220 xar_iter_free(iter); 221 } 222 ScopedXarIter(const ScopedXarIter &) = delete; 223 ScopedXarIter &operator=(const ScopedXarIter &) = delete; 224 operator xar_iter_t() { return iter; } 225 }; 226 } // namespace 227 #endif // defined(HAVE_LIBXAR) 228 229 // This is used to search for a data in code table entry for the PC being 230 // disassembled. The j parameter has the PC in j.first. A single data in code 231 // table entry can cover many bytes for each of its Kind's. So if the offset, 232 // aka the i.first value, of the data in code table entry plus its Length 233 // covers the PC being searched for this will return true. If not it will 234 // return false. 235 static bool compareDiceTableEntries(const DiceTableEntry &i, 236 const DiceTableEntry &j) { 237 uint16_t Length; 238 i.second.getLength(Length); 239 240 return j.first >= i.first && j.first < i.first + Length; 241 } 242 243 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 244 unsigned short Kind) { 245 uint32_t Value, Size = 1; 246 247 switch (Kind) { 248 default: 249 case MachO::DICE_KIND_DATA: 250 if (Length >= 4) { 251 if (!NoShowRawInsn) 252 dumpBytes(makeArrayRef(bytes, 4), outs()); 253 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 254 outs() << "\t.long " << Value; 255 Size = 4; 256 } else if (Length >= 2) { 257 if (!NoShowRawInsn) 258 dumpBytes(makeArrayRef(bytes, 2), outs()); 259 Value = bytes[1] << 8 | bytes[0]; 260 outs() << "\t.short " << Value; 261 Size = 2; 262 } else { 263 if (!NoShowRawInsn) 264 dumpBytes(makeArrayRef(bytes, 2), outs()); 265 Value = bytes[0]; 266 outs() << "\t.byte " << Value; 267 Size = 1; 268 } 269 if (Kind == MachO::DICE_KIND_DATA) 270 outs() << "\t@ KIND_DATA\n"; 271 else 272 outs() << "\t@ data in code kind = " << Kind << "\n"; 273 break; 274 case MachO::DICE_KIND_JUMP_TABLE8: 275 if (!NoShowRawInsn) 276 dumpBytes(makeArrayRef(bytes, 1), outs()); 277 Value = bytes[0]; 278 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 279 Size = 1; 280 break; 281 case MachO::DICE_KIND_JUMP_TABLE16: 282 if (!NoShowRawInsn) 283 dumpBytes(makeArrayRef(bytes, 2), outs()); 284 Value = bytes[1] << 8 | bytes[0]; 285 outs() << "\t.short " << format("%5u", Value & 0xffff) 286 << "\t@ KIND_JUMP_TABLE16\n"; 287 Size = 2; 288 break; 289 case MachO::DICE_KIND_JUMP_TABLE32: 290 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 291 if (!NoShowRawInsn) 292 dumpBytes(makeArrayRef(bytes, 4), outs()); 293 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 294 outs() << "\t.long " << Value; 295 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 296 outs() << "\t@ KIND_JUMP_TABLE32\n"; 297 else 298 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 299 Size = 4; 300 break; 301 } 302 return Size; 303 } 304 305 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 306 std::vector<SectionRef> &Sections, 307 std::vector<SymbolRef> &Symbols, 308 SmallVectorImpl<uint64_t> &FoundFns, 309 uint64_t &BaseSegmentAddress) { 310 for (const SymbolRef &Symbol : MachOObj->symbols()) { 311 Expected<StringRef> SymName = Symbol.getName(); 312 if (!SymName) 313 report_error(MachOObj->getFileName(), SymName.takeError()); 314 if (!SymName->startswith("ltmp")) 315 Symbols.push_back(Symbol); 316 } 317 318 for (const SectionRef &Section : MachOObj->sections()) { 319 StringRef SectName; 320 Section.getName(SectName); 321 Sections.push_back(Section); 322 } 323 324 bool BaseSegmentAddressSet = false; 325 for (const auto &Command : MachOObj->load_commands()) { 326 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 327 // We found a function starts segment, parse the addresses for later 328 // consumption. 329 MachO::linkedit_data_command LLC = 330 MachOObj->getLinkeditDataLoadCommand(Command); 331 332 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 333 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 334 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 335 StringRef SegName = SLC.segname; 336 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 337 BaseSegmentAddressSet = true; 338 BaseSegmentAddress = SLC.vmaddr; 339 } 340 } 341 } 342 } 343 344 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 345 uint32_t n, uint32_t count, 346 uint32_t stride, uint64_t addr) { 347 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 348 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 349 if (n > nindirectsyms) 350 outs() << " (entries start past the end of the indirect symbol " 351 "table) (reserved1 field greater than the table size)"; 352 else if (n + count > nindirectsyms) 353 outs() << " (entries extends past the end of the indirect symbol " 354 "table)"; 355 outs() << "\n"; 356 uint32_t cputype = O->getHeader().cputype; 357 if (cputype & MachO::CPU_ARCH_ABI64) 358 outs() << "address index"; 359 else 360 outs() << "address index"; 361 if (verbose) 362 outs() << " name\n"; 363 else 364 outs() << "\n"; 365 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 366 if (cputype & MachO::CPU_ARCH_ABI64) 367 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 368 else 369 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 370 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 371 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 372 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 373 outs() << "LOCAL\n"; 374 continue; 375 } 376 if (indirect_symbol == 377 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 378 outs() << "LOCAL ABSOLUTE\n"; 379 continue; 380 } 381 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 382 outs() << "ABSOLUTE\n"; 383 continue; 384 } 385 outs() << format("%5u ", indirect_symbol); 386 if (verbose) { 387 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 388 if (indirect_symbol < Symtab.nsyms) { 389 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 390 SymbolRef Symbol = *Sym; 391 Expected<StringRef> SymName = Symbol.getName(); 392 if (!SymName) 393 report_error(O->getFileName(), SymName.takeError()); 394 outs() << *SymName; 395 } else { 396 outs() << "?"; 397 } 398 } 399 outs() << "\n"; 400 } 401 } 402 403 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 404 for (const auto &Load : O->load_commands()) { 405 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 406 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 407 for (unsigned J = 0; J < Seg.nsects; ++J) { 408 MachO::section_64 Sec = O->getSection64(Load, J); 409 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 410 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 411 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 412 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 413 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 414 section_type == MachO::S_SYMBOL_STUBS) { 415 uint32_t stride; 416 if (section_type == MachO::S_SYMBOL_STUBS) 417 stride = Sec.reserved2; 418 else 419 stride = 8; 420 if (stride == 0) { 421 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 422 << Sec.sectname << ") " 423 << "(size of stubs in reserved2 field is zero)\n"; 424 continue; 425 } 426 uint32_t count = Sec.size / stride; 427 outs() << "Indirect symbols for (" << Sec.segname << "," 428 << Sec.sectname << ") " << count << " entries"; 429 uint32_t n = Sec.reserved1; 430 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 431 } 432 } 433 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 434 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 435 for (unsigned J = 0; J < Seg.nsects; ++J) { 436 MachO::section Sec = O->getSection(Load, J); 437 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 438 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 439 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 440 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 441 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 442 section_type == MachO::S_SYMBOL_STUBS) { 443 uint32_t stride; 444 if (section_type == MachO::S_SYMBOL_STUBS) 445 stride = Sec.reserved2; 446 else 447 stride = 4; 448 if (stride == 0) { 449 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 450 << Sec.sectname << ") " 451 << "(size of stubs in reserved2 field is zero)\n"; 452 continue; 453 } 454 uint32_t count = Sec.size / stride; 455 outs() << "Indirect symbols for (" << Sec.segname << "," 456 << Sec.sectname << ") " << count << " entries"; 457 uint32_t n = Sec.reserved1; 458 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 459 } 460 } 461 } 462 } 463 } 464 465 static void PrintRType(const uint64_t cputype, const unsigned r_type) { 466 static char const *generic_r_types[] = { 467 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ", 468 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", 469 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 470 }; 471 static char const *x86_64_r_types[] = { 472 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", 473 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ", 474 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 475 }; 476 static char const *arm_r_types[] = { 477 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", 478 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ", 479 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 480 }; 481 static char const *arm64_r_types[] = { 482 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", 483 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", 484 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 485 }; 486 487 if (r_type > 0xf){ 488 outs() << format("%-7u", r_type) << " "; 489 return; 490 } 491 switch (cputype) { 492 case MachO::CPU_TYPE_I386: 493 outs() << generic_r_types[r_type]; 494 break; 495 case MachO::CPU_TYPE_X86_64: 496 outs() << x86_64_r_types[r_type]; 497 break; 498 case MachO::CPU_TYPE_ARM: 499 outs() << arm_r_types[r_type]; 500 break; 501 case MachO::CPU_TYPE_ARM64: 502 outs() << arm64_r_types[r_type]; 503 break; 504 default: 505 outs() << format("%-7u ", r_type); 506 } 507 } 508 509 static void PrintRLength(const uint64_t cputype, const unsigned r_type, 510 const unsigned r_length, const bool previous_arm_half){ 511 if (cputype == MachO::CPU_TYPE_ARM && 512 (r_type == llvm::MachO::ARM_RELOC_HALF || 513 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF || 514 previous_arm_half == true)) { 515 if ((r_length & 0x1) == 0) 516 outs() << "lo/"; 517 else 518 outs() << "hi/"; 519 if ((r_length & 0x1) == 0) 520 outs() << "arm "; 521 else 522 outs() << "thm "; 523 } else { 524 switch (r_length) { 525 case 0: 526 outs() << "byte "; 527 break; 528 case 1: 529 outs() << "word "; 530 break; 531 case 2: 532 outs() << "long "; 533 break; 534 case 3: 535 if (cputype == MachO::CPU_TYPE_X86_64) 536 outs() << "quad "; 537 else 538 outs() << format("?(%2d) ", r_length); 539 break; 540 default: 541 outs() << format("?(%2d) ", r_length); 542 } 543 } 544 } 545 546 static void PrintRelocationEntries(const MachOObjectFile *O, 547 const relocation_iterator Begin, 548 const relocation_iterator End, 549 const uint64_t cputype, 550 const bool verbose) { 551 const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 552 bool previous_arm_half = false; 553 bool previous_sectdiff = false; 554 uint32_t sectdiff_r_type = 0; 555 556 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { 557 const DataRefImpl Rel = Reloc->getRawDataRefImpl(); 558 const MachO::any_relocation_info RE = O->getRelocation(Rel); 559 const unsigned r_type = O->getAnyRelocationType(RE); 560 const bool r_scattered = O->isRelocationScattered(RE); 561 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); 562 const unsigned r_length = O->getAnyRelocationLength(RE); 563 const unsigned r_address = O->getAnyRelocationAddress(RE); 564 const bool r_extern = (r_scattered ? false : 565 O->getPlainRelocationExternal(RE)); 566 const uint32_t r_value = (r_scattered ? 567 O->getScatteredRelocationValue(RE) : 0); 568 const unsigned r_symbolnum = (r_scattered ? 0 : 569 O->getPlainRelocationSymbolNum(RE)); 570 571 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { 572 if (verbose) { 573 // scattered: address 574 if ((cputype == MachO::CPU_TYPE_I386 && 575 r_type == llvm::MachO::GENERIC_RELOC_PAIR) || 576 (cputype == MachO::CPU_TYPE_ARM && 577 r_type == llvm::MachO::ARM_RELOC_PAIR)) 578 outs() << " "; 579 else 580 outs() << format("%08x ", (unsigned int)r_address); 581 582 // scattered: pcrel 583 if (r_pcrel) 584 outs() << "True "; 585 else 586 outs() << "False "; 587 588 // scattered: length 589 PrintRLength(cputype, r_type, r_length, previous_arm_half); 590 591 // scattered: extern & type 592 outs() << "n/a "; 593 PrintRType(cputype, r_type); 594 595 // scattered: scattered & value 596 outs() << format("True 0x%08x", (unsigned int)r_value); 597 if (previous_sectdiff == false) { 598 if ((cputype == MachO::CPU_TYPE_ARM && 599 r_type == llvm::MachO::ARM_RELOC_PAIR)) 600 outs() << format(" half = 0x%04x ", (unsigned int)r_address); 601 } 602 else if (cputype == MachO::CPU_TYPE_ARM && 603 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF) 604 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); 605 if ((cputype == MachO::CPU_TYPE_I386 && 606 (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF || 607 r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || 608 (cputype == MachO::CPU_TYPE_ARM && 609 (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF || 610 sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF || 611 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) { 612 previous_sectdiff = true; 613 sectdiff_r_type = r_type; 614 } 615 else { 616 previous_sectdiff = false; 617 sectdiff_r_type = 0; 618 } 619 if (cputype == MachO::CPU_TYPE_ARM && 620 (r_type == llvm::MachO::ARM_RELOC_HALF || 621 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) 622 previous_arm_half = true; 623 else 624 previous_arm_half = false; 625 outs() << "\n"; 626 } 627 else { 628 // scattered: address pcrel length extern type scattered value 629 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n", 630 (unsigned int)r_address, r_pcrel, r_length, r_type, 631 (unsigned int)r_value); 632 } 633 } 634 else { 635 if (verbose) { 636 // plain: address 637 if (cputype == MachO::CPU_TYPE_ARM && 638 r_type == llvm::MachO::ARM_RELOC_PAIR) 639 outs() << " "; 640 else 641 outs() << format("%08x ", (unsigned int)r_address); 642 643 // plain: pcrel 644 if (r_pcrel) 645 outs() << "True "; 646 else 647 outs() << "False "; 648 649 // plain: length 650 PrintRLength(cputype, r_type, r_length, previous_arm_half); 651 652 if (r_extern) { 653 // plain: extern & type & scattered 654 outs() << "True "; 655 PrintRType(cputype, r_type); 656 outs() << "False "; 657 658 // plain: symbolnum/value 659 if (r_symbolnum > Symtab.nsyms) 660 outs() << format("?(%d)\n", r_symbolnum); 661 else { 662 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); 663 Expected<StringRef> SymNameNext = Symbol.getName(); 664 const char *name = NULL; 665 if (SymNameNext) 666 name = SymNameNext->data(); 667 if (name == NULL) 668 outs() << format("?(%d)\n", r_symbolnum); 669 else 670 outs() << name << "\n"; 671 } 672 } 673 else { 674 // plain: extern & type & scattered 675 outs() << "False "; 676 PrintRType(cputype, r_type); 677 outs() << "False "; 678 679 // plain: symbolnum/value 680 if (cputype == MachO::CPU_TYPE_ARM && 681 r_type == llvm::MachO::ARM_RELOC_PAIR) 682 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); 683 else if (cputype == MachO::CPU_TYPE_ARM64 && 684 r_type == llvm::MachO::ARM64_RELOC_ADDEND) 685 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); 686 else { 687 outs() << format("%d ", r_symbolnum); 688 if (r_symbolnum == llvm::MachO::R_ABS) 689 outs() << "R_ABS\n"; 690 else { 691 // in this case, r_symbolnum is actually a 1-based section number 692 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; 693 if (r_symbolnum > 0 && r_symbolnum <= nsects) { 694 llvm::object::DataRefImpl DRI; 695 DRI.d.a = r_symbolnum-1; 696 StringRef SegName = O->getSectionFinalSegmentName(DRI); 697 StringRef SectName; 698 if (O->getSectionName(DRI, SectName)) 699 outs() << "(?,?)\n"; 700 else 701 outs() << "(" << SegName << "," << SectName << ")\n"; 702 } 703 else { 704 outs() << "(?,?)\n"; 705 } 706 } 707 } 708 } 709 if (cputype == MachO::CPU_TYPE_ARM && 710 (r_type == llvm::MachO::ARM_RELOC_HALF || 711 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) 712 previous_arm_half = true; 713 else 714 previous_arm_half = false; 715 } 716 else { 717 // plain: address pcrel length extern type scattered symbolnum/section 718 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n", 719 (unsigned int)r_address, r_pcrel, r_length, r_extern, 720 r_type, r_symbolnum); 721 } 722 } 723 } 724 } 725 726 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { 727 const uint64_t cputype = O->getHeader().cputype; 728 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 729 if (Dysymtab.nextrel != 0) { 730 outs() << "External relocation information " << Dysymtab.nextrel 731 << " entries"; 732 outs() << "\naddress pcrel length extern type scattered " 733 "symbolnum/value\n"; 734 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, 735 verbose); 736 } 737 if (Dysymtab.nlocrel != 0) { 738 outs() << format("Local relocation information %u entries", 739 Dysymtab.nlocrel); 740 outs() << "\naddress pcrel length extern type scattered " 741 "symbolnum/value\n"; 742 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, 743 verbose); 744 } 745 for (const auto &Load : O->load_commands()) { 746 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 747 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 748 for (unsigned J = 0; J < Seg.nsects; ++J) { 749 const MachO::section_64 Sec = O->getSection64(Load, J); 750 if (Sec.nreloc != 0) { 751 DataRefImpl DRI; 752 DRI.d.a = J; 753 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 754 StringRef SectName; 755 if (O->getSectionName(DRI, SectName)) 756 outs() << "Relocation information (" << SegName << ",?) " 757 << format("%u entries", Sec.nreloc); 758 else 759 outs() << "Relocation information (" << SegName << "," 760 << SectName << format(") %u entries", Sec.nreloc); 761 outs() << "\naddress pcrel length extern type scattered " 762 "symbolnum/value\n"; 763 PrintRelocationEntries(O, O->section_rel_begin(DRI), 764 O->section_rel_end(DRI), cputype, verbose); 765 } 766 } 767 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 768 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 769 for (unsigned J = 0; J < Seg.nsects; ++J) { 770 const MachO::section Sec = O->getSection(Load, J); 771 if (Sec.nreloc != 0) { 772 DataRefImpl DRI; 773 DRI.d.a = J; 774 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 775 StringRef SectName; 776 if (O->getSectionName(DRI, SectName)) 777 outs() << "Relocation information (" << SegName << ",?) " 778 << format("%u entries", Sec.nreloc); 779 else 780 outs() << "Relocation information (" << SegName << "," 781 << SectName << format(") %u entries", Sec.nreloc); 782 outs() << "\naddress pcrel length extern type scattered " 783 "symbolnum/value\n"; 784 PrintRelocationEntries(O, O->section_rel_begin(DRI), 785 O->section_rel_end(DRI), cputype, verbose); 786 } 787 } 788 } 789 } 790 } 791 792 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 793 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 794 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 795 outs() << "Data in code table (" << nentries << " entries)\n"; 796 outs() << "offset length kind\n"; 797 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 798 ++DI) { 799 uint32_t Offset; 800 DI->getOffset(Offset); 801 outs() << format("0x%08" PRIx32, Offset) << " "; 802 uint16_t Length; 803 DI->getLength(Length); 804 outs() << format("%6u", Length) << " "; 805 uint16_t Kind; 806 DI->getKind(Kind); 807 if (verbose) { 808 switch (Kind) { 809 case MachO::DICE_KIND_DATA: 810 outs() << "DATA"; 811 break; 812 case MachO::DICE_KIND_JUMP_TABLE8: 813 outs() << "JUMP_TABLE8"; 814 break; 815 case MachO::DICE_KIND_JUMP_TABLE16: 816 outs() << "JUMP_TABLE16"; 817 break; 818 case MachO::DICE_KIND_JUMP_TABLE32: 819 outs() << "JUMP_TABLE32"; 820 break; 821 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 822 outs() << "ABS_JUMP_TABLE32"; 823 break; 824 default: 825 outs() << format("0x%04" PRIx32, Kind); 826 break; 827 } 828 } else 829 outs() << format("0x%04" PRIx32, Kind); 830 outs() << "\n"; 831 } 832 } 833 834 static void PrintLinkOptHints(MachOObjectFile *O) { 835 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 836 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 837 uint32_t nloh = LohLC.datasize; 838 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 839 for (uint32_t i = 0; i < nloh;) { 840 unsigned n; 841 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 842 i += n; 843 outs() << " identifier " << identifier << " "; 844 if (i >= nloh) 845 return; 846 switch (identifier) { 847 case 1: 848 outs() << "AdrpAdrp\n"; 849 break; 850 case 2: 851 outs() << "AdrpLdr\n"; 852 break; 853 case 3: 854 outs() << "AdrpAddLdr\n"; 855 break; 856 case 4: 857 outs() << "AdrpLdrGotLdr\n"; 858 break; 859 case 5: 860 outs() << "AdrpAddStr\n"; 861 break; 862 case 6: 863 outs() << "AdrpLdrGotStr\n"; 864 break; 865 case 7: 866 outs() << "AdrpAdd\n"; 867 break; 868 case 8: 869 outs() << "AdrpLdrGot\n"; 870 break; 871 default: 872 outs() << "Unknown identifier value\n"; 873 break; 874 } 875 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 876 i += n; 877 outs() << " narguments " << narguments << "\n"; 878 if (i >= nloh) 879 return; 880 881 for (uint32_t j = 0; j < narguments; j++) { 882 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 883 i += n; 884 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 885 if (i >= nloh) 886 return; 887 } 888 } 889 } 890 891 static void PrintDylibs(MachOObjectFile *O, bool JustId) { 892 unsigned Index = 0; 893 for (const auto &Load : O->load_commands()) { 894 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 895 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 896 Load.C.cmd == MachO::LC_LOAD_DYLIB || 897 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 898 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 899 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 900 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 901 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 902 if (dl.dylib.name < dl.cmdsize) { 903 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 904 if (JustId) 905 outs() << p << "\n"; 906 else { 907 outs() << "\t" << p; 908 outs() << " (compatibility version " 909 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 910 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 911 << (dl.dylib.compatibility_version & 0xff) << ","; 912 outs() << " current version " 913 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 914 << ((dl.dylib.current_version >> 8) & 0xff) << "." 915 << (dl.dylib.current_version & 0xff) << ")\n"; 916 } 917 } else { 918 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 919 if (Load.C.cmd == MachO::LC_ID_DYLIB) 920 outs() << "LC_ID_DYLIB "; 921 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 922 outs() << "LC_LOAD_DYLIB "; 923 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 924 outs() << "LC_LOAD_WEAK_DYLIB "; 925 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 926 outs() << "LC_LAZY_LOAD_DYLIB "; 927 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 928 outs() << "LC_REEXPORT_DYLIB "; 929 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 930 outs() << "LC_LOAD_UPWARD_DYLIB "; 931 else 932 outs() << "LC_??? "; 933 outs() << "command " << Index++ << "\n"; 934 } 935 } 936 } 937 } 938 939 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 940 941 static void CreateSymbolAddressMap(MachOObjectFile *O, 942 SymbolAddressMap *AddrMap) { 943 // Create a map of symbol addresses to symbol names. 944 for (const SymbolRef &Symbol : O->symbols()) { 945 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 946 if (!STOrErr) 947 report_error(O->getFileName(), STOrErr.takeError()); 948 SymbolRef::Type ST = *STOrErr; 949 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 950 ST == SymbolRef::ST_Other) { 951 uint64_t Address = Symbol.getValue(); 952 Expected<StringRef> SymNameOrErr = Symbol.getName(); 953 if (!SymNameOrErr) 954 report_error(O->getFileName(), SymNameOrErr.takeError()); 955 StringRef SymName = *SymNameOrErr; 956 if (!SymName.startswith(".objc")) 957 (*AddrMap)[Address] = SymName; 958 } 959 } 960 } 961 962 // GuessSymbolName is passed the address of what might be a symbol and a 963 // pointer to the SymbolAddressMap. It returns the name of a symbol 964 // with that address or nullptr if no symbol is found with that address. 965 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 966 const char *SymbolName = nullptr; 967 // A DenseMap can't lookup up some values. 968 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 969 StringRef name = AddrMap->lookup(value); 970 if (!name.empty()) 971 SymbolName = name.data(); 972 } 973 return SymbolName; 974 } 975 976 static void DumpCstringChar(const char c) { 977 char p[2]; 978 p[0] = c; 979 p[1] = '\0'; 980 outs().write_escaped(p); 981 } 982 983 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 984 uint32_t sect_size, uint64_t sect_addr, 985 bool print_addresses) { 986 for (uint32_t i = 0; i < sect_size; i++) { 987 if (print_addresses) { 988 if (O->is64Bit()) 989 outs() << format("%016" PRIx64, sect_addr + i) << " "; 990 else 991 outs() << format("%08" PRIx64, sect_addr + i) << " "; 992 } 993 for (; i < sect_size && sect[i] != '\0'; i++) 994 DumpCstringChar(sect[i]); 995 if (i < sect_size && sect[i] == '\0') 996 outs() << "\n"; 997 } 998 } 999 1000 static void DumpLiteral4(uint32_t l, float f) { 1001 outs() << format("0x%08" PRIx32, l); 1002 if ((l & 0x7f800000) != 0x7f800000) 1003 outs() << format(" (%.16e)\n", f); 1004 else { 1005 if (l == 0x7f800000) 1006 outs() << " (+Infinity)\n"; 1007 else if (l == 0xff800000) 1008 outs() << " (-Infinity)\n"; 1009 else if ((l & 0x00400000) == 0x00400000) 1010 outs() << " (non-signaling Not-a-Number)\n"; 1011 else 1012 outs() << " (signaling Not-a-Number)\n"; 1013 } 1014 } 1015 1016 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 1017 uint32_t sect_size, uint64_t sect_addr, 1018 bool print_addresses) { 1019 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 1020 if (print_addresses) { 1021 if (O->is64Bit()) 1022 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1023 else 1024 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1025 } 1026 float f; 1027 memcpy(&f, sect + i, sizeof(float)); 1028 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1029 sys::swapByteOrder(f); 1030 uint32_t l; 1031 memcpy(&l, sect + i, sizeof(uint32_t)); 1032 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1033 sys::swapByteOrder(l); 1034 DumpLiteral4(l, f); 1035 } 1036 } 1037 1038 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 1039 double d) { 1040 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 1041 uint32_t Hi, Lo; 1042 Hi = (O->isLittleEndian()) ? l1 : l0; 1043 Lo = (O->isLittleEndian()) ? l0 : l1; 1044 1045 // Hi is the high word, so this is equivalent to if(isfinite(d)) 1046 if ((Hi & 0x7ff00000) != 0x7ff00000) 1047 outs() << format(" (%.16e)\n", d); 1048 else { 1049 if (Hi == 0x7ff00000 && Lo == 0) 1050 outs() << " (+Infinity)\n"; 1051 else if (Hi == 0xfff00000 && Lo == 0) 1052 outs() << " (-Infinity)\n"; 1053 else if ((Hi & 0x00080000) == 0x00080000) 1054 outs() << " (non-signaling Not-a-Number)\n"; 1055 else 1056 outs() << " (signaling Not-a-Number)\n"; 1057 } 1058 } 1059 1060 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 1061 uint32_t sect_size, uint64_t sect_addr, 1062 bool print_addresses) { 1063 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 1064 if (print_addresses) { 1065 if (O->is64Bit()) 1066 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1067 else 1068 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1069 } 1070 double d; 1071 memcpy(&d, sect + i, sizeof(double)); 1072 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1073 sys::swapByteOrder(d); 1074 uint32_t l0, l1; 1075 memcpy(&l0, sect + i, sizeof(uint32_t)); 1076 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1077 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1078 sys::swapByteOrder(l0); 1079 sys::swapByteOrder(l1); 1080 } 1081 DumpLiteral8(O, l0, l1, d); 1082 } 1083 } 1084 1085 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 1086 outs() << format("0x%08" PRIx32, l0) << " "; 1087 outs() << format("0x%08" PRIx32, l1) << " "; 1088 outs() << format("0x%08" PRIx32, l2) << " "; 1089 outs() << format("0x%08" PRIx32, l3) << "\n"; 1090 } 1091 1092 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 1093 uint32_t sect_size, uint64_t sect_addr, 1094 bool print_addresses) { 1095 for (uint32_t i = 0; i < sect_size; i += 16) { 1096 if (print_addresses) { 1097 if (O->is64Bit()) 1098 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1099 else 1100 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1101 } 1102 uint32_t l0, l1, l2, l3; 1103 memcpy(&l0, sect + i, sizeof(uint32_t)); 1104 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1105 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 1106 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1107 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1108 sys::swapByteOrder(l0); 1109 sys::swapByteOrder(l1); 1110 sys::swapByteOrder(l2); 1111 sys::swapByteOrder(l3); 1112 } 1113 DumpLiteral16(l0, l1, l2, l3); 1114 } 1115 } 1116 1117 static void DumpLiteralPointerSection(MachOObjectFile *O, 1118 const SectionRef &Section, 1119 const char *sect, uint32_t sect_size, 1120 uint64_t sect_addr, 1121 bool print_addresses) { 1122 // Collect the literal sections in this Mach-O file. 1123 std::vector<SectionRef> LiteralSections; 1124 for (const SectionRef &Section : O->sections()) { 1125 DataRefImpl Ref = Section.getRawDataRefImpl(); 1126 uint32_t section_type; 1127 if (O->is64Bit()) { 1128 const MachO::section_64 Sec = O->getSection64(Ref); 1129 section_type = Sec.flags & MachO::SECTION_TYPE; 1130 } else { 1131 const MachO::section Sec = O->getSection(Ref); 1132 section_type = Sec.flags & MachO::SECTION_TYPE; 1133 } 1134 if (section_type == MachO::S_CSTRING_LITERALS || 1135 section_type == MachO::S_4BYTE_LITERALS || 1136 section_type == MachO::S_8BYTE_LITERALS || 1137 section_type == MachO::S_16BYTE_LITERALS) 1138 LiteralSections.push_back(Section); 1139 } 1140 1141 // Set the size of the literal pointer. 1142 uint32_t lp_size = O->is64Bit() ? 8 : 4; 1143 1144 // Collect the external relocation symbols for the literal pointers. 1145 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1146 for (const RelocationRef &Reloc : Section.relocations()) { 1147 DataRefImpl Rel; 1148 MachO::any_relocation_info RE; 1149 bool isExtern = false; 1150 Rel = Reloc.getRawDataRefImpl(); 1151 RE = O->getRelocation(Rel); 1152 isExtern = O->getPlainRelocationExternal(RE); 1153 if (isExtern) { 1154 uint64_t RelocOffset = Reloc.getOffset(); 1155 symbol_iterator RelocSym = Reloc.getSymbol(); 1156 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1157 } 1158 } 1159 array_pod_sort(Relocs.begin(), Relocs.end()); 1160 1161 // Dump each literal pointer. 1162 for (uint32_t i = 0; i < sect_size; i += lp_size) { 1163 if (print_addresses) { 1164 if (O->is64Bit()) 1165 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1166 else 1167 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1168 } 1169 uint64_t lp; 1170 if (O->is64Bit()) { 1171 memcpy(&lp, sect + i, sizeof(uint64_t)); 1172 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1173 sys::swapByteOrder(lp); 1174 } else { 1175 uint32_t li; 1176 memcpy(&li, sect + i, sizeof(uint32_t)); 1177 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1178 sys::swapByteOrder(li); 1179 lp = li; 1180 } 1181 1182 // First look for an external relocation entry for this literal pointer. 1183 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1184 return P.first == i; 1185 }); 1186 if (Reloc != Relocs.end()) { 1187 symbol_iterator RelocSym = Reloc->second; 1188 Expected<StringRef> SymName = RelocSym->getName(); 1189 if (!SymName) 1190 report_error(O->getFileName(), SymName.takeError()); 1191 outs() << "external relocation entry for symbol:" << *SymName << "\n"; 1192 continue; 1193 } 1194 1195 // For local references see what the section the literal pointer points to. 1196 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 1197 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 1198 }); 1199 if (Sect == LiteralSections.end()) { 1200 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 1201 continue; 1202 } 1203 1204 uint64_t SectAddress = Sect->getAddress(); 1205 uint64_t SectSize = Sect->getSize(); 1206 1207 StringRef SectName; 1208 Sect->getName(SectName); 1209 DataRefImpl Ref = Sect->getRawDataRefImpl(); 1210 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 1211 outs() << SegmentName << ":" << SectName << ":"; 1212 1213 uint32_t section_type; 1214 if (O->is64Bit()) { 1215 const MachO::section_64 Sec = O->getSection64(Ref); 1216 section_type = Sec.flags & MachO::SECTION_TYPE; 1217 } else { 1218 const MachO::section Sec = O->getSection(Ref); 1219 section_type = Sec.flags & MachO::SECTION_TYPE; 1220 } 1221 1222 StringRef BytesStr; 1223 Sect->getContents(BytesStr); 1224 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 1225 1226 switch (section_type) { 1227 case MachO::S_CSTRING_LITERALS: 1228 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 1229 i++) { 1230 DumpCstringChar(Contents[i]); 1231 } 1232 outs() << "\n"; 1233 break; 1234 case MachO::S_4BYTE_LITERALS: 1235 float f; 1236 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 1237 uint32_t l; 1238 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 1239 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1240 sys::swapByteOrder(f); 1241 sys::swapByteOrder(l); 1242 } 1243 DumpLiteral4(l, f); 1244 break; 1245 case MachO::S_8BYTE_LITERALS: { 1246 double d; 1247 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 1248 uint32_t l0, l1; 1249 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1250 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1251 sizeof(uint32_t)); 1252 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1253 sys::swapByteOrder(f); 1254 sys::swapByteOrder(l0); 1255 sys::swapByteOrder(l1); 1256 } 1257 DumpLiteral8(O, l0, l1, d); 1258 break; 1259 } 1260 case MachO::S_16BYTE_LITERALS: { 1261 uint32_t l0, l1, l2, l3; 1262 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1263 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1264 sizeof(uint32_t)); 1265 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 1266 sizeof(uint32_t)); 1267 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 1268 sizeof(uint32_t)); 1269 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1270 sys::swapByteOrder(l0); 1271 sys::swapByteOrder(l1); 1272 sys::swapByteOrder(l2); 1273 sys::swapByteOrder(l3); 1274 } 1275 DumpLiteral16(l0, l1, l2, l3); 1276 break; 1277 } 1278 } 1279 } 1280 } 1281 1282 static void DumpInitTermPointerSection(MachOObjectFile *O, 1283 const SectionRef &Section, 1284 const char *sect, 1285 uint32_t sect_size, uint64_t sect_addr, 1286 SymbolAddressMap *AddrMap, 1287 bool verbose) { 1288 uint32_t stride; 1289 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 1290 1291 // Collect the external relocation symbols for the pointers. 1292 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1293 for (const RelocationRef &Reloc : Section.relocations()) { 1294 DataRefImpl Rel; 1295 MachO::any_relocation_info RE; 1296 bool isExtern = false; 1297 Rel = Reloc.getRawDataRefImpl(); 1298 RE = O->getRelocation(Rel); 1299 isExtern = O->getPlainRelocationExternal(RE); 1300 if (isExtern) { 1301 uint64_t RelocOffset = Reloc.getOffset(); 1302 symbol_iterator RelocSym = Reloc.getSymbol(); 1303 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1304 } 1305 } 1306 array_pod_sort(Relocs.begin(), Relocs.end()); 1307 1308 for (uint32_t i = 0; i < sect_size; i += stride) { 1309 const char *SymbolName = nullptr; 1310 uint64_t p; 1311 if (O->is64Bit()) { 1312 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 1313 uint64_t pointer_value; 1314 memcpy(&pointer_value, sect + i, stride); 1315 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1316 sys::swapByteOrder(pointer_value); 1317 outs() << format("0x%016" PRIx64, pointer_value); 1318 p = pointer_value; 1319 } else { 1320 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 1321 uint32_t pointer_value; 1322 memcpy(&pointer_value, sect + i, stride); 1323 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1324 sys::swapByteOrder(pointer_value); 1325 outs() << format("0x%08" PRIx32, pointer_value); 1326 p = pointer_value; 1327 } 1328 if (verbose) { 1329 // First look for an external relocation entry for this pointer. 1330 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1331 return P.first == i; 1332 }); 1333 if (Reloc != Relocs.end()) { 1334 symbol_iterator RelocSym = Reloc->second; 1335 Expected<StringRef> SymName = RelocSym->getName(); 1336 if (!SymName) 1337 report_error(O->getFileName(), SymName.takeError()); 1338 outs() << " " << *SymName; 1339 } else { 1340 SymbolName = GuessSymbolName(p, AddrMap); 1341 if (SymbolName) 1342 outs() << " " << SymbolName; 1343 } 1344 } 1345 outs() << "\n"; 1346 } 1347 } 1348 1349 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 1350 uint32_t size, uint64_t addr) { 1351 uint32_t cputype = O->getHeader().cputype; 1352 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 1353 uint32_t j; 1354 for (uint32_t i = 0; i < size; i += j, addr += j) { 1355 if (O->is64Bit()) 1356 outs() << format("%016" PRIx64, addr) << "\t"; 1357 else 1358 outs() << format("%08" PRIx64, addr) << "\t"; 1359 for (j = 0; j < 16 && i + j < size; j++) { 1360 uint8_t byte_word = *(sect + i + j); 1361 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1362 } 1363 outs() << "\n"; 1364 } 1365 } else { 1366 uint32_t j; 1367 for (uint32_t i = 0; i < size; i += j, addr += j) { 1368 if (O->is64Bit()) 1369 outs() << format("%016" PRIx64, addr) << "\t"; 1370 else 1371 outs() << format("%08" PRIx64, addr) << "\t"; 1372 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 1373 j += sizeof(int32_t)) { 1374 if (i + j + sizeof(int32_t) <= size) { 1375 uint32_t long_word; 1376 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1377 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1378 sys::swapByteOrder(long_word); 1379 outs() << format("%08" PRIx32, long_word) << " "; 1380 } else { 1381 for (uint32_t k = 0; i + j + k < size; k++) { 1382 uint8_t byte_word = *(sect + i + j + k); 1383 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1384 } 1385 } 1386 } 1387 outs() << "\n"; 1388 } 1389 } 1390 } 1391 1392 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1393 StringRef DisSegName, StringRef DisSectName); 1394 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1395 uint32_t size, uint32_t addr); 1396 #ifdef HAVE_LIBXAR 1397 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 1398 uint32_t size, bool verbose, 1399 bool PrintXarHeader, bool PrintXarFileHeaders, 1400 std::string XarMemberName); 1401 #endif // defined(HAVE_LIBXAR) 1402 1403 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1404 bool verbose) { 1405 SymbolAddressMap AddrMap; 1406 if (verbose) 1407 CreateSymbolAddressMap(O, &AddrMap); 1408 1409 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1410 StringRef DumpSection = FilterSections[i]; 1411 std::pair<StringRef, StringRef> DumpSegSectName; 1412 DumpSegSectName = DumpSection.split(','); 1413 StringRef DumpSegName, DumpSectName; 1414 if (DumpSegSectName.second.size()) { 1415 DumpSegName = DumpSegSectName.first; 1416 DumpSectName = DumpSegSectName.second; 1417 } else { 1418 DumpSegName = ""; 1419 DumpSectName = DumpSegSectName.first; 1420 } 1421 for (const SectionRef &Section : O->sections()) { 1422 StringRef SectName; 1423 Section.getName(SectName); 1424 DataRefImpl Ref = Section.getRawDataRefImpl(); 1425 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1426 if ((DumpSegName.empty() || SegName == DumpSegName) && 1427 (SectName == DumpSectName)) { 1428 1429 uint32_t section_flags; 1430 if (O->is64Bit()) { 1431 const MachO::section_64 Sec = O->getSection64(Ref); 1432 section_flags = Sec.flags; 1433 1434 } else { 1435 const MachO::section Sec = O->getSection(Ref); 1436 section_flags = Sec.flags; 1437 } 1438 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1439 1440 StringRef BytesStr; 1441 Section.getContents(BytesStr); 1442 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1443 uint32_t sect_size = BytesStr.size(); 1444 uint64_t sect_addr = Section.getAddress(); 1445 1446 outs() << "Contents of (" << SegName << "," << SectName 1447 << ") section\n"; 1448 1449 if (verbose) { 1450 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1451 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1452 DisassembleMachO(Filename, O, SegName, SectName); 1453 continue; 1454 } 1455 if (SegName == "__TEXT" && SectName == "__info_plist") { 1456 outs() << sect; 1457 continue; 1458 } 1459 if (SegName == "__OBJC" && SectName == "__protocol") { 1460 DumpProtocolSection(O, sect, sect_size, sect_addr); 1461 continue; 1462 } 1463 #ifdef HAVE_LIBXAR 1464 if (SegName == "__LLVM" && SectName == "__bundle") { 1465 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands, 1466 ArchiveHeaders, ""); 1467 continue; 1468 } 1469 #endif // defined(HAVE_LIBXAR) 1470 switch (section_type) { 1471 case MachO::S_REGULAR: 1472 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1473 break; 1474 case MachO::S_ZEROFILL: 1475 outs() << "zerofill section and has no contents in the file\n"; 1476 break; 1477 case MachO::S_CSTRING_LITERALS: 1478 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1479 break; 1480 case MachO::S_4BYTE_LITERALS: 1481 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1482 break; 1483 case MachO::S_8BYTE_LITERALS: 1484 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1485 break; 1486 case MachO::S_16BYTE_LITERALS: 1487 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1488 break; 1489 case MachO::S_LITERAL_POINTERS: 1490 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1491 !NoLeadingAddr); 1492 break; 1493 case MachO::S_MOD_INIT_FUNC_POINTERS: 1494 case MachO::S_MOD_TERM_FUNC_POINTERS: 1495 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr, 1496 &AddrMap, verbose); 1497 break; 1498 default: 1499 outs() << "Unknown section type (" 1500 << format("0x%08" PRIx32, section_type) << ")\n"; 1501 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1502 break; 1503 } 1504 } else { 1505 if (section_type == MachO::S_ZEROFILL) 1506 outs() << "zerofill section and has no contents in the file\n"; 1507 else 1508 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1509 } 1510 } 1511 } 1512 } 1513 } 1514 1515 static void DumpInfoPlistSectionContents(StringRef Filename, 1516 MachOObjectFile *O) { 1517 for (const SectionRef &Section : O->sections()) { 1518 StringRef SectName; 1519 Section.getName(SectName); 1520 DataRefImpl Ref = Section.getRawDataRefImpl(); 1521 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1522 if (SegName == "__TEXT" && SectName == "__info_plist") { 1523 if (!NoLeadingHeaders) 1524 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1525 StringRef BytesStr; 1526 Section.getContents(BytesStr); 1527 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1528 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 1529 return; 1530 } 1531 } 1532 } 1533 1534 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1535 // and if it is and there is a list of architecture flags is specified then 1536 // check to make sure this Mach-O file is one of those architectures or all 1537 // architectures were specified. If not then an error is generated and this 1538 // routine returns false. Else it returns true. 1539 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1540 auto *MachO = dyn_cast<MachOObjectFile>(O); 1541 1542 if (!MachO || ArchAll || ArchFlags.empty()) 1543 return true; 1544 1545 MachO::mach_header H; 1546 MachO::mach_header_64 H_64; 1547 Triple T; 1548 const char *McpuDefault, *ArchFlag; 1549 if (MachO->is64Bit()) { 1550 H_64 = MachO->MachOObjectFile::getHeader64(); 1551 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 1552 &McpuDefault, &ArchFlag); 1553 } else { 1554 H = MachO->MachOObjectFile::getHeader(); 1555 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 1556 &McpuDefault, &ArchFlag); 1557 } 1558 const std::string ArchFlagName(ArchFlag); 1559 if (none_of(ArchFlags, [&](const std::string &Name) { 1560 return Name == ArchFlagName; 1561 })) { 1562 errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n"; 1563 return false; 1564 } 1565 return true; 1566 } 1567 1568 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 1569 1570 // ProcessMachO() is passed a single opened Mach-O file, which may be an 1571 // archive member and or in a slice of a universal file. It prints the 1572 // the file name and header info and then processes it according to the 1573 // command line options. 1574 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 1575 StringRef ArchiveMemberName = StringRef(), 1576 StringRef ArchitectureName = StringRef()) { 1577 // If we are doing some processing here on the Mach-O file print the header 1578 // info. And don't print it otherwise like in the case of printing the 1579 // UniversalHeaders or ArchiveHeaders. 1580 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || 1581 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || 1582 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData || 1583 (FilterSections.size() != 0)) { 1584 if (!NoLeadingHeaders) { 1585 outs() << Name; 1586 if (!ArchiveMemberName.empty()) 1587 outs() << '(' << ArchiveMemberName << ')'; 1588 if (!ArchitectureName.empty()) 1589 outs() << " (architecture " << ArchitectureName << ")"; 1590 outs() << ":\n"; 1591 } 1592 } 1593 // To use the report_error() form with an ArchiveName and FileName set 1594 // these up based on what is passed for Name and ArchiveMemberName. 1595 StringRef ArchiveName; 1596 StringRef FileName; 1597 if (!ArchiveMemberName.empty()) { 1598 ArchiveName = Name; 1599 FileName = ArchiveMemberName; 1600 } else { 1601 ArchiveName = StringRef(); 1602 FileName = Name; 1603 } 1604 1605 // If we need the symbol table to do the operation then check it here to 1606 // produce a good error message as to where the Mach-O file comes from in 1607 // the error message. 1608 if (Disassemble || IndirectSymbols || FilterSections.size() != 0 || 1609 UnwindInfo) 1610 if (Error Err = MachOOF->checkSymbolTable()) 1611 report_error(ArchiveName, FileName, std::move(Err), ArchitectureName); 1612 1613 if (Disassemble) { 1614 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE && 1615 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64) 1616 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text"); 1617 else 1618 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 1619 } 1620 if (IndirectSymbols) 1621 PrintIndirectSymbols(MachOOF, !NonVerbose); 1622 if (DataInCode) 1623 PrintDataInCodeTable(MachOOF, !NonVerbose); 1624 if (LinkOptHints) 1625 PrintLinkOptHints(MachOOF); 1626 if (Relocations) 1627 PrintRelocations(MachOOF, !NonVerbose); 1628 if (SectionHeaders) 1629 PrintSectionHeaders(MachOOF); 1630 if (SectionContents) 1631 PrintSectionContents(MachOOF); 1632 if (FilterSections.size() != 0) 1633 DumpSectionContents(FileName, MachOOF, !NonVerbose); 1634 if (InfoPlist) 1635 DumpInfoPlistSectionContents(FileName, MachOOF); 1636 if (DylibsUsed) 1637 PrintDylibs(MachOOF, false); 1638 if (DylibId) 1639 PrintDylibs(MachOOF, true); 1640 if (SymbolTable) 1641 PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName); 1642 if (UnwindInfo) 1643 printMachOUnwindInfo(MachOOF); 1644 if (PrivateHeaders) { 1645 printMachOFileHeader(MachOOF); 1646 printMachOLoadCommands(MachOOF); 1647 } 1648 if (FirstPrivateHeader) 1649 printMachOFileHeader(MachOOF); 1650 if (ObjcMetaData) 1651 printObjcMetaData(MachOOF, !NonVerbose); 1652 if (ExportsTrie) 1653 printExportsTrie(MachOOF); 1654 if (Rebase) 1655 printRebaseTable(MachOOF); 1656 if (Bind) 1657 printBindTable(MachOOF); 1658 if (LazyBind) 1659 printLazyBindTable(MachOOF); 1660 if (WeakBind) 1661 printWeakBindTable(MachOOF); 1662 1663 if (DwarfDumpType != DIDT_Null) { 1664 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF); 1665 // Dump the complete DWARF structure. 1666 DIDumpOptions DumpOpts; 1667 DumpOpts.DumpType = DwarfDumpType; 1668 DICtx->dump(outs(), DumpOpts); 1669 } 1670 } 1671 1672 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 1673 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 1674 outs() << " cputype (" << cputype << ")\n"; 1675 outs() << " cpusubtype (" << cpusubtype << ")\n"; 1676 } 1677 1678 // printCPUType() helps print_fat_headers by printing the cputype and 1679 // pusubtype (symbolically for the one's it knows about). 1680 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 1681 switch (cputype) { 1682 case MachO::CPU_TYPE_I386: 1683 switch (cpusubtype) { 1684 case MachO::CPU_SUBTYPE_I386_ALL: 1685 outs() << " cputype CPU_TYPE_I386\n"; 1686 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 1687 break; 1688 default: 1689 printUnknownCPUType(cputype, cpusubtype); 1690 break; 1691 } 1692 break; 1693 case MachO::CPU_TYPE_X86_64: 1694 switch (cpusubtype) { 1695 case MachO::CPU_SUBTYPE_X86_64_ALL: 1696 outs() << " cputype CPU_TYPE_X86_64\n"; 1697 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 1698 break; 1699 case MachO::CPU_SUBTYPE_X86_64_H: 1700 outs() << " cputype CPU_TYPE_X86_64\n"; 1701 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 1702 break; 1703 default: 1704 printUnknownCPUType(cputype, cpusubtype); 1705 break; 1706 } 1707 break; 1708 case MachO::CPU_TYPE_ARM: 1709 switch (cpusubtype) { 1710 case MachO::CPU_SUBTYPE_ARM_ALL: 1711 outs() << " cputype CPU_TYPE_ARM\n"; 1712 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 1713 break; 1714 case MachO::CPU_SUBTYPE_ARM_V4T: 1715 outs() << " cputype CPU_TYPE_ARM\n"; 1716 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 1717 break; 1718 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1719 outs() << " cputype CPU_TYPE_ARM\n"; 1720 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 1721 break; 1722 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1723 outs() << " cputype CPU_TYPE_ARM\n"; 1724 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 1725 break; 1726 case MachO::CPU_SUBTYPE_ARM_V6: 1727 outs() << " cputype CPU_TYPE_ARM\n"; 1728 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 1729 break; 1730 case MachO::CPU_SUBTYPE_ARM_V6M: 1731 outs() << " cputype CPU_TYPE_ARM\n"; 1732 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 1733 break; 1734 case MachO::CPU_SUBTYPE_ARM_V7: 1735 outs() << " cputype CPU_TYPE_ARM\n"; 1736 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 1737 break; 1738 case MachO::CPU_SUBTYPE_ARM_V7EM: 1739 outs() << " cputype CPU_TYPE_ARM\n"; 1740 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 1741 break; 1742 case MachO::CPU_SUBTYPE_ARM_V7K: 1743 outs() << " cputype CPU_TYPE_ARM\n"; 1744 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 1745 break; 1746 case MachO::CPU_SUBTYPE_ARM_V7M: 1747 outs() << " cputype CPU_TYPE_ARM\n"; 1748 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 1749 break; 1750 case MachO::CPU_SUBTYPE_ARM_V7S: 1751 outs() << " cputype CPU_TYPE_ARM\n"; 1752 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 1753 break; 1754 default: 1755 printUnknownCPUType(cputype, cpusubtype); 1756 break; 1757 } 1758 break; 1759 case MachO::CPU_TYPE_ARM64: 1760 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 1761 case MachO::CPU_SUBTYPE_ARM64_ALL: 1762 outs() << " cputype CPU_TYPE_ARM64\n"; 1763 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 1764 break; 1765 default: 1766 printUnknownCPUType(cputype, cpusubtype); 1767 break; 1768 } 1769 break; 1770 default: 1771 printUnknownCPUType(cputype, cpusubtype); 1772 break; 1773 } 1774 } 1775 1776 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 1777 bool verbose) { 1778 outs() << "Fat headers\n"; 1779 if (verbose) { 1780 if (UB->getMagic() == MachO::FAT_MAGIC) 1781 outs() << "fat_magic FAT_MAGIC\n"; 1782 else // UB->getMagic() == MachO::FAT_MAGIC_64 1783 outs() << "fat_magic FAT_MAGIC_64\n"; 1784 } else 1785 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 1786 1787 uint32_t nfat_arch = UB->getNumberOfObjects(); 1788 StringRef Buf = UB->getData(); 1789 uint64_t size = Buf.size(); 1790 uint64_t big_size = sizeof(struct MachO::fat_header) + 1791 nfat_arch * sizeof(struct MachO::fat_arch); 1792 outs() << "nfat_arch " << UB->getNumberOfObjects(); 1793 if (nfat_arch == 0) 1794 outs() << " (malformed, contains zero architecture types)\n"; 1795 else if (big_size > size) 1796 outs() << " (malformed, architectures past end of file)\n"; 1797 else 1798 outs() << "\n"; 1799 1800 for (uint32_t i = 0; i < nfat_arch; ++i) { 1801 MachOUniversalBinary::ObjectForArch OFA(UB, i); 1802 uint32_t cputype = OFA.getCPUType(); 1803 uint32_t cpusubtype = OFA.getCPUSubType(); 1804 outs() << "architecture "; 1805 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 1806 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 1807 uint32_t other_cputype = other_OFA.getCPUType(); 1808 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 1809 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 1810 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 1811 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 1812 outs() << "(illegal duplicate architecture) "; 1813 break; 1814 } 1815 } 1816 if (verbose) { 1817 outs() << OFA.getArchFlagName() << "\n"; 1818 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 1819 } else { 1820 outs() << i << "\n"; 1821 outs() << " cputype " << cputype << "\n"; 1822 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 1823 << "\n"; 1824 } 1825 if (verbose && 1826 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 1827 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 1828 else 1829 outs() << " capabilities " 1830 << format("0x%" PRIx32, 1831 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 1832 outs() << " offset " << OFA.getOffset(); 1833 if (OFA.getOffset() > size) 1834 outs() << " (past end of file)"; 1835 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0) 1836 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 1837 outs() << "\n"; 1838 outs() << " size " << OFA.getSize(); 1839 big_size = OFA.getOffset() + OFA.getSize(); 1840 if (big_size > size) 1841 outs() << " (past end of file)"; 1842 outs() << "\n"; 1843 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 1844 << ")\n"; 1845 } 1846 } 1847 1848 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 1849 bool verbose, bool print_offset, 1850 StringRef ArchitectureName = StringRef()) { 1851 if (print_offset) 1852 outs() << C.getChildOffset() << "\t"; 1853 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode(); 1854 if (!ModeOrErr) 1855 report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName); 1856 sys::fs::perms Mode = ModeOrErr.get(); 1857 if (verbose) { 1858 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 1859 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 1860 outs() << "-"; 1861 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 1862 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 1863 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 1864 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 1865 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 1866 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 1867 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 1868 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 1869 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 1870 } else { 1871 outs() << format("0%o ", Mode); 1872 } 1873 1874 Expected<unsigned> UIDOrErr = C.getUID(); 1875 if (!UIDOrErr) 1876 report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName); 1877 unsigned UID = UIDOrErr.get(); 1878 outs() << format("%3d/", UID); 1879 Expected<unsigned> GIDOrErr = C.getGID(); 1880 if (!GIDOrErr) 1881 report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName); 1882 unsigned GID = GIDOrErr.get(); 1883 outs() << format("%-3d ", GID); 1884 Expected<uint64_t> Size = C.getRawSize(); 1885 if (!Size) 1886 report_error(Filename, C, Size.takeError(), ArchitectureName); 1887 outs() << format("%5" PRId64, Size.get()) << " "; 1888 1889 StringRef RawLastModified = C.getRawLastModified(); 1890 if (verbose) { 1891 unsigned Seconds; 1892 if (RawLastModified.getAsInteger(10, Seconds)) 1893 outs() << "(date: \"" << RawLastModified 1894 << "\" contains non-decimal chars) "; 1895 else { 1896 // Since cime(3) returns a 26 character string of the form: 1897 // "Sun Sep 16 01:03:52 1973\n\0" 1898 // just print 24 characters. 1899 time_t t = Seconds; 1900 outs() << format("%.24s ", ctime(&t)); 1901 } 1902 } else { 1903 outs() << RawLastModified << " "; 1904 } 1905 1906 if (verbose) { 1907 Expected<StringRef> NameOrErr = C.getName(); 1908 if (!NameOrErr) { 1909 consumeError(NameOrErr.takeError()); 1910 Expected<StringRef> NameOrErr = C.getRawName(); 1911 if (!NameOrErr) 1912 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1913 StringRef RawName = NameOrErr.get(); 1914 outs() << RawName << "\n"; 1915 } else { 1916 StringRef Name = NameOrErr.get(); 1917 outs() << Name << "\n"; 1918 } 1919 } else { 1920 Expected<StringRef> NameOrErr = C.getRawName(); 1921 if (!NameOrErr) 1922 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1923 StringRef RawName = NameOrErr.get(); 1924 outs() << RawName << "\n"; 1925 } 1926 } 1927 1928 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 1929 bool print_offset, 1930 StringRef ArchitectureName = StringRef()) { 1931 Error Err = Error::success(); 1932 ; 1933 for (const auto &C : A->children(Err, false)) 1934 printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName); 1935 1936 if (Err) 1937 report_error(StringRef(), Filename, std::move(Err), ArchitectureName); 1938 } 1939 1940 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 1941 // -arch flags selecting just those slices as specified by them and also parses 1942 // archive files. Then for each individual Mach-O file ProcessMachO() is 1943 // called to process the file based on the command line options. 1944 void llvm::ParseInputMachO(StringRef Filename) { 1945 // Check for -arch all and verifiy the -arch flags are valid. 1946 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 1947 if (ArchFlags[i] == "all") { 1948 ArchAll = true; 1949 } else { 1950 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 1951 errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] + 1952 "'for the -arch option\n"; 1953 return; 1954 } 1955 } 1956 } 1957 1958 // Attempt to open the binary. 1959 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 1960 if (!BinaryOrErr) { 1961 if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 1962 report_error(Filename, std::move(E)); 1963 else 1964 outs() << Filename << ": is not an object file\n"; 1965 return; 1966 } 1967 Binary &Bin = *BinaryOrErr.get().getBinary(); 1968 1969 if (Archive *A = dyn_cast<Archive>(&Bin)) { 1970 outs() << "Archive : " << Filename << "\n"; 1971 if (ArchiveHeaders) 1972 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets); 1973 1974 Error Err = Error::success(); 1975 for (auto &C : A->children(Err)) { 1976 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 1977 if (!ChildOrErr) { 1978 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 1979 report_error(Filename, C, std::move(E)); 1980 continue; 1981 } 1982 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 1983 if (!checkMachOAndArchFlags(O, Filename)) 1984 return; 1985 ProcessMachO(Filename, O, O->getFileName()); 1986 } 1987 } 1988 if (Err) 1989 report_error(Filename, std::move(Err)); 1990 return; 1991 } 1992 if (UniversalHeaders) { 1993 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) 1994 printMachOUniversalHeaders(UB, !NonVerbose); 1995 } 1996 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 1997 // If we have a list of architecture flags specified dump only those. 1998 if (!ArchAll && ArchFlags.size() != 0) { 1999 // Look for a slice in the universal binary that matches each ArchFlag. 2000 bool ArchFound; 2001 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2002 ArchFound = false; 2003 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2004 E = UB->end_objects(); 2005 I != E; ++I) { 2006 if (ArchFlags[i] == I->getArchFlagName()) { 2007 ArchFound = true; 2008 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2009 I->getAsObjectFile(); 2010 std::string ArchitectureName = ""; 2011 if (ArchFlags.size() > 1) 2012 ArchitectureName = I->getArchFlagName(); 2013 if (ObjOrErr) { 2014 ObjectFile &O = *ObjOrErr.get(); 2015 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2016 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2017 } else if (auto E = isNotObjectErrorInvalidFileType( 2018 ObjOrErr.takeError())) { 2019 report_error(Filename, StringRef(), std::move(E), 2020 ArchitectureName); 2021 continue; 2022 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2023 I->getAsArchive()) { 2024 std::unique_ptr<Archive> &A = *AOrErr; 2025 outs() << "Archive : " << Filename; 2026 if (!ArchitectureName.empty()) 2027 outs() << " (architecture " << ArchitectureName << ")"; 2028 outs() << "\n"; 2029 if (ArchiveHeaders) 2030 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2031 ArchiveMemberOffsets, ArchitectureName); 2032 Error Err = Error::success(); 2033 for (auto &C : A->children(Err)) { 2034 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2035 if (!ChildOrErr) { 2036 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2037 report_error(Filename, C, std::move(E), ArchitectureName); 2038 continue; 2039 } 2040 if (MachOObjectFile *O = 2041 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2042 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2043 } 2044 if (Err) 2045 report_error(Filename, std::move(Err)); 2046 } else { 2047 consumeError(AOrErr.takeError()); 2048 error("Mach-O universal file: " + Filename + " for " + 2049 "architecture " + StringRef(I->getArchFlagName()) + 2050 " is not a Mach-O file or an archive file"); 2051 } 2052 } 2053 } 2054 if (!ArchFound) { 2055 errs() << "llvm-objdump: file: " + Filename + " does not contain " 2056 << "architecture: " + ArchFlags[i] + "\n"; 2057 return; 2058 } 2059 } 2060 return; 2061 } 2062 // No architecture flags were specified so if this contains a slice that 2063 // matches the host architecture dump only that. 2064 if (!ArchAll) { 2065 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2066 E = UB->end_objects(); 2067 I != E; ++I) { 2068 if (MachOObjectFile::getHostArch().getArchName() == 2069 I->getArchFlagName()) { 2070 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2071 std::string ArchiveName; 2072 ArchiveName.clear(); 2073 if (ObjOrErr) { 2074 ObjectFile &O = *ObjOrErr.get(); 2075 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2076 ProcessMachO(Filename, MachOOF); 2077 } else if (auto E = isNotObjectErrorInvalidFileType( 2078 ObjOrErr.takeError())) { 2079 report_error(Filename, std::move(E)); 2080 continue; 2081 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2082 I->getAsArchive()) { 2083 std::unique_ptr<Archive> &A = *AOrErr; 2084 outs() << "Archive : " << Filename << "\n"; 2085 if (ArchiveHeaders) 2086 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2087 ArchiveMemberOffsets); 2088 Error Err = Error::success(); 2089 for (auto &C : A->children(Err)) { 2090 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2091 if (!ChildOrErr) { 2092 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2093 report_error(Filename, C, std::move(E)); 2094 continue; 2095 } 2096 if (MachOObjectFile *O = 2097 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2098 ProcessMachO(Filename, O, O->getFileName()); 2099 } 2100 if (Err) 2101 report_error(Filename, std::move(Err)); 2102 } else { 2103 consumeError(AOrErr.takeError()); 2104 error("Mach-O universal file: " + Filename + " for architecture " + 2105 StringRef(I->getArchFlagName()) + 2106 " is not a Mach-O file or an archive file"); 2107 } 2108 return; 2109 } 2110 } 2111 } 2112 // Either all architectures have been specified or none have been specified 2113 // and this does not contain the host architecture so dump all the slices. 2114 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2115 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2116 E = UB->end_objects(); 2117 I != E; ++I) { 2118 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2119 std::string ArchitectureName = ""; 2120 if (moreThanOneArch) 2121 ArchitectureName = I->getArchFlagName(); 2122 if (ObjOrErr) { 2123 ObjectFile &Obj = *ObjOrErr.get(); 2124 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2125 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2126 } else if (auto E = isNotObjectErrorInvalidFileType( 2127 ObjOrErr.takeError())) { 2128 report_error(StringRef(), Filename, std::move(E), ArchitectureName); 2129 continue; 2130 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2131 I->getAsArchive()) { 2132 std::unique_ptr<Archive> &A = *AOrErr; 2133 outs() << "Archive : " << Filename; 2134 if (!ArchitectureName.empty()) 2135 outs() << " (architecture " << ArchitectureName << ")"; 2136 outs() << "\n"; 2137 if (ArchiveHeaders) 2138 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2139 ArchiveMemberOffsets, ArchitectureName); 2140 Error Err = Error::success(); 2141 for (auto &C : A->children(Err)) { 2142 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2143 if (!ChildOrErr) { 2144 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2145 report_error(Filename, C, std::move(E), ArchitectureName); 2146 continue; 2147 } 2148 if (MachOObjectFile *O = 2149 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2150 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2151 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2152 ArchitectureName); 2153 } 2154 } 2155 if (Err) 2156 report_error(Filename, std::move(Err)); 2157 } else { 2158 consumeError(AOrErr.takeError()); 2159 error("Mach-O universal file: " + Filename + " for architecture " + 2160 StringRef(I->getArchFlagName()) + 2161 " is not a Mach-O file or an archive file"); 2162 } 2163 } 2164 return; 2165 } 2166 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2167 if (!checkMachOAndArchFlags(O, Filename)) 2168 return; 2169 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) { 2170 ProcessMachO(Filename, MachOOF); 2171 } else 2172 errs() << "llvm-objdump: '" << Filename << "': " 2173 << "Object is not a Mach-O file type.\n"; 2174 return; 2175 } 2176 llvm_unreachable("Input object can't be invalid at this point"); 2177 } 2178 2179 // The block of info used by the Symbolizer call backs. 2180 struct DisassembleInfo { 2181 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, 2182 std::vector<SectionRef> *Sections, bool verbose) 2183 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {} 2184 bool verbose; 2185 MachOObjectFile *O; 2186 SectionRef S; 2187 SymbolAddressMap *AddrMap; 2188 std::vector<SectionRef> *Sections; 2189 const char *class_name = nullptr; 2190 const char *selector_name = nullptr; 2191 std::unique_ptr<char[]> method = nullptr; 2192 char *demangled_name = nullptr; 2193 uint64_t adrp_addr = 0; 2194 uint32_t adrp_inst = 0; 2195 std::unique_ptr<SymbolAddressMap> bindtable; 2196 uint32_t depth = 0; 2197 }; 2198 2199 // SymbolizerGetOpInfo() is the operand information call back function. 2200 // This is called to get the symbolic information for operand(s) of an 2201 // instruction when it is being done. This routine does this from 2202 // the relocation information, symbol table, etc. That block of information 2203 // is a pointer to the struct DisassembleInfo that was passed when the 2204 // disassembler context was created and passed to back to here when 2205 // called back by the disassembler for instruction operands that could have 2206 // relocation information. The address of the instruction containing operand is 2207 // at the Pc parameter. The immediate value the operand has is passed in 2208 // op_info->Value and is at Offset past the start of the instruction and has a 2209 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2210 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2211 // names and addends of the symbolic expression to add for the operand. The 2212 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2213 // information is returned then this function returns 1 else it returns 0. 2214 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2215 uint64_t Size, int TagType, void *TagBuf) { 2216 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2217 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2218 uint64_t value = op_info->Value; 2219 2220 // Make sure all fields returned are zero if we don't set them. 2221 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2222 op_info->Value = value; 2223 2224 // If the TagType is not the value 1 which it code knows about or if no 2225 // verbose symbolic information is wanted then just return 0, indicating no 2226 // information is being returned. 2227 if (TagType != 1 || !info->verbose) 2228 return 0; 2229 2230 unsigned int Arch = info->O->getArch(); 2231 if (Arch == Triple::x86) { 2232 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2233 return 0; 2234 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2235 // TODO: 2236 // Search the external relocation entries of a fully linked image 2237 // (if any) for an entry that matches this segment offset. 2238 // uint32_t seg_offset = (Pc + Offset); 2239 return 0; 2240 } 2241 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2242 // for an entry for this section offset. 2243 uint32_t sect_addr = info->S.getAddress(); 2244 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2245 bool reloc_found = false; 2246 DataRefImpl Rel; 2247 MachO::any_relocation_info RE; 2248 bool isExtern = false; 2249 SymbolRef Symbol; 2250 bool r_scattered = false; 2251 uint32_t r_value, pair_r_value, r_type; 2252 for (const RelocationRef &Reloc : info->S.relocations()) { 2253 uint64_t RelocOffset = Reloc.getOffset(); 2254 if (RelocOffset == sect_offset) { 2255 Rel = Reloc.getRawDataRefImpl(); 2256 RE = info->O->getRelocation(Rel); 2257 r_type = info->O->getAnyRelocationType(RE); 2258 r_scattered = info->O->isRelocationScattered(RE); 2259 if (r_scattered) { 2260 r_value = info->O->getScatteredRelocationValue(RE); 2261 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2262 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2263 DataRefImpl RelNext = Rel; 2264 info->O->moveRelocationNext(RelNext); 2265 MachO::any_relocation_info RENext; 2266 RENext = info->O->getRelocation(RelNext); 2267 if (info->O->isRelocationScattered(RENext)) 2268 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2269 else 2270 return 0; 2271 } 2272 } else { 2273 isExtern = info->O->getPlainRelocationExternal(RE); 2274 if (isExtern) { 2275 symbol_iterator RelocSym = Reloc.getSymbol(); 2276 Symbol = *RelocSym; 2277 } 2278 } 2279 reloc_found = true; 2280 break; 2281 } 2282 } 2283 if (reloc_found && isExtern) { 2284 Expected<StringRef> SymName = Symbol.getName(); 2285 if (!SymName) 2286 report_error(info->O->getFileName(), SymName.takeError()); 2287 const char *name = SymName->data(); 2288 op_info->AddSymbol.Present = 1; 2289 op_info->AddSymbol.Name = name; 2290 // For i386 extern relocation entries the value in the instruction is 2291 // the offset from the symbol, and value is already set in op_info->Value. 2292 return 1; 2293 } 2294 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2295 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2296 const char *add = GuessSymbolName(r_value, info->AddrMap); 2297 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2298 uint32_t offset = value - (r_value - pair_r_value); 2299 op_info->AddSymbol.Present = 1; 2300 if (add != nullptr) 2301 op_info->AddSymbol.Name = add; 2302 else 2303 op_info->AddSymbol.Value = r_value; 2304 op_info->SubtractSymbol.Present = 1; 2305 if (sub != nullptr) 2306 op_info->SubtractSymbol.Name = sub; 2307 else 2308 op_info->SubtractSymbol.Value = pair_r_value; 2309 op_info->Value = offset; 2310 return 1; 2311 } 2312 return 0; 2313 } 2314 if (Arch == Triple::x86_64) { 2315 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2316 return 0; 2317 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2318 // relocation entries of a linked image (if any) for an entry that matches 2319 // this segment offset. 2320 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2321 uint64_t seg_offset = Pc + Offset; 2322 bool reloc_found = false; 2323 DataRefImpl Rel; 2324 MachO::any_relocation_info RE; 2325 bool isExtern = false; 2326 SymbolRef Symbol; 2327 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2328 uint64_t RelocOffset = Reloc.getOffset(); 2329 if (RelocOffset == seg_offset) { 2330 Rel = Reloc.getRawDataRefImpl(); 2331 RE = info->O->getRelocation(Rel); 2332 // external relocation entries should always be external. 2333 isExtern = info->O->getPlainRelocationExternal(RE); 2334 if (isExtern) { 2335 symbol_iterator RelocSym = Reloc.getSymbol(); 2336 Symbol = *RelocSym; 2337 } 2338 reloc_found = true; 2339 break; 2340 } 2341 } 2342 if (reloc_found && isExtern) { 2343 // The Value passed in will be adjusted by the Pc if the instruction 2344 // adds the Pc. But for x86_64 external relocation entries the Value 2345 // is the offset from the external symbol. 2346 if (info->O->getAnyRelocationPCRel(RE)) 2347 op_info->Value -= Pc + Offset + Size; 2348 Expected<StringRef> SymName = Symbol.getName(); 2349 if (!SymName) 2350 report_error(info->O->getFileName(), SymName.takeError()); 2351 const char *name = SymName->data(); 2352 op_info->AddSymbol.Present = 1; 2353 op_info->AddSymbol.Name = name; 2354 return 1; 2355 } 2356 return 0; 2357 } 2358 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2359 // for an entry for this section offset. 2360 uint64_t sect_addr = info->S.getAddress(); 2361 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2362 bool reloc_found = false; 2363 DataRefImpl Rel; 2364 MachO::any_relocation_info RE; 2365 bool isExtern = false; 2366 SymbolRef Symbol; 2367 for (const RelocationRef &Reloc : info->S.relocations()) { 2368 uint64_t RelocOffset = Reloc.getOffset(); 2369 if (RelocOffset == sect_offset) { 2370 Rel = Reloc.getRawDataRefImpl(); 2371 RE = info->O->getRelocation(Rel); 2372 // NOTE: Scattered relocations don't exist on x86_64. 2373 isExtern = info->O->getPlainRelocationExternal(RE); 2374 if (isExtern) { 2375 symbol_iterator RelocSym = Reloc.getSymbol(); 2376 Symbol = *RelocSym; 2377 } 2378 reloc_found = true; 2379 break; 2380 } 2381 } 2382 if (reloc_found && isExtern) { 2383 // The Value passed in will be adjusted by the Pc if the instruction 2384 // adds the Pc. But for x86_64 external relocation entries the Value 2385 // is the offset from the external symbol. 2386 if (info->O->getAnyRelocationPCRel(RE)) 2387 op_info->Value -= Pc + Offset + Size; 2388 Expected<StringRef> SymName = Symbol.getName(); 2389 if (!SymName) 2390 report_error(info->O->getFileName(), SymName.takeError()); 2391 const char *name = SymName->data(); 2392 unsigned Type = info->O->getAnyRelocationType(RE); 2393 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2394 DataRefImpl RelNext = Rel; 2395 info->O->moveRelocationNext(RelNext); 2396 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2397 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2398 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2399 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2400 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2401 op_info->SubtractSymbol.Present = 1; 2402 op_info->SubtractSymbol.Name = name; 2403 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2404 Symbol = *RelocSymNext; 2405 Expected<StringRef> SymNameNext = Symbol.getName(); 2406 if (!SymNameNext) 2407 report_error(info->O->getFileName(), SymNameNext.takeError()); 2408 name = SymNameNext->data(); 2409 } 2410 } 2411 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 2412 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 2413 op_info->AddSymbol.Present = 1; 2414 op_info->AddSymbol.Name = name; 2415 return 1; 2416 } 2417 return 0; 2418 } 2419 if (Arch == Triple::arm) { 2420 if (Offset != 0 || (Size != 4 && Size != 2)) 2421 return 0; 2422 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2423 // TODO: 2424 // Search the external relocation entries of a fully linked image 2425 // (if any) for an entry that matches this segment offset. 2426 // uint32_t seg_offset = (Pc + Offset); 2427 return 0; 2428 } 2429 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2430 // for an entry for this section offset. 2431 uint32_t sect_addr = info->S.getAddress(); 2432 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2433 DataRefImpl Rel; 2434 MachO::any_relocation_info RE; 2435 bool isExtern = false; 2436 SymbolRef Symbol; 2437 bool r_scattered = false; 2438 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 2439 auto Reloc = 2440 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2441 uint64_t RelocOffset = Reloc.getOffset(); 2442 return RelocOffset == sect_offset; 2443 }); 2444 2445 if (Reloc == info->S.relocations().end()) 2446 return 0; 2447 2448 Rel = Reloc->getRawDataRefImpl(); 2449 RE = info->O->getRelocation(Rel); 2450 r_length = info->O->getAnyRelocationLength(RE); 2451 r_scattered = info->O->isRelocationScattered(RE); 2452 if (r_scattered) { 2453 r_value = info->O->getScatteredRelocationValue(RE); 2454 r_type = info->O->getScatteredRelocationType(RE); 2455 } else { 2456 r_type = info->O->getAnyRelocationType(RE); 2457 isExtern = info->O->getPlainRelocationExternal(RE); 2458 if (isExtern) { 2459 symbol_iterator RelocSym = Reloc->getSymbol(); 2460 Symbol = *RelocSym; 2461 } 2462 } 2463 if (r_type == MachO::ARM_RELOC_HALF || 2464 r_type == MachO::ARM_RELOC_SECTDIFF || 2465 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 2466 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2467 DataRefImpl RelNext = Rel; 2468 info->O->moveRelocationNext(RelNext); 2469 MachO::any_relocation_info RENext; 2470 RENext = info->O->getRelocation(RelNext); 2471 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 2472 if (info->O->isRelocationScattered(RENext)) 2473 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2474 } 2475 2476 if (isExtern) { 2477 Expected<StringRef> SymName = Symbol.getName(); 2478 if (!SymName) 2479 report_error(info->O->getFileName(), SymName.takeError()); 2480 const char *name = SymName->data(); 2481 op_info->AddSymbol.Present = 1; 2482 op_info->AddSymbol.Name = name; 2483 switch (r_type) { 2484 case MachO::ARM_RELOC_HALF: 2485 if ((r_length & 0x1) == 1) { 2486 op_info->Value = value << 16 | other_half; 2487 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2488 } else { 2489 op_info->Value = other_half << 16 | value; 2490 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2491 } 2492 break; 2493 default: 2494 break; 2495 } 2496 return 1; 2497 } 2498 // If we have a branch that is not an external relocation entry then 2499 // return 0 so the code in tryAddingSymbolicOperand() can use the 2500 // SymbolLookUp call back with the branch target address to look up the 2501 // symbol and possibility add an annotation for a symbol stub. 2502 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 2503 r_type == MachO::ARM_THUMB_RELOC_BR22)) 2504 return 0; 2505 2506 uint32_t offset = 0; 2507 if (r_type == MachO::ARM_RELOC_HALF || 2508 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2509 if ((r_length & 0x1) == 1) 2510 value = value << 16 | other_half; 2511 else 2512 value = other_half << 16 | value; 2513 } 2514 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 2515 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 2516 offset = value - r_value; 2517 value = r_value; 2518 } 2519 2520 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2521 if ((r_length & 0x1) == 1) 2522 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2523 else 2524 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2525 const char *add = GuessSymbolName(r_value, info->AddrMap); 2526 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2527 int32_t offset = value - (r_value - pair_r_value); 2528 op_info->AddSymbol.Present = 1; 2529 if (add != nullptr) 2530 op_info->AddSymbol.Name = add; 2531 else 2532 op_info->AddSymbol.Value = r_value; 2533 op_info->SubtractSymbol.Present = 1; 2534 if (sub != nullptr) 2535 op_info->SubtractSymbol.Name = sub; 2536 else 2537 op_info->SubtractSymbol.Value = pair_r_value; 2538 op_info->Value = offset; 2539 return 1; 2540 } 2541 2542 op_info->AddSymbol.Present = 1; 2543 op_info->Value = offset; 2544 if (r_type == MachO::ARM_RELOC_HALF) { 2545 if ((r_length & 0x1) == 1) 2546 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2547 else 2548 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2549 } 2550 const char *add = GuessSymbolName(value, info->AddrMap); 2551 if (add != nullptr) { 2552 op_info->AddSymbol.Name = add; 2553 return 1; 2554 } 2555 op_info->AddSymbol.Value = value; 2556 return 1; 2557 } 2558 if (Arch == Triple::aarch64) { 2559 if (Offset != 0 || Size != 4) 2560 return 0; 2561 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2562 // TODO: 2563 // Search the external relocation entries of a fully linked image 2564 // (if any) for an entry that matches this segment offset. 2565 // uint64_t seg_offset = (Pc + Offset); 2566 return 0; 2567 } 2568 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2569 // for an entry for this section offset. 2570 uint64_t sect_addr = info->S.getAddress(); 2571 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2572 auto Reloc = 2573 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2574 uint64_t RelocOffset = Reloc.getOffset(); 2575 return RelocOffset == sect_offset; 2576 }); 2577 2578 if (Reloc == info->S.relocations().end()) 2579 return 0; 2580 2581 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2582 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 2583 uint32_t r_type = info->O->getAnyRelocationType(RE); 2584 if (r_type == MachO::ARM64_RELOC_ADDEND) { 2585 DataRefImpl RelNext = Rel; 2586 info->O->moveRelocationNext(RelNext); 2587 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2588 if (value == 0) { 2589 value = info->O->getPlainRelocationSymbolNum(RENext); 2590 op_info->Value = value; 2591 } 2592 } 2593 // NOTE: Scattered relocations don't exist on arm64. 2594 if (!info->O->getPlainRelocationExternal(RE)) 2595 return 0; 2596 Expected<StringRef> SymName = Reloc->getSymbol()->getName(); 2597 if (!SymName) 2598 report_error(info->O->getFileName(), SymName.takeError()); 2599 const char *name = SymName->data(); 2600 op_info->AddSymbol.Present = 1; 2601 op_info->AddSymbol.Name = name; 2602 2603 switch (r_type) { 2604 case MachO::ARM64_RELOC_PAGE21: 2605 /* @page */ 2606 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 2607 break; 2608 case MachO::ARM64_RELOC_PAGEOFF12: 2609 /* @pageoff */ 2610 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 2611 break; 2612 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 2613 /* @gotpage */ 2614 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 2615 break; 2616 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 2617 /* @gotpageoff */ 2618 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 2619 break; 2620 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 2621 /* @tvlppage is not implemented in llvm-mc */ 2622 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 2623 break; 2624 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 2625 /* @tvlppageoff is not implemented in llvm-mc */ 2626 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 2627 break; 2628 default: 2629 case MachO::ARM64_RELOC_BRANCH26: 2630 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 2631 break; 2632 } 2633 return 1; 2634 } 2635 return 0; 2636 } 2637 2638 // GuessCstringPointer is passed the address of what might be a pointer to a 2639 // literal string in a cstring section. If that address is in a cstring section 2640 // it returns a pointer to that string. Else it returns nullptr. 2641 static const char *GuessCstringPointer(uint64_t ReferenceValue, 2642 struct DisassembleInfo *info) { 2643 for (const auto &Load : info->O->load_commands()) { 2644 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2645 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2646 for (unsigned J = 0; J < Seg.nsects; ++J) { 2647 MachO::section_64 Sec = info->O->getSection64(Load, J); 2648 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2649 if (section_type == MachO::S_CSTRING_LITERALS && 2650 ReferenceValue >= Sec.addr && 2651 ReferenceValue < Sec.addr + Sec.size) { 2652 uint64_t sect_offset = ReferenceValue - Sec.addr; 2653 uint64_t object_offset = Sec.offset + sect_offset; 2654 StringRef MachOContents = info->O->getData(); 2655 uint64_t object_size = MachOContents.size(); 2656 const char *object_addr = (const char *)MachOContents.data(); 2657 if (object_offset < object_size) { 2658 const char *name = object_addr + object_offset; 2659 return name; 2660 } else { 2661 return nullptr; 2662 } 2663 } 2664 } 2665 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2666 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2667 for (unsigned J = 0; J < Seg.nsects; ++J) { 2668 MachO::section Sec = info->O->getSection(Load, J); 2669 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2670 if (section_type == MachO::S_CSTRING_LITERALS && 2671 ReferenceValue >= Sec.addr && 2672 ReferenceValue < Sec.addr + Sec.size) { 2673 uint64_t sect_offset = ReferenceValue - Sec.addr; 2674 uint64_t object_offset = Sec.offset + sect_offset; 2675 StringRef MachOContents = info->O->getData(); 2676 uint64_t object_size = MachOContents.size(); 2677 const char *object_addr = (const char *)MachOContents.data(); 2678 if (object_offset < object_size) { 2679 const char *name = object_addr + object_offset; 2680 return name; 2681 } else { 2682 return nullptr; 2683 } 2684 } 2685 } 2686 } 2687 } 2688 return nullptr; 2689 } 2690 2691 // GuessIndirectSymbol returns the name of the indirect symbol for the 2692 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 2693 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 2694 // symbol name being referenced by the stub or pointer. 2695 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 2696 struct DisassembleInfo *info) { 2697 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 2698 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 2699 for (const auto &Load : info->O->load_commands()) { 2700 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2701 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2702 for (unsigned J = 0; J < Seg.nsects; ++J) { 2703 MachO::section_64 Sec = info->O->getSection64(Load, J); 2704 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2705 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2706 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2707 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2708 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2709 section_type == MachO::S_SYMBOL_STUBS) && 2710 ReferenceValue >= Sec.addr && 2711 ReferenceValue < Sec.addr + Sec.size) { 2712 uint32_t stride; 2713 if (section_type == MachO::S_SYMBOL_STUBS) 2714 stride = Sec.reserved2; 2715 else 2716 stride = 8; 2717 if (stride == 0) 2718 return nullptr; 2719 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2720 if (index < Dysymtab.nindirectsyms) { 2721 uint32_t indirect_symbol = 2722 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2723 if (indirect_symbol < Symtab.nsyms) { 2724 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2725 SymbolRef Symbol = *Sym; 2726 Expected<StringRef> SymName = Symbol.getName(); 2727 if (!SymName) 2728 report_error(info->O->getFileName(), SymName.takeError()); 2729 const char *name = SymName->data(); 2730 return name; 2731 } 2732 } 2733 } 2734 } 2735 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2736 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2737 for (unsigned J = 0; J < Seg.nsects; ++J) { 2738 MachO::section Sec = info->O->getSection(Load, J); 2739 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2740 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2741 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2742 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2743 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2744 section_type == MachO::S_SYMBOL_STUBS) && 2745 ReferenceValue >= Sec.addr && 2746 ReferenceValue < Sec.addr + Sec.size) { 2747 uint32_t stride; 2748 if (section_type == MachO::S_SYMBOL_STUBS) 2749 stride = Sec.reserved2; 2750 else 2751 stride = 4; 2752 if (stride == 0) 2753 return nullptr; 2754 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2755 if (index < Dysymtab.nindirectsyms) { 2756 uint32_t indirect_symbol = 2757 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2758 if (indirect_symbol < Symtab.nsyms) { 2759 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2760 SymbolRef Symbol = *Sym; 2761 Expected<StringRef> SymName = Symbol.getName(); 2762 if (!SymName) 2763 report_error(info->O->getFileName(), SymName.takeError()); 2764 const char *name = SymName->data(); 2765 return name; 2766 } 2767 } 2768 } 2769 } 2770 } 2771 } 2772 return nullptr; 2773 } 2774 2775 // method_reference() is called passing it the ReferenceName that might be 2776 // a reference it to an Objective-C method call. If so then it allocates and 2777 // assembles a method call string with the values last seen and saved in 2778 // the DisassembleInfo's class_name and selector_name fields. This is saved 2779 // into the method field of the info and any previous string is free'ed. 2780 // Then the class_name field in the info is set to nullptr. The method call 2781 // string is set into ReferenceName and ReferenceType is set to 2782 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 2783 // then both ReferenceType and ReferenceName are left unchanged. 2784 static void method_reference(struct DisassembleInfo *info, 2785 uint64_t *ReferenceType, 2786 const char **ReferenceName) { 2787 unsigned int Arch = info->O->getArch(); 2788 if (*ReferenceName != nullptr) { 2789 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 2790 if (info->selector_name != nullptr) { 2791 if (info->class_name != nullptr) { 2792 info->method = llvm::make_unique<char[]>( 2793 5 + strlen(info->class_name) + strlen(info->selector_name)); 2794 char *method = info->method.get(); 2795 if (method != nullptr) { 2796 strcpy(method, "+["); 2797 strcat(method, info->class_name); 2798 strcat(method, " "); 2799 strcat(method, info->selector_name); 2800 strcat(method, "]"); 2801 *ReferenceName = method; 2802 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2803 } 2804 } else { 2805 info->method = 2806 llvm::make_unique<char[]>(9 + strlen(info->selector_name)); 2807 char *method = info->method.get(); 2808 if (method != nullptr) { 2809 if (Arch == Triple::x86_64) 2810 strcpy(method, "-[%rdi "); 2811 else if (Arch == Triple::aarch64) 2812 strcpy(method, "-[x0 "); 2813 else 2814 strcpy(method, "-[r? "); 2815 strcat(method, info->selector_name); 2816 strcat(method, "]"); 2817 *ReferenceName = method; 2818 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2819 } 2820 } 2821 info->class_name = nullptr; 2822 } 2823 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 2824 if (info->selector_name != nullptr) { 2825 info->method = 2826 llvm::make_unique<char[]>(17 + strlen(info->selector_name)); 2827 char *method = info->method.get(); 2828 if (method != nullptr) { 2829 if (Arch == Triple::x86_64) 2830 strcpy(method, "-[[%rdi super] "); 2831 else if (Arch == Triple::aarch64) 2832 strcpy(method, "-[[x0 super] "); 2833 else 2834 strcpy(method, "-[[r? super] "); 2835 strcat(method, info->selector_name); 2836 strcat(method, "]"); 2837 *ReferenceName = method; 2838 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2839 } 2840 info->class_name = nullptr; 2841 } 2842 } 2843 } 2844 } 2845 2846 // GuessPointerPointer() is passed the address of what might be a pointer to 2847 // a reference to an Objective-C class, selector, message ref or cfstring. 2848 // If so the value of the pointer is returned and one of the booleans are set 2849 // to true. If not zero is returned and all the booleans are set to false. 2850 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 2851 struct DisassembleInfo *info, 2852 bool &classref, bool &selref, bool &msgref, 2853 bool &cfstring) { 2854 classref = false; 2855 selref = false; 2856 msgref = false; 2857 cfstring = false; 2858 for (const auto &Load : info->O->load_commands()) { 2859 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2860 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2861 for (unsigned J = 0; J < Seg.nsects; ++J) { 2862 MachO::section_64 Sec = info->O->getSection64(Load, J); 2863 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 2864 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2865 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 2866 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 2867 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 2868 ReferenceValue >= Sec.addr && 2869 ReferenceValue < Sec.addr + Sec.size) { 2870 uint64_t sect_offset = ReferenceValue - Sec.addr; 2871 uint64_t object_offset = Sec.offset + sect_offset; 2872 StringRef MachOContents = info->O->getData(); 2873 uint64_t object_size = MachOContents.size(); 2874 const char *object_addr = (const char *)MachOContents.data(); 2875 if (object_offset < object_size) { 2876 uint64_t pointer_value; 2877 memcpy(&pointer_value, object_addr + object_offset, 2878 sizeof(uint64_t)); 2879 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2880 sys::swapByteOrder(pointer_value); 2881 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 2882 selref = true; 2883 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2884 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 2885 classref = true; 2886 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 2887 ReferenceValue + 8 < Sec.addr + Sec.size) { 2888 msgref = true; 2889 memcpy(&pointer_value, object_addr + object_offset + 8, 2890 sizeof(uint64_t)); 2891 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2892 sys::swapByteOrder(pointer_value); 2893 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 2894 cfstring = true; 2895 return pointer_value; 2896 } else { 2897 return 0; 2898 } 2899 } 2900 } 2901 } 2902 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 2903 } 2904 return 0; 2905 } 2906 2907 // get_pointer_64 returns a pointer to the bytes in the object file at the 2908 // Address from a section in the Mach-O file. And indirectly returns the 2909 // offset into the section, number of bytes left in the section past the offset 2910 // and which section is was being referenced. If the Address is not in a 2911 // section nullptr is returned. 2912 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 2913 uint32_t &left, SectionRef &S, 2914 DisassembleInfo *info, 2915 bool objc_only = false) { 2916 offset = 0; 2917 left = 0; 2918 S = SectionRef(); 2919 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 2920 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 2921 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 2922 if (SectSize == 0) 2923 continue; 2924 if (objc_only) { 2925 StringRef SectName; 2926 ((*(info->Sections))[SectIdx]).getName(SectName); 2927 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 2928 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 2929 if (SegName != "__OBJC" && SectName != "__cstring") 2930 continue; 2931 } 2932 if (Address >= SectAddress && Address < SectAddress + SectSize) { 2933 S = (*(info->Sections))[SectIdx]; 2934 offset = Address - SectAddress; 2935 left = SectSize - offset; 2936 StringRef SectContents; 2937 ((*(info->Sections))[SectIdx]).getContents(SectContents); 2938 return SectContents.data() + offset; 2939 } 2940 } 2941 return nullptr; 2942 } 2943 2944 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 2945 uint32_t &left, SectionRef &S, 2946 DisassembleInfo *info, 2947 bool objc_only = false) { 2948 return get_pointer_64(Address, offset, left, S, info, objc_only); 2949 } 2950 2951 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 2952 // the symbol indirectly through n_value. Based on the relocation information 2953 // for the specified section offset in the specified section reference. 2954 // If no relocation information is found and a non-zero ReferenceValue for the 2955 // symbol is passed, look up that address in the info's AddrMap. 2956 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 2957 DisassembleInfo *info, uint64_t &n_value, 2958 uint64_t ReferenceValue = 0) { 2959 n_value = 0; 2960 if (!info->verbose) 2961 return nullptr; 2962 2963 // See if there is an external relocation entry at the sect_offset. 2964 bool reloc_found = false; 2965 DataRefImpl Rel; 2966 MachO::any_relocation_info RE; 2967 bool isExtern = false; 2968 SymbolRef Symbol; 2969 for (const RelocationRef &Reloc : S.relocations()) { 2970 uint64_t RelocOffset = Reloc.getOffset(); 2971 if (RelocOffset == sect_offset) { 2972 Rel = Reloc.getRawDataRefImpl(); 2973 RE = info->O->getRelocation(Rel); 2974 if (info->O->isRelocationScattered(RE)) 2975 continue; 2976 isExtern = info->O->getPlainRelocationExternal(RE); 2977 if (isExtern) { 2978 symbol_iterator RelocSym = Reloc.getSymbol(); 2979 Symbol = *RelocSym; 2980 } 2981 reloc_found = true; 2982 break; 2983 } 2984 } 2985 // If there is an external relocation entry for a symbol in this section 2986 // at this section_offset then use that symbol's value for the n_value 2987 // and return its name. 2988 const char *SymbolName = nullptr; 2989 if (reloc_found && isExtern) { 2990 n_value = Symbol.getValue(); 2991 Expected<StringRef> NameOrError = Symbol.getName(); 2992 if (!NameOrError) 2993 report_error(info->O->getFileName(), NameOrError.takeError()); 2994 StringRef Name = *NameOrError; 2995 if (!Name.empty()) { 2996 SymbolName = Name.data(); 2997 return SymbolName; 2998 } 2999 } 3000 3001 // TODO: For fully linked images, look through the external relocation 3002 // entries off the dynamic symtab command. For these the r_offset is from the 3003 // start of the first writeable segment in the Mach-O file. So the offset 3004 // to this section from that segment is passed to this routine by the caller, 3005 // as the database_offset. Which is the difference of the section's starting 3006 // address and the first writable segment. 3007 // 3008 // NOTE: need add passing the database_offset to this routine. 3009 3010 // We did not find an external relocation entry so look up the ReferenceValue 3011 // as an address of a symbol and if found return that symbol's name. 3012 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 3013 3014 return SymbolName; 3015 } 3016 3017 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 3018 DisassembleInfo *info, 3019 uint32_t ReferenceValue) { 3020 uint64_t n_value64; 3021 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 3022 } 3023 3024 // These are structs in the Objective-C meta data and read to produce the 3025 // comments for disassembly. While these are part of the ABI they are no 3026 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 3027 // . 3028 3029 // The cfstring object in a 64-bit Mach-O file. 3030 struct cfstring64_t { 3031 uint64_t isa; // class64_t * (64-bit pointer) 3032 uint64_t flags; // flag bits 3033 uint64_t characters; // char * (64-bit pointer) 3034 uint64_t length; // number of non-NULL characters in above 3035 }; 3036 3037 // The class object in a 64-bit Mach-O file. 3038 struct class64_t { 3039 uint64_t isa; // class64_t * (64-bit pointer) 3040 uint64_t superclass; // class64_t * (64-bit pointer) 3041 uint64_t cache; // Cache (64-bit pointer) 3042 uint64_t vtable; // IMP * (64-bit pointer) 3043 uint64_t data; // class_ro64_t * (64-bit pointer) 3044 }; 3045 3046 struct class32_t { 3047 uint32_t isa; /* class32_t * (32-bit pointer) */ 3048 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3049 uint32_t cache; /* Cache (32-bit pointer) */ 3050 uint32_t vtable; /* IMP * (32-bit pointer) */ 3051 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3052 }; 3053 3054 struct class_ro64_t { 3055 uint32_t flags; 3056 uint32_t instanceStart; 3057 uint32_t instanceSize; 3058 uint32_t reserved; 3059 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3060 uint64_t name; // const char * (64-bit pointer) 3061 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3062 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3063 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3064 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3065 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3066 }; 3067 3068 struct class_ro32_t { 3069 uint32_t flags; 3070 uint32_t instanceStart; 3071 uint32_t instanceSize; 3072 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3073 uint32_t name; /* const char * (32-bit pointer) */ 3074 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3075 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3076 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3077 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3078 uint32_t baseProperties; /* const struct objc_property_list * 3079 (32-bit pointer) */ 3080 }; 3081 3082 /* Values for class_ro{64,32}_t->flags */ 3083 #define RO_META (1 << 0) 3084 #define RO_ROOT (1 << 1) 3085 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3086 3087 struct method_list64_t { 3088 uint32_t entsize; 3089 uint32_t count; 3090 /* struct method64_t first; These structures follow inline */ 3091 }; 3092 3093 struct method_list32_t { 3094 uint32_t entsize; 3095 uint32_t count; 3096 /* struct method32_t first; These structures follow inline */ 3097 }; 3098 3099 struct method64_t { 3100 uint64_t name; /* SEL (64-bit pointer) */ 3101 uint64_t types; /* const char * (64-bit pointer) */ 3102 uint64_t imp; /* IMP (64-bit pointer) */ 3103 }; 3104 3105 struct method32_t { 3106 uint32_t name; /* SEL (32-bit pointer) */ 3107 uint32_t types; /* const char * (32-bit pointer) */ 3108 uint32_t imp; /* IMP (32-bit pointer) */ 3109 }; 3110 3111 struct protocol_list64_t { 3112 uint64_t count; /* uintptr_t (a 64-bit value) */ 3113 /* struct protocol64_t * list[0]; These pointers follow inline */ 3114 }; 3115 3116 struct protocol_list32_t { 3117 uint32_t count; /* uintptr_t (a 32-bit value) */ 3118 /* struct protocol32_t * list[0]; These pointers follow inline */ 3119 }; 3120 3121 struct protocol64_t { 3122 uint64_t isa; /* id * (64-bit pointer) */ 3123 uint64_t name; /* const char * (64-bit pointer) */ 3124 uint64_t protocols; /* struct protocol_list64_t * 3125 (64-bit pointer) */ 3126 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3127 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3128 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3129 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3130 uint64_t instanceProperties; /* struct objc_property_list * 3131 (64-bit pointer) */ 3132 }; 3133 3134 struct protocol32_t { 3135 uint32_t isa; /* id * (32-bit pointer) */ 3136 uint32_t name; /* const char * (32-bit pointer) */ 3137 uint32_t protocols; /* struct protocol_list_t * 3138 (32-bit pointer) */ 3139 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3140 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3141 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3142 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3143 uint32_t instanceProperties; /* struct objc_property_list * 3144 (32-bit pointer) */ 3145 }; 3146 3147 struct ivar_list64_t { 3148 uint32_t entsize; 3149 uint32_t count; 3150 /* struct ivar64_t first; These structures follow inline */ 3151 }; 3152 3153 struct ivar_list32_t { 3154 uint32_t entsize; 3155 uint32_t count; 3156 /* struct ivar32_t first; These structures follow inline */ 3157 }; 3158 3159 struct ivar64_t { 3160 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3161 uint64_t name; /* const char * (64-bit pointer) */ 3162 uint64_t type; /* const char * (64-bit pointer) */ 3163 uint32_t alignment; 3164 uint32_t size; 3165 }; 3166 3167 struct ivar32_t { 3168 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3169 uint32_t name; /* const char * (32-bit pointer) */ 3170 uint32_t type; /* const char * (32-bit pointer) */ 3171 uint32_t alignment; 3172 uint32_t size; 3173 }; 3174 3175 struct objc_property_list64 { 3176 uint32_t entsize; 3177 uint32_t count; 3178 /* struct objc_property64 first; These structures follow inline */ 3179 }; 3180 3181 struct objc_property_list32 { 3182 uint32_t entsize; 3183 uint32_t count; 3184 /* struct objc_property32 first; These structures follow inline */ 3185 }; 3186 3187 struct objc_property64 { 3188 uint64_t name; /* const char * (64-bit pointer) */ 3189 uint64_t attributes; /* const char * (64-bit pointer) */ 3190 }; 3191 3192 struct objc_property32 { 3193 uint32_t name; /* const char * (32-bit pointer) */ 3194 uint32_t attributes; /* const char * (32-bit pointer) */ 3195 }; 3196 3197 struct category64_t { 3198 uint64_t name; /* const char * (64-bit pointer) */ 3199 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3200 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3201 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3202 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3203 uint64_t instanceProperties; /* struct objc_property_list * 3204 (64-bit pointer) */ 3205 }; 3206 3207 struct category32_t { 3208 uint32_t name; /* const char * (32-bit pointer) */ 3209 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3210 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3211 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3212 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3213 uint32_t instanceProperties; /* struct objc_property_list * 3214 (32-bit pointer) */ 3215 }; 3216 3217 struct objc_image_info64 { 3218 uint32_t version; 3219 uint32_t flags; 3220 }; 3221 struct objc_image_info32 { 3222 uint32_t version; 3223 uint32_t flags; 3224 }; 3225 struct imageInfo_t { 3226 uint32_t version; 3227 uint32_t flags; 3228 }; 3229 /* masks for objc_image_info.flags */ 3230 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3231 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3232 #define OBJC_IMAGE_IS_SIMULATED (1 << 5) 3233 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6) 3234 3235 struct message_ref64 { 3236 uint64_t imp; /* IMP (64-bit pointer) */ 3237 uint64_t sel; /* SEL (64-bit pointer) */ 3238 }; 3239 3240 struct message_ref32 { 3241 uint32_t imp; /* IMP (32-bit pointer) */ 3242 uint32_t sel; /* SEL (32-bit pointer) */ 3243 }; 3244 3245 // Objective-C 1 (32-bit only) meta data structs. 3246 3247 struct objc_module_t { 3248 uint32_t version; 3249 uint32_t size; 3250 uint32_t name; /* char * (32-bit pointer) */ 3251 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3252 }; 3253 3254 struct objc_symtab_t { 3255 uint32_t sel_ref_cnt; 3256 uint32_t refs; /* SEL * (32-bit pointer) */ 3257 uint16_t cls_def_cnt; 3258 uint16_t cat_def_cnt; 3259 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3260 }; 3261 3262 struct objc_class_t { 3263 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3264 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3265 uint32_t name; /* const char * (32-bit pointer) */ 3266 int32_t version; 3267 int32_t info; 3268 int32_t instance_size; 3269 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3270 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3271 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3272 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3273 }; 3274 3275 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3276 // class is not a metaclass 3277 #define CLS_CLASS 0x1 3278 // class is a metaclass 3279 #define CLS_META 0x2 3280 3281 struct objc_category_t { 3282 uint32_t category_name; /* char * (32-bit pointer) */ 3283 uint32_t class_name; /* char * (32-bit pointer) */ 3284 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3285 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3286 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3287 }; 3288 3289 struct objc_ivar_t { 3290 uint32_t ivar_name; /* char * (32-bit pointer) */ 3291 uint32_t ivar_type; /* char * (32-bit pointer) */ 3292 int32_t ivar_offset; 3293 }; 3294 3295 struct objc_ivar_list_t { 3296 int32_t ivar_count; 3297 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3298 }; 3299 3300 struct objc_method_list_t { 3301 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3302 int32_t method_count; 3303 // struct objc_method_t method_list[1]; /* variable length structure */ 3304 }; 3305 3306 struct objc_method_t { 3307 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3308 uint32_t method_types; /* char * (32-bit pointer) */ 3309 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3310 (32-bit pointer) */ 3311 }; 3312 3313 struct objc_protocol_list_t { 3314 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3315 int32_t count; 3316 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3317 // (32-bit pointer) */ 3318 }; 3319 3320 struct objc_protocol_t { 3321 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3322 uint32_t protocol_name; /* char * (32-bit pointer) */ 3323 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3324 uint32_t instance_methods; /* struct objc_method_description_list * 3325 (32-bit pointer) */ 3326 uint32_t class_methods; /* struct objc_method_description_list * 3327 (32-bit pointer) */ 3328 }; 3329 3330 struct objc_method_description_list_t { 3331 int32_t count; 3332 // struct objc_method_description_t list[1]; 3333 }; 3334 3335 struct objc_method_description_t { 3336 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3337 uint32_t types; /* char * (32-bit pointer) */ 3338 }; 3339 3340 inline void swapStruct(struct cfstring64_t &cfs) { 3341 sys::swapByteOrder(cfs.isa); 3342 sys::swapByteOrder(cfs.flags); 3343 sys::swapByteOrder(cfs.characters); 3344 sys::swapByteOrder(cfs.length); 3345 } 3346 3347 inline void swapStruct(struct class64_t &c) { 3348 sys::swapByteOrder(c.isa); 3349 sys::swapByteOrder(c.superclass); 3350 sys::swapByteOrder(c.cache); 3351 sys::swapByteOrder(c.vtable); 3352 sys::swapByteOrder(c.data); 3353 } 3354 3355 inline void swapStruct(struct class32_t &c) { 3356 sys::swapByteOrder(c.isa); 3357 sys::swapByteOrder(c.superclass); 3358 sys::swapByteOrder(c.cache); 3359 sys::swapByteOrder(c.vtable); 3360 sys::swapByteOrder(c.data); 3361 } 3362 3363 inline void swapStruct(struct class_ro64_t &cro) { 3364 sys::swapByteOrder(cro.flags); 3365 sys::swapByteOrder(cro.instanceStart); 3366 sys::swapByteOrder(cro.instanceSize); 3367 sys::swapByteOrder(cro.reserved); 3368 sys::swapByteOrder(cro.ivarLayout); 3369 sys::swapByteOrder(cro.name); 3370 sys::swapByteOrder(cro.baseMethods); 3371 sys::swapByteOrder(cro.baseProtocols); 3372 sys::swapByteOrder(cro.ivars); 3373 sys::swapByteOrder(cro.weakIvarLayout); 3374 sys::swapByteOrder(cro.baseProperties); 3375 } 3376 3377 inline void swapStruct(struct class_ro32_t &cro) { 3378 sys::swapByteOrder(cro.flags); 3379 sys::swapByteOrder(cro.instanceStart); 3380 sys::swapByteOrder(cro.instanceSize); 3381 sys::swapByteOrder(cro.ivarLayout); 3382 sys::swapByteOrder(cro.name); 3383 sys::swapByteOrder(cro.baseMethods); 3384 sys::swapByteOrder(cro.baseProtocols); 3385 sys::swapByteOrder(cro.ivars); 3386 sys::swapByteOrder(cro.weakIvarLayout); 3387 sys::swapByteOrder(cro.baseProperties); 3388 } 3389 3390 inline void swapStruct(struct method_list64_t &ml) { 3391 sys::swapByteOrder(ml.entsize); 3392 sys::swapByteOrder(ml.count); 3393 } 3394 3395 inline void swapStruct(struct method_list32_t &ml) { 3396 sys::swapByteOrder(ml.entsize); 3397 sys::swapByteOrder(ml.count); 3398 } 3399 3400 inline void swapStruct(struct method64_t &m) { 3401 sys::swapByteOrder(m.name); 3402 sys::swapByteOrder(m.types); 3403 sys::swapByteOrder(m.imp); 3404 } 3405 3406 inline void swapStruct(struct method32_t &m) { 3407 sys::swapByteOrder(m.name); 3408 sys::swapByteOrder(m.types); 3409 sys::swapByteOrder(m.imp); 3410 } 3411 3412 inline void swapStruct(struct protocol_list64_t &pl) { 3413 sys::swapByteOrder(pl.count); 3414 } 3415 3416 inline void swapStruct(struct protocol_list32_t &pl) { 3417 sys::swapByteOrder(pl.count); 3418 } 3419 3420 inline void swapStruct(struct protocol64_t &p) { 3421 sys::swapByteOrder(p.isa); 3422 sys::swapByteOrder(p.name); 3423 sys::swapByteOrder(p.protocols); 3424 sys::swapByteOrder(p.instanceMethods); 3425 sys::swapByteOrder(p.classMethods); 3426 sys::swapByteOrder(p.optionalInstanceMethods); 3427 sys::swapByteOrder(p.optionalClassMethods); 3428 sys::swapByteOrder(p.instanceProperties); 3429 } 3430 3431 inline void swapStruct(struct protocol32_t &p) { 3432 sys::swapByteOrder(p.isa); 3433 sys::swapByteOrder(p.name); 3434 sys::swapByteOrder(p.protocols); 3435 sys::swapByteOrder(p.instanceMethods); 3436 sys::swapByteOrder(p.classMethods); 3437 sys::swapByteOrder(p.optionalInstanceMethods); 3438 sys::swapByteOrder(p.optionalClassMethods); 3439 sys::swapByteOrder(p.instanceProperties); 3440 } 3441 3442 inline void swapStruct(struct ivar_list64_t &il) { 3443 sys::swapByteOrder(il.entsize); 3444 sys::swapByteOrder(il.count); 3445 } 3446 3447 inline void swapStruct(struct ivar_list32_t &il) { 3448 sys::swapByteOrder(il.entsize); 3449 sys::swapByteOrder(il.count); 3450 } 3451 3452 inline void swapStruct(struct ivar64_t &i) { 3453 sys::swapByteOrder(i.offset); 3454 sys::swapByteOrder(i.name); 3455 sys::swapByteOrder(i.type); 3456 sys::swapByteOrder(i.alignment); 3457 sys::swapByteOrder(i.size); 3458 } 3459 3460 inline void swapStruct(struct ivar32_t &i) { 3461 sys::swapByteOrder(i.offset); 3462 sys::swapByteOrder(i.name); 3463 sys::swapByteOrder(i.type); 3464 sys::swapByteOrder(i.alignment); 3465 sys::swapByteOrder(i.size); 3466 } 3467 3468 inline void swapStruct(struct objc_property_list64 &pl) { 3469 sys::swapByteOrder(pl.entsize); 3470 sys::swapByteOrder(pl.count); 3471 } 3472 3473 inline void swapStruct(struct objc_property_list32 &pl) { 3474 sys::swapByteOrder(pl.entsize); 3475 sys::swapByteOrder(pl.count); 3476 } 3477 3478 inline void swapStruct(struct objc_property64 &op) { 3479 sys::swapByteOrder(op.name); 3480 sys::swapByteOrder(op.attributes); 3481 } 3482 3483 inline void swapStruct(struct objc_property32 &op) { 3484 sys::swapByteOrder(op.name); 3485 sys::swapByteOrder(op.attributes); 3486 } 3487 3488 inline void swapStruct(struct category64_t &c) { 3489 sys::swapByteOrder(c.name); 3490 sys::swapByteOrder(c.cls); 3491 sys::swapByteOrder(c.instanceMethods); 3492 sys::swapByteOrder(c.classMethods); 3493 sys::swapByteOrder(c.protocols); 3494 sys::swapByteOrder(c.instanceProperties); 3495 } 3496 3497 inline void swapStruct(struct category32_t &c) { 3498 sys::swapByteOrder(c.name); 3499 sys::swapByteOrder(c.cls); 3500 sys::swapByteOrder(c.instanceMethods); 3501 sys::swapByteOrder(c.classMethods); 3502 sys::swapByteOrder(c.protocols); 3503 sys::swapByteOrder(c.instanceProperties); 3504 } 3505 3506 inline void swapStruct(struct objc_image_info64 &o) { 3507 sys::swapByteOrder(o.version); 3508 sys::swapByteOrder(o.flags); 3509 } 3510 3511 inline void swapStruct(struct objc_image_info32 &o) { 3512 sys::swapByteOrder(o.version); 3513 sys::swapByteOrder(o.flags); 3514 } 3515 3516 inline void swapStruct(struct imageInfo_t &o) { 3517 sys::swapByteOrder(o.version); 3518 sys::swapByteOrder(o.flags); 3519 } 3520 3521 inline void swapStruct(struct message_ref64 &mr) { 3522 sys::swapByteOrder(mr.imp); 3523 sys::swapByteOrder(mr.sel); 3524 } 3525 3526 inline void swapStruct(struct message_ref32 &mr) { 3527 sys::swapByteOrder(mr.imp); 3528 sys::swapByteOrder(mr.sel); 3529 } 3530 3531 inline void swapStruct(struct objc_module_t &module) { 3532 sys::swapByteOrder(module.version); 3533 sys::swapByteOrder(module.size); 3534 sys::swapByteOrder(module.name); 3535 sys::swapByteOrder(module.symtab); 3536 } 3537 3538 inline void swapStruct(struct objc_symtab_t &symtab) { 3539 sys::swapByteOrder(symtab.sel_ref_cnt); 3540 sys::swapByteOrder(symtab.refs); 3541 sys::swapByteOrder(symtab.cls_def_cnt); 3542 sys::swapByteOrder(symtab.cat_def_cnt); 3543 } 3544 3545 inline void swapStruct(struct objc_class_t &objc_class) { 3546 sys::swapByteOrder(objc_class.isa); 3547 sys::swapByteOrder(objc_class.super_class); 3548 sys::swapByteOrder(objc_class.name); 3549 sys::swapByteOrder(objc_class.version); 3550 sys::swapByteOrder(objc_class.info); 3551 sys::swapByteOrder(objc_class.instance_size); 3552 sys::swapByteOrder(objc_class.ivars); 3553 sys::swapByteOrder(objc_class.methodLists); 3554 sys::swapByteOrder(objc_class.cache); 3555 sys::swapByteOrder(objc_class.protocols); 3556 } 3557 3558 inline void swapStruct(struct objc_category_t &objc_category) { 3559 sys::swapByteOrder(objc_category.category_name); 3560 sys::swapByteOrder(objc_category.class_name); 3561 sys::swapByteOrder(objc_category.instance_methods); 3562 sys::swapByteOrder(objc_category.class_methods); 3563 sys::swapByteOrder(objc_category.protocols); 3564 } 3565 3566 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 3567 sys::swapByteOrder(objc_ivar_list.ivar_count); 3568 } 3569 3570 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 3571 sys::swapByteOrder(objc_ivar.ivar_name); 3572 sys::swapByteOrder(objc_ivar.ivar_type); 3573 sys::swapByteOrder(objc_ivar.ivar_offset); 3574 } 3575 3576 inline void swapStruct(struct objc_method_list_t &method_list) { 3577 sys::swapByteOrder(method_list.obsolete); 3578 sys::swapByteOrder(method_list.method_count); 3579 } 3580 3581 inline void swapStruct(struct objc_method_t &method) { 3582 sys::swapByteOrder(method.method_name); 3583 sys::swapByteOrder(method.method_types); 3584 sys::swapByteOrder(method.method_imp); 3585 } 3586 3587 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 3588 sys::swapByteOrder(protocol_list.next); 3589 sys::swapByteOrder(protocol_list.count); 3590 } 3591 3592 inline void swapStruct(struct objc_protocol_t &protocol) { 3593 sys::swapByteOrder(protocol.isa); 3594 sys::swapByteOrder(protocol.protocol_name); 3595 sys::swapByteOrder(protocol.protocol_list); 3596 sys::swapByteOrder(protocol.instance_methods); 3597 sys::swapByteOrder(protocol.class_methods); 3598 } 3599 3600 inline void swapStruct(struct objc_method_description_list_t &mdl) { 3601 sys::swapByteOrder(mdl.count); 3602 } 3603 3604 inline void swapStruct(struct objc_method_description_t &md) { 3605 sys::swapByteOrder(md.name); 3606 sys::swapByteOrder(md.types); 3607 } 3608 3609 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 3610 struct DisassembleInfo *info); 3611 3612 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 3613 // to an Objective-C class and returns the class name. It is also passed the 3614 // address of the pointer, so when the pointer is zero as it can be in an .o 3615 // file, that is used to look for an external relocation entry with a symbol 3616 // name. 3617 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 3618 uint64_t ReferenceValue, 3619 struct DisassembleInfo *info) { 3620 const char *r; 3621 uint32_t offset, left; 3622 SectionRef S; 3623 3624 // The pointer_value can be 0 in an object file and have a relocation 3625 // entry for the class symbol at the ReferenceValue (the address of the 3626 // pointer). 3627 if (pointer_value == 0) { 3628 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3629 if (r == nullptr || left < sizeof(uint64_t)) 3630 return nullptr; 3631 uint64_t n_value; 3632 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3633 if (symbol_name == nullptr) 3634 return nullptr; 3635 const char *class_name = strrchr(symbol_name, '$'); 3636 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 3637 return class_name + 2; 3638 else 3639 return nullptr; 3640 } 3641 3642 // The case were the pointer_value is non-zero and points to a class defined 3643 // in this Mach-O file. 3644 r = get_pointer_64(pointer_value, offset, left, S, info); 3645 if (r == nullptr || left < sizeof(struct class64_t)) 3646 return nullptr; 3647 struct class64_t c; 3648 memcpy(&c, r, sizeof(struct class64_t)); 3649 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3650 swapStruct(c); 3651 if (c.data == 0) 3652 return nullptr; 3653 r = get_pointer_64(c.data, offset, left, S, info); 3654 if (r == nullptr || left < sizeof(struct class_ro64_t)) 3655 return nullptr; 3656 struct class_ro64_t cro; 3657 memcpy(&cro, r, sizeof(struct class_ro64_t)); 3658 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3659 swapStruct(cro); 3660 if (cro.name == 0) 3661 return nullptr; 3662 const char *name = get_pointer_64(cro.name, offset, left, S, info); 3663 return name; 3664 } 3665 3666 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 3667 // pointer to a cfstring and returns its name or nullptr. 3668 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 3669 struct DisassembleInfo *info) { 3670 const char *r, *name; 3671 uint32_t offset, left; 3672 SectionRef S; 3673 struct cfstring64_t cfs; 3674 uint64_t cfs_characters; 3675 3676 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3677 if (r == nullptr || left < sizeof(struct cfstring64_t)) 3678 return nullptr; 3679 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 3680 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3681 swapStruct(cfs); 3682 if (cfs.characters == 0) { 3683 uint64_t n_value; 3684 const char *symbol_name = get_symbol_64( 3685 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 3686 if (symbol_name == nullptr) 3687 return nullptr; 3688 cfs_characters = n_value; 3689 } else 3690 cfs_characters = cfs.characters; 3691 name = get_pointer_64(cfs_characters, offset, left, S, info); 3692 3693 return name; 3694 } 3695 3696 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 3697 // of a pointer to an Objective-C selector reference when the pointer value is 3698 // zero as in a .o file and is likely to have a external relocation entry with 3699 // who's symbol's n_value is the real pointer to the selector name. If that is 3700 // the case the real pointer to the selector name is returned else 0 is 3701 // returned 3702 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 3703 struct DisassembleInfo *info) { 3704 uint32_t offset, left; 3705 SectionRef S; 3706 3707 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 3708 if (r == nullptr || left < sizeof(uint64_t)) 3709 return 0; 3710 uint64_t n_value; 3711 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3712 if (symbol_name == nullptr) 3713 return 0; 3714 return n_value; 3715 } 3716 3717 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 3718 const char *sectname) { 3719 for (const SectionRef &Section : O->sections()) { 3720 StringRef SectName; 3721 Section.getName(SectName); 3722 DataRefImpl Ref = Section.getRawDataRefImpl(); 3723 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3724 if (SegName == segname && SectName == sectname) 3725 return Section; 3726 } 3727 return SectionRef(); 3728 } 3729 3730 static void 3731 walk_pointer_list_64(const char *listname, const SectionRef S, 3732 MachOObjectFile *O, struct DisassembleInfo *info, 3733 void (*func)(uint64_t, struct DisassembleInfo *info)) { 3734 if (S == SectionRef()) 3735 return; 3736 3737 StringRef SectName; 3738 S.getName(SectName); 3739 DataRefImpl Ref = S.getRawDataRefImpl(); 3740 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3741 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3742 3743 StringRef BytesStr; 3744 S.getContents(BytesStr); 3745 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3746 3747 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 3748 uint32_t left = S.getSize() - i; 3749 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 3750 uint64_t p = 0; 3751 memcpy(&p, Contents + i, size); 3752 if (i + sizeof(uint64_t) > S.getSize()) 3753 outs() << listname << " list pointer extends past end of (" << SegName 3754 << "," << SectName << ") section\n"; 3755 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 3756 3757 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3758 sys::swapByteOrder(p); 3759 3760 uint64_t n_value = 0; 3761 const char *name = get_symbol_64(i, S, info, n_value, p); 3762 if (name == nullptr) 3763 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 3764 3765 if (n_value != 0) { 3766 outs() << format("0x%" PRIx64, n_value); 3767 if (p != 0) 3768 outs() << " + " << format("0x%" PRIx64, p); 3769 } else 3770 outs() << format("0x%" PRIx64, p); 3771 if (name != nullptr) 3772 outs() << " " << name; 3773 outs() << "\n"; 3774 3775 p += n_value; 3776 if (func) 3777 func(p, info); 3778 } 3779 } 3780 3781 static void 3782 walk_pointer_list_32(const char *listname, const SectionRef S, 3783 MachOObjectFile *O, struct DisassembleInfo *info, 3784 void (*func)(uint32_t, struct DisassembleInfo *info)) { 3785 if (S == SectionRef()) 3786 return; 3787 3788 StringRef SectName; 3789 S.getName(SectName); 3790 DataRefImpl Ref = S.getRawDataRefImpl(); 3791 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3792 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3793 3794 StringRef BytesStr; 3795 S.getContents(BytesStr); 3796 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3797 3798 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 3799 uint32_t left = S.getSize() - i; 3800 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 3801 uint32_t p = 0; 3802 memcpy(&p, Contents + i, size); 3803 if (i + sizeof(uint32_t) > S.getSize()) 3804 outs() << listname << " list pointer extends past end of (" << SegName 3805 << "," << SectName << ") section\n"; 3806 uint32_t Address = S.getAddress() + i; 3807 outs() << format("%08" PRIx32, Address) << " "; 3808 3809 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3810 sys::swapByteOrder(p); 3811 outs() << format("0x%" PRIx32, p); 3812 3813 const char *name = get_symbol_32(i, S, info, p); 3814 if (name != nullptr) 3815 outs() << " " << name; 3816 outs() << "\n"; 3817 3818 if (func) 3819 func(p, info); 3820 } 3821 } 3822 3823 static void print_layout_map(const char *layout_map, uint32_t left) { 3824 if (layout_map == nullptr) 3825 return; 3826 outs() << " layout map: "; 3827 do { 3828 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 3829 left--; 3830 layout_map++; 3831 } while (*layout_map != '\0' && left != 0); 3832 outs() << "\n"; 3833 } 3834 3835 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 3836 uint32_t offset, left; 3837 SectionRef S; 3838 const char *layout_map; 3839 3840 if (p == 0) 3841 return; 3842 layout_map = get_pointer_64(p, offset, left, S, info); 3843 print_layout_map(layout_map, left); 3844 } 3845 3846 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 3847 uint32_t offset, left; 3848 SectionRef S; 3849 const char *layout_map; 3850 3851 if (p == 0) 3852 return; 3853 layout_map = get_pointer_32(p, offset, left, S, info); 3854 print_layout_map(layout_map, left); 3855 } 3856 3857 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 3858 const char *indent) { 3859 struct method_list64_t ml; 3860 struct method64_t m; 3861 const char *r; 3862 uint32_t offset, xoffset, left, i; 3863 SectionRef S, xS; 3864 const char *name, *sym_name; 3865 uint64_t n_value; 3866 3867 r = get_pointer_64(p, offset, left, S, info); 3868 if (r == nullptr) 3869 return; 3870 memset(&ml, '\0', sizeof(struct method_list64_t)); 3871 if (left < sizeof(struct method_list64_t)) { 3872 memcpy(&ml, r, left); 3873 outs() << " (method_list_t entends past the end of the section)\n"; 3874 } else 3875 memcpy(&ml, r, sizeof(struct method_list64_t)); 3876 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3877 swapStruct(ml); 3878 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3879 outs() << indent << "\t\t count " << ml.count << "\n"; 3880 3881 p += sizeof(struct method_list64_t); 3882 offset += sizeof(struct method_list64_t); 3883 for (i = 0; i < ml.count; i++) { 3884 r = get_pointer_64(p, offset, left, S, info); 3885 if (r == nullptr) 3886 return; 3887 memset(&m, '\0', sizeof(struct method64_t)); 3888 if (left < sizeof(struct method64_t)) { 3889 memcpy(&m, r, left); 3890 outs() << indent << " (method_t extends past the end of the section)\n"; 3891 } else 3892 memcpy(&m, r, sizeof(struct method64_t)); 3893 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3894 swapStruct(m); 3895 3896 outs() << indent << "\t\t name "; 3897 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 3898 info, n_value, m.name); 3899 if (n_value != 0) { 3900 if (info->verbose && sym_name != nullptr) 3901 outs() << sym_name; 3902 else 3903 outs() << format("0x%" PRIx64, n_value); 3904 if (m.name != 0) 3905 outs() << " + " << format("0x%" PRIx64, m.name); 3906 } else 3907 outs() << format("0x%" PRIx64, m.name); 3908 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 3909 if (name != nullptr) 3910 outs() << format(" %.*s", left, name); 3911 outs() << "\n"; 3912 3913 outs() << indent << "\t\t types "; 3914 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 3915 info, n_value, m.types); 3916 if (n_value != 0) { 3917 if (info->verbose && sym_name != nullptr) 3918 outs() << sym_name; 3919 else 3920 outs() << format("0x%" PRIx64, n_value); 3921 if (m.types != 0) 3922 outs() << " + " << format("0x%" PRIx64, m.types); 3923 } else 3924 outs() << format("0x%" PRIx64, m.types); 3925 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 3926 if (name != nullptr) 3927 outs() << format(" %.*s", left, name); 3928 outs() << "\n"; 3929 3930 outs() << indent << "\t\t imp "; 3931 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 3932 n_value, m.imp); 3933 if (info->verbose && name == nullptr) { 3934 if (n_value != 0) { 3935 outs() << format("0x%" PRIx64, n_value) << " "; 3936 if (m.imp != 0) 3937 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 3938 } else 3939 outs() << format("0x%" PRIx64, m.imp) << " "; 3940 } 3941 if (name != nullptr) 3942 outs() << name; 3943 outs() << "\n"; 3944 3945 p += sizeof(struct method64_t); 3946 offset += sizeof(struct method64_t); 3947 } 3948 } 3949 3950 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 3951 const char *indent) { 3952 struct method_list32_t ml; 3953 struct method32_t m; 3954 const char *r, *name; 3955 uint32_t offset, xoffset, left, i; 3956 SectionRef S, xS; 3957 3958 r = get_pointer_32(p, offset, left, S, info); 3959 if (r == nullptr) 3960 return; 3961 memset(&ml, '\0', sizeof(struct method_list32_t)); 3962 if (left < sizeof(struct method_list32_t)) { 3963 memcpy(&ml, r, left); 3964 outs() << " (method_list_t entends past the end of the section)\n"; 3965 } else 3966 memcpy(&ml, r, sizeof(struct method_list32_t)); 3967 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3968 swapStruct(ml); 3969 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3970 outs() << indent << "\t\t count " << ml.count << "\n"; 3971 3972 p += sizeof(struct method_list32_t); 3973 offset += sizeof(struct method_list32_t); 3974 for (i = 0; i < ml.count; i++) { 3975 r = get_pointer_32(p, offset, left, S, info); 3976 if (r == nullptr) 3977 return; 3978 memset(&m, '\0', sizeof(struct method32_t)); 3979 if (left < sizeof(struct method32_t)) { 3980 memcpy(&ml, r, left); 3981 outs() << indent << " (method_t entends past the end of the section)\n"; 3982 } else 3983 memcpy(&m, r, sizeof(struct method32_t)); 3984 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3985 swapStruct(m); 3986 3987 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 3988 name = get_pointer_32(m.name, xoffset, left, xS, info); 3989 if (name != nullptr) 3990 outs() << format(" %.*s", left, name); 3991 outs() << "\n"; 3992 3993 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 3994 name = get_pointer_32(m.types, xoffset, left, xS, info); 3995 if (name != nullptr) 3996 outs() << format(" %.*s", left, name); 3997 outs() << "\n"; 3998 3999 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4000 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 4001 m.imp); 4002 if (name != nullptr) 4003 outs() << " " << name; 4004 outs() << "\n"; 4005 4006 p += sizeof(struct method32_t); 4007 offset += sizeof(struct method32_t); 4008 } 4009 } 4010 4011 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 4012 uint32_t offset, left, xleft; 4013 SectionRef S; 4014 struct objc_method_list_t method_list; 4015 struct objc_method_t method; 4016 const char *r, *methods, *name, *SymbolName; 4017 int32_t i; 4018 4019 r = get_pointer_32(p, offset, left, S, info, true); 4020 if (r == nullptr) 4021 return true; 4022 4023 outs() << "\n"; 4024 if (left > sizeof(struct objc_method_list_t)) { 4025 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 4026 } else { 4027 outs() << "\t\t objc_method_list extends past end of the section\n"; 4028 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 4029 memcpy(&method_list, r, left); 4030 } 4031 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4032 swapStruct(method_list); 4033 4034 outs() << "\t\t obsolete " 4035 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4036 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4037 4038 methods = r + sizeof(struct objc_method_list_t); 4039 for (i = 0; i < method_list.method_count; i++) { 4040 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4041 outs() << "\t\t remaining method's extend past the of the section\n"; 4042 break; 4043 } 4044 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4045 sizeof(struct objc_method_t)); 4046 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4047 swapStruct(method); 4048 4049 outs() << "\t\t method_name " 4050 << format("0x%08" PRIx32, method.method_name); 4051 if (info->verbose) { 4052 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4053 if (name != nullptr) 4054 outs() << format(" %.*s", xleft, name); 4055 else 4056 outs() << " (not in an __OBJC section)"; 4057 } 4058 outs() << "\n"; 4059 4060 outs() << "\t\t method_types " 4061 << format("0x%08" PRIx32, method.method_types); 4062 if (info->verbose) { 4063 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4064 if (name != nullptr) 4065 outs() << format(" %.*s", xleft, name); 4066 else 4067 outs() << " (not in an __OBJC section)"; 4068 } 4069 outs() << "\n"; 4070 4071 outs() << "\t\t method_imp " 4072 << format("0x%08" PRIx32, method.method_imp) << " "; 4073 if (info->verbose) { 4074 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4075 if (SymbolName != nullptr) 4076 outs() << SymbolName; 4077 } 4078 outs() << "\n"; 4079 } 4080 return false; 4081 } 4082 4083 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4084 struct protocol_list64_t pl; 4085 uint64_t q, n_value; 4086 struct protocol64_t pc; 4087 const char *r; 4088 uint32_t offset, xoffset, left, i; 4089 SectionRef S, xS; 4090 const char *name, *sym_name; 4091 4092 r = get_pointer_64(p, offset, left, S, info); 4093 if (r == nullptr) 4094 return; 4095 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4096 if (left < sizeof(struct protocol_list64_t)) { 4097 memcpy(&pl, r, left); 4098 outs() << " (protocol_list_t entends past the end of the section)\n"; 4099 } else 4100 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4101 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4102 swapStruct(pl); 4103 outs() << " count " << pl.count << "\n"; 4104 4105 p += sizeof(struct protocol_list64_t); 4106 offset += sizeof(struct protocol_list64_t); 4107 for (i = 0; i < pl.count; i++) { 4108 r = get_pointer_64(p, offset, left, S, info); 4109 if (r == nullptr) 4110 return; 4111 q = 0; 4112 if (left < sizeof(uint64_t)) { 4113 memcpy(&q, r, left); 4114 outs() << " (protocol_t * entends past the end of the section)\n"; 4115 } else 4116 memcpy(&q, r, sizeof(uint64_t)); 4117 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4118 sys::swapByteOrder(q); 4119 4120 outs() << "\t\t list[" << i << "] "; 4121 sym_name = get_symbol_64(offset, S, info, n_value, q); 4122 if (n_value != 0) { 4123 if (info->verbose && sym_name != nullptr) 4124 outs() << sym_name; 4125 else 4126 outs() << format("0x%" PRIx64, n_value); 4127 if (q != 0) 4128 outs() << " + " << format("0x%" PRIx64, q); 4129 } else 4130 outs() << format("0x%" PRIx64, q); 4131 outs() << " (struct protocol_t *)\n"; 4132 4133 r = get_pointer_64(q + n_value, offset, left, S, info); 4134 if (r == nullptr) 4135 return; 4136 memset(&pc, '\0', sizeof(struct protocol64_t)); 4137 if (left < sizeof(struct protocol64_t)) { 4138 memcpy(&pc, r, left); 4139 outs() << " (protocol_t entends past the end of the section)\n"; 4140 } else 4141 memcpy(&pc, r, sizeof(struct protocol64_t)); 4142 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4143 swapStruct(pc); 4144 4145 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4146 4147 outs() << "\t\t\t name "; 4148 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4149 info, n_value, pc.name); 4150 if (n_value != 0) { 4151 if (info->verbose && sym_name != nullptr) 4152 outs() << sym_name; 4153 else 4154 outs() << format("0x%" PRIx64, n_value); 4155 if (pc.name != 0) 4156 outs() << " + " << format("0x%" PRIx64, pc.name); 4157 } else 4158 outs() << format("0x%" PRIx64, pc.name); 4159 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4160 if (name != nullptr) 4161 outs() << format(" %.*s", left, name); 4162 outs() << "\n"; 4163 4164 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4165 4166 outs() << "\t\t instanceMethods "; 4167 sym_name = 4168 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4169 S, info, n_value, pc.instanceMethods); 4170 if (n_value != 0) { 4171 if (info->verbose && sym_name != nullptr) 4172 outs() << sym_name; 4173 else 4174 outs() << format("0x%" PRIx64, n_value); 4175 if (pc.instanceMethods != 0) 4176 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4177 } else 4178 outs() << format("0x%" PRIx64, pc.instanceMethods); 4179 outs() << " (struct method_list_t *)\n"; 4180 if (pc.instanceMethods + n_value != 0) 4181 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4182 4183 outs() << "\t\t classMethods "; 4184 sym_name = 4185 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4186 info, n_value, pc.classMethods); 4187 if (n_value != 0) { 4188 if (info->verbose && sym_name != nullptr) 4189 outs() << sym_name; 4190 else 4191 outs() << format("0x%" PRIx64, n_value); 4192 if (pc.classMethods != 0) 4193 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4194 } else 4195 outs() << format("0x%" PRIx64, pc.classMethods); 4196 outs() << " (struct method_list_t *)\n"; 4197 if (pc.classMethods + n_value != 0) 4198 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4199 4200 outs() << "\t optionalInstanceMethods " 4201 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4202 outs() << "\t optionalClassMethods " 4203 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4204 outs() << "\t instanceProperties " 4205 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4206 4207 p += sizeof(uint64_t); 4208 offset += sizeof(uint64_t); 4209 } 4210 } 4211 4212 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4213 struct protocol_list32_t pl; 4214 uint32_t q; 4215 struct protocol32_t pc; 4216 const char *r; 4217 uint32_t offset, xoffset, left, i; 4218 SectionRef S, xS; 4219 const char *name; 4220 4221 r = get_pointer_32(p, offset, left, S, info); 4222 if (r == nullptr) 4223 return; 4224 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4225 if (left < sizeof(struct protocol_list32_t)) { 4226 memcpy(&pl, r, left); 4227 outs() << " (protocol_list_t entends past the end of the section)\n"; 4228 } else 4229 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4230 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4231 swapStruct(pl); 4232 outs() << " count " << pl.count << "\n"; 4233 4234 p += sizeof(struct protocol_list32_t); 4235 offset += sizeof(struct protocol_list32_t); 4236 for (i = 0; i < pl.count; i++) { 4237 r = get_pointer_32(p, offset, left, S, info); 4238 if (r == nullptr) 4239 return; 4240 q = 0; 4241 if (left < sizeof(uint32_t)) { 4242 memcpy(&q, r, left); 4243 outs() << " (protocol_t * entends past the end of the section)\n"; 4244 } else 4245 memcpy(&q, r, sizeof(uint32_t)); 4246 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4247 sys::swapByteOrder(q); 4248 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4249 << " (struct protocol_t *)\n"; 4250 r = get_pointer_32(q, offset, left, S, info); 4251 if (r == nullptr) 4252 return; 4253 memset(&pc, '\0', sizeof(struct protocol32_t)); 4254 if (left < sizeof(struct protocol32_t)) { 4255 memcpy(&pc, r, left); 4256 outs() << " (protocol_t entends past the end of the section)\n"; 4257 } else 4258 memcpy(&pc, r, sizeof(struct protocol32_t)); 4259 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4260 swapStruct(pc); 4261 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4262 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4263 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4264 if (name != nullptr) 4265 outs() << format(" %.*s", left, name); 4266 outs() << "\n"; 4267 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4268 outs() << "\t\t instanceMethods " 4269 << format("0x%" PRIx32, pc.instanceMethods) 4270 << " (struct method_list_t *)\n"; 4271 if (pc.instanceMethods != 0) 4272 print_method_list32_t(pc.instanceMethods, info, "\t"); 4273 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4274 << " (struct method_list_t *)\n"; 4275 if (pc.classMethods != 0) 4276 print_method_list32_t(pc.classMethods, info, "\t"); 4277 outs() << "\t optionalInstanceMethods " 4278 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4279 outs() << "\t optionalClassMethods " 4280 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4281 outs() << "\t instanceProperties " 4282 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4283 p += sizeof(uint32_t); 4284 offset += sizeof(uint32_t); 4285 } 4286 } 4287 4288 static void print_indent(uint32_t indent) { 4289 for (uint32_t i = 0; i < indent;) { 4290 if (indent - i >= 8) { 4291 outs() << "\t"; 4292 i += 8; 4293 } else { 4294 for (uint32_t j = i; j < indent; j++) 4295 outs() << " "; 4296 return; 4297 } 4298 } 4299 } 4300 4301 static bool print_method_description_list(uint32_t p, uint32_t indent, 4302 struct DisassembleInfo *info) { 4303 uint32_t offset, left, xleft; 4304 SectionRef S; 4305 struct objc_method_description_list_t mdl; 4306 struct objc_method_description_t md; 4307 const char *r, *list, *name; 4308 int32_t i; 4309 4310 r = get_pointer_32(p, offset, left, S, info, true); 4311 if (r == nullptr) 4312 return true; 4313 4314 outs() << "\n"; 4315 if (left > sizeof(struct objc_method_description_list_t)) { 4316 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 4317 } else { 4318 print_indent(indent); 4319 outs() << " objc_method_description_list extends past end of the section\n"; 4320 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 4321 memcpy(&mdl, r, left); 4322 } 4323 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4324 swapStruct(mdl); 4325 4326 print_indent(indent); 4327 outs() << " count " << mdl.count << "\n"; 4328 4329 list = r + sizeof(struct objc_method_description_list_t); 4330 for (i = 0; i < mdl.count; i++) { 4331 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 4332 print_indent(indent); 4333 outs() << " remaining list entries extend past the of the section\n"; 4334 break; 4335 } 4336 print_indent(indent); 4337 outs() << " list[" << i << "]\n"; 4338 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 4339 sizeof(struct objc_method_description_t)); 4340 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4341 swapStruct(md); 4342 4343 print_indent(indent); 4344 outs() << " name " << format("0x%08" PRIx32, md.name); 4345 if (info->verbose) { 4346 name = get_pointer_32(md.name, offset, xleft, S, info, true); 4347 if (name != nullptr) 4348 outs() << format(" %.*s", xleft, name); 4349 else 4350 outs() << " (not in an __OBJC section)"; 4351 } 4352 outs() << "\n"; 4353 4354 print_indent(indent); 4355 outs() << " types " << format("0x%08" PRIx32, md.types); 4356 if (info->verbose) { 4357 name = get_pointer_32(md.types, offset, xleft, S, info, true); 4358 if (name != nullptr) 4359 outs() << format(" %.*s", xleft, name); 4360 else 4361 outs() << " (not in an __OBJC section)"; 4362 } 4363 outs() << "\n"; 4364 } 4365 return false; 4366 } 4367 4368 static bool print_protocol_list(uint32_t p, uint32_t indent, 4369 struct DisassembleInfo *info); 4370 4371 static bool print_protocol(uint32_t p, uint32_t indent, 4372 struct DisassembleInfo *info) { 4373 uint32_t offset, left; 4374 SectionRef S; 4375 struct objc_protocol_t protocol; 4376 const char *r, *name; 4377 4378 r = get_pointer_32(p, offset, left, S, info, true); 4379 if (r == nullptr) 4380 return true; 4381 4382 outs() << "\n"; 4383 if (left >= sizeof(struct objc_protocol_t)) { 4384 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 4385 } else { 4386 print_indent(indent); 4387 outs() << " Protocol extends past end of the section\n"; 4388 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 4389 memcpy(&protocol, r, left); 4390 } 4391 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4392 swapStruct(protocol); 4393 4394 print_indent(indent); 4395 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 4396 << "\n"; 4397 4398 print_indent(indent); 4399 outs() << " protocol_name " 4400 << format("0x%08" PRIx32, protocol.protocol_name); 4401 if (info->verbose) { 4402 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 4403 if (name != nullptr) 4404 outs() << format(" %.*s", left, name); 4405 else 4406 outs() << " (not in an __OBJC section)"; 4407 } 4408 outs() << "\n"; 4409 4410 print_indent(indent); 4411 outs() << " protocol_list " 4412 << format("0x%08" PRIx32, protocol.protocol_list); 4413 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 4414 outs() << " (not in an __OBJC section)\n"; 4415 4416 print_indent(indent); 4417 outs() << " instance_methods " 4418 << format("0x%08" PRIx32, protocol.instance_methods); 4419 if (print_method_description_list(protocol.instance_methods, indent, info)) 4420 outs() << " (not in an __OBJC section)\n"; 4421 4422 print_indent(indent); 4423 outs() << " class_methods " 4424 << format("0x%08" PRIx32, protocol.class_methods); 4425 if (print_method_description_list(protocol.class_methods, indent, info)) 4426 outs() << " (not in an __OBJC section)\n"; 4427 4428 return false; 4429 } 4430 4431 static bool print_protocol_list(uint32_t p, uint32_t indent, 4432 struct DisassembleInfo *info) { 4433 uint32_t offset, left, l; 4434 SectionRef S; 4435 struct objc_protocol_list_t protocol_list; 4436 const char *r, *list; 4437 int32_t i; 4438 4439 r = get_pointer_32(p, offset, left, S, info, true); 4440 if (r == nullptr) 4441 return true; 4442 4443 outs() << "\n"; 4444 if (left > sizeof(struct objc_protocol_list_t)) { 4445 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 4446 } else { 4447 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 4448 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 4449 memcpy(&protocol_list, r, left); 4450 } 4451 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4452 swapStruct(protocol_list); 4453 4454 print_indent(indent); 4455 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 4456 << "\n"; 4457 print_indent(indent); 4458 outs() << " count " << protocol_list.count << "\n"; 4459 4460 list = r + sizeof(struct objc_protocol_list_t); 4461 for (i = 0; i < protocol_list.count; i++) { 4462 if ((i + 1) * sizeof(uint32_t) > left) { 4463 outs() << "\t\t remaining list entries extend past the of the section\n"; 4464 break; 4465 } 4466 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 4467 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4468 sys::swapByteOrder(l); 4469 4470 print_indent(indent); 4471 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 4472 if (print_protocol(l, indent, info)) 4473 outs() << "(not in an __OBJC section)\n"; 4474 } 4475 return false; 4476 } 4477 4478 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 4479 struct ivar_list64_t il; 4480 struct ivar64_t i; 4481 const char *r; 4482 uint32_t offset, xoffset, left, j; 4483 SectionRef S, xS; 4484 const char *name, *sym_name, *ivar_offset_p; 4485 uint64_t ivar_offset, n_value; 4486 4487 r = get_pointer_64(p, offset, left, S, info); 4488 if (r == nullptr) 4489 return; 4490 memset(&il, '\0', sizeof(struct ivar_list64_t)); 4491 if (left < sizeof(struct ivar_list64_t)) { 4492 memcpy(&il, r, left); 4493 outs() << " (ivar_list_t entends past the end of the section)\n"; 4494 } else 4495 memcpy(&il, r, sizeof(struct ivar_list64_t)); 4496 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4497 swapStruct(il); 4498 outs() << " entsize " << il.entsize << "\n"; 4499 outs() << " count " << il.count << "\n"; 4500 4501 p += sizeof(struct ivar_list64_t); 4502 offset += sizeof(struct ivar_list64_t); 4503 for (j = 0; j < il.count; j++) { 4504 r = get_pointer_64(p, offset, left, S, info); 4505 if (r == nullptr) 4506 return; 4507 memset(&i, '\0', sizeof(struct ivar64_t)); 4508 if (left < sizeof(struct ivar64_t)) { 4509 memcpy(&i, r, left); 4510 outs() << " (ivar_t entends past the end of the section)\n"; 4511 } else 4512 memcpy(&i, r, sizeof(struct ivar64_t)); 4513 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4514 swapStruct(i); 4515 4516 outs() << "\t\t\t offset "; 4517 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 4518 info, n_value, i.offset); 4519 if (n_value != 0) { 4520 if (info->verbose && sym_name != nullptr) 4521 outs() << sym_name; 4522 else 4523 outs() << format("0x%" PRIx64, n_value); 4524 if (i.offset != 0) 4525 outs() << " + " << format("0x%" PRIx64, i.offset); 4526 } else 4527 outs() << format("0x%" PRIx64, i.offset); 4528 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 4529 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4530 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4531 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4532 sys::swapByteOrder(ivar_offset); 4533 outs() << " " << ivar_offset << "\n"; 4534 } else 4535 outs() << "\n"; 4536 4537 outs() << "\t\t\t name "; 4538 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 4539 n_value, i.name); 4540 if (n_value != 0) { 4541 if (info->verbose && sym_name != nullptr) 4542 outs() << sym_name; 4543 else 4544 outs() << format("0x%" PRIx64, n_value); 4545 if (i.name != 0) 4546 outs() << " + " << format("0x%" PRIx64, i.name); 4547 } else 4548 outs() << format("0x%" PRIx64, i.name); 4549 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 4550 if (name != nullptr) 4551 outs() << format(" %.*s", left, name); 4552 outs() << "\n"; 4553 4554 outs() << "\t\t\t type "; 4555 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 4556 n_value, i.name); 4557 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 4558 if (n_value != 0) { 4559 if (info->verbose && sym_name != nullptr) 4560 outs() << sym_name; 4561 else 4562 outs() << format("0x%" PRIx64, n_value); 4563 if (i.type != 0) 4564 outs() << " + " << format("0x%" PRIx64, i.type); 4565 } else 4566 outs() << format("0x%" PRIx64, i.type); 4567 if (name != nullptr) 4568 outs() << format(" %.*s", left, name); 4569 outs() << "\n"; 4570 4571 outs() << "\t\t\talignment " << i.alignment << "\n"; 4572 outs() << "\t\t\t size " << i.size << "\n"; 4573 4574 p += sizeof(struct ivar64_t); 4575 offset += sizeof(struct ivar64_t); 4576 } 4577 } 4578 4579 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 4580 struct ivar_list32_t il; 4581 struct ivar32_t i; 4582 const char *r; 4583 uint32_t offset, xoffset, left, j; 4584 SectionRef S, xS; 4585 const char *name, *ivar_offset_p; 4586 uint32_t ivar_offset; 4587 4588 r = get_pointer_32(p, offset, left, S, info); 4589 if (r == nullptr) 4590 return; 4591 memset(&il, '\0', sizeof(struct ivar_list32_t)); 4592 if (left < sizeof(struct ivar_list32_t)) { 4593 memcpy(&il, r, left); 4594 outs() << " (ivar_list_t entends past the end of the section)\n"; 4595 } else 4596 memcpy(&il, r, sizeof(struct ivar_list32_t)); 4597 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4598 swapStruct(il); 4599 outs() << " entsize " << il.entsize << "\n"; 4600 outs() << " count " << il.count << "\n"; 4601 4602 p += sizeof(struct ivar_list32_t); 4603 offset += sizeof(struct ivar_list32_t); 4604 for (j = 0; j < il.count; j++) { 4605 r = get_pointer_32(p, offset, left, S, info); 4606 if (r == nullptr) 4607 return; 4608 memset(&i, '\0', sizeof(struct ivar32_t)); 4609 if (left < sizeof(struct ivar32_t)) { 4610 memcpy(&i, r, left); 4611 outs() << " (ivar_t entends past the end of the section)\n"; 4612 } else 4613 memcpy(&i, r, sizeof(struct ivar32_t)); 4614 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4615 swapStruct(i); 4616 4617 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 4618 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 4619 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4620 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4621 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4622 sys::swapByteOrder(ivar_offset); 4623 outs() << " " << ivar_offset << "\n"; 4624 } else 4625 outs() << "\n"; 4626 4627 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 4628 name = get_pointer_32(i.name, xoffset, left, xS, info); 4629 if (name != nullptr) 4630 outs() << format(" %.*s", left, name); 4631 outs() << "\n"; 4632 4633 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 4634 name = get_pointer_32(i.type, xoffset, left, xS, info); 4635 if (name != nullptr) 4636 outs() << format(" %.*s", left, name); 4637 outs() << "\n"; 4638 4639 outs() << "\t\t\talignment " << i.alignment << "\n"; 4640 outs() << "\t\t\t size " << i.size << "\n"; 4641 4642 p += sizeof(struct ivar32_t); 4643 offset += sizeof(struct ivar32_t); 4644 } 4645 } 4646 4647 static void print_objc_property_list64(uint64_t p, 4648 struct DisassembleInfo *info) { 4649 struct objc_property_list64 opl; 4650 struct objc_property64 op; 4651 const char *r; 4652 uint32_t offset, xoffset, left, j; 4653 SectionRef S, xS; 4654 const char *name, *sym_name; 4655 uint64_t n_value; 4656 4657 r = get_pointer_64(p, offset, left, S, info); 4658 if (r == nullptr) 4659 return; 4660 memset(&opl, '\0', sizeof(struct objc_property_list64)); 4661 if (left < sizeof(struct objc_property_list64)) { 4662 memcpy(&opl, r, left); 4663 outs() << " (objc_property_list entends past the end of the section)\n"; 4664 } else 4665 memcpy(&opl, r, sizeof(struct objc_property_list64)); 4666 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4667 swapStruct(opl); 4668 outs() << " entsize " << opl.entsize << "\n"; 4669 outs() << " count " << opl.count << "\n"; 4670 4671 p += sizeof(struct objc_property_list64); 4672 offset += sizeof(struct objc_property_list64); 4673 for (j = 0; j < opl.count; j++) { 4674 r = get_pointer_64(p, offset, left, S, info); 4675 if (r == nullptr) 4676 return; 4677 memset(&op, '\0', sizeof(struct objc_property64)); 4678 if (left < sizeof(struct objc_property64)) { 4679 memcpy(&op, r, left); 4680 outs() << " (objc_property entends past the end of the section)\n"; 4681 } else 4682 memcpy(&op, r, sizeof(struct objc_property64)); 4683 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4684 swapStruct(op); 4685 4686 outs() << "\t\t\t name "; 4687 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 4688 info, n_value, op.name); 4689 if (n_value != 0) { 4690 if (info->verbose && sym_name != nullptr) 4691 outs() << sym_name; 4692 else 4693 outs() << format("0x%" PRIx64, n_value); 4694 if (op.name != 0) 4695 outs() << " + " << format("0x%" PRIx64, op.name); 4696 } else 4697 outs() << format("0x%" PRIx64, op.name); 4698 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 4699 if (name != nullptr) 4700 outs() << format(" %.*s", left, name); 4701 outs() << "\n"; 4702 4703 outs() << "\t\t\tattributes "; 4704 sym_name = 4705 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 4706 info, n_value, op.attributes); 4707 if (n_value != 0) { 4708 if (info->verbose && sym_name != nullptr) 4709 outs() << sym_name; 4710 else 4711 outs() << format("0x%" PRIx64, n_value); 4712 if (op.attributes != 0) 4713 outs() << " + " << format("0x%" PRIx64, op.attributes); 4714 } else 4715 outs() << format("0x%" PRIx64, op.attributes); 4716 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 4717 if (name != nullptr) 4718 outs() << format(" %.*s", left, name); 4719 outs() << "\n"; 4720 4721 p += sizeof(struct objc_property64); 4722 offset += sizeof(struct objc_property64); 4723 } 4724 } 4725 4726 static void print_objc_property_list32(uint32_t p, 4727 struct DisassembleInfo *info) { 4728 struct objc_property_list32 opl; 4729 struct objc_property32 op; 4730 const char *r; 4731 uint32_t offset, xoffset, left, j; 4732 SectionRef S, xS; 4733 const char *name; 4734 4735 r = get_pointer_32(p, offset, left, S, info); 4736 if (r == nullptr) 4737 return; 4738 memset(&opl, '\0', sizeof(struct objc_property_list32)); 4739 if (left < sizeof(struct objc_property_list32)) { 4740 memcpy(&opl, r, left); 4741 outs() << " (objc_property_list entends past the end of the section)\n"; 4742 } else 4743 memcpy(&opl, r, sizeof(struct objc_property_list32)); 4744 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4745 swapStruct(opl); 4746 outs() << " entsize " << opl.entsize << "\n"; 4747 outs() << " count " << opl.count << "\n"; 4748 4749 p += sizeof(struct objc_property_list32); 4750 offset += sizeof(struct objc_property_list32); 4751 for (j = 0; j < opl.count; j++) { 4752 r = get_pointer_32(p, offset, left, S, info); 4753 if (r == nullptr) 4754 return; 4755 memset(&op, '\0', sizeof(struct objc_property32)); 4756 if (left < sizeof(struct objc_property32)) { 4757 memcpy(&op, r, left); 4758 outs() << " (objc_property entends past the end of the section)\n"; 4759 } else 4760 memcpy(&op, r, sizeof(struct objc_property32)); 4761 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4762 swapStruct(op); 4763 4764 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 4765 name = get_pointer_32(op.name, xoffset, left, xS, info); 4766 if (name != nullptr) 4767 outs() << format(" %.*s", left, name); 4768 outs() << "\n"; 4769 4770 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 4771 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 4772 if (name != nullptr) 4773 outs() << format(" %.*s", left, name); 4774 outs() << "\n"; 4775 4776 p += sizeof(struct objc_property32); 4777 offset += sizeof(struct objc_property32); 4778 } 4779 } 4780 4781 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 4782 bool &is_meta_class) { 4783 struct class_ro64_t cro; 4784 const char *r; 4785 uint32_t offset, xoffset, left; 4786 SectionRef S, xS; 4787 const char *name, *sym_name; 4788 uint64_t n_value; 4789 4790 r = get_pointer_64(p, offset, left, S, info); 4791 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4792 return false; 4793 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4794 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4795 swapStruct(cro); 4796 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4797 if (cro.flags & RO_META) 4798 outs() << " RO_META"; 4799 if (cro.flags & RO_ROOT) 4800 outs() << " RO_ROOT"; 4801 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4802 outs() << " RO_HAS_CXX_STRUCTORS"; 4803 outs() << "\n"; 4804 outs() << " instanceStart " << cro.instanceStart << "\n"; 4805 outs() << " instanceSize " << cro.instanceSize << "\n"; 4806 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 4807 << "\n"; 4808 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 4809 << "\n"; 4810 print_layout_map64(cro.ivarLayout, info); 4811 4812 outs() << " name "; 4813 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 4814 info, n_value, cro.name); 4815 if (n_value != 0) { 4816 if (info->verbose && sym_name != nullptr) 4817 outs() << sym_name; 4818 else 4819 outs() << format("0x%" PRIx64, n_value); 4820 if (cro.name != 0) 4821 outs() << " + " << format("0x%" PRIx64, cro.name); 4822 } else 4823 outs() << format("0x%" PRIx64, cro.name); 4824 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 4825 if (name != nullptr) 4826 outs() << format(" %.*s", left, name); 4827 outs() << "\n"; 4828 4829 outs() << " baseMethods "; 4830 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 4831 S, info, n_value, cro.baseMethods); 4832 if (n_value != 0) { 4833 if (info->verbose && sym_name != nullptr) 4834 outs() << sym_name; 4835 else 4836 outs() << format("0x%" PRIx64, n_value); 4837 if (cro.baseMethods != 0) 4838 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 4839 } else 4840 outs() << format("0x%" PRIx64, cro.baseMethods); 4841 outs() << " (struct method_list_t *)\n"; 4842 if (cro.baseMethods + n_value != 0) 4843 print_method_list64_t(cro.baseMethods + n_value, info, ""); 4844 4845 outs() << " baseProtocols "; 4846 sym_name = 4847 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 4848 info, n_value, cro.baseProtocols); 4849 if (n_value != 0) { 4850 if (info->verbose && sym_name != nullptr) 4851 outs() << sym_name; 4852 else 4853 outs() << format("0x%" PRIx64, n_value); 4854 if (cro.baseProtocols != 0) 4855 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 4856 } else 4857 outs() << format("0x%" PRIx64, cro.baseProtocols); 4858 outs() << "\n"; 4859 if (cro.baseProtocols + n_value != 0) 4860 print_protocol_list64_t(cro.baseProtocols + n_value, info); 4861 4862 outs() << " ivars "; 4863 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 4864 info, n_value, cro.ivars); 4865 if (n_value != 0) { 4866 if (info->verbose && sym_name != nullptr) 4867 outs() << sym_name; 4868 else 4869 outs() << format("0x%" PRIx64, n_value); 4870 if (cro.ivars != 0) 4871 outs() << " + " << format("0x%" PRIx64, cro.ivars); 4872 } else 4873 outs() << format("0x%" PRIx64, cro.ivars); 4874 outs() << "\n"; 4875 if (cro.ivars + n_value != 0) 4876 print_ivar_list64_t(cro.ivars + n_value, info); 4877 4878 outs() << " weakIvarLayout "; 4879 sym_name = 4880 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 4881 info, n_value, cro.weakIvarLayout); 4882 if (n_value != 0) { 4883 if (info->verbose && sym_name != nullptr) 4884 outs() << sym_name; 4885 else 4886 outs() << format("0x%" PRIx64, n_value); 4887 if (cro.weakIvarLayout != 0) 4888 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 4889 } else 4890 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 4891 outs() << "\n"; 4892 print_layout_map64(cro.weakIvarLayout + n_value, info); 4893 4894 outs() << " baseProperties "; 4895 sym_name = 4896 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 4897 info, n_value, cro.baseProperties); 4898 if (n_value != 0) { 4899 if (info->verbose && sym_name != nullptr) 4900 outs() << sym_name; 4901 else 4902 outs() << format("0x%" PRIx64, n_value); 4903 if (cro.baseProperties != 0) 4904 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 4905 } else 4906 outs() << format("0x%" PRIx64, cro.baseProperties); 4907 outs() << "\n"; 4908 if (cro.baseProperties + n_value != 0) 4909 print_objc_property_list64(cro.baseProperties + n_value, info); 4910 4911 is_meta_class = (cro.flags & RO_META) != 0; 4912 return true; 4913 } 4914 4915 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 4916 bool &is_meta_class) { 4917 struct class_ro32_t cro; 4918 const char *r; 4919 uint32_t offset, xoffset, left; 4920 SectionRef S, xS; 4921 const char *name; 4922 4923 r = get_pointer_32(p, offset, left, S, info); 4924 if (r == nullptr) 4925 return false; 4926 memset(&cro, '\0', sizeof(struct class_ro32_t)); 4927 if (left < sizeof(struct class_ro32_t)) { 4928 memcpy(&cro, r, left); 4929 outs() << " (class_ro_t entends past the end of the section)\n"; 4930 } else 4931 memcpy(&cro, r, sizeof(struct class_ro32_t)); 4932 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4933 swapStruct(cro); 4934 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4935 if (cro.flags & RO_META) 4936 outs() << " RO_META"; 4937 if (cro.flags & RO_ROOT) 4938 outs() << " RO_ROOT"; 4939 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4940 outs() << " RO_HAS_CXX_STRUCTORS"; 4941 outs() << "\n"; 4942 outs() << " instanceStart " << cro.instanceStart << "\n"; 4943 outs() << " instanceSize " << cro.instanceSize << "\n"; 4944 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 4945 << "\n"; 4946 print_layout_map32(cro.ivarLayout, info); 4947 4948 outs() << " name " << format("0x%" PRIx32, cro.name); 4949 name = get_pointer_32(cro.name, xoffset, left, xS, info); 4950 if (name != nullptr) 4951 outs() << format(" %.*s", left, name); 4952 outs() << "\n"; 4953 4954 outs() << " baseMethods " 4955 << format("0x%" PRIx32, cro.baseMethods) 4956 << " (struct method_list_t *)\n"; 4957 if (cro.baseMethods != 0) 4958 print_method_list32_t(cro.baseMethods, info, ""); 4959 4960 outs() << " baseProtocols " 4961 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 4962 if (cro.baseProtocols != 0) 4963 print_protocol_list32_t(cro.baseProtocols, info); 4964 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 4965 << "\n"; 4966 if (cro.ivars != 0) 4967 print_ivar_list32_t(cro.ivars, info); 4968 outs() << " weakIvarLayout " 4969 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 4970 print_layout_map32(cro.weakIvarLayout, info); 4971 outs() << " baseProperties " 4972 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 4973 if (cro.baseProperties != 0) 4974 print_objc_property_list32(cro.baseProperties, info); 4975 is_meta_class = (cro.flags & RO_META) != 0; 4976 return true; 4977 } 4978 4979 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 4980 struct class64_t c; 4981 const char *r; 4982 uint32_t offset, left; 4983 SectionRef S; 4984 const char *name; 4985 uint64_t isa_n_value, n_value; 4986 4987 r = get_pointer_64(p, offset, left, S, info); 4988 if (r == nullptr || left < sizeof(struct class64_t)) 4989 return; 4990 memcpy(&c, r, sizeof(struct class64_t)); 4991 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4992 swapStruct(c); 4993 4994 outs() << " isa " << format("0x%" PRIx64, c.isa); 4995 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 4996 isa_n_value, c.isa); 4997 if (name != nullptr) 4998 outs() << " " << name; 4999 outs() << "\n"; 5000 5001 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 5002 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 5003 n_value, c.superclass); 5004 if (name != nullptr) 5005 outs() << " " << name; 5006 else { 5007 name = get_dyld_bind_info_symbolname(S.getAddress() + 5008 offset + offsetof(struct class64_t, superclass), info); 5009 if (name != nullptr) 5010 outs() << " " << name; 5011 } 5012 outs() << "\n"; 5013 5014 outs() << " cache " << format("0x%" PRIx64, c.cache); 5015 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 5016 n_value, c.cache); 5017 if (name != nullptr) 5018 outs() << " " << name; 5019 outs() << "\n"; 5020 5021 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 5022 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 5023 n_value, c.vtable); 5024 if (name != nullptr) 5025 outs() << " " << name; 5026 outs() << "\n"; 5027 5028 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 5029 n_value, c.data); 5030 outs() << " data "; 5031 if (n_value != 0) { 5032 if (info->verbose && name != nullptr) 5033 outs() << name; 5034 else 5035 outs() << format("0x%" PRIx64, n_value); 5036 if (c.data != 0) 5037 outs() << " + " << format("0x%" PRIx64, c.data); 5038 } else 5039 outs() << format("0x%" PRIx64, c.data); 5040 outs() << " (struct class_ro_t *)"; 5041 5042 // This is a Swift class if some of the low bits of the pointer are set. 5043 if ((c.data + n_value) & 0x7) 5044 outs() << " Swift class"; 5045 outs() << "\n"; 5046 bool is_meta_class; 5047 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5048 return; 5049 5050 if (!is_meta_class && 5051 c.isa + isa_n_value != p && 5052 c.isa + isa_n_value != 0 && 5053 info->depth < 100) { 5054 info->depth++; 5055 outs() << "Meta Class\n"; 5056 print_class64_t(c.isa + isa_n_value, info); 5057 } 5058 } 5059 5060 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5061 struct class32_t c; 5062 const char *r; 5063 uint32_t offset, left; 5064 SectionRef S; 5065 const char *name; 5066 5067 r = get_pointer_32(p, offset, left, S, info); 5068 if (r == nullptr) 5069 return; 5070 memset(&c, '\0', sizeof(struct class32_t)); 5071 if (left < sizeof(struct class32_t)) { 5072 memcpy(&c, r, left); 5073 outs() << " (class_t entends past the end of the section)\n"; 5074 } else 5075 memcpy(&c, r, sizeof(struct class32_t)); 5076 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5077 swapStruct(c); 5078 5079 outs() << " isa " << format("0x%" PRIx32, c.isa); 5080 name = 5081 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5082 if (name != nullptr) 5083 outs() << " " << name; 5084 outs() << "\n"; 5085 5086 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5087 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5088 c.superclass); 5089 if (name != nullptr) 5090 outs() << " " << name; 5091 outs() << "\n"; 5092 5093 outs() << " cache " << format("0x%" PRIx32, c.cache); 5094 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5095 c.cache); 5096 if (name != nullptr) 5097 outs() << " " << name; 5098 outs() << "\n"; 5099 5100 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5101 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5102 c.vtable); 5103 if (name != nullptr) 5104 outs() << " " << name; 5105 outs() << "\n"; 5106 5107 name = 5108 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5109 outs() << " data " << format("0x%" PRIx32, c.data) 5110 << " (struct class_ro_t *)"; 5111 5112 // This is a Swift class if some of the low bits of the pointer are set. 5113 if (c.data & 0x3) 5114 outs() << " Swift class"; 5115 outs() << "\n"; 5116 bool is_meta_class; 5117 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5118 return; 5119 5120 if (!is_meta_class) { 5121 outs() << "Meta Class\n"; 5122 print_class32_t(c.isa, info); 5123 } 5124 } 5125 5126 static void print_objc_class_t(struct objc_class_t *objc_class, 5127 struct DisassembleInfo *info) { 5128 uint32_t offset, left, xleft; 5129 const char *name, *p, *ivar_list; 5130 SectionRef S; 5131 int32_t i; 5132 struct objc_ivar_list_t objc_ivar_list; 5133 struct objc_ivar_t ivar; 5134 5135 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5136 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5137 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5138 if (name != nullptr) 5139 outs() << format(" %.*s", left, name); 5140 else 5141 outs() << " (not in an __OBJC section)"; 5142 } 5143 outs() << "\n"; 5144 5145 outs() << "\t super_class " 5146 << format("0x%08" PRIx32, objc_class->super_class); 5147 if (info->verbose) { 5148 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5149 if (name != nullptr) 5150 outs() << format(" %.*s", left, name); 5151 else 5152 outs() << " (not in an __OBJC section)"; 5153 } 5154 outs() << "\n"; 5155 5156 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5157 if (info->verbose) { 5158 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5159 if (name != nullptr) 5160 outs() << format(" %.*s", left, name); 5161 else 5162 outs() << " (not in an __OBJC section)"; 5163 } 5164 outs() << "\n"; 5165 5166 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5167 << "\n"; 5168 5169 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5170 if (info->verbose) { 5171 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5172 outs() << " CLS_CLASS"; 5173 else if (CLS_GETINFO(objc_class, CLS_META)) 5174 outs() << " CLS_META"; 5175 } 5176 outs() << "\n"; 5177 5178 outs() << "\t instance_size " 5179 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5180 5181 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5182 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5183 if (p != nullptr) { 5184 if (left > sizeof(struct objc_ivar_list_t)) { 5185 outs() << "\n"; 5186 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5187 } else { 5188 outs() << " (entends past the end of the section)\n"; 5189 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5190 memcpy(&objc_ivar_list, p, left); 5191 } 5192 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5193 swapStruct(objc_ivar_list); 5194 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5195 ivar_list = p + sizeof(struct objc_ivar_list_t); 5196 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5197 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5198 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5199 break; 5200 } 5201 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5202 sizeof(struct objc_ivar_t)); 5203 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5204 swapStruct(ivar); 5205 5206 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5207 if (info->verbose) { 5208 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5209 if (name != nullptr) 5210 outs() << format(" %.*s", xleft, name); 5211 else 5212 outs() << " (not in an __OBJC section)"; 5213 } 5214 outs() << "\n"; 5215 5216 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5217 if (info->verbose) { 5218 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5219 if (name != nullptr) 5220 outs() << format(" %.*s", xleft, name); 5221 else 5222 outs() << " (not in an __OBJC section)"; 5223 } 5224 outs() << "\n"; 5225 5226 outs() << "\t\t ivar_offset " 5227 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5228 } 5229 } else { 5230 outs() << " (not in an __OBJC section)\n"; 5231 } 5232 5233 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5234 if (print_method_list(objc_class->methodLists, info)) 5235 outs() << " (not in an __OBJC section)\n"; 5236 5237 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5238 << "\n"; 5239 5240 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5241 if (print_protocol_list(objc_class->protocols, 16, info)) 5242 outs() << " (not in an __OBJC section)\n"; 5243 } 5244 5245 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5246 struct DisassembleInfo *info) { 5247 uint32_t offset, left; 5248 const char *name; 5249 SectionRef S; 5250 5251 outs() << "\t category name " 5252 << format("0x%08" PRIx32, objc_category->category_name); 5253 if (info->verbose) { 5254 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5255 true); 5256 if (name != nullptr) 5257 outs() << format(" %.*s", left, name); 5258 else 5259 outs() << " (not in an __OBJC section)"; 5260 } 5261 outs() << "\n"; 5262 5263 outs() << "\t\t class name " 5264 << format("0x%08" PRIx32, objc_category->class_name); 5265 if (info->verbose) { 5266 name = 5267 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5268 if (name != nullptr) 5269 outs() << format(" %.*s", left, name); 5270 else 5271 outs() << " (not in an __OBJC section)"; 5272 } 5273 outs() << "\n"; 5274 5275 outs() << "\t instance methods " 5276 << format("0x%08" PRIx32, objc_category->instance_methods); 5277 if (print_method_list(objc_category->instance_methods, info)) 5278 outs() << " (not in an __OBJC section)\n"; 5279 5280 outs() << "\t class methods " 5281 << format("0x%08" PRIx32, objc_category->class_methods); 5282 if (print_method_list(objc_category->class_methods, info)) 5283 outs() << " (not in an __OBJC section)\n"; 5284 } 5285 5286 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5287 struct category64_t c; 5288 const char *r; 5289 uint32_t offset, xoffset, left; 5290 SectionRef S, xS; 5291 const char *name, *sym_name; 5292 uint64_t n_value; 5293 5294 r = get_pointer_64(p, offset, left, S, info); 5295 if (r == nullptr) 5296 return; 5297 memset(&c, '\0', sizeof(struct category64_t)); 5298 if (left < sizeof(struct category64_t)) { 5299 memcpy(&c, r, left); 5300 outs() << " (category_t entends past the end of the section)\n"; 5301 } else 5302 memcpy(&c, r, sizeof(struct category64_t)); 5303 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5304 swapStruct(c); 5305 5306 outs() << " name "; 5307 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 5308 info, n_value, c.name); 5309 if (n_value != 0) { 5310 if (info->verbose && sym_name != nullptr) 5311 outs() << sym_name; 5312 else 5313 outs() << format("0x%" PRIx64, n_value); 5314 if (c.name != 0) 5315 outs() << " + " << format("0x%" PRIx64, c.name); 5316 } else 5317 outs() << format("0x%" PRIx64, c.name); 5318 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 5319 if (name != nullptr) 5320 outs() << format(" %.*s", left, name); 5321 outs() << "\n"; 5322 5323 outs() << " cls "; 5324 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 5325 n_value, c.cls); 5326 if (n_value != 0) { 5327 if (info->verbose && sym_name != nullptr) 5328 outs() << sym_name; 5329 else 5330 outs() << format("0x%" PRIx64, n_value); 5331 if (c.cls != 0) 5332 outs() << " + " << format("0x%" PRIx64, c.cls); 5333 } else 5334 outs() << format("0x%" PRIx64, c.cls); 5335 outs() << "\n"; 5336 if (c.cls + n_value != 0) 5337 print_class64_t(c.cls + n_value, info); 5338 5339 outs() << " instanceMethods "; 5340 sym_name = 5341 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 5342 info, n_value, c.instanceMethods); 5343 if (n_value != 0) { 5344 if (info->verbose && sym_name != nullptr) 5345 outs() << sym_name; 5346 else 5347 outs() << format("0x%" PRIx64, n_value); 5348 if (c.instanceMethods != 0) 5349 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 5350 } else 5351 outs() << format("0x%" PRIx64, c.instanceMethods); 5352 outs() << "\n"; 5353 if (c.instanceMethods + n_value != 0) 5354 print_method_list64_t(c.instanceMethods + n_value, info, ""); 5355 5356 outs() << " classMethods "; 5357 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 5358 S, info, n_value, c.classMethods); 5359 if (n_value != 0) { 5360 if (info->verbose && sym_name != nullptr) 5361 outs() << sym_name; 5362 else 5363 outs() << format("0x%" PRIx64, n_value); 5364 if (c.classMethods != 0) 5365 outs() << " + " << format("0x%" PRIx64, c.classMethods); 5366 } else 5367 outs() << format("0x%" PRIx64, c.classMethods); 5368 outs() << "\n"; 5369 if (c.classMethods + n_value != 0) 5370 print_method_list64_t(c.classMethods + n_value, info, ""); 5371 5372 outs() << " protocols "; 5373 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 5374 info, n_value, c.protocols); 5375 if (n_value != 0) { 5376 if (info->verbose && sym_name != nullptr) 5377 outs() << sym_name; 5378 else 5379 outs() << format("0x%" PRIx64, n_value); 5380 if (c.protocols != 0) 5381 outs() << " + " << format("0x%" PRIx64, c.protocols); 5382 } else 5383 outs() << format("0x%" PRIx64, c.protocols); 5384 outs() << "\n"; 5385 if (c.protocols + n_value != 0) 5386 print_protocol_list64_t(c.protocols + n_value, info); 5387 5388 outs() << "instanceProperties "; 5389 sym_name = 5390 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 5391 S, info, n_value, c.instanceProperties); 5392 if (n_value != 0) { 5393 if (info->verbose && sym_name != nullptr) 5394 outs() << sym_name; 5395 else 5396 outs() << format("0x%" PRIx64, n_value); 5397 if (c.instanceProperties != 0) 5398 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 5399 } else 5400 outs() << format("0x%" PRIx64, c.instanceProperties); 5401 outs() << "\n"; 5402 if (c.instanceProperties + n_value != 0) 5403 print_objc_property_list64(c.instanceProperties + n_value, info); 5404 } 5405 5406 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 5407 struct category32_t c; 5408 const char *r; 5409 uint32_t offset, left; 5410 SectionRef S, xS; 5411 const char *name; 5412 5413 r = get_pointer_32(p, offset, left, S, info); 5414 if (r == nullptr) 5415 return; 5416 memset(&c, '\0', sizeof(struct category32_t)); 5417 if (left < sizeof(struct category32_t)) { 5418 memcpy(&c, r, left); 5419 outs() << " (category_t entends past the end of the section)\n"; 5420 } else 5421 memcpy(&c, r, sizeof(struct category32_t)); 5422 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5423 swapStruct(c); 5424 5425 outs() << " name " << format("0x%" PRIx32, c.name); 5426 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 5427 c.name); 5428 if (name) 5429 outs() << " " << name; 5430 outs() << "\n"; 5431 5432 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 5433 if (c.cls != 0) 5434 print_class32_t(c.cls, info); 5435 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 5436 << "\n"; 5437 if (c.instanceMethods != 0) 5438 print_method_list32_t(c.instanceMethods, info, ""); 5439 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 5440 << "\n"; 5441 if (c.classMethods != 0) 5442 print_method_list32_t(c.classMethods, info, ""); 5443 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 5444 if (c.protocols != 0) 5445 print_protocol_list32_t(c.protocols, info); 5446 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 5447 << "\n"; 5448 if (c.instanceProperties != 0) 5449 print_objc_property_list32(c.instanceProperties, info); 5450 } 5451 5452 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 5453 uint32_t i, left, offset, xoffset; 5454 uint64_t p, n_value; 5455 struct message_ref64 mr; 5456 const char *name, *sym_name; 5457 const char *r; 5458 SectionRef xS; 5459 5460 if (S == SectionRef()) 5461 return; 5462 5463 StringRef SectName; 5464 S.getName(SectName); 5465 DataRefImpl Ref = S.getRawDataRefImpl(); 5466 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5467 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5468 offset = 0; 5469 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5470 p = S.getAddress() + i; 5471 r = get_pointer_64(p, offset, left, S, info); 5472 if (r == nullptr) 5473 return; 5474 memset(&mr, '\0', sizeof(struct message_ref64)); 5475 if (left < sizeof(struct message_ref64)) { 5476 memcpy(&mr, r, left); 5477 outs() << " (message_ref entends past the end of the section)\n"; 5478 } else 5479 memcpy(&mr, r, sizeof(struct message_ref64)); 5480 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5481 swapStruct(mr); 5482 5483 outs() << " imp "; 5484 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 5485 n_value, mr.imp); 5486 if (n_value != 0) { 5487 outs() << format("0x%" PRIx64, n_value) << " "; 5488 if (mr.imp != 0) 5489 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 5490 } else 5491 outs() << format("0x%" PRIx64, mr.imp) << " "; 5492 if (name != nullptr) 5493 outs() << " " << name; 5494 outs() << "\n"; 5495 5496 outs() << " sel "; 5497 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 5498 info, n_value, mr.sel); 5499 if (n_value != 0) { 5500 if (info->verbose && sym_name != nullptr) 5501 outs() << sym_name; 5502 else 5503 outs() << format("0x%" PRIx64, n_value); 5504 if (mr.sel != 0) 5505 outs() << " + " << format("0x%" PRIx64, mr.sel); 5506 } else 5507 outs() << format("0x%" PRIx64, mr.sel); 5508 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 5509 if (name != nullptr) 5510 outs() << format(" %.*s", left, name); 5511 outs() << "\n"; 5512 5513 offset += sizeof(struct message_ref64); 5514 } 5515 } 5516 5517 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 5518 uint32_t i, left, offset, xoffset, p; 5519 struct message_ref32 mr; 5520 const char *name, *r; 5521 SectionRef xS; 5522 5523 if (S == SectionRef()) 5524 return; 5525 5526 StringRef SectName; 5527 S.getName(SectName); 5528 DataRefImpl Ref = S.getRawDataRefImpl(); 5529 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5530 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5531 offset = 0; 5532 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5533 p = S.getAddress() + i; 5534 r = get_pointer_32(p, offset, left, S, info); 5535 if (r == nullptr) 5536 return; 5537 memset(&mr, '\0', sizeof(struct message_ref32)); 5538 if (left < sizeof(struct message_ref32)) { 5539 memcpy(&mr, r, left); 5540 outs() << " (message_ref entends past the end of the section)\n"; 5541 } else 5542 memcpy(&mr, r, sizeof(struct message_ref32)); 5543 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5544 swapStruct(mr); 5545 5546 outs() << " imp " << format("0x%" PRIx32, mr.imp); 5547 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 5548 mr.imp); 5549 if (name != nullptr) 5550 outs() << " " << name; 5551 outs() << "\n"; 5552 5553 outs() << " sel " << format("0x%" PRIx32, mr.sel); 5554 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 5555 if (name != nullptr) 5556 outs() << " " << name; 5557 outs() << "\n"; 5558 5559 offset += sizeof(struct message_ref32); 5560 } 5561 } 5562 5563 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 5564 uint32_t left, offset, swift_version; 5565 uint64_t p; 5566 struct objc_image_info64 o; 5567 const char *r; 5568 5569 if (S == SectionRef()) 5570 return; 5571 5572 StringRef SectName; 5573 S.getName(SectName); 5574 DataRefImpl Ref = S.getRawDataRefImpl(); 5575 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5576 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5577 p = S.getAddress(); 5578 r = get_pointer_64(p, offset, left, S, info); 5579 if (r == nullptr) 5580 return; 5581 memset(&o, '\0', sizeof(struct objc_image_info64)); 5582 if (left < sizeof(struct objc_image_info64)) { 5583 memcpy(&o, r, left); 5584 outs() << " (objc_image_info entends past the end of the section)\n"; 5585 } else 5586 memcpy(&o, r, sizeof(struct objc_image_info64)); 5587 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5588 swapStruct(o); 5589 outs() << " version " << o.version << "\n"; 5590 outs() << " flags " << format("0x%" PRIx32, o.flags); 5591 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5592 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5593 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5594 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5595 if (o.flags & OBJC_IMAGE_IS_SIMULATED) 5596 outs() << " OBJC_IMAGE_IS_SIMULATED"; 5597 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES) 5598 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES"; 5599 swift_version = (o.flags >> 8) & 0xff; 5600 if (swift_version != 0) { 5601 if (swift_version == 1) 5602 outs() << " Swift 1.0"; 5603 else if (swift_version == 2) 5604 outs() << " Swift 1.1"; 5605 else if(swift_version == 3) 5606 outs() << " Swift 2.0"; 5607 else if(swift_version == 4) 5608 outs() << " Swift 3.0"; 5609 else if(swift_version == 5) 5610 outs() << " Swift 4.0"; 5611 else if(swift_version == 6) 5612 outs() << " Swift 4.1"; 5613 else 5614 outs() << " unknown future Swift version (" << swift_version << ")"; 5615 } 5616 outs() << "\n"; 5617 } 5618 5619 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 5620 uint32_t left, offset, swift_version, p; 5621 struct objc_image_info32 o; 5622 const char *r; 5623 5624 if (S == SectionRef()) 5625 return; 5626 5627 StringRef SectName; 5628 S.getName(SectName); 5629 DataRefImpl Ref = S.getRawDataRefImpl(); 5630 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5631 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5632 p = S.getAddress(); 5633 r = get_pointer_32(p, offset, left, S, info); 5634 if (r == nullptr) 5635 return; 5636 memset(&o, '\0', sizeof(struct objc_image_info32)); 5637 if (left < sizeof(struct objc_image_info32)) { 5638 memcpy(&o, r, left); 5639 outs() << " (objc_image_info entends past the end of the section)\n"; 5640 } else 5641 memcpy(&o, r, sizeof(struct objc_image_info32)); 5642 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5643 swapStruct(o); 5644 outs() << " version " << o.version << "\n"; 5645 outs() << " flags " << format("0x%" PRIx32, o.flags); 5646 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5647 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5648 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5649 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5650 swift_version = (o.flags >> 8) & 0xff; 5651 if (swift_version != 0) { 5652 if (swift_version == 1) 5653 outs() << " Swift 1.0"; 5654 else if (swift_version == 2) 5655 outs() << " Swift 1.1"; 5656 else if(swift_version == 3) 5657 outs() << " Swift 2.0"; 5658 else if(swift_version == 4) 5659 outs() << " Swift 3.0"; 5660 else if(swift_version == 5) 5661 outs() << " Swift 4.0"; 5662 else if(swift_version == 6) 5663 outs() << " Swift 4.1"; 5664 else 5665 outs() << " unknown future Swift version (" << swift_version << ")"; 5666 } 5667 outs() << "\n"; 5668 } 5669 5670 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 5671 uint32_t left, offset, p; 5672 struct imageInfo_t o; 5673 const char *r; 5674 5675 StringRef SectName; 5676 S.getName(SectName); 5677 DataRefImpl Ref = S.getRawDataRefImpl(); 5678 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5679 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5680 p = S.getAddress(); 5681 r = get_pointer_32(p, offset, left, S, info); 5682 if (r == nullptr) 5683 return; 5684 memset(&o, '\0', sizeof(struct imageInfo_t)); 5685 if (left < sizeof(struct imageInfo_t)) { 5686 memcpy(&o, r, left); 5687 outs() << " (imageInfo entends past the end of the section)\n"; 5688 } else 5689 memcpy(&o, r, sizeof(struct imageInfo_t)); 5690 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5691 swapStruct(o); 5692 outs() << " version " << o.version << "\n"; 5693 outs() << " flags " << format("0x%" PRIx32, o.flags); 5694 if (o.flags & 0x1) 5695 outs() << " F&C"; 5696 if (o.flags & 0x2) 5697 outs() << " GC"; 5698 if (o.flags & 0x4) 5699 outs() << " GC-only"; 5700 else 5701 outs() << " RR"; 5702 outs() << "\n"; 5703 } 5704 5705 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 5706 SymbolAddressMap AddrMap; 5707 if (verbose) 5708 CreateSymbolAddressMap(O, &AddrMap); 5709 5710 std::vector<SectionRef> Sections; 5711 for (const SectionRef &Section : O->sections()) { 5712 StringRef SectName; 5713 Section.getName(SectName); 5714 Sections.push_back(Section); 5715 } 5716 5717 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 5718 5719 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5720 if (CL == SectionRef()) 5721 CL = get_section(O, "__DATA", "__objc_classlist"); 5722 if (CL == SectionRef()) 5723 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5724 if (CL == SectionRef()) 5725 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5726 info.S = CL; 5727 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 5728 5729 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5730 if (CR == SectionRef()) 5731 CR = get_section(O, "__DATA", "__objc_classrefs"); 5732 if (CR == SectionRef()) 5733 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5734 if (CR == SectionRef()) 5735 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5736 info.S = CR; 5737 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 5738 5739 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5740 if (SR == SectionRef()) 5741 SR = get_section(O, "__DATA", "__objc_superrefs"); 5742 if (SR == SectionRef()) 5743 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5744 if (SR == SectionRef()) 5745 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5746 info.S = SR; 5747 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 5748 5749 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5750 if (CA == SectionRef()) 5751 CA = get_section(O, "__DATA", "__objc_catlist"); 5752 if (CA == SectionRef()) 5753 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5754 if (CA == SectionRef()) 5755 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5756 info.S = CA; 5757 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 5758 5759 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5760 if (PL == SectionRef()) 5761 PL = get_section(O, "__DATA", "__objc_protolist"); 5762 if (PL == SectionRef()) 5763 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5764 if (PL == SectionRef()) 5765 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5766 info.S = PL; 5767 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 5768 5769 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5770 if (MR == SectionRef()) 5771 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5772 if (MR == SectionRef()) 5773 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5774 if (MR == SectionRef()) 5775 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5776 info.S = MR; 5777 print_message_refs64(MR, &info); 5778 5779 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5780 if (II == SectionRef()) 5781 II = get_section(O, "__DATA", "__objc_imageinfo"); 5782 if (II == SectionRef()) 5783 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5784 if (II == SectionRef()) 5785 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5786 info.S = II; 5787 print_image_info64(II, &info); 5788 } 5789 5790 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5791 SymbolAddressMap AddrMap; 5792 if (verbose) 5793 CreateSymbolAddressMap(O, &AddrMap); 5794 5795 std::vector<SectionRef> Sections; 5796 for (const SectionRef &Section : O->sections()) { 5797 StringRef SectName; 5798 Section.getName(SectName); 5799 Sections.push_back(Section); 5800 } 5801 5802 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 5803 5804 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5805 if (CL == SectionRef()) 5806 CL = get_section(O, "__DATA", "__objc_classlist"); 5807 if (CL == SectionRef()) 5808 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5809 if (CL == SectionRef()) 5810 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5811 info.S = CL; 5812 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 5813 5814 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5815 if (CR == SectionRef()) 5816 CR = get_section(O, "__DATA", "__objc_classrefs"); 5817 if (CR == SectionRef()) 5818 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5819 if (CR == SectionRef()) 5820 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5821 info.S = CR; 5822 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 5823 5824 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5825 if (SR == SectionRef()) 5826 SR = get_section(O, "__DATA", "__objc_superrefs"); 5827 if (SR == SectionRef()) 5828 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5829 if (SR == SectionRef()) 5830 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5831 info.S = SR; 5832 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 5833 5834 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5835 if (CA == SectionRef()) 5836 CA = get_section(O, "__DATA", "__objc_catlist"); 5837 if (CA == SectionRef()) 5838 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5839 if (CA == SectionRef()) 5840 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5841 info.S = CA; 5842 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 5843 5844 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5845 if (PL == SectionRef()) 5846 PL = get_section(O, "__DATA", "__objc_protolist"); 5847 if (PL == SectionRef()) 5848 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5849 if (PL == SectionRef()) 5850 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5851 info.S = PL; 5852 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 5853 5854 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5855 if (MR == SectionRef()) 5856 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5857 if (MR == SectionRef()) 5858 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5859 if (MR == SectionRef()) 5860 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5861 info.S = MR; 5862 print_message_refs32(MR, &info); 5863 5864 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5865 if (II == SectionRef()) 5866 II = get_section(O, "__DATA", "__objc_imageinfo"); 5867 if (II == SectionRef()) 5868 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5869 if (II == SectionRef()) 5870 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5871 info.S = II; 5872 print_image_info32(II, &info); 5873 } 5874 5875 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5876 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 5877 const char *r, *name, *defs; 5878 struct objc_module_t module; 5879 SectionRef S, xS; 5880 struct objc_symtab_t symtab; 5881 struct objc_class_t objc_class; 5882 struct objc_category_t objc_category; 5883 5884 outs() << "Objective-C segment\n"; 5885 S = get_section(O, "__OBJC", "__module_info"); 5886 if (S == SectionRef()) 5887 return false; 5888 5889 SymbolAddressMap AddrMap; 5890 if (verbose) 5891 CreateSymbolAddressMap(O, &AddrMap); 5892 5893 std::vector<SectionRef> Sections; 5894 for (const SectionRef &Section : O->sections()) { 5895 StringRef SectName; 5896 Section.getName(SectName); 5897 Sections.push_back(Section); 5898 } 5899 5900 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 5901 5902 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 5903 p = S.getAddress() + i; 5904 r = get_pointer_32(p, offset, left, S, &info, true); 5905 if (r == nullptr) 5906 return true; 5907 memset(&module, '\0', sizeof(struct objc_module_t)); 5908 if (left < sizeof(struct objc_module_t)) { 5909 memcpy(&module, r, left); 5910 outs() << " (module extends past end of __module_info section)\n"; 5911 } else 5912 memcpy(&module, r, sizeof(struct objc_module_t)); 5913 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5914 swapStruct(module); 5915 5916 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 5917 outs() << " version " << module.version << "\n"; 5918 outs() << " size " << module.size << "\n"; 5919 outs() << " name "; 5920 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 5921 if (name != nullptr) 5922 outs() << format("%.*s", left, name); 5923 else 5924 outs() << format("0x%08" PRIx32, module.name) 5925 << "(not in an __OBJC section)"; 5926 outs() << "\n"; 5927 5928 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 5929 if (module.symtab == 0 || r == nullptr) { 5930 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 5931 << " (not in an __OBJC section)\n"; 5932 continue; 5933 } 5934 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 5935 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 5936 defs_left = 0; 5937 defs = nullptr; 5938 if (left < sizeof(struct objc_symtab_t)) { 5939 memcpy(&symtab, r, left); 5940 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 5941 } else { 5942 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 5943 if (left > sizeof(struct objc_symtab_t)) { 5944 defs_left = left - sizeof(struct objc_symtab_t); 5945 defs = r + sizeof(struct objc_symtab_t); 5946 } 5947 } 5948 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5949 swapStruct(symtab); 5950 5951 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 5952 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 5953 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 5954 if (r == nullptr) 5955 outs() << " (not in an __OBJC section)"; 5956 outs() << "\n"; 5957 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 5958 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 5959 if (symtab.cls_def_cnt > 0) 5960 outs() << "\tClass Definitions\n"; 5961 for (j = 0; j < symtab.cls_def_cnt; j++) { 5962 if ((j + 1) * sizeof(uint32_t) > defs_left) { 5963 outs() << "\t(remaining class defs entries entends past the end of the " 5964 << "section)\n"; 5965 break; 5966 } 5967 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 5968 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5969 sys::swapByteOrder(def); 5970 5971 r = get_pointer_32(def, xoffset, left, xS, &info, true); 5972 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 5973 if (r != nullptr) { 5974 if (left > sizeof(struct objc_class_t)) { 5975 outs() << "\n"; 5976 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 5977 } else { 5978 outs() << " (entends past the end of the section)\n"; 5979 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 5980 memcpy(&objc_class, r, left); 5981 } 5982 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5983 swapStruct(objc_class); 5984 print_objc_class_t(&objc_class, &info); 5985 } else { 5986 outs() << "(not in an __OBJC section)\n"; 5987 } 5988 5989 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 5990 outs() << "\tMeta Class"; 5991 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 5992 if (r != nullptr) { 5993 if (left > sizeof(struct objc_class_t)) { 5994 outs() << "\n"; 5995 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 5996 } else { 5997 outs() << " (entends past the end of the section)\n"; 5998 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 5999 memcpy(&objc_class, r, left); 6000 } 6001 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6002 swapStruct(objc_class); 6003 print_objc_class_t(&objc_class, &info); 6004 } else { 6005 outs() << "(not in an __OBJC section)\n"; 6006 } 6007 } 6008 } 6009 if (symtab.cat_def_cnt > 0) 6010 outs() << "\tCategory Definitions\n"; 6011 for (j = 0; j < symtab.cat_def_cnt; j++) { 6012 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 6013 outs() << "\t(remaining category defs entries entends past the end of " 6014 << "the section)\n"; 6015 break; 6016 } 6017 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6018 sizeof(uint32_t)); 6019 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6020 sys::swapByteOrder(def); 6021 6022 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6023 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6024 << format("0x%08" PRIx32, def); 6025 if (r != nullptr) { 6026 if (left > sizeof(struct objc_category_t)) { 6027 outs() << "\n"; 6028 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6029 } else { 6030 outs() << " (entends past the end of the section)\n"; 6031 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6032 memcpy(&objc_category, r, left); 6033 } 6034 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6035 swapStruct(objc_category); 6036 print_objc_objc_category_t(&objc_category, &info); 6037 } else { 6038 outs() << "(not in an __OBJC section)\n"; 6039 } 6040 } 6041 } 6042 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6043 if (II != SectionRef()) 6044 print_image_info(II, &info); 6045 6046 return true; 6047 } 6048 6049 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6050 uint32_t size, uint32_t addr) { 6051 SymbolAddressMap AddrMap; 6052 CreateSymbolAddressMap(O, &AddrMap); 6053 6054 std::vector<SectionRef> Sections; 6055 for (const SectionRef &Section : O->sections()) { 6056 StringRef SectName; 6057 Section.getName(SectName); 6058 Sections.push_back(Section); 6059 } 6060 6061 struct DisassembleInfo info(O, &AddrMap, &Sections, true); 6062 6063 const char *p; 6064 struct objc_protocol_t protocol; 6065 uint32_t left, paddr; 6066 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6067 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6068 left = size - (p - sect); 6069 if (left < sizeof(struct objc_protocol_t)) { 6070 outs() << "Protocol extends past end of __protocol section\n"; 6071 memcpy(&protocol, p, left); 6072 } else 6073 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6074 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6075 swapStruct(protocol); 6076 paddr = addr + (p - sect); 6077 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6078 if (print_protocol(paddr, 0, &info)) 6079 outs() << "(not in an __OBJC section)\n"; 6080 } 6081 } 6082 6083 #ifdef HAVE_LIBXAR 6084 inline void swapStruct(struct xar_header &xar) { 6085 sys::swapByteOrder(xar.magic); 6086 sys::swapByteOrder(xar.size); 6087 sys::swapByteOrder(xar.version); 6088 sys::swapByteOrder(xar.toc_length_compressed); 6089 sys::swapByteOrder(xar.toc_length_uncompressed); 6090 sys::swapByteOrder(xar.cksum_alg); 6091 } 6092 6093 static void PrintModeVerbose(uint32_t mode) { 6094 switch(mode & S_IFMT){ 6095 case S_IFDIR: 6096 outs() << "d"; 6097 break; 6098 case S_IFCHR: 6099 outs() << "c"; 6100 break; 6101 case S_IFBLK: 6102 outs() << "b"; 6103 break; 6104 case S_IFREG: 6105 outs() << "-"; 6106 break; 6107 case S_IFLNK: 6108 outs() << "l"; 6109 break; 6110 case S_IFSOCK: 6111 outs() << "s"; 6112 break; 6113 default: 6114 outs() << "?"; 6115 break; 6116 } 6117 6118 /* owner permissions */ 6119 if(mode & S_IREAD) 6120 outs() << "r"; 6121 else 6122 outs() << "-"; 6123 if(mode & S_IWRITE) 6124 outs() << "w"; 6125 else 6126 outs() << "-"; 6127 if(mode & S_ISUID) 6128 outs() << "s"; 6129 else if(mode & S_IEXEC) 6130 outs() << "x"; 6131 else 6132 outs() << "-"; 6133 6134 /* group permissions */ 6135 if(mode & (S_IREAD >> 3)) 6136 outs() << "r"; 6137 else 6138 outs() << "-"; 6139 if(mode & (S_IWRITE >> 3)) 6140 outs() << "w"; 6141 else 6142 outs() << "-"; 6143 if(mode & S_ISGID) 6144 outs() << "s"; 6145 else if(mode & (S_IEXEC >> 3)) 6146 outs() << "x"; 6147 else 6148 outs() << "-"; 6149 6150 /* other permissions */ 6151 if(mode & (S_IREAD >> 6)) 6152 outs() << "r"; 6153 else 6154 outs() << "-"; 6155 if(mode & (S_IWRITE >> 6)) 6156 outs() << "w"; 6157 else 6158 outs() << "-"; 6159 if(mode & S_ISVTX) 6160 outs() << "t"; 6161 else if(mode & (S_IEXEC >> 6)) 6162 outs() << "x"; 6163 else 6164 outs() << "-"; 6165 } 6166 6167 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { 6168 xar_file_t xf; 6169 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; 6170 char *endp; 6171 uint32_t mode_value; 6172 6173 ScopedXarIter xi; 6174 if (!xi) { 6175 errs() << "Can't obtain an xar iterator for xar archive " 6176 << XarFilename << "\n"; 6177 return; 6178 } 6179 6180 // Go through the xar's files. 6181 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { 6182 ScopedXarIter xp; 6183 if(!xp){ 6184 errs() << "Can't obtain an xar iterator for xar archive " 6185 << XarFilename << "\n"; 6186 return; 6187 } 6188 type = nullptr; 6189 mode = nullptr; 6190 user = nullptr; 6191 group = nullptr; 6192 size = nullptr; 6193 mtime = nullptr; 6194 name = nullptr; 6195 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6196 const char *val = nullptr; 6197 xar_prop_get(xf, key, &val); 6198 #if 0 // Useful for debugging. 6199 outs() << "key: " << key << " value: " << val << "\n"; 6200 #endif 6201 if(strcmp(key, "type") == 0) 6202 type = val; 6203 if(strcmp(key, "mode") == 0) 6204 mode = val; 6205 if(strcmp(key, "user") == 0) 6206 user = val; 6207 if(strcmp(key, "group") == 0) 6208 group = val; 6209 if(strcmp(key, "data/size") == 0) 6210 size = val; 6211 if(strcmp(key, "mtime") == 0) 6212 mtime = val; 6213 if(strcmp(key, "name") == 0) 6214 name = val; 6215 } 6216 if(mode != nullptr){ 6217 mode_value = strtoul(mode, &endp, 8); 6218 if(*endp != '\0') 6219 outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; 6220 if(strcmp(type, "file") == 0) 6221 mode_value |= S_IFREG; 6222 PrintModeVerbose(mode_value); 6223 outs() << " "; 6224 } 6225 if(user != nullptr) 6226 outs() << format("%10s/", user); 6227 if(group != nullptr) 6228 outs() << format("%-10s ", group); 6229 if(size != nullptr) 6230 outs() << format("%7s ", size); 6231 if(mtime != nullptr){ 6232 for(m = mtime; *m != 'T' && *m != '\0'; m++) 6233 outs() << *m; 6234 if(*m == 'T') 6235 m++; 6236 outs() << " "; 6237 for( ; *m != 'Z' && *m != '\0'; m++) 6238 outs() << *m; 6239 outs() << " "; 6240 } 6241 if(name != nullptr) 6242 outs() << name; 6243 outs() << "\n"; 6244 } 6245 } 6246 6247 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 6248 uint32_t size, bool verbose, 6249 bool PrintXarHeader, bool PrintXarFileHeaders, 6250 std::string XarMemberName) { 6251 if(size < sizeof(struct xar_header)) { 6252 outs() << "size of (__LLVM,__bundle) section too small (smaller than size " 6253 "of struct xar_header)\n"; 6254 return; 6255 } 6256 struct xar_header XarHeader; 6257 memcpy(&XarHeader, sect, sizeof(struct xar_header)); 6258 if (sys::IsLittleEndianHost) 6259 swapStruct(XarHeader); 6260 if (PrintXarHeader) { 6261 if (!XarMemberName.empty()) 6262 outs() << "In xar member " << XarMemberName << ": "; 6263 else 6264 outs() << "For (__LLVM,__bundle) section: "; 6265 outs() << "xar header\n"; 6266 if (XarHeader.magic == XAR_HEADER_MAGIC) 6267 outs() << " magic XAR_HEADER_MAGIC\n"; 6268 else 6269 outs() << " magic " 6270 << format_hex(XarHeader.magic, 10, true) 6271 << " (not XAR_HEADER_MAGIC)\n"; 6272 outs() << " size " << XarHeader.size << "\n"; 6273 outs() << " version " << XarHeader.version << "\n"; 6274 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed 6275 << "\n"; 6276 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed 6277 << "\n"; 6278 outs() << " cksum_alg "; 6279 switch (XarHeader.cksum_alg) { 6280 case XAR_CKSUM_NONE: 6281 outs() << "XAR_CKSUM_NONE\n"; 6282 break; 6283 case XAR_CKSUM_SHA1: 6284 outs() << "XAR_CKSUM_SHA1\n"; 6285 break; 6286 case XAR_CKSUM_MD5: 6287 outs() << "XAR_CKSUM_MD5\n"; 6288 break; 6289 #ifdef XAR_CKSUM_SHA256 6290 case XAR_CKSUM_SHA256: 6291 outs() << "XAR_CKSUM_SHA256\n"; 6292 break; 6293 #endif 6294 #ifdef XAR_CKSUM_SHA512 6295 case XAR_CKSUM_SHA512: 6296 outs() << "XAR_CKSUM_SHA512\n"; 6297 break; 6298 #endif 6299 default: 6300 outs() << XarHeader.cksum_alg << "\n"; 6301 } 6302 } 6303 6304 SmallString<128> XarFilename; 6305 int FD; 6306 std::error_code XarEC = 6307 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); 6308 if (XarEC) { 6309 errs() << XarEC.message() << "\n"; 6310 return; 6311 } 6312 ToolOutputFile XarFile(XarFilename, FD); 6313 raw_fd_ostream &XarOut = XarFile.os(); 6314 StringRef XarContents(sect, size); 6315 XarOut << XarContents; 6316 XarOut.close(); 6317 if (XarOut.has_error()) 6318 return; 6319 6320 ScopedXarFile xar(XarFilename.c_str(), READ); 6321 if (!xar) { 6322 errs() << "Can't create temporary xar archive " << XarFilename << "\n"; 6323 return; 6324 } 6325 6326 SmallString<128> TocFilename; 6327 std::error_code TocEC = 6328 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); 6329 if (TocEC) { 6330 errs() << TocEC.message() << "\n"; 6331 return; 6332 } 6333 xar_serialize(xar, TocFilename.c_str()); 6334 6335 if (PrintXarFileHeaders) { 6336 if (!XarMemberName.empty()) 6337 outs() << "In xar member " << XarMemberName << ": "; 6338 else 6339 outs() << "For (__LLVM,__bundle) section: "; 6340 outs() << "xar archive files:\n"; 6341 PrintXarFilesSummary(XarFilename.c_str(), xar); 6342 } 6343 6344 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 6345 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); 6346 if (std::error_code EC = FileOrErr.getError()) { 6347 errs() << EC.message() << "\n"; 6348 return; 6349 } 6350 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 6351 6352 if (!XarMemberName.empty()) 6353 outs() << "In xar member " << XarMemberName << ": "; 6354 else 6355 outs() << "For (__LLVM,__bundle) section: "; 6356 outs() << "xar table of contents:\n"; 6357 outs() << Buffer->getBuffer() << "\n"; 6358 6359 // TODO: Go through the xar's files. 6360 ScopedXarIter xi; 6361 if(!xi){ 6362 errs() << "Can't obtain an xar iterator for xar archive " 6363 << XarFilename.c_str() << "\n"; 6364 return; 6365 } 6366 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ 6367 const char *key; 6368 const char *member_name, *member_type, *member_size_string; 6369 size_t member_size; 6370 6371 ScopedXarIter xp; 6372 if(!xp){ 6373 errs() << "Can't obtain an xar iterator for xar archive " 6374 << XarFilename.c_str() << "\n"; 6375 return; 6376 } 6377 member_name = NULL; 6378 member_type = NULL; 6379 member_size_string = NULL; 6380 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6381 const char *val = nullptr; 6382 xar_prop_get(xf, key, &val); 6383 #if 0 // Useful for debugging. 6384 outs() << "key: " << key << " value: " << val << "\n"; 6385 #endif 6386 if (strcmp(key, "name") == 0) 6387 member_name = val; 6388 if (strcmp(key, "type") == 0) 6389 member_type = val; 6390 if (strcmp(key, "data/size") == 0) 6391 member_size_string = val; 6392 } 6393 /* 6394 * If we find a file with a name, date/size and type properties 6395 * and with the type being "file" see if that is a xar file. 6396 */ 6397 if (member_name != NULL && member_type != NULL && 6398 strcmp(member_type, "file") == 0 && 6399 member_size_string != NULL){ 6400 // Extract the file into a buffer. 6401 char *endptr; 6402 member_size = strtoul(member_size_string, &endptr, 10); 6403 if (*endptr == '\0' && member_size != 0) { 6404 char *buffer; 6405 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { 6406 #if 0 // Useful for debugging. 6407 outs() << "xar member: " << member_name << " extracted\n"; 6408 #endif 6409 // Set the XarMemberName we want to see printed in the header. 6410 std::string OldXarMemberName; 6411 // If XarMemberName is already set this is nested. So 6412 // save the old name and create the nested name. 6413 if (!XarMemberName.empty()) { 6414 OldXarMemberName = XarMemberName; 6415 XarMemberName = 6416 (Twine("[") + XarMemberName + "]" + member_name).str(); 6417 } else { 6418 OldXarMemberName = ""; 6419 XarMemberName = member_name; 6420 } 6421 // See if this is could be a xar file (nested). 6422 if (member_size >= sizeof(struct xar_header)) { 6423 #if 0 // Useful for debugging. 6424 outs() << "could be a xar file: " << member_name << "\n"; 6425 #endif 6426 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); 6427 if (sys::IsLittleEndianHost) 6428 swapStruct(XarHeader); 6429 if (XarHeader.magic == XAR_HEADER_MAGIC) 6430 DumpBitcodeSection(O, buffer, member_size, verbose, 6431 PrintXarHeader, PrintXarFileHeaders, 6432 XarMemberName); 6433 } 6434 XarMemberName = OldXarMemberName; 6435 delete buffer; 6436 } 6437 } 6438 } 6439 } 6440 } 6441 #endif // defined(HAVE_LIBXAR) 6442 6443 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6444 if (O->is64Bit()) 6445 printObjc2_64bit_MetaData(O, verbose); 6446 else { 6447 MachO::mach_header H; 6448 H = O->getHeader(); 6449 if (H.cputype == MachO::CPU_TYPE_ARM) 6450 printObjc2_32bit_MetaData(O, verbose); 6451 else { 6452 // This is the 32-bit non-arm cputype case. Which is normally 6453 // the first Objective-C ABI. But it may be the case of a 6454 // binary for the iOS simulator which is the second Objective-C 6455 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6456 // and return false. 6457 if (!printObjc1_32bit_MetaData(O, verbose)) 6458 printObjc2_32bit_MetaData(O, verbose); 6459 } 6460 } 6461 } 6462 6463 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6464 // for the address passed in as ReferenceValue for printing as a comment with 6465 // the instruction and also returns the corresponding type of that item 6466 // indirectly through ReferenceType. 6467 // 6468 // If ReferenceValue is an address of literal cstring then a pointer to the 6469 // cstring is returned and ReferenceType is set to 6470 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6471 // 6472 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6473 // Class ref that name is returned and the ReferenceType is set accordingly. 6474 // 6475 // Lastly, literals which are Symbol address in a literal pool are looked for 6476 // and if found the symbol name is returned and ReferenceType is set to 6477 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6478 // 6479 // If there is no item in the Mach-O file for the address passed in as 6480 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6481 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6482 uint64_t ReferencePC, 6483 uint64_t *ReferenceType, 6484 struct DisassembleInfo *info) { 6485 // First see if there is an external relocation entry at the ReferencePC. 6486 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6487 uint64_t sect_addr = info->S.getAddress(); 6488 uint64_t sect_offset = ReferencePC - sect_addr; 6489 bool reloc_found = false; 6490 DataRefImpl Rel; 6491 MachO::any_relocation_info RE; 6492 bool isExtern = false; 6493 SymbolRef Symbol; 6494 for (const RelocationRef &Reloc : info->S.relocations()) { 6495 uint64_t RelocOffset = Reloc.getOffset(); 6496 if (RelocOffset == sect_offset) { 6497 Rel = Reloc.getRawDataRefImpl(); 6498 RE = info->O->getRelocation(Rel); 6499 if (info->O->isRelocationScattered(RE)) 6500 continue; 6501 isExtern = info->O->getPlainRelocationExternal(RE); 6502 if (isExtern) { 6503 symbol_iterator RelocSym = Reloc.getSymbol(); 6504 Symbol = *RelocSym; 6505 } 6506 reloc_found = true; 6507 break; 6508 } 6509 } 6510 // If there is an external relocation entry for a symbol in a section 6511 // then used that symbol's value for the value of the reference. 6512 if (reloc_found && isExtern) { 6513 if (info->O->getAnyRelocationPCRel(RE)) { 6514 unsigned Type = info->O->getAnyRelocationType(RE); 6515 if (Type == MachO::X86_64_RELOC_SIGNED) { 6516 ReferenceValue = Symbol.getValue(); 6517 } 6518 } 6519 } 6520 } 6521 6522 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6523 // Message refs and Class refs. 6524 bool classref, selref, msgref, cfstring; 6525 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6526 selref, msgref, cfstring); 6527 if (classref && pointer_value == 0) { 6528 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6529 // And the pointer_value in that section is typically zero as it will be 6530 // set by dyld as part of the "bind information". 6531 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6532 if (name != nullptr) { 6533 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6534 const char *class_name = strrchr(name, '$'); 6535 if (class_name != nullptr && class_name[1] == '_' && 6536 class_name[2] != '\0') { 6537 info->class_name = class_name + 2; 6538 return name; 6539 } 6540 } 6541 } 6542 6543 if (classref) { 6544 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6545 const char *name = 6546 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6547 if (name != nullptr) 6548 info->class_name = name; 6549 else 6550 name = "bad class ref"; 6551 return name; 6552 } 6553 6554 if (cfstring) { 6555 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6556 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6557 return name; 6558 } 6559 6560 if (selref && pointer_value == 0) 6561 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6562 6563 if (pointer_value != 0) 6564 ReferenceValue = pointer_value; 6565 6566 const char *name = GuessCstringPointer(ReferenceValue, info); 6567 if (name) { 6568 if (pointer_value != 0 && selref) { 6569 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6570 info->selector_name = name; 6571 } else if (pointer_value != 0 && msgref) { 6572 info->class_name = nullptr; 6573 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6574 info->selector_name = name; 6575 } else 6576 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6577 return name; 6578 } 6579 6580 // Lastly look for an indirect symbol with this ReferenceValue which is in 6581 // a literal pool. If found return that symbol name. 6582 name = GuessIndirectSymbol(ReferenceValue, info); 6583 if (name) { 6584 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6585 return name; 6586 } 6587 6588 return nullptr; 6589 } 6590 6591 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6592 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6593 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6594 // is created and returns the symbol name that matches the ReferenceValue or 6595 // nullptr if none. The ReferenceType is passed in for the IN type of 6596 // reference the instruction is making from the values in defined in the header 6597 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6598 // Out type and the ReferenceName will also be set which is added as a comment 6599 // to the disassembled instruction. 6600 // 6601 // If the symbol name is a C++ mangled name then the demangled name is 6602 // returned through ReferenceName and ReferenceType is set to 6603 // LLVMDisassembler_ReferenceType_DeMangled_Name . 6604 // 6605 // When this is called to get a symbol name for a branch target then the 6606 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 6607 // SymbolValue will be looked for in the indirect symbol table to determine if 6608 // it is an address for a symbol stub. If so then the symbol name for that 6609 // stub is returned indirectly through ReferenceName and then ReferenceType is 6610 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 6611 // 6612 // When this is called with an value loaded via a PC relative load then 6613 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 6614 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 6615 // or an Objective-C meta data reference. If so the output ReferenceType is 6616 // set to correspond to that as well as setting the ReferenceName. 6617 static const char *SymbolizerSymbolLookUp(void *DisInfo, 6618 uint64_t ReferenceValue, 6619 uint64_t *ReferenceType, 6620 uint64_t ReferencePC, 6621 const char **ReferenceName) { 6622 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 6623 // If no verbose symbolic information is wanted then just return nullptr. 6624 if (!info->verbose) { 6625 *ReferenceName = nullptr; 6626 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6627 return nullptr; 6628 } 6629 6630 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 6631 6632 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 6633 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 6634 if (*ReferenceName != nullptr) { 6635 method_reference(info, ReferenceType, ReferenceName); 6636 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 6637 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 6638 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6639 if (info->demangled_name != nullptr) 6640 free(info->demangled_name); 6641 int status; 6642 info->demangled_name = 6643 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6644 if (info->demangled_name != nullptr) { 6645 *ReferenceName = info->demangled_name; 6646 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6647 } else 6648 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6649 } else 6650 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6651 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 6652 *ReferenceName = 6653 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6654 if (*ReferenceName) 6655 method_reference(info, ReferenceType, ReferenceName); 6656 else 6657 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6658 // If this is arm64 and the reference is an adrp instruction save the 6659 // instruction, passed in ReferenceValue and the address of the instruction 6660 // for use later if we see and add immediate instruction. 6661 } else if (info->O->getArch() == Triple::aarch64 && 6662 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 6663 info->adrp_inst = ReferenceValue; 6664 info->adrp_addr = ReferencePC; 6665 SymbolName = nullptr; 6666 *ReferenceName = nullptr; 6667 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6668 // If this is arm64 and reference is an add immediate instruction and we 6669 // have 6670 // seen an adrp instruction just before it and the adrp's Xd register 6671 // matches 6672 // this add's Xn register reconstruct the value being referenced and look to 6673 // see if it is a literal pointer. Note the add immediate instruction is 6674 // passed in ReferenceValue. 6675 } else if (info->O->getArch() == Triple::aarch64 && 6676 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 6677 ReferencePC - 4 == info->adrp_addr && 6678 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6679 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6680 uint32_t addxri_inst; 6681 uint64_t adrp_imm, addxri_imm; 6682 6683 adrp_imm = 6684 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6685 if (info->adrp_inst & 0x0200000) 6686 adrp_imm |= 0xfffffffffc000000LL; 6687 6688 addxri_inst = ReferenceValue; 6689 addxri_imm = (addxri_inst >> 10) & 0xfff; 6690 if (((addxri_inst >> 22) & 0x3) == 1) 6691 addxri_imm <<= 12; 6692 6693 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6694 (adrp_imm << 12) + addxri_imm; 6695 6696 *ReferenceName = 6697 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6698 if (*ReferenceName == nullptr) 6699 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6700 // If this is arm64 and the reference is a load register instruction and we 6701 // have seen an adrp instruction just before it and the adrp's Xd register 6702 // matches this add's Xn register reconstruct the value being referenced and 6703 // look to see if it is a literal pointer. Note the load register 6704 // instruction is passed in ReferenceValue. 6705 } else if (info->O->getArch() == Triple::aarch64 && 6706 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 6707 ReferencePC - 4 == info->adrp_addr && 6708 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6709 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6710 uint32_t ldrxui_inst; 6711 uint64_t adrp_imm, ldrxui_imm; 6712 6713 adrp_imm = 6714 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6715 if (info->adrp_inst & 0x0200000) 6716 adrp_imm |= 0xfffffffffc000000LL; 6717 6718 ldrxui_inst = ReferenceValue; 6719 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 6720 6721 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6722 (adrp_imm << 12) + (ldrxui_imm << 3); 6723 6724 *ReferenceName = 6725 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6726 if (*ReferenceName == nullptr) 6727 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6728 } 6729 // If this arm64 and is an load register (PC-relative) instruction the 6730 // ReferenceValue is the PC plus the immediate value. 6731 else if (info->O->getArch() == Triple::aarch64 && 6732 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 6733 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 6734 *ReferenceName = 6735 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6736 if (*ReferenceName == nullptr) 6737 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6738 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6739 if (info->demangled_name != nullptr) 6740 free(info->demangled_name); 6741 int status; 6742 info->demangled_name = 6743 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6744 if (info->demangled_name != nullptr) { 6745 *ReferenceName = info->demangled_name; 6746 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6747 } 6748 } 6749 else { 6750 *ReferenceName = nullptr; 6751 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6752 } 6753 6754 return SymbolName; 6755 } 6756 6757 /// Emits the comments that are stored in the CommentStream. 6758 /// Each comment in the CommentStream must end with a newline. 6759 static void emitComments(raw_svector_ostream &CommentStream, 6760 SmallString<128> &CommentsToEmit, 6761 formatted_raw_ostream &FormattedOS, 6762 const MCAsmInfo &MAI) { 6763 // Flush the stream before taking its content. 6764 StringRef Comments = CommentsToEmit.str(); 6765 // Get the default information for printing a comment. 6766 StringRef CommentBegin = MAI.getCommentString(); 6767 unsigned CommentColumn = MAI.getCommentColumn(); 6768 bool IsFirst = true; 6769 while (!Comments.empty()) { 6770 if (!IsFirst) 6771 FormattedOS << '\n'; 6772 // Emit a line of comments. 6773 FormattedOS.PadToColumn(CommentColumn); 6774 size_t Position = Comments.find('\n'); 6775 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 6776 // Move after the newline character. 6777 Comments = Comments.substr(Position + 1); 6778 IsFirst = false; 6779 } 6780 FormattedOS.flush(); 6781 6782 // Tell the comment stream that the vector changed underneath it. 6783 CommentsToEmit.clear(); 6784 } 6785 6786 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 6787 StringRef DisSegName, StringRef DisSectName) { 6788 const char *McpuDefault = nullptr; 6789 const Target *ThumbTarget = nullptr; 6790 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 6791 if (!TheTarget) { 6792 // GetTarget prints out stuff. 6793 return; 6794 } 6795 std::string MachOMCPU; 6796 if (MCPU.empty() && McpuDefault) 6797 MachOMCPU = McpuDefault; 6798 else 6799 MachOMCPU = MCPU; 6800 6801 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 6802 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 6803 if (ThumbTarget) 6804 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 6805 6806 // Package up features to be passed to target/subtarget 6807 std::string FeaturesStr; 6808 if (MAttrs.size()) { 6809 SubtargetFeatures Features; 6810 for (unsigned i = 0; i != MAttrs.size(); ++i) 6811 Features.AddFeature(MAttrs[i]); 6812 FeaturesStr = Features.getString(); 6813 } 6814 6815 // Set up disassembler. 6816 std::unique_ptr<const MCRegisterInfo> MRI( 6817 TheTarget->createMCRegInfo(TripleName)); 6818 std::unique_ptr<const MCAsmInfo> AsmInfo( 6819 TheTarget->createMCAsmInfo(*MRI, TripleName)); 6820 std::unique_ptr<const MCSubtargetInfo> STI( 6821 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 6822 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 6823 std::unique_ptr<MCDisassembler> DisAsm( 6824 TheTarget->createMCDisassembler(*STI, Ctx)); 6825 std::unique_ptr<MCSymbolizer> Symbolizer; 6826 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false); 6827 std::unique_ptr<MCRelocationInfo> RelInfo( 6828 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 6829 if (RelInfo) { 6830 Symbolizer.reset(TheTarget->createMCSymbolizer( 6831 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6832 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 6833 DisAsm->setSymbolizer(std::move(Symbolizer)); 6834 } 6835 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 6836 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 6837 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 6838 // Set the display preference for hex vs. decimal immediates. 6839 IP->setPrintImmHex(PrintImmHex); 6840 // Comment stream and backing vector. 6841 SmallString<128> CommentsToEmit; 6842 raw_svector_ostream CommentStream(CommentsToEmit); 6843 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 6844 // if it is done then arm64 comments for string literals don't get printed 6845 // and some constant get printed instead and not setting it causes intel 6846 // (32-bit and 64-bit) comments printed with different spacing before the 6847 // comment causing different diffs with the 'C' disassembler library API. 6848 // IP->setCommentStream(CommentStream); 6849 6850 if (!AsmInfo || !STI || !DisAsm || !IP) { 6851 errs() << "error: couldn't initialize disassembler for target " 6852 << TripleName << '\n'; 6853 return; 6854 } 6855 6856 // Set up separate thumb disassembler if needed. 6857 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 6858 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 6859 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 6860 std::unique_ptr<MCDisassembler> ThumbDisAsm; 6861 std::unique_ptr<MCInstPrinter> ThumbIP; 6862 std::unique_ptr<MCContext> ThumbCtx; 6863 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 6864 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false); 6865 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 6866 if (ThumbTarget) { 6867 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 6868 ThumbAsmInfo.reset( 6869 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName)); 6870 ThumbSTI.reset( 6871 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 6872 FeaturesStr)); 6873 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 6874 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 6875 MCContext *PtrThumbCtx = ThumbCtx.get(); 6876 ThumbRelInfo.reset( 6877 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 6878 if (ThumbRelInfo) { 6879 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 6880 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6881 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 6882 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 6883 } 6884 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 6885 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 6886 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 6887 *ThumbInstrInfo, *ThumbMRI)); 6888 // Set the display preference for hex vs. decimal immediates. 6889 ThumbIP->setPrintImmHex(PrintImmHex); 6890 } 6891 6892 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) { 6893 errs() << "error: couldn't initialize disassembler for target " 6894 << ThumbTripleName << '\n'; 6895 return; 6896 } 6897 6898 MachO::mach_header Header = MachOOF->getHeader(); 6899 6900 // FIXME: Using the -cfg command line option, this code used to be able to 6901 // annotate relocations with the referenced symbol's name, and if this was 6902 // inside a __[cf]string section, the data it points to. This is now replaced 6903 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 6904 std::vector<SectionRef> Sections; 6905 std::vector<SymbolRef> Symbols; 6906 SmallVector<uint64_t, 8> FoundFns; 6907 uint64_t BaseSegmentAddress; 6908 6909 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 6910 BaseSegmentAddress); 6911 6912 // Sort the symbols by address, just in case they didn't come in that way. 6913 llvm::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); 6914 6915 // Build a data in code table that is sorted on by the address of each entry. 6916 uint64_t BaseAddress = 0; 6917 if (Header.filetype == MachO::MH_OBJECT) 6918 BaseAddress = Sections[0].getAddress(); 6919 else 6920 BaseAddress = BaseSegmentAddress; 6921 DiceTable Dices; 6922 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 6923 DI != DE; ++DI) { 6924 uint32_t Offset; 6925 DI->getOffset(Offset); 6926 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 6927 } 6928 array_pod_sort(Dices.begin(), Dices.end()); 6929 6930 #ifndef NDEBUG 6931 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); 6932 #else 6933 raw_ostream &DebugOut = nulls(); 6934 #endif 6935 6936 std::unique_ptr<DIContext> diContext; 6937 ObjectFile *DbgObj = MachOOF; 6938 // Try to find debug info and set up the DIContext for it. 6939 if (UseDbg) { 6940 // A separate DSym file path was specified, parse it as a macho file, 6941 // get the sections and supply it to the section name parsing machinery. 6942 if (!DSYMFile.empty()) { 6943 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 6944 MemoryBuffer::getFileOrSTDIN(DSYMFile); 6945 if (std::error_code EC = BufOrErr.getError()) { 6946 errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n'; 6947 return; 6948 } 6949 Expected<std::unique_ptr<MachOObjectFile>> DbgObjCheck = 6950 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()); 6951 6952 if (DbgObjCheck.takeError()) 6953 report_error(MachOOF->getFileName(), DbgObjCheck.takeError()); 6954 DbgObj = DbgObjCheck.get().release(); 6955 } 6956 6957 // Setup the DIContext 6958 diContext = DWARFContext::create(*DbgObj); 6959 } 6960 6961 if (FilterSections.size() == 0) 6962 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 6963 6964 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 6965 StringRef SectName; 6966 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName) 6967 continue; 6968 6969 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 6970 6971 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 6972 if (SegmentName != DisSegName) 6973 continue; 6974 6975 StringRef BytesStr; 6976 Sections[SectIdx].getContents(BytesStr); 6977 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()), 6978 BytesStr.size()); 6979 uint64_t SectAddress = Sections[SectIdx].getAddress(); 6980 6981 bool symbolTableWorked = false; 6982 6983 // Create a map of symbol addresses to symbol names for use by 6984 // the SymbolizerSymbolLookUp() routine. 6985 SymbolAddressMap AddrMap; 6986 bool DisSymNameFound = false; 6987 for (const SymbolRef &Symbol : MachOOF->symbols()) { 6988 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 6989 if (!STOrErr) 6990 report_error(MachOOF->getFileName(), STOrErr.takeError()); 6991 SymbolRef::Type ST = *STOrErr; 6992 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 6993 ST == SymbolRef::ST_Other) { 6994 uint64_t Address = Symbol.getValue(); 6995 Expected<StringRef> SymNameOrErr = Symbol.getName(); 6996 if (!SymNameOrErr) 6997 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 6998 StringRef SymName = *SymNameOrErr; 6999 AddrMap[Address] = SymName; 7000 if (!DisSymName.empty() && DisSymName == SymName) 7001 DisSymNameFound = true; 7002 } 7003 } 7004 if (!DisSymName.empty() && !DisSymNameFound) { 7005 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 7006 return; 7007 } 7008 // Set up the block of info used by the Symbolizer call backs. 7009 SymbolizerInfo.verbose = !NoSymbolicOperands; 7010 SymbolizerInfo.O = MachOOF; 7011 SymbolizerInfo.S = Sections[SectIdx]; 7012 SymbolizerInfo.AddrMap = &AddrMap; 7013 SymbolizerInfo.Sections = &Sections; 7014 // Same for the ThumbSymbolizer 7015 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands; 7016 ThumbSymbolizerInfo.O = MachOOF; 7017 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7018 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7019 ThumbSymbolizerInfo.Sections = &Sections; 7020 7021 unsigned int Arch = MachOOF->getArch(); 7022 7023 // Skip all symbols if this is a stubs file. 7024 if (Bytes.size() == 0) 7025 return; 7026 7027 // If the section has symbols but no symbol at the start of the section 7028 // these are used to make sure the bytes before the first symbol are 7029 // disassembled. 7030 bool FirstSymbol = true; 7031 bool FirstSymbolAtSectionStart = true; 7032 7033 // Disassemble symbol by symbol. 7034 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7035 Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName(); 7036 if (!SymNameOrErr) 7037 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 7038 StringRef SymName = *SymNameOrErr; 7039 7040 Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType(); 7041 if (!STOrErr) 7042 report_error(MachOOF->getFileName(), STOrErr.takeError()); 7043 SymbolRef::Type ST = *STOrErr; 7044 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7045 continue; 7046 7047 // Make sure the symbol is defined in this section. 7048 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7049 if (!containsSym) { 7050 if (!DisSymName.empty() && DisSymName == SymName) { 7051 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7052 return; 7053 } 7054 continue; 7055 } 7056 // The __mh_execute_header is special and we need to deal with that fact 7057 // this symbol is before the start of the (__TEXT,__text) section and at the 7058 // address of the start of the __TEXT segment. This is because this symbol 7059 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7060 // start of the section in a standard MH_EXECUTE filetype. 7061 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7062 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7063 return; 7064 } 7065 // When this code is trying to disassemble a symbol at a time and in the 7066 // case there is only the __mh_execute_header symbol left as in a stripped 7067 // executable, we need to deal with this by ignoring this symbol so the 7068 // whole section is disassembled and this symbol is then not displayed. 7069 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7070 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7071 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7072 continue; 7073 7074 // If we are only disassembling one symbol see if this is that symbol. 7075 if (!DisSymName.empty() && DisSymName != SymName) 7076 continue; 7077 7078 // Start at the address of the symbol relative to the section's address. 7079 uint64_t SectSize = Sections[SectIdx].getSize(); 7080 uint64_t Start = Symbols[SymIdx].getValue(); 7081 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7082 Start -= SectionAddress; 7083 7084 if (Start > SectSize) { 7085 outs() << "section data ends, " << SymName 7086 << " lies outside valid range\n"; 7087 return; 7088 } 7089 7090 // Stop disassembling either at the beginning of the next symbol or at 7091 // the end of the section. 7092 bool containsNextSym = false; 7093 uint64_t NextSym = 0; 7094 uint64_t NextSymIdx = SymIdx + 1; 7095 while (Symbols.size() > NextSymIdx) { 7096 Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType(); 7097 if (!STOrErr) 7098 report_error(MachOOF->getFileName(), STOrErr.takeError()); 7099 SymbolRef::Type NextSymType = *STOrErr; 7100 if (NextSymType == SymbolRef::ST_Function) { 7101 containsNextSym = 7102 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7103 NextSym = Symbols[NextSymIdx].getValue(); 7104 NextSym -= SectionAddress; 7105 break; 7106 } 7107 ++NextSymIdx; 7108 } 7109 7110 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7111 uint64_t Size; 7112 7113 symbolTableWorked = true; 7114 7115 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7116 bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb; 7117 7118 // We only need the dedicated Thumb target if there's a real choice 7119 // (i.e. we're not targeting M-class) and the function is Thumb. 7120 bool UseThumbTarget = IsThumb && ThumbTarget; 7121 7122 // If we are not specifying a symbol to start disassembly with and this 7123 // is the first symbol in the section but not at the start of the section 7124 // then move the disassembly index to the start of the section and 7125 // don't print the symbol name just yet. This is so the bytes before the 7126 // first symbol are disassembled. 7127 uint64_t SymbolStart = Start; 7128 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7129 FirstSymbolAtSectionStart = false; 7130 Start = 0; 7131 } 7132 else 7133 outs() << SymName << ":\n"; 7134 7135 DILineInfo lastLine; 7136 for (uint64_t Index = Start; Index < End; Index += Size) { 7137 MCInst Inst; 7138 7139 // If this is the first symbol in the section and it was not at the 7140 // start of the section, see if we are at its Index now and if so print 7141 // the symbol name. 7142 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7143 outs() << SymName << ":\n"; 7144 7145 uint64_t PC = SectAddress + Index; 7146 if (!NoLeadingAddr) { 7147 if (FullLeadingAddr) { 7148 if (MachOOF->is64Bit()) 7149 outs() << format("%016" PRIx64, PC); 7150 else 7151 outs() << format("%08" PRIx64, PC); 7152 } else { 7153 outs() << format("%8" PRIx64 ":", PC); 7154 } 7155 } 7156 if (!NoShowRawInsn || Arch == Triple::arm) 7157 outs() << "\t"; 7158 7159 // Check the data in code table here to see if this is data not an 7160 // instruction to be disassembled. 7161 DiceTable Dice; 7162 Dice.push_back(std::make_pair(PC, DiceRef())); 7163 dice_table_iterator DTI = 7164 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 7165 compareDiceTableEntries); 7166 if (DTI != Dices.end()) { 7167 uint16_t Length; 7168 DTI->second.getLength(Length); 7169 uint16_t Kind; 7170 DTI->second.getKind(Kind); 7171 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind); 7172 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 7173 (PC == (DTI->first + Length - 1)) && (Length & 1)) 7174 Size++; 7175 continue; 7176 } 7177 7178 SmallVector<char, 64> AnnotationsBytes; 7179 raw_svector_ostream Annotations(AnnotationsBytes); 7180 7181 bool gotInst; 7182 if (UseThumbTarget) 7183 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7184 PC, DebugOut, Annotations); 7185 else 7186 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7187 DebugOut, Annotations); 7188 if (gotInst) { 7189 if (!NoShowRawInsn || Arch == Triple::arm) { 7190 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); 7191 } 7192 formatted_raw_ostream FormattedOS(outs()); 7193 StringRef AnnotationsStr = Annotations.str(); 7194 if (UseThumbTarget) 7195 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI); 7196 else 7197 IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI); 7198 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7199 7200 // Print debug info. 7201 if (diContext) { 7202 DILineInfo dli = diContext->getLineInfoForAddress(PC); 7203 // Print valid line info if it changed. 7204 if (dli != lastLine && dli.Line != 0) 7205 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7206 << dli.Column; 7207 lastLine = dli; 7208 } 7209 outs() << "\n"; 7210 } else { 7211 unsigned int Arch = MachOOF->getArch(); 7212 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7213 outs() << format("\t.byte 0x%02x #bad opcode\n", 7214 *(Bytes.data() + Index) & 0xff); 7215 Size = 1; // skip exactly one illegible byte and move on. 7216 } else if (Arch == Triple::aarch64 || 7217 (Arch == Triple::arm && !IsThumb)) { 7218 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7219 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7220 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7221 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7222 outs() << format("\t.long\t0x%08x\n", opcode); 7223 Size = 4; 7224 } else if (Arch == Triple::arm) { 7225 assert(IsThumb && "ARM mode should have been dealt with above"); 7226 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7227 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7228 outs() << format("\t.short\t0x%04x\n", opcode); 7229 Size = 2; 7230 } else{ 7231 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 7232 if (Size == 0) 7233 Size = 1; // skip illegible bytes 7234 } 7235 } 7236 } 7237 // Now that we are done disassembled the first symbol set the bool that 7238 // were doing this to false. 7239 FirstSymbol = false; 7240 } 7241 if (!symbolTableWorked) { 7242 // Reading the symbol table didn't work, disassemble the whole section. 7243 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7244 uint64_t SectSize = Sections[SectIdx].getSize(); 7245 uint64_t InstSize; 7246 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7247 MCInst Inst; 7248 7249 uint64_t PC = SectAddress + Index; 7250 SmallVector<char, 64> AnnotationsBytes; 7251 raw_svector_ostream Annotations(AnnotationsBytes); 7252 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7253 DebugOut, Annotations)) { 7254 if (!NoLeadingAddr) { 7255 if (FullLeadingAddr) { 7256 if (MachOOF->is64Bit()) 7257 outs() << format("%016" PRIx64, PC); 7258 else 7259 outs() << format("%08" PRIx64, PC); 7260 } else { 7261 outs() << format("%8" PRIx64 ":", PC); 7262 } 7263 } 7264 if (!NoShowRawInsn || Arch == Triple::arm) { 7265 outs() << "\t"; 7266 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); 7267 } 7268 StringRef AnnotationsStr = Annotations.str(); 7269 IP->printInst(&Inst, outs(), AnnotationsStr, *STI); 7270 outs() << "\n"; 7271 } else { 7272 unsigned int Arch = MachOOF->getArch(); 7273 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7274 outs() << format("\t.byte 0x%02x #bad opcode\n", 7275 *(Bytes.data() + Index) & 0xff); 7276 InstSize = 1; // skip exactly one illegible byte and move on. 7277 } else { 7278 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 7279 if (InstSize == 0) 7280 InstSize = 1; // skip illegible bytes 7281 } 7282 } 7283 } 7284 } 7285 // The TripleName's need to be reset if we are called again for a different 7286 // archtecture. 7287 TripleName = ""; 7288 ThumbTripleName = ""; 7289 7290 if (SymbolizerInfo.demangled_name != nullptr) 7291 free(SymbolizerInfo.demangled_name); 7292 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7293 free(ThumbSymbolizerInfo.demangled_name); 7294 } 7295 } 7296 7297 //===----------------------------------------------------------------------===// 7298 // __compact_unwind section dumping 7299 //===----------------------------------------------------------------------===// 7300 7301 namespace { 7302 7303 template <typename T> 7304 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7305 using llvm::support::little; 7306 using llvm::support::unaligned; 7307 7308 if (Offset + sizeof(T) > Contents.size()) { 7309 outs() << "warning: attempt to read past end of buffer\n"; 7310 return T(); 7311 } 7312 7313 uint64_t Val = 7314 support::endian::read<T, little, unaligned>(Contents.data() + Offset); 7315 return Val; 7316 } 7317 7318 template <typename T> 7319 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7320 T Val = read<T>(Contents, Offset); 7321 Offset += sizeof(T); 7322 return Val; 7323 } 7324 7325 struct CompactUnwindEntry { 7326 uint32_t OffsetInSection; 7327 7328 uint64_t FunctionAddr; 7329 uint32_t Length; 7330 uint32_t CompactEncoding; 7331 uint64_t PersonalityAddr; 7332 uint64_t LSDAAddr; 7333 7334 RelocationRef FunctionReloc; 7335 RelocationRef PersonalityReloc; 7336 RelocationRef LSDAReloc; 7337 7338 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7339 : OffsetInSection(Offset) { 7340 if (Is64) 7341 read<uint64_t>(Contents, Offset); 7342 else 7343 read<uint32_t>(Contents, Offset); 7344 } 7345 7346 private: 7347 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7348 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7349 Length = readNext<uint32_t>(Contents, Offset); 7350 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7351 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7352 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7353 } 7354 }; 7355 } 7356 7357 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7358 /// and data being relocated, determine the best base Name and Addend to use for 7359 /// display purposes. 7360 /// 7361 /// 1. An Extern relocation will directly reference a symbol (and the data is 7362 /// then already an addend), so use that. 7363 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7364 // a symbol before it in the same section, and use the offset from there. 7365 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7366 /// referenced section. 7367 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7368 std::map<uint64_t, SymbolRef> &Symbols, 7369 const RelocationRef &Reloc, uint64_t Addr, 7370 StringRef &Name, uint64_t &Addend) { 7371 if (Reloc.getSymbol() != Obj->symbol_end()) { 7372 Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName(); 7373 if (!NameOrErr) 7374 report_error(Obj->getFileName(), NameOrErr.takeError()); 7375 Name = *NameOrErr; 7376 Addend = Addr; 7377 return; 7378 } 7379 7380 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7381 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7382 7383 uint64_t SectionAddr = RelocSection.getAddress(); 7384 7385 auto Sym = Symbols.upper_bound(Addr); 7386 if (Sym == Symbols.begin()) { 7387 // The first symbol in the object is after this reference, the best we can 7388 // do is section-relative notation. 7389 RelocSection.getName(Name); 7390 Addend = Addr - SectionAddr; 7391 return; 7392 } 7393 7394 // Go back one so that SymbolAddress <= Addr. 7395 --Sym; 7396 7397 auto SectOrErr = Sym->second.getSection(); 7398 if (!SectOrErr) 7399 report_error(Obj->getFileName(), SectOrErr.takeError()); 7400 section_iterator SymSection = *SectOrErr; 7401 if (RelocSection == *SymSection) { 7402 // There's a valid symbol in the same section before this reference. 7403 Expected<StringRef> NameOrErr = Sym->second.getName(); 7404 if (!NameOrErr) 7405 report_error(Obj->getFileName(), NameOrErr.takeError()); 7406 Name = *NameOrErr; 7407 Addend = Addr - Sym->first; 7408 return; 7409 } 7410 7411 // There is a symbol before this reference, but it's in a different 7412 // section. Probably not helpful to mention it, so use the section name. 7413 RelocSection.getName(Name); 7414 Addend = Addr - SectionAddr; 7415 } 7416 7417 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7418 std::map<uint64_t, SymbolRef> &Symbols, 7419 const RelocationRef &Reloc, uint64_t Addr) { 7420 StringRef Name; 7421 uint64_t Addend; 7422 7423 if (!Reloc.getObject()) 7424 return; 7425 7426 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7427 7428 outs() << Name; 7429 if (Addend) 7430 outs() << " + " << format("0x%" PRIx64, Addend); 7431 } 7432 7433 static void 7434 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7435 std::map<uint64_t, SymbolRef> &Symbols, 7436 const SectionRef &CompactUnwind) { 7437 7438 if (!Obj->isLittleEndian()) { 7439 outs() << "Skipping big-endian __compact_unwind section\n"; 7440 return; 7441 } 7442 7443 bool Is64 = Obj->is64Bit(); 7444 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7445 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7446 7447 StringRef Contents; 7448 CompactUnwind.getContents(Contents); 7449 7450 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7451 7452 // First populate the initial raw offsets, encodings and so on from the entry. 7453 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7454 CompactUnwindEntry Entry(Contents, Offset, Is64); 7455 CompactUnwinds.push_back(Entry); 7456 } 7457 7458 // Next we need to look at the relocations to find out what objects are 7459 // actually being referred to. 7460 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7461 uint64_t RelocAddress = Reloc.getOffset(); 7462 7463 uint32_t EntryIdx = RelocAddress / EntrySize; 7464 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7465 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7466 7467 if (OffsetInEntry == 0) 7468 Entry.FunctionReloc = Reloc; 7469 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7470 Entry.PersonalityReloc = Reloc; 7471 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7472 Entry.LSDAReloc = Reloc; 7473 else { 7474 outs() << "Invalid relocation in __compact_unwind section\n"; 7475 return; 7476 } 7477 } 7478 7479 // Finally, we're ready to print the data we've gathered. 7480 outs() << "Contents of __compact_unwind section:\n"; 7481 for (auto &Entry : CompactUnwinds) { 7482 outs() << " Entry at offset " 7483 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7484 7485 // 1. Start of the region this entry applies to. 7486 outs() << " start: " << format("0x%" PRIx64, 7487 Entry.FunctionAddr) << ' '; 7488 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7489 outs() << '\n'; 7490 7491 // 2. Length of the region this entry applies to. 7492 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7493 << '\n'; 7494 // 3. The 32-bit compact encoding. 7495 outs() << " compact encoding: " 7496 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7497 7498 // 4. The personality function, if present. 7499 if (Entry.PersonalityReloc.getObject()) { 7500 outs() << " personality function: " 7501 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7502 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7503 Entry.PersonalityAddr); 7504 outs() << '\n'; 7505 } 7506 7507 // 5. This entry's language-specific data area. 7508 if (Entry.LSDAReloc.getObject()) { 7509 outs() << " LSDA: " << format("0x%" PRIx64, 7510 Entry.LSDAAddr) << ' '; 7511 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7512 outs() << '\n'; 7513 } 7514 } 7515 } 7516 7517 //===----------------------------------------------------------------------===// 7518 // __unwind_info section dumping 7519 //===----------------------------------------------------------------------===// 7520 7521 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 7522 ptrdiff_t Pos = 0; 7523 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7524 (void)Kind; 7525 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7526 7527 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7528 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7529 7530 Pos = EntriesStart; 7531 for (unsigned i = 0; i < NumEntries; ++i) { 7532 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 7533 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7534 7535 outs() << " [" << i << "]: " 7536 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7537 << ", " 7538 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7539 } 7540 } 7541 7542 static void printCompressedSecondLevelUnwindPage( 7543 StringRef PageData, uint32_t FunctionBase, 7544 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7545 ptrdiff_t Pos = 0; 7546 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7547 (void)Kind; 7548 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 7549 7550 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7551 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7552 7553 uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos); 7554 readNext<uint16_t>(PageData, Pos); 7555 StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos); 7556 7557 Pos = EntriesStart; 7558 for (unsigned i = 0; i < NumEntries; ++i) { 7559 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 7560 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 7561 uint32_t EncodingIdx = Entry >> 24; 7562 7563 uint32_t Encoding; 7564 if (EncodingIdx < CommonEncodings.size()) 7565 Encoding = CommonEncodings[EncodingIdx]; 7566 else 7567 Encoding = read<uint32_t>(PageEncodings, 7568 sizeof(uint32_t) * 7569 (EncodingIdx - CommonEncodings.size())); 7570 7571 outs() << " [" << i << "]: " 7572 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7573 << ", " 7574 << "encoding[" << EncodingIdx 7575 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 7576 } 7577 } 7578 7579 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 7580 std::map<uint64_t, SymbolRef> &Symbols, 7581 const SectionRef &UnwindInfo) { 7582 7583 if (!Obj->isLittleEndian()) { 7584 outs() << "Skipping big-endian __unwind_info section\n"; 7585 return; 7586 } 7587 7588 outs() << "Contents of __unwind_info section:\n"; 7589 7590 StringRef Contents; 7591 UnwindInfo.getContents(Contents); 7592 ptrdiff_t Pos = 0; 7593 7594 //===---------------------------------- 7595 // Section header 7596 //===---------------------------------- 7597 7598 uint32_t Version = readNext<uint32_t>(Contents, Pos); 7599 outs() << " Version: " 7600 << format("0x%" PRIx32, Version) << '\n'; 7601 if (Version != 1) { 7602 outs() << " Skipping section with unknown version\n"; 7603 return; 7604 } 7605 7606 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 7607 outs() << " Common encodings array section offset: " 7608 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 7609 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 7610 outs() << " Number of common encodings in array: " 7611 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 7612 7613 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 7614 outs() << " Personality function array section offset: " 7615 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 7616 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 7617 outs() << " Number of personality functions in array: " 7618 << format("0x%" PRIx32, NumPersonalities) << '\n'; 7619 7620 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 7621 outs() << " Index array section offset: " 7622 << format("0x%" PRIx32, IndicesStart) << '\n'; 7623 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 7624 outs() << " Number of indices in array: " 7625 << format("0x%" PRIx32, NumIndices) << '\n'; 7626 7627 //===---------------------------------- 7628 // A shared list of common encodings 7629 //===---------------------------------- 7630 7631 // These occupy indices in the range [0, N] whenever an encoding is referenced 7632 // from a compressed 2nd level index table. In practice the linker only 7633 // creates ~128 of these, so that indices are available to embed encodings in 7634 // the 2nd level index. 7635 7636 SmallVector<uint32_t, 64> CommonEncodings; 7637 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 7638 Pos = CommonEncodingsStart; 7639 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 7640 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 7641 CommonEncodings.push_back(Encoding); 7642 7643 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 7644 << '\n'; 7645 } 7646 7647 //===---------------------------------- 7648 // Personality functions used in this executable 7649 //===---------------------------------- 7650 7651 // There should be only a handful of these (one per source language, 7652 // roughly). Particularly since they only get 2 bits in the compact encoding. 7653 7654 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 7655 Pos = PersonalitiesStart; 7656 for (unsigned i = 0; i < NumPersonalities; ++i) { 7657 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 7658 outs() << " personality[" << i + 1 7659 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 7660 } 7661 7662 //===---------------------------------- 7663 // The level 1 index entries 7664 //===---------------------------------- 7665 7666 // These specify an approximate place to start searching for the more detailed 7667 // information, sorted by PC. 7668 7669 struct IndexEntry { 7670 uint32_t FunctionOffset; 7671 uint32_t SecondLevelPageStart; 7672 uint32_t LSDAStart; 7673 }; 7674 7675 SmallVector<IndexEntry, 4> IndexEntries; 7676 7677 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 7678 Pos = IndicesStart; 7679 for (unsigned i = 0; i < NumIndices; ++i) { 7680 IndexEntry Entry; 7681 7682 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 7683 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 7684 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 7685 IndexEntries.push_back(Entry); 7686 7687 outs() << " [" << i << "]: " 7688 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 7689 << ", " 7690 << "2nd level page offset=" 7691 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 7692 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 7693 } 7694 7695 //===---------------------------------- 7696 // Next come the LSDA tables 7697 //===---------------------------------- 7698 7699 // The LSDA layout is rather implicit: it's a contiguous array of entries from 7700 // the first top-level index's LSDAOffset to the last (sentinel). 7701 7702 outs() << " LSDA descriptors:\n"; 7703 Pos = IndexEntries[0].LSDAStart; 7704 const uint32_t LSDASize = 2 * sizeof(uint32_t); 7705 int NumLSDAs = 7706 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 7707 7708 for (int i = 0; i < NumLSDAs; ++i) { 7709 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 7710 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 7711 outs() << " [" << i << "]: " 7712 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7713 << ", " 7714 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 7715 } 7716 7717 //===---------------------------------- 7718 // Finally, the 2nd level indices 7719 //===---------------------------------- 7720 7721 // Generally these are 4K in size, and have 2 possible forms: 7722 // + Regular stores up to 511 entries with disparate encodings 7723 // + Compressed stores up to 1021 entries if few enough compact encoding 7724 // values are used. 7725 outs() << " Second level indices:\n"; 7726 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 7727 // The final sentinel top-level index has no associated 2nd level page 7728 if (IndexEntries[i].SecondLevelPageStart == 0) 7729 break; 7730 7731 outs() << " Second level index[" << i << "]: " 7732 << "offset in section=" 7733 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 7734 << ", " 7735 << "base function offset=" 7736 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 7737 7738 Pos = IndexEntries[i].SecondLevelPageStart; 7739 if (Pos + sizeof(uint32_t) > Contents.size()) { 7740 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 7741 continue; 7742 } 7743 7744 uint32_t Kind = 7745 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 7746 if (Kind == 2) 7747 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 7748 else if (Kind == 3) 7749 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 7750 IndexEntries[i].FunctionOffset, 7751 CommonEncodings); 7752 else 7753 outs() << " Skipping 2nd level page with unknown kind " << Kind 7754 << '\n'; 7755 } 7756 } 7757 7758 void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { 7759 std::map<uint64_t, SymbolRef> Symbols; 7760 for (const SymbolRef &SymRef : Obj->symbols()) { 7761 // Discard any undefined or absolute symbols. They're not going to take part 7762 // in the convenience lookup for unwind info and just take up resources. 7763 auto SectOrErr = SymRef.getSection(); 7764 if (!SectOrErr) { 7765 // TODO: Actually report errors helpfully. 7766 consumeError(SectOrErr.takeError()); 7767 continue; 7768 } 7769 section_iterator Section = *SectOrErr; 7770 if (Section == Obj->section_end()) 7771 continue; 7772 7773 uint64_t Addr = SymRef.getValue(); 7774 Symbols.insert(std::make_pair(Addr, SymRef)); 7775 } 7776 7777 for (const SectionRef &Section : Obj->sections()) { 7778 StringRef SectName; 7779 Section.getName(SectName); 7780 if (SectName == "__compact_unwind") 7781 printMachOCompactUnwindSection(Obj, Symbols, Section); 7782 else if (SectName == "__unwind_info") 7783 printMachOUnwindInfoSection(Obj, Symbols, Section); 7784 } 7785 } 7786 7787 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 7788 uint32_t cpusubtype, uint32_t filetype, 7789 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 7790 bool verbose) { 7791 outs() << "Mach header\n"; 7792 outs() << " magic cputype cpusubtype caps filetype ncmds " 7793 "sizeofcmds flags\n"; 7794 if (verbose) { 7795 if (magic == MachO::MH_MAGIC) 7796 outs() << " MH_MAGIC"; 7797 else if (magic == MachO::MH_MAGIC_64) 7798 outs() << "MH_MAGIC_64"; 7799 else 7800 outs() << format(" 0x%08" PRIx32, magic); 7801 switch (cputype) { 7802 case MachO::CPU_TYPE_I386: 7803 outs() << " I386"; 7804 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7805 case MachO::CPU_SUBTYPE_I386_ALL: 7806 outs() << " ALL"; 7807 break; 7808 default: 7809 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7810 break; 7811 } 7812 break; 7813 case MachO::CPU_TYPE_X86_64: 7814 outs() << " X86_64"; 7815 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7816 case MachO::CPU_SUBTYPE_X86_64_ALL: 7817 outs() << " ALL"; 7818 break; 7819 case MachO::CPU_SUBTYPE_X86_64_H: 7820 outs() << " Haswell"; 7821 break; 7822 default: 7823 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7824 break; 7825 } 7826 break; 7827 case MachO::CPU_TYPE_ARM: 7828 outs() << " ARM"; 7829 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7830 case MachO::CPU_SUBTYPE_ARM_ALL: 7831 outs() << " ALL"; 7832 break; 7833 case MachO::CPU_SUBTYPE_ARM_V4T: 7834 outs() << " V4T"; 7835 break; 7836 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 7837 outs() << " V5TEJ"; 7838 break; 7839 case MachO::CPU_SUBTYPE_ARM_XSCALE: 7840 outs() << " XSCALE"; 7841 break; 7842 case MachO::CPU_SUBTYPE_ARM_V6: 7843 outs() << " V6"; 7844 break; 7845 case MachO::CPU_SUBTYPE_ARM_V6M: 7846 outs() << " V6M"; 7847 break; 7848 case MachO::CPU_SUBTYPE_ARM_V7: 7849 outs() << " V7"; 7850 break; 7851 case MachO::CPU_SUBTYPE_ARM_V7EM: 7852 outs() << " V7EM"; 7853 break; 7854 case MachO::CPU_SUBTYPE_ARM_V7K: 7855 outs() << " V7K"; 7856 break; 7857 case MachO::CPU_SUBTYPE_ARM_V7M: 7858 outs() << " V7M"; 7859 break; 7860 case MachO::CPU_SUBTYPE_ARM_V7S: 7861 outs() << " V7S"; 7862 break; 7863 default: 7864 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7865 break; 7866 } 7867 break; 7868 case MachO::CPU_TYPE_ARM64: 7869 outs() << " ARM64"; 7870 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7871 case MachO::CPU_SUBTYPE_ARM64_ALL: 7872 outs() << " ALL"; 7873 break; 7874 default: 7875 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7876 break; 7877 } 7878 break; 7879 case MachO::CPU_TYPE_POWERPC: 7880 outs() << " PPC"; 7881 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7882 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7883 outs() << " ALL"; 7884 break; 7885 default: 7886 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7887 break; 7888 } 7889 break; 7890 case MachO::CPU_TYPE_POWERPC64: 7891 outs() << " PPC64"; 7892 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7893 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7894 outs() << " ALL"; 7895 break; 7896 default: 7897 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7898 break; 7899 } 7900 break; 7901 default: 7902 outs() << format(" %7d", cputype); 7903 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7904 break; 7905 } 7906 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 7907 outs() << " LIB64"; 7908 } else { 7909 outs() << format(" 0x%02" PRIx32, 7910 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 7911 } 7912 switch (filetype) { 7913 case MachO::MH_OBJECT: 7914 outs() << " OBJECT"; 7915 break; 7916 case MachO::MH_EXECUTE: 7917 outs() << " EXECUTE"; 7918 break; 7919 case MachO::MH_FVMLIB: 7920 outs() << " FVMLIB"; 7921 break; 7922 case MachO::MH_CORE: 7923 outs() << " CORE"; 7924 break; 7925 case MachO::MH_PRELOAD: 7926 outs() << " PRELOAD"; 7927 break; 7928 case MachO::MH_DYLIB: 7929 outs() << " DYLIB"; 7930 break; 7931 case MachO::MH_DYLIB_STUB: 7932 outs() << " DYLIB_STUB"; 7933 break; 7934 case MachO::MH_DYLINKER: 7935 outs() << " DYLINKER"; 7936 break; 7937 case MachO::MH_BUNDLE: 7938 outs() << " BUNDLE"; 7939 break; 7940 case MachO::MH_DSYM: 7941 outs() << " DSYM"; 7942 break; 7943 case MachO::MH_KEXT_BUNDLE: 7944 outs() << " KEXTBUNDLE"; 7945 break; 7946 default: 7947 outs() << format(" %10u", filetype); 7948 break; 7949 } 7950 outs() << format(" %5u", ncmds); 7951 outs() << format(" %10u", sizeofcmds); 7952 uint32_t f = flags; 7953 if (f & MachO::MH_NOUNDEFS) { 7954 outs() << " NOUNDEFS"; 7955 f &= ~MachO::MH_NOUNDEFS; 7956 } 7957 if (f & MachO::MH_INCRLINK) { 7958 outs() << " INCRLINK"; 7959 f &= ~MachO::MH_INCRLINK; 7960 } 7961 if (f & MachO::MH_DYLDLINK) { 7962 outs() << " DYLDLINK"; 7963 f &= ~MachO::MH_DYLDLINK; 7964 } 7965 if (f & MachO::MH_BINDATLOAD) { 7966 outs() << " BINDATLOAD"; 7967 f &= ~MachO::MH_BINDATLOAD; 7968 } 7969 if (f & MachO::MH_PREBOUND) { 7970 outs() << " PREBOUND"; 7971 f &= ~MachO::MH_PREBOUND; 7972 } 7973 if (f & MachO::MH_SPLIT_SEGS) { 7974 outs() << " SPLIT_SEGS"; 7975 f &= ~MachO::MH_SPLIT_SEGS; 7976 } 7977 if (f & MachO::MH_LAZY_INIT) { 7978 outs() << " LAZY_INIT"; 7979 f &= ~MachO::MH_LAZY_INIT; 7980 } 7981 if (f & MachO::MH_TWOLEVEL) { 7982 outs() << " TWOLEVEL"; 7983 f &= ~MachO::MH_TWOLEVEL; 7984 } 7985 if (f & MachO::MH_FORCE_FLAT) { 7986 outs() << " FORCE_FLAT"; 7987 f &= ~MachO::MH_FORCE_FLAT; 7988 } 7989 if (f & MachO::MH_NOMULTIDEFS) { 7990 outs() << " NOMULTIDEFS"; 7991 f &= ~MachO::MH_NOMULTIDEFS; 7992 } 7993 if (f & MachO::MH_NOFIXPREBINDING) { 7994 outs() << " NOFIXPREBINDING"; 7995 f &= ~MachO::MH_NOFIXPREBINDING; 7996 } 7997 if (f & MachO::MH_PREBINDABLE) { 7998 outs() << " PREBINDABLE"; 7999 f &= ~MachO::MH_PREBINDABLE; 8000 } 8001 if (f & MachO::MH_ALLMODSBOUND) { 8002 outs() << " ALLMODSBOUND"; 8003 f &= ~MachO::MH_ALLMODSBOUND; 8004 } 8005 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8006 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8007 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8008 } 8009 if (f & MachO::MH_CANONICAL) { 8010 outs() << " CANONICAL"; 8011 f &= ~MachO::MH_CANONICAL; 8012 } 8013 if (f & MachO::MH_WEAK_DEFINES) { 8014 outs() << " WEAK_DEFINES"; 8015 f &= ~MachO::MH_WEAK_DEFINES; 8016 } 8017 if (f & MachO::MH_BINDS_TO_WEAK) { 8018 outs() << " BINDS_TO_WEAK"; 8019 f &= ~MachO::MH_BINDS_TO_WEAK; 8020 } 8021 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8022 outs() << " ALLOW_STACK_EXECUTION"; 8023 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8024 } 8025 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8026 outs() << " DEAD_STRIPPABLE_DYLIB"; 8027 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8028 } 8029 if (f & MachO::MH_PIE) { 8030 outs() << " PIE"; 8031 f &= ~MachO::MH_PIE; 8032 } 8033 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8034 outs() << " NO_REEXPORTED_DYLIBS"; 8035 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8036 } 8037 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8038 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8039 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8040 } 8041 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8042 outs() << " MH_NO_HEAP_EXECUTION"; 8043 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8044 } 8045 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8046 outs() << " APP_EXTENSION_SAFE"; 8047 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8048 } 8049 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8050 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8051 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8052 } 8053 if (f != 0 || flags == 0) 8054 outs() << format(" 0x%08" PRIx32, f); 8055 } else { 8056 outs() << format(" 0x%08" PRIx32, magic); 8057 outs() << format(" %7d", cputype); 8058 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8059 outs() << format(" 0x%02" PRIx32, 8060 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8061 outs() << format(" %10u", filetype); 8062 outs() << format(" %5u", ncmds); 8063 outs() << format(" %10u", sizeofcmds); 8064 outs() << format(" 0x%08" PRIx32, flags); 8065 } 8066 outs() << "\n"; 8067 } 8068 8069 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8070 StringRef SegName, uint64_t vmaddr, 8071 uint64_t vmsize, uint64_t fileoff, 8072 uint64_t filesize, uint32_t maxprot, 8073 uint32_t initprot, uint32_t nsects, 8074 uint32_t flags, uint32_t object_size, 8075 bool verbose) { 8076 uint64_t expected_cmdsize; 8077 if (cmd == MachO::LC_SEGMENT) { 8078 outs() << " cmd LC_SEGMENT\n"; 8079 expected_cmdsize = nsects; 8080 expected_cmdsize *= sizeof(struct MachO::section); 8081 expected_cmdsize += sizeof(struct MachO::segment_command); 8082 } else { 8083 outs() << " cmd LC_SEGMENT_64\n"; 8084 expected_cmdsize = nsects; 8085 expected_cmdsize *= sizeof(struct MachO::section_64); 8086 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8087 } 8088 outs() << " cmdsize " << cmdsize; 8089 if (cmdsize != expected_cmdsize) 8090 outs() << " Inconsistent size\n"; 8091 else 8092 outs() << "\n"; 8093 outs() << " segname " << SegName << "\n"; 8094 if (cmd == MachO::LC_SEGMENT_64) { 8095 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8096 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8097 } else { 8098 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8099 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8100 } 8101 outs() << " fileoff " << fileoff; 8102 if (fileoff > object_size) 8103 outs() << " (past end of file)\n"; 8104 else 8105 outs() << "\n"; 8106 outs() << " filesize " << filesize; 8107 if (fileoff + filesize > object_size) 8108 outs() << " (past end of file)\n"; 8109 else 8110 outs() << "\n"; 8111 if (verbose) { 8112 if ((maxprot & 8113 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8114 MachO::VM_PROT_EXECUTE)) != 0) 8115 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8116 else { 8117 outs() << " maxprot "; 8118 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8119 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8120 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8121 } 8122 if ((initprot & 8123 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8124 MachO::VM_PROT_EXECUTE)) != 0) 8125 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8126 else { 8127 outs() << " initprot "; 8128 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8129 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8130 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8131 } 8132 } else { 8133 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8134 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8135 } 8136 outs() << " nsects " << nsects << "\n"; 8137 if (verbose) { 8138 outs() << " flags"; 8139 if (flags == 0) 8140 outs() << " (none)\n"; 8141 else { 8142 if (flags & MachO::SG_HIGHVM) { 8143 outs() << " HIGHVM"; 8144 flags &= ~MachO::SG_HIGHVM; 8145 } 8146 if (flags & MachO::SG_FVMLIB) { 8147 outs() << " FVMLIB"; 8148 flags &= ~MachO::SG_FVMLIB; 8149 } 8150 if (flags & MachO::SG_NORELOC) { 8151 outs() << " NORELOC"; 8152 flags &= ~MachO::SG_NORELOC; 8153 } 8154 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8155 outs() << " PROTECTED_VERSION_1"; 8156 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8157 } 8158 if (flags) 8159 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8160 else 8161 outs() << "\n"; 8162 } 8163 } else { 8164 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8165 } 8166 } 8167 8168 static void PrintSection(const char *sectname, const char *segname, 8169 uint64_t addr, uint64_t size, uint32_t offset, 8170 uint32_t align, uint32_t reloff, uint32_t nreloc, 8171 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8172 uint32_t cmd, const char *sg_segname, 8173 uint32_t filetype, uint32_t object_size, 8174 bool verbose) { 8175 outs() << "Section\n"; 8176 outs() << " sectname " << format("%.16s\n", sectname); 8177 outs() << " segname " << format("%.16s", segname); 8178 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8179 outs() << " (does not match segment)\n"; 8180 else 8181 outs() << "\n"; 8182 if (cmd == MachO::LC_SEGMENT_64) { 8183 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8184 outs() << " size " << format("0x%016" PRIx64, size); 8185 } else { 8186 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8187 outs() << " size " << format("0x%08" PRIx64, size); 8188 } 8189 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8190 outs() << " (past end of file)\n"; 8191 else 8192 outs() << "\n"; 8193 outs() << " offset " << offset; 8194 if (offset > object_size) 8195 outs() << " (past end of file)\n"; 8196 else 8197 outs() << "\n"; 8198 uint32_t align_shifted = 1 << align; 8199 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8200 outs() << " reloff " << reloff; 8201 if (reloff > object_size) 8202 outs() << " (past end of file)\n"; 8203 else 8204 outs() << "\n"; 8205 outs() << " nreloc " << nreloc; 8206 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8207 outs() << " (past end of file)\n"; 8208 else 8209 outs() << "\n"; 8210 uint32_t section_type = flags & MachO::SECTION_TYPE; 8211 if (verbose) { 8212 outs() << " type"; 8213 if (section_type == MachO::S_REGULAR) 8214 outs() << " S_REGULAR\n"; 8215 else if (section_type == MachO::S_ZEROFILL) 8216 outs() << " S_ZEROFILL\n"; 8217 else if (section_type == MachO::S_CSTRING_LITERALS) 8218 outs() << " S_CSTRING_LITERALS\n"; 8219 else if (section_type == MachO::S_4BYTE_LITERALS) 8220 outs() << " S_4BYTE_LITERALS\n"; 8221 else if (section_type == MachO::S_8BYTE_LITERALS) 8222 outs() << " S_8BYTE_LITERALS\n"; 8223 else if (section_type == MachO::S_16BYTE_LITERALS) 8224 outs() << " S_16BYTE_LITERALS\n"; 8225 else if (section_type == MachO::S_LITERAL_POINTERS) 8226 outs() << " S_LITERAL_POINTERS\n"; 8227 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8228 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8229 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8230 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8231 else if (section_type == MachO::S_SYMBOL_STUBS) 8232 outs() << " S_SYMBOL_STUBS\n"; 8233 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8234 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8235 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8236 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8237 else if (section_type == MachO::S_COALESCED) 8238 outs() << " S_COALESCED\n"; 8239 else if (section_type == MachO::S_INTERPOSING) 8240 outs() << " S_INTERPOSING\n"; 8241 else if (section_type == MachO::S_DTRACE_DOF) 8242 outs() << " S_DTRACE_DOF\n"; 8243 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8244 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8245 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8246 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8247 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8248 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8249 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8250 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8251 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8252 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8253 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8254 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8255 else 8256 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8257 outs() << "attributes"; 8258 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8259 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8260 outs() << " PURE_INSTRUCTIONS"; 8261 if (section_attributes & MachO::S_ATTR_NO_TOC) 8262 outs() << " NO_TOC"; 8263 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8264 outs() << " STRIP_STATIC_SYMS"; 8265 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8266 outs() << " NO_DEAD_STRIP"; 8267 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8268 outs() << " LIVE_SUPPORT"; 8269 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8270 outs() << " SELF_MODIFYING_CODE"; 8271 if (section_attributes & MachO::S_ATTR_DEBUG) 8272 outs() << " DEBUG"; 8273 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8274 outs() << " SOME_INSTRUCTIONS"; 8275 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8276 outs() << " EXT_RELOC"; 8277 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8278 outs() << " LOC_RELOC"; 8279 if (section_attributes == 0) 8280 outs() << " (none)"; 8281 outs() << "\n"; 8282 } else 8283 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8284 outs() << " reserved1 " << reserved1; 8285 if (section_type == MachO::S_SYMBOL_STUBS || 8286 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8287 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8288 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8289 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8290 outs() << " (index into indirect symbol table)\n"; 8291 else 8292 outs() << "\n"; 8293 outs() << " reserved2 " << reserved2; 8294 if (section_type == MachO::S_SYMBOL_STUBS) 8295 outs() << " (size of stubs)\n"; 8296 else 8297 outs() << "\n"; 8298 } 8299 8300 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8301 uint32_t object_size) { 8302 outs() << " cmd LC_SYMTAB\n"; 8303 outs() << " cmdsize " << st.cmdsize; 8304 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8305 outs() << " Incorrect size\n"; 8306 else 8307 outs() << "\n"; 8308 outs() << " symoff " << st.symoff; 8309 if (st.symoff > object_size) 8310 outs() << " (past end of file)\n"; 8311 else 8312 outs() << "\n"; 8313 outs() << " nsyms " << st.nsyms; 8314 uint64_t big_size; 8315 if (Is64Bit) { 8316 big_size = st.nsyms; 8317 big_size *= sizeof(struct MachO::nlist_64); 8318 big_size += st.symoff; 8319 if (big_size > object_size) 8320 outs() << " (past end of file)\n"; 8321 else 8322 outs() << "\n"; 8323 } else { 8324 big_size = st.nsyms; 8325 big_size *= sizeof(struct MachO::nlist); 8326 big_size += st.symoff; 8327 if (big_size > object_size) 8328 outs() << " (past end of file)\n"; 8329 else 8330 outs() << "\n"; 8331 } 8332 outs() << " stroff " << st.stroff; 8333 if (st.stroff > object_size) 8334 outs() << " (past end of file)\n"; 8335 else 8336 outs() << "\n"; 8337 outs() << " strsize " << st.strsize; 8338 big_size = st.stroff; 8339 big_size += st.strsize; 8340 if (big_size > object_size) 8341 outs() << " (past end of file)\n"; 8342 else 8343 outs() << "\n"; 8344 } 8345 8346 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8347 uint32_t nsyms, uint32_t object_size, 8348 bool Is64Bit) { 8349 outs() << " cmd LC_DYSYMTAB\n"; 8350 outs() << " cmdsize " << dyst.cmdsize; 8351 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8352 outs() << " Incorrect size\n"; 8353 else 8354 outs() << "\n"; 8355 outs() << " ilocalsym " << dyst.ilocalsym; 8356 if (dyst.ilocalsym > nsyms) 8357 outs() << " (greater than the number of symbols)\n"; 8358 else 8359 outs() << "\n"; 8360 outs() << " nlocalsym " << dyst.nlocalsym; 8361 uint64_t big_size; 8362 big_size = dyst.ilocalsym; 8363 big_size += dyst.nlocalsym; 8364 if (big_size > nsyms) 8365 outs() << " (past the end of the symbol table)\n"; 8366 else 8367 outs() << "\n"; 8368 outs() << " iextdefsym " << dyst.iextdefsym; 8369 if (dyst.iextdefsym > nsyms) 8370 outs() << " (greater than the number of symbols)\n"; 8371 else 8372 outs() << "\n"; 8373 outs() << " nextdefsym " << dyst.nextdefsym; 8374 big_size = dyst.iextdefsym; 8375 big_size += dyst.nextdefsym; 8376 if (big_size > nsyms) 8377 outs() << " (past the end of the symbol table)\n"; 8378 else 8379 outs() << "\n"; 8380 outs() << " iundefsym " << dyst.iundefsym; 8381 if (dyst.iundefsym > nsyms) 8382 outs() << " (greater than the number of symbols)\n"; 8383 else 8384 outs() << "\n"; 8385 outs() << " nundefsym " << dyst.nundefsym; 8386 big_size = dyst.iundefsym; 8387 big_size += dyst.nundefsym; 8388 if (big_size > nsyms) 8389 outs() << " (past the end of the symbol table)\n"; 8390 else 8391 outs() << "\n"; 8392 outs() << " tocoff " << dyst.tocoff; 8393 if (dyst.tocoff > object_size) 8394 outs() << " (past end of file)\n"; 8395 else 8396 outs() << "\n"; 8397 outs() << " ntoc " << dyst.ntoc; 8398 big_size = dyst.ntoc; 8399 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8400 big_size += dyst.tocoff; 8401 if (big_size > object_size) 8402 outs() << " (past end of file)\n"; 8403 else 8404 outs() << "\n"; 8405 outs() << " modtaboff " << dyst.modtaboff; 8406 if (dyst.modtaboff > object_size) 8407 outs() << " (past end of file)\n"; 8408 else 8409 outs() << "\n"; 8410 outs() << " nmodtab " << dyst.nmodtab; 8411 uint64_t modtabend; 8412 if (Is64Bit) { 8413 modtabend = dyst.nmodtab; 8414 modtabend *= sizeof(struct MachO::dylib_module_64); 8415 modtabend += dyst.modtaboff; 8416 } else { 8417 modtabend = dyst.nmodtab; 8418 modtabend *= sizeof(struct MachO::dylib_module); 8419 modtabend += dyst.modtaboff; 8420 } 8421 if (modtabend > object_size) 8422 outs() << " (past end of file)\n"; 8423 else 8424 outs() << "\n"; 8425 outs() << " extrefsymoff " << dyst.extrefsymoff; 8426 if (dyst.extrefsymoff > object_size) 8427 outs() << " (past end of file)\n"; 8428 else 8429 outs() << "\n"; 8430 outs() << " nextrefsyms " << dyst.nextrefsyms; 8431 big_size = dyst.nextrefsyms; 8432 big_size *= sizeof(struct MachO::dylib_reference); 8433 big_size += dyst.extrefsymoff; 8434 if (big_size > object_size) 8435 outs() << " (past end of file)\n"; 8436 else 8437 outs() << "\n"; 8438 outs() << " indirectsymoff " << dyst.indirectsymoff; 8439 if (dyst.indirectsymoff > object_size) 8440 outs() << " (past end of file)\n"; 8441 else 8442 outs() << "\n"; 8443 outs() << " nindirectsyms " << dyst.nindirectsyms; 8444 big_size = dyst.nindirectsyms; 8445 big_size *= sizeof(uint32_t); 8446 big_size += dyst.indirectsymoff; 8447 if (big_size > object_size) 8448 outs() << " (past end of file)\n"; 8449 else 8450 outs() << "\n"; 8451 outs() << " extreloff " << dyst.extreloff; 8452 if (dyst.extreloff > object_size) 8453 outs() << " (past end of file)\n"; 8454 else 8455 outs() << "\n"; 8456 outs() << " nextrel " << dyst.nextrel; 8457 big_size = dyst.nextrel; 8458 big_size *= sizeof(struct MachO::relocation_info); 8459 big_size += dyst.extreloff; 8460 if (big_size > object_size) 8461 outs() << " (past end of file)\n"; 8462 else 8463 outs() << "\n"; 8464 outs() << " locreloff " << dyst.locreloff; 8465 if (dyst.locreloff > object_size) 8466 outs() << " (past end of file)\n"; 8467 else 8468 outs() << "\n"; 8469 outs() << " nlocrel " << dyst.nlocrel; 8470 big_size = dyst.nlocrel; 8471 big_size *= sizeof(struct MachO::relocation_info); 8472 big_size += dyst.locreloff; 8473 if (big_size > object_size) 8474 outs() << " (past end of file)\n"; 8475 else 8476 outs() << "\n"; 8477 } 8478 8479 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8480 uint32_t object_size) { 8481 if (dc.cmd == MachO::LC_DYLD_INFO) 8482 outs() << " cmd LC_DYLD_INFO\n"; 8483 else 8484 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8485 outs() << " cmdsize " << dc.cmdsize; 8486 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8487 outs() << " Incorrect size\n"; 8488 else 8489 outs() << "\n"; 8490 outs() << " rebase_off " << dc.rebase_off; 8491 if (dc.rebase_off > object_size) 8492 outs() << " (past end of file)\n"; 8493 else 8494 outs() << "\n"; 8495 outs() << " rebase_size " << dc.rebase_size; 8496 uint64_t big_size; 8497 big_size = dc.rebase_off; 8498 big_size += dc.rebase_size; 8499 if (big_size > object_size) 8500 outs() << " (past end of file)\n"; 8501 else 8502 outs() << "\n"; 8503 outs() << " bind_off " << dc.bind_off; 8504 if (dc.bind_off > object_size) 8505 outs() << " (past end of file)\n"; 8506 else 8507 outs() << "\n"; 8508 outs() << " bind_size " << dc.bind_size; 8509 big_size = dc.bind_off; 8510 big_size += dc.bind_size; 8511 if (big_size > object_size) 8512 outs() << " (past end of file)\n"; 8513 else 8514 outs() << "\n"; 8515 outs() << " weak_bind_off " << dc.weak_bind_off; 8516 if (dc.weak_bind_off > object_size) 8517 outs() << " (past end of file)\n"; 8518 else 8519 outs() << "\n"; 8520 outs() << " weak_bind_size " << dc.weak_bind_size; 8521 big_size = dc.weak_bind_off; 8522 big_size += dc.weak_bind_size; 8523 if (big_size > object_size) 8524 outs() << " (past end of file)\n"; 8525 else 8526 outs() << "\n"; 8527 outs() << " lazy_bind_off " << dc.lazy_bind_off; 8528 if (dc.lazy_bind_off > object_size) 8529 outs() << " (past end of file)\n"; 8530 else 8531 outs() << "\n"; 8532 outs() << " lazy_bind_size " << dc.lazy_bind_size; 8533 big_size = dc.lazy_bind_off; 8534 big_size += dc.lazy_bind_size; 8535 if (big_size > object_size) 8536 outs() << " (past end of file)\n"; 8537 else 8538 outs() << "\n"; 8539 outs() << " export_off " << dc.export_off; 8540 if (dc.export_off > object_size) 8541 outs() << " (past end of file)\n"; 8542 else 8543 outs() << "\n"; 8544 outs() << " export_size " << dc.export_size; 8545 big_size = dc.export_off; 8546 big_size += dc.export_size; 8547 if (big_size > object_size) 8548 outs() << " (past end of file)\n"; 8549 else 8550 outs() << "\n"; 8551 } 8552 8553 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 8554 const char *Ptr) { 8555 if (dyld.cmd == MachO::LC_ID_DYLINKER) 8556 outs() << " cmd LC_ID_DYLINKER\n"; 8557 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 8558 outs() << " cmd LC_LOAD_DYLINKER\n"; 8559 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 8560 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 8561 else 8562 outs() << " cmd ?(" << dyld.cmd << ")\n"; 8563 outs() << " cmdsize " << dyld.cmdsize; 8564 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 8565 outs() << " Incorrect size\n"; 8566 else 8567 outs() << "\n"; 8568 if (dyld.name >= dyld.cmdsize) 8569 outs() << " name ?(bad offset " << dyld.name << ")\n"; 8570 else { 8571 const char *P = (const char *)(Ptr) + dyld.name; 8572 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 8573 } 8574 } 8575 8576 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 8577 outs() << " cmd LC_UUID\n"; 8578 outs() << " cmdsize " << uuid.cmdsize; 8579 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 8580 outs() << " Incorrect size\n"; 8581 else 8582 outs() << "\n"; 8583 outs() << " uuid "; 8584 for (int i = 0; i < 16; ++i) { 8585 outs() << format("%02" PRIX32, uuid.uuid[i]); 8586 if (i == 3 || i == 5 || i == 7 || i == 9) 8587 outs() << "-"; 8588 } 8589 outs() << "\n"; 8590 } 8591 8592 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 8593 outs() << " cmd LC_RPATH\n"; 8594 outs() << " cmdsize " << rpath.cmdsize; 8595 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 8596 outs() << " Incorrect size\n"; 8597 else 8598 outs() << "\n"; 8599 if (rpath.path >= rpath.cmdsize) 8600 outs() << " path ?(bad offset " << rpath.path << ")\n"; 8601 else { 8602 const char *P = (const char *)(Ptr) + rpath.path; 8603 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 8604 } 8605 } 8606 8607 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 8608 StringRef LoadCmdName; 8609 switch (vd.cmd) { 8610 case MachO::LC_VERSION_MIN_MACOSX: 8611 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 8612 break; 8613 case MachO::LC_VERSION_MIN_IPHONEOS: 8614 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 8615 break; 8616 case MachO::LC_VERSION_MIN_TVOS: 8617 LoadCmdName = "LC_VERSION_MIN_TVOS"; 8618 break; 8619 case MachO::LC_VERSION_MIN_WATCHOS: 8620 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 8621 break; 8622 default: 8623 llvm_unreachable("Unknown version min load command"); 8624 } 8625 8626 outs() << " cmd " << LoadCmdName << '\n'; 8627 outs() << " cmdsize " << vd.cmdsize; 8628 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 8629 outs() << " Incorrect size\n"; 8630 else 8631 outs() << "\n"; 8632 outs() << " version " 8633 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 8634 << MachOObjectFile::getVersionMinMinor(vd, false); 8635 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 8636 if (Update != 0) 8637 outs() << "." << Update; 8638 outs() << "\n"; 8639 if (vd.sdk == 0) 8640 outs() << " sdk n/a"; 8641 else { 8642 outs() << " sdk " 8643 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 8644 << MachOObjectFile::getVersionMinMinor(vd, true); 8645 } 8646 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 8647 if (Update != 0) 8648 outs() << "." << Update; 8649 outs() << "\n"; 8650 } 8651 8652 static void PrintNoteLoadCommand(MachO::note_command Nt) { 8653 outs() << " cmd LC_NOTE\n"; 8654 outs() << " cmdsize " << Nt.cmdsize; 8655 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 8656 outs() << " Incorrect size\n"; 8657 else 8658 outs() << "\n"; 8659 const char *d = Nt.data_owner; 8660 outs() << "data_owner " << format("%.16s\n", d); 8661 outs() << " offset " << Nt.offset << "\n"; 8662 outs() << " size " << Nt.size << "\n"; 8663 } 8664 8665 static void PrintBuildToolVersion(MachO::build_tool_version bv) { 8666 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; 8667 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 8668 << "\n"; 8669 } 8670 8671 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 8672 MachO::build_version_command bd) { 8673 outs() << " cmd LC_BUILD_VERSION\n"; 8674 outs() << " cmdsize " << bd.cmdsize; 8675 if (bd.cmdsize != 8676 sizeof(struct MachO::build_version_command) + 8677 bd.ntools * sizeof(struct MachO::build_tool_version)) 8678 outs() << " Incorrect size\n"; 8679 else 8680 outs() << "\n"; 8681 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) 8682 << "\n"; 8683 if (bd.sdk) 8684 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 8685 << "\n"; 8686 else 8687 outs() << " sdk n/a\n"; 8688 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 8689 << "\n"; 8690 outs() << " ntools " << bd.ntools << "\n"; 8691 for (unsigned i = 0; i < bd.ntools; ++i) { 8692 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 8693 PrintBuildToolVersion(bv); 8694 } 8695 } 8696 8697 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 8698 outs() << " cmd LC_SOURCE_VERSION\n"; 8699 outs() << " cmdsize " << sd.cmdsize; 8700 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 8701 outs() << " Incorrect size\n"; 8702 else 8703 outs() << "\n"; 8704 uint64_t a = (sd.version >> 40) & 0xffffff; 8705 uint64_t b = (sd.version >> 30) & 0x3ff; 8706 uint64_t c = (sd.version >> 20) & 0x3ff; 8707 uint64_t d = (sd.version >> 10) & 0x3ff; 8708 uint64_t e = sd.version & 0x3ff; 8709 outs() << " version " << a << "." << b; 8710 if (e != 0) 8711 outs() << "." << c << "." << d << "." << e; 8712 else if (d != 0) 8713 outs() << "." << c << "." << d; 8714 else if (c != 0) 8715 outs() << "." << c; 8716 outs() << "\n"; 8717 } 8718 8719 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 8720 outs() << " cmd LC_MAIN\n"; 8721 outs() << " cmdsize " << ep.cmdsize; 8722 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 8723 outs() << " Incorrect size\n"; 8724 else 8725 outs() << "\n"; 8726 outs() << " entryoff " << ep.entryoff << "\n"; 8727 outs() << " stacksize " << ep.stacksize << "\n"; 8728 } 8729 8730 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 8731 uint32_t object_size) { 8732 outs() << " cmd LC_ENCRYPTION_INFO\n"; 8733 outs() << " cmdsize " << ec.cmdsize; 8734 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 8735 outs() << " Incorrect size\n"; 8736 else 8737 outs() << "\n"; 8738 outs() << " cryptoff " << ec.cryptoff; 8739 if (ec.cryptoff > object_size) 8740 outs() << " (past end of file)\n"; 8741 else 8742 outs() << "\n"; 8743 outs() << " cryptsize " << ec.cryptsize; 8744 if (ec.cryptsize > object_size) 8745 outs() << " (past end of file)\n"; 8746 else 8747 outs() << "\n"; 8748 outs() << " cryptid " << ec.cryptid << "\n"; 8749 } 8750 8751 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 8752 uint32_t object_size) { 8753 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 8754 outs() << " cmdsize " << ec.cmdsize; 8755 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 8756 outs() << " Incorrect size\n"; 8757 else 8758 outs() << "\n"; 8759 outs() << " cryptoff " << ec.cryptoff; 8760 if (ec.cryptoff > object_size) 8761 outs() << " (past end of file)\n"; 8762 else 8763 outs() << "\n"; 8764 outs() << " cryptsize " << ec.cryptsize; 8765 if (ec.cryptsize > object_size) 8766 outs() << " (past end of file)\n"; 8767 else 8768 outs() << "\n"; 8769 outs() << " cryptid " << ec.cryptid << "\n"; 8770 outs() << " pad " << ec.pad << "\n"; 8771 } 8772 8773 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 8774 const char *Ptr) { 8775 outs() << " cmd LC_LINKER_OPTION\n"; 8776 outs() << " cmdsize " << lo.cmdsize; 8777 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 8778 outs() << " Incorrect size\n"; 8779 else 8780 outs() << "\n"; 8781 outs() << " count " << lo.count << "\n"; 8782 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 8783 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 8784 uint32_t i = 0; 8785 while (left > 0) { 8786 while (*string == '\0' && left > 0) { 8787 string++; 8788 left--; 8789 } 8790 if (left > 0) { 8791 i++; 8792 outs() << " string #" << i << " " << format("%.*s\n", left, string); 8793 uint32_t NullPos = StringRef(string, left).find('\0'); 8794 uint32_t len = std::min(NullPos, left) + 1; 8795 string += len; 8796 left -= len; 8797 } 8798 } 8799 if (lo.count != i) 8800 outs() << " count " << lo.count << " does not match number of strings " 8801 << i << "\n"; 8802 } 8803 8804 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 8805 const char *Ptr) { 8806 outs() << " cmd LC_SUB_FRAMEWORK\n"; 8807 outs() << " cmdsize " << sub.cmdsize; 8808 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 8809 outs() << " Incorrect size\n"; 8810 else 8811 outs() << "\n"; 8812 if (sub.umbrella < sub.cmdsize) { 8813 const char *P = Ptr + sub.umbrella; 8814 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 8815 } else { 8816 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 8817 } 8818 } 8819 8820 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 8821 const char *Ptr) { 8822 outs() << " cmd LC_SUB_UMBRELLA\n"; 8823 outs() << " cmdsize " << sub.cmdsize; 8824 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 8825 outs() << " Incorrect size\n"; 8826 else 8827 outs() << "\n"; 8828 if (sub.sub_umbrella < sub.cmdsize) { 8829 const char *P = Ptr + sub.sub_umbrella; 8830 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 8831 } else { 8832 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 8833 } 8834 } 8835 8836 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 8837 const char *Ptr) { 8838 outs() << " cmd LC_SUB_LIBRARY\n"; 8839 outs() << " cmdsize " << sub.cmdsize; 8840 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 8841 outs() << " Incorrect size\n"; 8842 else 8843 outs() << "\n"; 8844 if (sub.sub_library < sub.cmdsize) { 8845 const char *P = Ptr + sub.sub_library; 8846 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 8847 } else { 8848 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 8849 } 8850 } 8851 8852 static void PrintSubClientCommand(MachO::sub_client_command sub, 8853 const char *Ptr) { 8854 outs() << " cmd LC_SUB_CLIENT\n"; 8855 outs() << " cmdsize " << sub.cmdsize; 8856 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 8857 outs() << " Incorrect size\n"; 8858 else 8859 outs() << "\n"; 8860 if (sub.client < sub.cmdsize) { 8861 const char *P = Ptr + sub.client; 8862 outs() << " client " << P << " (offset " << sub.client << ")\n"; 8863 } else { 8864 outs() << " client ?(bad offset " << sub.client << ")\n"; 8865 } 8866 } 8867 8868 static void PrintRoutinesCommand(MachO::routines_command r) { 8869 outs() << " cmd LC_ROUTINES\n"; 8870 outs() << " cmdsize " << r.cmdsize; 8871 if (r.cmdsize != sizeof(struct MachO::routines_command)) 8872 outs() << " Incorrect size\n"; 8873 else 8874 outs() << "\n"; 8875 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 8876 outs() << " init_module " << r.init_module << "\n"; 8877 outs() << " reserved1 " << r.reserved1 << "\n"; 8878 outs() << " reserved2 " << r.reserved2 << "\n"; 8879 outs() << " reserved3 " << r.reserved3 << "\n"; 8880 outs() << " reserved4 " << r.reserved4 << "\n"; 8881 outs() << " reserved5 " << r.reserved5 << "\n"; 8882 outs() << " reserved6 " << r.reserved6 << "\n"; 8883 } 8884 8885 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 8886 outs() << " cmd LC_ROUTINES_64\n"; 8887 outs() << " cmdsize " << r.cmdsize; 8888 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 8889 outs() << " Incorrect size\n"; 8890 else 8891 outs() << "\n"; 8892 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 8893 outs() << " init_module " << r.init_module << "\n"; 8894 outs() << " reserved1 " << r.reserved1 << "\n"; 8895 outs() << " reserved2 " << r.reserved2 << "\n"; 8896 outs() << " reserved3 " << r.reserved3 << "\n"; 8897 outs() << " reserved4 " << r.reserved4 << "\n"; 8898 outs() << " reserved5 " << r.reserved5 << "\n"; 8899 outs() << " reserved6 " << r.reserved6 << "\n"; 8900 } 8901 8902 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 8903 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 8904 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 8905 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 8906 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 8907 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 8908 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 8909 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 8910 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 8911 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 8912 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 8913 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 8914 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 8915 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 8916 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 8917 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 8918 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 8919 } 8920 8921 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 8922 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 8923 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 8924 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 8925 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 8926 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 8927 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 8928 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 8929 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 8930 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 8931 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 8932 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 8933 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 8934 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 8935 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 8936 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 8937 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 8938 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 8939 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 8940 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 8941 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 8942 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 8943 } 8944 8945 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 8946 uint32_t f; 8947 outs() << "\t mmst_reg "; 8948 for (f = 0; f < 10; f++) 8949 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 8950 outs() << "\n"; 8951 outs() << "\t mmst_rsrv "; 8952 for (f = 0; f < 6; f++) 8953 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 8954 outs() << "\n"; 8955 } 8956 8957 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 8958 uint32_t f; 8959 outs() << "\t xmm_reg "; 8960 for (f = 0; f < 16; f++) 8961 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 8962 outs() << "\n"; 8963 } 8964 8965 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 8966 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 8967 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 8968 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 8969 outs() << " denorm " << fpu.fpu_fcw.denorm; 8970 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 8971 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 8972 outs() << " undfl " << fpu.fpu_fcw.undfl; 8973 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 8974 outs() << "\t\t pc "; 8975 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 8976 outs() << "FP_PREC_24B "; 8977 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 8978 outs() << "FP_PREC_53B "; 8979 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 8980 outs() << "FP_PREC_64B "; 8981 else 8982 outs() << fpu.fpu_fcw.pc << " "; 8983 outs() << "rc "; 8984 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 8985 outs() << "FP_RND_NEAR "; 8986 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 8987 outs() << "FP_RND_DOWN "; 8988 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 8989 outs() << "FP_RND_UP "; 8990 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 8991 outs() << "FP_CHOP "; 8992 outs() << "\n"; 8993 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 8994 outs() << " denorm " << fpu.fpu_fsw.denorm; 8995 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 8996 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 8997 outs() << " undfl " << fpu.fpu_fsw.undfl; 8998 outs() << " precis " << fpu.fpu_fsw.precis; 8999 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 9000 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9001 outs() << " c0 " << fpu.fpu_fsw.c0; 9002 outs() << " c1 " << fpu.fpu_fsw.c1; 9003 outs() << " c2 " << fpu.fpu_fsw.c2; 9004 outs() << " tos " << fpu.fpu_fsw.tos; 9005 outs() << " c3 " << fpu.fpu_fsw.c3; 9006 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9007 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9008 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9009 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9010 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9011 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9012 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9013 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9014 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9015 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9016 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9017 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9018 outs() << "\n"; 9019 outs() << "\t fpu_stmm0:\n"; 9020 Print_mmst_reg(fpu.fpu_stmm0); 9021 outs() << "\t fpu_stmm1:\n"; 9022 Print_mmst_reg(fpu.fpu_stmm1); 9023 outs() << "\t fpu_stmm2:\n"; 9024 Print_mmst_reg(fpu.fpu_stmm2); 9025 outs() << "\t fpu_stmm3:\n"; 9026 Print_mmst_reg(fpu.fpu_stmm3); 9027 outs() << "\t fpu_stmm4:\n"; 9028 Print_mmst_reg(fpu.fpu_stmm4); 9029 outs() << "\t fpu_stmm5:\n"; 9030 Print_mmst_reg(fpu.fpu_stmm5); 9031 outs() << "\t fpu_stmm6:\n"; 9032 Print_mmst_reg(fpu.fpu_stmm6); 9033 outs() << "\t fpu_stmm7:\n"; 9034 Print_mmst_reg(fpu.fpu_stmm7); 9035 outs() << "\t fpu_xmm0:\n"; 9036 Print_xmm_reg(fpu.fpu_xmm0); 9037 outs() << "\t fpu_xmm1:\n"; 9038 Print_xmm_reg(fpu.fpu_xmm1); 9039 outs() << "\t fpu_xmm2:\n"; 9040 Print_xmm_reg(fpu.fpu_xmm2); 9041 outs() << "\t fpu_xmm3:\n"; 9042 Print_xmm_reg(fpu.fpu_xmm3); 9043 outs() << "\t fpu_xmm4:\n"; 9044 Print_xmm_reg(fpu.fpu_xmm4); 9045 outs() << "\t fpu_xmm5:\n"; 9046 Print_xmm_reg(fpu.fpu_xmm5); 9047 outs() << "\t fpu_xmm6:\n"; 9048 Print_xmm_reg(fpu.fpu_xmm6); 9049 outs() << "\t fpu_xmm7:\n"; 9050 Print_xmm_reg(fpu.fpu_xmm7); 9051 outs() << "\t fpu_xmm8:\n"; 9052 Print_xmm_reg(fpu.fpu_xmm8); 9053 outs() << "\t fpu_xmm9:\n"; 9054 Print_xmm_reg(fpu.fpu_xmm9); 9055 outs() << "\t fpu_xmm10:\n"; 9056 Print_xmm_reg(fpu.fpu_xmm10); 9057 outs() << "\t fpu_xmm11:\n"; 9058 Print_xmm_reg(fpu.fpu_xmm11); 9059 outs() << "\t fpu_xmm12:\n"; 9060 Print_xmm_reg(fpu.fpu_xmm12); 9061 outs() << "\t fpu_xmm13:\n"; 9062 Print_xmm_reg(fpu.fpu_xmm13); 9063 outs() << "\t fpu_xmm14:\n"; 9064 Print_xmm_reg(fpu.fpu_xmm14); 9065 outs() << "\t fpu_xmm15:\n"; 9066 Print_xmm_reg(fpu.fpu_xmm15); 9067 outs() << "\t fpu_rsrv4:\n"; 9068 for (uint32_t f = 0; f < 6; f++) { 9069 outs() << "\t "; 9070 for (uint32_t g = 0; g < 16; g++) 9071 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9072 outs() << "\n"; 9073 } 9074 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9075 outs() << "\n"; 9076 } 9077 9078 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9079 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9080 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9081 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9082 } 9083 9084 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9085 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9086 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9087 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9088 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9089 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9090 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9091 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9092 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9093 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9094 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9095 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9096 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9097 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9098 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9099 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9100 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9101 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9102 } 9103 9104 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9105 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9106 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9107 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9108 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9109 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9110 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9111 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9112 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9113 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9114 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9115 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9116 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9117 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9118 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9119 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9120 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9121 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9122 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9123 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9124 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9125 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9126 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9127 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9128 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9129 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9130 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9131 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9132 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9133 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9134 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9135 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9136 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9137 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9138 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9139 } 9140 9141 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9142 bool isLittleEndian, uint32_t cputype) { 9143 if (t.cmd == MachO::LC_THREAD) 9144 outs() << " cmd LC_THREAD\n"; 9145 else if (t.cmd == MachO::LC_UNIXTHREAD) 9146 outs() << " cmd LC_UNIXTHREAD\n"; 9147 else 9148 outs() << " cmd " << t.cmd << " (unknown)\n"; 9149 outs() << " cmdsize " << t.cmdsize; 9150 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9151 outs() << " Incorrect size\n"; 9152 else 9153 outs() << "\n"; 9154 9155 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9156 const char *end = Ptr + t.cmdsize; 9157 uint32_t flavor, count, left; 9158 if (cputype == MachO::CPU_TYPE_I386) { 9159 while (begin < end) { 9160 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9161 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9162 begin += sizeof(uint32_t); 9163 } else { 9164 flavor = 0; 9165 begin = end; 9166 } 9167 if (isLittleEndian != sys::IsLittleEndianHost) 9168 sys::swapByteOrder(flavor); 9169 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9170 memcpy((char *)&count, begin, sizeof(uint32_t)); 9171 begin += sizeof(uint32_t); 9172 } else { 9173 count = 0; 9174 begin = end; 9175 } 9176 if (isLittleEndian != sys::IsLittleEndianHost) 9177 sys::swapByteOrder(count); 9178 if (flavor == MachO::x86_THREAD_STATE32) { 9179 outs() << " flavor i386_THREAD_STATE\n"; 9180 if (count == MachO::x86_THREAD_STATE32_COUNT) 9181 outs() << " count i386_THREAD_STATE_COUNT\n"; 9182 else 9183 outs() << " count " << count 9184 << " (not x86_THREAD_STATE32_COUNT)\n"; 9185 MachO::x86_thread_state32_t cpu32; 9186 left = end - begin; 9187 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9188 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9189 begin += sizeof(MachO::x86_thread_state32_t); 9190 } else { 9191 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9192 memcpy(&cpu32, begin, left); 9193 begin += left; 9194 } 9195 if (isLittleEndian != sys::IsLittleEndianHost) 9196 swapStruct(cpu32); 9197 Print_x86_thread_state32_t(cpu32); 9198 } else if (flavor == MachO::x86_THREAD_STATE) { 9199 outs() << " flavor x86_THREAD_STATE\n"; 9200 if (count == MachO::x86_THREAD_STATE_COUNT) 9201 outs() << " count x86_THREAD_STATE_COUNT\n"; 9202 else 9203 outs() << " count " << count 9204 << " (not x86_THREAD_STATE_COUNT)\n"; 9205 struct MachO::x86_thread_state_t ts; 9206 left = end - begin; 9207 if (left >= sizeof(MachO::x86_thread_state_t)) { 9208 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9209 begin += sizeof(MachO::x86_thread_state_t); 9210 } else { 9211 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9212 memcpy(&ts, begin, left); 9213 begin += left; 9214 } 9215 if (isLittleEndian != sys::IsLittleEndianHost) 9216 swapStruct(ts); 9217 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9218 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9219 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9220 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9221 else 9222 outs() << "tsh.count " << ts.tsh.count 9223 << " (not x86_THREAD_STATE32_COUNT\n"; 9224 Print_x86_thread_state32_t(ts.uts.ts32); 9225 } else { 9226 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9227 << ts.tsh.count << "\n"; 9228 } 9229 } else { 9230 outs() << " flavor " << flavor << " (unknown)\n"; 9231 outs() << " count " << count << "\n"; 9232 outs() << " state (unknown)\n"; 9233 begin += count * sizeof(uint32_t); 9234 } 9235 } 9236 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9237 while (begin < end) { 9238 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9239 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9240 begin += sizeof(uint32_t); 9241 } else { 9242 flavor = 0; 9243 begin = end; 9244 } 9245 if (isLittleEndian != sys::IsLittleEndianHost) 9246 sys::swapByteOrder(flavor); 9247 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9248 memcpy((char *)&count, begin, sizeof(uint32_t)); 9249 begin += sizeof(uint32_t); 9250 } else { 9251 count = 0; 9252 begin = end; 9253 } 9254 if (isLittleEndian != sys::IsLittleEndianHost) 9255 sys::swapByteOrder(count); 9256 if (flavor == MachO::x86_THREAD_STATE64) { 9257 outs() << " flavor x86_THREAD_STATE64\n"; 9258 if (count == MachO::x86_THREAD_STATE64_COUNT) 9259 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9260 else 9261 outs() << " count " << count 9262 << " (not x86_THREAD_STATE64_COUNT)\n"; 9263 MachO::x86_thread_state64_t cpu64; 9264 left = end - begin; 9265 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9266 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9267 begin += sizeof(MachO::x86_thread_state64_t); 9268 } else { 9269 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9270 memcpy(&cpu64, begin, left); 9271 begin += left; 9272 } 9273 if (isLittleEndian != sys::IsLittleEndianHost) 9274 swapStruct(cpu64); 9275 Print_x86_thread_state64_t(cpu64); 9276 } else if (flavor == MachO::x86_THREAD_STATE) { 9277 outs() << " flavor x86_THREAD_STATE\n"; 9278 if (count == MachO::x86_THREAD_STATE_COUNT) 9279 outs() << " count x86_THREAD_STATE_COUNT\n"; 9280 else 9281 outs() << " count " << count 9282 << " (not x86_THREAD_STATE_COUNT)\n"; 9283 struct MachO::x86_thread_state_t ts; 9284 left = end - begin; 9285 if (left >= sizeof(MachO::x86_thread_state_t)) { 9286 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9287 begin += sizeof(MachO::x86_thread_state_t); 9288 } else { 9289 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9290 memcpy(&ts, begin, left); 9291 begin += left; 9292 } 9293 if (isLittleEndian != sys::IsLittleEndianHost) 9294 swapStruct(ts); 9295 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9296 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9297 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9298 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9299 else 9300 outs() << "tsh.count " << ts.tsh.count 9301 << " (not x86_THREAD_STATE64_COUNT\n"; 9302 Print_x86_thread_state64_t(ts.uts.ts64); 9303 } else { 9304 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9305 << ts.tsh.count << "\n"; 9306 } 9307 } else if (flavor == MachO::x86_FLOAT_STATE) { 9308 outs() << " flavor x86_FLOAT_STATE\n"; 9309 if (count == MachO::x86_FLOAT_STATE_COUNT) 9310 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9311 else 9312 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9313 struct MachO::x86_float_state_t fs; 9314 left = end - begin; 9315 if (left >= sizeof(MachO::x86_float_state_t)) { 9316 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9317 begin += sizeof(MachO::x86_float_state_t); 9318 } else { 9319 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9320 memcpy(&fs, begin, left); 9321 begin += left; 9322 } 9323 if (isLittleEndian != sys::IsLittleEndianHost) 9324 swapStruct(fs); 9325 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9326 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9327 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9328 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9329 else 9330 outs() << "fsh.count " << fs.fsh.count 9331 << " (not x86_FLOAT_STATE64_COUNT\n"; 9332 Print_x86_float_state_t(fs.ufs.fs64); 9333 } else { 9334 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9335 << fs.fsh.count << "\n"; 9336 } 9337 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9338 outs() << " flavor x86_EXCEPTION_STATE\n"; 9339 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9340 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9341 else 9342 outs() << " count " << count 9343 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9344 struct MachO::x86_exception_state_t es; 9345 left = end - begin; 9346 if (left >= sizeof(MachO::x86_exception_state_t)) { 9347 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9348 begin += sizeof(MachO::x86_exception_state_t); 9349 } else { 9350 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9351 memcpy(&es, begin, left); 9352 begin += left; 9353 } 9354 if (isLittleEndian != sys::IsLittleEndianHost) 9355 swapStruct(es); 9356 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9357 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9358 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9359 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9360 else 9361 outs() << "\t esh.count " << es.esh.count 9362 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9363 Print_x86_exception_state_t(es.ues.es64); 9364 } else { 9365 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9366 << es.esh.count << "\n"; 9367 } 9368 } else if (flavor == MachO::x86_EXCEPTION_STATE64) { 9369 outs() << " flavor x86_EXCEPTION_STATE64\n"; 9370 if (count == MachO::x86_EXCEPTION_STATE64_COUNT) 9371 outs() << " count x86_EXCEPTION_STATE64_COUNT\n"; 9372 else 9373 outs() << " count " << count 9374 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; 9375 struct MachO::x86_exception_state64_t es64; 9376 left = end - begin; 9377 if (left >= sizeof(MachO::x86_exception_state64_t)) { 9378 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); 9379 begin += sizeof(MachO::x86_exception_state64_t); 9380 } else { 9381 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); 9382 memcpy(&es64, begin, left); 9383 begin += left; 9384 } 9385 if (isLittleEndian != sys::IsLittleEndianHost) 9386 swapStruct(es64); 9387 Print_x86_exception_state_t(es64); 9388 } else { 9389 outs() << " flavor " << flavor << " (unknown)\n"; 9390 outs() << " count " << count << "\n"; 9391 outs() << " state (unknown)\n"; 9392 begin += count * sizeof(uint32_t); 9393 } 9394 } 9395 } else if (cputype == MachO::CPU_TYPE_ARM) { 9396 while (begin < end) { 9397 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9398 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9399 begin += sizeof(uint32_t); 9400 } else { 9401 flavor = 0; 9402 begin = end; 9403 } 9404 if (isLittleEndian != sys::IsLittleEndianHost) 9405 sys::swapByteOrder(flavor); 9406 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9407 memcpy((char *)&count, begin, sizeof(uint32_t)); 9408 begin += sizeof(uint32_t); 9409 } else { 9410 count = 0; 9411 begin = end; 9412 } 9413 if (isLittleEndian != sys::IsLittleEndianHost) 9414 sys::swapByteOrder(count); 9415 if (flavor == MachO::ARM_THREAD_STATE) { 9416 outs() << " flavor ARM_THREAD_STATE\n"; 9417 if (count == MachO::ARM_THREAD_STATE_COUNT) 9418 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9419 else 9420 outs() << " count " << count 9421 << " (not ARM_THREAD_STATE_COUNT)\n"; 9422 MachO::arm_thread_state32_t cpu32; 9423 left = end - begin; 9424 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9425 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9426 begin += sizeof(MachO::arm_thread_state32_t); 9427 } else { 9428 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9429 memcpy(&cpu32, begin, left); 9430 begin += left; 9431 } 9432 if (isLittleEndian != sys::IsLittleEndianHost) 9433 swapStruct(cpu32); 9434 Print_arm_thread_state32_t(cpu32); 9435 } else { 9436 outs() << " flavor " << flavor << " (unknown)\n"; 9437 outs() << " count " << count << "\n"; 9438 outs() << " state (unknown)\n"; 9439 begin += count * sizeof(uint32_t); 9440 } 9441 } 9442 } else if (cputype == MachO::CPU_TYPE_ARM64) { 9443 while (begin < end) { 9444 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9445 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9446 begin += sizeof(uint32_t); 9447 } else { 9448 flavor = 0; 9449 begin = end; 9450 } 9451 if (isLittleEndian != sys::IsLittleEndianHost) 9452 sys::swapByteOrder(flavor); 9453 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9454 memcpy((char *)&count, begin, sizeof(uint32_t)); 9455 begin += sizeof(uint32_t); 9456 } else { 9457 count = 0; 9458 begin = end; 9459 } 9460 if (isLittleEndian != sys::IsLittleEndianHost) 9461 sys::swapByteOrder(count); 9462 if (flavor == MachO::ARM_THREAD_STATE64) { 9463 outs() << " flavor ARM_THREAD_STATE64\n"; 9464 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9465 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9466 else 9467 outs() << " count " << count 9468 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9469 MachO::arm_thread_state64_t cpu64; 9470 left = end - begin; 9471 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9472 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9473 begin += sizeof(MachO::arm_thread_state64_t); 9474 } else { 9475 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9476 memcpy(&cpu64, begin, left); 9477 begin += left; 9478 } 9479 if (isLittleEndian != sys::IsLittleEndianHost) 9480 swapStruct(cpu64); 9481 Print_arm_thread_state64_t(cpu64); 9482 } else { 9483 outs() << " flavor " << flavor << " (unknown)\n"; 9484 outs() << " count " << count << "\n"; 9485 outs() << " state (unknown)\n"; 9486 begin += count * sizeof(uint32_t); 9487 } 9488 } 9489 } else { 9490 while (begin < end) { 9491 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9492 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9493 begin += sizeof(uint32_t); 9494 } else { 9495 flavor = 0; 9496 begin = end; 9497 } 9498 if (isLittleEndian != sys::IsLittleEndianHost) 9499 sys::swapByteOrder(flavor); 9500 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9501 memcpy((char *)&count, begin, sizeof(uint32_t)); 9502 begin += sizeof(uint32_t); 9503 } else { 9504 count = 0; 9505 begin = end; 9506 } 9507 if (isLittleEndian != sys::IsLittleEndianHost) 9508 sys::swapByteOrder(count); 9509 outs() << " flavor " << flavor << "\n"; 9510 outs() << " count " << count << "\n"; 9511 outs() << " state (Unknown cputype/cpusubtype)\n"; 9512 begin += count * sizeof(uint32_t); 9513 } 9514 } 9515 } 9516 9517 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 9518 if (dl.cmd == MachO::LC_ID_DYLIB) 9519 outs() << " cmd LC_ID_DYLIB\n"; 9520 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 9521 outs() << " cmd LC_LOAD_DYLIB\n"; 9522 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 9523 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 9524 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 9525 outs() << " cmd LC_REEXPORT_DYLIB\n"; 9526 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 9527 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 9528 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 9529 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 9530 else 9531 outs() << " cmd " << dl.cmd << " (unknown)\n"; 9532 outs() << " cmdsize " << dl.cmdsize; 9533 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 9534 outs() << " Incorrect size\n"; 9535 else 9536 outs() << "\n"; 9537 if (dl.dylib.name < dl.cmdsize) { 9538 const char *P = (const char *)(Ptr) + dl.dylib.name; 9539 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 9540 } else { 9541 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 9542 } 9543 outs() << " time stamp " << dl.dylib.timestamp << " "; 9544 time_t t = dl.dylib.timestamp; 9545 outs() << ctime(&t); 9546 outs() << " current version "; 9547 if (dl.dylib.current_version == 0xffffffff) 9548 outs() << "n/a\n"; 9549 else 9550 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 9551 << ((dl.dylib.current_version >> 8) & 0xff) << "." 9552 << (dl.dylib.current_version & 0xff) << "\n"; 9553 outs() << "compatibility version "; 9554 if (dl.dylib.compatibility_version == 0xffffffff) 9555 outs() << "n/a\n"; 9556 else 9557 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 9558 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 9559 << (dl.dylib.compatibility_version & 0xff) << "\n"; 9560 } 9561 9562 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 9563 uint32_t object_size) { 9564 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 9565 outs() << " cmd LC_CODE_SIGNATURE\n"; 9566 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 9567 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 9568 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 9569 outs() << " cmd LC_FUNCTION_STARTS\n"; 9570 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 9571 outs() << " cmd LC_DATA_IN_CODE\n"; 9572 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 9573 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 9574 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 9575 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 9576 else 9577 outs() << " cmd " << ld.cmd << " (?)\n"; 9578 outs() << " cmdsize " << ld.cmdsize; 9579 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 9580 outs() << " Incorrect size\n"; 9581 else 9582 outs() << "\n"; 9583 outs() << " dataoff " << ld.dataoff; 9584 if (ld.dataoff > object_size) 9585 outs() << " (past end of file)\n"; 9586 else 9587 outs() << "\n"; 9588 outs() << " datasize " << ld.datasize; 9589 uint64_t big_size = ld.dataoff; 9590 big_size += ld.datasize; 9591 if (big_size > object_size) 9592 outs() << " (past end of file)\n"; 9593 else 9594 outs() << "\n"; 9595 } 9596 9597 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 9598 uint32_t cputype, bool verbose) { 9599 StringRef Buf = Obj->getData(); 9600 unsigned Index = 0; 9601 for (const auto &Command : Obj->load_commands()) { 9602 outs() << "Load command " << Index++ << "\n"; 9603 if (Command.C.cmd == MachO::LC_SEGMENT) { 9604 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 9605 const char *sg_segname = SLC.segname; 9606 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 9607 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 9608 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 9609 verbose); 9610 for (unsigned j = 0; j < SLC.nsects; j++) { 9611 MachO::section S = Obj->getSection(Command, j); 9612 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 9613 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 9614 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 9615 } 9616 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9617 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 9618 const char *sg_segname = SLC_64.segname; 9619 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 9620 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 9621 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 9622 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 9623 for (unsigned j = 0; j < SLC_64.nsects; j++) { 9624 MachO::section_64 S_64 = Obj->getSection64(Command, j); 9625 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 9626 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 9627 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 9628 sg_segname, filetype, Buf.size(), verbose); 9629 } 9630 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 9631 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9632 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 9633 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 9634 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 9635 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9636 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 9637 Obj->is64Bit()); 9638 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 9639 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 9640 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 9641 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 9642 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 9643 Command.C.cmd == MachO::LC_ID_DYLINKER || 9644 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 9645 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 9646 PrintDyldLoadCommand(Dyld, Command.Ptr); 9647 } else if (Command.C.cmd == MachO::LC_UUID) { 9648 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 9649 PrintUuidLoadCommand(Uuid); 9650 } else if (Command.C.cmd == MachO::LC_RPATH) { 9651 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 9652 PrintRpathLoadCommand(Rpath, Command.Ptr); 9653 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 9654 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 9655 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 9656 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 9657 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 9658 PrintVersionMinLoadCommand(Vd); 9659 } else if (Command.C.cmd == MachO::LC_NOTE) { 9660 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 9661 PrintNoteLoadCommand(Nt); 9662 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 9663 MachO::build_version_command Bv = 9664 Obj->getBuildVersionLoadCommand(Command); 9665 PrintBuildVersionLoadCommand(Obj, Bv); 9666 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 9667 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 9668 PrintSourceVersionCommand(Sd); 9669 } else if (Command.C.cmd == MachO::LC_MAIN) { 9670 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 9671 PrintEntryPointCommand(Ep); 9672 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 9673 MachO::encryption_info_command Ei = 9674 Obj->getEncryptionInfoCommand(Command); 9675 PrintEncryptionInfoCommand(Ei, Buf.size()); 9676 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 9677 MachO::encryption_info_command_64 Ei = 9678 Obj->getEncryptionInfoCommand64(Command); 9679 PrintEncryptionInfoCommand64(Ei, Buf.size()); 9680 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 9681 MachO::linker_option_command Lo = 9682 Obj->getLinkerOptionLoadCommand(Command); 9683 PrintLinkerOptionCommand(Lo, Command.Ptr); 9684 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 9685 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 9686 PrintSubFrameworkCommand(Sf, Command.Ptr); 9687 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 9688 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 9689 PrintSubUmbrellaCommand(Sf, Command.Ptr); 9690 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 9691 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 9692 PrintSubLibraryCommand(Sl, Command.Ptr); 9693 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 9694 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 9695 PrintSubClientCommand(Sc, Command.Ptr); 9696 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 9697 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 9698 PrintRoutinesCommand(Rc); 9699 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 9700 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 9701 PrintRoutinesCommand64(Rc); 9702 } else if (Command.C.cmd == MachO::LC_THREAD || 9703 Command.C.cmd == MachO::LC_UNIXTHREAD) { 9704 MachO::thread_command Tc = Obj->getThreadCommand(Command); 9705 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 9706 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 9707 Command.C.cmd == MachO::LC_ID_DYLIB || 9708 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 9709 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 9710 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 9711 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 9712 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 9713 PrintDylibCommand(Dl, Command.Ptr); 9714 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 9715 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 9716 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 9717 Command.C.cmd == MachO::LC_DATA_IN_CODE || 9718 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 9719 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 9720 MachO::linkedit_data_command Ld = 9721 Obj->getLinkeditDataLoadCommand(Command); 9722 PrintLinkEditDataCommand(Ld, Buf.size()); 9723 } else { 9724 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 9725 << ")\n"; 9726 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 9727 // TODO: get and print the raw bytes of the load command. 9728 } 9729 // TODO: print all the other kinds of load commands. 9730 } 9731 } 9732 9733 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 9734 if (Obj->is64Bit()) { 9735 MachO::mach_header_64 H_64; 9736 H_64 = Obj->getHeader64(); 9737 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 9738 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 9739 } else { 9740 MachO::mach_header H; 9741 H = Obj->getHeader(); 9742 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 9743 H.sizeofcmds, H.flags, verbose); 9744 } 9745 } 9746 9747 void llvm::printMachOFileHeader(const object::ObjectFile *Obj) { 9748 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9749 PrintMachHeader(file, !NonVerbose); 9750 } 9751 9752 void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) { 9753 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9754 uint32_t filetype = 0; 9755 uint32_t cputype = 0; 9756 if (file->is64Bit()) { 9757 MachO::mach_header_64 H_64; 9758 H_64 = file->getHeader64(); 9759 filetype = H_64.filetype; 9760 cputype = H_64.cputype; 9761 } else { 9762 MachO::mach_header H; 9763 H = file->getHeader(); 9764 filetype = H.filetype; 9765 cputype = H.cputype; 9766 } 9767 PrintLoadCommands(file, filetype, cputype, !NonVerbose); 9768 } 9769 9770 //===----------------------------------------------------------------------===// 9771 // export trie dumping 9772 //===----------------------------------------------------------------------===// 9773 9774 void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) { 9775 uint64_t BaseSegmentAddress = 0; 9776 for (const auto &Command : Obj->load_commands()) { 9777 if (Command.C.cmd == MachO::LC_SEGMENT) { 9778 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 9779 if (Seg.fileoff == 0 && Seg.filesize != 0) { 9780 BaseSegmentAddress = Seg.vmaddr; 9781 break; 9782 } 9783 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9784 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 9785 if (Seg.fileoff == 0 && Seg.filesize != 0) { 9786 BaseSegmentAddress = Seg.vmaddr; 9787 break; 9788 } 9789 } 9790 } 9791 Error Err = Error::success(); 9792 for (const llvm::object::ExportEntry &Entry : Obj->exports(Err)) { 9793 uint64_t Flags = Entry.flags(); 9794 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 9795 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 9796 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9797 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 9798 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9799 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 9800 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 9801 if (ReExport) 9802 outs() << "[re-export] "; 9803 else 9804 outs() << format("0x%08llX ", 9805 Entry.address() + BaseSegmentAddress); 9806 outs() << Entry.name(); 9807 if (WeakDef || ThreadLocal || Resolver || Abs) { 9808 bool NeedsComma = false; 9809 outs() << " ["; 9810 if (WeakDef) { 9811 outs() << "weak_def"; 9812 NeedsComma = true; 9813 } 9814 if (ThreadLocal) { 9815 if (NeedsComma) 9816 outs() << ", "; 9817 outs() << "per-thread"; 9818 NeedsComma = true; 9819 } 9820 if (Abs) { 9821 if (NeedsComma) 9822 outs() << ", "; 9823 outs() << "absolute"; 9824 NeedsComma = true; 9825 } 9826 if (Resolver) { 9827 if (NeedsComma) 9828 outs() << ", "; 9829 outs() << format("resolver=0x%08llX", Entry.other()); 9830 NeedsComma = true; 9831 } 9832 outs() << "]"; 9833 } 9834 if (ReExport) { 9835 StringRef DylibName = "unknown"; 9836 int Ordinal = Entry.other() - 1; 9837 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 9838 if (Entry.otherName().empty()) 9839 outs() << " (from " << DylibName << ")"; 9840 else 9841 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 9842 } 9843 outs() << "\n"; 9844 } 9845 if (Err) 9846 report_error(Obj->getFileName(), std::move(Err)); 9847 } 9848 9849 //===----------------------------------------------------------------------===// 9850 // rebase table dumping 9851 //===----------------------------------------------------------------------===// 9852 9853 void llvm::printMachORebaseTable(object::MachOObjectFile *Obj) { 9854 outs() << "segment section address type\n"; 9855 Error Err = Error::success(); 9856 for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 9857 StringRef SegmentName = Entry.segmentName(); 9858 StringRef SectionName = Entry.sectionName(); 9859 uint64_t Address = Entry.address(); 9860 9861 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 9862 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 9863 SegmentName.str().c_str(), SectionName.str().c_str(), 9864 Address, Entry.typeName().str().c_str()); 9865 } 9866 if (Err) 9867 report_error(Obj->getFileName(), std::move(Err)); 9868 } 9869 9870 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 9871 StringRef DylibName; 9872 switch (Ordinal) { 9873 case MachO::BIND_SPECIAL_DYLIB_SELF: 9874 return "this-image"; 9875 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 9876 return "main-executable"; 9877 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 9878 return "flat-namespace"; 9879 default: 9880 if (Ordinal > 0) { 9881 std::error_code EC = 9882 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 9883 if (EC) 9884 return "<<bad library ordinal>>"; 9885 return DylibName; 9886 } 9887 } 9888 return "<<unknown special ordinal>>"; 9889 } 9890 9891 //===----------------------------------------------------------------------===// 9892 // bind table dumping 9893 //===----------------------------------------------------------------------===// 9894 9895 void llvm::printMachOBindTable(object::MachOObjectFile *Obj) { 9896 // Build table of sections so names can used in final output. 9897 outs() << "segment section address type " 9898 "addend dylib symbol\n"; 9899 Error Err = Error::success(); 9900 for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 9901 StringRef SegmentName = Entry.segmentName(); 9902 StringRef SectionName = Entry.sectionName(); 9903 uint64_t Address = Entry.address(); 9904 9905 // Table lines look like: 9906 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 9907 StringRef Attr; 9908 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 9909 Attr = " (weak_import)"; 9910 outs() << left_justify(SegmentName, 8) << " " 9911 << left_justify(SectionName, 18) << " " 9912 << format_hex(Address, 10, true) << " " 9913 << left_justify(Entry.typeName(), 8) << " " 9914 << format_decimal(Entry.addend(), 8) << " " 9915 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9916 << Entry.symbolName() << Attr << "\n"; 9917 } 9918 if (Err) 9919 report_error(Obj->getFileName(), std::move(Err)); 9920 } 9921 9922 //===----------------------------------------------------------------------===// 9923 // lazy bind table dumping 9924 //===----------------------------------------------------------------------===// 9925 9926 void llvm::printMachOLazyBindTable(object::MachOObjectFile *Obj) { 9927 outs() << "segment section address " 9928 "dylib symbol\n"; 9929 Error Err = Error::success(); 9930 for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 9931 StringRef SegmentName = Entry.segmentName(); 9932 StringRef SectionName = Entry.sectionName(); 9933 uint64_t Address = Entry.address(); 9934 9935 // Table lines look like: 9936 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 9937 outs() << left_justify(SegmentName, 8) << " " 9938 << left_justify(SectionName, 18) << " " 9939 << format_hex(Address, 10, true) << " " 9940 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9941 << Entry.symbolName() << "\n"; 9942 } 9943 if (Err) 9944 report_error(Obj->getFileName(), std::move(Err)); 9945 } 9946 9947 //===----------------------------------------------------------------------===// 9948 // weak bind table dumping 9949 //===----------------------------------------------------------------------===// 9950 9951 void llvm::printMachOWeakBindTable(object::MachOObjectFile *Obj) { 9952 outs() << "segment section address " 9953 "type addend symbol\n"; 9954 Error Err = Error::success(); 9955 for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 9956 // Strong symbols don't have a location to update. 9957 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 9958 outs() << " strong " 9959 << Entry.symbolName() << "\n"; 9960 continue; 9961 } 9962 StringRef SegmentName = Entry.segmentName(); 9963 StringRef SectionName = Entry.sectionName(); 9964 uint64_t Address = Entry.address(); 9965 9966 // Table lines look like: 9967 // __DATA __data 0x00001000 pointer 0 _foo 9968 outs() << left_justify(SegmentName, 8) << " " 9969 << left_justify(SectionName, 18) << " " 9970 << format_hex(Address, 10, true) << " " 9971 << left_justify(Entry.typeName(), 8) << " " 9972 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 9973 << "\n"; 9974 } 9975 if (Err) 9976 report_error(Obj->getFileName(), std::move(Err)); 9977 } 9978 9979 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 9980 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 9981 // information for that address. If the address is found its binding symbol 9982 // name is returned. If not nullptr is returned. 9983 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 9984 struct DisassembleInfo *info) { 9985 if (info->bindtable == nullptr) { 9986 info->bindtable = llvm::make_unique<SymbolAddressMap>(); 9987 Error Err = Error::success(); 9988 for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 9989 uint64_t Address = Entry.address(); 9990 StringRef name = Entry.symbolName(); 9991 if (!name.empty()) 9992 (*info->bindtable)[Address] = name; 9993 } 9994 if (Err) 9995 report_error(info->O->getFileName(), std::move(Err)); 9996 } 9997 auto name = info->bindtable->lookup(ReferenceValue); 9998 return !name.empty() ? name.data() : nullptr; 9999 } 10000 10001