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 llvm::ArchiveHeaders("archive-headers", 80 cl::desc("Print archive headers for Mach-O archives " 81 "(requires -macho)")); 82 83 cl::opt<bool> 84 ArchiveMemberOffsets("archive-member-offsets", 85 cl::desc("Print the offset to each archive member for " 86 "Mach-O archives (requires -macho and " 87 "-archive-headers)")); 88 89 cl::opt<bool> 90 llvm::IndirectSymbols("indirect-symbols", 91 cl::desc("Print indirect symbol table for Mach-O " 92 "objects (requires -macho)")); 93 94 cl::opt<bool> 95 llvm::DataInCode("data-in-code", 96 cl::desc("Print the data in code table for Mach-O objects " 97 "(requires -macho)")); 98 99 cl::opt<bool> 100 llvm::LinkOptHints("link-opt-hints", 101 cl::desc("Print the linker optimization hints for " 102 "Mach-O objects (requires -macho)")); 103 104 cl::opt<bool> 105 llvm::InfoPlist("info-plist", 106 cl::desc("Print the info plist section as strings for " 107 "Mach-O objects (requires -macho)")); 108 109 cl::opt<bool> 110 llvm::DylibsUsed("dylibs-used", 111 cl::desc("Print the shared libraries used for linked " 112 "Mach-O files (requires -macho)")); 113 114 cl::opt<bool> 115 llvm::DylibId("dylib-id", 116 cl::desc("Print the shared library's id for the dylib Mach-O " 117 "file (requires -macho)")); 118 119 cl::opt<bool> 120 llvm::NonVerbose("non-verbose", 121 cl::desc("Print the info for Mach-O objects in " 122 "non-verbose or numeric form (requires -macho)")); 123 124 cl::opt<bool> 125 llvm::ObjcMetaData("objc-meta-data", 126 cl::desc("Print the Objective-C runtime meta data for " 127 "Mach-O files (requires -macho)")); 128 129 cl::opt<std::string> llvm::DisSymName( 130 "dis-symname", 131 cl::desc("disassemble just this symbol's instructions (requires -macho)")); 132 133 static cl::opt<bool> NoSymbolicOperands( 134 "no-symbolic-operands", 135 cl::desc("do not symbolic operands when disassembling (requires -macho)")); 136 137 static cl::list<std::string> 138 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 139 cl::ZeroOrMore); 140 141 bool ArchAll = false; 142 143 static std::string ThumbTripleName; 144 145 static const Target *GetTarget(const MachOObjectFile *MachOObj, 146 const char **McpuDefault, 147 const Target **ThumbTarget) { 148 // Figure out the target triple. 149 llvm::Triple TT(TripleName); 150 if (TripleName.empty()) { 151 TT = MachOObj->getArchTriple(McpuDefault); 152 TripleName = TT.str(); 153 } 154 155 if (TT.getArch() == Triple::arm) { 156 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs 157 // that support ARM are also capable of Thumb mode. 158 llvm::Triple ThumbTriple = TT; 159 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str(); 160 ThumbTriple.setArchName(ThumbName); 161 ThumbTripleName = ThumbTriple.str(); 162 } 163 164 // Get the target specific parser. 165 std::string Error; 166 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 167 if (TheTarget && ThumbTripleName.empty()) 168 return TheTarget; 169 170 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 171 if (*ThumbTarget) 172 return TheTarget; 173 174 errs() << "llvm-objdump: error: unable to get target for '"; 175 if (!TheTarget) 176 errs() << TripleName; 177 else 178 errs() << ThumbTripleName; 179 errs() << "', see --version and --triple.\n"; 180 return nullptr; 181 } 182 183 struct SymbolSorter { 184 bool operator()(const SymbolRef &A, const SymbolRef &B) { 185 Expected<SymbolRef::Type> ATypeOrErr = A.getType(); 186 if (!ATypeOrErr) 187 report_error(A.getObject()->getFileName(), ATypeOrErr.takeError()); 188 SymbolRef::Type AType = *ATypeOrErr; 189 Expected<SymbolRef::Type> BTypeOrErr = B.getType(); 190 if (!BTypeOrErr) 191 report_error(B.getObject()->getFileName(), BTypeOrErr.takeError()); 192 SymbolRef::Type BType = *BTypeOrErr; 193 uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue(); 194 uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue(); 195 return AAddr < BAddr; 196 } 197 }; 198 199 // Types for the storted data in code table that is built before disassembly 200 // and the predicate function to sort them. 201 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 202 typedef std::vector<DiceTableEntry> DiceTable; 203 typedef DiceTable::iterator dice_table_iterator; 204 205 #ifdef HAVE_LIBXAR 206 namespace { 207 struct ScopedXarFile { 208 xar_t xar; 209 ScopedXarFile(const char *filename, int32_t flags) 210 : xar(xar_open(filename, flags)) {} 211 ~ScopedXarFile() { 212 if (xar) 213 xar_close(xar); 214 } 215 ScopedXarFile(const ScopedXarFile &) = delete; 216 ScopedXarFile &operator=(const ScopedXarFile &) = delete; 217 operator xar_t() { return xar; } 218 }; 219 220 struct ScopedXarIter { 221 xar_iter_t iter; 222 ScopedXarIter() : iter(xar_iter_new()) {} 223 ~ScopedXarIter() { 224 if (iter) 225 xar_iter_free(iter); 226 } 227 ScopedXarIter(const ScopedXarIter &) = delete; 228 ScopedXarIter &operator=(const ScopedXarIter &) = delete; 229 operator xar_iter_t() { return iter; } 230 }; 231 } // namespace 232 #endif // defined(HAVE_LIBXAR) 233 234 // This is used to search for a data in code table entry for the PC being 235 // disassembled. The j parameter has the PC in j.first. A single data in code 236 // table entry can cover many bytes for each of its Kind's. So if the offset, 237 // aka the i.first value, of the data in code table entry plus its Length 238 // covers the PC being searched for this will return true. If not it will 239 // return false. 240 static bool compareDiceTableEntries(const DiceTableEntry &i, 241 const DiceTableEntry &j) { 242 uint16_t Length; 243 i.second.getLength(Length); 244 245 return j.first >= i.first && j.first < i.first + Length; 246 } 247 248 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 249 unsigned short Kind) { 250 uint32_t Value, Size = 1; 251 252 switch (Kind) { 253 default: 254 case MachO::DICE_KIND_DATA: 255 if (Length >= 4) { 256 if (!NoShowRawInsn) 257 dumpBytes(makeArrayRef(bytes, 4), outs()); 258 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 259 outs() << "\t.long " << Value; 260 Size = 4; 261 } else if (Length >= 2) { 262 if (!NoShowRawInsn) 263 dumpBytes(makeArrayRef(bytes, 2), outs()); 264 Value = bytes[1] << 8 | bytes[0]; 265 outs() << "\t.short " << Value; 266 Size = 2; 267 } else { 268 if (!NoShowRawInsn) 269 dumpBytes(makeArrayRef(bytes, 2), outs()); 270 Value = bytes[0]; 271 outs() << "\t.byte " << Value; 272 Size = 1; 273 } 274 if (Kind == MachO::DICE_KIND_DATA) 275 outs() << "\t@ KIND_DATA\n"; 276 else 277 outs() << "\t@ data in code kind = " << Kind << "\n"; 278 break; 279 case MachO::DICE_KIND_JUMP_TABLE8: 280 if (!NoShowRawInsn) 281 dumpBytes(makeArrayRef(bytes, 1), outs()); 282 Value = bytes[0]; 283 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 284 Size = 1; 285 break; 286 case MachO::DICE_KIND_JUMP_TABLE16: 287 if (!NoShowRawInsn) 288 dumpBytes(makeArrayRef(bytes, 2), outs()); 289 Value = bytes[1] << 8 | bytes[0]; 290 outs() << "\t.short " << format("%5u", Value & 0xffff) 291 << "\t@ KIND_JUMP_TABLE16\n"; 292 Size = 2; 293 break; 294 case MachO::DICE_KIND_JUMP_TABLE32: 295 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 296 if (!NoShowRawInsn) 297 dumpBytes(makeArrayRef(bytes, 4), outs()); 298 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 299 outs() << "\t.long " << Value; 300 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 301 outs() << "\t@ KIND_JUMP_TABLE32\n"; 302 else 303 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 304 Size = 4; 305 break; 306 } 307 return Size; 308 } 309 310 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 311 std::vector<SectionRef> &Sections, 312 std::vector<SymbolRef> &Symbols, 313 SmallVectorImpl<uint64_t> &FoundFns, 314 uint64_t &BaseSegmentAddress) { 315 for (const SymbolRef &Symbol : MachOObj->symbols()) { 316 Expected<StringRef> SymName = Symbol.getName(); 317 if (!SymName) 318 report_error(MachOObj->getFileName(), SymName.takeError()); 319 if (!SymName->startswith("ltmp")) 320 Symbols.push_back(Symbol); 321 } 322 323 for (const SectionRef &Section : MachOObj->sections()) { 324 StringRef SectName; 325 Section.getName(SectName); 326 Sections.push_back(Section); 327 } 328 329 bool BaseSegmentAddressSet = false; 330 for (const auto &Command : MachOObj->load_commands()) { 331 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 332 // We found a function starts segment, parse the addresses for later 333 // consumption. 334 MachO::linkedit_data_command LLC = 335 MachOObj->getLinkeditDataLoadCommand(Command); 336 337 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 338 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 339 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 340 StringRef SegName = SLC.segname; 341 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 342 BaseSegmentAddressSet = true; 343 BaseSegmentAddress = SLC.vmaddr; 344 } 345 } 346 } 347 } 348 349 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 350 uint32_t n, uint32_t count, 351 uint32_t stride, uint64_t addr) { 352 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 353 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 354 if (n > nindirectsyms) 355 outs() << " (entries start past the end of the indirect symbol " 356 "table) (reserved1 field greater than the table size)"; 357 else if (n + count > nindirectsyms) 358 outs() << " (entries extends past the end of the indirect symbol " 359 "table)"; 360 outs() << "\n"; 361 uint32_t cputype = O->getHeader().cputype; 362 if (cputype & MachO::CPU_ARCH_ABI64) 363 outs() << "address index"; 364 else 365 outs() << "address index"; 366 if (verbose) 367 outs() << " name\n"; 368 else 369 outs() << "\n"; 370 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 371 if (cputype & MachO::CPU_ARCH_ABI64) 372 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 373 else 374 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 375 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 376 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 377 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 378 outs() << "LOCAL\n"; 379 continue; 380 } 381 if (indirect_symbol == 382 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 383 outs() << "LOCAL ABSOLUTE\n"; 384 continue; 385 } 386 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 387 outs() << "ABSOLUTE\n"; 388 continue; 389 } 390 outs() << format("%5u ", indirect_symbol); 391 if (verbose) { 392 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 393 if (indirect_symbol < Symtab.nsyms) { 394 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 395 SymbolRef Symbol = *Sym; 396 Expected<StringRef> SymName = Symbol.getName(); 397 if (!SymName) 398 report_error(O->getFileName(), SymName.takeError()); 399 outs() << *SymName; 400 } else { 401 outs() << "?"; 402 } 403 } 404 outs() << "\n"; 405 } 406 } 407 408 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 409 for (const auto &Load : O->load_commands()) { 410 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 411 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 412 for (unsigned J = 0; J < Seg.nsects; ++J) { 413 MachO::section_64 Sec = O->getSection64(Load, J); 414 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 415 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 416 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 417 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 418 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 419 section_type == MachO::S_SYMBOL_STUBS) { 420 uint32_t stride; 421 if (section_type == MachO::S_SYMBOL_STUBS) 422 stride = Sec.reserved2; 423 else 424 stride = 8; 425 if (stride == 0) { 426 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 427 << Sec.sectname << ") " 428 << "(size of stubs in reserved2 field is zero)\n"; 429 continue; 430 } 431 uint32_t count = Sec.size / stride; 432 outs() << "Indirect symbols for (" << Sec.segname << "," 433 << Sec.sectname << ") " << count << " entries"; 434 uint32_t n = Sec.reserved1; 435 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 436 } 437 } 438 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 439 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 440 for (unsigned J = 0; J < Seg.nsects; ++J) { 441 MachO::section Sec = O->getSection(Load, J); 442 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 443 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 444 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 445 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 446 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 447 section_type == MachO::S_SYMBOL_STUBS) { 448 uint32_t stride; 449 if (section_type == MachO::S_SYMBOL_STUBS) 450 stride = Sec.reserved2; 451 else 452 stride = 4; 453 if (stride == 0) { 454 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 455 << Sec.sectname << ") " 456 << "(size of stubs in reserved2 field is zero)\n"; 457 continue; 458 } 459 uint32_t count = Sec.size / stride; 460 outs() << "Indirect symbols for (" << Sec.segname << "," 461 << Sec.sectname << ") " << count << " entries"; 462 uint32_t n = Sec.reserved1; 463 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 464 } 465 } 466 } 467 } 468 } 469 470 static void PrintRType(const uint64_t cputype, const unsigned r_type) { 471 static char const *generic_r_types[] = { 472 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ", 473 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", 474 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 475 }; 476 static char const *x86_64_r_types[] = { 477 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", 478 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ", 479 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 480 }; 481 static char const *arm_r_types[] = { 482 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", 483 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ", 484 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 485 }; 486 static char const *arm64_r_types[] = { 487 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", 488 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", 489 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 490 }; 491 492 if (r_type > 0xf){ 493 outs() << format("%-7u", r_type) << " "; 494 return; 495 } 496 switch (cputype) { 497 case MachO::CPU_TYPE_I386: 498 outs() << generic_r_types[r_type]; 499 break; 500 case MachO::CPU_TYPE_X86_64: 501 outs() << x86_64_r_types[r_type]; 502 break; 503 case MachO::CPU_TYPE_ARM: 504 outs() << arm_r_types[r_type]; 505 break; 506 case MachO::CPU_TYPE_ARM64: 507 outs() << arm64_r_types[r_type]; 508 break; 509 default: 510 outs() << format("%-7u ", r_type); 511 } 512 } 513 514 static void PrintRLength(const uint64_t cputype, const unsigned r_type, 515 const unsigned r_length, const bool previous_arm_half){ 516 if (cputype == MachO::CPU_TYPE_ARM && 517 (r_type == llvm::MachO::ARM_RELOC_HALF || 518 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF || 519 previous_arm_half == true)) { 520 if ((r_length & 0x1) == 0) 521 outs() << "lo/"; 522 else 523 outs() << "hi/"; 524 if ((r_length & 0x1) == 0) 525 outs() << "arm "; 526 else 527 outs() << "thm "; 528 } else { 529 switch (r_length) { 530 case 0: 531 outs() << "byte "; 532 break; 533 case 1: 534 outs() << "word "; 535 break; 536 case 2: 537 outs() << "long "; 538 break; 539 case 3: 540 if (cputype == MachO::CPU_TYPE_X86_64) 541 outs() << "quad "; 542 else 543 outs() << format("?(%2d) ", r_length); 544 break; 545 default: 546 outs() << format("?(%2d) ", r_length); 547 } 548 } 549 } 550 551 static void PrintRelocationEntries(const MachOObjectFile *O, 552 const relocation_iterator Begin, 553 const relocation_iterator End, 554 const uint64_t cputype, 555 const bool verbose) { 556 const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 557 bool previous_arm_half = false; 558 bool previous_sectdiff = false; 559 uint32_t sectdiff_r_type = 0; 560 561 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { 562 const DataRefImpl Rel = Reloc->getRawDataRefImpl(); 563 const MachO::any_relocation_info RE = O->getRelocation(Rel); 564 const unsigned r_type = O->getAnyRelocationType(RE); 565 const bool r_scattered = O->isRelocationScattered(RE); 566 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); 567 const unsigned r_length = O->getAnyRelocationLength(RE); 568 const unsigned r_address = O->getAnyRelocationAddress(RE); 569 const bool r_extern = (r_scattered ? false : 570 O->getPlainRelocationExternal(RE)); 571 const uint32_t r_value = (r_scattered ? 572 O->getScatteredRelocationValue(RE) : 0); 573 const unsigned r_symbolnum = (r_scattered ? 0 : 574 O->getPlainRelocationSymbolNum(RE)); 575 576 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { 577 if (verbose) { 578 // scattered: address 579 if ((cputype == MachO::CPU_TYPE_I386 && 580 r_type == llvm::MachO::GENERIC_RELOC_PAIR) || 581 (cputype == MachO::CPU_TYPE_ARM && 582 r_type == llvm::MachO::ARM_RELOC_PAIR)) 583 outs() << " "; 584 else 585 outs() << format("%08x ", (unsigned int)r_address); 586 587 // scattered: pcrel 588 if (r_pcrel) 589 outs() << "True "; 590 else 591 outs() << "False "; 592 593 // scattered: length 594 PrintRLength(cputype, r_type, r_length, previous_arm_half); 595 596 // scattered: extern & type 597 outs() << "n/a "; 598 PrintRType(cputype, r_type); 599 600 // scattered: scattered & value 601 outs() << format("True 0x%08x", (unsigned int)r_value); 602 if (previous_sectdiff == false) { 603 if ((cputype == MachO::CPU_TYPE_ARM && 604 r_type == llvm::MachO::ARM_RELOC_PAIR)) 605 outs() << format(" half = 0x%04x ", (unsigned int)r_address); 606 } 607 else if (cputype == MachO::CPU_TYPE_ARM && 608 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF) 609 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); 610 if ((cputype == MachO::CPU_TYPE_I386 && 611 (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF || 612 r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || 613 (cputype == MachO::CPU_TYPE_ARM && 614 (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF || 615 sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF || 616 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) { 617 previous_sectdiff = true; 618 sectdiff_r_type = r_type; 619 } 620 else { 621 previous_sectdiff = false; 622 sectdiff_r_type = 0; 623 } 624 if (cputype == MachO::CPU_TYPE_ARM && 625 (r_type == llvm::MachO::ARM_RELOC_HALF || 626 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) 627 previous_arm_half = true; 628 else 629 previous_arm_half = false; 630 outs() << "\n"; 631 } 632 else { 633 // scattered: address pcrel length extern type scattered value 634 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n", 635 (unsigned int)r_address, r_pcrel, r_length, r_type, 636 (unsigned int)r_value); 637 } 638 } 639 else { 640 if (verbose) { 641 // plain: address 642 if (cputype == MachO::CPU_TYPE_ARM && 643 r_type == llvm::MachO::ARM_RELOC_PAIR) 644 outs() << " "; 645 else 646 outs() << format("%08x ", (unsigned int)r_address); 647 648 // plain: pcrel 649 if (r_pcrel) 650 outs() << "True "; 651 else 652 outs() << "False "; 653 654 // plain: length 655 PrintRLength(cputype, r_type, r_length, previous_arm_half); 656 657 if (r_extern) { 658 // plain: extern & type & scattered 659 outs() << "True "; 660 PrintRType(cputype, r_type); 661 outs() << "False "; 662 663 // plain: symbolnum/value 664 if (r_symbolnum > Symtab.nsyms) 665 outs() << format("?(%d)\n", r_symbolnum); 666 else { 667 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); 668 Expected<StringRef> SymNameNext = Symbol.getName(); 669 const char *name = NULL; 670 if (SymNameNext) 671 name = SymNameNext->data(); 672 if (name == NULL) 673 outs() << format("?(%d)\n", r_symbolnum); 674 else 675 outs() << name << "\n"; 676 } 677 } 678 else { 679 // plain: extern & type & scattered 680 outs() << "False "; 681 PrintRType(cputype, r_type); 682 outs() << "False "; 683 684 // plain: symbolnum/value 685 if (cputype == MachO::CPU_TYPE_ARM && 686 r_type == llvm::MachO::ARM_RELOC_PAIR) 687 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); 688 else if (cputype == MachO::CPU_TYPE_ARM64 && 689 r_type == llvm::MachO::ARM64_RELOC_ADDEND) 690 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); 691 else { 692 outs() << format("%d ", r_symbolnum); 693 if (r_symbolnum == llvm::MachO::R_ABS) 694 outs() << "R_ABS\n"; 695 else { 696 // in this case, r_symbolnum is actually a 1-based section number 697 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; 698 if (r_symbolnum > 0 && r_symbolnum <= nsects) { 699 llvm::object::DataRefImpl DRI; 700 DRI.d.a = r_symbolnum-1; 701 StringRef SegName = O->getSectionFinalSegmentName(DRI); 702 StringRef SectName; 703 if (O->getSectionName(DRI, SectName)) 704 outs() << "(?,?)\n"; 705 else 706 outs() << "(" << SegName << "," << SectName << ")\n"; 707 } 708 else { 709 outs() << "(?,?)\n"; 710 } 711 } 712 } 713 } 714 if (cputype == MachO::CPU_TYPE_ARM && 715 (r_type == llvm::MachO::ARM_RELOC_HALF || 716 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) 717 previous_arm_half = true; 718 else 719 previous_arm_half = false; 720 } 721 else { 722 // plain: address pcrel length extern type scattered symbolnum/section 723 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n", 724 (unsigned int)r_address, r_pcrel, r_length, r_extern, 725 r_type, r_symbolnum); 726 } 727 } 728 } 729 } 730 731 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { 732 const uint64_t cputype = O->getHeader().cputype; 733 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 734 if (Dysymtab.nextrel != 0) { 735 outs() << "External relocation information " << Dysymtab.nextrel 736 << " entries"; 737 outs() << "\naddress pcrel length extern type scattered " 738 "symbolnum/value\n"; 739 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, 740 verbose); 741 } 742 if (Dysymtab.nlocrel != 0) { 743 outs() << format("Local relocation information %u entries", 744 Dysymtab.nlocrel); 745 outs() << "\naddress pcrel length extern type scattered " 746 "symbolnum/value\n"; 747 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, 748 verbose); 749 } 750 for (const auto &Load : O->load_commands()) { 751 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 752 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 753 for (unsigned J = 0; J < Seg.nsects; ++J) { 754 const MachO::section_64 Sec = O->getSection64(Load, J); 755 if (Sec.nreloc != 0) { 756 DataRefImpl DRI; 757 DRI.d.a = J; 758 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 759 StringRef SectName; 760 if (O->getSectionName(DRI, SectName)) 761 outs() << "Relocation information (" << SegName << ",?) " 762 << format("%u entries", Sec.nreloc); 763 else 764 outs() << "Relocation information (" << SegName << "," 765 << SectName << format(") %u entries", Sec.nreloc); 766 outs() << "\naddress pcrel length extern type scattered " 767 "symbolnum/value\n"; 768 PrintRelocationEntries(O, O->section_rel_begin(DRI), 769 O->section_rel_end(DRI), cputype, verbose); 770 } 771 } 772 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 773 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 774 for (unsigned J = 0; J < Seg.nsects; ++J) { 775 const MachO::section Sec = O->getSection(Load, J); 776 if (Sec.nreloc != 0) { 777 DataRefImpl DRI; 778 DRI.d.a = J; 779 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 780 StringRef SectName; 781 if (O->getSectionName(DRI, SectName)) 782 outs() << "Relocation information (" << SegName << ",?) " 783 << format("%u entries", Sec.nreloc); 784 else 785 outs() << "Relocation information (" << SegName << "," 786 << SectName << format(") %u entries", Sec.nreloc); 787 outs() << "\naddress pcrel length extern type scattered " 788 "symbolnum/value\n"; 789 PrintRelocationEntries(O, O->section_rel_begin(DRI), 790 O->section_rel_end(DRI), cputype, verbose); 791 } 792 } 793 } 794 } 795 } 796 797 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 798 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 799 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 800 outs() << "Data in code table (" << nentries << " entries)\n"; 801 outs() << "offset length kind\n"; 802 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 803 ++DI) { 804 uint32_t Offset; 805 DI->getOffset(Offset); 806 outs() << format("0x%08" PRIx32, Offset) << " "; 807 uint16_t Length; 808 DI->getLength(Length); 809 outs() << format("%6u", Length) << " "; 810 uint16_t Kind; 811 DI->getKind(Kind); 812 if (verbose) { 813 switch (Kind) { 814 case MachO::DICE_KIND_DATA: 815 outs() << "DATA"; 816 break; 817 case MachO::DICE_KIND_JUMP_TABLE8: 818 outs() << "JUMP_TABLE8"; 819 break; 820 case MachO::DICE_KIND_JUMP_TABLE16: 821 outs() << "JUMP_TABLE16"; 822 break; 823 case MachO::DICE_KIND_JUMP_TABLE32: 824 outs() << "JUMP_TABLE32"; 825 break; 826 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 827 outs() << "ABS_JUMP_TABLE32"; 828 break; 829 default: 830 outs() << format("0x%04" PRIx32, Kind); 831 break; 832 } 833 } else 834 outs() << format("0x%04" PRIx32, Kind); 835 outs() << "\n"; 836 } 837 } 838 839 static void PrintLinkOptHints(MachOObjectFile *O) { 840 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 841 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 842 uint32_t nloh = LohLC.datasize; 843 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 844 for (uint32_t i = 0; i < nloh;) { 845 unsigned n; 846 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 847 i += n; 848 outs() << " identifier " << identifier << " "; 849 if (i >= nloh) 850 return; 851 switch (identifier) { 852 case 1: 853 outs() << "AdrpAdrp\n"; 854 break; 855 case 2: 856 outs() << "AdrpLdr\n"; 857 break; 858 case 3: 859 outs() << "AdrpAddLdr\n"; 860 break; 861 case 4: 862 outs() << "AdrpLdrGotLdr\n"; 863 break; 864 case 5: 865 outs() << "AdrpAddStr\n"; 866 break; 867 case 6: 868 outs() << "AdrpLdrGotStr\n"; 869 break; 870 case 7: 871 outs() << "AdrpAdd\n"; 872 break; 873 case 8: 874 outs() << "AdrpLdrGot\n"; 875 break; 876 default: 877 outs() << "Unknown identifier value\n"; 878 break; 879 } 880 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 881 i += n; 882 outs() << " narguments " << narguments << "\n"; 883 if (i >= nloh) 884 return; 885 886 for (uint32_t j = 0; j < narguments; j++) { 887 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 888 i += n; 889 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 890 if (i >= nloh) 891 return; 892 } 893 } 894 } 895 896 static void PrintDylibs(MachOObjectFile *O, bool JustId) { 897 unsigned Index = 0; 898 for (const auto &Load : O->load_commands()) { 899 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 900 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 901 Load.C.cmd == MachO::LC_LOAD_DYLIB || 902 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 903 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 904 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 905 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 906 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 907 if (dl.dylib.name < dl.cmdsize) { 908 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 909 if (JustId) 910 outs() << p << "\n"; 911 else { 912 outs() << "\t" << p; 913 outs() << " (compatibility version " 914 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 915 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 916 << (dl.dylib.compatibility_version & 0xff) << ","; 917 outs() << " current version " 918 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 919 << ((dl.dylib.current_version >> 8) & 0xff) << "." 920 << (dl.dylib.current_version & 0xff) << ")\n"; 921 } 922 } else { 923 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 924 if (Load.C.cmd == MachO::LC_ID_DYLIB) 925 outs() << "LC_ID_DYLIB "; 926 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 927 outs() << "LC_LOAD_DYLIB "; 928 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 929 outs() << "LC_LOAD_WEAK_DYLIB "; 930 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 931 outs() << "LC_LAZY_LOAD_DYLIB "; 932 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 933 outs() << "LC_REEXPORT_DYLIB "; 934 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 935 outs() << "LC_LOAD_UPWARD_DYLIB "; 936 else 937 outs() << "LC_??? "; 938 outs() << "command " << Index++ << "\n"; 939 } 940 } 941 } 942 } 943 944 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 945 946 static void CreateSymbolAddressMap(MachOObjectFile *O, 947 SymbolAddressMap *AddrMap) { 948 // Create a map of symbol addresses to symbol names. 949 for (const SymbolRef &Symbol : O->symbols()) { 950 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 951 if (!STOrErr) 952 report_error(O->getFileName(), STOrErr.takeError()); 953 SymbolRef::Type ST = *STOrErr; 954 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 955 ST == SymbolRef::ST_Other) { 956 uint64_t Address = Symbol.getValue(); 957 Expected<StringRef> SymNameOrErr = Symbol.getName(); 958 if (!SymNameOrErr) 959 report_error(O->getFileName(), SymNameOrErr.takeError()); 960 StringRef SymName = *SymNameOrErr; 961 if (!SymName.startswith(".objc")) 962 (*AddrMap)[Address] = SymName; 963 } 964 } 965 } 966 967 // GuessSymbolName is passed the address of what might be a symbol and a 968 // pointer to the SymbolAddressMap. It returns the name of a symbol 969 // with that address or nullptr if no symbol is found with that address. 970 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 971 const char *SymbolName = nullptr; 972 // A DenseMap can't lookup up some values. 973 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 974 StringRef name = AddrMap->lookup(value); 975 if (!name.empty()) 976 SymbolName = name.data(); 977 } 978 return SymbolName; 979 } 980 981 static void DumpCstringChar(const char c) { 982 char p[2]; 983 p[0] = c; 984 p[1] = '\0'; 985 outs().write_escaped(p); 986 } 987 988 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 989 uint32_t sect_size, uint64_t sect_addr, 990 bool print_addresses) { 991 for (uint32_t i = 0; i < sect_size; i++) { 992 if (print_addresses) { 993 if (O->is64Bit()) 994 outs() << format("%016" PRIx64, sect_addr + i) << " "; 995 else 996 outs() << format("%08" PRIx64, sect_addr + i) << " "; 997 } 998 for (; i < sect_size && sect[i] != '\0'; i++) 999 DumpCstringChar(sect[i]); 1000 if (i < sect_size && sect[i] == '\0') 1001 outs() << "\n"; 1002 } 1003 } 1004 1005 static void DumpLiteral4(uint32_t l, float f) { 1006 outs() << format("0x%08" PRIx32, l); 1007 if ((l & 0x7f800000) != 0x7f800000) 1008 outs() << format(" (%.16e)\n", f); 1009 else { 1010 if (l == 0x7f800000) 1011 outs() << " (+Infinity)\n"; 1012 else if (l == 0xff800000) 1013 outs() << " (-Infinity)\n"; 1014 else if ((l & 0x00400000) == 0x00400000) 1015 outs() << " (non-signaling Not-a-Number)\n"; 1016 else 1017 outs() << " (signaling Not-a-Number)\n"; 1018 } 1019 } 1020 1021 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 1022 uint32_t sect_size, uint64_t sect_addr, 1023 bool print_addresses) { 1024 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 1025 if (print_addresses) { 1026 if (O->is64Bit()) 1027 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1028 else 1029 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1030 } 1031 float f; 1032 memcpy(&f, sect + i, sizeof(float)); 1033 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1034 sys::swapByteOrder(f); 1035 uint32_t l; 1036 memcpy(&l, sect + i, sizeof(uint32_t)); 1037 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1038 sys::swapByteOrder(l); 1039 DumpLiteral4(l, f); 1040 } 1041 } 1042 1043 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 1044 double d) { 1045 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 1046 uint32_t Hi, Lo; 1047 Hi = (O->isLittleEndian()) ? l1 : l0; 1048 Lo = (O->isLittleEndian()) ? l0 : l1; 1049 1050 // Hi is the high word, so this is equivalent to if(isfinite(d)) 1051 if ((Hi & 0x7ff00000) != 0x7ff00000) 1052 outs() << format(" (%.16e)\n", d); 1053 else { 1054 if (Hi == 0x7ff00000 && Lo == 0) 1055 outs() << " (+Infinity)\n"; 1056 else if (Hi == 0xfff00000 && Lo == 0) 1057 outs() << " (-Infinity)\n"; 1058 else if ((Hi & 0x00080000) == 0x00080000) 1059 outs() << " (non-signaling Not-a-Number)\n"; 1060 else 1061 outs() << " (signaling Not-a-Number)\n"; 1062 } 1063 } 1064 1065 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 1066 uint32_t sect_size, uint64_t sect_addr, 1067 bool print_addresses) { 1068 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 1069 if (print_addresses) { 1070 if (O->is64Bit()) 1071 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1072 else 1073 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1074 } 1075 double d; 1076 memcpy(&d, sect + i, sizeof(double)); 1077 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1078 sys::swapByteOrder(d); 1079 uint32_t l0, l1; 1080 memcpy(&l0, sect + i, sizeof(uint32_t)); 1081 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1082 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1083 sys::swapByteOrder(l0); 1084 sys::swapByteOrder(l1); 1085 } 1086 DumpLiteral8(O, l0, l1, d); 1087 } 1088 } 1089 1090 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 1091 outs() << format("0x%08" PRIx32, l0) << " "; 1092 outs() << format("0x%08" PRIx32, l1) << " "; 1093 outs() << format("0x%08" PRIx32, l2) << " "; 1094 outs() << format("0x%08" PRIx32, l3) << "\n"; 1095 } 1096 1097 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 1098 uint32_t sect_size, uint64_t sect_addr, 1099 bool print_addresses) { 1100 for (uint32_t i = 0; i < sect_size; i += 16) { 1101 if (print_addresses) { 1102 if (O->is64Bit()) 1103 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1104 else 1105 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1106 } 1107 uint32_t l0, l1, l2, l3; 1108 memcpy(&l0, sect + i, sizeof(uint32_t)); 1109 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1110 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 1111 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1112 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1113 sys::swapByteOrder(l0); 1114 sys::swapByteOrder(l1); 1115 sys::swapByteOrder(l2); 1116 sys::swapByteOrder(l3); 1117 } 1118 DumpLiteral16(l0, l1, l2, l3); 1119 } 1120 } 1121 1122 static void DumpLiteralPointerSection(MachOObjectFile *O, 1123 const SectionRef &Section, 1124 const char *sect, uint32_t sect_size, 1125 uint64_t sect_addr, 1126 bool print_addresses) { 1127 // Collect the literal sections in this Mach-O file. 1128 std::vector<SectionRef> LiteralSections; 1129 for (const SectionRef &Section : O->sections()) { 1130 DataRefImpl Ref = Section.getRawDataRefImpl(); 1131 uint32_t section_type; 1132 if (O->is64Bit()) { 1133 const MachO::section_64 Sec = O->getSection64(Ref); 1134 section_type = Sec.flags & MachO::SECTION_TYPE; 1135 } else { 1136 const MachO::section Sec = O->getSection(Ref); 1137 section_type = Sec.flags & MachO::SECTION_TYPE; 1138 } 1139 if (section_type == MachO::S_CSTRING_LITERALS || 1140 section_type == MachO::S_4BYTE_LITERALS || 1141 section_type == MachO::S_8BYTE_LITERALS || 1142 section_type == MachO::S_16BYTE_LITERALS) 1143 LiteralSections.push_back(Section); 1144 } 1145 1146 // Set the size of the literal pointer. 1147 uint32_t lp_size = O->is64Bit() ? 8 : 4; 1148 1149 // Collect the external relocation symbols for the literal pointers. 1150 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1151 for (const RelocationRef &Reloc : Section.relocations()) { 1152 DataRefImpl Rel; 1153 MachO::any_relocation_info RE; 1154 bool isExtern = false; 1155 Rel = Reloc.getRawDataRefImpl(); 1156 RE = O->getRelocation(Rel); 1157 isExtern = O->getPlainRelocationExternal(RE); 1158 if (isExtern) { 1159 uint64_t RelocOffset = Reloc.getOffset(); 1160 symbol_iterator RelocSym = Reloc.getSymbol(); 1161 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1162 } 1163 } 1164 array_pod_sort(Relocs.begin(), Relocs.end()); 1165 1166 // Dump each literal pointer. 1167 for (uint32_t i = 0; i < sect_size; i += lp_size) { 1168 if (print_addresses) { 1169 if (O->is64Bit()) 1170 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1171 else 1172 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1173 } 1174 uint64_t lp; 1175 if (O->is64Bit()) { 1176 memcpy(&lp, sect + i, sizeof(uint64_t)); 1177 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1178 sys::swapByteOrder(lp); 1179 } else { 1180 uint32_t li; 1181 memcpy(&li, sect + i, sizeof(uint32_t)); 1182 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1183 sys::swapByteOrder(li); 1184 lp = li; 1185 } 1186 1187 // First look for an external relocation entry for this literal pointer. 1188 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1189 return P.first == i; 1190 }); 1191 if (Reloc != Relocs.end()) { 1192 symbol_iterator RelocSym = Reloc->second; 1193 Expected<StringRef> SymName = RelocSym->getName(); 1194 if (!SymName) 1195 report_error(O->getFileName(), SymName.takeError()); 1196 outs() << "external relocation entry for symbol:" << *SymName << "\n"; 1197 continue; 1198 } 1199 1200 // For local references see what the section the literal pointer points to. 1201 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 1202 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 1203 }); 1204 if (Sect == LiteralSections.end()) { 1205 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 1206 continue; 1207 } 1208 1209 uint64_t SectAddress = Sect->getAddress(); 1210 uint64_t SectSize = Sect->getSize(); 1211 1212 StringRef SectName; 1213 Sect->getName(SectName); 1214 DataRefImpl Ref = Sect->getRawDataRefImpl(); 1215 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 1216 outs() << SegmentName << ":" << SectName << ":"; 1217 1218 uint32_t section_type; 1219 if (O->is64Bit()) { 1220 const MachO::section_64 Sec = O->getSection64(Ref); 1221 section_type = Sec.flags & MachO::SECTION_TYPE; 1222 } else { 1223 const MachO::section Sec = O->getSection(Ref); 1224 section_type = Sec.flags & MachO::SECTION_TYPE; 1225 } 1226 1227 StringRef BytesStr; 1228 Sect->getContents(BytesStr); 1229 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 1230 1231 switch (section_type) { 1232 case MachO::S_CSTRING_LITERALS: 1233 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 1234 i++) { 1235 DumpCstringChar(Contents[i]); 1236 } 1237 outs() << "\n"; 1238 break; 1239 case MachO::S_4BYTE_LITERALS: 1240 float f; 1241 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 1242 uint32_t l; 1243 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 1244 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1245 sys::swapByteOrder(f); 1246 sys::swapByteOrder(l); 1247 } 1248 DumpLiteral4(l, f); 1249 break; 1250 case MachO::S_8BYTE_LITERALS: { 1251 double d; 1252 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 1253 uint32_t l0, l1; 1254 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1255 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1256 sizeof(uint32_t)); 1257 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1258 sys::swapByteOrder(f); 1259 sys::swapByteOrder(l0); 1260 sys::swapByteOrder(l1); 1261 } 1262 DumpLiteral8(O, l0, l1, d); 1263 break; 1264 } 1265 case MachO::S_16BYTE_LITERALS: { 1266 uint32_t l0, l1, l2, l3; 1267 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1268 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1269 sizeof(uint32_t)); 1270 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 1271 sizeof(uint32_t)); 1272 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 1273 sizeof(uint32_t)); 1274 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1275 sys::swapByteOrder(l0); 1276 sys::swapByteOrder(l1); 1277 sys::swapByteOrder(l2); 1278 sys::swapByteOrder(l3); 1279 } 1280 DumpLiteral16(l0, l1, l2, l3); 1281 break; 1282 } 1283 } 1284 } 1285 } 1286 1287 static void DumpInitTermPointerSection(MachOObjectFile *O, 1288 const SectionRef &Section, 1289 const char *sect, 1290 uint32_t sect_size, uint64_t sect_addr, 1291 SymbolAddressMap *AddrMap, 1292 bool verbose) { 1293 uint32_t stride; 1294 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 1295 1296 // Collect the external relocation symbols for the pointers. 1297 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1298 for (const RelocationRef &Reloc : Section.relocations()) { 1299 DataRefImpl Rel; 1300 MachO::any_relocation_info RE; 1301 bool isExtern = false; 1302 Rel = Reloc.getRawDataRefImpl(); 1303 RE = O->getRelocation(Rel); 1304 isExtern = O->getPlainRelocationExternal(RE); 1305 if (isExtern) { 1306 uint64_t RelocOffset = Reloc.getOffset(); 1307 symbol_iterator RelocSym = Reloc.getSymbol(); 1308 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1309 } 1310 } 1311 array_pod_sort(Relocs.begin(), Relocs.end()); 1312 1313 for (uint32_t i = 0; i < sect_size; i += stride) { 1314 const char *SymbolName = nullptr; 1315 uint64_t p; 1316 if (O->is64Bit()) { 1317 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 1318 uint64_t pointer_value; 1319 memcpy(&pointer_value, sect + i, stride); 1320 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1321 sys::swapByteOrder(pointer_value); 1322 outs() << format("0x%016" PRIx64, pointer_value); 1323 p = pointer_value; 1324 } else { 1325 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 1326 uint32_t pointer_value; 1327 memcpy(&pointer_value, sect + i, stride); 1328 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1329 sys::swapByteOrder(pointer_value); 1330 outs() << format("0x%08" PRIx32, pointer_value); 1331 p = pointer_value; 1332 } 1333 if (verbose) { 1334 // First look for an external relocation entry for this pointer. 1335 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1336 return P.first == i; 1337 }); 1338 if (Reloc != Relocs.end()) { 1339 symbol_iterator RelocSym = Reloc->second; 1340 Expected<StringRef> SymName = RelocSym->getName(); 1341 if (!SymName) 1342 report_error(O->getFileName(), SymName.takeError()); 1343 outs() << " " << *SymName; 1344 } else { 1345 SymbolName = GuessSymbolName(p, AddrMap); 1346 if (SymbolName) 1347 outs() << " " << SymbolName; 1348 } 1349 } 1350 outs() << "\n"; 1351 } 1352 } 1353 1354 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 1355 uint32_t size, uint64_t addr) { 1356 uint32_t cputype = O->getHeader().cputype; 1357 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 1358 uint32_t j; 1359 for (uint32_t i = 0; i < size; i += j, addr += j) { 1360 if (O->is64Bit()) 1361 outs() << format("%016" PRIx64, addr) << "\t"; 1362 else 1363 outs() << format("%08" PRIx64, addr) << "\t"; 1364 for (j = 0; j < 16 && i + j < size; j++) { 1365 uint8_t byte_word = *(sect + i + j); 1366 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1367 } 1368 outs() << "\n"; 1369 } 1370 } else { 1371 uint32_t j; 1372 for (uint32_t i = 0; i < size; i += j, addr += j) { 1373 if (O->is64Bit()) 1374 outs() << format("%016" PRIx64, addr) << "\t"; 1375 else 1376 outs() << format("%08" PRIx64, addr) << "\t"; 1377 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 1378 j += sizeof(int32_t)) { 1379 if (i + j + sizeof(int32_t) <= size) { 1380 uint32_t long_word; 1381 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1382 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1383 sys::swapByteOrder(long_word); 1384 outs() << format("%08" PRIx32, long_word) << " "; 1385 } else { 1386 for (uint32_t k = 0; i + j + k < size; k++) { 1387 uint8_t byte_word = *(sect + i + j + k); 1388 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1389 } 1390 } 1391 } 1392 outs() << "\n"; 1393 } 1394 } 1395 } 1396 1397 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1398 StringRef DisSegName, StringRef DisSectName); 1399 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1400 uint32_t size, uint32_t addr); 1401 #ifdef HAVE_LIBXAR 1402 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 1403 uint32_t size, bool verbose, 1404 bool PrintXarHeader, bool PrintXarFileHeaders, 1405 std::string XarMemberName); 1406 #endif // defined(HAVE_LIBXAR) 1407 1408 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1409 bool verbose) { 1410 SymbolAddressMap AddrMap; 1411 if (verbose) 1412 CreateSymbolAddressMap(O, &AddrMap); 1413 1414 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1415 StringRef DumpSection = FilterSections[i]; 1416 std::pair<StringRef, StringRef> DumpSegSectName; 1417 DumpSegSectName = DumpSection.split(','); 1418 StringRef DumpSegName, DumpSectName; 1419 if (DumpSegSectName.second.size()) { 1420 DumpSegName = DumpSegSectName.first; 1421 DumpSectName = DumpSegSectName.second; 1422 } else { 1423 DumpSegName = ""; 1424 DumpSectName = DumpSegSectName.first; 1425 } 1426 for (const SectionRef &Section : O->sections()) { 1427 StringRef SectName; 1428 Section.getName(SectName); 1429 DataRefImpl Ref = Section.getRawDataRefImpl(); 1430 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1431 if ((DumpSegName.empty() || SegName == DumpSegName) && 1432 (SectName == DumpSectName)) { 1433 1434 uint32_t section_flags; 1435 if (O->is64Bit()) { 1436 const MachO::section_64 Sec = O->getSection64(Ref); 1437 section_flags = Sec.flags; 1438 1439 } else { 1440 const MachO::section Sec = O->getSection(Ref); 1441 section_flags = Sec.flags; 1442 } 1443 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1444 1445 StringRef BytesStr; 1446 Section.getContents(BytesStr); 1447 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1448 uint32_t sect_size = BytesStr.size(); 1449 uint64_t sect_addr = Section.getAddress(); 1450 1451 outs() << "Contents of (" << SegName << "," << SectName 1452 << ") section\n"; 1453 1454 if (verbose) { 1455 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1456 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1457 DisassembleMachO(Filename, O, SegName, SectName); 1458 continue; 1459 } 1460 if (SegName == "__TEXT" && SectName == "__info_plist") { 1461 outs() << sect; 1462 continue; 1463 } 1464 if (SegName == "__OBJC" && SectName == "__protocol") { 1465 DumpProtocolSection(O, sect, sect_size, sect_addr); 1466 continue; 1467 } 1468 #ifdef HAVE_LIBXAR 1469 if (SegName == "__LLVM" && SectName == "__bundle") { 1470 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands, 1471 ArchiveHeaders, ""); 1472 continue; 1473 } 1474 #endif // defined(HAVE_LIBXAR) 1475 switch (section_type) { 1476 case MachO::S_REGULAR: 1477 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1478 break; 1479 case MachO::S_ZEROFILL: 1480 outs() << "zerofill section and has no contents in the file\n"; 1481 break; 1482 case MachO::S_CSTRING_LITERALS: 1483 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1484 break; 1485 case MachO::S_4BYTE_LITERALS: 1486 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1487 break; 1488 case MachO::S_8BYTE_LITERALS: 1489 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1490 break; 1491 case MachO::S_16BYTE_LITERALS: 1492 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1493 break; 1494 case MachO::S_LITERAL_POINTERS: 1495 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1496 !NoLeadingAddr); 1497 break; 1498 case MachO::S_MOD_INIT_FUNC_POINTERS: 1499 case MachO::S_MOD_TERM_FUNC_POINTERS: 1500 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr, 1501 &AddrMap, verbose); 1502 break; 1503 default: 1504 outs() << "Unknown section type (" 1505 << format("0x%08" PRIx32, section_type) << ")\n"; 1506 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1507 break; 1508 } 1509 } else { 1510 if (section_type == MachO::S_ZEROFILL) 1511 outs() << "zerofill section and has no contents in the file\n"; 1512 else 1513 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1514 } 1515 } 1516 } 1517 } 1518 } 1519 1520 static void DumpInfoPlistSectionContents(StringRef Filename, 1521 MachOObjectFile *O) { 1522 for (const SectionRef &Section : O->sections()) { 1523 StringRef SectName; 1524 Section.getName(SectName); 1525 DataRefImpl Ref = Section.getRawDataRefImpl(); 1526 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1527 if (SegName == "__TEXT" && SectName == "__info_plist") { 1528 if (!NoLeadingHeaders) 1529 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1530 StringRef BytesStr; 1531 Section.getContents(BytesStr); 1532 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1533 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 1534 return; 1535 } 1536 } 1537 } 1538 1539 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1540 // and if it is and there is a list of architecture flags is specified then 1541 // check to make sure this Mach-O file is one of those architectures or all 1542 // architectures were specified. If not then an error is generated and this 1543 // routine returns false. Else it returns true. 1544 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1545 auto *MachO = dyn_cast<MachOObjectFile>(O); 1546 1547 if (!MachO || ArchAll || ArchFlags.empty()) 1548 return true; 1549 1550 MachO::mach_header H; 1551 MachO::mach_header_64 H_64; 1552 Triple T; 1553 const char *McpuDefault, *ArchFlag; 1554 if (MachO->is64Bit()) { 1555 H_64 = MachO->MachOObjectFile::getHeader64(); 1556 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 1557 &McpuDefault, &ArchFlag); 1558 } else { 1559 H = MachO->MachOObjectFile::getHeader(); 1560 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 1561 &McpuDefault, &ArchFlag); 1562 } 1563 const std::string ArchFlagName(ArchFlag); 1564 if (none_of(ArchFlags, [&](const std::string &Name) { 1565 return Name == ArchFlagName; 1566 })) { 1567 errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n"; 1568 return false; 1569 } 1570 return true; 1571 } 1572 1573 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 1574 1575 // ProcessMachO() is passed a single opened Mach-O file, which may be an 1576 // archive member and or in a slice of a universal file. It prints the 1577 // the file name and header info and then processes it according to the 1578 // command line options. 1579 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 1580 StringRef ArchiveMemberName = StringRef(), 1581 StringRef ArchitectureName = StringRef()) { 1582 // If we are doing some processing here on the Mach-O file print the header 1583 // info. And don't print it otherwise like in the case of printing the 1584 // UniversalHeaders or ArchiveHeaders. 1585 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || 1586 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || 1587 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData || 1588 (FilterSections.size() != 0)) { 1589 if (!NoLeadingHeaders) { 1590 outs() << Name; 1591 if (!ArchiveMemberName.empty()) 1592 outs() << '(' << ArchiveMemberName << ')'; 1593 if (!ArchitectureName.empty()) 1594 outs() << " (architecture " << ArchitectureName << ")"; 1595 outs() << ":\n"; 1596 } 1597 } 1598 // To use the report_error() form with an ArchiveName and FileName set 1599 // these up based on what is passed for Name and ArchiveMemberName. 1600 StringRef ArchiveName; 1601 StringRef FileName; 1602 if (!ArchiveMemberName.empty()) { 1603 ArchiveName = Name; 1604 FileName = ArchiveMemberName; 1605 } else { 1606 ArchiveName = StringRef(); 1607 FileName = Name; 1608 } 1609 1610 // If we need the symbol table to do the operation then check it here to 1611 // produce a good error message as to where the Mach-O file comes from in 1612 // the error message. 1613 if (Disassemble || IndirectSymbols || FilterSections.size() != 0 || 1614 UnwindInfo) 1615 if (Error Err = MachOOF->checkSymbolTable()) 1616 report_error(ArchiveName, FileName, std::move(Err), ArchitectureName); 1617 1618 if (Disassemble) { 1619 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE && 1620 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64) 1621 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text"); 1622 else 1623 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 1624 } 1625 if (IndirectSymbols) 1626 PrintIndirectSymbols(MachOOF, !NonVerbose); 1627 if (DataInCode) 1628 PrintDataInCodeTable(MachOOF, !NonVerbose); 1629 if (LinkOptHints) 1630 PrintLinkOptHints(MachOOF); 1631 if (Relocations) 1632 PrintRelocations(MachOOF, !NonVerbose); 1633 if (SectionHeaders) 1634 PrintSectionHeaders(MachOOF); 1635 if (SectionContents) 1636 PrintSectionContents(MachOOF); 1637 if (FilterSections.size() != 0) 1638 DumpSectionContents(FileName, MachOOF, !NonVerbose); 1639 if (InfoPlist) 1640 DumpInfoPlistSectionContents(FileName, MachOOF); 1641 if (DylibsUsed) 1642 PrintDylibs(MachOOF, false); 1643 if (DylibId) 1644 PrintDylibs(MachOOF, true); 1645 if (SymbolTable) 1646 PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName); 1647 if (UnwindInfo) 1648 printMachOUnwindInfo(MachOOF); 1649 if (PrivateHeaders) { 1650 printMachOFileHeader(MachOOF); 1651 printMachOLoadCommands(MachOOF); 1652 } 1653 if (FirstPrivateHeader) 1654 printMachOFileHeader(MachOOF); 1655 if (ObjcMetaData) 1656 printObjcMetaData(MachOOF, !NonVerbose); 1657 if (ExportsTrie) 1658 printExportsTrie(MachOOF); 1659 if (Rebase) 1660 printRebaseTable(MachOOF); 1661 if (Bind) 1662 printBindTable(MachOOF); 1663 if (LazyBind) 1664 printLazyBindTable(MachOOF); 1665 if (WeakBind) 1666 printWeakBindTable(MachOOF); 1667 1668 if (DwarfDumpType != DIDT_Null) { 1669 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF); 1670 // Dump the complete DWARF structure. 1671 DIDumpOptions DumpOpts; 1672 DumpOpts.DumpType = DwarfDumpType; 1673 DICtx->dump(outs(), DumpOpts); 1674 } 1675 } 1676 1677 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 1678 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 1679 outs() << " cputype (" << cputype << ")\n"; 1680 outs() << " cpusubtype (" << cpusubtype << ")\n"; 1681 } 1682 1683 // printCPUType() helps print_fat_headers by printing the cputype and 1684 // pusubtype (symbolically for the one's it knows about). 1685 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 1686 switch (cputype) { 1687 case MachO::CPU_TYPE_I386: 1688 switch (cpusubtype) { 1689 case MachO::CPU_SUBTYPE_I386_ALL: 1690 outs() << " cputype CPU_TYPE_I386\n"; 1691 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 1692 break; 1693 default: 1694 printUnknownCPUType(cputype, cpusubtype); 1695 break; 1696 } 1697 break; 1698 case MachO::CPU_TYPE_X86_64: 1699 switch (cpusubtype) { 1700 case MachO::CPU_SUBTYPE_X86_64_ALL: 1701 outs() << " cputype CPU_TYPE_X86_64\n"; 1702 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 1703 break; 1704 case MachO::CPU_SUBTYPE_X86_64_H: 1705 outs() << " cputype CPU_TYPE_X86_64\n"; 1706 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 1707 break; 1708 default: 1709 printUnknownCPUType(cputype, cpusubtype); 1710 break; 1711 } 1712 break; 1713 case MachO::CPU_TYPE_ARM: 1714 switch (cpusubtype) { 1715 case MachO::CPU_SUBTYPE_ARM_ALL: 1716 outs() << " cputype CPU_TYPE_ARM\n"; 1717 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 1718 break; 1719 case MachO::CPU_SUBTYPE_ARM_V4T: 1720 outs() << " cputype CPU_TYPE_ARM\n"; 1721 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 1722 break; 1723 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1724 outs() << " cputype CPU_TYPE_ARM\n"; 1725 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 1726 break; 1727 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1728 outs() << " cputype CPU_TYPE_ARM\n"; 1729 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 1730 break; 1731 case MachO::CPU_SUBTYPE_ARM_V6: 1732 outs() << " cputype CPU_TYPE_ARM\n"; 1733 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 1734 break; 1735 case MachO::CPU_SUBTYPE_ARM_V6M: 1736 outs() << " cputype CPU_TYPE_ARM\n"; 1737 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 1738 break; 1739 case MachO::CPU_SUBTYPE_ARM_V7: 1740 outs() << " cputype CPU_TYPE_ARM\n"; 1741 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 1742 break; 1743 case MachO::CPU_SUBTYPE_ARM_V7EM: 1744 outs() << " cputype CPU_TYPE_ARM\n"; 1745 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 1746 break; 1747 case MachO::CPU_SUBTYPE_ARM_V7K: 1748 outs() << " cputype CPU_TYPE_ARM\n"; 1749 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 1750 break; 1751 case MachO::CPU_SUBTYPE_ARM_V7M: 1752 outs() << " cputype CPU_TYPE_ARM\n"; 1753 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 1754 break; 1755 case MachO::CPU_SUBTYPE_ARM_V7S: 1756 outs() << " cputype CPU_TYPE_ARM\n"; 1757 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 1758 break; 1759 default: 1760 printUnknownCPUType(cputype, cpusubtype); 1761 break; 1762 } 1763 break; 1764 case MachO::CPU_TYPE_ARM64: 1765 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 1766 case MachO::CPU_SUBTYPE_ARM64_ALL: 1767 outs() << " cputype CPU_TYPE_ARM64\n"; 1768 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 1769 break; 1770 default: 1771 printUnknownCPUType(cputype, cpusubtype); 1772 break; 1773 } 1774 break; 1775 default: 1776 printUnknownCPUType(cputype, cpusubtype); 1777 break; 1778 } 1779 } 1780 1781 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 1782 bool verbose) { 1783 outs() << "Fat headers\n"; 1784 if (verbose) { 1785 if (UB->getMagic() == MachO::FAT_MAGIC) 1786 outs() << "fat_magic FAT_MAGIC\n"; 1787 else // UB->getMagic() == MachO::FAT_MAGIC_64 1788 outs() << "fat_magic FAT_MAGIC_64\n"; 1789 } else 1790 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 1791 1792 uint32_t nfat_arch = UB->getNumberOfObjects(); 1793 StringRef Buf = UB->getData(); 1794 uint64_t size = Buf.size(); 1795 uint64_t big_size = sizeof(struct MachO::fat_header) + 1796 nfat_arch * sizeof(struct MachO::fat_arch); 1797 outs() << "nfat_arch " << UB->getNumberOfObjects(); 1798 if (nfat_arch == 0) 1799 outs() << " (malformed, contains zero architecture types)\n"; 1800 else if (big_size > size) 1801 outs() << " (malformed, architectures past end of file)\n"; 1802 else 1803 outs() << "\n"; 1804 1805 for (uint32_t i = 0; i < nfat_arch; ++i) { 1806 MachOUniversalBinary::ObjectForArch OFA(UB, i); 1807 uint32_t cputype = OFA.getCPUType(); 1808 uint32_t cpusubtype = OFA.getCPUSubType(); 1809 outs() << "architecture "; 1810 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 1811 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 1812 uint32_t other_cputype = other_OFA.getCPUType(); 1813 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 1814 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 1815 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 1816 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 1817 outs() << "(illegal duplicate architecture) "; 1818 break; 1819 } 1820 } 1821 if (verbose) { 1822 outs() << OFA.getArchFlagName() << "\n"; 1823 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 1824 } else { 1825 outs() << i << "\n"; 1826 outs() << " cputype " << cputype << "\n"; 1827 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 1828 << "\n"; 1829 } 1830 if (verbose && 1831 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 1832 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 1833 else 1834 outs() << " capabilities " 1835 << format("0x%" PRIx32, 1836 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 1837 outs() << " offset " << OFA.getOffset(); 1838 if (OFA.getOffset() > size) 1839 outs() << " (past end of file)"; 1840 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0) 1841 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 1842 outs() << "\n"; 1843 outs() << " size " << OFA.getSize(); 1844 big_size = OFA.getOffset() + OFA.getSize(); 1845 if (big_size > size) 1846 outs() << " (past end of file)"; 1847 outs() << "\n"; 1848 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 1849 << ")\n"; 1850 } 1851 } 1852 1853 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 1854 bool verbose, bool print_offset, 1855 StringRef ArchitectureName = StringRef()) { 1856 if (print_offset) 1857 outs() << C.getChildOffset() << "\t"; 1858 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode(); 1859 if (!ModeOrErr) 1860 report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName); 1861 sys::fs::perms Mode = ModeOrErr.get(); 1862 if (verbose) { 1863 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 1864 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 1865 outs() << "-"; 1866 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 1867 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 1868 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 1869 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 1870 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 1871 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 1872 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 1873 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 1874 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 1875 } else { 1876 outs() << format("0%o ", Mode); 1877 } 1878 1879 Expected<unsigned> UIDOrErr = C.getUID(); 1880 if (!UIDOrErr) 1881 report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName); 1882 unsigned UID = UIDOrErr.get(); 1883 outs() << format("%3d/", UID); 1884 Expected<unsigned> GIDOrErr = C.getGID(); 1885 if (!GIDOrErr) 1886 report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName); 1887 unsigned GID = GIDOrErr.get(); 1888 outs() << format("%-3d ", GID); 1889 Expected<uint64_t> Size = C.getRawSize(); 1890 if (!Size) 1891 report_error(Filename, C, Size.takeError(), ArchitectureName); 1892 outs() << format("%5" PRId64, Size.get()) << " "; 1893 1894 StringRef RawLastModified = C.getRawLastModified(); 1895 if (verbose) { 1896 unsigned Seconds; 1897 if (RawLastModified.getAsInteger(10, Seconds)) 1898 outs() << "(date: \"" << RawLastModified 1899 << "\" contains non-decimal chars) "; 1900 else { 1901 // Since cime(3) returns a 26 character string of the form: 1902 // "Sun Sep 16 01:03:52 1973\n\0" 1903 // just print 24 characters. 1904 time_t t = Seconds; 1905 outs() << format("%.24s ", ctime(&t)); 1906 } 1907 } else { 1908 outs() << RawLastModified << " "; 1909 } 1910 1911 if (verbose) { 1912 Expected<StringRef> NameOrErr = C.getName(); 1913 if (!NameOrErr) { 1914 consumeError(NameOrErr.takeError()); 1915 Expected<StringRef> NameOrErr = C.getRawName(); 1916 if (!NameOrErr) 1917 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1918 StringRef RawName = NameOrErr.get(); 1919 outs() << RawName << "\n"; 1920 } else { 1921 StringRef Name = NameOrErr.get(); 1922 outs() << Name << "\n"; 1923 } 1924 } else { 1925 Expected<StringRef> NameOrErr = C.getRawName(); 1926 if (!NameOrErr) 1927 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1928 StringRef RawName = NameOrErr.get(); 1929 outs() << RawName << "\n"; 1930 } 1931 } 1932 1933 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 1934 bool print_offset, 1935 StringRef ArchitectureName = StringRef()) { 1936 Error Err = Error::success(); 1937 ; 1938 for (const auto &C : A->children(Err, false)) 1939 printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName); 1940 1941 if (Err) 1942 report_error(StringRef(), Filename, std::move(Err), ArchitectureName); 1943 } 1944 1945 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 1946 // -arch flags selecting just those slices as specified by them and also parses 1947 // archive files. Then for each individual Mach-O file ProcessMachO() is 1948 // called to process the file based on the command line options. 1949 void llvm::ParseInputMachO(StringRef Filename) { 1950 // Check for -arch all and verifiy the -arch flags are valid. 1951 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 1952 if (ArchFlags[i] == "all") { 1953 ArchAll = true; 1954 } else { 1955 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 1956 errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] + 1957 "'for the -arch option\n"; 1958 return; 1959 } 1960 } 1961 } 1962 1963 // Attempt to open the binary. 1964 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 1965 if (!BinaryOrErr) { 1966 if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 1967 report_error(Filename, std::move(E)); 1968 else 1969 outs() << Filename << ": is not an object file\n"; 1970 return; 1971 } 1972 Binary &Bin = *BinaryOrErr.get().getBinary(); 1973 1974 if (Archive *A = dyn_cast<Archive>(&Bin)) { 1975 outs() << "Archive : " << Filename << "\n"; 1976 if (ArchiveHeaders) 1977 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets); 1978 1979 Error Err = Error::success(); 1980 for (auto &C : A->children(Err)) { 1981 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 1982 if (!ChildOrErr) { 1983 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 1984 report_error(Filename, C, std::move(E)); 1985 continue; 1986 } 1987 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 1988 if (!checkMachOAndArchFlags(O, Filename)) 1989 return; 1990 ProcessMachO(Filename, O, O->getFileName()); 1991 } 1992 } 1993 if (Err) 1994 report_error(Filename, std::move(Err)); 1995 return; 1996 } 1997 if (UniversalHeaders) { 1998 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) 1999 printMachOUniversalHeaders(UB, !NonVerbose); 2000 } 2001 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 2002 // If we have a list of architecture flags specified dump only those. 2003 if (!ArchAll && ArchFlags.size() != 0) { 2004 // Look for a slice in the universal binary that matches each ArchFlag. 2005 bool ArchFound; 2006 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2007 ArchFound = false; 2008 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2009 E = UB->end_objects(); 2010 I != E; ++I) { 2011 if (ArchFlags[i] == I->getArchFlagName()) { 2012 ArchFound = true; 2013 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2014 I->getAsObjectFile(); 2015 std::string ArchitectureName = ""; 2016 if (ArchFlags.size() > 1) 2017 ArchitectureName = I->getArchFlagName(); 2018 if (ObjOrErr) { 2019 ObjectFile &O = *ObjOrErr.get(); 2020 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2021 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2022 } else if (auto E = isNotObjectErrorInvalidFileType( 2023 ObjOrErr.takeError())) { 2024 report_error(Filename, StringRef(), std::move(E), 2025 ArchitectureName); 2026 continue; 2027 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2028 I->getAsArchive()) { 2029 std::unique_ptr<Archive> &A = *AOrErr; 2030 outs() << "Archive : " << Filename; 2031 if (!ArchitectureName.empty()) 2032 outs() << " (architecture " << ArchitectureName << ")"; 2033 outs() << "\n"; 2034 if (ArchiveHeaders) 2035 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2036 ArchiveMemberOffsets, ArchitectureName); 2037 Error Err = Error::success(); 2038 for (auto &C : A->children(Err)) { 2039 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2040 if (!ChildOrErr) { 2041 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2042 report_error(Filename, C, std::move(E), ArchitectureName); 2043 continue; 2044 } 2045 if (MachOObjectFile *O = 2046 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2047 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2048 } 2049 if (Err) 2050 report_error(Filename, std::move(Err)); 2051 } else { 2052 consumeError(AOrErr.takeError()); 2053 error("Mach-O universal file: " + Filename + " for " + 2054 "architecture " + StringRef(I->getArchFlagName()) + 2055 " is not a Mach-O file or an archive file"); 2056 } 2057 } 2058 } 2059 if (!ArchFound) { 2060 errs() << "llvm-objdump: file: " + Filename + " does not contain " 2061 << "architecture: " + ArchFlags[i] + "\n"; 2062 return; 2063 } 2064 } 2065 return; 2066 } 2067 // No architecture flags were specified so if this contains a slice that 2068 // matches the host architecture dump only that. 2069 if (!ArchAll) { 2070 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2071 E = UB->end_objects(); 2072 I != E; ++I) { 2073 if (MachOObjectFile::getHostArch().getArchName() == 2074 I->getArchFlagName()) { 2075 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2076 std::string ArchiveName; 2077 ArchiveName.clear(); 2078 if (ObjOrErr) { 2079 ObjectFile &O = *ObjOrErr.get(); 2080 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2081 ProcessMachO(Filename, MachOOF); 2082 } else if (auto E = isNotObjectErrorInvalidFileType( 2083 ObjOrErr.takeError())) { 2084 report_error(Filename, std::move(E)); 2085 continue; 2086 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2087 I->getAsArchive()) { 2088 std::unique_ptr<Archive> &A = *AOrErr; 2089 outs() << "Archive : " << Filename << "\n"; 2090 if (ArchiveHeaders) 2091 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2092 ArchiveMemberOffsets); 2093 Error Err = Error::success(); 2094 for (auto &C : A->children(Err)) { 2095 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2096 if (!ChildOrErr) { 2097 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2098 report_error(Filename, C, std::move(E)); 2099 continue; 2100 } 2101 if (MachOObjectFile *O = 2102 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2103 ProcessMachO(Filename, O, O->getFileName()); 2104 } 2105 if (Err) 2106 report_error(Filename, std::move(Err)); 2107 } else { 2108 consumeError(AOrErr.takeError()); 2109 error("Mach-O universal file: " + Filename + " for architecture " + 2110 StringRef(I->getArchFlagName()) + 2111 " is not a Mach-O file or an archive file"); 2112 } 2113 return; 2114 } 2115 } 2116 } 2117 // Either all architectures have been specified or none have been specified 2118 // and this does not contain the host architecture so dump all the slices. 2119 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2120 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2121 E = UB->end_objects(); 2122 I != E; ++I) { 2123 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2124 std::string ArchitectureName = ""; 2125 if (moreThanOneArch) 2126 ArchitectureName = I->getArchFlagName(); 2127 if (ObjOrErr) { 2128 ObjectFile &Obj = *ObjOrErr.get(); 2129 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2130 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2131 } else if (auto E = isNotObjectErrorInvalidFileType( 2132 ObjOrErr.takeError())) { 2133 report_error(StringRef(), Filename, std::move(E), ArchitectureName); 2134 continue; 2135 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2136 I->getAsArchive()) { 2137 std::unique_ptr<Archive> &A = *AOrErr; 2138 outs() << "Archive : " << Filename; 2139 if (!ArchitectureName.empty()) 2140 outs() << " (architecture " << ArchitectureName << ")"; 2141 outs() << "\n"; 2142 if (ArchiveHeaders) 2143 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2144 ArchiveMemberOffsets, ArchitectureName); 2145 Error Err = Error::success(); 2146 for (auto &C : A->children(Err)) { 2147 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2148 if (!ChildOrErr) { 2149 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2150 report_error(Filename, C, std::move(E), ArchitectureName); 2151 continue; 2152 } 2153 if (MachOObjectFile *O = 2154 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2155 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2156 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2157 ArchitectureName); 2158 } 2159 } 2160 if (Err) 2161 report_error(Filename, std::move(Err)); 2162 } else { 2163 consumeError(AOrErr.takeError()); 2164 error("Mach-O universal file: " + Filename + " for architecture " + 2165 StringRef(I->getArchFlagName()) + 2166 " is not a Mach-O file or an archive file"); 2167 } 2168 } 2169 return; 2170 } 2171 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2172 if (!checkMachOAndArchFlags(O, Filename)) 2173 return; 2174 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) { 2175 ProcessMachO(Filename, MachOOF); 2176 } else 2177 errs() << "llvm-objdump: '" << Filename << "': " 2178 << "Object is not a Mach-O file type.\n"; 2179 return; 2180 } 2181 llvm_unreachable("Input object can't be invalid at this point"); 2182 } 2183 2184 // The block of info used by the Symbolizer call backs. 2185 struct DisassembleInfo { 2186 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, 2187 std::vector<SectionRef> *Sections, bool verbose) 2188 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {} 2189 bool verbose; 2190 MachOObjectFile *O; 2191 SectionRef S; 2192 SymbolAddressMap *AddrMap; 2193 std::vector<SectionRef> *Sections; 2194 const char *class_name = nullptr; 2195 const char *selector_name = nullptr; 2196 std::unique_ptr<char[]> method = nullptr; 2197 char *demangled_name = nullptr; 2198 uint64_t adrp_addr = 0; 2199 uint32_t adrp_inst = 0; 2200 std::unique_ptr<SymbolAddressMap> bindtable; 2201 uint32_t depth = 0; 2202 }; 2203 2204 // SymbolizerGetOpInfo() is the operand information call back function. 2205 // This is called to get the symbolic information for operand(s) of an 2206 // instruction when it is being done. This routine does this from 2207 // the relocation information, symbol table, etc. That block of information 2208 // is a pointer to the struct DisassembleInfo that was passed when the 2209 // disassembler context was created and passed to back to here when 2210 // called back by the disassembler for instruction operands that could have 2211 // relocation information. The address of the instruction containing operand is 2212 // at the Pc parameter. The immediate value the operand has is passed in 2213 // op_info->Value and is at Offset past the start of the instruction and has a 2214 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2215 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2216 // names and addends of the symbolic expression to add for the operand. The 2217 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2218 // information is returned then this function returns 1 else it returns 0. 2219 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2220 uint64_t Size, int TagType, void *TagBuf) { 2221 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2222 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2223 uint64_t value = op_info->Value; 2224 2225 // Make sure all fields returned are zero if we don't set them. 2226 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2227 op_info->Value = value; 2228 2229 // If the TagType is not the value 1 which it code knows about or if no 2230 // verbose symbolic information is wanted then just return 0, indicating no 2231 // information is being returned. 2232 if (TagType != 1 || !info->verbose) 2233 return 0; 2234 2235 unsigned int Arch = info->O->getArch(); 2236 if (Arch == Triple::x86) { 2237 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2238 return 0; 2239 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2240 // TODO: 2241 // Search the external relocation entries of a fully linked image 2242 // (if any) for an entry that matches this segment offset. 2243 // uint32_t seg_offset = (Pc + Offset); 2244 return 0; 2245 } 2246 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2247 // for an entry for this section offset. 2248 uint32_t sect_addr = info->S.getAddress(); 2249 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2250 bool reloc_found = false; 2251 DataRefImpl Rel; 2252 MachO::any_relocation_info RE; 2253 bool isExtern = false; 2254 SymbolRef Symbol; 2255 bool r_scattered = false; 2256 uint32_t r_value, pair_r_value, r_type; 2257 for (const RelocationRef &Reloc : info->S.relocations()) { 2258 uint64_t RelocOffset = Reloc.getOffset(); 2259 if (RelocOffset == sect_offset) { 2260 Rel = Reloc.getRawDataRefImpl(); 2261 RE = info->O->getRelocation(Rel); 2262 r_type = info->O->getAnyRelocationType(RE); 2263 r_scattered = info->O->isRelocationScattered(RE); 2264 if (r_scattered) { 2265 r_value = info->O->getScatteredRelocationValue(RE); 2266 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2267 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2268 DataRefImpl RelNext = Rel; 2269 info->O->moveRelocationNext(RelNext); 2270 MachO::any_relocation_info RENext; 2271 RENext = info->O->getRelocation(RelNext); 2272 if (info->O->isRelocationScattered(RENext)) 2273 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2274 else 2275 return 0; 2276 } 2277 } else { 2278 isExtern = info->O->getPlainRelocationExternal(RE); 2279 if (isExtern) { 2280 symbol_iterator RelocSym = Reloc.getSymbol(); 2281 Symbol = *RelocSym; 2282 } 2283 } 2284 reloc_found = true; 2285 break; 2286 } 2287 } 2288 if (reloc_found && isExtern) { 2289 Expected<StringRef> SymName = Symbol.getName(); 2290 if (!SymName) 2291 report_error(info->O->getFileName(), SymName.takeError()); 2292 const char *name = SymName->data(); 2293 op_info->AddSymbol.Present = 1; 2294 op_info->AddSymbol.Name = name; 2295 // For i386 extern relocation entries the value in the instruction is 2296 // the offset from the symbol, and value is already set in op_info->Value. 2297 return 1; 2298 } 2299 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2300 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2301 const char *add = GuessSymbolName(r_value, info->AddrMap); 2302 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2303 uint32_t offset = value - (r_value - pair_r_value); 2304 op_info->AddSymbol.Present = 1; 2305 if (add != nullptr) 2306 op_info->AddSymbol.Name = add; 2307 else 2308 op_info->AddSymbol.Value = r_value; 2309 op_info->SubtractSymbol.Present = 1; 2310 if (sub != nullptr) 2311 op_info->SubtractSymbol.Name = sub; 2312 else 2313 op_info->SubtractSymbol.Value = pair_r_value; 2314 op_info->Value = offset; 2315 return 1; 2316 } 2317 return 0; 2318 } 2319 if (Arch == Triple::x86_64) { 2320 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2321 return 0; 2322 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2323 // relocation entries of a linked image (if any) for an entry that matches 2324 // this segment offset. 2325 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2326 uint64_t seg_offset = Pc + Offset; 2327 bool reloc_found = false; 2328 DataRefImpl Rel; 2329 MachO::any_relocation_info RE; 2330 bool isExtern = false; 2331 SymbolRef Symbol; 2332 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2333 uint64_t RelocOffset = Reloc.getOffset(); 2334 if (RelocOffset == seg_offset) { 2335 Rel = Reloc.getRawDataRefImpl(); 2336 RE = info->O->getRelocation(Rel); 2337 // external relocation entries should always be external. 2338 isExtern = info->O->getPlainRelocationExternal(RE); 2339 if (isExtern) { 2340 symbol_iterator RelocSym = Reloc.getSymbol(); 2341 Symbol = *RelocSym; 2342 } 2343 reloc_found = true; 2344 break; 2345 } 2346 } 2347 if (reloc_found && isExtern) { 2348 // The Value passed in will be adjusted by the Pc if the instruction 2349 // adds the Pc. But for x86_64 external relocation entries the Value 2350 // is the offset from the external symbol. 2351 if (info->O->getAnyRelocationPCRel(RE)) 2352 op_info->Value -= Pc + Offset + Size; 2353 Expected<StringRef> SymName = Symbol.getName(); 2354 if (!SymName) 2355 report_error(info->O->getFileName(), SymName.takeError()); 2356 const char *name = SymName->data(); 2357 op_info->AddSymbol.Present = 1; 2358 op_info->AddSymbol.Name = name; 2359 return 1; 2360 } 2361 return 0; 2362 } 2363 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2364 // for an entry for this section offset. 2365 uint64_t sect_addr = info->S.getAddress(); 2366 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2367 bool reloc_found = false; 2368 DataRefImpl Rel; 2369 MachO::any_relocation_info RE; 2370 bool isExtern = false; 2371 SymbolRef Symbol; 2372 for (const RelocationRef &Reloc : info->S.relocations()) { 2373 uint64_t RelocOffset = Reloc.getOffset(); 2374 if (RelocOffset == sect_offset) { 2375 Rel = Reloc.getRawDataRefImpl(); 2376 RE = info->O->getRelocation(Rel); 2377 // NOTE: Scattered relocations don't exist on x86_64. 2378 isExtern = info->O->getPlainRelocationExternal(RE); 2379 if (isExtern) { 2380 symbol_iterator RelocSym = Reloc.getSymbol(); 2381 Symbol = *RelocSym; 2382 } 2383 reloc_found = true; 2384 break; 2385 } 2386 } 2387 if (reloc_found && isExtern) { 2388 // The Value passed in will be adjusted by the Pc if the instruction 2389 // adds the Pc. But for x86_64 external relocation entries the Value 2390 // is the offset from the external symbol. 2391 if (info->O->getAnyRelocationPCRel(RE)) 2392 op_info->Value -= Pc + Offset + Size; 2393 Expected<StringRef> SymName = Symbol.getName(); 2394 if (!SymName) 2395 report_error(info->O->getFileName(), SymName.takeError()); 2396 const char *name = SymName->data(); 2397 unsigned Type = info->O->getAnyRelocationType(RE); 2398 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2399 DataRefImpl RelNext = Rel; 2400 info->O->moveRelocationNext(RelNext); 2401 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2402 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2403 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2404 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2405 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2406 op_info->SubtractSymbol.Present = 1; 2407 op_info->SubtractSymbol.Name = name; 2408 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2409 Symbol = *RelocSymNext; 2410 Expected<StringRef> SymNameNext = Symbol.getName(); 2411 if (!SymNameNext) 2412 report_error(info->O->getFileName(), SymNameNext.takeError()); 2413 name = SymNameNext->data(); 2414 } 2415 } 2416 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 2417 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 2418 op_info->AddSymbol.Present = 1; 2419 op_info->AddSymbol.Name = name; 2420 return 1; 2421 } 2422 return 0; 2423 } 2424 if (Arch == Triple::arm) { 2425 if (Offset != 0 || (Size != 4 && Size != 2)) 2426 return 0; 2427 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2428 // TODO: 2429 // Search the external relocation entries of a fully linked image 2430 // (if any) for an entry that matches this segment offset. 2431 // uint32_t seg_offset = (Pc + Offset); 2432 return 0; 2433 } 2434 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2435 // for an entry for this section offset. 2436 uint32_t sect_addr = info->S.getAddress(); 2437 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2438 DataRefImpl Rel; 2439 MachO::any_relocation_info RE; 2440 bool isExtern = false; 2441 SymbolRef Symbol; 2442 bool r_scattered = false; 2443 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 2444 auto Reloc = 2445 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2446 uint64_t RelocOffset = Reloc.getOffset(); 2447 return RelocOffset == sect_offset; 2448 }); 2449 2450 if (Reloc == info->S.relocations().end()) 2451 return 0; 2452 2453 Rel = Reloc->getRawDataRefImpl(); 2454 RE = info->O->getRelocation(Rel); 2455 r_length = info->O->getAnyRelocationLength(RE); 2456 r_scattered = info->O->isRelocationScattered(RE); 2457 if (r_scattered) { 2458 r_value = info->O->getScatteredRelocationValue(RE); 2459 r_type = info->O->getScatteredRelocationType(RE); 2460 } else { 2461 r_type = info->O->getAnyRelocationType(RE); 2462 isExtern = info->O->getPlainRelocationExternal(RE); 2463 if (isExtern) { 2464 symbol_iterator RelocSym = Reloc->getSymbol(); 2465 Symbol = *RelocSym; 2466 } 2467 } 2468 if (r_type == MachO::ARM_RELOC_HALF || 2469 r_type == MachO::ARM_RELOC_SECTDIFF || 2470 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 2471 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2472 DataRefImpl RelNext = Rel; 2473 info->O->moveRelocationNext(RelNext); 2474 MachO::any_relocation_info RENext; 2475 RENext = info->O->getRelocation(RelNext); 2476 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 2477 if (info->O->isRelocationScattered(RENext)) 2478 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2479 } 2480 2481 if (isExtern) { 2482 Expected<StringRef> SymName = Symbol.getName(); 2483 if (!SymName) 2484 report_error(info->O->getFileName(), SymName.takeError()); 2485 const char *name = SymName->data(); 2486 op_info->AddSymbol.Present = 1; 2487 op_info->AddSymbol.Name = name; 2488 switch (r_type) { 2489 case MachO::ARM_RELOC_HALF: 2490 if ((r_length & 0x1) == 1) { 2491 op_info->Value = value << 16 | other_half; 2492 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2493 } else { 2494 op_info->Value = other_half << 16 | value; 2495 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2496 } 2497 break; 2498 default: 2499 break; 2500 } 2501 return 1; 2502 } 2503 // If we have a branch that is not an external relocation entry then 2504 // return 0 so the code in tryAddingSymbolicOperand() can use the 2505 // SymbolLookUp call back with the branch target address to look up the 2506 // symbol and possibility add an annotation for a symbol stub. 2507 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 2508 r_type == MachO::ARM_THUMB_RELOC_BR22)) 2509 return 0; 2510 2511 uint32_t offset = 0; 2512 if (r_type == MachO::ARM_RELOC_HALF || 2513 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2514 if ((r_length & 0x1) == 1) 2515 value = value << 16 | other_half; 2516 else 2517 value = other_half << 16 | value; 2518 } 2519 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 2520 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 2521 offset = value - r_value; 2522 value = r_value; 2523 } 2524 2525 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2526 if ((r_length & 0x1) == 1) 2527 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2528 else 2529 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2530 const char *add = GuessSymbolName(r_value, info->AddrMap); 2531 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2532 int32_t offset = value - (r_value - pair_r_value); 2533 op_info->AddSymbol.Present = 1; 2534 if (add != nullptr) 2535 op_info->AddSymbol.Name = add; 2536 else 2537 op_info->AddSymbol.Value = r_value; 2538 op_info->SubtractSymbol.Present = 1; 2539 if (sub != nullptr) 2540 op_info->SubtractSymbol.Name = sub; 2541 else 2542 op_info->SubtractSymbol.Value = pair_r_value; 2543 op_info->Value = offset; 2544 return 1; 2545 } 2546 2547 op_info->AddSymbol.Present = 1; 2548 op_info->Value = offset; 2549 if (r_type == MachO::ARM_RELOC_HALF) { 2550 if ((r_length & 0x1) == 1) 2551 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2552 else 2553 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2554 } 2555 const char *add = GuessSymbolName(value, info->AddrMap); 2556 if (add != nullptr) { 2557 op_info->AddSymbol.Name = add; 2558 return 1; 2559 } 2560 op_info->AddSymbol.Value = value; 2561 return 1; 2562 } 2563 if (Arch == Triple::aarch64) { 2564 if (Offset != 0 || Size != 4) 2565 return 0; 2566 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2567 // TODO: 2568 // Search the external relocation entries of a fully linked image 2569 // (if any) for an entry that matches this segment offset. 2570 // uint64_t seg_offset = (Pc + Offset); 2571 return 0; 2572 } 2573 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2574 // for an entry for this section offset. 2575 uint64_t sect_addr = info->S.getAddress(); 2576 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2577 auto Reloc = 2578 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2579 uint64_t RelocOffset = Reloc.getOffset(); 2580 return RelocOffset == sect_offset; 2581 }); 2582 2583 if (Reloc == info->S.relocations().end()) 2584 return 0; 2585 2586 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2587 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 2588 uint32_t r_type = info->O->getAnyRelocationType(RE); 2589 if (r_type == MachO::ARM64_RELOC_ADDEND) { 2590 DataRefImpl RelNext = Rel; 2591 info->O->moveRelocationNext(RelNext); 2592 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2593 if (value == 0) { 2594 value = info->O->getPlainRelocationSymbolNum(RENext); 2595 op_info->Value = value; 2596 } 2597 } 2598 // NOTE: Scattered relocations don't exist on arm64. 2599 if (!info->O->getPlainRelocationExternal(RE)) 2600 return 0; 2601 Expected<StringRef> SymName = Reloc->getSymbol()->getName(); 2602 if (!SymName) 2603 report_error(info->O->getFileName(), SymName.takeError()); 2604 const char *name = SymName->data(); 2605 op_info->AddSymbol.Present = 1; 2606 op_info->AddSymbol.Name = name; 2607 2608 switch (r_type) { 2609 case MachO::ARM64_RELOC_PAGE21: 2610 /* @page */ 2611 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 2612 break; 2613 case MachO::ARM64_RELOC_PAGEOFF12: 2614 /* @pageoff */ 2615 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 2616 break; 2617 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 2618 /* @gotpage */ 2619 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 2620 break; 2621 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 2622 /* @gotpageoff */ 2623 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 2624 break; 2625 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 2626 /* @tvlppage is not implemented in llvm-mc */ 2627 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 2628 break; 2629 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 2630 /* @tvlppageoff is not implemented in llvm-mc */ 2631 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 2632 break; 2633 default: 2634 case MachO::ARM64_RELOC_BRANCH26: 2635 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 2636 break; 2637 } 2638 return 1; 2639 } 2640 return 0; 2641 } 2642 2643 // GuessCstringPointer is passed the address of what might be a pointer to a 2644 // literal string in a cstring section. If that address is in a cstring section 2645 // it returns a pointer to that string. Else it returns nullptr. 2646 static const char *GuessCstringPointer(uint64_t ReferenceValue, 2647 struct DisassembleInfo *info) { 2648 for (const auto &Load : info->O->load_commands()) { 2649 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2650 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2651 for (unsigned J = 0; J < Seg.nsects; ++J) { 2652 MachO::section_64 Sec = info->O->getSection64(Load, J); 2653 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2654 if (section_type == MachO::S_CSTRING_LITERALS && 2655 ReferenceValue >= Sec.addr && 2656 ReferenceValue < Sec.addr + Sec.size) { 2657 uint64_t sect_offset = ReferenceValue - Sec.addr; 2658 uint64_t object_offset = Sec.offset + sect_offset; 2659 StringRef MachOContents = info->O->getData(); 2660 uint64_t object_size = MachOContents.size(); 2661 const char *object_addr = (const char *)MachOContents.data(); 2662 if (object_offset < object_size) { 2663 const char *name = object_addr + object_offset; 2664 return name; 2665 } else { 2666 return nullptr; 2667 } 2668 } 2669 } 2670 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2671 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2672 for (unsigned J = 0; J < Seg.nsects; ++J) { 2673 MachO::section Sec = info->O->getSection(Load, J); 2674 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2675 if (section_type == MachO::S_CSTRING_LITERALS && 2676 ReferenceValue >= Sec.addr && 2677 ReferenceValue < Sec.addr + Sec.size) { 2678 uint64_t sect_offset = ReferenceValue - Sec.addr; 2679 uint64_t object_offset = Sec.offset + sect_offset; 2680 StringRef MachOContents = info->O->getData(); 2681 uint64_t object_size = MachOContents.size(); 2682 const char *object_addr = (const char *)MachOContents.data(); 2683 if (object_offset < object_size) { 2684 const char *name = object_addr + object_offset; 2685 return name; 2686 } else { 2687 return nullptr; 2688 } 2689 } 2690 } 2691 } 2692 } 2693 return nullptr; 2694 } 2695 2696 // GuessIndirectSymbol returns the name of the indirect symbol for the 2697 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 2698 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 2699 // symbol name being referenced by the stub or pointer. 2700 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 2701 struct DisassembleInfo *info) { 2702 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 2703 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 2704 for (const auto &Load : info->O->load_commands()) { 2705 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2706 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2707 for (unsigned J = 0; J < Seg.nsects; ++J) { 2708 MachO::section_64 Sec = info->O->getSection64(Load, J); 2709 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2710 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2711 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2712 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2713 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2714 section_type == MachO::S_SYMBOL_STUBS) && 2715 ReferenceValue >= Sec.addr && 2716 ReferenceValue < Sec.addr + Sec.size) { 2717 uint32_t stride; 2718 if (section_type == MachO::S_SYMBOL_STUBS) 2719 stride = Sec.reserved2; 2720 else 2721 stride = 8; 2722 if (stride == 0) 2723 return nullptr; 2724 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2725 if (index < Dysymtab.nindirectsyms) { 2726 uint32_t indirect_symbol = 2727 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2728 if (indirect_symbol < Symtab.nsyms) { 2729 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2730 SymbolRef Symbol = *Sym; 2731 Expected<StringRef> SymName = Symbol.getName(); 2732 if (!SymName) 2733 report_error(info->O->getFileName(), SymName.takeError()); 2734 const char *name = SymName->data(); 2735 return name; 2736 } 2737 } 2738 } 2739 } 2740 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2741 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2742 for (unsigned J = 0; J < Seg.nsects; ++J) { 2743 MachO::section Sec = info->O->getSection(Load, J); 2744 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2745 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2746 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2747 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2748 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2749 section_type == MachO::S_SYMBOL_STUBS) && 2750 ReferenceValue >= Sec.addr && 2751 ReferenceValue < Sec.addr + Sec.size) { 2752 uint32_t stride; 2753 if (section_type == MachO::S_SYMBOL_STUBS) 2754 stride = Sec.reserved2; 2755 else 2756 stride = 4; 2757 if (stride == 0) 2758 return nullptr; 2759 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2760 if (index < Dysymtab.nindirectsyms) { 2761 uint32_t indirect_symbol = 2762 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2763 if (indirect_symbol < Symtab.nsyms) { 2764 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2765 SymbolRef Symbol = *Sym; 2766 Expected<StringRef> SymName = Symbol.getName(); 2767 if (!SymName) 2768 report_error(info->O->getFileName(), SymName.takeError()); 2769 const char *name = SymName->data(); 2770 return name; 2771 } 2772 } 2773 } 2774 } 2775 } 2776 } 2777 return nullptr; 2778 } 2779 2780 // method_reference() is called passing it the ReferenceName that might be 2781 // a reference it to an Objective-C method call. If so then it allocates and 2782 // assembles a method call string with the values last seen and saved in 2783 // the DisassembleInfo's class_name and selector_name fields. This is saved 2784 // into the method field of the info and any previous string is free'ed. 2785 // Then the class_name field in the info is set to nullptr. The method call 2786 // string is set into ReferenceName and ReferenceType is set to 2787 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 2788 // then both ReferenceType and ReferenceName are left unchanged. 2789 static void method_reference(struct DisassembleInfo *info, 2790 uint64_t *ReferenceType, 2791 const char **ReferenceName) { 2792 unsigned int Arch = info->O->getArch(); 2793 if (*ReferenceName != nullptr) { 2794 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 2795 if (info->selector_name != nullptr) { 2796 if (info->class_name != nullptr) { 2797 info->method = llvm::make_unique<char[]>( 2798 5 + strlen(info->class_name) + strlen(info->selector_name)); 2799 char *method = info->method.get(); 2800 if (method != nullptr) { 2801 strcpy(method, "+["); 2802 strcat(method, info->class_name); 2803 strcat(method, " "); 2804 strcat(method, info->selector_name); 2805 strcat(method, "]"); 2806 *ReferenceName = method; 2807 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2808 } 2809 } else { 2810 info->method = 2811 llvm::make_unique<char[]>(9 + strlen(info->selector_name)); 2812 char *method = info->method.get(); 2813 if (method != nullptr) { 2814 if (Arch == Triple::x86_64) 2815 strcpy(method, "-[%rdi "); 2816 else if (Arch == Triple::aarch64) 2817 strcpy(method, "-[x0 "); 2818 else 2819 strcpy(method, "-[r? "); 2820 strcat(method, info->selector_name); 2821 strcat(method, "]"); 2822 *ReferenceName = method; 2823 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2824 } 2825 } 2826 info->class_name = nullptr; 2827 } 2828 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 2829 if (info->selector_name != nullptr) { 2830 info->method = 2831 llvm::make_unique<char[]>(17 + strlen(info->selector_name)); 2832 char *method = info->method.get(); 2833 if (method != nullptr) { 2834 if (Arch == Triple::x86_64) 2835 strcpy(method, "-[[%rdi super] "); 2836 else if (Arch == Triple::aarch64) 2837 strcpy(method, "-[[x0 super] "); 2838 else 2839 strcpy(method, "-[[r? super] "); 2840 strcat(method, info->selector_name); 2841 strcat(method, "]"); 2842 *ReferenceName = method; 2843 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2844 } 2845 info->class_name = nullptr; 2846 } 2847 } 2848 } 2849 } 2850 2851 // GuessPointerPointer() is passed the address of what might be a pointer to 2852 // a reference to an Objective-C class, selector, message ref or cfstring. 2853 // If so the value of the pointer is returned and one of the booleans are set 2854 // to true. If not zero is returned and all the booleans are set to false. 2855 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 2856 struct DisassembleInfo *info, 2857 bool &classref, bool &selref, bool &msgref, 2858 bool &cfstring) { 2859 classref = false; 2860 selref = false; 2861 msgref = false; 2862 cfstring = false; 2863 for (const auto &Load : info->O->load_commands()) { 2864 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2865 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2866 for (unsigned J = 0; J < Seg.nsects; ++J) { 2867 MachO::section_64 Sec = info->O->getSection64(Load, J); 2868 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 2869 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2870 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 2871 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 2872 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 2873 ReferenceValue >= Sec.addr && 2874 ReferenceValue < Sec.addr + Sec.size) { 2875 uint64_t sect_offset = ReferenceValue - Sec.addr; 2876 uint64_t object_offset = Sec.offset + sect_offset; 2877 StringRef MachOContents = info->O->getData(); 2878 uint64_t object_size = MachOContents.size(); 2879 const char *object_addr = (const char *)MachOContents.data(); 2880 if (object_offset < object_size) { 2881 uint64_t pointer_value; 2882 memcpy(&pointer_value, object_addr + object_offset, 2883 sizeof(uint64_t)); 2884 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2885 sys::swapByteOrder(pointer_value); 2886 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 2887 selref = true; 2888 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2889 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 2890 classref = true; 2891 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 2892 ReferenceValue + 8 < Sec.addr + Sec.size) { 2893 msgref = true; 2894 memcpy(&pointer_value, object_addr + object_offset + 8, 2895 sizeof(uint64_t)); 2896 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2897 sys::swapByteOrder(pointer_value); 2898 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 2899 cfstring = true; 2900 return pointer_value; 2901 } else { 2902 return 0; 2903 } 2904 } 2905 } 2906 } 2907 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 2908 } 2909 return 0; 2910 } 2911 2912 // get_pointer_64 returns a pointer to the bytes in the object file at the 2913 // Address from a section in the Mach-O file. And indirectly returns the 2914 // offset into the section, number of bytes left in the section past the offset 2915 // and which section is was being referenced. If the Address is not in a 2916 // section nullptr is returned. 2917 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 2918 uint32_t &left, SectionRef &S, 2919 DisassembleInfo *info, 2920 bool objc_only = false) { 2921 offset = 0; 2922 left = 0; 2923 S = SectionRef(); 2924 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 2925 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 2926 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 2927 if (SectSize == 0) 2928 continue; 2929 if (objc_only) { 2930 StringRef SectName; 2931 ((*(info->Sections))[SectIdx]).getName(SectName); 2932 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 2933 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 2934 if (SegName != "__OBJC" && SectName != "__cstring") 2935 continue; 2936 } 2937 if (Address >= SectAddress && Address < SectAddress + SectSize) { 2938 S = (*(info->Sections))[SectIdx]; 2939 offset = Address - SectAddress; 2940 left = SectSize - offset; 2941 StringRef SectContents; 2942 ((*(info->Sections))[SectIdx]).getContents(SectContents); 2943 return SectContents.data() + offset; 2944 } 2945 } 2946 return nullptr; 2947 } 2948 2949 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 2950 uint32_t &left, SectionRef &S, 2951 DisassembleInfo *info, 2952 bool objc_only = false) { 2953 return get_pointer_64(Address, offset, left, S, info, objc_only); 2954 } 2955 2956 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 2957 // the symbol indirectly through n_value. Based on the relocation information 2958 // for the specified section offset in the specified section reference. 2959 // If no relocation information is found and a non-zero ReferenceValue for the 2960 // symbol is passed, look up that address in the info's AddrMap. 2961 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 2962 DisassembleInfo *info, uint64_t &n_value, 2963 uint64_t ReferenceValue = 0) { 2964 n_value = 0; 2965 if (!info->verbose) 2966 return nullptr; 2967 2968 // See if there is an external relocation entry at the sect_offset. 2969 bool reloc_found = false; 2970 DataRefImpl Rel; 2971 MachO::any_relocation_info RE; 2972 bool isExtern = false; 2973 SymbolRef Symbol; 2974 for (const RelocationRef &Reloc : S.relocations()) { 2975 uint64_t RelocOffset = Reloc.getOffset(); 2976 if (RelocOffset == sect_offset) { 2977 Rel = Reloc.getRawDataRefImpl(); 2978 RE = info->O->getRelocation(Rel); 2979 if (info->O->isRelocationScattered(RE)) 2980 continue; 2981 isExtern = info->O->getPlainRelocationExternal(RE); 2982 if (isExtern) { 2983 symbol_iterator RelocSym = Reloc.getSymbol(); 2984 Symbol = *RelocSym; 2985 } 2986 reloc_found = true; 2987 break; 2988 } 2989 } 2990 // If there is an external relocation entry for a symbol in this section 2991 // at this section_offset then use that symbol's value for the n_value 2992 // and return its name. 2993 const char *SymbolName = nullptr; 2994 if (reloc_found && isExtern) { 2995 n_value = Symbol.getValue(); 2996 Expected<StringRef> NameOrError = Symbol.getName(); 2997 if (!NameOrError) 2998 report_error(info->O->getFileName(), NameOrError.takeError()); 2999 StringRef Name = *NameOrError; 3000 if (!Name.empty()) { 3001 SymbolName = Name.data(); 3002 return SymbolName; 3003 } 3004 } 3005 3006 // TODO: For fully linked images, look through the external relocation 3007 // entries off the dynamic symtab command. For these the r_offset is from the 3008 // start of the first writeable segment in the Mach-O file. So the offset 3009 // to this section from that segment is passed to this routine by the caller, 3010 // as the database_offset. Which is the difference of the section's starting 3011 // address and the first writable segment. 3012 // 3013 // NOTE: need add passing the database_offset to this routine. 3014 3015 // We did not find an external relocation entry so look up the ReferenceValue 3016 // as an address of a symbol and if found return that symbol's name. 3017 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 3018 3019 return SymbolName; 3020 } 3021 3022 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 3023 DisassembleInfo *info, 3024 uint32_t ReferenceValue) { 3025 uint64_t n_value64; 3026 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 3027 } 3028 3029 // These are structs in the Objective-C meta data and read to produce the 3030 // comments for disassembly. While these are part of the ABI they are no 3031 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 3032 // . 3033 3034 // The cfstring object in a 64-bit Mach-O file. 3035 struct cfstring64_t { 3036 uint64_t isa; // class64_t * (64-bit pointer) 3037 uint64_t flags; // flag bits 3038 uint64_t characters; // char * (64-bit pointer) 3039 uint64_t length; // number of non-NULL characters in above 3040 }; 3041 3042 // The class object in a 64-bit Mach-O file. 3043 struct class64_t { 3044 uint64_t isa; // class64_t * (64-bit pointer) 3045 uint64_t superclass; // class64_t * (64-bit pointer) 3046 uint64_t cache; // Cache (64-bit pointer) 3047 uint64_t vtable; // IMP * (64-bit pointer) 3048 uint64_t data; // class_ro64_t * (64-bit pointer) 3049 }; 3050 3051 struct class32_t { 3052 uint32_t isa; /* class32_t * (32-bit pointer) */ 3053 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3054 uint32_t cache; /* Cache (32-bit pointer) */ 3055 uint32_t vtable; /* IMP * (32-bit pointer) */ 3056 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3057 }; 3058 3059 struct class_ro64_t { 3060 uint32_t flags; 3061 uint32_t instanceStart; 3062 uint32_t instanceSize; 3063 uint32_t reserved; 3064 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3065 uint64_t name; // const char * (64-bit pointer) 3066 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3067 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3068 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3069 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3070 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3071 }; 3072 3073 struct class_ro32_t { 3074 uint32_t flags; 3075 uint32_t instanceStart; 3076 uint32_t instanceSize; 3077 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3078 uint32_t name; /* const char * (32-bit pointer) */ 3079 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3080 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3081 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3082 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3083 uint32_t baseProperties; /* const struct objc_property_list * 3084 (32-bit pointer) */ 3085 }; 3086 3087 /* Values for class_ro{64,32}_t->flags */ 3088 #define RO_META (1 << 0) 3089 #define RO_ROOT (1 << 1) 3090 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3091 3092 struct method_list64_t { 3093 uint32_t entsize; 3094 uint32_t count; 3095 /* struct method64_t first; These structures follow inline */ 3096 }; 3097 3098 struct method_list32_t { 3099 uint32_t entsize; 3100 uint32_t count; 3101 /* struct method32_t first; These structures follow inline */ 3102 }; 3103 3104 struct method64_t { 3105 uint64_t name; /* SEL (64-bit pointer) */ 3106 uint64_t types; /* const char * (64-bit pointer) */ 3107 uint64_t imp; /* IMP (64-bit pointer) */ 3108 }; 3109 3110 struct method32_t { 3111 uint32_t name; /* SEL (32-bit pointer) */ 3112 uint32_t types; /* const char * (32-bit pointer) */ 3113 uint32_t imp; /* IMP (32-bit pointer) */ 3114 }; 3115 3116 struct protocol_list64_t { 3117 uint64_t count; /* uintptr_t (a 64-bit value) */ 3118 /* struct protocol64_t * list[0]; These pointers follow inline */ 3119 }; 3120 3121 struct protocol_list32_t { 3122 uint32_t count; /* uintptr_t (a 32-bit value) */ 3123 /* struct protocol32_t * list[0]; These pointers follow inline */ 3124 }; 3125 3126 struct protocol64_t { 3127 uint64_t isa; /* id * (64-bit pointer) */ 3128 uint64_t name; /* const char * (64-bit pointer) */ 3129 uint64_t protocols; /* struct protocol_list64_t * 3130 (64-bit pointer) */ 3131 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3132 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3133 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3134 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3135 uint64_t instanceProperties; /* struct objc_property_list * 3136 (64-bit pointer) */ 3137 }; 3138 3139 struct protocol32_t { 3140 uint32_t isa; /* id * (32-bit pointer) */ 3141 uint32_t name; /* const char * (32-bit pointer) */ 3142 uint32_t protocols; /* struct protocol_list_t * 3143 (32-bit pointer) */ 3144 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3145 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3146 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3147 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3148 uint32_t instanceProperties; /* struct objc_property_list * 3149 (32-bit pointer) */ 3150 }; 3151 3152 struct ivar_list64_t { 3153 uint32_t entsize; 3154 uint32_t count; 3155 /* struct ivar64_t first; These structures follow inline */ 3156 }; 3157 3158 struct ivar_list32_t { 3159 uint32_t entsize; 3160 uint32_t count; 3161 /* struct ivar32_t first; These structures follow inline */ 3162 }; 3163 3164 struct ivar64_t { 3165 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3166 uint64_t name; /* const char * (64-bit pointer) */ 3167 uint64_t type; /* const char * (64-bit pointer) */ 3168 uint32_t alignment; 3169 uint32_t size; 3170 }; 3171 3172 struct ivar32_t { 3173 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3174 uint32_t name; /* const char * (32-bit pointer) */ 3175 uint32_t type; /* const char * (32-bit pointer) */ 3176 uint32_t alignment; 3177 uint32_t size; 3178 }; 3179 3180 struct objc_property_list64 { 3181 uint32_t entsize; 3182 uint32_t count; 3183 /* struct objc_property64 first; These structures follow inline */ 3184 }; 3185 3186 struct objc_property_list32 { 3187 uint32_t entsize; 3188 uint32_t count; 3189 /* struct objc_property32 first; These structures follow inline */ 3190 }; 3191 3192 struct objc_property64 { 3193 uint64_t name; /* const char * (64-bit pointer) */ 3194 uint64_t attributes; /* const char * (64-bit pointer) */ 3195 }; 3196 3197 struct objc_property32 { 3198 uint32_t name; /* const char * (32-bit pointer) */ 3199 uint32_t attributes; /* const char * (32-bit pointer) */ 3200 }; 3201 3202 struct category64_t { 3203 uint64_t name; /* const char * (64-bit pointer) */ 3204 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3205 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3206 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3207 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3208 uint64_t instanceProperties; /* struct objc_property_list * 3209 (64-bit pointer) */ 3210 }; 3211 3212 struct category32_t { 3213 uint32_t name; /* const char * (32-bit pointer) */ 3214 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3215 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3216 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3217 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3218 uint32_t instanceProperties; /* struct objc_property_list * 3219 (32-bit pointer) */ 3220 }; 3221 3222 struct objc_image_info64 { 3223 uint32_t version; 3224 uint32_t flags; 3225 }; 3226 struct objc_image_info32 { 3227 uint32_t version; 3228 uint32_t flags; 3229 }; 3230 struct imageInfo_t { 3231 uint32_t version; 3232 uint32_t flags; 3233 }; 3234 /* masks for objc_image_info.flags */ 3235 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3236 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3237 3238 struct message_ref64 { 3239 uint64_t imp; /* IMP (64-bit pointer) */ 3240 uint64_t sel; /* SEL (64-bit pointer) */ 3241 }; 3242 3243 struct message_ref32 { 3244 uint32_t imp; /* IMP (32-bit pointer) */ 3245 uint32_t sel; /* SEL (32-bit pointer) */ 3246 }; 3247 3248 // Objective-C 1 (32-bit only) meta data structs. 3249 3250 struct objc_module_t { 3251 uint32_t version; 3252 uint32_t size; 3253 uint32_t name; /* char * (32-bit pointer) */ 3254 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3255 }; 3256 3257 struct objc_symtab_t { 3258 uint32_t sel_ref_cnt; 3259 uint32_t refs; /* SEL * (32-bit pointer) */ 3260 uint16_t cls_def_cnt; 3261 uint16_t cat_def_cnt; 3262 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3263 }; 3264 3265 struct objc_class_t { 3266 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3267 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3268 uint32_t name; /* const char * (32-bit pointer) */ 3269 int32_t version; 3270 int32_t info; 3271 int32_t instance_size; 3272 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3273 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3274 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3275 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3276 }; 3277 3278 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3279 // class is not a metaclass 3280 #define CLS_CLASS 0x1 3281 // class is a metaclass 3282 #define CLS_META 0x2 3283 3284 struct objc_category_t { 3285 uint32_t category_name; /* char * (32-bit pointer) */ 3286 uint32_t class_name; /* char * (32-bit pointer) */ 3287 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3288 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3289 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3290 }; 3291 3292 struct objc_ivar_t { 3293 uint32_t ivar_name; /* char * (32-bit pointer) */ 3294 uint32_t ivar_type; /* char * (32-bit pointer) */ 3295 int32_t ivar_offset; 3296 }; 3297 3298 struct objc_ivar_list_t { 3299 int32_t ivar_count; 3300 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3301 }; 3302 3303 struct objc_method_list_t { 3304 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3305 int32_t method_count; 3306 // struct objc_method_t method_list[1]; /* variable length structure */ 3307 }; 3308 3309 struct objc_method_t { 3310 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3311 uint32_t method_types; /* char * (32-bit pointer) */ 3312 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3313 (32-bit pointer) */ 3314 }; 3315 3316 struct objc_protocol_list_t { 3317 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3318 int32_t count; 3319 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3320 // (32-bit pointer) */ 3321 }; 3322 3323 struct objc_protocol_t { 3324 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3325 uint32_t protocol_name; /* char * (32-bit pointer) */ 3326 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3327 uint32_t instance_methods; /* struct objc_method_description_list * 3328 (32-bit pointer) */ 3329 uint32_t class_methods; /* struct objc_method_description_list * 3330 (32-bit pointer) */ 3331 }; 3332 3333 struct objc_method_description_list_t { 3334 int32_t count; 3335 // struct objc_method_description_t list[1]; 3336 }; 3337 3338 struct objc_method_description_t { 3339 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3340 uint32_t types; /* char * (32-bit pointer) */ 3341 }; 3342 3343 inline void swapStruct(struct cfstring64_t &cfs) { 3344 sys::swapByteOrder(cfs.isa); 3345 sys::swapByteOrder(cfs.flags); 3346 sys::swapByteOrder(cfs.characters); 3347 sys::swapByteOrder(cfs.length); 3348 } 3349 3350 inline void swapStruct(struct class64_t &c) { 3351 sys::swapByteOrder(c.isa); 3352 sys::swapByteOrder(c.superclass); 3353 sys::swapByteOrder(c.cache); 3354 sys::swapByteOrder(c.vtable); 3355 sys::swapByteOrder(c.data); 3356 } 3357 3358 inline void swapStruct(struct class32_t &c) { 3359 sys::swapByteOrder(c.isa); 3360 sys::swapByteOrder(c.superclass); 3361 sys::swapByteOrder(c.cache); 3362 sys::swapByteOrder(c.vtable); 3363 sys::swapByteOrder(c.data); 3364 } 3365 3366 inline void swapStruct(struct class_ro64_t &cro) { 3367 sys::swapByteOrder(cro.flags); 3368 sys::swapByteOrder(cro.instanceStart); 3369 sys::swapByteOrder(cro.instanceSize); 3370 sys::swapByteOrder(cro.reserved); 3371 sys::swapByteOrder(cro.ivarLayout); 3372 sys::swapByteOrder(cro.name); 3373 sys::swapByteOrder(cro.baseMethods); 3374 sys::swapByteOrder(cro.baseProtocols); 3375 sys::swapByteOrder(cro.ivars); 3376 sys::swapByteOrder(cro.weakIvarLayout); 3377 sys::swapByteOrder(cro.baseProperties); 3378 } 3379 3380 inline void swapStruct(struct class_ro32_t &cro) { 3381 sys::swapByteOrder(cro.flags); 3382 sys::swapByteOrder(cro.instanceStart); 3383 sys::swapByteOrder(cro.instanceSize); 3384 sys::swapByteOrder(cro.ivarLayout); 3385 sys::swapByteOrder(cro.name); 3386 sys::swapByteOrder(cro.baseMethods); 3387 sys::swapByteOrder(cro.baseProtocols); 3388 sys::swapByteOrder(cro.ivars); 3389 sys::swapByteOrder(cro.weakIvarLayout); 3390 sys::swapByteOrder(cro.baseProperties); 3391 } 3392 3393 inline void swapStruct(struct method_list64_t &ml) { 3394 sys::swapByteOrder(ml.entsize); 3395 sys::swapByteOrder(ml.count); 3396 } 3397 3398 inline void swapStruct(struct method_list32_t &ml) { 3399 sys::swapByteOrder(ml.entsize); 3400 sys::swapByteOrder(ml.count); 3401 } 3402 3403 inline void swapStruct(struct method64_t &m) { 3404 sys::swapByteOrder(m.name); 3405 sys::swapByteOrder(m.types); 3406 sys::swapByteOrder(m.imp); 3407 } 3408 3409 inline void swapStruct(struct method32_t &m) { 3410 sys::swapByteOrder(m.name); 3411 sys::swapByteOrder(m.types); 3412 sys::swapByteOrder(m.imp); 3413 } 3414 3415 inline void swapStruct(struct protocol_list64_t &pl) { 3416 sys::swapByteOrder(pl.count); 3417 } 3418 3419 inline void swapStruct(struct protocol_list32_t &pl) { 3420 sys::swapByteOrder(pl.count); 3421 } 3422 3423 inline void swapStruct(struct protocol64_t &p) { 3424 sys::swapByteOrder(p.isa); 3425 sys::swapByteOrder(p.name); 3426 sys::swapByteOrder(p.protocols); 3427 sys::swapByteOrder(p.instanceMethods); 3428 sys::swapByteOrder(p.classMethods); 3429 sys::swapByteOrder(p.optionalInstanceMethods); 3430 sys::swapByteOrder(p.optionalClassMethods); 3431 sys::swapByteOrder(p.instanceProperties); 3432 } 3433 3434 inline void swapStruct(struct protocol32_t &p) { 3435 sys::swapByteOrder(p.isa); 3436 sys::swapByteOrder(p.name); 3437 sys::swapByteOrder(p.protocols); 3438 sys::swapByteOrder(p.instanceMethods); 3439 sys::swapByteOrder(p.classMethods); 3440 sys::swapByteOrder(p.optionalInstanceMethods); 3441 sys::swapByteOrder(p.optionalClassMethods); 3442 sys::swapByteOrder(p.instanceProperties); 3443 } 3444 3445 inline void swapStruct(struct ivar_list64_t &il) { 3446 sys::swapByteOrder(il.entsize); 3447 sys::swapByteOrder(il.count); 3448 } 3449 3450 inline void swapStruct(struct ivar_list32_t &il) { 3451 sys::swapByteOrder(il.entsize); 3452 sys::swapByteOrder(il.count); 3453 } 3454 3455 inline void swapStruct(struct ivar64_t &i) { 3456 sys::swapByteOrder(i.offset); 3457 sys::swapByteOrder(i.name); 3458 sys::swapByteOrder(i.type); 3459 sys::swapByteOrder(i.alignment); 3460 sys::swapByteOrder(i.size); 3461 } 3462 3463 inline void swapStruct(struct ivar32_t &i) { 3464 sys::swapByteOrder(i.offset); 3465 sys::swapByteOrder(i.name); 3466 sys::swapByteOrder(i.type); 3467 sys::swapByteOrder(i.alignment); 3468 sys::swapByteOrder(i.size); 3469 } 3470 3471 inline void swapStruct(struct objc_property_list64 &pl) { 3472 sys::swapByteOrder(pl.entsize); 3473 sys::swapByteOrder(pl.count); 3474 } 3475 3476 inline void swapStruct(struct objc_property_list32 &pl) { 3477 sys::swapByteOrder(pl.entsize); 3478 sys::swapByteOrder(pl.count); 3479 } 3480 3481 inline void swapStruct(struct objc_property64 &op) { 3482 sys::swapByteOrder(op.name); 3483 sys::swapByteOrder(op.attributes); 3484 } 3485 3486 inline void swapStruct(struct objc_property32 &op) { 3487 sys::swapByteOrder(op.name); 3488 sys::swapByteOrder(op.attributes); 3489 } 3490 3491 inline void swapStruct(struct category64_t &c) { 3492 sys::swapByteOrder(c.name); 3493 sys::swapByteOrder(c.cls); 3494 sys::swapByteOrder(c.instanceMethods); 3495 sys::swapByteOrder(c.classMethods); 3496 sys::swapByteOrder(c.protocols); 3497 sys::swapByteOrder(c.instanceProperties); 3498 } 3499 3500 inline void swapStruct(struct category32_t &c) { 3501 sys::swapByteOrder(c.name); 3502 sys::swapByteOrder(c.cls); 3503 sys::swapByteOrder(c.instanceMethods); 3504 sys::swapByteOrder(c.classMethods); 3505 sys::swapByteOrder(c.protocols); 3506 sys::swapByteOrder(c.instanceProperties); 3507 } 3508 3509 inline void swapStruct(struct objc_image_info64 &o) { 3510 sys::swapByteOrder(o.version); 3511 sys::swapByteOrder(o.flags); 3512 } 3513 3514 inline void swapStruct(struct objc_image_info32 &o) { 3515 sys::swapByteOrder(o.version); 3516 sys::swapByteOrder(o.flags); 3517 } 3518 3519 inline void swapStruct(struct imageInfo_t &o) { 3520 sys::swapByteOrder(o.version); 3521 sys::swapByteOrder(o.flags); 3522 } 3523 3524 inline void swapStruct(struct message_ref64 &mr) { 3525 sys::swapByteOrder(mr.imp); 3526 sys::swapByteOrder(mr.sel); 3527 } 3528 3529 inline void swapStruct(struct message_ref32 &mr) { 3530 sys::swapByteOrder(mr.imp); 3531 sys::swapByteOrder(mr.sel); 3532 } 3533 3534 inline void swapStruct(struct objc_module_t &module) { 3535 sys::swapByteOrder(module.version); 3536 sys::swapByteOrder(module.size); 3537 sys::swapByteOrder(module.name); 3538 sys::swapByteOrder(module.symtab); 3539 } 3540 3541 inline void swapStruct(struct objc_symtab_t &symtab) { 3542 sys::swapByteOrder(symtab.sel_ref_cnt); 3543 sys::swapByteOrder(symtab.refs); 3544 sys::swapByteOrder(symtab.cls_def_cnt); 3545 sys::swapByteOrder(symtab.cat_def_cnt); 3546 } 3547 3548 inline void swapStruct(struct objc_class_t &objc_class) { 3549 sys::swapByteOrder(objc_class.isa); 3550 sys::swapByteOrder(objc_class.super_class); 3551 sys::swapByteOrder(objc_class.name); 3552 sys::swapByteOrder(objc_class.version); 3553 sys::swapByteOrder(objc_class.info); 3554 sys::swapByteOrder(objc_class.instance_size); 3555 sys::swapByteOrder(objc_class.ivars); 3556 sys::swapByteOrder(objc_class.methodLists); 3557 sys::swapByteOrder(objc_class.cache); 3558 sys::swapByteOrder(objc_class.protocols); 3559 } 3560 3561 inline void swapStruct(struct objc_category_t &objc_category) { 3562 sys::swapByteOrder(objc_category.category_name); 3563 sys::swapByteOrder(objc_category.class_name); 3564 sys::swapByteOrder(objc_category.instance_methods); 3565 sys::swapByteOrder(objc_category.class_methods); 3566 sys::swapByteOrder(objc_category.protocols); 3567 } 3568 3569 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 3570 sys::swapByteOrder(objc_ivar_list.ivar_count); 3571 } 3572 3573 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 3574 sys::swapByteOrder(objc_ivar.ivar_name); 3575 sys::swapByteOrder(objc_ivar.ivar_type); 3576 sys::swapByteOrder(objc_ivar.ivar_offset); 3577 } 3578 3579 inline void swapStruct(struct objc_method_list_t &method_list) { 3580 sys::swapByteOrder(method_list.obsolete); 3581 sys::swapByteOrder(method_list.method_count); 3582 } 3583 3584 inline void swapStruct(struct objc_method_t &method) { 3585 sys::swapByteOrder(method.method_name); 3586 sys::swapByteOrder(method.method_types); 3587 sys::swapByteOrder(method.method_imp); 3588 } 3589 3590 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 3591 sys::swapByteOrder(protocol_list.next); 3592 sys::swapByteOrder(protocol_list.count); 3593 } 3594 3595 inline void swapStruct(struct objc_protocol_t &protocol) { 3596 sys::swapByteOrder(protocol.isa); 3597 sys::swapByteOrder(protocol.protocol_name); 3598 sys::swapByteOrder(protocol.protocol_list); 3599 sys::swapByteOrder(protocol.instance_methods); 3600 sys::swapByteOrder(protocol.class_methods); 3601 } 3602 3603 inline void swapStruct(struct objc_method_description_list_t &mdl) { 3604 sys::swapByteOrder(mdl.count); 3605 } 3606 3607 inline void swapStruct(struct objc_method_description_t &md) { 3608 sys::swapByteOrder(md.name); 3609 sys::swapByteOrder(md.types); 3610 } 3611 3612 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 3613 struct DisassembleInfo *info); 3614 3615 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 3616 // to an Objective-C class and returns the class name. It is also passed the 3617 // address of the pointer, so when the pointer is zero as it can be in an .o 3618 // file, that is used to look for an external relocation entry with a symbol 3619 // name. 3620 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 3621 uint64_t ReferenceValue, 3622 struct DisassembleInfo *info) { 3623 const char *r; 3624 uint32_t offset, left; 3625 SectionRef S; 3626 3627 // The pointer_value can be 0 in an object file and have a relocation 3628 // entry for the class symbol at the ReferenceValue (the address of the 3629 // pointer). 3630 if (pointer_value == 0) { 3631 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3632 if (r == nullptr || left < sizeof(uint64_t)) 3633 return nullptr; 3634 uint64_t n_value; 3635 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3636 if (symbol_name == nullptr) 3637 return nullptr; 3638 const char *class_name = strrchr(symbol_name, '$'); 3639 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 3640 return class_name + 2; 3641 else 3642 return nullptr; 3643 } 3644 3645 // The case were the pointer_value is non-zero and points to a class defined 3646 // in this Mach-O file. 3647 r = get_pointer_64(pointer_value, offset, left, S, info); 3648 if (r == nullptr || left < sizeof(struct class64_t)) 3649 return nullptr; 3650 struct class64_t c; 3651 memcpy(&c, r, sizeof(struct class64_t)); 3652 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3653 swapStruct(c); 3654 if (c.data == 0) 3655 return nullptr; 3656 r = get_pointer_64(c.data, offset, left, S, info); 3657 if (r == nullptr || left < sizeof(struct class_ro64_t)) 3658 return nullptr; 3659 struct class_ro64_t cro; 3660 memcpy(&cro, r, sizeof(struct class_ro64_t)); 3661 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3662 swapStruct(cro); 3663 if (cro.name == 0) 3664 return nullptr; 3665 const char *name = get_pointer_64(cro.name, offset, left, S, info); 3666 return name; 3667 } 3668 3669 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 3670 // pointer to a cfstring and returns its name or nullptr. 3671 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 3672 struct DisassembleInfo *info) { 3673 const char *r, *name; 3674 uint32_t offset, left; 3675 SectionRef S; 3676 struct cfstring64_t cfs; 3677 uint64_t cfs_characters; 3678 3679 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3680 if (r == nullptr || left < sizeof(struct cfstring64_t)) 3681 return nullptr; 3682 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 3683 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3684 swapStruct(cfs); 3685 if (cfs.characters == 0) { 3686 uint64_t n_value; 3687 const char *symbol_name = get_symbol_64( 3688 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 3689 if (symbol_name == nullptr) 3690 return nullptr; 3691 cfs_characters = n_value; 3692 } else 3693 cfs_characters = cfs.characters; 3694 name = get_pointer_64(cfs_characters, offset, left, S, info); 3695 3696 return name; 3697 } 3698 3699 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 3700 // of a pointer to an Objective-C selector reference when the pointer value is 3701 // zero as in a .o file and is likely to have a external relocation entry with 3702 // who's symbol's n_value is the real pointer to the selector name. If that is 3703 // the case the real pointer to the selector name is returned else 0 is 3704 // returned 3705 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 3706 struct DisassembleInfo *info) { 3707 uint32_t offset, left; 3708 SectionRef S; 3709 3710 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 3711 if (r == nullptr || left < sizeof(uint64_t)) 3712 return 0; 3713 uint64_t n_value; 3714 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3715 if (symbol_name == nullptr) 3716 return 0; 3717 return n_value; 3718 } 3719 3720 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 3721 const char *sectname) { 3722 for (const SectionRef &Section : O->sections()) { 3723 StringRef SectName; 3724 Section.getName(SectName); 3725 DataRefImpl Ref = Section.getRawDataRefImpl(); 3726 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3727 if (SegName == segname && SectName == sectname) 3728 return Section; 3729 } 3730 return SectionRef(); 3731 } 3732 3733 static void 3734 walk_pointer_list_64(const char *listname, const SectionRef S, 3735 MachOObjectFile *O, struct DisassembleInfo *info, 3736 void (*func)(uint64_t, struct DisassembleInfo *info)) { 3737 if (S == SectionRef()) 3738 return; 3739 3740 StringRef SectName; 3741 S.getName(SectName); 3742 DataRefImpl Ref = S.getRawDataRefImpl(); 3743 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3744 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3745 3746 StringRef BytesStr; 3747 S.getContents(BytesStr); 3748 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3749 3750 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 3751 uint32_t left = S.getSize() - i; 3752 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 3753 uint64_t p = 0; 3754 memcpy(&p, Contents + i, size); 3755 if (i + sizeof(uint64_t) > S.getSize()) 3756 outs() << listname << " list pointer extends past end of (" << SegName 3757 << "," << SectName << ") section\n"; 3758 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 3759 3760 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3761 sys::swapByteOrder(p); 3762 3763 uint64_t n_value = 0; 3764 const char *name = get_symbol_64(i, S, info, n_value, p); 3765 if (name == nullptr) 3766 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 3767 3768 if (n_value != 0) { 3769 outs() << format("0x%" PRIx64, n_value); 3770 if (p != 0) 3771 outs() << " + " << format("0x%" PRIx64, p); 3772 } else 3773 outs() << format("0x%" PRIx64, p); 3774 if (name != nullptr) 3775 outs() << " " << name; 3776 outs() << "\n"; 3777 3778 p += n_value; 3779 if (func) 3780 func(p, info); 3781 } 3782 } 3783 3784 static void 3785 walk_pointer_list_32(const char *listname, const SectionRef S, 3786 MachOObjectFile *O, struct DisassembleInfo *info, 3787 void (*func)(uint32_t, struct DisassembleInfo *info)) { 3788 if (S == SectionRef()) 3789 return; 3790 3791 StringRef SectName; 3792 S.getName(SectName); 3793 DataRefImpl Ref = S.getRawDataRefImpl(); 3794 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3795 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3796 3797 StringRef BytesStr; 3798 S.getContents(BytesStr); 3799 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3800 3801 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 3802 uint32_t left = S.getSize() - i; 3803 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 3804 uint32_t p = 0; 3805 memcpy(&p, Contents + i, size); 3806 if (i + sizeof(uint32_t) > S.getSize()) 3807 outs() << listname << " list pointer extends past end of (" << SegName 3808 << "," << SectName << ") section\n"; 3809 uint32_t Address = S.getAddress() + i; 3810 outs() << format("%08" PRIx32, Address) << " "; 3811 3812 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3813 sys::swapByteOrder(p); 3814 outs() << format("0x%" PRIx32, p); 3815 3816 const char *name = get_symbol_32(i, S, info, p); 3817 if (name != nullptr) 3818 outs() << " " << name; 3819 outs() << "\n"; 3820 3821 if (func) 3822 func(p, info); 3823 } 3824 } 3825 3826 static void print_layout_map(const char *layout_map, uint32_t left) { 3827 if (layout_map == nullptr) 3828 return; 3829 outs() << " layout map: "; 3830 do { 3831 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 3832 left--; 3833 layout_map++; 3834 } while (*layout_map != '\0' && left != 0); 3835 outs() << "\n"; 3836 } 3837 3838 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 3839 uint32_t offset, left; 3840 SectionRef S; 3841 const char *layout_map; 3842 3843 if (p == 0) 3844 return; 3845 layout_map = get_pointer_64(p, offset, left, S, info); 3846 print_layout_map(layout_map, left); 3847 } 3848 3849 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 3850 uint32_t offset, left; 3851 SectionRef S; 3852 const char *layout_map; 3853 3854 if (p == 0) 3855 return; 3856 layout_map = get_pointer_32(p, offset, left, S, info); 3857 print_layout_map(layout_map, left); 3858 } 3859 3860 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 3861 const char *indent) { 3862 struct method_list64_t ml; 3863 struct method64_t m; 3864 const char *r; 3865 uint32_t offset, xoffset, left, i; 3866 SectionRef S, xS; 3867 const char *name, *sym_name; 3868 uint64_t n_value; 3869 3870 r = get_pointer_64(p, offset, left, S, info); 3871 if (r == nullptr) 3872 return; 3873 memset(&ml, '\0', sizeof(struct method_list64_t)); 3874 if (left < sizeof(struct method_list64_t)) { 3875 memcpy(&ml, r, left); 3876 outs() << " (method_list_t entends past the end of the section)\n"; 3877 } else 3878 memcpy(&ml, r, sizeof(struct method_list64_t)); 3879 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3880 swapStruct(ml); 3881 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3882 outs() << indent << "\t\t count " << ml.count << "\n"; 3883 3884 p += sizeof(struct method_list64_t); 3885 offset += sizeof(struct method_list64_t); 3886 for (i = 0; i < ml.count; i++) { 3887 r = get_pointer_64(p, offset, left, S, info); 3888 if (r == nullptr) 3889 return; 3890 memset(&m, '\0', sizeof(struct method64_t)); 3891 if (left < sizeof(struct method64_t)) { 3892 memcpy(&m, r, left); 3893 outs() << indent << " (method_t extends past the end of the section)\n"; 3894 } else 3895 memcpy(&m, r, sizeof(struct method64_t)); 3896 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3897 swapStruct(m); 3898 3899 outs() << indent << "\t\t name "; 3900 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 3901 info, n_value, m.name); 3902 if (n_value != 0) { 3903 if (info->verbose && sym_name != nullptr) 3904 outs() << sym_name; 3905 else 3906 outs() << format("0x%" PRIx64, n_value); 3907 if (m.name != 0) 3908 outs() << " + " << format("0x%" PRIx64, m.name); 3909 } else 3910 outs() << format("0x%" PRIx64, m.name); 3911 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 3912 if (name != nullptr) 3913 outs() << format(" %.*s", left, name); 3914 outs() << "\n"; 3915 3916 outs() << indent << "\t\t types "; 3917 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 3918 info, n_value, m.types); 3919 if (n_value != 0) { 3920 if (info->verbose && sym_name != nullptr) 3921 outs() << sym_name; 3922 else 3923 outs() << format("0x%" PRIx64, n_value); 3924 if (m.types != 0) 3925 outs() << " + " << format("0x%" PRIx64, m.types); 3926 } else 3927 outs() << format("0x%" PRIx64, m.types); 3928 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 3929 if (name != nullptr) 3930 outs() << format(" %.*s", left, name); 3931 outs() << "\n"; 3932 3933 outs() << indent << "\t\t imp "; 3934 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 3935 n_value, m.imp); 3936 if (info->verbose && name == nullptr) { 3937 if (n_value != 0) { 3938 outs() << format("0x%" PRIx64, n_value) << " "; 3939 if (m.imp != 0) 3940 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 3941 } else 3942 outs() << format("0x%" PRIx64, m.imp) << " "; 3943 } 3944 if (name != nullptr) 3945 outs() << name; 3946 outs() << "\n"; 3947 3948 p += sizeof(struct method64_t); 3949 offset += sizeof(struct method64_t); 3950 } 3951 } 3952 3953 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 3954 const char *indent) { 3955 struct method_list32_t ml; 3956 struct method32_t m; 3957 const char *r, *name; 3958 uint32_t offset, xoffset, left, i; 3959 SectionRef S, xS; 3960 3961 r = get_pointer_32(p, offset, left, S, info); 3962 if (r == nullptr) 3963 return; 3964 memset(&ml, '\0', sizeof(struct method_list32_t)); 3965 if (left < sizeof(struct method_list32_t)) { 3966 memcpy(&ml, r, left); 3967 outs() << " (method_list_t entends past the end of the section)\n"; 3968 } else 3969 memcpy(&ml, r, sizeof(struct method_list32_t)); 3970 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3971 swapStruct(ml); 3972 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3973 outs() << indent << "\t\t count " << ml.count << "\n"; 3974 3975 p += sizeof(struct method_list32_t); 3976 offset += sizeof(struct method_list32_t); 3977 for (i = 0; i < ml.count; i++) { 3978 r = get_pointer_32(p, offset, left, S, info); 3979 if (r == nullptr) 3980 return; 3981 memset(&m, '\0', sizeof(struct method32_t)); 3982 if (left < sizeof(struct method32_t)) { 3983 memcpy(&ml, r, left); 3984 outs() << indent << " (method_t entends past the end of the section)\n"; 3985 } else 3986 memcpy(&m, r, sizeof(struct method32_t)); 3987 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3988 swapStruct(m); 3989 3990 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 3991 name = get_pointer_32(m.name, xoffset, left, xS, info); 3992 if (name != nullptr) 3993 outs() << format(" %.*s", left, name); 3994 outs() << "\n"; 3995 3996 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 3997 name = get_pointer_32(m.types, xoffset, left, xS, info); 3998 if (name != nullptr) 3999 outs() << format(" %.*s", left, name); 4000 outs() << "\n"; 4001 4002 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4003 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 4004 m.imp); 4005 if (name != nullptr) 4006 outs() << " " << name; 4007 outs() << "\n"; 4008 4009 p += sizeof(struct method32_t); 4010 offset += sizeof(struct method32_t); 4011 } 4012 } 4013 4014 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 4015 uint32_t offset, left, xleft; 4016 SectionRef S; 4017 struct objc_method_list_t method_list; 4018 struct objc_method_t method; 4019 const char *r, *methods, *name, *SymbolName; 4020 int32_t i; 4021 4022 r = get_pointer_32(p, offset, left, S, info, true); 4023 if (r == nullptr) 4024 return true; 4025 4026 outs() << "\n"; 4027 if (left > sizeof(struct objc_method_list_t)) { 4028 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 4029 } else { 4030 outs() << "\t\t objc_method_list extends past end of the section\n"; 4031 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 4032 memcpy(&method_list, r, left); 4033 } 4034 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4035 swapStruct(method_list); 4036 4037 outs() << "\t\t obsolete " 4038 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4039 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4040 4041 methods = r + sizeof(struct objc_method_list_t); 4042 for (i = 0; i < method_list.method_count; i++) { 4043 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4044 outs() << "\t\t remaining method's extend past the of the section\n"; 4045 break; 4046 } 4047 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4048 sizeof(struct objc_method_t)); 4049 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4050 swapStruct(method); 4051 4052 outs() << "\t\t method_name " 4053 << format("0x%08" PRIx32, method.method_name); 4054 if (info->verbose) { 4055 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4056 if (name != nullptr) 4057 outs() << format(" %.*s", xleft, name); 4058 else 4059 outs() << " (not in an __OBJC section)"; 4060 } 4061 outs() << "\n"; 4062 4063 outs() << "\t\t method_types " 4064 << format("0x%08" PRIx32, method.method_types); 4065 if (info->verbose) { 4066 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4067 if (name != nullptr) 4068 outs() << format(" %.*s", xleft, name); 4069 else 4070 outs() << " (not in an __OBJC section)"; 4071 } 4072 outs() << "\n"; 4073 4074 outs() << "\t\t method_imp " 4075 << format("0x%08" PRIx32, method.method_imp) << " "; 4076 if (info->verbose) { 4077 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4078 if (SymbolName != nullptr) 4079 outs() << SymbolName; 4080 } 4081 outs() << "\n"; 4082 } 4083 return false; 4084 } 4085 4086 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4087 struct protocol_list64_t pl; 4088 uint64_t q, n_value; 4089 struct protocol64_t pc; 4090 const char *r; 4091 uint32_t offset, xoffset, left, i; 4092 SectionRef S, xS; 4093 const char *name, *sym_name; 4094 4095 r = get_pointer_64(p, offset, left, S, info); 4096 if (r == nullptr) 4097 return; 4098 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4099 if (left < sizeof(struct protocol_list64_t)) { 4100 memcpy(&pl, r, left); 4101 outs() << " (protocol_list_t entends past the end of the section)\n"; 4102 } else 4103 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4104 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4105 swapStruct(pl); 4106 outs() << " count " << pl.count << "\n"; 4107 4108 p += sizeof(struct protocol_list64_t); 4109 offset += sizeof(struct protocol_list64_t); 4110 for (i = 0; i < pl.count; i++) { 4111 r = get_pointer_64(p, offset, left, S, info); 4112 if (r == nullptr) 4113 return; 4114 q = 0; 4115 if (left < sizeof(uint64_t)) { 4116 memcpy(&q, r, left); 4117 outs() << " (protocol_t * entends past the end of the section)\n"; 4118 } else 4119 memcpy(&q, r, sizeof(uint64_t)); 4120 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4121 sys::swapByteOrder(q); 4122 4123 outs() << "\t\t list[" << i << "] "; 4124 sym_name = get_symbol_64(offset, S, info, n_value, q); 4125 if (n_value != 0) { 4126 if (info->verbose && sym_name != nullptr) 4127 outs() << sym_name; 4128 else 4129 outs() << format("0x%" PRIx64, n_value); 4130 if (q != 0) 4131 outs() << " + " << format("0x%" PRIx64, q); 4132 } else 4133 outs() << format("0x%" PRIx64, q); 4134 outs() << " (struct protocol_t *)\n"; 4135 4136 r = get_pointer_64(q + n_value, offset, left, S, info); 4137 if (r == nullptr) 4138 return; 4139 memset(&pc, '\0', sizeof(struct protocol64_t)); 4140 if (left < sizeof(struct protocol64_t)) { 4141 memcpy(&pc, r, left); 4142 outs() << " (protocol_t entends past the end of the section)\n"; 4143 } else 4144 memcpy(&pc, r, sizeof(struct protocol64_t)); 4145 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4146 swapStruct(pc); 4147 4148 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4149 4150 outs() << "\t\t\t name "; 4151 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4152 info, n_value, pc.name); 4153 if (n_value != 0) { 4154 if (info->verbose && sym_name != nullptr) 4155 outs() << sym_name; 4156 else 4157 outs() << format("0x%" PRIx64, n_value); 4158 if (pc.name != 0) 4159 outs() << " + " << format("0x%" PRIx64, pc.name); 4160 } else 4161 outs() << format("0x%" PRIx64, pc.name); 4162 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4163 if (name != nullptr) 4164 outs() << format(" %.*s", left, name); 4165 outs() << "\n"; 4166 4167 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4168 4169 outs() << "\t\t instanceMethods "; 4170 sym_name = 4171 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4172 S, info, n_value, pc.instanceMethods); 4173 if (n_value != 0) { 4174 if (info->verbose && sym_name != nullptr) 4175 outs() << sym_name; 4176 else 4177 outs() << format("0x%" PRIx64, n_value); 4178 if (pc.instanceMethods != 0) 4179 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4180 } else 4181 outs() << format("0x%" PRIx64, pc.instanceMethods); 4182 outs() << " (struct method_list_t *)\n"; 4183 if (pc.instanceMethods + n_value != 0) 4184 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4185 4186 outs() << "\t\t classMethods "; 4187 sym_name = 4188 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4189 info, n_value, pc.classMethods); 4190 if (n_value != 0) { 4191 if (info->verbose && sym_name != nullptr) 4192 outs() << sym_name; 4193 else 4194 outs() << format("0x%" PRIx64, n_value); 4195 if (pc.classMethods != 0) 4196 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4197 } else 4198 outs() << format("0x%" PRIx64, pc.classMethods); 4199 outs() << " (struct method_list_t *)\n"; 4200 if (pc.classMethods + n_value != 0) 4201 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4202 4203 outs() << "\t optionalInstanceMethods " 4204 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4205 outs() << "\t optionalClassMethods " 4206 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4207 outs() << "\t instanceProperties " 4208 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4209 4210 p += sizeof(uint64_t); 4211 offset += sizeof(uint64_t); 4212 } 4213 } 4214 4215 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4216 struct protocol_list32_t pl; 4217 uint32_t q; 4218 struct protocol32_t pc; 4219 const char *r; 4220 uint32_t offset, xoffset, left, i; 4221 SectionRef S, xS; 4222 const char *name; 4223 4224 r = get_pointer_32(p, offset, left, S, info); 4225 if (r == nullptr) 4226 return; 4227 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4228 if (left < sizeof(struct protocol_list32_t)) { 4229 memcpy(&pl, r, left); 4230 outs() << " (protocol_list_t entends past the end of the section)\n"; 4231 } else 4232 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4233 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4234 swapStruct(pl); 4235 outs() << " count " << pl.count << "\n"; 4236 4237 p += sizeof(struct protocol_list32_t); 4238 offset += sizeof(struct protocol_list32_t); 4239 for (i = 0; i < pl.count; i++) { 4240 r = get_pointer_32(p, offset, left, S, info); 4241 if (r == nullptr) 4242 return; 4243 q = 0; 4244 if (left < sizeof(uint32_t)) { 4245 memcpy(&q, r, left); 4246 outs() << " (protocol_t * entends past the end of the section)\n"; 4247 } else 4248 memcpy(&q, r, sizeof(uint32_t)); 4249 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4250 sys::swapByteOrder(q); 4251 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4252 << " (struct protocol_t *)\n"; 4253 r = get_pointer_32(q, offset, left, S, info); 4254 if (r == nullptr) 4255 return; 4256 memset(&pc, '\0', sizeof(struct protocol32_t)); 4257 if (left < sizeof(struct protocol32_t)) { 4258 memcpy(&pc, r, left); 4259 outs() << " (protocol_t entends past the end of the section)\n"; 4260 } else 4261 memcpy(&pc, r, sizeof(struct protocol32_t)); 4262 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4263 swapStruct(pc); 4264 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4265 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4266 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4267 if (name != nullptr) 4268 outs() << format(" %.*s", left, name); 4269 outs() << "\n"; 4270 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4271 outs() << "\t\t instanceMethods " 4272 << format("0x%" PRIx32, pc.instanceMethods) 4273 << " (struct method_list_t *)\n"; 4274 if (pc.instanceMethods != 0) 4275 print_method_list32_t(pc.instanceMethods, info, "\t"); 4276 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4277 << " (struct method_list_t *)\n"; 4278 if (pc.classMethods != 0) 4279 print_method_list32_t(pc.classMethods, info, "\t"); 4280 outs() << "\t optionalInstanceMethods " 4281 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4282 outs() << "\t optionalClassMethods " 4283 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4284 outs() << "\t instanceProperties " 4285 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4286 p += sizeof(uint32_t); 4287 offset += sizeof(uint32_t); 4288 } 4289 } 4290 4291 static void print_indent(uint32_t indent) { 4292 for (uint32_t i = 0; i < indent;) { 4293 if (indent - i >= 8) { 4294 outs() << "\t"; 4295 i += 8; 4296 } else { 4297 for (uint32_t j = i; j < indent; j++) 4298 outs() << " "; 4299 return; 4300 } 4301 } 4302 } 4303 4304 static bool print_method_description_list(uint32_t p, uint32_t indent, 4305 struct DisassembleInfo *info) { 4306 uint32_t offset, left, xleft; 4307 SectionRef S; 4308 struct objc_method_description_list_t mdl; 4309 struct objc_method_description_t md; 4310 const char *r, *list, *name; 4311 int32_t i; 4312 4313 r = get_pointer_32(p, offset, left, S, info, true); 4314 if (r == nullptr) 4315 return true; 4316 4317 outs() << "\n"; 4318 if (left > sizeof(struct objc_method_description_list_t)) { 4319 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 4320 } else { 4321 print_indent(indent); 4322 outs() << " objc_method_description_list extends past end of the section\n"; 4323 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 4324 memcpy(&mdl, r, left); 4325 } 4326 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4327 swapStruct(mdl); 4328 4329 print_indent(indent); 4330 outs() << " count " << mdl.count << "\n"; 4331 4332 list = r + sizeof(struct objc_method_description_list_t); 4333 for (i = 0; i < mdl.count; i++) { 4334 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 4335 print_indent(indent); 4336 outs() << " remaining list entries extend past the of the section\n"; 4337 break; 4338 } 4339 print_indent(indent); 4340 outs() << " list[" << i << "]\n"; 4341 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 4342 sizeof(struct objc_method_description_t)); 4343 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4344 swapStruct(md); 4345 4346 print_indent(indent); 4347 outs() << " name " << format("0x%08" PRIx32, md.name); 4348 if (info->verbose) { 4349 name = get_pointer_32(md.name, offset, xleft, S, info, true); 4350 if (name != nullptr) 4351 outs() << format(" %.*s", xleft, name); 4352 else 4353 outs() << " (not in an __OBJC section)"; 4354 } 4355 outs() << "\n"; 4356 4357 print_indent(indent); 4358 outs() << " types " << format("0x%08" PRIx32, md.types); 4359 if (info->verbose) { 4360 name = get_pointer_32(md.types, offset, xleft, S, info, true); 4361 if (name != nullptr) 4362 outs() << format(" %.*s", xleft, name); 4363 else 4364 outs() << " (not in an __OBJC section)"; 4365 } 4366 outs() << "\n"; 4367 } 4368 return false; 4369 } 4370 4371 static bool print_protocol_list(uint32_t p, uint32_t indent, 4372 struct DisassembleInfo *info); 4373 4374 static bool print_protocol(uint32_t p, uint32_t indent, 4375 struct DisassembleInfo *info) { 4376 uint32_t offset, left; 4377 SectionRef S; 4378 struct objc_protocol_t protocol; 4379 const char *r, *name; 4380 4381 r = get_pointer_32(p, offset, left, S, info, true); 4382 if (r == nullptr) 4383 return true; 4384 4385 outs() << "\n"; 4386 if (left >= sizeof(struct objc_protocol_t)) { 4387 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 4388 } else { 4389 print_indent(indent); 4390 outs() << " Protocol extends past end of the section\n"; 4391 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 4392 memcpy(&protocol, r, left); 4393 } 4394 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4395 swapStruct(protocol); 4396 4397 print_indent(indent); 4398 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 4399 << "\n"; 4400 4401 print_indent(indent); 4402 outs() << " protocol_name " 4403 << format("0x%08" PRIx32, protocol.protocol_name); 4404 if (info->verbose) { 4405 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 4406 if (name != nullptr) 4407 outs() << format(" %.*s", left, name); 4408 else 4409 outs() << " (not in an __OBJC section)"; 4410 } 4411 outs() << "\n"; 4412 4413 print_indent(indent); 4414 outs() << " protocol_list " 4415 << format("0x%08" PRIx32, protocol.protocol_list); 4416 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 4417 outs() << " (not in an __OBJC section)\n"; 4418 4419 print_indent(indent); 4420 outs() << " instance_methods " 4421 << format("0x%08" PRIx32, protocol.instance_methods); 4422 if (print_method_description_list(protocol.instance_methods, indent, info)) 4423 outs() << " (not in an __OBJC section)\n"; 4424 4425 print_indent(indent); 4426 outs() << " class_methods " 4427 << format("0x%08" PRIx32, protocol.class_methods); 4428 if (print_method_description_list(protocol.class_methods, indent, info)) 4429 outs() << " (not in an __OBJC section)\n"; 4430 4431 return false; 4432 } 4433 4434 static bool print_protocol_list(uint32_t p, uint32_t indent, 4435 struct DisassembleInfo *info) { 4436 uint32_t offset, left, l; 4437 SectionRef S; 4438 struct objc_protocol_list_t protocol_list; 4439 const char *r, *list; 4440 int32_t i; 4441 4442 r = get_pointer_32(p, offset, left, S, info, true); 4443 if (r == nullptr) 4444 return true; 4445 4446 outs() << "\n"; 4447 if (left > sizeof(struct objc_protocol_list_t)) { 4448 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 4449 } else { 4450 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 4451 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 4452 memcpy(&protocol_list, r, left); 4453 } 4454 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4455 swapStruct(protocol_list); 4456 4457 print_indent(indent); 4458 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 4459 << "\n"; 4460 print_indent(indent); 4461 outs() << " count " << protocol_list.count << "\n"; 4462 4463 list = r + sizeof(struct objc_protocol_list_t); 4464 for (i = 0; i < protocol_list.count; i++) { 4465 if ((i + 1) * sizeof(uint32_t) > left) { 4466 outs() << "\t\t remaining list entries extend past the of the section\n"; 4467 break; 4468 } 4469 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 4470 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4471 sys::swapByteOrder(l); 4472 4473 print_indent(indent); 4474 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 4475 if (print_protocol(l, indent, info)) 4476 outs() << "(not in an __OBJC section)\n"; 4477 } 4478 return false; 4479 } 4480 4481 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 4482 struct ivar_list64_t il; 4483 struct ivar64_t i; 4484 const char *r; 4485 uint32_t offset, xoffset, left, j; 4486 SectionRef S, xS; 4487 const char *name, *sym_name, *ivar_offset_p; 4488 uint64_t ivar_offset, n_value; 4489 4490 r = get_pointer_64(p, offset, left, S, info); 4491 if (r == nullptr) 4492 return; 4493 memset(&il, '\0', sizeof(struct ivar_list64_t)); 4494 if (left < sizeof(struct ivar_list64_t)) { 4495 memcpy(&il, r, left); 4496 outs() << " (ivar_list_t entends past the end of the section)\n"; 4497 } else 4498 memcpy(&il, r, sizeof(struct ivar_list64_t)); 4499 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4500 swapStruct(il); 4501 outs() << " entsize " << il.entsize << "\n"; 4502 outs() << " count " << il.count << "\n"; 4503 4504 p += sizeof(struct ivar_list64_t); 4505 offset += sizeof(struct ivar_list64_t); 4506 for (j = 0; j < il.count; j++) { 4507 r = get_pointer_64(p, offset, left, S, info); 4508 if (r == nullptr) 4509 return; 4510 memset(&i, '\0', sizeof(struct ivar64_t)); 4511 if (left < sizeof(struct ivar64_t)) { 4512 memcpy(&i, r, left); 4513 outs() << " (ivar_t entends past the end of the section)\n"; 4514 } else 4515 memcpy(&i, r, sizeof(struct ivar64_t)); 4516 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4517 swapStruct(i); 4518 4519 outs() << "\t\t\t offset "; 4520 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 4521 info, n_value, i.offset); 4522 if (n_value != 0) { 4523 if (info->verbose && sym_name != nullptr) 4524 outs() << sym_name; 4525 else 4526 outs() << format("0x%" PRIx64, n_value); 4527 if (i.offset != 0) 4528 outs() << " + " << format("0x%" PRIx64, i.offset); 4529 } else 4530 outs() << format("0x%" PRIx64, i.offset); 4531 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 4532 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4533 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4534 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4535 sys::swapByteOrder(ivar_offset); 4536 outs() << " " << ivar_offset << "\n"; 4537 } else 4538 outs() << "\n"; 4539 4540 outs() << "\t\t\t name "; 4541 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 4542 n_value, i.name); 4543 if (n_value != 0) { 4544 if (info->verbose && sym_name != nullptr) 4545 outs() << sym_name; 4546 else 4547 outs() << format("0x%" PRIx64, n_value); 4548 if (i.name != 0) 4549 outs() << " + " << format("0x%" PRIx64, i.name); 4550 } else 4551 outs() << format("0x%" PRIx64, i.name); 4552 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 4553 if (name != nullptr) 4554 outs() << format(" %.*s", left, name); 4555 outs() << "\n"; 4556 4557 outs() << "\t\t\t type "; 4558 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 4559 n_value, i.name); 4560 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 4561 if (n_value != 0) { 4562 if (info->verbose && sym_name != nullptr) 4563 outs() << sym_name; 4564 else 4565 outs() << format("0x%" PRIx64, n_value); 4566 if (i.type != 0) 4567 outs() << " + " << format("0x%" PRIx64, i.type); 4568 } else 4569 outs() << format("0x%" PRIx64, i.type); 4570 if (name != nullptr) 4571 outs() << format(" %.*s", left, name); 4572 outs() << "\n"; 4573 4574 outs() << "\t\t\talignment " << i.alignment << "\n"; 4575 outs() << "\t\t\t size " << i.size << "\n"; 4576 4577 p += sizeof(struct ivar64_t); 4578 offset += sizeof(struct ivar64_t); 4579 } 4580 } 4581 4582 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 4583 struct ivar_list32_t il; 4584 struct ivar32_t i; 4585 const char *r; 4586 uint32_t offset, xoffset, left, j; 4587 SectionRef S, xS; 4588 const char *name, *ivar_offset_p; 4589 uint32_t ivar_offset; 4590 4591 r = get_pointer_32(p, offset, left, S, info); 4592 if (r == nullptr) 4593 return; 4594 memset(&il, '\0', sizeof(struct ivar_list32_t)); 4595 if (left < sizeof(struct ivar_list32_t)) { 4596 memcpy(&il, r, left); 4597 outs() << " (ivar_list_t entends past the end of the section)\n"; 4598 } else 4599 memcpy(&il, r, sizeof(struct ivar_list32_t)); 4600 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4601 swapStruct(il); 4602 outs() << " entsize " << il.entsize << "\n"; 4603 outs() << " count " << il.count << "\n"; 4604 4605 p += sizeof(struct ivar_list32_t); 4606 offset += sizeof(struct ivar_list32_t); 4607 for (j = 0; j < il.count; j++) { 4608 r = get_pointer_32(p, offset, left, S, info); 4609 if (r == nullptr) 4610 return; 4611 memset(&i, '\0', sizeof(struct ivar32_t)); 4612 if (left < sizeof(struct ivar32_t)) { 4613 memcpy(&i, r, left); 4614 outs() << " (ivar_t entends past the end of the section)\n"; 4615 } else 4616 memcpy(&i, r, sizeof(struct ivar32_t)); 4617 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4618 swapStruct(i); 4619 4620 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 4621 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 4622 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4623 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4624 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4625 sys::swapByteOrder(ivar_offset); 4626 outs() << " " << ivar_offset << "\n"; 4627 } else 4628 outs() << "\n"; 4629 4630 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 4631 name = get_pointer_32(i.name, xoffset, left, xS, info); 4632 if (name != nullptr) 4633 outs() << format(" %.*s", left, name); 4634 outs() << "\n"; 4635 4636 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 4637 name = get_pointer_32(i.type, xoffset, left, xS, info); 4638 if (name != nullptr) 4639 outs() << format(" %.*s", left, name); 4640 outs() << "\n"; 4641 4642 outs() << "\t\t\talignment " << i.alignment << "\n"; 4643 outs() << "\t\t\t size " << i.size << "\n"; 4644 4645 p += sizeof(struct ivar32_t); 4646 offset += sizeof(struct ivar32_t); 4647 } 4648 } 4649 4650 static void print_objc_property_list64(uint64_t p, 4651 struct DisassembleInfo *info) { 4652 struct objc_property_list64 opl; 4653 struct objc_property64 op; 4654 const char *r; 4655 uint32_t offset, xoffset, left, j; 4656 SectionRef S, xS; 4657 const char *name, *sym_name; 4658 uint64_t n_value; 4659 4660 r = get_pointer_64(p, offset, left, S, info); 4661 if (r == nullptr) 4662 return; 4663 memset(&opl, '\0', sizeof(struct objc_property_list64)); 4664 if (left < sizeof(struct objc_property_list64)) { 4665 memcpy(&opl, r, left); 4666 outs() << " (objc_property_list entends past the end of the section)\n"; 4667 } else 4668 memcpy(&opl, r, sizeof(struct objc_property_list64)); 4669 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4670 swapStruct(opl); 4671 outs() << " entsize " << opl.entsize << "\n"; 4672 outs() << " count " << opl.count << "\n"; 4673 4674 p += sizeof(struct objc_property_list64); 4675 offset += sizeof(struct objc_property_list64); 4676 for (j = 0; j < opl.count; j++) { 4677 r = get_pointer_64(p, offset, left, S, info); 4678 if (r == nullptr) 4679 return; 4680 memset(&op, '\0', sizeof(struct objc_property64)); 4681 if (left < sizeof(struct objc_property64)) { 4682 memcpy(&op, r, left); 4683 outs() << " (objc_property entends past the end of the section)\n"; 4684 } else 4685 memcpy(&op, r, sizeof(struct objc_property64)); 4686 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4687 swapStruct(op); 4688 4689 outs() << "\t\t\t name "; 4690 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 4691 info, n_value, op.name); 4692 if (n_value != 0) { 4693 if (info->verbose && sym_name != nullptr) 4694 outs() << sym_name; 4695 else 4696 outs() << format("0x%" PRIx64, n_value); 4697 if (op.name != 0) 4698 outs() << " + " << format("0x%" PRIx64, op.name); 4699 } else 4700 outs() << format("0x%" PRIx64, op.name); 4701 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 4702 if (name != nullptr) 4703 outs() << format(" %.*s", left, name); 4704 outs() << "\n"; 4705 4706 outs() << "\t\t\tattributes "; 4707 sym_name = 4708 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 4709 info, n_value, op.attributes); 4710 if (n_value != 0) { 4711 if (info->verbose && sym_name != nullptr) 4712 outs() << sym_name; 4713 else 4714 outs() << format("0x%" PRIx64, n_value); 4715 if (op.attributes != 0) 4716 outs() << " + " << format("0x%" PRIx64, op.attributes); 4717 } else 4718 outs() << format("0x%" PRIx64, op.attributes); 4719 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 4720 if (name != nullptr) 4721 outs() << format(" %.*s", left, name); 4722 outs() << "\n"; 4723 4724 p += sizeof(struct objc_property64); 4725 offset += sizeof(struct objc_property64); 4726 } 4727 } 4728 4729 static void print_objc_property_list32(uint32_t p, 4730 struct DisassembleInfo *info) { 4731 struct objc_property_list32 opl; 4732 struct objc_property32 op; 4733 const char *r; 4734 uint32_t offset, xoffset, left, j; 4735 SectionRef S, xS; 4736 const char *name; 4737 4738 r = get_pointer_32(p, offset, left, S, info); 4739 if (r == nullptr) 4740 return; 4741 memset(&opl, '\0', sizeof(struct objc_property_list32)); 4742 if (left < sizeof(struct objc_property_list32)) { 4743 memcpy(&opl, r, left); 4744 outs() << " (objc_property_list entends past the end of the section)\n"; 4745 } else 4746 memcpy(&opl, r, sizeof(struct objc_property_list32)); 4747 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4748 swapStruct(opl); 4749 outs() << " entsize " << opl.entsize << "\n"; 4750 outs() << " count " << opl.count << "\n"; 4751 4752 p += sizeof(struct objc_property_list32); 4753 offset += sizeof(struct objc_property_list32); 4754 for (j = 0; j < opl.count; j++) { 4755 r = get_pointer_32(p, offset, left, S, info); 4756 if (r == nullptr) 4757 return; 4758 memset(&op, '\0', sizeof(struct objc_property32)); 4759 if (left < sizeof(struct objc_property32)) { 4760 memcpy(&op, r, left); 4761 outs() << " (objc_property entends past the end of the section)\n"; 4762 } else 4763 memcpy(&op, r, sizeof(struct objc_property32)); 4764 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4765 swapStruct(op); 4766 4767 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 4768 name = get_pointer_32(op.name, xoffset, left, xS, info); 4769 if (name != nullptr) 4770 outs() << format(" %.*s", left, name); 4771 outs() << "\n"; 4772 4773 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 4774 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 4775 if (name != nullptr) 4776 outs() << format(" %.*s", left, name); 4777 outs() << "\n"; 4778 4779 p += sizeof(struct objc_property32); 4780 offset += sizeof(struct objc_property32); 4781 } 4782 } 4783 4784 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 4785 bool &is_meta_class) { 4786 struct class_ro64_t cro; 4787 const char *r; 4788 uint32_t offset, xoffset, left; 4789 SectionRef S, xS; 4790 const char *name, *sym_name; 4791 uint64_t n_value; 4792 4793 r = get_pointer_64(p, offset, left, S, info); 4794 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4795 return false; 4796 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4797 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4798 swapStruct(cro); 4799 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4800 if (cro.flags & RO_META) 4801 outs() << " RO_META"; 4802 if (cro.flags & RO_ROOT) 4803 outs() << " RO_ROOT"; 4804 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4805 outs() << " RO_HAS_CXX_STRUCTORS"; 4806 outs() << "\n"; 4807 outs() << " instanceStart " << cro.instanceStart << "\n"; 4808 outs() << " instanceSize " << cro.instanceSize << "\n"; 4809 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 4810 << "\n"; 4811 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 4812 << "\n"; 4813 print_layout_map64(cro.ivarLayout, info); 4814 4815 outs() << " name "; 4816 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 4817 info, n_value, cro.name); 4818 if (n_value != 0) { 4819 if (info->verbose && sym_name != nullptr) 4820 outs() << sym_name; 4821 else 4822 outs() << format("0x%" PRIx64, n_value); 4823 if (cro.name != 0) 4824 outs() << " + " << format("0x%" PRIx64, cro.name); 4825 } else 4826 outs() << format("0x%" PRIx64, cro.name); 4827 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 4828 if (name != nullptr) 4829 outs() << format(" %.*s", left, name); 4830 outs() << "\n"; 4831 4832 outs() << " baseMethods "; 4833 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 4834 S, info, n_value, cro.baseMethods); 4835 if (n_value != 0) { 4836 if (info->verbose && sym_name != nullptr) 4837 outs() << sym_name; 4838 else 4839 outs() << format("0x%" PRIx64, n_value); 4840 if (cro.baseMethods != 0) 4841 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 4842 } else 4843 outs() << format("0x%" PRIx64, cro.baseMethods); 4844 outs() << " (struct method_list_t *)\n"; 4845 if (cro.baseMethods + n_value != 0) 4846 print_method_list64_t(cro.baseMethods + n_value, info, ""); 4847 4848 outs() << " baseProtocols "; 4849 sym_name = 4850 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 4851 info, n_value, cro.baseProtocols); 4852 if (n_value != 0) { 4853 if (info->verbose && sym_name != nullptr) 4854 outs() << sym_name; 4855 else 4856 outs() << format("0x%" PRIx64, n_value); 4857 if (cro.baseProtocols != 0) 4858 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 4859 } else 4860 outs() << format("0x%" PRIx64, cro.baseProtocols); 4861 outs() << "\n"; 4862 if (cro.baseProtocols + n_value != 0) 4863 print_protocol_list64_t(cro.baseProtocols + n_value, info); 4864 4865 outs() << " ivars "; 4866 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 4867 info, n_value, cro.ivars); 4868 if (n_value != 0) { 4869 if (info->verbose && sym_name != nullptr) 4870 outs() << sym_name; 4871 else 4872 outs() << format("0x%" PRIx64, n_value); 4873 if (cro.ivars != 0) 4874 outs() << " + " << format("0x%" PRIx64, cro.ivars); 4875 } else 4876 outs() << format("0x%" PRIx64, cro.ivars); 4877 outs() << "\n"; 4878 if (cro.ivars + n_value != 0) 4879 print_ivar_list64_t(cro.ivars + n_value, info); 4880 4881 outs() << " weakIvarLayout "; 4882 sym_name = 4883 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 4884 info, n_value, cro.weakIvarLayout); 4885 if (n_value != 0) { 4886 if (info->verbose && sym_name != nullptr) 4887 outs() << sym_name; 4888 else 4889 outs() << format("0x%" PRIx64, n_value); 4890 if (cro.weakIvarLayout != 0) 4891 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 4892 } else 4893 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 4894 outs() << "\n"; 4895 print_layout_map64(cro.weakIvarLayout + n_value, info); 4896 4897 outs() << " baseProperties "; 4898 sym_name = 4899 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 4900 info, n_value, cro.baseProperties); 4901 if (n_value != 0) { 4902 if (info->verbose && sym_name != nullptr) 4903 outs() << sym_name; 4904 else 4905 outs() << format("0x%" PRIx64, n_value); 4906 if (cro.baseProperties != 0) 4907 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 4908 } else 4909 outs() << format("0x%" PRIx64, cro.baseProperties); 4910 outs() << "\n"; 4911 if (cro.baseProperties + n_value != 0) 4912 print_objc_property_list64(cro.baseProperties + n_value, info); 4913 4914 is_meta_class = (cro.flags & RO_META) != 0; 4915 return true; 4916 } 4917 4918 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 4919 bool &is_meta_class) { 4920 struct class_ro32_t cro; 4921 const char *r; 4922 uint32_t offset, xoffset, left; 4923 SectionRef S, xS; 4924 const char *name; 4925 4926 r = get_pointer_32(p, offset, left, S, info); 4927 if (r == nullptr) 4928 return false; 4929 memset(&cro, '\0', sizeof(struct class_ro32_t)); 4930 if (left < sizeof(struct class_ro32_t)) { 4931 memcpy(&cro, r, left); 4932 outs() << " (class_ro_t entends past the end of the section)\n"; 4933 } else 4934 memcpy(&cro, r, sizeof(struct class_ro32_t)); 4935 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4936 swapStruct(cro); 4937 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4938 if (cro.flags & RO_META) 4939 outs() << " RO_META"; 4940 if (cro.flags & RO_ROOT) 4941 outs() << " RO_ROOT"; 4942 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4943 outs() << " RO_HAS_CXX_STRUCTORS"; 4944 outs() << "\n"; 4945 outs() << " instanceStart " << cro.instanceStart << "\n"; 4946 outs() << " instanceSize " << cro.instanceSize << "\n"; 4947 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 4948 << "\n"; 4949 print_layout_map32(cro.ivarLayout, info); 4950 4951 outs() << " name " << format("0x%" PRIx32, cro.name); 4952 name = get_pointer_32(cro.name, xoffset, left, xS, info); 4953 if (name != nullptr) 4954 outs() << format(" %.*s", left, name); 4955 outs() << "\n"; 4956 4957 outs() << " baseMethods " 4958 << format("0x%" PRIx32, cro.baseMethods) 4959 << " (struct method_list_t *)\n"; 4960 if (cro.baseMethods != 0) 4961 print_method_list32_t(cro.baseMethods, info, ""); 4962 4963 outs() << " baseProtocols " 4964 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 4965 if (cro.baseProtocols != 0) 4966 print_protocol_list32_t(cro.baseProtocols, info); 4967 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 4968 << "\n"; 4969 if (cro.ivars != 0) 4970 print_ivar_list32_t(cro.ivars, info); 4971 outs() << " weakIvarLayout " 4972 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 4973 print_layout_map32(cro.weakIvarLayout, info); 4974 outs() << " baseProperties " 4975 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 4976 if (cro.baseProperties != 0) 4977 print_objc_property_list32(cro.baseProperties, info); 4978 is_meta_class = (cro.flags & RO_META) != 0; 4979 return true; 4980 } 4981 4982 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 4983 struct class64_t c; 4984 const char *r; 4985 uint32_t offset, left; 4986 SectionRef S; 4987 const char *name; 4988 uint64_t isa_n_value, n_value; 4989 4990 r = get_pointer_64(p, offset, left, S, info); 4991 if (r == nullptr || left < sizeof(struct class64_t)) 4992 return; 4993 memcpy(&c, r, sizeof(struct class64_t)); 4994 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4995 swapStruct(c); 4996 4997 outs() << " isa " << format("0x%" PRIx64, c.isa); 4998 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 4999 isa_n_value, c.isa); 5000 if (name != nullptr) 5001 outs() << " " << name; 5002 outs() << "\n"; 5003 5004 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 5005 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 5006 n_value, c.superclass); 5007 if (name != nullptr) 5008 outs() << " " << name; 5009 else { 5010 name = get_dyld_bind_info_symbolname(S.getAddress() + 5011 offset + offsetof(struct class64_t, superclass), info); 5012 if (name != nullptr) 5013 outs() << " " << name; 5014 } 5015 outs() << "\n"; 5016 5017 outs() << " cache " << format("0x%" PRIx64, c.cache); 5018 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 5019 n_value, c.cache); 5020 if (name != nullptr) 5021 outs() << " " << name; 5022 outs() << "\n"; 5023 5024 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 5025 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 5026 n_value, c.vtable); 5027 if (name != nullptr) 5028 outs() << " " << name; 5029 outs() << "\n"; 5030 5031 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 5032 n_value, c.data); 5033 outs() << " data "; 5034 if (n_value != 0) { 5035 if (info->verbose && name != nullptr) 5036 outs() << name; 5037 else 5038 outs() << format("0x%" PRIx64, n_value); 5039 if (c.data != 0) 5040 outs() << " + " << format("0x%" PRIx64, c.data); 5041 } else 5042 outs() << format("0x%" PRIx64, c.data); 5043 outs() << " (struct class_ro_t *)"; 5044 5045 // This is a Swift class if some of the low bits of the pointer are set. 5046 if ((c.data + n_value) & 0x7) 5047 outs() << " Swift class"; 5048 outs() << "\n"; 5049 bool is_meta_class; 5050 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5051 return; 5052 5053 if (!is_meta_class && 5054 c.isa + isa_n_value != p && 5055 c.isa + isa_n_value != 0 && 5056 info->depth < 100) { 5057 info->depth++; 5058 outs() << "Meta Class\n"; 5059 print_class64_t(c.isa + isa_n_value, info); 5060 } 5061 } 5062 5063 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5064 struct class32_t c; 5065 const char *r; 5066 uint32_t offset, left; 5067 SectionRef S; 5068 const char *name; 5069 5070 r = get_pointer_32(p, offset, left, S, info); 5071 if (r == nullptr) 5072 return; 5073 memset(&c, '\0', sizeof(struct class32_t)); 5074 if (left < sizeof(struct class32_t)) { 5075 memcpy(&c, r, left); 5076 outs() << " (class_t entends past the end of the section)\n"; 5077 } else 5078 memcpy(&c, r, sizeof(struct class32_t)); 5079 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5080 swapStruct(c); 5081 5082 outs() << " isa " << format("0x%" PRIx32, c.isa); 5083 name = 5084 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5085 if (name != nullptr) 5086 outs() << " " << name; 5087 outs() << "\n"; 5088 5089 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5090 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5091 c.superclass); 5092 if (name != nullptr) 5093 outs() << " " << name; 5094 outs() << "\n"; 5095 5096 outs() << " cache " << format("0x%" PRIx32, c.cache); 5097 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5098 c.cache); 5099 if (name != nullptr) 5100 outs() << " " << name; 5101 outs() << "\n"; 5102 5103 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5104 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5105 c.vtable); 5106 if (name != nullptr) 5107 outs() << " " << name; 5108 outs() << "\n"; 5109 5110 name = 5111 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5112 outs() << " data " << format("0x%" PRIx32, c.data) 5113 << " (struct class_ro_t *)"; 5114 5115 // This is a Swift class if some of the low bits of the pointer are set. 5116 if (c.data & 0x3) 5117 outs() << " Swift class"; 5118 outs() << "\n"; 5119 bool is_meta_class; 5120 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5121 return; 5122 5123 if (!is_meta_class) { 5124 outs() << "Meta Class\n"; 5125 print_class32_t(c.isa, info); 5126 } 5127 } 5128 5129 static void print_objc_class_t(struct objc_class_t *objc_class, 5130 struct DisassembleInfo *info) { 5131 uint32_t offset, left, xleft; 5132 const char *name, *p, *ivar_list; 5133 SectionRef S; 5134 int32_t i; 5135 struct objc_ivar_list_t objc_ivar_list; 5136 struct objc_ivar_t ivar; 5137 5138 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5139 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5140 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5141 if (name != nullptr) 5142 outs() << format(" %.*s", left, name); 5143 else 5144 outs() << " (not in an __OBJC section)"; 5145 } 5146 outs() << "\n"; 5147 5148 outs() << "\t super_class " 5149 << format("0x%08" PRIx32, objc_class->super_class); 5150 if (info->verbose) { 5151 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5152 if (name != nullptr) 5153 outs() << format(" %.*s", left, name); 5154 else 5155 outs() << " (not in an __OBJC section)"; 5156 } 5157 outs() << "\n"; 5158 5159 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5160 if (info->verbose) { 5161 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5162 if (name != nullptr) 5163 outs() << format(" %.*s", left, name); 5164 else 5165 outs() << " (not in an __OBJC section)"; 5166 } 5167 outs() << "\n"; 5168 5169 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5170 << "\n"; 5171 5172 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5173 if (info->verbose) { 5174 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5175 outs() << " CLS_CLASS"; 5176 else if (CLS_GETINFO(objc_class, CLS_META)) 5177 outs() << " CLS_META"; 5178 } 5179 outs() << "\n"; 5180 5181 outs() << "\t instance_size " 5182 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5183 5184 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5185 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5186 if (p != nullptr) { 5187 if (left > sizeof(struct objc_ivar_list_t)) { 5188 outs() << "\n"; 5189 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5190 } else { 5191 outs() << " (entends past the end of the section)\n"; 5192 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5193 memcpy(&objc_ivar_list, p, left); 5194 } 5195 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5196 swapStruct(objc_ivar_list); 5197 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5198 ivar_list = p + sizeof(struct objc_ivar_list_t); 5199 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5200 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5201 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5202 break; 5203 } 5204 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5205 sizeof(struct objc_ivar_t)); 5206 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5207 swapStruct(ivar); 5208 5209 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5210 if (info->verbose) { 5211 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5212 if (name != nullptr) 5213 outs() << format(" %.*s", xleft, name); 5214 else 5215 outs() << " (not in an __OBJC section)"; 5216 } 5217 outs() << "\n"; 5218 5219 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5220 if (info->verbose) { 5221 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5222 if (name != nullptr) 5223 outs() << format(" %.*s", xleft, name); 5224 else 5225 outs() << " (not in an __OBJC section)"; 5226 } 5227 outs() << "\n"; 5228 5229 outs() << "\t\t ivar_offset " 5230 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5231 } 5232 } else { 5233 outs() << " (not in an __OBJC section)\n"; 5234 } 5235 5236 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5237 if (print_method_list(objc_class->methodLists, info)) 5238 outs() << " (not in an __OBJC section)\n"; 5239 5240 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5241 << "\n"; 5242 5243 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5244 if (print_protocol_list(objc_class->protocols, 16, info)) 5245 outs() << " (not in an __OBJC section)\n"; 5246 } 5247 5248 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5249 struct DisassembleInfo *info) { 5250 uint32_t offset, left; 5251 const char *name; 5252 SectionRef S; 5253 5254 outs() << "\t category name " 5255 << format("0x%08" PRIx32, objc_category->category_name); 5256 if (info->verbose) { 5257 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5258 true); 5259 if (name != nullptr) 5260 outs() << format(" %.*s", left, name); 5261 else 5262 outs() << " (not in an __OBJC section)"; 5263 } 5264 outs() << "\n"; 5265 5266 outs() << "\t\t class name " 5267 << format("0x%08" PRIx32, objc_category->class_name); 5268 if (info->verbose) { 5269 name = 5270 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5271 if (name != nullptr) 5272 outs() << format(" %.*s", left, name); 5273 else 5274 outs() << " (not in an __OBJC section)"; 5275 } 5276 outs() << "\n"; 5277 5278 outs() << "\t instance methods " 5279 << format("0x%08" PRIx32, objc_category->instance_methods); 5280 if (print_method_list(objc_category->instance_methods, info)) 5281 outs() << " (not in an __OBJC section)\n"; 5282 5283 outs() << "\t class methods " 5284 << format("0x%08" PRIx32, objc_category->class_methods); 5285 if (print_method_list(objc_category->class_methods, info)) 5286 outs() << " (not in an __OBJC section)\n"; 5287 } 5288 5289 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5290 struct category64_t c; 5291 const char *r; 5292 uint32_t offset, xoffset, left; 5293 SectionRef S, xS; 5294 const char *name, *sym_name; 5295 uint64_t n_value; 5296 5297 r = get_pointer_64(p, offset, left, S, info); 5298 if (r == nullptr) 5299 return; 5300 memset(&c, '\0', sizeof(struct category64_t)); 5301 if (left < sizeof(struct category64_t)) { 5302 memcpy(&c, r, left); 5303 outs() << " (category_t entends past the end of the section)\n"; 5304 } else 5305 memcpy(&c, r, sizeof(struct category64_t)); 5306 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5307 swapStruct(c); 5308 5309 outs() << " name "; 5310 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 5311 info, n_value, c.name); 5312 if (n_value != 0) { 5313 if (info->verbose && sym_name != nullptr) 5314 outs() << sym_name; 5315 else 5316 outs() << format("0x%" PRIx64, n_value); 5317 if (c.name != 0) 5318 outs() << " + " << format("0x%" PRIx64, c.name); 5319 } else 5320 outs() << format("0x%" PRIx64, c.name); 5321 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 5322 if (name != nullptr) 5323 outs() << format(" %.*s", left, name); 5324 outs() << "\n"; 5325 5326 outs() << " cls "; 5327 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 5328 n_value, c.cls); 5329 if (n_value != 0) { 5330 if (info->verbose && sym_name != nullptr) 5331 outs() << sym_name; 5332 else 5333 outs() << format("0x%" PRIx64, n_value); 5334 if (c.cls != 0) 5335 outs() << " + " << format("0x%" PRIx64, c.cls); 5336 } else 5337 outs() << format("0x%" PRIx64, c.cls); 5338 outs() << "\n"; 5339 if (c.cls + n_value != 0) 5340 print_class64_t(c.cls + n_value, info); 5341 5342 outs() << " instanceMethods "; 5343 sym_name = 5344 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 5345 info, n_value, c.instanceMethods); 5346 if (n_value != 0) { 5347 if (info->verbose && sym_name != nullptr) 5348 outs() << sym_name; 5349 else 5350 outs() << format("0x%" PRIx64, n_value); 5351 if (c.instanceMethods != 0) 5352 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 5353 } else 5354 outs() << format("0x%" PRIx64, c.instanceMethods); 5355 outs() << "\n"; 5356 if (c.instanceMethods + n_value != 0) 5357 print_method_list64_t(c.instanceMethods + n_value, info, ""); 5358 5359 outs() << " classMethods "; 5360 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 5361 S, info, n_value, c.classMethods); 5362 if (n_value != 0) { 5363 if (info->verbose && sym_name != nullptr) 5364 outs() << sym_name; 5365 else 5366 outs() << format("0x%" PRIx64, n_value); 5367 if (c.classMethods != 0) 5368 outs() << " + " << format("0x%" PRIx64, c.classMethods); 5369 } else 5370 outs() << format("0x%" PRIx64, c.classMethods); 5371 outs() << "\n"; 5372 if (c.classMethods + n_value != 0) 5373 print_method_list64_t(c.classMethods + n_value, info, ""); 5374 5375 outs() << " protocols "; 5376 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 5377 info, n_value, c.protocols); 5378 if (n_value != 0) { 5379 if (info->verbose && sym_name != nullptr) 5380 outs() << sym_name; 5381 else 5382 outs() << format("0x%" PRIx64, n_value); 5383 if (c.protocols != 0) 5384 outs() << " + " << format("0x%" PRIx64, c.protocols); 5385 } else 5386 outs() << format("0x%" PRIx64, c.protocols); 5387 outs() << "\n"; 5388 if (c.protocols + n_value != 0) 5389 print_protocol_list64_t(c.protocols + n_value, info); 5390 5391 outs() << "instanceProperties "; 5392 sym_name = 5393 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 5394 S, info, n_value, c.instanceProperties); 5395 if (n_value != 0) { 5396 if (info->verbose && sym_name != nullptr) 5397 outs() << sym_name; 5398 else 5399 outs() << format("0x%" PRIx64, n_value); 5400 if (c.instanceProperties != 0) 5401 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 5402 } else 5403 outs() << format("0x%" PRIx64, c.instanceProperties); 5404 outs() << "\n"; 5405 if (c.instanceProperties + n_value != 0) 5406 print_objc_property_list64(c.instanceProperties + n_value, info); 5407 } 5408 5409 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 5410 struct category32_t c; 5411 const char *r; 5412 uint32_t offset, left; 5413 SectionRef S, xS; 5414 const char *name; 5415 5416 r = get_pointer_32(p, offset, left, S, info); 5417 if (r == nullptr) 5418 return; 5419 memset(&c, '\0', sizeof(struct category32_t)); 5420 if (left < sizeof(struct category32_t)) { 5421 memcpy(&c, r, left); 5422 outs() << " (category_t entends past the end of the section)\n"; 5423 } else 5424 memcpy(&c, r, sizeof(struct category32_t)); 5425 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5426 swapStruct(c); 5427 5428 outs() << " name " << format("0x%" PRIx32, c.name); 5429 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 5430 c.name); 5431 if (name) 5432 outs() << " " << name; 5433 outs() << "\n"; 5434 5435 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 5436 if (c.cls != 0) 5437 print_class32_t(c.cls, info); 5438 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 5439 << "\n"; 5440 if (c.instanceMethods != 0) 5441 print_method_list32_t(c.instanceMethods, info, ""); 5442 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 5443 << "\n"; 5444 if (c.classMethods != 0) 5445 print_method_list32_t(c.classMethods, info, ""); 5446 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 5447 if (c.protocols != 0) 5448 print_protocol_list32_t(c.protocols, info); 5449 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 5450 << "\n"; 5451 if (c.instanceProperties != 0) 5452 print_objc_property_list32(c.instanceProperties, info); 5453 } 5454 5455 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 5456 uint32_t i, left, offset, xoffset; 5457 uint64_t p, n_value; 5458 struct message_ref64 mr; 5459 const char *name, *sym_name; 5460 const char *r; 5461 SectionRef xS; 5462 5463 if (S == SectionRef()) 5464 return; 5465 5466 StringRef SectName; 5467 S.getName(SectName); 5468 DataRefImpl Ref = S.getRawDataRefImpl(); 5469 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5470 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5471 offset = 0; 5472 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5473 p = S.getAddress() + i; 5474 r = get_pointer_64(p, offset, left, S, info); 5475 if (r == nullptr) 5476 return; 5477 memset(&mr, '\0', sizeof(struct message_ref64)); 5478 if (left < sizeof(struct message_ref64)) { 5479 memcpy(&mr, r, left); 5480 outs() << " (message_ref entends past the end of the section)\n"; 5481 } else 5482 memcpy(&mr, r, sizeof(struct message_ref64)); 5483 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5484 swapStruct(mr); 5485 5486 outs() << " imp "; 5487 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 5488 n_value, mr.imp); 5489 if (n_value != 0) { 5490 outs() << format("0x%" PRIx64, n_value) << " "; 5491 if (mr.imp != 0) 5492 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 5493 } else 5494 outs() << format("0x%" PRIx64, mr.imp) << " "; 5495 if (name != nullptr) 5496 outs() << " " << name; 5497 outs() << "\n"; 5498 5499 outs() << " sel "; 5500 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 5501 info, n_value, mr.sel); 5502 if (n_value != 0) { 5503 if (info->verbose && sym_name != nullptr) 5504 outs() << sym_name; 5505 else 5506 outs() << format("0x%" PRIx64, n_value); 5507 if (mr.sel != 0) 5508 outs() << " + " << format("0x%" PRIx64, mr.sel); 5509 } else 5510 outs() << format("0x%" PRIx64, mr.sel); 5511 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 5512 if (name != nullptr) 5513 outs() << format(" %.*s", left, name); 5514 outs() << "\n"; 5515 5516 offset += sizeof(struct message_ref64); 5517 } 5518 } 5519 5520 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 5521 uint32_t i, left, offset, xoffset, p; 5522 struct message_ref32 mr; 5523 const char *name, *r; 5524 SectionRef xS; 5525 5526 if (S == SectionRef()) 5527 return; 5528 5529 StringRef SectName; 5530 S.getName(SectName); 5531 DataRefImpl Ref = S.getRawDataRefImpl(); 5532 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5533 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5534 offset = 0; 5535 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5536 p = S.getAddress() + i; 5537 r = get_pointer_32(p, offset, left, S, info); 5538 if (r == nullptr) 5539 return; 5540 memset(&mr, '\0', sizeof(struct message_ref32)); 5541 if (left < sizeof(struct message_ref32)) { 5542 memcpy(&mr, r, left); 5543 outs() << " (message_ref entends past the end of the section)\n"; 5544 } else 5545 memcpy(&mr, r, sizeof(struct message_ref32)); 5546 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5547 swapStruct(mr); 5548 5549 outs() << " imp " << format("0x%" PRIx32, mr.imp); 5550 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 5551 mr.imp); 5552 if (name != nullptr) 5553 outs() << " " << name; 5554 outs() << "\n"; 5555 5556 outs() << " sel " << format("0x%" PRIx32, mr.sel); 5557 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 5558 if (name != nullptr) 5559 outs() << " " << name; 5560 outs() << "\n"; 5561 5562 offset += sizeof(struct message_ref32); 5563 } 5564 } 5565 5566 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 5567 uint32_t left, offset, swift_version; 5568 uint64_t p; 5569 struct objc_image_info64 o; 5570 const char *r; 5571 5572 if (S == SectionRef()) 5573 return; 5574 5575 StringRef SectName; 5576 S.getName(SectName); 5577 DataRefImpl Ref = S.getRawDataRefImpl(); 5578 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5579 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5580 p = S.getAddress(); 5581 r = get_pointer_64(p, offset, left, S, info); 5582 if (r == nullptr) 5583 return; 5584 memset(&o, '\0', sizeof(struct objc_image_info64)); 5585 if (left < sizeof(struct objc_image_info64)) { 5586 memcpy(&o, r, left); 5587 outs() << " (objc_image_info entends past the end of the section)\n"; 5588 } else 5589 memcpy(&o, r, sizeof(struct objc_image_info64)); 5590 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5591 swapStruct(o); 5592 outs() << " version " << o.version << "\n"; 5593 outs() << " flags " << format("0x%" PRIx32, o.flags); 5594 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5595 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5596 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5597 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5598 swift_version = (o.flags >> 8) & 0xff; 5599 if (swift_version != 0) { 5600 if (swift_version == 1) 5601 outs() << " Swift 1.0"; 5602 else if (swift_version == 2) 5603 outs() << " Swift 1.1"; 5604 else if(swift_version == 3) 5605 outs() << " Swift 2.0"; 5606 else if(swift_version == 4) 5607 outs() << " Swift 3.0"; 5608 else if(swift_version == 5) 5609 outs() << " Swift 4.0"; 5610 else if(swift_version == 6) 5611 outs() << " Swift 4.1"; 5612 else 5613 outs() << " unknown future Swift version (" << swift_version << ")"; 5614 } 5615 outs() << "\n"; 5616 } 5617 5618 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 5619 uint32_t left, offset, swift_version, p; 5620 struct objc_image_info32 o; 5621 const char *r; 5622 5623 if (S == SectionRef()) 5624 return; 5625 5626 StringRef SectName; 5627 S.getName(SectName); 5628 DataRefImpl Ref = S.getRawDataRefImpl(); 5629 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5630 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5631 p = S.getAddress(); 5632 r = get_pointer_32(p, offset, left, S, info); 5633 if (r == nullptr) 5634 return; 5635 memset(&o, '\0', sizeof(struct objc_image_info32)); 5636 if (left < sizeof(struct objc_image_info32)) { 5637 memcpy(&o, r, left); 5638 outs() << " (objc_image_info entends past the end of the section)\n"; 5639 } else 5640 memcpy(&o, r, sizeof(struct objc_image_info32)); 5641 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5642 swapStruct(o); 5643 outs() << " version " << o.version << "\n"; 5644 outs() << " flags " << format("0x%" PRIx32, o.flags); 5645 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5646 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5647 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5648 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5649 swift_version = (o.flags >> 8) & 0xff; 5650 if (swift_version != 0) { 5651 if (swift_version == 1) 5652 outs() << " Swift 1.0"; 5653 else if (swift_version == 2) 5654 outs() << " Swift 1.1"; 5655 else if(swift_version == 3) 5656 outs() << " Swift 2.0"; 5657 else if(swift_version == 4) 5658 outs() << " Swift 3.0"; 5659 else if(swift_version == 5) 5660 outs() << " Swift 4.0"; 5661 else if(swift_version == 6) 5662 outs() << " Swift 4.1"; 5663 else 5664 outs() << " unknown future Swift version (" << swift_version << ")"; 5665 } 5666 outs() << "\n"; 5667 } 5668 5669 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 5670 uint32_t left, offset, p; 5671 struct imageInfo_t o; 5672 const char *r; 5673 5674 StringRef SectName; 5675 S.getName(SectName); 5676 DataRefImpl Ref = S.getRawDataRefImpl(); 5677 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5678 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5679 p = S.getAddress(); 5680 r = get_pointer_32(p, offset, left, S, info); 5681 if (r == nullptr) 5682 return; 5683 memset(&o, '\0', sizeof(struct imageInfo_t)); 5684 if (left < sizeof(struct imageInfo_t)) { 5685 memcpy(&o, r, left); 5686 outs() << " (imageInfo entends past the end of the section)\n"; 5687 } else 5688 memcpy(&o, r, sizeof(struct imageInfo_t)); 5689 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5690 swapStruct(o); 5691 outs() << " version " << o.version << "\n"; 5692 outs() << " flags " << format("0x%" PRIx32, o.flags); 5693 if (o.flags & 0x1) 5694 outs() << " F&C"; 5695 if (o.flags & 0x2) 5696 outs() << " GC"; 5697 if (o.flags & 0x4) 5698 outs() << " GC-only"; 5699 else 5700 outs() << " RR"; 5701 outs() << "\n"; 5702 } 5703 5704 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 5705 SymbolAddressMap AddrMap; 5706 if (verbose) 5707 CreateSymbolAddressMap(O, &AddrMap); 5708 5709 std::vector<SectionRef> Sections; 5710 for (const SectionRef &Section : O->sections()) { 5711 StringRef SectName; 5712 Section.getName(SectName); 5713 Sections.push_back(Section); 5714 } 5715 5716 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 5717 5718 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5719 if (CL == SectionRef()) 5720 CL = get_section(O, "__DATA", "__objc_classlist"); 5721 if (CL == SectionRef()) 5722 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5723 if (CL == SectionRef()) 5724 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5725 info.S = CL; 5726 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 5727 5728 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5729 if (CR == SectionRef()) 5730 CR = get_section(O, "__DATA", "__objc_classrefs"); 5731 if (CR == SectionRef()) 5732 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5733 if (CR == SectionRef()) 5734 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5735 info.S = CR; 5736 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 5737 5738 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5739 if (SR == SectionRef()) 5740 SR = get_section(O, "__DATA", "__objc_superrefs"); 5741 if (SR == SectionRef()) 5742 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5743 if (SR == SectionRef()) 5744 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5745 info.S = SR; 5746 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 5747 5748 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5749 if (CA == SectionRef()) 5750 CA = get_section(O, "__DATA", "__objc_catlist"); 5751 if (CA == SectionRef()) 5752 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5753 if (CA == SectionRef()) 5754 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5755 info.S = CA; 5756 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 5757 5758 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5759 if (PL == SectionRef()) 5760 PL = get_section(O, "__DATA", "__objc_protolist"); 5761 if (PL == SectionRef()) 5762 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5763 if (PL == SectionRef()) 5764 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5765 info.S = PL; 5766 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 5767 5768 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5769 if (MR == SectionRef()) 5770 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5771 if (MR == SectionRef()) 5772 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5773 if (MR == SectionRef()) 5774 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5775 info.S = MR; 5776 print_message_refs64(MR, &info); 5777 5778 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5779 if (II == SectionRef()) 5780 II = get_section(O, "__DATA", "__objc_imageinfo"); 5781 if (II == SectionRef()) 5782 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5783 if (II == SectionRef()) 5784 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5785 info.S = II; 5786 print_image_info64(II, &info); 5787 } 5788 5789 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5790 SymbolAddressMap AddrMap; 5791 if (verbose) 5792 CreateSymbolAddressMap(O, &AddrMap); 5793 5794 std::vector<SectionRef> Sections; 5795 for (const SectionRef &Section : O->sections()) { 5796 StringRef SectName; 5797 Section.getName(SectName); 5798 Sections.push_back(Section); 5799 } 5800 5801 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 5802 5803 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5804 if (CL == SectionRef()) 5805 CL = get_section(O, "__DATA", "__objc_classlist"); 5806 if (CL == SectionRef()) 5807 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5808 if (CL == SectionRef()) 5809 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5810 info.S = CL; 5811 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 5812 5813 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5814 if (CR == SectionRef()) 5815 CR = get_section(O, "__DATA", "__objc_classrefs"); 5816 if (CR == SectionRef()) 5817 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5818 if (CR == SectionRef()) 5819 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5820 info.S = CR; 5821 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 5822 5823 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5824 if (SR == SectionRef()) 5825 SR = get_section(O, "__DATA", "__objc_superrefs"); 5826 if (SR == SectionRef()) 5827 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5828 if (SR == SectionRef()) 5829 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5830 info.S = SR; 5831 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 5832 5833 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5834 if (CA == SectionRef()) 5835 CA = get_section(O, "__DATA", "__objc_catlist"); 5836 if (CA == SectionRef()) 5837 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5838 if (CA == SectionRef()) 5839 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5840 info.S = CA; 5841 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 5842 5843 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5844 if (PL == SectionRef()) 5845 PL = get_section(O, "__DATA", "__objc_protolist"); 5846 if (PL == SectionRef()) 5847 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5848 if (PL == SectionRef()) 5849 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5850 info.S = PL; 5851 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 5852 5853 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5854 if (MR == SectionRef()) 5855 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5856 if (MR == SectionRef()) 5857 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5858 if (MR == SectionRef()) 5859 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5860 info.S = MR; 5861 print_message_refs32(MR, &info); 5862 5863 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5864 if (II == SectionRef()) 5865 II = get_section(O, "__DATA", "__objc_imageinfo"); 5866 if (II == SectionRef()) 5867 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5868 if (II == SectionRef()) 5869 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5870 info.S = II; 5871 print_image_info32(II, &info); 5872 } 5873 5874 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5875 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 5876 const char *r, *name, *defs; 5877 struct objc_module_t module; 5878 SectionRef S, xS; 5879 struct objc_symtab_t symtab; 5880 struct objc_class_t objc_class; 5881 struct objc_category_t objc_category; 5882 5883 outs() << "Objective-C segment\n"; 5884 S = get_section(O, "__OBJC", "__module_info"); 5885 if (S == SectionRef()) 5886 return false; 5887 5888 SymbolAddressMap AddrMap; 5889 if (verbose) 5890 CreateSymbolAddressMap(O, &AddrMap); 5891 5892 std::vector<SectionRef> Sections; 5893 for (const SectionRef &Section : O->sections()) { 5894 StringRef SectName; 5895 Section.getName(SectName); 5896 Sections.push_back(Section); 5897 } 5898 5899 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 5900 5901 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 5902 p = S.getAddress() + i; 5903 r = get_pointer_32(p, offset, left, S, &info, true); 5904 if (r == nullptr) 5905 return true; 5906 memset(&module, '\0', sizeof(struct objc_module_t)); 5907 if (left < sizeof(struct objc_module_t)) { 5908 memcpy(&module, r, left); 5909 outs() << " (module extends past end of __module_info section)\n"; 5910 } else 5911 memcpy(&module, r, sizeof(struct objc_module_t)); 5912 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5913 swapStruct(module); 5914 5915 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 5916 outs() << " version " << module.version << "\n"; 5917 outs() << " size " << module.size << "\n"; 5918 outs() << " name "; 5919 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 5920 if (name != nullptr) 5921 outs() << format("%.*s", left, name); 5922 else 5923 outs() << format("0x%08" PRIx32, module.name) 5924 << "(not in an __OBJC section)"; 5925 outs() << "\n"; 5926 5927 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 5928 if (module.symtab == 0 || r == nullptr) { 5929 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 5930 << " (not in an __OBJC section)\n"; 5931 continue; 5932 } 5933 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 5934 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 5935 defs_left = 0; 5936 defs = nullptr; 5937 if (left < sizeof(struct objc_symtab_t)) { 5938 memcpy(&symtab, r, left); 5939 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 5940 } else { 5941 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 5942 if (left > sizeof(struct objc_symtab_t)) { 5943 defs_left = left - sizeof(struct objc_symtab_t); 5944 defs = r + sizeof(struct objc_symtab_t); 5945 } 5946 } 5947 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5948 swapStruct(symtab); 5949 5950 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 5951 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 5952 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 5953 if (r == nullptr) 5954 outs() << " (not in an __OBJC section)"; 5955 outs() << "\n"; 5956 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 5957 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 5958 if (symtab.cls_def_cnt > 0) 5959 outs() << "\tClass Definitions\n"; 5960 for (j = 0; j < symtab.cls_def_cnt; j++) { 5961 if ((j + 1) * sizeof(uint32_t) > defs_left) { 5962 outs() << "\t(remaining class defs entries entends past the end of the " 5963 << "section)\n"; 5964 break; 5965 } 5966 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 5967 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5968 sys::swapByteOrder(def); 5969 5970 r = get_pointer_32(def, xoffset, left, xS, &info, true); 5971 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 5972 if (r != nullptr) { 5973 if (left > sizeof(struct objc_class_t)) { 5974 outs() << "\n"; 5975 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 5976 } else { 5977 outs() << " (entends past the end of the section)\n"; 5978 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 5979 memcpy(&objc_class, r, left); 5980 } 5981 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5982 swapStruct(objc_class); 5983 print_objc_class_t(&objc_class, &info); 5984 } else { 5985 outs() << "(not in an __OBJC section)\n"; 5986 } 5987 5988 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 5989 outs() << "\tMeta Class"; 5990 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 5991 if (r != nullptr) { 5992 if (left > sizeof(struct objc_class_t)) { 5993 outs() << "\n"; 5994 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 5995 } else { 5996 outs() << " (entends past the end of the section)\n"; 5997 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 5998 memcpy(&objc_class, r, left); 5999 } 6000 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6001 swapStruct(objc_class); 6002 print_objc_class_t(&objc_class, &info); 6003 } else { 6004 outs() << "(not in an __OBJC section)\n"; 6005 } 6006 } 6007 } 6008 if (symtab.cat_def_cnt > 0) 6009 outs() << "\tCategory Definitions\n"; 6010 for (j = 0; j < symtab.cat_def_cnt; j++) { 6011 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 6012 outs() << "\t(remaining category defs entries entends past the end of " 6013 << "the section)\n"; 6014 break; 6015 } 6016 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6017 sizeof(uint32_t)); 6018 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6019 sys::swapByteOrder(def); 6020 6021 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6022 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6023 << format("0x%08" PRIx32, def); 6024 if (r != nullptr) { 6025 if (left > sizeof(struct objc_category_t)) { 6026 outs() << "\n"; 6027 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6028 } else { 6029 outs() << " (entends past the end of the section)\n"; 6030 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6031 memcpy(&objc_category, r, left); 6032 } 6033 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6034 swapStruct(objc_category); 6035 print_objc_objc_category_t(&objc_category, &info); 6036 } else { 6037 outs() << "(not in an __OBJC section)\n"; 6038 } 6039 } 6040 } 6041 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6042 if (II != SectionRef()) 6043 print_image_info(II, &info); 6044 6045 return true; 6046 } 6047 6048 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6049 uint32_t size, uint32_t addr) { 6050 SymbolAddressMap AddrMap; 6051 CreateSymbolAddressMap(O, &AddrMap); 6052 6053 std::vector<SectionRef> Sections; 6054 for (const SectionRef &Section : O->sections()) { 6055 StringRef SectName; 6056 Section.getName(SectName); 6057 Sections.push_back(Section); 6058 } 6059 6060 struct DisassembleInfo info(O, &AddrMap, &Sections, true); 6061 6062 const char *p; 6063 struct objc_protocol_t protocol; 6064 uint32_t left, paddr; 6065 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6066 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6067 left = size - (p - sect); 6068 if (left < sizeof(struct objc_protocol_t)) { 6069 outs() << "Protocol extends past end of __protocol section\n"; 6070 memcpy(&protocol, p, left); 6071 } else 6072 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6073 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6074 swapStruct(protocol); 6075 paddr = addr + (p - sect); 6076 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6077 if (print_protocol(paddr, 0, &info)) 6078 outs() << "(not in an __OBJC section)\n"; 6079 } 6080 } 6081 6082 #ifdef HAVE_LIBXAR 6083 inline void swapStruct(struct xar_header &xar) { 6084 sys::swapByteOrder(xar.magic); 6085 sys::swapByteOrder(xar.size); 6086 sys::swapByteOrder(xar.version); 6087 sys::swapByteOrder(xar.toc_length_compressed); 6088 sys::swapByteOrder(xar.toc_length_uncompressed); 6089 sys::swapByteOrder(xar.cksum_alg); 6090 } 6091 6092 static void PrintModeVerbose(uint32_t mode) { 6093 switch(mode & S_IFMT){ 6094 case S_IFDIR: 6095 outs() << "d"; 6096 break; 6097 case S_IFCHR: 6098 outs() << "c"; 6099 break; 6100 case S_IFBLK: 6101 outs() << "b"; 6102 break; 6103 case S_IFREG: 6104 outs() << "-"; 6105 break; 6106 case S_IFLNK: 6107 outs() << "l"; 6108 break; 6109 case S_IFSOCK: 6110 outs() << "s"; 6111 break; 6112 default: 6113 outs() << "?"; 6114 break; 6115 } 6116 6117 /* owner permissions */ 6118 if(mode & S_IREAD) 6119 outs() << "r"; 6120 else 6121 outs() << "-"; 6122 if(mode & S_IWRITE) 6123 outs() << "w"; 6124 else 6125 outs() << "-"; 6126 if(mode & S_ISUID) 6127 outs() << "s"; 6128 else if(mode & S_IEXEC) 6129 outs() << "x"; 6130 else 6131 outs() << "-"; 6132 6133 /* group permissions */ 6134 if(mode & (S_IREAD >> 3)) 6135 outs() << "r"; 6136 else 6137 outs() << "-"; 6138 if(mode & (S_IWRITE >> 3)) 6139 outs() << "w"; 6140 else 6141 outs() << "-"; 6142 if(mode & S_ISGID) 6143 outs() << "s"; 6144 else if(mode & (S_IEXEC >> 3)) 6145 outs() << "x"; 6146 else 6147 outs() << "-"; 6148 6149 /* other permissions */ 6150 if(mode & (S_IREAD >> 6)) 6151 outs() << "r"; 6152 else 6153 outs() << "-"; 6154 if(mode & (S_IWRITE >> 6)) 6155 outs() << "w"; 6156 else 6157 outs() << "-"; 6158 if(mode & S_ISVTX) 6159 outs() << "t"; 6160 else if(mode & (S_IEXEC >> 6)) 6161 outs() << "x"; 6162 else 6163 outs() << "-"; 6164 } 6165 6166 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { 6167 xar_file_t xf; 6168 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; 6169 char *endp; 6170 uint32_t mode_value; 6171 6172 ScopedXarIter xi; 6173 if (!xi) { 6174 errs() << "Can't obtain an xar iterator for xar archive " 6175 << XarFilename << "\n"; 6176 return; 6177 } 6178 6179 // Go through the xar's files. 6180 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { 6181 ScopedXarIter xp; 6182 if(!xp){ 6183 errs() << "Can't obtain an xar iterator for xar archive " 6184 << XarFilename << "\n"; 6185 return; 6186 } 6187 type = nullptr; 6188 mode = nullptr; 6189 user = nullptr; 6190 group = nullptr; 6191 size = nullptr; 6192 mtime = nullptr; 6193 name = nullptr; 6194 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6195 const char *val = nullptr; 6196 xar_prop_get(xf, key, &val); 6197 #if 0 // Useful for debugging. 6198 outs() << "key: " << key << " value: " << val << "\n"; 6199 #endif 6200 if(strcmp(key, "type") == 0) 6201 type = val; 6202 if(strcmp(key, "mode") == 0) 6203 mode = val; 6204 if(strcmp(key, "user") == 0) 6205 user = val; 6206 if(strcmp(key, "group") == 0) 6207 group = val; 6208 if(strcmp(key, "data/size") == 0) 6209 size = val; 6210 if(strcmp(key, "mtime") == 0) 6211 mtime = val; 6212 if(strcmp(key, "name") == 0) 6213 name = val; 6214 } 6215 if(mode != nullptr){ 6216 mode_value = strtoul(mode, &endp, 8); 6217 if(*endp != '\0') 6218 outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; 6219 if(strcmp(type, "file") == 0) 6220 mode_value |= S_IFREG; 6221 PrintModeVerbose(mode_value); 6222 outs() << " "; 6223 } 6224 if(user != nullptr) 6225 outs() << format("%10s/", user); 6226 if(group != nullptr) 6227 outs() << format("%-10s ", group); 6228 if(size != nullptr) 6229 outs() << format("%7s ", size); 6230 if(mtime != nullptr){ 6231 for(m = mtime; *m != 'T' && *m != '\0'; m++) 6232 outs() << *m; 6233 if(*m == 'T') 6234 m++; 6235 outs() << " "; 6236 for( ; *m != 'Z' && *m != '\0'; m++) 6237 outs() << *m; 6238 outs() << " "; 6239 } 6240 if(name != nullptr) 6241 outs() << name; 6242 outs() << "\n"; 6243 } 6244 } 6245 6246 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 6247 uint32_t size, bool verbose, 6248 bool PrintXarHeader, bool PrintXarFileHeaders, 6249 std::string XarMemberName) { 6250 if(size < sizeof(struct xar_header)) { 6251 outs() << "size of (__LLVM,__bundle) section too small (smaller than size " 6252 "of struct xar_header)\n"; 6253 return; 6254 } 6255 struct xar_header XarHeader; 6256 memcpy(&XarHeader, sect, sizeof(struct xar_header)); 6257 if (sys::IsLittleEndianHost) 6258 swapStruct(XarHeader); 6259 if (PrintXarHeader) { 6260 if (!XarMemberName.empty()) 6261 outs() << "In xar member " << XarMemberName << ": "; 6262 else 6263 outs() << "For (__LLVM,__bundle) section: "; 6264 outs() << "xar header\n"; 6265 if (XarHeader.magic == XAR_HEADER_MAGIC) 6266 outs() << " magic XAR_HEADER_MAGIC\n"; 6267 else 6268 outs() << " magic " 6269 << format_hex(XarHeader.magic, 10, true) 6270 << " (not XAR_HEADER_MAGIC)\n"; 6271 outs() << " size " << XarHeader.size << "\n"; 6272 outs() << " version " << XarHeader.version << "\n"; 6273 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed 6274 << "\n"; 6275 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed 6276 << "\n"; 6277 outs() << " cksum_alg "; 6278 switch (XarHeader.cksum_alg) { 6279 case XAR_CKSUM_NONE: 6280 outs() << "XAR_CKSUM_NONE\n"; 6281 break; 6282 case XAR_CKSUM_SHA1: 6283 outs() << "XAR_CKSUM_SHA1\n"; 6284 break; 6285 case XAR_CKSUM_MD5: 6286 outs() << "XAR_CKSUM_MD5\n"; 6287 break; 6288 #ifdef XAR_CKSUM_SHA256 6289 case XAR_CKSUM_SHA256: 6290 outs() << "XAR_CKSUM_SHA256\n"; 6291 break; 6292 #endif 6293 #ifdef XAR_CKSUM_SHA512 6294 case XAR_CKSUM_SHA512: 6295 outs() << "XAR_CKSUM_SHA512\n"; 6296 break; 6297 #endif 6298 default: 6299 outs() << XarHeader.cksum_alg << "\n"; 6300 } 6301 } 6302 6303 SmallString<128> XarFilename; 6304 int FD; 6305 std::error_code XarEC = 6306 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); 6307 if (XarEC) { 6308 errs() << XarEC.message() << "\n"; 6309 return; 6310 } 6311 ToolOutputFile XarFile(XarFilename, FD); 6312 raw_fd_ostream &XarOut = XarFile.os(); 6313 StringRef XarContents(sect, size); 6314 XarOut << XarContents; 6315 XarOut.close(); 6316 if (XarOut.has_error()) 6317 return; 6318 6319 ScopedXarFile xar(XarFilename.c_str(), READ); 6320 if (!xar) { 6321 errs() << "Can't create temporary xar archive " << XarFilename << "\n"; 6322 return; 6323 } 6324 6325 SmallString<128> TocFilename; 6326 std::error_code TocEC = 6327 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); 6328 if (TocEC) { 6329 errs() << TocEC.message() << "\n"; 6330 return; 6331 } 6332 xar_serialize(xar, TocFilename.c_str()); 6333 6334 if (PrintXarFileHeaders) { 6335 if (!XarMemberName.empty()) 6336 outs() << "In xar member " << XarMemberName << ": "; 6337 else 6338 outs() << "For (__LLVM,__bundle) section: "; 6339 outs() << "xar archive files:\n"; 6340 PrintXarFilesSummary(XarFilename.c_str(), xar); 6341 } 6342 6343 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 6344 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); 6345 if (std::error_code EC = FileOrErr.getError()) { 6346 errs() << EC.message() << "\n"; 6347 return; 6348 } 6349 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 6350 6351 if (!XarMemberName.empty()) 6352 outs() << "In xar member " << XarMemberName << ": "; 6353 else 6354 outs() << "For (__LLVM,__bundle) section: "; 6355 outs() << "xar table of contents:\n"; 6356 outs() << Buffer->getBuffer() << "\n"; 6357 6358 // TODO: Go through the xar's files. 6359 ScopedXarIter xi; 6360 if(!xi){ 6361 errs() << "Can't obtain an xar iterator for xar archive " 6362 << XarFilename.c_str() << "\n"; 6363 return; 6364 } 6365 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ 6366 const char *key; 6367 const char *member_name, *member_type, *member_size_string; 6368 size_t member_size; 6369 6370 ScopedXarIter xp; 6371 if(!xp){ 6372 errs() << "Can't obtain an xar iterator for xar archive " 6373 << XarFilename.c_str() << "\n"; 6374 return; 6375 } 6376 member_name = NULL; 6377 member_type = NULL; 6378 member_size_string = NULL; 6379 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6380 const char *val = nullptr; 6381 xar_prop_get(xf, key, &val); 6382 #if 0 // Useful for debugging. 6383 outs() << "key: " << key << " value: " << val << "\n"; 6384 #endif 6385 if (strcmp(key, "name") == 0) 6386 member_name = val; 6387 if (strcmp(key, "type") == 0) 6388 member_type = val; 6389 if (strcmp(key, "data/size") == 0) 6390 member_size_string = val; 6391 } 6392 /* 6393 * If we find a file with a name, date/size and type properties 6394 * and with the type being "file" see if that is a xar file. 6395 */ 6396 if (member_name != NULL && member_type != NULL && 6397 strcmp(member_type, "file") == 0 && 6398 member_size_string != NULL){ 6399 // Extract the file into a buffer. 6400 char *endptr; 6401 member_size = strtoul(member_size_string, &endptr, 10); 6402 if (*endptr == '\0' && member_size != 0) { 6403 char *buffer; 6404 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { 6405 #if 0 // Useful for debugging. 6406 outs() << "xar member: " << member_name << " extracted\n"; 6407 #endif 6408 // Set the XarMemberName we want to see printed in the header. 6409 std::string OldXarMemberName; 6410 // If XarMemberName is already set this is nested. So 6411 // save the old name and create the nested name. 6412 if (!XarMemberName.empty()) { 6413 OldXarMemberName = XarMemberName; 6414 XarMemberName = 6415 (Twine("[") + XarMemberName + "]" + member_name).str(); 6416 } else { 6417 OldXarMemberName = ""; 6418 XarMemberName = member_name; 6419 } 6420 // See if this is could be a xar file (nested). 6421 if (member_size >= sizeof(struct xar_header)) { 6422 #if 0 // Useful for debugging. 6423 outs() << "could be a xar file: " << member_name << "\n"; 6424 #endif 6425 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); 6426 if (sys::IsLittleEndianHost) 6427 swapStruct(XarHeader); 6428 if (XarHeader.magic == XAR_HEADER_MAGIC) 6429 DumpBitcodeSection(O, buffer, member_size, verbose, 6430 PrintXarHeader, PrintXarFileHeaders, 6431 XarMemberName); 6432 } 6433 XarMemberName = OldXarMemberName; 6434 delete buffer; 6435 } 6436 } 6437 } 6438 } 6439 } 6440 #endif // defined(HAVE_LIBXAR) 6441 6442 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6443 if (O->is64Bit()) 6444 printObjc2_64bit_MetaData(O, verbose); 6445 else { 6446 MachO::mach_header H; 6447 H = O->getHeader(); 6448 if (H.cputype == MachO::CPU_TYPE_ARM) 6449 printObjc2_32bit_MetaData(O, verbose); 6450 else { 6451 // This is the 32-bit non-arm cputype case. Which is normally 6452 // the first Objective-C ABI. But it may be the case of a 6453 // binary for the iOS simulator which is the second Objective-C 6454 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6455 // and return false. 6456 if (!printObjc1_32bit_MetaData(O, verbose)) 6457 printObjc2_32bit_MetaData(O, verbose); 6458 } 6459 } 6460 } 6461 6462 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6463 // for the address passed in as ReferenceValue for printing as a comment with 6464 // the instruction and also returns the corresponding type of that item 6465 // indirectly through ReferenceType. 6466 // 6467 // If ReferenceValue is an address of literal cstring then a pointer to the 6468 // cstring is returned and ReferenceType is set to 6469 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6470 // 6471 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6472 // Class ref that name is returned and the ReferenceType is set accordingly. 6473 // 6474 // Lastly, literals which are Symbol address in a literal pool are looked for 6475 // and if found the symbol name is returned and ReferenceType is set to 6476 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6477 // 6478 // If there is no item in the Mach-O file for the address passed in as 6479 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6480 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6481 uint64_t ReferencePC, 6482 uint64_t *ReferenceType, 6483 struct DisassembleInfo *info) { 6484 // First see if there is an external relocation entry at the ReferencePC. 6485 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6486 uint64_t sect_addr = info->S.getAddress(); 6487 uint64_t sect_offset = ReferencePC - sect_addr; 6488 bool reloc_found = false; 6489 DataRefImpl Rel; 6490 MachO::any_relocation_info RE; 6491 bool isExtern = false; 6492 SymbolRef Symbol; 6493 for (const RelocationRef &Reloc : info->S.relocations()) { 6494 uint64_t RelocOffset = Reloc.getOffset(); 6495 if (RelocOffset == sect_offset) { 6496 Rel = Reloc.getRawDataRefImpl(); 6497 RE = info->O->getRelocation(Rel); 6498 if (info->O->isRelocationScattered(RE)) 6499 continue; 6500 isExtern = info->O->getPlainRelocationExternal(RE); 6501 if (isExtern) { 6502 symbol_iterator RelocSym = Reloc.getSymbol(); 6503 Symbol = *RelocSym; 6504 } 6505 reloc_found = true; 6506 break; 6507 } 6508 } 6509 // If there is an external relocation entry for a symbol in a section 6510 // then used that symbol's value for the value of the reference. 6511 if (reloc_found && isExtern) { 6512 if (info->O->getAnyRelocationPCRel(RE)) { 6513 unsigned Type = info->O->getAnyRelocationType(RE); 6514 if (Type == MachO::X86_64_RELOC_SIGNED) { 6515 ReferenceValue = Symbol.getValue(); 6516 } 6517 } 6518 } 6519 } 6520 6521 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6522 // Message refs and Class refs. 6523 bool classref, selref, msgref, cfstring; 6524 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6525 selref, msgref, cfstring); 6526 if (classref && pointer_value == 0) { 6527 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6528 // And the pointer_value in that section is typically zero as it will be 6529 // set by dyld as part of the "bind information". 6530 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6531 if (name != nullptr) { 6532 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6533 const char *class_name = strrchr(name, '$'); 6534 if (class_name != nullptr && class_name[1] == '_' && 6535 class_name[2] != '\0') { 6536 info->class_name = class_name + 2; 6537 return name; 6538 } 6539 } 6540 } 6541 6542 if (classref) { 6543 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6544 const char *name = 6545 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6546 if (name != nullptr) 6547 info->class_name = name; 6548 else 6549 name = "bad class ref"; 6550 return name; 6551 } 6552 6553 if (cfstring) { 6554 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6555 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6556 return name; 6557 } 6558 6559 if (selref && pointer_value == 0) 6560 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6561 6562 if (pointer_value != 0) 6563 ReferenceValue = pointer_value; 6564 6565 const char *name = GuessCstringPointer(ReferenceValue, info); 6566 if (name) { 6567 if (pointer_value != 0 && selref) { 6568 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6569 info->selector_name = name; 6570 } else if (pointer_value != 0 && msgref) { 6571 info->class_name = nullptr; 6572 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6573 info->selector_name = name; 6574 } else 6575 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6576 return name; 6577 } 6578 6579 // Lastly look for an indirect symbol with this ReferenceValue which is in 6580 // a literal pool. If found return that symbol name. 6581 name = GuessIndirectSymbol(ReferenceValue, info); 6582 if (name) { 6583 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6584 return name; 6585 } 6586 6587 return nullptr; 6588 } 6589 6590 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6591 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6592 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6593 // is created and returns the symbol name that matches the ReferenceValue or 6594 // nullptr if none. The ReferenceType is passed in for the IN type of 6595 // reference the instruction is making from the values in defined in the header 6596 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6597 // Out type and the ReferenceName will also be set which is added as a comment 6598 // to the disassembled instruction. 6599 // 6600 // If the symbol name is a C++ mangled name then the demangled name is 6601 // returned through ReferenceName and ReferenceType is set to 6602 // LLVMDisassembler_ReferenceType_DeMangled_Name . 6603 // 6604 // When this is called to get a symbol name for a branch target then the 6605 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 6606 // SymbolValue will be looked for in the indirect symbol table to determine if 6607 // it is an address for a symbol stub. If so then the symbol name for that 6608 // stub is returned indirectly through ReferenceName and then ReferenceType is 6609 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 6610 // 6611 // When this is called with an value loaded via a PC relative load then 6612 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 6613 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 6614 // or an Objective-C meta data reference. If so the output ReferenceType is 6615 // set to correspond to that as well as setting the ReferenceName. 6616 static const char *SymbolizerSymbolLookUp(void *DisInfo, 6617 uint64_t ReferenceValue, 6618 uint64_t *ReferenceType, 6619 uint64_t ReferencePC, 6620 const char **ReferenceName) { 6621 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 6622 // If no verbose symbolic information is wanted then just return nullptr. 6623 if (!info->verbose) { 6624 *ReferenceName = nullptr; 6625 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6626 return nullptr; 6627 } 6628 6629 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 6630 6631 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 6632 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 6633 if (*ReferenceName != nullptr) { 6634 method_reference(info, ReferenceType, ReferenceName); 6635 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 6636 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 6637 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6638 if (info->demangled_name != nullptr) 6639 free(info->demangled_name); 6640 int status; 6641 info->demangled_name = 6642 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6643 if (info->demangled_name != nullptr) { 6644 *ReferenceName = info->demangled_name; 6645 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6646 } else 6647 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6648 } else 6649 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6650 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 6651 *ReferenceName = 6652 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6653 if (*ReferenceName) 6654 method_reference(info, ReferenceType, ReferenceName); 6655 else 6656 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6657 // If this is arm64 and the reference is an adrp instruction save the 6658 // instruction, passed in ReferenceValue and the address of the instruction 6659 // for use later if we see and add immediate instruction. 6660 } else if (info->O->getArch() == Triple::aarch64 && 6661 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 6662 info->adrp_inst = ReferenceValue; 6663 info->adrp_addr = ReferencePC; 6664 SymbolName = nullptr; 6665 *ReferenceName = nullptr; 6666 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6667 // If this is arm64 and reference is an add immediate instruction and we 6668 // have 6669 // seen an adrp instruction just before it and the adrp's Xd register 6670 // matches 6671 // this add's Xn register reconstruct the value being referenced and look to 6672 // see if it is a literal pointer. Note the add immediate instruction is 6673 // passed in ReferenceValue. 6674 } else if (info->O->getArch() == Triple::aarch64 && 6675 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 6676 ReferencePC - 4 == info->adrp_addr && 6677 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6678 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6679 uint32_t addxri_inst; 6680 uint64_t adrp_imm, addxri_imm; 6681 6682 adrp_imm = 6683 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6684 if (info->adrp_inst & 0x0200000) 6685 adrp_imm |= 0xfffffffffc000000LL; 6686 6687 addxri_inst = ReferenceValue; 6688 addxri_imm = (addxri_inst >> 10) & 0xfff; 6689 if (((addxri_inst >> 22) & 0x3) == 1) 6690 addxri_imm <<= 12; 6691 6692 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6693 (adrp_imm << 12) + addxri_imm; 6694 6695 *ReferenceName = 6696 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6697 if (*ReferenceName == nullptr) 6698 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6699 // If this is arm64 and the reference is a load register instruction and we 6700 // have seen an adrp instruction just before it and the adrp's Xd register 6701 // matches this add's Xn register reconstruct the value being referenced and 6702 // look to see if it is a literal pointer. Note the load register 6703 // instruction is passed in ReferenceValue. 6704 } else if (info->O->getArch() == Triple::aarch64 && 6705 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 6706 ReferencePC - 4 == info->adrp_addr && 6707 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6708 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6709 uint32_t ldrxui_inst; 6710 uint64_t adrp_imm, ldrxui_imm; 6711 6712 adrp_imm = 6713 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6714 if (info->adrp_inst & 0x0200000) 6715 adrp_imm |= 0xfffffffffc000000LL; 6716 6717 ldrxui_inst = ReferenceValue; 6718 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 6719 6720 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6721 (adrp_imm << 12) + (ldrxui_imm << 3); 6722 6723 *ReferenceName = 6724 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6725 if (*ReferenceName == nullptr) 6726 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6727 } 6728 // If this arm64 and is an load register (PC-relative) instruction the 6729 // ReferenceValue is the PC plus the immediate value. 6730 else if (info->O->getArch() == Triple::aarch64 && 6731 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 6732 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 6733 *ReferenceName = 6734 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6735 if (*ReferenceName == nullptr) 6736 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6737 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6738 if (info->demangled_name != nullptr) 6739 free(info->demangled_name); 6740 int status; 6741 info->demangled_name = 6742 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6743 if (info->demangled_name != nullptr) { 6744 *ReferenceName = info->demangled_name; 6745 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6746 } 6747 } 6748 else { 6749 *ReferenceName = nullptr; 6750 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6751 } 6752 6753 return SymbolName; 6754 } 6755 6756 /// Emits the comments that are stored in the CommentStream. 6757 /// Each comment in the CommentStream must end with a newline. 6758 static void emitComments(raw_svector_ostream &CommentStream, 6759 SmallString<128> &CommentsToEmit, 6760 formatted_raw_ostream &FormattedOS, 6761 const MCAsmInfo &MAI) { 6762 // Flush the stream before taking its content. 6763 StringRef Comments = CommentsToEmit.str(); 6764 // Get the default information for printing a comment. 6765 StringRef CommentBegin = MAI.getCommentString(); 6766 unsigned CommentColumn = MAI.getCommentColumn(); 6767 bool IsFirst = true; 6768 while (!Comments.empty()) { 6769 if (!IsFirst) 6770 FormattedOS << '\n'; 6771 // Emit a line of comments. 6772 FormattedOS.PadToColumn(CommentColumn); 6773 size_t Position = Comments.find('\n'); 6774 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 6775 // Move after the newline character. 6776 Comments = Comments.substr(Position + 1); 6777 IsFirst = false; 6778 } 6779 FormattedOS.flush(); 6780 6781 // Tell the comment stream that the vector changed underneath it. 6782 CommentsToEmit.clear(); 6783 } 6784 6785 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 6786 StringRef DisSegName, StringRef DisSectName) { 6787 const char *McpuDefault = nullptr; 6788 const Target *ThumbTarget = nullptr; 6789 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 6790 if (!TheTarget) { 6791 // GetTarget prints out stuff. 6792 return; 6793 } 6794 std::string MachOMCPU; 6795 if (MCPU.empty() && McpuDefault) 6796 MachOMCPU = McpuDefault; 6797 else 6798 MachOMCPU = MCPU; 6799 6800 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 6801 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 6802 if (ThumbTarget) 6803 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 6804 6805 // Package up features to be passed to target/subtarget 6806 std::string FeaturesStr; 6807 if (MAttrs.size()) { 6808 SubtargetFeatures Features; 6809 for (unsigned i = 0; i != MAttrs.size(); ++i) 6810 Features.AddFeature(MAttrs[i]); 6811 FeaturesStr = Features.getString(); 6812 } 6813 6814 // Set up disassembler. 6815 std::unique_ptr<const MCRegisterInfo> MRI( 6816 TheTarget->createMCRegInfo(TripleName)); 6817 std::unique_ptr<const MCAsmInfo> AsmInfo( 6818 TheTarget->createMCAsmInfo(*MRI, TripleName)); 6819 std::unique_ptr<const MCSubtargetInfo> STI( 6820 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 6821 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 6822 std::unique_ptr<MCDisassembler> DisAsm( 6823 TheTarget->createMCDisassembler(*STI, Ctx)); 6824 std::unique_ptr<MCSymbolizer> Symbolizer; 6825 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false); 6826 std::unique_ptr<MCRelocationInfo> RelInfo( 6827 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 6828 if (RelInfo) { 6829 Symbolizer.reset(TheTarget->createMCSymbolizer( 6830 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6831 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 6832 DisAsm->setSymbolizer(std::move(Symbolizer)); 6833 } 6834 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 6835 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 6836 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 6837 // Set the display preference for hex vs. decimal immediates. 6838 IP->setPrintImmHex(PrintImmHex); 6839 // Comment stream and backing vector. 6840 SmallString<128> CommentsToEmit; 6841 raw_svector_ostream CommentStream(CommentsToEmit); 6842 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 6843 // if it is done then arm64 comments for string literals don't get printed 6844 // and some constant get printed instead and not setting it causes intel 6845 // (32-bit and 64-bit) comments printed with different spacing before the 6846 // comment causing different diffs with the 'C' disassembler library API. 6847 // IP->setCommentStream(CommentStream); 6848 6849 if (!AsmInfo || !STI || !DisAsm || !IP) { 6850 errs() << "error: couldn't initialize disassembler for target " 6851 << TripleName << '\n'; 6852 return; 6853 } 6854 6855 // Set up separate thumb disassembler if needed. 6856 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 6857 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 6858 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 6859 std::unique_ptr<MCDisassembler> ThumbDisAsm; 6860 std::unique_ptr<MCInstPrinter> ThumbIP; 6861 std::unique_ptr<MCContext> ThumbCtx; 6862 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 6863 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false); 6864 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 6865 if (ThumbTarget) { 6866 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 6867 ThumbAsmInfo.reset( 6868 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName)); 6869 ThumbSTI.reset( 6870 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 6871 FeaturesStr)); 6872 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 6873 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 6874 MCContext *PtrThumbCtx = ThumbCtx.get(); 6875 ThumbRelInfo.reset( 6876 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 6877 if (ThumbRelInfo) { 6878 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 6879 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6880 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 6881 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 6882 } 6883 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 6884 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 6885 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 6886 *ThumbInstrInfo, *ThumbMRI)); 6887 // Set the display preference for hex vs. decimal immediates. 6888 ThumbIP->setPrintImmHex(PrintImmHex); 6889 } 6890 6891 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) { 6892 errs() << "error: couldn't initialize disassembler for target " 6893 << ThumbTripleName << '\n'; 6894 return; 6895 } 6896 6897 MachO::mach_header Header = MachOOF->getHeader(); 6898 6899 // FIXME: Using the -cfg command line option, this code used to be able to 6900 // annotate relocations with the referenced symbol's name, and if this was 6901 // inside a __[cf]string section, the data it points to. This is now replaced 6902 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 6903 std::vector<SectionRef> Sections; 6904 std::vector<SymbolRef> Symbols; 6905 SmallVector<uint64_t, 8> FoundFns; 6906 uint64_t BaseSegmentAddress; 6907 6908 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 6909 BaseSegmentAddress); 6910 6911 // Sort the symbols by address, just in case they didn't come in that way. 6912 llvm::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); 6913 6914 // Build a data in code table that is sorted on by the address of each entry. 6915 uint64_t BaseAddress = 0; 6916 if (Header.filetype == MachO::MH_OBJECT) 6917 BaseAddress = Sections[0].getAddress(); 6918 else 6919 BaseAddress = BaseSegmentAddress; 6920 DiceTable Dices; 6921 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 6922 DI != DE; ++DI) { 6923 uint32_t Offset; 6924 DI->getOffset(Offset); 6925 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 6926 } 6927 array_pod_sort(Dices.begin(), Dices.end()); 6928 6929 #ifndef NDEBUG 6930 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); 6931 #else 6932 raw_ostream &DebugOut = nulls(); 6933 #endif 6934 6935 std::unique_ptr<DIContext> diContext; 6936 ObjectFile *DbgObj = MachOOF; 6937 // Try to find debug info and set up the DIContext for it. 6938 if (UseDbg) { 6939 // A separate DSym file path was specified, parse it as a macho file, 6940 // get the sections and supply it to the section name parsing machinery. 6941 if (!DSYMFile.empty()) { 6942 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 6943 MemoryBuffer::getFileOrSTDIN(DSYMFile); 6944 if (std::error_code EC = BufOrErr.getError()) { 6945 errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n'; 6946 return; 6947 } 6948 Expected<std::unique_ptr<MachOObjectFile>> DbgObjCheck = 6949 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()); 6950 6951 if (DbgObjCheck.takeError()) 6952 report_error(MachOOF->getFileName(), DbgObjCheck.takeError()); 6953 DbgObj = DbgObjCheck.get().release(); 6954 } 6955 6956 // Setup the DIContext 6957 diContext = DWARFContext::create(*DbgObj); 6958 } 6959 6960 if (FilterSections.size() == 0) 6961 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 6962 6963 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 6964 StringRef SectName; 6965 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName) 6966 continue; 6967 6968 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 6969 6970 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 6971 if (SegmentName != DisSegName) 6972 continue; 6973 6974 StringRef BytesStr; 6975 Sections[SectIdx].getContents(BytesStr); 6976 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()), 6977 BytesStr.size()); 6978 uint64_t SectAddress = Sections[SectIdx].getAddress(); 6979 6980 bool symbolTableWorked = false; 6981 6982 // Create a map of symbol addresses to symbol names for use by 6983 // the SymbolizerSymbolLookUp() routine. 6984 SymbolAddressMap AddrMap; 6985 bool DisSymNameFound = false; 6986 for (const SymbolRef &Symbol : MachOOF->symbols()) { 6987 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 6988 if (!STOrErr) 6989 report_error(MachOOF->getFileName(), STOrErr.takeError()); 6990 SymbolRef::Type ST = *STOrErr; 6991 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 6992 ST == SymbolRef::ST_Other) { 6993 uint64_t Address = Symbol.getValue(); 6994 Expected<StringRef> SymNameOrErr = Symbol.getName(); 6995 if (!SymNameOrErr) 6996 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 6997 StringRef SymName = *SymNameOrErr; 6998 AddrMap[Address] = SymName; 6999 if (!DisSymName.empty() && DisSymName == SymName) 7000 DisSymNameFound = true; 7001 } 7002 } 7003 if (!DisSymName.empty() && !DisSymNameFound) { 7004 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 7005 return; 7006 } 7007 // Set up the block of info used by the Symbolizer call backs. 7008 SymbolizerInfo.verbose = !NoSymbolicOperands; 7009 SymbolizerInfo.O = MachOOF; 7010 SymbolizerInfo.S = Sections[SectIdx]; 7011 SymbolizerInfo.AddrMap = &AddrMap; 7012 SymbolizerInfo.Sections = &Sections; 7013 // Same for the ThumbSymbolizer 7014 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands; 7015 ThumbSymbolizerInfo.O = MachOOF; 7016 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7017 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7018 ThumbSymbolizerInfo.Sections = &Sections; 7019 7020 unsigned int Arch = MachOOF->getArch(); 7021 7022 // Skip all symbols if this is a stubs file. 7023 if (Bytes.size() == 0) 7024 return; 7025 7026 // If the section has symbols but no symbol at the start of the section 7027 // these are used to make sure the bytes before the first symbol are 7028 // disassembled. 7029 bool FirstSymbol = true; 7030 bool FirstSymbolAtSectionStart = true; 7031 7032 // Disassemble symbol by symbol. 7033 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7034 Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName(); 7035 if (!SymNameOrErr) 7036 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 7037 StringRef SymName = *SymNameOrErr; 7038 7039 Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType(); 7040 if (!STOrErr) 7041 report_error(MachOOF->getFileName(), STOrErr.takeError()); 7042 SymbolRef::Type ST = *STOrErr; 7043 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7044 continue; 7045 7046 // Make sure the symbol is defined in this section. 7047 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7048 if (!containsSym) { 7049 if (!DisSymName.empty() && DisSymName == SymName) { 7050 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7051 return; 7052 } 7053 continue; 7054 } 7055 // The __mh_execute_header is special and we need to deal with that fact 7056 // this symbol is before the start of the (__TEXT,__text) section and at the 7057 // address of the start of the __TEXT segment. This is because this symbol 7058 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7059 // start of the section in a standard MH_EXECUTE filetype. 7060 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7061 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7062 return; 7063 } 7064 // When this code is trying to disassemble a symbol at a time and in the 7065 // case there is only the __mh_execute_header symbol left as in a stripped 7066 // executable, we need to deal with this by ignoring this symbol so the 7067 // whole section is disassembled and this symbol is then not displayed. 7068 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7069 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7070 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7071 continue; 7072 7073 // If we are only disassembling one symbol see if this is that symbol. 7074 if (!DisSymName.empty() && DisSymName != SymName) 7075 continue; 7076 7077 // Start at the address of the symbol relative to the section's address. 7078 uint64_t SectSize = Sections[SectIdx].getSize(); 7079 uint64_t Start = Symbols[SymIdx].getValue(); 7080 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7081 Start -= SectionAddress; 7082 7083 if (Start > SectSize) { 7084 outs() << "section data ends, " << SymName 7085 << " lies outside valid range\n"; 7086 return; 7087 } 7088 7089 // Stop disassembling either at the beginning of the next symbol or at 7090 // the end of the section. 7091 bool containsNextSym = false; 7092 uint64_t NextSym = 0; 7093 uint64_t NextSymIdx = SymIdx + 1; 7094 while (Symbols.size() > NextSymIdx) { 7095 Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType(); 7096 if (!STOrErr) 7097 report_error(MachOOF->getFileName(), STOrErr.takeError()); 7098 SymbolRef::Type NextSymType = *STOrErr; 7099 if (NextSymType == SymbolRef::ST_Function) { 7100 containsNextSym = 7101 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7102 NextSym = Symbols[NextSymIdx].getValue(); 7103 NextSym -= SectionAddress; 7104 break; 7105 } 7106 ++NextSymIdx; 7107 } 7108 7109 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7110 uint64_t Size; 7111 7112 symbolTableWorked = true; 7113 7114 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7115 bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb; 7116 7117 // We only need the dedicated Thumb target if there's a real choice 7118 // (i.e. we're not targeting M-class) and the function is Thumb. 7119 bool UseThumbTarget = IsThumb && ThumbTarget; 7120 7121 // If we are not specifying a symbol to start disassembly with and this 7122 // is the first symbol in the section but not at the start of the section 7123 // then move the disassembly index to the start of the section and 7124 // don't print the symbol name just yet. This is so the bytes before the 7125 // first symbol are disassembled. 7126 uint64_t SymbolStart = Start; 7127 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7128 FirstSymbolAtSectionStart = false; 7129 Start = 0; 7130 } 7131 else 7132 outs() << SymName << ":\n"; 7133 7134 DILineInfo lastLine; 7135 for (uint64_t Index = Start; Index < End; Index += Size) { 7136 MCInst Inst; 7137 7138 // If this is the first symbol in the section and it was not at the 7139 // start of the section, see if we are at its Index now and if so print 7140 // the symbol name. 7141 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7142 outs() << SymName << ":\n"; 7143 7144 uint64_t PC = SectAddress + Index; 7145 if (!NoLeadingAddr) { 7146 if (FullLeadingAddr) { 7147 if (MachOOF->is64Bit()) 7148 outs() << format("%016" PRIx64, PC); 7149 else 7150 outs() << format("%08" PRIx64, PC); 7151 } else { 7152 outs() << format("%8" PRIx64 ":", PC); 7153 } 7154 } 7155 if (!NoShowRawInsn || Arch == Triple::arm) 7156 outs() << "\t"; 7157 7158 // Check the data in code table here to see if this is data not an 7159 // instruction to be disassembled. 7160 DiceTable Dice; 7161 Dice.push_back(std::make_pair(PC, DiceRef())); 7162 dice_table_iterator DTI = 7163 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 7164 compareDiceTableEntries); 7165 if (DTI != Dices.end()) { 7166 uint16_t Length; 7167 DTI->second.getLength(Length); 7168 uint16_t Kind; 7169 DTI->second.getKind(Kind); 7170 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind); 7171 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 7172 (PC == (DTI->first + Length - 1)) && (Length & 1)) 7173 Size++; 7174 continue; 7175 } 7176 7177 SmallVector<char, 64> AnnotationsBytes; 7178 raw_svector_ostream Annotations(AnnotationsBytes); 7179 7180 bool gotInst; 7181 if (UseThumbTarget) 7182 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7183 PC, DebugOut, Annotations); 7184 else 7185 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7186 DebugOut, Annotations); 7187 if (gotInst) { 7188 if (!NoShowRawInsn || Arch == Triple::arm) { 7189 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); 7190 } 7191 formatted_raw_ostream FormattedOS(outs()); 7192 StringRef AnnotationsStr = Annotations.str(); 7193 if (UseThumbTarget) 7194 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI); 7195 else 7196 IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI); 7197 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7198 7199 // Print debug info. 7200 if (diContext) { 7201 DILineInfo dli = diContext->getLineInfoForAddress(PC); 7202 // Print valid line info if it changed. 7203 if (dli != lastLine && dli.Line != 0) 7204 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7205 << dli.Column; 7206 lastLine = dli; 7207 } 7208 outs() << "\n"; 7209 } else { 7210 unsigned int Arch = MachOOF->getArch(); 7211 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7212 outs() << format("\t.byte 0x%02x #bad opcode\n", 7213 *(Bytes.data() + Index) & 0xff); 7214 Size = 1; // skip exactly one illegible byte and move on. 7215 } else if (Arch == Triple::aarch64 || 7216 (Arch == Triple::arm && !IsThumb)) { 7217 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7218 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7219 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7220 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7221 outs() << format("\t.long\t0x%08x\n", opcode); 7222 Size = 4; 7223 } else if (Arch == Triple::arm) { 7224 assert(IsThumb && "ARM mode should have been dealt with above"); 7225 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7226 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7227 outs() << format("\t.short\t0x%04x\n", opcode); 7228 Size = 2; 7229 } else{ 7230 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 7231 if (Size == 0) 7232 Size = 1; // skip illegible bytes 7233 } 7234 } 7235 } 7236 // Now that we are done disassembled the first symbol set the bool that 7237 // were doing this to false. 7238 FirstSymbol = false; 7239 } 7240 if (!symbolTableWorked) { 7241 // Reading the symbol table didn't work, disassemble the whole section. 7242 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7243 uint64_t SectSize = Sections[SectIdx].getSize(); 7244 uint64_t InstSize; 7245 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7246 MCInst Inst; 7247 7248 uint64_t PC = SectAddress + Index; 7249 SmallVector<char, 64> AnnotationsBytes; 7250 raw_svector_ostream Annotations(AnnotationsBytes); 7251 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7252 DebugOut, Annotations)) { 7253 if (!NoLeadingAddr) { 7254 if (FullLeadingAddr) { 7255 if (MachOOF->is64Bit()) 7256 outs() << format("%016" PRIx64, PC); 7257 else 7258 outs() << format("%08" PRIx64, PC); 7259 } else { 7260 outs() << format("%8" PRIx64 ":", PC); 7261 } 7262 } 7263 if (!NoShowRawInsn || Arch == Triple::arm) { 7264 outs() << "\t"; 7265 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); 7266 } 7267 StringRef AnnotationsStr = Annotations.str(); 7268 IP->printInst(&Inst, outs(), AnnotationsStr, *STI); 7269 outs() << "\n"; 7270 } else { 7271 unsigned int Arch = MachOOF->getArch(); 7272 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7273 outs() << format("\t.byte 0x%02x #bad opcode\n", 7274 *(Bytes.data() + Index) & 0xff); 7275 InstSize = 1; // skip exactly one illegible byte and move on. 7276 } else { 7277 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 7278 if (InstSize == 0) 7279 InstSize = 1; // skip illegible bytes 7280 } 7281 } 7282 } 7283 } 7284 // The TripleName's need to be reset if we are called again for a different 7285 // archtecture. 7286 TripleName = ""; 7287 ThumbTripleName = ""; 7288 7289 if (SymbolizerInfo.demangled_name != nullptr) 7290 free(SymbolizerInfo.demangled_name); 7291 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7292 free(ThumbSymbolizerInfo.demangled_name); 7293 } 7294 } 7295 7296 //===----------------------------------------------------------------------===// 7297 // __compact_unwind section dumping 7298 //===----------------------------------------------------------------------===// 7299 7300 namespace { 7301 7302 template <typename T> 7303 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7304 using llvm::support::little; 7305 using llvm::support::unaligned; 7306 7307 if (Offset + sizeof(T) > Contents.size()) { 7308 outs() << "warning: attempt to read past end of buffer\n"; 7309 return T(); 7310 } 7311 7312 uint64_t Val = 7313 support::endian::read<T, little, unaligned>(Contents.data() + Offset); 7314 return Val; 7315 } 7316 7317 template <typename T> 7318 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7319 T Val = read<T>(Contents, Offset); 7320 Offset += sizeof(T); 7321 return Val; 7322 } 7323 7324 struct CompactUnwindEntry { 7325 uint32_t OffsetInSection; 7326 7327 uint64_t FunctionAddr; 7328 uint32_t Length; 7329 uint32_t CompactEncoding; 7330 uint64_t PersonalityAddr; 7331 uint64_t LSDAAddr; 7332 7333 RelocationRef FunctionReloc; 7334 RelocationRef PersonalityReloc; 7335 RelocationRef LSDAReloc; 7336 7337 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7338 : OffsetInSection(Offset) { 7339 if (Is64) 7340 read<uint64_t>(Contents, Offset); 7341 else 7342 read<uint32_t>(Contents, Offset); 7343 } 7344 7345 private: 7346 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7347 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7348 Length = readNext<uint32_t>(Contents, Offset); 7349 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7350 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7351 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7352 } 7353 }; 7354 } 7355 7356 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7357 /// and data being relocated, determine the best base Name and Addend to use for 7358 /// display purposes. 7359 /// 7360 /// 1. An Extern relocation will directly reference a symbol (and the data is 7361 /// then already an addend), so use that. 7362 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7363 // a symbol before it in the same section, and use the offset from there. 7364 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7365 /// referenced section. 7366 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7367 std::map<uint64_t, SymbolRef> &Symbols, 7368 const RelocationRef &Reloc, uint64_t Addr, 7369 StringRef &Name, uint64_t &Addend) { 7370 if (Reloc.getSymbol() != Obj->symbol_end()) { 7371 Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName(); 7372 if (!NameOrErr) 7373 report_error(Obj->getFileName(), NameOrErr.takeError()); 7374 Name = *NameOrErr; 7375 Addend = Addr; 7376 return; 7377 } 7378 7379 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7380 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7381 7382 uint64_t SectionAddr = RelocSection.getAddress(); 7383 7384 auto Sym = Symbols.upper_bound(Addr); 7385 if (Sym == Symbols.begin()) { 7386 // The first symbol in the object is after this reference, the best we can 7387 // do is section-relative notation. 7388 RelocSection.getName(Name); 7389 Addend = Addr - SectionAddr; 7390 return; 7391 } 7392 7393 // Go back one so that SymbolAddress <= Addr. 7394 --Sym; 7395 7396 auto SectOrErr = Sym->second.getSection(); 7397 if (!SectOrErr) 7398 report_error(Obj->getFileName(), SectOrErr.takeError()); 7399 section_iterator SymSection = *SectOrErr; 7400 if (RelocSection == *SymSection) { 7401 // There's a valid symbol in the same section before this reference. 7402 Expected<StringRef> NameOrErr = Sym->second.getName(); 7403 if (!NameOrErr) 7404 report_error(Obj->getFileName(), NameOrErr.takeError()); 7405 Name = *NameOrErr; 7406 Addend = Addr - Sym->first; 7407 return; 7408 } 7409 7410 // There is a symbol before this reference, but it's in a different 7411 // section. Probably not helpful to mention it, so use the section name. 7412 RelocSection.getName(Name); 7413 Addend = Addr - SectionAddr; 7414 } 7415 7416 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7417 std::map<uint64_t, SymbolRef> &Symbols, 7418 const RelocationRef &Reloc, uint64_t Addr) { 7419 StringRef Name; 7420 uint64_t Addend; 7421 7422 if (!Reloc.getObject()) 7423 return; 7424 7425 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7426 7427 outs() << Name; 7428 if (Addend) 7429 outs() << " + " << format("0x%" PRIx64, Addend); 7430 } 7431 7432 static void 7433 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7434 std::map<uint64_t, SymbolRef> &Symbols, 7435 const SectionRef &CompactUnwind) { 7436 7437 if (!Obj->isLittleEndian()) { 7438 outs() << "Skipping big-endian __compact_unwind section\n"; 7439 return; 7440 } 7441 7442 bool Is64 = Obj->is64Bit(); 7443 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7444 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7445 7446 StringRef Contents; 7447 CompactUnwind.getContents(Contents); 7448 7449 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7450 7451 // First populate the initial raw offsets, encodings and so on from the entry. 7452 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7453 CompactUnwindEntry Entry(Contents, Offset, Is64); 7454 CompactUnwinds.push_back(Entry); 7455 } 7456 7457 // Next we need to look at the relocations to find out what objects are 7458 // actually being referred to. 7459 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7460 uint64_t RelocAddress = Reloc.getOffset(); 7461 7462 uint32_t EntryIdx = RelocAddress / EntrySize; 7463 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7464 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7465 7466 if (OffsetInEntry == 0) 7467 Entry.FunctionReloc = Reloc; 7468 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7469 Entry.PersonalityReloc = Reloc; 7470 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7471 Entry.LSDAReloc = Reloc; 7472 else { 7473 outs() << "Invalid relocation in __compact_unwind section\n"; 7474 return; 7475 } 7476 } 7477 7478 // Finally, we're ready to print the data we've gathered. 7479 outs() << "Contents of __compact_unwind section:\n"; 7480 for (auto &Entry : CompactUnwinds) { 7481 outs() << " Entry at offset " 7482 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7483 7484 // 1. Start of the region this entry applies to. 7485 outs() << " start: " << format("0x%" PRIx64, 7486 Entry.FunctionAddr) << ' '; 7487 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7488 outs() << '\n'; 7489 7490 // 2. Length of the region this entry applies to. 7491 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7492 << '\n'; 7493 // 3. The 32-bit compact encoding. 7494 outs() << " compact encoding: " 7495 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7496 7497 // 4. The personality function, if present. 7498 if (Entry.PersonalityReloc.getObject()) { 7499 outs() << " personality function: " 7500 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7501 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7502 Entry.PersonalityAddr); 7503 outs() << '\n'; 7504 } 7505 7506 // 5. This entry's language-specific data area. 7507 if (Entry.LSDAReloc.getObject()) { 7508 outs() << " LSDA: " << format("0x%" PRIx64, 7509 Entry.LSDAAddr) << ' '; 7510 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7511 outs() << '\n'; 7512 } 7513 } 7514 } 7515 7516 //===----------------------------------------------------------------------===// 7517 // __unwind_info section dumping 7518 //===----------------------------------------------------------------------===// 7519 7520 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 7521 ptrdiff_t Pos = 0; 7522 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7523 (void)Kind; 7524 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7525 7526 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7527 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7528 7529 Pos = EntriesStart; 7530 for (unsigned i = 0; i < NumEntries; ++i) { 7531 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 7532 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7533 7534 outs() << " [" << i << "]: " 7535 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7536 << ", " 7537 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7538 } 7539 } 7540 7541 static void printCompressedSecondLevelUnwindPage( 7542 StringRef PageData, uint32_t FunctionBase, 7543 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7544 ptrdiff_t Pos = 0; 7545 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7546 (void)Kind; 7547 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 7548 7549 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7550 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7551 7552 uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos); 7553 readNext<uint16_t>(PageData, Pos); 7554 StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos); 7555 7556 Pos = EntriesStart; 7557 for (unsigned i = 0; i < NumEntries; ++i) { 7558 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 7559 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 7560 uint32_t EncodingIdx = Entry >> 24; 7561 7562 uint32_t Encoding; 7563 if (EncodingIdx < CommonEncodings.size()) 7564 Encoding = CommonEncodings[EncodingIdx]; 7565 else 7566 Encoding = read<uint32_t>(PageEncodings, 7567 sizeof(uint32_t) * 7568 (EncodingIdx - CommonEncodings.size())); 7569 7570 outs() << " [" << i << "]: " 7571 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7572 << ", " 7573 << "encoding[" << EncodingIdx 7574 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 7575 } 7576 } 7577 7578 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 7579 std::map<uint64_t, SymbolRef> &Symbols, 7580 const SectionRef &UnwindInfo) { 7581 7582 if (!Obj->isLittleEndian()) { 7583 outs() << "Skipping big-endian __unwind_info section\n"; 7584 return; 7585 } 7586 7587 outs() << "Contents of __unwind_info section:\n"; 7588 7589 StringRef Contents; 7590 UnwindInfo.getContents(Contents); 7591 ptrdiff_t Pos = 0; 7592 7593 //===---------------------------------- 7594 // Section header 7595 //===---------------------------------- 7596 7597 uint32_t Version = readNext<uint32_t>(Contents, Pos); 7598 outs() << " Version: " 7599 << format("0x%" PRIx32, Version) << '\n'; 7600 if (Version != 1) { 7601 outs() << " Skipping section with unknown version\n"; 7602 return; 7603 } 7604 7605 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 7606 outs() << " Common encodings array section offset: " 7607 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 7608 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 7609 outs() << " Number of common encodings in array: " 7610 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 7611 7612 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 7613 outs() << " Personality function array section offset: " 7614 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 7615 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 7616 outs() << " Number of personality functions in array: " 7617 << format("0x%" PRIx32, NumPersonalities) << '\n'; 7618 7619 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 7620 outs() << " Index array section offset: " 7621 << format("0x%" PRIx32, IndicesStart) << '\n'; 7622 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 7623 outs() << " Number of indices in array: " 7624 << format("0x%" PRIx32, NumIndices) << '\n'; 7625 7626 //===---------------------------------- 7627 // A shared list of common encodings 7628 //===---------------------------------- 7629 7630 // These occupy indices in the range [0, N] whenever an encoding is referenced 7631 // from a compressed 2nd level index table. In practice the linker only 7632 // creates ~128 of these, so that indices are available to embed encodings in 7633 // the 2nd level index. 7634 7635 SmallVector<uint32_t, 64> CommonEncodings; 7636 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 7637 Pos = CommonEncodingsStart; 7638 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 7639 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 7640 CommonEncodings.push_back(Encoding); 7641 7642 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 7643 << '\n'; 7644 } 7645 7646 //===---------------------------------- 7647 // Personality functions used in this executable 7648 //===---------------------------------- 7649 7650 // There should be only a handful of these (one per source language, 7651 // roughly). Particularly since they only get 2 bits in the compact encoding. 7652 7653 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 7654 Pos = PersonalitiesStart; 7655 for (unsigned i = 0; i < NumPersonalities; ++i) { 7656 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 7657 outs() << " personality[" << i + 1 7658 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 7659 } 7660 7661 //===---------------------------------- 7662 // The level 1 index entries 7663 //===---------------------------------- 7664 7665 // These specify an approximate place to start searching for the more detailed 7666 // information, sorted by PC. 7667 7668 struct IndexEntry { 7669 uint32_t FunctionOffset; 7670 uint32_t SecondLevelPageStart; 7671 uint32_t LSDAStart; 7672 }; 7673 7674 SmallVector<IndexEntry, 4> IndexEntries; 7675 7676 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 7677 Pos = IndicesStart; 7678 for (unsigned i = 0; i < NumIndices; ++i) { 7679 IndexEntry Entry; 7680 7681 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 7682 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 7683 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 7684 IndexEntries.push_back(Entry); 7685 7686 outs() << " [" << i << "]: " 7687 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 7688 << ", " 7689 << "2nd level page offset=" 7690 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 7691 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 7692 } 7693 7694 //===---------------------------------- 7695 // Next come the LSDA tables 7696 //===---------------------------------- 7697 7698 // The LSDA layout is rather implicit: it's a contiguous array of entries from 7699 // the first top-level index's LSDAOffset to the last (sentinel). 7700 7701 outs() << " LSDA descriptors:\n"; 7702 Pos = IndexEntries[0].LSDAStart; 7703 const uint32_t LSDASize = 2 * sizeof(uint32_t); 7704 int NumLSDAs = 7705 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 7706 7707 for (int i = 0; i < NumLSDAs; ++i) { 7708 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 7709 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 7710 outs() << " [" << i << "]: " 7711 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7712 << ", " 7713 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 7714 } 7715 7716 //===---------------------------------- 7717 // Finally, the 2nd level indices 7718 //===---------------------------------- 7719 7720 // Generally these are 4K in size, and have 2 possible forms: 7721 // + Regular stores up to 511 entries with disparate encodings 7722 // + Compressed stores up to 1021 entries if few enough compact encoding 7723 // values are used. 7724 outs() << " Second level indices:\n"; 7725 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 7726 // The final sentinel top-level index has no associated 2nd level page 7727 if (IndexEntries[i].SecondLevelPageStart == 0) 7728 break; 7729 7730 outs() << " Second level index[" << i << "]: " 7731 << "offset in section=" 7732 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 7733 << ", " 7734 << "base function offset=" 7735 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 7736 7737 Pos = IndexEntries[i].SecondLevelPageStart; 7738 if (Pos + sizeof(uint32_t) > Contents.size()) { 7739 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 7740 continue; 7741 } 7742 7743 uint32_t Kind = 7744 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 7745 if (Kind == 2) 7746 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 7747 else if (Kind == 3) 7748 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 7749 IndexEntries[i].FunctionOffset, 7750 CommonEncodings); 7751 else 7752 outs() << " Skipping 2nd level page with unknown kind " << Kind 7753 << '\n'; 7754 } 7755 } 7756 7757 void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { 7758 std::map<uint64_t, SymbolRef> Symbols; 7759 for (const SymbolRef &SymRef : Obj->symbols()) { 7760 // Discard any undefined or absolute symbols. They're not going to take part 7761 // in the convenience lookup for unwind info and just take up resources. 7762 auto SectOrErr = SymRef.getSection(); 7763 if (!SectOrErr) { 7764 // TODO: Actually report errors helpfully. 7765 consumeError(SectOrErr.takeError()); 7766 continue; 7767 } 7768 section_iterator Section = *SectOrErr; 7769 if (Section == Obj->section_end()) 7770 continue; 7771 7772 uint64_t Addr = SymRef.getValue(); 7773 Symbols.insert(std::make_pair(Addr, SymRef)); 7774 } 7775 7776 for (const SectionRef &Section : Obj->sections()) { 7777 StringRef SectName; 7778 Section.getName(SectName); 7779 if (SectName == "__compact_unwind") 7780 printMachOCompactUnwindSection(Obj, Symbols, Section); 7781 else if (SectName == "__unwind_info") 7782 printMachOUnwindInfoSection(Obj, Symbols, Section); 7783 } 7784 } 7785 7786 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 7787 uint32_t cpusubtype, uint32_t filetype, 7788 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 7789 bool verbose) { 7790 outs() << "Mach header\n"; 7791 outs() << " magic cputype cpusubtype caps filetype ncmds " 7792 "sizeofcmds flags\n"; 7793 if (verbose) { 7794 if (magic == MachO::MH_MAGIC) 7795 outs() << " MH_MAGIC"; 7796 else if (magic == MachO::MH_MAGIC_64) 7797 outs() << "MH_MAGIC_64"; 7798 else 7799 outs() << format(" 0x%08" PRIx32, magic); 7800 switch (cputype) { 7801 case MachO::CPU_TYPE_I386: 7802 outs() << " I386"; 7803 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7804 case MachO::CPU_SUBTYPE_I386_ALL: 7805 outs() << " ALL"; 7806 break; 7807 default: 7808 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7809 break; 7810 } 7811 break; 7812 case MachO::CPU_TYPE_X86_64: 7813 outs() << " X86_64"; 7814 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7815 case MachO::CPU_SUBTYPE_X86_64_ALL: 7816 outs() << " ALL"; 7817 break; 7818 case MachO::CPU_SUBTYPE_X86_64_H: 7819 outs() << " Haswell"; 7820 break; 7821 default: 7822 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7823 break; 7824 } 7825 break; 7826 case MachO::CPU_TYPE_ARM: 7827 outs() << " ARM"; 7828 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7829 case MachO::CPU_SUBTYPE_ARM_ALL: 7830 outs() << " ALL"; 7831 break; 7832 case MachO::CPU_SUBTYPE_ARM_V4T: 7833 outs() << " V4T"; 7834 break; 7835 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 7836 outs() << " V5TEJ"; 7837 break; 7838 case MachO::CPU_SUBTYPE_ARM_XSCALE: 7839 outs() << " XSCALE"; 7840 break; 7841 case MachO::CPU_SUBTYPE_ARM_V6: 7842 outs() << " V6"; 7843 break; 7844 case MachO::CPU_SUBTYPE_ARM_V6M: 7845 outs() << " V6M"; 7846 break; 7847 case MachO::CPU_SUBTYPE_ARM_V7: 7848 outs() << " V7"; 7849 break; 7850 case MachO::CPU_SUBTYPE_ARM_V7EM: 7851 outs() << " V7EM"; 7852 break; 7853 case MachO::CPU_SUBTYPE_ARM_V7K: 7854 outs() << " V7K"; 7855 break; 7856 case MachO::CPU_SUBTYPE_ARM_V7M: 7857 outs() << " V7M"; 7858 break; 7859 case MachO::CPU_SUBTYPE_ARM_V7S: 7860 outs() << " V7S"; 7861 break; 7862 default: 7863 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7864 break; 7865 } 7866 break; 7867 case MachO::CPU_TYPE_ARM64: 7868 outs() << " ARM64"; 7869 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7870 case MachO::CPU_SUBTYPE_ARM64_ALL: 7871 outs() << " ALL"; 7872 break; 7873 default: 7874 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7875 break; 7876 } 7877 break; 7878 case MachO::CPU_TYPE_POWERPC: 7879 outs() << " PPC"; 7880 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7881 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7882 outs() << " ALL"; 7883 break; 7884 default: 7885 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7886 break; 7887 } 7888 break; 7889 case MachO::CPU_TYPE_POWERPC64: 7890 outs() << " PPC64"; 7891 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7892 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7893 outs() << " ALL"; 7894 break; 7895 default: 7896 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7897 break; 7898 } 7899 break; 7900 default: 7901 outs() << format(" %7d", cputype); 7902 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7903 break; 7904 } 7905 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 7906 outs() << " LIB64"; 7907 } else { 7908 outs() << format(" 0x%02" PRIx32, 7909 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 7910 } 7911 switch (filetype) { 7912 case MachO::MH_OBJECT: 7913 outs() << " OBJECT"; 7914 break; 7915 case MachO::MH_EXECUTE: 7916 outs() << " EXECUTE"; 7917 break; 7918 case MachO::MH_FVMLIB: 7919 outs() << " FVMLIB"; 7920 break; 7921 case MachO::MH_CORE: 7922 outs() << " CORE"; 7923 break; 7924 case MachO::MH_PRELOAD: 7925 outs() << " PRELOAD"; 7926 break; 7927 case MachO::MH_DYLIB: 7928 outs() << " DYLIB"; 7929 break; 7930 case MachO::MH_DYLIB_STUB: 7931 outs() << " DYLIB_STUB"; 7932 break; 7933 case MachO::MH_DYLINKER: 7934 outs() << " DYLINKER"; 7935 break; 7936 case MachO::MH_BUNDLE: 7937 outs() << " BUNDLE"; 7938 break; 7939 case MachO::MH_DSYM: 7940 outs() << " DSYM"; 7941 break; 7942 case MachO::MH_KEXT_BUNDLE: 7943 outs() << " KEXTBUNDLE"; 7944 break; 7945 default: 7946 outs() << format(" %10u", filetype); 7947 break; 7948 } 7949 outs() << format(" %5u", ncmds); 7950 outs() << format(" %10u", sizeofcmds); 7951 uint32_t f = flags; 7952 if (f & MachO::MH_NOUNDEFS) { 7953 outs() << " NOUNDEFS"; 7954 f &= ~MachO::MH_NOUNDEFS; 7955 } 7956 if (f & MachO::MH_INCRLINK) { 7957 outs() << " INCRLINK"; 7958 f &= ~MachO::MH_INCRLINK; 7959 } 7960 if (f & MachO::MH_DYLDLINK) { 7961 outs() << " DYLDLINK"; 7962 f &= ~MachO::MH_DYLDLINK; 7963 } 7964 if (f & MachO::MH_BINDATLOAD) { 7965 outs() << " BINDATLOAD"; 7966 f &= ~MachO::MH_BINDATLOAD; 7967 } 7968 if (f & MachO::MH_PREBOUND) { 7969 outs() << " PREBOUND"; 7970 f &= ~MachO::MH_PREBOUND; 7971 } 7972 if (f & MachO::MH_SPLIT_SEGS) { 7973 outs() << " SPLIT_SEGS"; 7974 f &= ~MachO::MH_SPLIT_SEGS; 7975 } 7976 if (f & MachO::MH_LAZY_INIT) { 7977 outs() << " LAZY_INIT"; 7978 f &= ~MachO::MH_LAZY_INIT; 7979 } 7980 if (f & MachO::MH_TWOLEVEL) { 7981 outs() << " TWOLEVEL"; 7982 f &= ~MachO::MH_TWOLEVEL; 7983 } 7984 if (f & MachO::MH_FORCE_FLAT) { 7985 outs() << " FORCE_FLAT"; 7986 f &= ~MachO::MH_FORCE_FLAT; 7987 } 7988 if (f & MachO::MH_NOMULTIDEFS) { 7989 outs() << " NOMULTIDEFS"; 7990 f &= ~MachO::MH_NOMULTIDEFS; 7991 } 7992 if (f & MachO::MH_NOFIXPREBINDING) { 7993 outs() << " NOFIXPREBINDING"; 7994 f &= ~MachO::MH_NOFIXPREBINDING; 7995 } 7996 if (f & MachO::MH_PREBINDABLE) { 7997 outs() << " PREBINDABLE"; 7998 f &= ~MachO::MH_PREBINDABLE; 7999 } 8000 if (f & MachO::MH_ALLMODSBOUND) { 8001 outs() << " ALLMODSBOUND"; 8002 f &= ~MachO::MH_ALLMODSBOUND; 8003 } 8004 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8005 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8006 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8007 } 8008 if (f & MachO::MH_CANONICAL) { 8009 outs() << " CANONICAL"; 8010 f &= ~MachO::MH_CANONICAL; 8011 } 8012 if (f & MachO::MH_WEAK_DEFINES) { 8013 outs() << " WEAK_DEFINES"; 8014 f &= ~MachO::MH_WEAK_DEFINES; 8015 } 8016 if (f & MachO::MH_BINDS_TO_WEAK) { 8017 outs() << " BINDS_TO_WEAK"; 8018 f &= ~MachO::MH_BINDS_TO_WEAK; 8019 } 8020 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8021 outs() << " ALLOW_STACK_EXECUTION"; 8022 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8023 } 8024 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8025 outs() << " DEAD_STRIPPABLE_DYLIB"; 8026 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8027 } 8028 if (f & MachO::MH_PIE) { 8029 outs() << " PIE"; 8030 f &= ~MachO::MH_PIE; 8031 } 8032 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8033 outs() << " NO_REEXPORTED_DYLIBS"; 8034 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8035 } 8036 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8037 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8038 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8039 } 8040 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8041 outs() << " MH_NO_HEAP_EXECUTION"; 8042 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8043 } 8044 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8045 outs() << " APP_EXTENSION_SAFE"; 8046 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8047 } 8048 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8049 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8050 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8051 } 8052 if (f != 0 || flags == 0) 8053 outs() << format(" 0x%08" PRIx32, f); 8054 } else { 8055 outs() << format(" 0x%08" PRIx32, magic); 8056 outs() << format(" %7d", cputype); 8057 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8058 outs() << format(" 0x%02" PRIx32, 8059 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8060 outs() << format(" %10u", filetype); 8061 outs() << format(" %5u", ncmds); 8062 outs() << format(" %10u", sizeofcmds); 8063 outs() << format(" 0x%08" PRIx32, flags); 8064 } 8065 outs() << "\n"; 8066 } 8067 8068 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8069 StringRef SegName, uint64_t vmaddr, 8070 uint64_t vmsize, uint64_t fileoff, 8071 uint64_t filesize, uint32_t maxprot, 8072 uint32_t initprot, uint32_t nsects, 8073 uint32_t flags, uint32_t object_size, 8074 bool verbose) { 8075 uint64_t expected_cmdsize; 8076 if (cmd == MachO::LC_SEGMENT) { 8077 outs() << " cmd LC_SEGMENT\n"; 8078 expected_cmdsize = nsects; 8079 expected_cmdsize *= sizeof(struct MachO::section); 8080 expected_cmdsize += sizeof(struct MachO::segment_command); 8081 } else { 8082 outs() << " cmd LC_SEGMENT_64\n"; 8083 expected_cmdsize = nsects; 8084 expected_cmdsize *= sizeof(struct MachO::section_64); 8085 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8086 } 8087 outs() << " cmdsize " << cmdsize; 8088 if (cmdsize != expected_cmdsize) 8089 outs() << " Inconsistent size\n"; 8090 else 8091 outs() << "\n"; 8092 outs() << " segname " << SegName << "\n"; 8093 if (cmd == MachO::LC_SEGMENT_64) { 8094 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8095 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8096 } else { 8097 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8098 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8099 } 8100 outs() << " fileoff " << fileoff; 8101 if (fileoff > object_size) 8102 outs() << " (past end of file)\n"; 8103 else 8104 outs() << "\n"; 8105 outs() << " filesize " << filesize; 8106 if (fileoff + filesize > object_size) 8107 outs() << " (past end of file)\n"; 8108 else 8109 outs() << "\n"; 8110 if (verbose) { 8111 if ((maxprot & 8112 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8113 MachO::VM_PROT_EXECUTE)) != 0) 8114 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8115 else { 8116 outs() << " maxprot "; 8117 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8118 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8119 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8120 } 8121 if ((initprot & 8122 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8123 MachO::VM_PROT_EXECUTE)) != 0) 8124 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8125 else { 8126 outs() << " initprot "; 8127 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8128 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8129 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8130 } 8131 } else { 8132 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8133 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8134 } 8135 outs() << " nsects " << nsects << "\n"; 8136 if (verbose) { 8137 outs() << " flags"; 8138 if (flags == 0) 8139 outs() << " (none)\n"; 8140 else { 8141 if (flags & MachO::SG_HIGHVM) { 8142 outs() << " HIGHVM"; 8143 flags &= ~MachO::SG_HIGHVM; 8144 } 8145 if (flags & MachO::SG_FVMLIB) { 8146 outs() << " FVMLIB"; 8147 flags &= ~MachO::SG_FVMLIB; 8148 } 8149 if (flags & MachO::SG_NORELOC) { 8150 outs() << " NORELOC"; 8151 flags &= ~MachO::SG_NORELOC; 8152 } 8153 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8154 outs() << " PROTECTED_VERSION_1"; 8155 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8156 } 8157 if (flags) 8158 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8159 else 8160 outs() << "\n"; 8161 } 8162 } else { 8163 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8164 } 8165 } 8166 8167 static void PrintSection(const char *sectname, const char *segname, 8168 uint64_t addr, uint64_t size, uint32_t offset, 8169 uint32_t align, uint32_t reloff, uint32_t nreloc, 8170 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8171 uint32_t cmd, const char *sg_segname, 8172 uint32_t filetype, uint32_t object_size, 8173 bool verbose) { 8174 outs() << "Section\n"; 8175 outs() << " sectname " << format("%.16s\n", sectname); 8176 outs() << " segname " << format("%.16s", segname); 8177 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8178 outs() << " (does not match segment)\n"; 8179 else 8180 outs() << "\n"; 8181 if (cmd == MachO::LC_SEGMENT_64) { 8182 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8183 outs() << " size " << format("0x%016" PRIx64, size); 8184 } else { 8185 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8186 outs() << " size " << format("0x%08" PRIx64, size); 8187 } 8188 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8189 outs() << " (past end of file)\n"; 8190 else 8191 outs() << "\n"; 8192 outs() << " offset " << offset; 8193 if (offset > object_size) 8194 outs() << " (past end of file)\n"; 8195 else 8196 outs() << "\n"; 8197 uint32_t align_shifted = 1 << align; 8198 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8199 outs() << " reloff " << reloff; 8200 if (reloff > object_size) 8201 outs() << " (past end of file)\n"; 8202 else 8203 outs() << "\n"; 8204 outs() << " nreloc " << nreloc; 8205 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8206 outs() << " (past end of file)\n"; 8207 else 8208 outs() << "\n"; 8209 uint32_t section_type = flags & MachO::SECTION_TYPE; 8210 if (verbose) { 8211 outs() << " type"; 8212 if (section_type == MachO::S_REGULAR) 8213 outs() << " S_REGULAR\n"; 8214 else if (section_type == MachO::S_ZEROFILL) 8215 outs() << " S_ZEROFILL\n"; 8216 else if (section_type == MachO::S_CSTRING_LITERALS) 8217 outs() << " S_CSTRING_LITERALS\n"; 8218 else if (section_type == MachO::S_4BYTE_LITERALS) 8219 outs() << " S_4BYTE_LITERALS\n"; 8220 else if (section_type == MachO::S_8BYTE_LITERALS) 8221 outs() << " S_8BYTE_LITERALS\n"; 8222 else if (section_type == MachO::S_16BYTE_LITERALS) 8223 outs() << " S_16BYTE_LITERALS\n"; 8224 else if (section_type == MachO::S_LITERAL_POINTERS) 8225 outs() << " S_LITERAL_POINTERS\n"; 8226 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8227 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8228 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8229 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8230 else if (section_type == MachO::S_SYMBOL_STUBS) 8231 outs() << " S_SYMBOL_STUBS\n"; 8232 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8233 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8234 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8235 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8236 else if (section_type == MachO::S_COALESCED) 8237 outs() << " S_COALESCED\n"; 8238 else if (section_type == MachO::S_INTERPOSING) 8239 outs() << " S_INTERPOSING\n"; 8240 else if (section_type == MachO::S_DTRACE_DOF) 8241 outs() << " S_DTRACE_DOF\n"; 8242 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8243 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8244 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8245 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8246 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8247 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8248 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8249 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8250 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8251 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8252 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8253 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8254 else 8255 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8256 outs() << "attributes"; 8257 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8258 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8259 outs() << " PURE_INSTRUCTIONS"; 8260 if (section_attributes & MachO::S_ATTR_NO_TOC) 8261 outs() << " NO_TOC"; 8262 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8263 outs() << " STRIP_STATIC_SYMS"; 8264 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8265 outs() << " NO_DEAD_STRIP"; 8266 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8267 outs() << " LIVE_SUPPORT"; 8268 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8269 outs() << " SELF_MODIFYING_CODE"; 8270 if (section_attributes & MachO::S_ATTR_DEBUG) 8271 outs() << " DEBUG"; 8272 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8273 outs() << " SOME_INSTRUCTIONS"; 8274 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8275 outs() << " EXT_RELOC"; 8276 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8277 outs() << " LOC_RELOC"; 8278 if (section_attributes == 0) 8279 outs() << " (none)"; 8280 outs() << "\n"; 8281 } else 8282 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8283 outs() << " reserved1 " << reserved1; 8284 if (section_type == MachO::S_SYMBOL_STUBS || 8285 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8286 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8287 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8288 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8289 outs() << " (index into indirect symbol table)\n"; 8290 else 8291 outs() << "\n"; 8292 outs() << " reserved2 " << reserved2; 8293 if (section_type == MachO::S_SYMBOL_STUBS) 8294 outs() << " (size of stubs)\n"; 8295 else 8296 outs() << "\n"; 8297 } 8298 8299 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8300 uint32_t object_size) { 8301 outs() << " cmd LC_SYMTAB\n"; 8302 outs() << " cmdsize " << st.cmdsize; 8303 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8304 outs() << " Incorrect size\n"; 8305 else 8306 outs() << "\n"; 8307 outs() << " symoff " << st.symoff; 8308 if (st.symoff > object_size) 8309 outs() << " (past end of file)\n"; 8310 else 8311 outs() << "\n"; 8312 outs() << " nsyms " << st.nsyms; 8313 uint64_t big_size; 8314 if (Is64Bit) { 8315 big_size = st.nsyms; 8316 big_size *= sizeof(struct MachO::nlist_64); 8317 big_size += st.symoff; 8318 if (big_size > object_size) 8319 outs() << " (past end of file)\n"; 8320 else 8321 outs() << "\n"; 8322 } else { 8323 big_size = st.nsyms; 8324 big_size *= sizeof(struct MachO::nlist); 8325 big_size += st.symoff; 8326 if (big_size > object_size) 8327 outs() << " (past end of file)\n"; 8328 else 8329 outs() << "\n"; 8330 } 8331 outs() << " stroff " << st.stroff; 8332 if (st.stroff > object_size) 8333 outs() << " (past end of file)\n"; 8334 else 8335 outs() << "\n"; 8336 outs() << " strsize " << st.strsize; 8337 big_size = st.stroff; 8338 big_size += st.strsize; 8339 if (big_size > object_size) 8340 outs() << " (past end of file)\n"; 8341 else 8342 outs() << "\n"; 8343 } 8344 8345 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8346 uint32_t nsyms, uint32_t object_size, 8347 bool Is64Bit) { 8348 outs() << " cmd LC_DYSYMTAB\n"; 8349 outs() << " cmdsize " << dyst.cmdsize; 8350 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8351 outs() << " Incorrect size\n"; 8352 else 8353 outs() << "\n"; 8354 outs() << " ilocalsym " << dyst.ilocalsym; 8355 if (dyst.ilocalsym > nsyms) 8356 outs() << " (greater than the number of symbols)\n"; 8357 else 8358 outs() << "\n"; 8359 outs() << " nlocalsym " << dyst.nlocalsym; 8360 uint64_t big_size; 8361 big_size = dyst.ilocalsym; 8362 big_size += dyst.nlocalsym; 8363 if (big_size > nsyms) 8364 outs() << " (past the end of the symbol table)\n"; 8365 else 8366 outs() << "\n"; 8367 outs() << " iextdefsym " << dyst.iextdefsym; 8368 if (dyst.iextdefsym > nsyms) 8369 outs() << " (greater than the number of symbols)\n"; 8370 else 8371 outs() << "\n"; 8372 outs() << " nextdefsym " << dyst.nextdefsym; 8373 big_size = dyst.iextdefsym; 8374 big_size += dyst.nextdefsym; 8375 if (big_size > nsyms) 8376 outs() << " (past the end of the symbol table)\n"; 8377 else 8378 outs() << "\n"; 8379 outs() << " iundefsym " << dyst.iundefsym; 8380 if (dyst.iundefsym > nsyms) 8381 outs() << " (greater than the number of symbols)\n"; 8382 else 8383 outs() << "\n"; 8384 outs() << " nundefsym " << dyst.nundefsym; 8385 big_size = dyst.iundefsym; 8386 big_size += dyst.nundefsym; 8387 if (big_size > nsyms) 8388 outs() << " (past the end of the symbol table)\n"; 8389 else 8390 outs() << "\n"; 8391 outs() << " tocoff " << dyst.tocoff; 8392 if (dyst.tocoff > object_size) 8393 outs() << " (past end of file)\n"; 8394 else 8395 outs() << "\n"; 8396 outs() << " ntoc " << dyst.ntoc; 8397 big_size = dyst.ntoc; 8398 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8399 big_size += dyst.tocoff; 8400 if (big_size > object_size) 8401 outs() << " (past end of file)\n"; 8402 else 8403 outs() << "\n"; 8404 outs() << " modtaboff " << dyst.modtaboff; 8405 if (dyst.modtaboff > object_size) 8406 outs() << " (past end of file)\n"; 8407 else 8408 outs() << "\n"; 8409 outs() << " nmodtab " << dyst.nmodtab; 8410 uint64_t modtabend; 8411 if (Is64Bit) { 8412 modtabend = dyst.nmodtab; 8413 modtabend *= sizeof(struct MachO::dylib_module_64); 8414 modtabend += dyst.modtaboff; 8415 } else { 8416 modtabend = dyst.nmodtab; 8417 modtabend *= sizeof(struct MachO::dylib_module); 8418 modtabend += dyst.modtaboff; 8419 } 8420 if (modtabend > object_size) 8421 outs() << " (past end of file)\n"; 8422 else 8423 outs() << "\n"; 8424 outs() << " extrefsymoff " << dyst.extrefsymoff; 8425 if (dyst.extrefsymoff > object_size) 8426 outs() << " (past end of file)\n"; 8427 else 8428 outs() << "\n"; 8429 outs() << " nextrefsyms " << dyst.nextrefsyms; 8430 big_size = dyst.nextrefsyms; 8431 big_size *= sizeof(struct MachO::dylib_reference); 8432 big_size += dyst.extrefsymoff; 8433 if (big_size > object_size) 8434 outs() << " (past end of file)\n"; 8435 else 8436 outs() << "\n"; 8437 outs() << " indirectsymoff " << dyst.indirectsymoff; 8438 if (dyst.indirectsymoff > object_size) 8439 outs() << " (past end of file)\n"; 8440 else 8441 outs() << "\n"; 8442 outs() << " nindirectsyms " << dyst.nindirectsyms; 8443 big_size = dyst.nindirectsyms; 8444 big_size *= sizeof(uint32_t); 8445 big_size += dyst.indirectsymoff; 8446 if (big_size > object_size) 8447 outs() << " (past end of file)\n"; 8448 else 8449 outs() << "\n"; 8450 outs() << " extreloff " << dyst.extreloff; 8451 if (dyst.extreloff > object_size) 8452 outs() << " (past end of file)\n"; 8453 else 8454 outs() << "\n"; 8455 outs() << " nextrel " << dyst.nextrel; 8456 big_size = dyst.nextrel; 8457 big_size *= sizeof(struct MachO::relocation_info); 8458 big_size += dyst.extreloff; 8459 if (big_size > object_size) 8460 outs() << " (past end of file)\n"; 8461 else 8462 outs() << "\n"; 8463 outs() << " locreloff " << dyst.locreloff; 8464 if (dyst.locreloff > object_size) 8465 outs() << " (past end of file)\n"; 8466 else 8467 outs() << "\n"; 8468 outs() << " nlocrel " << dyst.nlocrel; 8469 big_size = dyst.nlocrel; 8470 big_size *= sizeof(struct MachO::relocation_info); 8471 big_size += dyst.locreloff; 8472 if (big_size > object_size) 8473 outs() << " (past end of file)\n"; 8474 else 8475 outs() << "\n"; 8476 } 8477 8478 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8479 uint32_t object_size) { 8480 if (dc.cmd == MachO::LC_DYLD_INFO) 8481 outs() << " cmd LC_DYLD_INFO\n"; 8482 else 8483 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8484 outs() << " cmdsize " << dc.cmdsize; 8485 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8486 outs() << " Incorrect size\n"; 8487 else 8488 outs() << "\n"; 8489 outs() << " rebase_off " << dc.rebase_off; 8490 if (dc.rebase_off > object_size) 8491 outs() << " (past end of file)\n"; 8492 else 8493 outs() << "\n"; 8494 outs() << " rebase_size " << dc.rebase_size; 8495 uint64_t big_size; 8496 big_size = dc.rebase_off; 8497 big_size += dc.rebase_size; 8498 if (big_size > object_size) 8499 outs() << " (past end of file)\n"; 8500 else 8501 outs() << "\n"; 8502 outs() << " bind_off " << dc.bind_off; 8503 if (dc.bind_off > object_size) 8504 outs() << " (past end of file)\n"; 8505 else 8506 outs() << "\n"; 8507 outs() << " bind_size " << dc.bind_size; 8508 big_size = dc.bind_off; 8509 big_size += dc.bind_size; 8510 if (big_size > object_size) 8511 outs() << " (past end of file)\n"; 8512 else 8513 outs() << "\n"; 8514 outs() << " weak_bind_off " << dc.weak_bind_off; 8515 if (dc.weak_bind_off > object_size) 8516 outs() << " (past end of file)\n"; 8517 else 8518 outs() << "\n"; 8519 outs() << " weak_bind_size " << dc.weak_bind_size; 8520 big_size = dc.weak_bind_off; 8521 big_size += dc.weak_bind_size; 8522 if (big_size > object_size) 8523 outs() << " (past end of file)\n"; 8524 else 8525 outs() << "\n"; 8526 outs() << " lazy_bind_off " << dc.lazy_bind_off; 8527 if (dc.lazy_bind_off > object_size) 8528 outs() << " (past end of file)\n"; 8529 else 8530 outs() << "\n"; 8531 outs() << " lazy_bind_size " << dc.lazy_bind_size; 8532 big_size = dc.lazy_bind_off; 8533 big_size += dc.lazy_bind_size; 8534 if (big_size > object_size) 8535 outs() << " (past end of file)\n"; 8536 else 8537 outs() << "\n"; 8538 outs() << " export_off " << dc.export_off; 8539 if (dc.export_off > object_size) 8540 outs() << " (past end of file)\n"; 8541 else 8542 outs() << "\n"; 8543 outs() << " export_size " << dc.export_size; 8544 big_size = dc.export_off; 8545 big_size += dc.export_size; 8546 if (big_size > object_size) 8547 outs() << " (past end of file)\n"; 8548 else 8549 outs() << "\n"; 8550 } 8551 8552 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 8553 const char *Ptr) { 8554 if (dyld.cmd == MachO::LC_ID_DYLINKER) 8555 outs() << " cmd LC_ID_DYLINKER\n"; 8556 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 8557 outs() << " cmd LC_LOAD_DYLINKER\n"; 8558 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 8559 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 8560 else 8561 outs() << " cmd ?(" << dyld.cmd << ")\n"; 8562 outs() << " cmdsize " << dyld.cmdsize; 8563 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 8564 outs() << " Incorrect size\n"; 8565 else 8566 outs() << "\n"; 8567 if (dyld.name >= dyld.cmdsize) 8568 outs() << " name ?(bad offset " << dyld.name << ")\n"; 8569 else { 8570 const char *P = (const char *)(Ptr) + dyld.name; 8571 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 8572 } 8573 } 8574 8575 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 8576 outs() << " cmd LC_UUID\n"; 8577 outs() << " cmdsize " << uuid.cmdsize; 8578 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 8579 outs() << " Incorrect size\n"; 8580 else 8581 outs() << "\n"; 8582 outs() << " uuid "; 8583 for (int i = 0; i < 16; ++i) { 8584 outs() << format("%02" PRIX32, uuid.uuid[i]); 8585 if (i == 3 || i == 5 || i == 7 || i == 9) 8586 outs() << "-"; 8587 } 8588 outs() << "\n"; 8589 } 8590 8591 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 8592 outs() << " cmd LC_RPATH\n"; 8593 outs() << " cmdsize " << rpath.cmdsize; 8594 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 8595 outs() << " Incorrect size\n"; 8596 else 8597 outs() << "\n"; 8598 if (rpath.path >= rpath.cmdsize) 8599 outs() << " path ?(bad offset " << rpath.path << ")\n"; 8600 else { 8601 const char *P = (const char *)(Ptr) + rpath.path; 8602 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 8603 } 8604 } 8605 8606 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 8607 StringRef LoadCmdName; 8608 switch (vd.cmd) { 8609 case MachO::LC_VERSION_MIN_MACOSX: 8610 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 8611 break; 8612 case MachO::LC_VERSION_MIN_IPHONEOS: 8613 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 8614 break; 8615 case MachO::LC_VERSION_MIN_TVOS: 8616 LoadCmdName = "LC_VERSION_MIN_TVOS"; 8617 break; 8618 case MachO::LC_VERSION_MIN_WATCHOS: 8619 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 8620 break; 8621 default: 8622 llvm_unreachable("Unknown version min load command"); 8623 } 8624 8625 outs() << " cmd " << LoadCmdName << '\n'; 8626 outs() << " cmdsize " << vd.cmdsize; 8627 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 8628 outs() << " Incorrect size\n"; 8629 else 8630 outs() << "\n"; 8631 outs() << " version " 8632 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 8633 << MachOObjectFile::getVersionMinMinor(vd, false); 8634 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 8635 if (Update != 0) 8636 outs() << "." << Update; 8637 outs() << "\n"; 8638 if (vd.sdk == 0) 8639 outs() << " sdk n/a"; 8640 else { 8641 outs() << " sdk " 8642 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 8643 << MachOObjectFile::getVersionMinMinor(vd, true); 8644 } 8645 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 8646 if (Update != 0) 8647 outs() << "." << Update; 8648 outs() << "\n"; 8649 } 8650 8651 static void PrintNoteLoadCommand(MachO::note_command Nt) { 8652 outs() << " cmd LC_NOTE\n"; 8653 outs() << " cmdsize " << Nt.cmdsize; 8654 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 8655 outs() << " Incorrect size\n"; 8656 else 8657 outs() << "\n"; 8658 const char *d = Nt.data_owner; 8659 outs() << "data_owner " << format("%.16s\n", d); 8660 outs() << " offset " << Nt.offset << "\n"; 8661 outs() << " size " << Nt.size << "\n"; 8662 } 8663 8664 static void PrintBuildToolVersion(MachO::build_tool_version bv) { 8665 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; 8666 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 8667 << "\n"; 8668 } 8669 8670 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 8671 MachO::build_version_command bd) { 8672 outs() << " cmd LC_BUILD_VERSION\n"; 8673 outs() << " cmdsize " << bd.cmdsize; 8674 if (bd.cmdsize != 8675 sizeof(struct MachO::build_version_command) + 8676 bd.ntools * sizeof(struct MachO::build_tool_version)) 8677 outs() << " Incorrect size\n"; 8678 else 8679 outs() << "\n"; 8680 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) 8681 << "\n"; 8682 if (bd.sdk) 8683 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 8684 << "\n"; 8685 else 8686 outs() << " sdk n/a\n"; 8687 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 8688 << "\n"; 8689 outs() << " ntools " << bd.ntools << "\n"; 8690 for (unsigned i = 0; i < bd.ntools; ++i) { 8691 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 8692 PrintBuildToolVersion(bv); 8693 } 8694 } 8695 8696 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 8697 outs() << " cmd LC_SOURCE_VERSION\n"; 8698 outs() << " cmdsize " << sd.cmdsize; 8699 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 8700 outs() << " Incorrect size\n"; 8701 else 8702 outs() << "\n"; 8703 uint64_t a = (sd.version >> 40) & 0xffffff; 8704 uint64_t b = (sd.version >> 30) & 0x3ff; 8705 uint64_t c = (sd.version >> 20) & 0x3ff; 8706 uint64_t d = (sd.version >> 10) & 0x3ff; 8707 uint64_t e = sd.version & 0x3ff; 8708 outs() << " version " << a << "." << b; 8709 if (e != 0) 8710 outs() << "." << c << "." << d << "." << e; 8711 else if (d != 0) 8712 outs() << "." << c << "." << d; 8713 else if (c != 0) 8714 outs() << "." << c; 8715 outs() << "\n"; 8716 } 8717 8718 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 8719 outs() << " cmd LC_MAIN\n"; 8720 outs() << " cmdsize " << ep.cmdsize; 8721 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 8722 outs() << " Incorrect size\n"; 8723 else 8724 outs() << "\n"; 8725 outs() << " entryoff " << ep.entryoff << "\n"; 8726 outs() << " stacksize " << ep.stacksize << "\n"; 8727 } 8728 8729 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 8730 uint32_t object_size) { 8731 outs() << " cmd LC_ENCRYPTION_INFO\n"; 8732 outs() << " cmdsize " << ec.cmdsize; 8733 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 8734 outs() << " Incorrect size\n"; 8735 else 8736 outs() << "\n"; 8737 outs() << " cryptoff " << ec.cryptoff; 8738 if (ec.cryptoff > object_size) 8739 outs() << " (past end of file)\n"; 8740 else 8741 outs() << "\n"; 8742 outs() << " cryptsize " << ec.cryptsize; 8743 if (ec.cryptsize > object_size) 8744 outs() << " (past end of file)\n"; 8745 else 8746 outs() << "\n"; 8747 outs() << " cryptid " << ec.cryptid << "\n"; 8748 } 8749 8750 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 8751 uint32_t object_size) { 8752 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 8753 outs() << " cmdsize " << ec.cmdsize; 8754 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 8755 outs() << " Incorrect size\n"; 8756 else 8757 outs() << "\n"; 8758 outs() << " cryptoff " << ec.cryptoff; 8759 if (ec.cryptoff > object_size) 8760 outs() << " (past end of file)\n"; 8761 else 8762 outs() << "\n"; 8763 outs() << " cryptsize " << ec.cryptsize; 8764 if (ec.cryptsize > object_size) 8765 outs() << " (past end of file)\n"; 8766 else 8767 outs() << "\n"; 8768 outs() << " cryptid " << ec.cryptid << "\n"; 8769 outs() << " pad " << ec.pad << "\n"; 8770 } 8771 8772 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 8773 const char *Ptr) { 8774 outs() << " cmd LC_LINKER_OPTION\n"; 8775 outs() << " cmdsize " << lo.cmdsize; 8776 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 8777 outs() << " Incorrect size\n"; 8778 else 8779 outs() << "\n"; 8780 outs() << " count " << lo.count << "\n"; 8781 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 8782 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 8783 uint32_t i = 0; 8784 while (left > 0) { 8785 while (*string == '\0' && left > 0) { 8786 string++; 8787 left--; 8788 } 8789 if (left > 0) { 8790 i++; 8791 outs() << " string #" << i << " " << format("%.*s\n", left, string); 8792 uint32_t NullPos = StringRef(string, left).find('\0'); 8793 uint32_t len = std::min(NullPos, left) + 1; 8794 string += len; 8795 left -= len; 8796 } 8797 } 8798 if (lo.count != i) 8799 outs() << " count " << lo.count << " does not match number of strings " 8800 << i << "\n"; 8801 } 8802 8803 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 8804 const char *Ptr) { 8805 outs() << " cmd LC_SUB_FRAMEWORK\n"; 8806 outs() << " cmdsize " << sub.cmdsize; 8807 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 8808 outs() << " Incorrect size\n"; 8809 else 8810 outs() << "\n"; 8811 if (sub.umbrella < sub.cmdsize) { 8812 const char *P = Ptr + sub.umbrella; 8813 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 8814 } else { 8815 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 8816 } 8817 } 8818 8819 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 8820 const char *Ptr) { 8821 outs() << " cmd LC_SUB_UMBRELLA\n"; 8822 outs() << " cmdsize " << sub.cmdsize; 8823 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 8824 outs() << " Incorrect size\n"; 8825 else 8826 outs() << "\n"; 8827 if (sub.sub_umbrella < sub.cmdsize) { 8828 const char *P = Ptr + sub.sub_umbrella; 8829 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 8830 } else { 8831 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 8832 } 8833 } 8834 8835 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 8836 const char *Ptr) { 8837 outs() << " cmd LC_SUB_LIBRARY\n"; 8838 outs() << " cmdsize " << sub.cmdsize; 8839 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 8840 outs() << " Incorrect size\n"; 8841 else 8842 outs() << "\n"; 8843 if (sub.sub_library < sub.cmdsize) { 8844 const char *P = Ptr + sub.sub_library; 8845 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 8846 } else { 8847 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 8848 } 8849 } 8850 8851 static void PrintSubClientCommand(MachO::sub_client_command sub, 8852 const char *Ptr) { 8853 outs() << " cmd LC_SUB_CLIENT\n"; 8854 outs() << " cmdsize " << sub.cmdsize; 8855 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 8856 outs() << " Incorrect size\n"; 8857 else 8858 outs() << "\n"; 8859 if (sub.client < sub.cmdsize) { 8860 const char *P = Ptr + sub.client; 8861 outs() << " client " << P << " (offset " << sub.client << ")\n"; 8862 } else { 8863 outs() << " client ?(bad offset " << sub.client << ")\n"; 8864 } 8865 } 8866 8867 static void PrintRoutinesCommand(MachO::routines_command r) { 8868 outs() << " cmd LC_ROUTINES\n"; 8869 outs() << " cmdsize " << r.cmdsize; 8870 if (r.cmdsize != sizeof(struct MachO::routines_command)) 8871 outs() << " Incorrect size\n"; 8872 else 8873 outs() << "\n"; 8874 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 8875 outs() << " init_module " << r.init_module << "\n"; 8876 outs() << " reserved1 " << r.reserved1 << "\n"; 8877 outs() << " reserved2 " << r.reserved2 << "\n"; 8878 outs() << " reserved3 " << r.reserved3 << "\n"; 8879 outs() << " reserved4 " << r.reserved4 << "\n"; 8880 outs() << " reserved5 " << r.reserved5 << "\n"; 8881 outs() << " reserved6 " << r.reserved6 << "\n"; 8882 } 8883 8884 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 8885 outs() << " cmd LC_ROUTINES_64\n"; 8886 outs() << " cmdsize " << r.cmdsize; 8887 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 8888 outs() << " Incorrect size\n"; 8889 else 8890 outs() << "\n"; 8891 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 8892 outs() << " init_module " << r.init_module << "\n"; 8893 outs() << " reserved1 " << r.reserved1 << "\n"; 8894 outs() << " reserved2 " << r.reserved2 << "\n"; 8895 outs() << " reserved3 " << r.reserved3 << "\n"; 8896 outs() << " reserved4 " << r.reserved4 << "\n"; 8897 outs() << " reserved5 " << r.reserved5 << "\n"; 8898 outs() << " reserved6 " << r.reserved6 << "\n"; 8899 } 8900 8901 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 8902 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 8903 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 8904 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 8905 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 8906 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 8907 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 8908 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 8909 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 8910 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 8911 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 8912 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 8913 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 8914 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 8915 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 8916 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 8917 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 8918 } 8919 8920 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 8921 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 8922 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 8923 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 8924 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 8925 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 8926 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 8927 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 8928 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 8929 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 8930 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 8931 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 8932 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 8933 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 8934 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 8935 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 8936 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 8937 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 8938 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 8939 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 8940 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 8941 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 8942 } 8943 8944 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 8945 uint32_t f; 8946 outs() << "\t mmst_reg "; 8947 for (f = 0; f < 10; f++) 8948 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 8949 outs() << "\n"; 8950 outs() << "\t mmst_rsrv "; 8951 for (f = 0; f < 6; f++) 8952 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 8953 outs() << "\n"; 8954 } 8955 8956 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 8957 uint32_t f; 8958 outs() << "\t xmm_reg "; 8959 for (f = 0; f < 16; f++) 8960 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 8961 outs() << "\n"; 8962 } 8963 8964 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 8965 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 8966 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 8967 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 8968 outs() << " denorm " << fpu.fpu_fcw.denorm; 8969 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 8970 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 8971 outs() << " undfl " << fpu.fpu_fcw.undfl; 8972 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 8973 outs() << "\t\t pc "; 8974 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 8975 outs() << "FP_PREC_24B "; 8976 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 8977 outs() << "FP_PREC_53B "; 8978 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 8979 outs() << "FP_PREC_64B "; 8980 else 8981 outs() << fpu.fpu_fcw.pc << " "; 8982 outs() << "rc "; 8983 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 8984 outs() << "FP_RND_NEAR "; 8985 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 8986 outs() << "FP_RND_DOWN "; 8987 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 8988 outs() << "FP_RND_UP "; 8989 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 8990 outs() << "FP_CHOP "; 8991 outs() << "\n"; 8992 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 8993 outs() << " denorm " << fpu.fpu_fsw.denorm; 8994 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 8995 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 8996 outs() << " undfl " << fpu.fpu_fsw.undfl; 8997 outs() << " precis " << fpu.fpu_fsw.precis; 8998 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 8999 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9000 outs() << " c0 " << fpu.fpu_fsw.c0; 9001 outs() << " c1 " << fpu.fpu_fsw.c1; 9002 outs() << " c2 " << fpu.fpu_fsw.c2; 9003 outs() << " tos " << fpu.fpu_fsw.tos; 9004 outs() << " c3 " << fpu.fpu_fsw.c3; 9005 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9006 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9007 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9008 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9009 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9010 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9011 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9012 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9013 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9014 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9015 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9016 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9017 outs() << "\n"; 9018 outs() << "\t fpu_stmm0:\n"; 9019 Print_mmst_reg(fpu.fpu_stmm0); 9020 outs() << "\t fpu_stmm1:\n"; 9021 Print_mmst_reg(fpu.fpu_stmm1); 9022 outs() << "\t fpu_stmm2:\n"; 9023 Print_mmst_reg(fpu.fpu_stmm2); 9024 outs() << "\t fpu_stmm3:\n"; 9025 Print_mmst_reg(fpu.fpu_stmm3); 9026 outs() << "\t fpu_stmm4:\n"; 9027 Print_mmst_reg(fpu.fpu_stmm4); 9028 outs() << "\t fpu_stmm5:\n"; 9029 Print_mmst_reg(fpu.fpu_stmm5); 9030 outs() << "\t fpu_stmm6:\n"; 9031 Print_mmst_reg(fpu.fpu_stmm6); 9032 outs() << "\t fpu_stmm7:\n"; 9033 Print_mmst_reg(fpu.fpu_stmm7); 9034 outs() << "\t fpu_xmm0:\n"; 9035 Print_xmm_reg(fpu.fpu_xmm0); 9036 outs() << "\t fpu_xmm1:\n"; 9037 Print_xmm_reg(fpu.fpu_xmm1); 9038 outs() << "\t fpu_xmm2:\n"; 9039 Print_xmm_reg(fpu.fpu_xmm2); 9040 outs() << "\t fpu_xmm3:\n"; 9041 Print_xmm_reg(fpu.fpu_xmm3); 9042 outs() << "\t fpu_xmm4:\n"; 9043 Print_xmm_reg(fpu.fpu_xmm4); 9044 outs() << "\t fpu_xmm5:\n"; 9045 Print_xmm_reg(fpu.fpu_xmm5); 9046 outs() << "\t fpu_xmm6:\n"; 9047 Print_xmm_reg(fpu.fpu_xmm6); 9048 outs() << "\t fpu_xmm7:\n"; 9049 Print_xmm_reg(fpu.fpu_xmm7); 9050 outs() << "\t fpu_xmm8:\n"; 9051 Print_xmm_reg(fpu.fpu_xmm8); 9052 outs() << "\t fpu_xmm9:\n"; 9053 Print_xmm_reg(fpu.fpu_xmm9); 9054 outs() << "\t fpu_xmm10:\n"; 9055 Print_xmm_reg(fpu.fpu_xmm10); 9056 outs() << "\t fpu_xmm11:\n"; 9057 Print_xmm_reg(fpu.fpu_xmm11); 9058 outs() << "\t fpu_xmm12:\n"; 9059 Print_xmm_reg(fpu.fpu_xmm12); 9060 outs() << "\t fpu_xmm13:\n"; 9061 Print_xmm_reg(fpu.fpu_xmm13); 9062 outs() << "\t fpu_xmm14:\n"; 9063 Print_xmm_reg(fpu.fpu_xmm14); 9064 outs() << "\t fpu_xmm15:\n"; 9065 Print_xmm_reg(fpu.fpu_xmm15); 9066 outs() << "\t fpu_rsrv4:\n"; 9067 for (uint32_t f = 0; f < 6; f++) { 9068 outs() << "\t "; 9069 for (uint32_t g = 0; g < 16; g++) 9070 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9071 outs() << "\n"; 9072 } 9073 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9074 outs() << "\n"; 9075 } 9076 9077 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9078 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9079 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9080 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9081 } 9082 9083 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9084 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9085 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9086 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9087 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9088 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9089 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9090 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9091 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9092 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9093 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9094 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9095 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9096 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9097 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9098 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9099 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9100 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9101 } 9102 9103 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9104 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9105 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9106 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9107 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9108 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9109 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9110 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9111 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9112 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9113 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9114 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9115 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9116 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9117 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9118 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9119 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9120 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9121 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9122 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9123 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9124 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9125 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9126 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9127 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9128 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9129 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9130 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9131 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9132 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9133 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9134 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9135 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9136 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9137 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9138 } 9139 9140 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9141 bool isLittleEndian, uint32_t cputype) { 9142 if (t.cmd == MachO::LC_THREAD) 9143 outs() << " cmd LC_THREAD\n"; 9144 else if (t.cmd == MachO::LC_UNIXTHREAD) 9145 outs() << " cmd LC_UNIXTHREAD\n"; 9146 else 9147 outs() << " cmd " << t.cmd << " (unknown)\n"; 9148 outs() << " cmdsize " << t.cmdsize; 9149 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9150 outs() << " Incorrect size\n"; 9151 else 9152 outs() << "\n"; 9153 9154 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9155 const char *end = Ptr + t.cmdsize; 9156 uint32_t flavor, count, left; 9157 if (cputype == MachO::CPU_TYPE_I386) { 9158 while (begin < end) { 9159 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9160 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9161 begin += sizeof(uint32_t); 9162 } else { 9163 flavor = 0; 9164 begin = end; 9165 } 9166 if (isLittleEndian != sys::IsLittleEndianHost) 9167 sys::swapByteOrder(flavor); 9168 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9169 memcpy((char *)&count, begin, sizeof(uint32_t)); 9170 begin += sizeof(uint32_t); 9171 } else { 9172 count = 0; 9173 begin = end; 9174 } 9175 if (isLittleEndian != sys::IsLittleEndianHost) 9176 sys::swapByteOrder(count); 9177 if (flavor == MachO::x86_THREAD_STATE32) { 9178 outs() << " flavor i386_THREAD_STATE\n"; 9179 if (count == MachO::x86_THREAD_STATE32_COUNT) 9180 outs() << " count i386_THREAD_STATE_COUNT\n"; 9181 else 9182 outs() << " count " << count 9183 << " (not x86_THREAD_STATE32_COUNT)\n"; 9184 MachO::x86_thread_state32_t cpu32; 9185 left = end - begin; 9186 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9187 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9188 begin += sizeof(MachO::x86_thread_state32_t); 9189 } else { 9190 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9191 memcpy(&cpu32, begin, left); 9192 begin += left; 9193 } 9194 if (isLittleEndian != sys::IsLittleEndianHost) 9195 swapStruct(cpu32); 9196 Print_x86_thread_state32_t(cpu32); 9197 } else if (flavor == MachO::x86_THREAD_STATE) { 9198 outs() << " flavor x86_THREAD_STATE\n"; 9199 if (count == MachO::x86_THREAD_STATE_COUNT) 9200 outs() << " count x86_THREAD_STATE_COUNT\n"; 9201 else 9202 outs() << " count " << count 9203 << " (not x86_THREAD_STATE_COUNT)\n"; 9204 struct MachO::x86_thread_state_t ts; 9205 left = end - begin; 9206 if (left >= sizeof(MachO::x86_thread_state_t)) { 9207 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9208 begin += sizeof(MachO::x86_thread_state_t); 9209 } else { 9210 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9211 memcpy(&ts, begin, left); 9212 begin += left; 9213 } 9214 if (isLittleEndian != sys::IsLittleEndianHost) 9215 swapStruct(ts); 9216 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9217 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9218 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9219 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9220 else 9221 outs() << "tsh.count " << ts.tsh.count 9222 << " (not x86_THREAD_STATE32_COUNT\n"; 9223 Print_x86_thread_state32_t(ts.uts.ts32); 9224 } else { 9225 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9226 << ts.tsh.count << "\n"; 9227 } 9228 } else { 9229 outs() << " flavor " << flavor << " (unknown)\n"; 9230 outs() << " count " << count << "\n"; 9231 outs() << " state (unknown)\n"; 9232 begin += count * sizeof(uint32_t); 9233 } 9234 } 9235 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9236 while (begin < end) { 9237 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9238 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9239 begin += sizeof(uint32_t); 9240 } else { 9241 flavor = 0; 9242 begin = end; 9243 } 9244 if (isLittleEndian != sys::IsLittleEndianHost) 9245 sys::swapByteOrder(flavor); 9246 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9247 memcpy((char *)&count, begin, sizeof(uint32_t)); 9248 begin += sizeof(uint32_t); 9249 } else { 9250 count = 0; 9251 begin = end; 9252 } 9253 if (isLittleEndian != sys::IsLittleEndianHost) 9254 sys::swapByteOrder(count); 9255 if (flavor == MachO::x86_THREAD_STATE64) { 9256 outs() << " flavor x86_THREAD_STATE64\n"; 9257 if (count == MachO::x86_THREAD_STATE64_COUNT) 9258 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9259 else 9260 outs() << " count " << count 9261 << " (not x86_THREAD_STATE64_COUNT)\n"; 9262 MachO::x86_thread_state64_t cpu64; 9263 left = end - begin; 9264 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9265 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9266 begin += sizeof(MachO::x86_thread_state64_t); 9267 } else { 9268 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9269 memcpy(&cpu64, begin, left); 9270 begin += left; 9271 } 9272 if (isLittleEndian != sys::IsLittleEndianHost) 9273 swapStruct(cpu64); 9274 Print_x86_thread_state64_t(cpu64); 9275 } else if (flavor == MachO::x86_THREAD_STATE) { 9276 outs() << " flavor x86_THREAD_STATE\n"; 9277 if (count == MachO::x86_THREAD_STATE_COUNT) 9278 outs() << " count x86_THREAD_STATE_COUNT\n"; 9279 else 9280 outs() << " count " << count 9281 << " (not x86_THREAD_STATE_COUNT)\n"; 9282 struct MachO::x86_thread_state_t ts; 9283 left = end - begin; 9284 if (left >= sizeof(MachO::x86_thread_state_t)) { 9285 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9286 begin += sizeof(MachO::x86_thread_state_t); 9287 } else { 9288 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9289 memcpy(&ts, begin, left); 9290 begin += left; 9291 } 9292 if (isLittleEndian != sys::IsLittleEndianHost) 9293 swapStruct(ts); 9294 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9295 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9296 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9297 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9298 else 9299 outs() << "tsh.count " << ts.tsh.count 9300 << " (not x86_THREAD_STATE64_COUNT\n"; 9301 Print_x86_thread_state64_t(ts.uts.ts64); 9302 } else { 9303 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9304 << ts.tsh.count << "\n"; 9305 } 9306 } else if (flavor == MachO::x86_FLOAT_STATE) { 9307 outs() << " flavor x86_FLOAT_STATE\n"; 9308 if (count == MachO::x86_FLOAT_STATE_COUNT) 9309 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9310 else 9311 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9312 struct MachO::x86_float_state_t fs; 9313 left = end - begin; 9314 if (left >= sizeof(MachO::x86_float_state_t)) { 9315 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9316 begin += sizeof(MachO::x86_float_state_t); 9317 } else { 9318 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9319 memcpy(&fs, begin, left); 9320 begin += left; 9321 } 9322 if (isLittleEndian != sys::IsLittleEndianHost) 9323 swapStruct(fs); 9324 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9325 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9326 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9327 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9328 else 9329 outs() << "fsh.count " << fs.fsh.count 9330 << " (not x86_FLOAT_STATE64_COUNT\n"; 9331 Print_x86_float_state_t(fs.ufs.fs64); 9332 } else { 9333 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9334 << fs.fsh.count << "\n"; 9335 } 9336 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9337 outs() << " flavor x86_EXCEPTION_STATE\n"; 9338 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9339 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9340 else 9341 outs() << " count " << count 9342 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9343 struct MachO::x86_exception_state_t es; 9344 left = end - begin; 9345 if (left >= sizeof(MachO::x86_exception_state_t)) { 9346 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9347 begin += sizeof(MachO::x86_exception_state_t); 9348 } else { 9349 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9350 memcpy(&es, begin, left); 9351 begin += left; 9352 } 9353 if (isLittleEndian != sys::IsLittleEndianHost) 9354 swapStruct(es); 9355 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9356 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9357 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9358 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9359 else 9360 outs() << "\t esh.count " << es.esh.count 9361 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9362 Print_x86_exception_state_t(es.ues.es64); 9363 } else { 9364 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9365 << es.esh.count << "\n"; 9366 } 9367 } else if (flavor == MachO::x86_EXCEPTION_STATE64) { 9368 outs() << " flavor x86_EXCEPTION_STATE64\n"; 9369 if (count == MachO::x86_EXCEPTION_STATE64_COUNT) 9370 outs() << " count x86_EXCEPTION_STATE64_COUNT\n"; 9371 else 9372 outs() << " count " << count 9373 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; 9374 struct MachO::x86_exception_state64_t es64; 9375 left = end - begin; 9376 if (left >= sizeof(MachO::x86_exception_state64_t)) { 9377 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); 9378 begin += sizeof(MachO::x86_exception_state64_t); 9379 } else { 9380 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); 9381 memcpy(&es64, begin, left); 9382 begin += left; 9383 } 9384 if (isLittleEndian != sys::IsLittleEndianHost) 9385 swapStruct(es64); 9386 Print_x86_exception_state_t(es64); 9387 } else { 9388 outs() << " flavor " << flavor << " (unknown)\n"; 9389 outs() << " count " << count << "\n"; 9390 outs() << " state (unknown)\n"; 9391 begin += count * sizeof(uint32_t); 9392 } 9393 } 9394 } else if (cputype == MachO::CPU_TYPE_ARM) { 9395 while (begin < end) { 9396 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9397 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9398 begin += sizeof(uint32_t); 9399 } else { 9400 flavor = 0; 9401 begin = end; 9402 } 9403 if (isLittleEndian != sys::IsLittleEndianHost) 9404 sys::swapByteOrder(flavor); 9405 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9406 memcpy((char *)&count, begin, sizeof(uint32_t)); 9407 begin += sizeof(uint32_t); 9408 } else { 9409 count = 0; 9410 begin = end; 9411 } 9412 if (isLittleEndian != sys::IsLittleEndianHost) 9413 sys::swapByteOrder(count); 9414 if (flavor == MachO::ARM_THREAD_STATE) { 9415 outs() << " flavor ARM_THREAD_STATE\n"; 9416 if (count == MachO::ARM_THREAD_STATE_COUNT) 9417 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9418 else 9419 outs() << " count " << count 9420 << " (not ARM_THREAD_STATE_COUNT)\n"; 9421 MachO::arm_thread_state32_t cpu32; 9422 left = end - begin; 9423 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9424 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9425 begin += sizeof(MachO::arm_thread_state32_t); 9426 } else { 9427 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9428 memcpy(&cpu32, begin, left); 9429 begin += left; 9430 } 9431 if (isLittleEndian != sys::IsLittleEndianHost) 9432 swapStruct(cpu32); 9433 Print_arm_thread_state32_t(cpu32); 9434 } else { 9435 outs() << " flavor " << flavor << " (unknown)\n"; 9436 outs() << " count " << count << "\n"; 9437 outs() << " state (unknown)\n"; 9438 begin += count * sizeof(uint32_t); 9439 } 9440 } 9441 } else if (cputype == MachO::CPU_TYPE_ARM64) { 9442 while (begin < end) { 9443 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9444 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9445 begin += sizeof(uint32_t); 9446 } else { 9447 flavor = 0; 9448 begin = end; 9449 } 9450 if (isLittleEndian != sys::IsLittleEndianHost) 9451 sys::swapByteOrder(flavor); 9452 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9453 memcpy((char *)&count, begin, sizeof(uint32_t)); 9454 begin += sizeof(uint32_t); 9455 } else { 9456 count = 0; 9457 begin = end; 9458 } 9459 if (isLittleEndian != sys::IsLittleEndianHost) 9460 sys::swapByteOrder(count); 9461 if (flavor == MachO::ARM_THREAD_STATE64) { 9462 outs() << " flavor ARM_THREAD_STATE64\n"; 9463 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9464 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9465 else 9466 outs() << " count " << count 9467 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9468 MachO::arm_thread_state64_t cpu64; 9469 left = end - begin; 9470 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9471 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9472 begin += sizeof(MachO::arm_thread_state64_t); 9473 } else { 9474 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9475 memcpy(&cpu64, begin, left); 9476 begin += left; 9477 } 9478 if (isLittleEndian != sys::IsLittleEndianHost) 9479 swapStruct(cpu64); 9480 Print_arm_thread_state64_t(cpu64); 9481 } else { 9482 outs() << " flavor " << flavor << " (unknown)\n"; 9483 outs() << " count " << count << "\n"; 9484 outs() << " state (unknown)\n"; 9485 begin += count * sizeof(uint32_t); 9486 } 9487 } 9488 } else { 9489 while (begin < end) { 9490 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9491 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9492 begin += sizeof(uint32_t); 9493 } else { 9494 flavor = 0; 9495 begin = end; 9496 } 9497 if (isLittleEndian != sys::IsLittleEndianHost) 9498 sys::swapByteOrder(flavor); 9499 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9500 memcpy((char *)&count, begin, sizeof(uint32_t)); 9501 begin += sizeof(uint32_t); 9502 } else { 9503 count = 0; 9504 begin = end; 9505 } 9506 if (isLittleEndian != sys::IsLittleEndianHost) 9507 sys::swapByteOrder(count); 9508 outs() << " flavor " << flavor << "\n"; 9509 outs() << " count " << count << "\n"; 9510 outs() << " state (Unknown cputype/cpusubtype)\n"; 9511 begin += count * sizeof(uint32_t); 9512 } 9513 } 9514 } 9515 9516 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 9517 if (dl.cmd == MachO::LC_ID_DYLIB) 9518 outs() << " cmd LC_ID_DYLIB\n"; 9519 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 9520 outs() << " cmd LC_LOAD_DYLIB\n"; 9521 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 9522 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 9523 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 9524 outs() << " cmd LC_REEXPORT_DYLIB\n"; 9525 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 9526 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 9527 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 9528 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 9529 else 9530 outs() << " cmd " << dl.cmd << " (unknown)\n"; 9531 outs() << " cmdsize " << dl.cmdsize; 9532 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 9533 outs() << " Incorrect size\n"; 9534 else 9535 outs() << "\n"; 9536 if (dl.dylib.name < dl.cmdsize) { 9537 const char *P = (const char *)(Ptr) + dl.dylib.name; 9538 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 9539 } else { 9540 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 9541 } 9542 outs() << " time stamp " << dl.dylib.timestamp << " "; 9543 time_t t = dl.dylib.timestamp; 9544 outs() << ctime(&t); 9545 outs() << " current version "; 9546 if (dl.dylib.current_version == 0xffffffff) 9547 outs() << "n/a\n"; 9548 else 9549 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 9550 << ((dl.dylib.current_version >> 8) & 0xff) << "." 9551 << (dl.dylib.current_version & 0xff) << "\n"; 9552 outs() << "compatibility version "; 9553 if (dl.dylib.compatibility_version == 0xffffffff) 9554 outs() << "n/a\n"; 9555 else 9556 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 9557 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 9558 << (dl.dylib.compatibility_version & 0xff) << "\n"; 9559 } 9560 9561 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 9562 uint32_t object_size) { 9563 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 9564 outs() << " cmd LC_CODE_SIGNATURE\n"; 9565 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 9566 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 9567 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 9568 outs() << " cmd LC_FUNCTION_STARTS\n"; 9569 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 9570 outs() << " cmd LC_DATA_IN_CODE\n"; 9571 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 9572 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 9573 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 9574 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 9575 else 9576 outs() << " cmd " << ld.cmd << " (?)\n"; 9577 outs() << " cmdsize " << ld.cmdsize; 9578 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 9579 outs() << " Incorrect size\n"; 9580 else 9581 outs() << "\n"; 9582 outs() << " dataoff " << ld.dataoff; 9583 if (ld.dataoff > object_size) 9584 outs() << " (past end of file)\n"; 9585 else 9586 outs() << "\n"; 9587 outs() << " datasize " << ld.datasize; 9588 uint64_t big_size = ld.dataoff; 9589 big_size += ld.datasize; 9590 if (big_size > object_size) 9591 outs() << " (past end of file)\n"; 9592 else 9593 outs() << "\n"; 9594 } 9595 9596 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 9597 uint32_t cputype, bool verbose) { 9598 StringRef Buf = Obj->getData(); 9599 unsigned Index = 0; 9600 for (const auto &Command : Obj->load_commands()) { 9601 outs() << "Load command " << Index++ << "\n"; 9602 if (Command.C.cmd == MachO::LC_SEGMENT) { 9603 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 9604 const char *sg_segname = SLC.segname; 9605 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 9606 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 9607 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 9608 verbose); 9609 for (unsigned j = 0; j < SLC.nsects; j++) { 9610 MachO::section S = Obj->getSection(Command, j); 9611 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 9612 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 9613 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 9614 } 9615 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9616 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 9617 const char *sg_segname = SLC_64.segname; 9618 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 9619 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 9620 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 9621 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 9622 for (unsigned j = 0; j < SLC_64.nsects; j++) { 9623 MachO::section_64 S_64 = Obj->getSection64(Command, j); 9624 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 9625 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 9626 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 9627 sg_segname, filetype, Buf.size(), verbose); 9628 } 9629 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 9630 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9631 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 9632 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 9633 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 9634 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9635 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 9636 Obj->is64Bit()); 9637 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 9638 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 9639 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 9640 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 9641 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 9642 Command.C.cmd == MachO::LC_ID_DYLINKER || 9643 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 9644 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 9645 PrintDyldLoadCommand(Dyld, Command.Ptr); 9646 } else if (Command.C.cmd == MachO::LC_UUID) { 9647 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 9648 PrintUuidLoadCommand(Uuid); 9649 } else if (Command.C.cmd == MachO::LC_RPATH) { 9650 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 9651 PrintRpathLoadCommand(Rpath, Command.Ptr); 9652 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 9653 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 9654 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 9655 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 9656 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 9657 PrintVersionMinLoadCommand(Vd); 9658 } else if (Command.C.cmd == MachO::LC_NOTE) { 9659 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 9660 PrintNoteLoadCommand(Nt); 9661 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 9662 MachO::build_version_command Bv = 9663 Obj->getBuildVersionLoadCommand(Command); 9664 PrintBuildVersionLoadCommand(Obj, Bv); 9665 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 9666 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 9667 PrintSourceVersionCommand(Sd); 9668 } else if (Command.C.cmd == MachO::LC_MAIN) { 9669 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 9670 PrintEntryPointCommand(Ep); 9671 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 9672 MachO::encryption_info_command Ei = 9673 Obj->getEncryptionInfoCommand(Command); 9674 PrintEncryptionInfoCommand(Ei, Buf.size()); 9675 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 9676 MachO::encryption_info_command_64 Ei = 9677 Obj->getEncryptionInfoCommand64(Command); 9678 PrintEncryptionInfoCommand64(Ei, Buf.size()); 9679 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 9680 MachO::linker_option_command Lo = 9681 Obj->getLinkerOptionLoadCommand(Command); 9682 PrintLinkerOptionCommand(Lo, Command.Ptr); 9683 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 9684 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 9685 PrintSubFrameworkCommand(Sf, Command.Ptr); 9686 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 9687 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 9688 PrintSubUmbrellaCommand(Sf, Command.Ptr); 9689 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 9690 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 9691 PrintSubLibraryCommand(Sl, Command.Ptr); 9692 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 9693 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 9694 PrintSubClientCommand(Sc, Command.Ptr); 9695 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 9696 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 9697 PrintRoutinesCommand(Rc); 9698 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 9699 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 9700 PrintRoutinesCommand64(Rc); 9701 } else if (Command.C.cmd == MachO::LC_THREAD || 9702 Command.C.cmd == MachO::LC_UNIXTHREAD) { 9703 MachO::thread_command Tc = Obj->getThreadCommand(Command); 9704 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 9705 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 9706 Command.C.cmd == MachO::LC_ID_DYLIB || 9707 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 9708 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 9709 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 9710 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 9711 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 9712 PrintDylibCommand(Dl, Command.Ptr); 9713 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 9714 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 9715 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 9716 Command.C.cmd == MachO::LC_DATA_IN_CODE || 9717 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 9718 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 9719 MachO::linkedit_data_command Ld = 9720 Obj->getLinkeditDataLoadCommand(Command); 9721 PrintLinkEditDataCommand(Ld, Buf.size()); 9722 } else { 9723 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 9724 << ")\n"; 9725 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 9726 // TODO: get and print the raw bytes of the load command. 9727 } 9728 // TODO: print all the other kinds of load commands. 9729 } 9730 } 9731 9732 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 9733 if (Obj->is64Bit()) { 9734 MachO::mach_header_64 H_64; 9735 H_64 = Obj->getHeader64(); 9736 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 9737 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 9738 } else { 9739 MachO::mach_header H; 9740 H = Obj->getHeader(); 9741 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 9742 H.sizeofcmds, H.flags, verbose); 9743 } 9744 } 9745 9746 void llvm::printMachOFileHeader(const object::ObjectFile *Obj) { 9747 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9748 PrintMachHeader(file, !NonVerbose); 9749 } 9750 9751 void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) { 9752 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9753 uint32_t filetype = 0; 9754 uint32_t cputype = 0; 9755 if (file->is64Bit()) { 9756 MachO::mach_header_64 H_64; 9757 H_64 = file->getHeader64(); 9758 filetype = H_64.filetype; 9759 cputype = H_64.cputype; 9760 } else { 9761 MachO::mach_header H; 9762 H = file->getHeader(); 9763 filetype = H.filetype; 9764 cputype = H.cputype; 9765 } 9766 PrintLoadCommands(file, filetype, cputype, !NonVerbose); 9767 } 9768 9769 //===----------------------------------------------------------------------===// 9770 // export trie dumping 9771 //===----------------------------------------------------------------------===// 9772 9773 void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) { 9774 uint64_t BaseSegmentAddress = 0; 9775 for (const auto &Command : Obj->load_commands()) { 9776 if (Command.C.cmd == MachO::LC_SEGMENT) { 9777 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 9778 if (Seg.fileoff == 0 && Seg.filesize != 0) { 9779 BaseSegmentAddress = Seg.vmaddr; 9780 break; 9781 } 9782 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9783 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 9784 if (Seg.fileoff == 0 && Seg.filesize != 0) { 9785 BaseSegmentAddress = Seg.vmaddr; 9786 break; 9787 } 9788 } 9789 } 9790 Error Err = Error::success(); 9791 for (const llvm::object::ExportEntry &Entry : Obj->exports(Err)) { 9792 uint64_t Flags = Entry.flags(); 9793 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 9794 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 9795 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9796 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 9797 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9798 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 9799 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 9800 if (ReExport) 9801 outs() << "[re-export] "; 9802 else 9803 outs() << format("0x%08llX ", 9804 Entry.address() + BaseSegmentAddress); 9805 outs() << Entry.name(); 9806 if (WeakDef || ThreadLocal || Resolver || Abs) { 9807 bool NeedsComma = false; 9808 outs() << " ["; 9809 if (WeakDef) { 9810 outs() << "weak_def"; 9811 NeedsComma = true; 9812 } 9813 if (ThreadLocal) { 9814 if (NeedsComma) 9815 outs() << ", "; 9816 outs() << "per-thread"; 9817 NeedsComma = true; 9818 } 9819 if (Abs) { 9820 if (NeedsComma) 9821 outs() << ", "; 9822 outs() << "absolute"; 9823 NeedsComma = true; 9824 } 9825 if (Resolver) { 9826 if (NeedsComma) 9827 outs() << ", "; 9828 outs() << format("resolver=0x%08llX", Entry.other()); 9829 NeedsComma = true; 9830 } 9831 outs() << "]"; 9832 } 9833 if (ReExport) { 9834 StringRef DylibName = "unknown"; 9835 int Ordinal = Entry.other() - 1; 9836 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 9837 if (Entry.otherName().empty()) 9838 outs() << " (from " << DylibName << ")"; 9839 else 9840 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 9841 } 9842 outs() << "\n"; 9843 } 9844 if (Err) 9845 report_error(Obj->getFileName(), std::move(Err)); 9846 } 9847 9848 //===----------------------------------------------------------------------===// 9849 // rebase table dumping 9850 //===----------------------------------------------------------------------===// 9851 9852 void llvm::printMachORebaseTable(object::MachOObjectFile *Obj) { 9853 outs() << "segment section address type\n"; 9854 Error Err = Error::success(); 9855 for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 9856 StringRef SegmentName = Entry.segmentName(); 9857 StringRef SectionName = Entry.sectionName(); 9858 uint64_t Address = Entry.address(); 9859 9860 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 9861 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 9862 SegmentName.str().c_str(), SectionName.str().c_str(), 9863 Address, Entry.typeName().str().c_str()); 9864 } 9865 if (Err) 9866 report_error(Obj->getFileName(), std::move(Err)); 9867 } 9868 9869 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 9870 StringRef DylibName; 9871 switch (Ordinal) { 9872 case MachO::BIND_SPECIAL_DYLIB_SELF: 9873 return "this-image"; 9874 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 9875 return "main-executable"; 9876 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 9877 return "flat-namespace"; 9878 default: 9879 if (Ordinal > 0) { 9880 std::error_code EC = 9881 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 9882 if (EC) 9883 return "<<bad library ordinal>>"; 9884 return DylibName; 9885 } 9886 } 9887 return "<<unknown special ordinal>>"; 9888 } 9889 9890 //===----------------------------------------------------------------------===// 9891 // bind table dumping 9892 //===----------------------------------------------------------------------===// 9893 9894 void llvm::printMachOBindTable(object::MachOObjectFile *Obj) { 9895 // Build table of sections so names can used in final output. 9896 outs() << "segment section address type " 9897 "addend dylib symbol\n"; 9898 Error Err = Error::success(); 9899 for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 9900 StringRef SegmentName = Entry.segmentName(); 9901 StringRef SectionName = Entry.sectionName(); 9902 uint64_t Address = Entry.address(); 9903 9904 // Table lines look like: 9905 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 9906 StringRef Attr; 9907 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 9908 Attr = " (weak_import)"; 9909 outs() << left_justify(SegmentName, 8) << " " 9910 << left_justify(SectionName, 18) << " " 9911 << format_hex(Address, 10, true) << " " 9912 << left_justify(Entry.typeName(), 8) << " " 9913 << format_decimal(Entry.addend(), 8) << " " 9914 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9915 << Entry.symbolName() << Attr << "\n"; 9916 } 9917 if (Err) 9918 report_error(Obj->getFileName(), std::move(Err)); 9919 } 9920 9921 //===----------------------------------------------------------------------===// 9922 // lazy bind table dumping 9923 //===----------------------------------------------------------------------===// 9924 9925 void llvm::printMachOLazyBindTable(object::MachOObjectFile *Obj) { 9926 outs() << "segment section address " 9927 "dylib symbol\n"; 9928 Error Err = Error::success(); 9929 for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 9930 StringRef SegmentName = Entry.segmentName(); 9931 StringRef SectionName = Entry.sectionName(); 9932 uint64_t Address = Entry.address(); 9933 9934 // Table lines look like: 9935 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 9936 outs() << left_justify(SegmentName, 8) << " " 9937 << left_justify(SectionName, 18) << " " 9938 << format_hex(Address, 10, true) << " " 9939 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9940 << Entry.symbolName() << "\n"; 9941 } 9942 if (Err) 9943 report_error(Obj->getFileName(), std::move(Err)); 9944 } 9945 9946 //===----------------------------------------------------------------------===// 9947 // weak bind table dumping 9948 //===----------------------------------------------------------------------===// 9949 9950 void llvm::printMachOWeakBindTable(object::MachOObjectFile *Obj) { 9951 outs() << "segment section address " 9952 "type addend symbol\n"; 9953 Error Err = Error::success(); 9954 for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 9955 // Strong symbols don't have a location to update. 9956 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 9957 outs() << " strong " 9958 << Entry.symbolName() << "\n"; 9959 continue; 9960 } 9961 StringRef SegmentName = Entry.segmentName(); 9962 StringRef SectionName = Entry.sectionName(); 9963 uint64_t Address = Entry.address(); 9964 9965 // Table lines look like: 9966 // __DATA __data 0x00001000 pointer 0 _foo 9967 outs() << left_justify(SegmentName, 8) << " " 9968 << left_justify(SectionName, 18) << " " 9969 << format_hex(Address, 10, true) << " " 9970 << left_justify(Entry.typeName(), 8) << " " 9971 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 9972 << "\n"; 9973 } 9974 if (Err) 9975 report_error(Obj->getFileName(), std::move(Err)); 9976 } 9977 9978 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 9979 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 9980 // information for that address. If the address is found its binding symbol 9981 // name is returned. If not nullptr is returned. 9982 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 9983 struct DisassembleInfo *info) { 9984 if (info->bindtable == nullptr) { 9985 info->bindtable = llvm::make_unique<SymbolAddressMap>(); 9986 Error Err = Error::success(); 9987 for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 9988 uint64_t Address = Entry.address(); 9989 StringRef name = Entry.symbolName(); 9990 if (!name.empty()) 9991 (*info->bindtable)[Address] = name; 9992 } 9993 if (Err) 9994 report_error(info->O->getFileName(), std::move(Err)); 9995 } 9996 auto name = info->bindtable->lookup(ReferenceValue); 9997 return !name.empty() ? name.data() : nullptr; 9998 } 9999 10000