1 //===-- MachODump.cpp - Object file dumping utility for llvm --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the MachO-specific dumper for llvm-objdump. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm-objdump.h" 15 #include "llvm-c/Disassembler.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/BinaryFormat/MachO.h" 20 #include "llvm/Config/config.h" 21 #include "llvm/DebugInfo/DIContext.h" 22 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 23 #include "llvm/Demangle/Demangle.h" 24 #include "llvm/MC/MCAsmInfo.h" 25 #include "llvm/MC/MCContext.h" 26 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 27 #include "llvm/MC/MCInst.h" 28 #include "llvm/MC/MCInstPrinter.h" 29 #include "llvm/MC/MCInstrDesc.h" 30 #include "llvm/MC/MCInstrInfo.h" 31 #include "llvm/MC/MCRegisterInfo.h" 32 #include "llvm/MC/MCSubtargetInfo.h" 33 #include "llvm/Object/MachO.h" 34 #include "llvm/Object/MachOUniversal.h" 35 #include "llvm/Support/Casting.h" 36 #include "llvm/Support/CommandLine.h" 37 #include "llvm/Support/Debug.h" 38 #include "llvm/Support/Endian.h" 39 #include "llvm/Support/Format.h" 40 #include "llvm/Support/FormattedStream.h" 41 #include "llvm/Support/GraphWriter.h" 42 #include "llvm/Support/LEB128.h" 43 #include "llvm/Support/MemoryBuffer.h" 44 #include "llvm/Support/TargetRegistry.h" 45 #include "llvm/Support/TargetSelect.h" 46 #include "llvm/Support/ToolOutputFile.h" 47 #include "llvm/Support/raw_ostream.h" 48 #include <algorithm> 49 #include <cstring> 50 #include <system_error> 51 52 #ifdef HAVE_LIBXAR 53 extern "C" { 54 #include <xar/xar.h> 55 } 56 #endif 57 58 using namespace llvm; 59 using namespace object; 60 61 static cl::opt<bool> 62 UseDbg("g", 63 cl::desc("Print line information from debug info if available")); 64 65 static cl::opt<std::string> DSYMFile("dsym", 66 cl::desc("Use .dSYM file for debug info")); 67 68 static cl::opt<bool> FullLeadingAddr("full-leading-addr", 69 cl::desc("Print full leading address")); 70 71 static cl::opt<bool> NoLeadingHeaders("no-leading-headers", 72 cl::desc("Print no leading headers")); 73 74 cl::opt<bool> llvm::UniversalHeaders("universal-headers", 75 cl::desc("Print Mach-O universal headers " 76 "(requires -macho)")); 77 78 cl::opt<bool> 79 ArchiveMemberOffsets("archive-member-offsets", 80 cl::desc("Print the offset to each archive member for " 81 "Mach-O archives (requires -macho and " 82 "-archive-headers)")); 83 84 cl::opt<bool> 85 llvm::IndirectSymbols("indirect-symbols", 86 cl::desc("Print indirect symbol table for Mach-O " 87 "objects (requires -macho)")); 88 89 cl::opt<bool> 90 llvm::DataInCode("data-in-code", 91 cl::desc("Print the data in code table for Mach-O objects " 92 "(requires -macho)")); 93 94 cl::opt<bool> 95 llvm::LinkOptHints("link-opt-hints", 96 cl::desc("Print the linker optimization hints for " 97 "Mach-O objects (requires -macho)")); 98 99 cl::opt<bool> 100 llvm::InfoPlist("info-plist", 101 cl::desc("Print the info plist section as strings for " 102 "Mach-O objects (requires -macho)")); 103 104 cl::opt<bool> 105 llvm::DylibsUsed("dylibs-used", 106 cl::desc("Print the shared libraries used for linked " 107 "Mach-O files (requires -macho)")); 108 109 cl::opt<bool> 110 llvm::DylibId("dylib-id", 111 cl::desc("Print the shared library's id for the dylib Mach-O " 112 "file (requires -macho)")); 113 114 cl::opt<bool> 115 llvm::NonVerbose("non-verbose", 116 cl::desc("Print the info for Mach-O objects in " 117 "non-verbose or numeric form (requires -macho)")); 118 119 cl::opt<bool> 120 llvm::ObjcMetaData("objc-meta-data", 121 cl::desc("Print the Objective-C runtime meta data for " 122 "Mach-O files (requires -macho)")); 123 124 cl::opt<std::string> llvm::DisSymName( 125 "dis-symname", 126 cl::desc("disassemble just this symbol's instructions (requires -macho)")); 127 128 static cl::opt<bool> NoSymbolicOperands( 129 "no-symbolic-operands", 130 cl::desc("do not symbolic operands when disassembling (requires -macho)")); 131 132 static cl::list<std::string> 133 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 134 cl::ZeroOrMore); 135 136 bool ArchAll = false; 137 138 static std::string ThumbTripleName; 139 140 static const Target *GetTarget(const MachOObjectFile *MachOObj, 141 const char **McpuDefault, 142 const Target **ThumbTarget) { 143 // Figure out the target triple. 144 llvm::Triple TT(TripleName); 145 if (TripleName.empty()) { 146 TT = MachOObj->getArchTriple(McpuDefault); 147 TripleName = TT.str(); 148 } 149 150 if (TT.getArch() == Triple::arm) { 151 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs 152 // that support ARM are also capable of Thumb mode. 153 llvm::Triple ThumbTriple = TT; 154 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str(); 155 ThumbTriple.setArchName(ThumbName); 156 ThumbTripleName = ThumbTriple.str(); 157 } 158 159 // Get the target specific parser. 160 std::string Error; 161 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 162 if (TheTarget && ThumbTripleName.empty()) 163 return TheTarget; 164 165 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 166 if (*ThumbTarget) 167 return TheTarget; 168 169 errs() << "llvm-objdump: error: unable to get target for '"; 170 if (!TheTarget) 171 errs() << TripleName; 172 else 173 errs() << ThumbTripleName; 174 errs() << "', see --version and --triple.\n"; 175 return nullptr; 176 } 177 178 struct SymbolSorter { 179 bool operator()(const SymbolRef &A, const SymbolRef &B) { 180 Expected<SymbolRef::Type> ATypeOrErr = A.getType(); 181 if (!ATypeOrErr) 182 report_error(A.getObject()->getFileName(), ATypeOrErr.takeError()); 183 SymbolRef::Type AType = *ATypeOrErr; 184 Expected<SymbolRef::Type> BTypeOrErr = B.getType(); 185 if (!BTypeOrErr) 186 report_error(B.getObject()->getFileName(), BTypeOrErr.takeError()); 187 SymbolRef::Type BType = *BTypeOrErr; 188 uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue(); 189 uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue(); 190 return AAddr < BAddr; 191 } 192 }; 193 194 // Types for the storted data in code table that is built before disassembly 195 // and the predicate function to sort them. 196 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 197 typedef std::vector<DiceTableEntry> DiceTable; 198 typedef DiceTable::iterator dice_table_iterator; 199 200 #ifdef HAVE_LIBXAR 201 namespace { 202 struct ScopedXarFile { 203 xar_t xar; 204 ScopedXarFile(const char *filename, int32_t flags) 205 : xar(xar_open(filename, flags)) {} 206 ~ScopedXarFile() { 207 if (xar) 208 xar_close(xar); 209 } 210 ScopedXarFile(const ScopedXarFile &) = delete; 211 ScopedXarFile &operator=(const ScopedXarFile &) = delete; 212 operator xar_t() { return xar; } 213 }; 214 215 struct ScopedXarIter { 216 xar_iter_t iter; 217 ScopedXarIter() : iter(xar_iter_new()) {} 218 ~ScopedXarIter() { 219 if (iter) 220 xar_iter_free(iter); 221 } 222 ScopedXarIter(const ScopedXarIter &) = delete; 223 ScopedXarIter &operator=(const ScopedXarIter &) = delete; 224 operator xar_iter_t() { return iter; } 225 }; 226 } // namespace 227 #endif // defined(HAVE_LIBXAR) 228 229 // This is used to search for a data in code table entry for the PC being 230 // disassembled. The j parameter has the PC in j.first. A single data in code 231 // table entry can cover many bytes for each of its Kind's. So if the offset, 232 // aka the i.first value, of the data in code table entry plus its Length 233 // covers the PC being searched for this will return true. If not it will 234 // return false. 235 static bool compareDiceTableEntries(const DiceTableEntry &i, 236 const DiceTableEntry &j) { 237 uint16_t Length; 238 i.second.getLength(Length); 239 240 return j.first >= i.first && j.first < i.first + Length; 241 } 242 243 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 244 unsigned short Kind) { 245 uint32_t Value, Size = 1; 246 247 switch (Kind) { 248 default: 249 case MachO::DICE_KIND_DATA: 250 if (Length >= 4) { 251 if (!NoShowRawInsn) 252 dumpBytes(makeArrayRef(bytes, 4), outs()); 253 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 254 outs() << "\t.long " << Value; 255 Size = 4; 256 } else if (Length >= 2) { 257 if (!NoShowRawInsn) 258 dumpBytes(makeArrayRef(bytes, 2), outs()); 259 Value = bytes[1] << 8 | bytes[0]; 260 outs() << "\t.short " << Value; 261 Size = 2; 262 } else { 263 if (!NoShowRawInsn) 264 dumpBytes(makeArrayRef(bytes, 2), outs()); 265 Value = bytes[0]; 266 outs() << "\t.byte " << Value; 267 Size = 1; 268 } 269 if (Kind == MachO::DICE_KIND_DATA) 270 outs() << "\t@ KIND_DATA\n"; 271 else 272 outs() << "\t@ data in code kind = " << Kind << "\n"; 273 break; 274 case MachO::DICE_KIND_JUMP_TABLE8: 275 if (!NoShowRawInsn) 276 dumpBytes(makeArrayRef(bytes, 1), outs()); 277 Value = bytes[0]; 278 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 279 Size = 1; 280 break; 281 case MachO::DICE_KIND_JUMP_TABLE16: 282 if (!NoShowRawInsn) 283 dumpBytes(makeArrayRef(bytes, 2), outs()); 284 Value = bytes[1] << 8 | bytes[0]; 285 outs() << "\t.short " << format("%5u", Value & 0xffff) 286 << "\t@ KIND_JUMP_TABLE16\n"; 287 Size = 2; 288 break; 289 case MachO::DICE_KIND_JUMP_TABLE32: 290 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 291 if (!NoShowRawInsn) 292 dumpBytes(makeArrayRef(bytes, 4), outs()); 293 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 294 outs() << "\t.long " << Value; 295 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 296 outs() << "\t@ KIND_JUMP_TABLE32\n"; 297 else 298 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 299 Size = 4; 300 break; 301 } 302 return Size; 303 } 304 305 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 306 std::vector<SectionRef> &Sections, 307 std::vector<SymbolRef> &Symbols, 308 SmallVectorImpl<uint64_t> &FoundFns, 309 uint64_t &BaseSegmentAddress) { 310 for (const SymbolRef &Symbol : MachOObj->symbols()) { 311 Expected<StringRef> SymName = Symbol.getName(); 312 if (!SymName) 313 report_error(MachOObj->getFileName(), SymName.takeError()); 314 if (!SymName->startswith("ltmp")) 315 Symbols.push_back(Symbol); 316 } 317 318 for (const SectionRef &Section : MachOObj->sections()) { 319 StringRef SectName; 320 Section.getName(SectName); 321 Sections.push_back(Section); 322 } 323 324 bool BaseSegmentAddressSet = false; 325 for (const auto &Command : MachOObj->load_commands()) { 326 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 327 // We found a function starts segment, parse the addresses for later 328 // consumption. 329 MachO::linkedit_data_command LLC = 330 MachOObj->getLinkeditDataLoadCommand(Command); 331 332 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 333 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 334 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 335 StringRef SegName = SLC.segname; 336 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 337 BaseSegmentAddressSet = true; 338 BaseSegmentAddress = SLC.vmaddr; 339 } 340 } 341 } 342 } 343 344 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 345 uint32_t n, uint32_t count, 346 uint32_t stride, uint64_t addr) { 347 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 348 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 349 if (n > nindirectsyms) 350 outs() << " (entries start past the end of the indirect symbol " 351 "table) (reserved1 field greater than the table size)"; 352 else if (n + count > nindirectsyms) 353 outs() << " (entries extends past the end of the indirect symbol " 354 "table)"; 355 outs() << "\n"; 356 uint32_t cputype = O->getHeader().cputype; 357 if (cputype & MachO::CPU_ARCH_ABI64) 358 outs() << "address index"; 359 else 360 outs() << "address index"; 361 if (verbose) 362 outs() << " name\n"; 363 else 364 outs() << "\n"; 365 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 366 if (cputype & MachO::CPU_ARCH_ABI64) 367 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 368 else 369 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 370 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 371 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 372 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 373 outs() << "LOCAL\n"; 374 continue; 375 } 376 if (indirect_symbol == 377 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 378 outs() << "LOCAL ABSOLUTE\n"; 379 continue; 380 } 381 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 382 outs() << "ABSOLUTE\n"; 383 continue; 384 } 385 outs() << format("%5u ", indirect_symbol); 386 if (verbose) { 387 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 388 if (indirect_symbol < Symtab.nsyms) { 389 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 390 SymbolRef Symbol = *Sym; 391 Expected<StringRef> SymName = Symbol.getName(); 392 if (!SymName) 393 report_error(O->getFileName(), SymName.takeError()); 394 outs() << *SymName; 395 } else { 396 outs() << "?"; 397 } 398 } 399 outs() << "\n"; 400 } 401 } 402 403 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 404 for (const auto &Load : O->load_commands()) { 405 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 406 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 407 for (unsigned J = 0; J < Seg.nsects; ++J) { 408 MachO::section_64 Sec = O->getSection64(Load, J); 409 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 410 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 411 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 412 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 413 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 414 section_type == MachO::S_SYMBOL_STUBS) { 415 uint32_t stride; 416 if (section_type == MachO::S_SYMBOL_STUBS) 417 stride = Sec.reserved2; 418 else 419 stride = 8; 420 if (stride == 0) { 421 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 422 << Sec.sectname << ") " 423 << "(size of stubs in reserved2 field is zero)\n"; 424 continue; 425 } 426 uint32_t count = Sec.size / stride; 427 outs() << "Indirect symbols for (" << Sec.segname << "," 428 << Sec.sectname << ") " << count << " entries"; 429 uint32_t n = Sec.reserved1; 430 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 431 } 432 } 433 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 434 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 435 for (unsigned J = 0; J < Seg.nsects; ++J) { 436 MachO::section Sec = O->getSection(Load, J); 437 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 438 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 439 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 440 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 441 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 442 section_type == MachO::S_SYMBOL_STUBS) { 443 uint32_t stride; 444 if (section_type == MachO::S_SYMBOL_STUBS) 445 stride = Sec.reserved2; 446 else 447 stride = 4; 448 if (stride == 0) { 449 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 450 << Sec.sectname << ") " 451 << "(size of stubs in reserved2 field is zero)\n"; 452 continue; 453 } 454 uint32_t count = Sec.size / stride; 455 outs() << "Indirect symbols for (" << Sec.segname << "," 456 << Sec.sectname << ") " << count << " entries"; 457 uint32_t n = Sec.reserved1; 458 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 459 } 460 } 461 } 462 } 463 } 464 465 static void PrintRType(const uint64_t cputype, const unsigned r_type) { 466 static char const *generic_r_types[] = { 467 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ", 468 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", 469 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 470 }; 471 static char const *x86_64_r_types[] = { 472 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", 473 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ", 474 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 475 }; 476 static char const *arm_r_types[] = { 477 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", 478 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ", 479 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 480 }; 481 static char const *arm64_r_types[] = { 482 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", 483 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", 484 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 485 }; 486 487 if (r_type > 0xf){ 488 outs() << format("%-7u", r_type) << " "; 489 return; 490 } 491 switch (cputype) { 492 case MachO::CPU_TYPE_I386: 493 outs() << generic_r_types[r_type]; 494 break; 495 case MachO::CPU_TYPE_X86_64: 496 outs() << x86_64_r_types[r_type]; 497 break; 498 case MachO::CPU_TYPE_ARM: 499 outs() << arm_r_types[r_type]; 500 break; 501 case MachO::CPU_TYPE_ARM64: 502 outs() << arm64_r_types[r_type]; 503 break; 504 default: 505 outs() << format("%-7u ", r_type); 506 } 507 } 508 509 static void PrintRLength(const uint64_t cputype, const unsigned r_type, 510 const unsigned r_length, const bool previous_arm_half){ 511 if (cputype == MachO::CPU_TYPE_ARM && 512 (r_type == llvm::MachO::ARM_RELOC_HALF || 513 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF || 514 previous_arm_half == true)) { 515 if ((r_length & 0x1) == 0) 516 outs() << "lo/"; 517 else 518 outs() << "hi/"; 519 if ((r_length & 0x1) == 0) 520 outs() << "arm "; 521 else 522 outs() << "thm "; 523 } else { 524 switch (r_length) { 525 case 0: 526 outs() << "byte "; 527 break; 528 case 1: 529 outs() << "word "; 530 break; 531 case 2: 532 outs() << "long "; 533 break; 534 case 3: 535 if (cputype == MachO::CPU_TYPE_X86_64) 536 outs() << "quad "; 537 else 538 outs() << format("?(%2d) ", r_length); 539 break; 540 default: 541 outs() << format("?(%2d) ", r_length); 542 } 543 } 544 } 545 546 static void PrintRelocationEntries(const MachOObjectFile *O, 547 const relocation_iterator Begin, 548 const relocation_iterator End, 549 const uint64_t cputype, 550 const bool verbose) { 551 const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 552 bool previous_arm_half = false; 553 bool previous_sectdiff = false; 554 uint32_t sectdiff_r_type = 0; 555 556 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { 557 const DataRefImpl Rel = Reloc->getRawDataRefImpl(); 558 const MachO::any_relocation_info RE = O->getRelocation(Rel); 559 const unsigned r_type = O->getAnyRelocationType(RE); 560 const bool r_scattered = O->isRelocationScattered(RE); 561 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); 562 const unsigned r_length = O->getAnyRelocationLength(RE); 563 const unsigned r_address = O->getAnyRelocationAddress(RE); 564 const bool r_extern = (r_scattered ? false : 565 O->getPlainRelocationExternal(RE)); 566 const uint32_t r_value = (r_scattered ? 567 O->getScatteredRelocationValue(RE) : 0); 568 const unsigned r_symbolnum = (r_scattered ? 0 : 569 O->getPlainRelocationSymbolNum(RE)); 570 571 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { 572 if (verbose) { 573 // scattered: address 574 if ((cputype == MachO::CPU_TYPE_I386 && 575 r_type == llvm::MachO::GENERIC_RELOC_PAIR) || 576 (cputype == MachO::CPU_TYPE_ARM && 577 r_type == llvm::MachO::ARM_RELOC_PAIR)) 578 outs() << " "; 579 else 580 outs() << format("%08x ", (unsigned int)r_address); 581 582 // scattered: pcrel 583 if (r_pcrel) 584 outs() << "True "; 585 else 586 outs() << "False "; 587 588 // scattered: length 589 PrintRLength(cputype, r_type, r_length, previous_arm_half); 590 591 // scattered: extern & type 592 outs() << "n/a "; 593 PrintRType(cputype, r_type); 594 595 // scattered: scattered & value 596 outs() << format("True 0x%08x", (unsigned int)r_value); 597 if (previous_sectdiff == false) { 598 if ((cputype == MachO::CPU_TYPE_ARM && 599 r_type == llvm::MachO::ARM_RELOC_PAIR)) 600 outs() << format(" half = 0x%04x ", (unsigned int)r_address); 601 } 602 else if (cputype == MachO::CPU_TYPE_ARM && 603 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF) 604 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); 605 if ((cputype == MachO::CPU_TYPE_I386 && 606 (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF || 607 r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || 608 (cputype == MachO::CPU_TYPE_ARM && 609 (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF || 610 sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF || 611 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) { 612 previous_sectdiff = true; 613 sectdiff_r_type = r_type; 614 } 615 else { 616 previous_sectdiff = false; 617 sectdiff_r_type = 0; 618 } 619 if (cputype == MachO::CPU_TYPE_ARM && 620 (r_type == llvm::MachO::ARM_RELOC_HALF || 621 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) 622 previous_arm_half = true; 623 else 624 previous_arm_half = false; 625 outs() << "\n"; 626 } 627 else { 628 // scattered: address pcrel length extern type scattered value 629 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n", 630 (unsigned int)r_address, r_pcrel, r_length, r_type, 631 (unsigned int)r_value); 632 } 633 } 634 else { 635 if (verbose) { 636 // plain: address 637 if (cputype == MachO::CPU_TYPE_ARM && 638 r_type == llvm::MachO::ARM_RELOC_PAIR) 639 outs() << " "; 640 else 641 outs() << format("%08x ", (unsigned int)r_address); 642 643 // plain: pcrel 644 if (r_pcrel) 645 outs() << "True "; 646 else 647 outs() << "False "; 648 649 // plain: length 650 PrintRLength(cputype, r_type, r_length, previous_arm_half); 651 652 if (r_extern) { 653 // plain: extern & type & scattered 654 outs() << "True "; 655 PrintRType(cputype, r_type); 656 outs() << "False "; 657 658 // plain: symbolnum/value 659 if (r_symbolnum > Symtab.nsyms) 660 outs() << format("?(%d)\n", r_symbolnum); 661 else { 662 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); 663 Expected<StringRef> SymNameNext = Symbol.getName(); 664 const char *name = NULL; 665 if (SymNameNext) 666 name = SymNameNext->data(); 667 if (name == NULL) 668 outs() << format("?(%d)\n", r_symbolnum); 669 else 670 outs() << name << "\n"; 671 } 672 } 673 else { 674 // plain: extern & type & scattered 675 outs() << "False "; 676 PrintRType(cputype, r_type); 677 outs() << "False "; 678 679 // plain: symbolnum/value 680 if (cputype == MachO::CPU_TYPE_ARM && 681 r_type == llvm::MachO::ARM_RELOC_PAIR) 682 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); 683 else if (cputype == MachO::CPU_TYPE_ARM64 && 684 r_type == llvm::MachO::ARM64_RELOC_ADDEND) 685 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); 686 else { 687 outs() << format("%d ", r_symbolnum); 688 if (r_symbolnum == llvm::MachO::R_ABS) 689 outs() << "R_ABS\n"; 690 else { 691 // in this case, r_symbolnum is actually a 1-based section number 692 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; 693 if (r_symbolnum > 0 && r_symbolnum <= nsects) { 694 llvm::object::DataRefImpl DRI; 695 DRI.d.a = r_symbolnum-1; 696 StringRef SegName = O->getSectionFinalSegmentName(DRI); 697 StringRef SectName; 698 if (O->getSectionName(DRI, SectName)) 699 outs() << "(?,?)\n"; 700 else 701 outs() << "(" << SegName << "," << SectName << ")\n"; 702 } 703 else { 704 outs() << "(?,?)\n"; 705 } 706 } 707 } 708 } 709 if (cputype == MachO::CPU_TYPE_ARM && 710 (r_type == llvm::MachO::ARM_RELOC_HALF || 711 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) 712 previous_arm_half = true; 713 else 714 previous_arm_half = false; 715 } 716 else { 717 // plain: address pcrel length extern type scattered symbolnum/section 718 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n", 719 (unsigned int)r_address, r_pcrel, r_length, r_extern, 720 r_type, r_symbolnum); 721 } 722 } 723 } 724 } 725 726 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { 727 const uint64_t cputype = O->getHeader().cputype; 728 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 729 if (Dysymtab.nextrel != 0) { 730 outs() << "External relocation information " << Dysymtab.nextrel 731 << " entries"; 732 outs() << "\naddress pcrel length extern type scattered " 733 "symbolnum/value\n"; 734 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, 735 verbose); 736 } 737 if (Dysymtab.nlocrel != 0) { 738 outs() << format("Local relocation information %u entries", 739 Dysymtab.nlocrel); 740 outs() << "\naddress pcrel length extern type scattered " 741 "symbolnum/value\n"; 742 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, 743 verbose); 744 } 745 for (const auto &Load : O->load_commands()) { 746 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 747 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 748 for (unsigned J = 0; J < Seg.nsects; ++J) { 749 const MachO::section_64 Sec = O->getSection64(Load, J); 750 if (Sec.nreloc != 0) { 751 DataRefImpl DRI; 752 DRI.d.a = J; 753 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 754 StringRef SectName; 755 if (O->getSectionName(DRI, SectName)) 756 outs() << "Relocation information (" << SegName << ",?) " 757 << format("%u entries", Sec.nreloc); 758 else 759 outs() << "Relocation information (" << SegName << "," 760 << SectName << format(") %u entries", Sec.nreloc); 761 outs() << "\naddress pcrel length extern type scattered " 762 "symbolnum/value\n"; 763 PrintRelocationEntries(O, O->section_rel_begin(DRI), 764 O->section_rel_end(DRI), cputype, verbose); 765 } 766 } 767 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 768 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 769 for (unsigned J = 0; J < Seg.nsects; ++J) { 770 const MachO::section Sec = O->getSection(Load, J); 771 if (Sec.nreloc != 0) { 772 DataRefImpl DRI; 773 DRI.d.a = J; 774 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 775 StringRef SectName; 776 if (O->getSectionName(DRI, SectName)) 777 outs() << "Relocation information (" << SegName << ",?) " 778 << format("%u entries", Sec.nreloc); 779 else 780 outs() << "Relocation information (" << SegName << "," 781 << SectName << format(") %u entries", Sec.nreloc); 782 outs() << "\naddress pcrel length extern type scattered " 783 "symbolnum/value\n"; 784 PrintRelocationEntries(O, O->section_rel_begin(DRI), 785 O->section_rel_end(DRI), cputype, verbose); 786 } 787 } 788 } 789 } 790 } 791 792 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 793 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 794 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 795 outs() << "Data in code table (" << nentries << " entries)\n"; 796 outs() << "offset length kind\n"; 797 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 798 ++DI) { 799 uint32_t Offset; 800 DI->getOffset(Offset); 801 outs() << format("0x%08" PRIx32, Offset) << " "; 802 uint16_t Length; 803 DI->getLength(Length); 804 outs() << format("%6u", Length) << " "; 805 uint16_t Kind; 806 DI->getKind(Kind); 807 if (verbose) { 808 switch (Kind) { 809 case MachO::DICE_KIND_DATA: 810 outs() << "DATA"; 811 break; 812 case MachO::DICE_KIND_JUMP_TABLE8: 813 outs() << "JUMP_TABLE8"; 814 break; 815 case MachO::DICE_KIND_JUMP_TABLE16: 816 outs() << "JUMP_TABLE16"; 817 break; 818 case MachO::DICE_KIND_JUMP_TABLE32: 819 outs() << "JUMP_TABLE32"; 820 break; 821 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 822 outs() << "ABS_JUMP_TABLE32"; 823 break; 824 default: 825 outs() << format("0x%04" PRIx32, Kind); 826 break; 827 } 828 } else 829 outs() << format("0x%04" PRIx32, Kind); 830 outs() << "\n"; 831 } 832 } 833 834 static void PrintLinkOptHints(MachOObjectFile *O) { 835 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 836 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 837 uint32_t nloh = LohLC.datasize; 838 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 839 for (uint32_t i = 0; i < nloh;) { 840 unsigned n; 841 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 842 i += n; 843 outs() << " identifier " << identifier << " "; 844 if (i >= nloh) 845 return; 846 switch (identifier) { 847 case 1: 848 outs() << "AdrpAdrp\n"; 849 break; 850 case 2: 851 outs() << "AdrpLdr\n"; 852 break; 853 case 3: 854 outs() << "AdrpAddLdr\n"; 855 break; 856 case 4: 857 outs() << "AdrpLdrGotLdr\n"; 858 break; 859 case 5: 860 outs() << "AdrpAddStr\n"; 861 break; 862 case 6: 863 outs() << "AdrpLdrGotStr\n"; 864 break; 865 case 7: 866 outs() << "AdrpAdd\n"; 867 break; 868 case 8: 869 outs() << "AdrpLdrGot\n"; 870 break; 871 default: 872 outs() << "Unknown identifier value\n"; 873 break; 874 } 875 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 876 i += n; 877 outs() << " narguments " << narguments << "\n"; 878 if (i >= nloh) 879 return; 880 881 for (uint32_t j = 0; j < narguments; j++) { 882 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 883 i += n; 884 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 885 if (i >= nloh) 886 return; 887 } 888 } 889 } 890 891 static void PrintDylibs(MachOObjectFile *O, bool JustId) { 892 unsigned Index = 0; 893 for (const auto &Load : O->load_commands()) { 894 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 895 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 896 Load.C.cmd == MachO::LC_LOAD_DYLIB || 897 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 898 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 899 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 900 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 901 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 902 if (dl.dylib.name < dl.cmdsize) { 903 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 904 if (JustId) 905 outs() << p << "\n"; 906 else { 907 outs() << "\t" << p; 908 outs() << " (compatibility version " 909 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 910 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 911 << (dl.dylib.compatibility_version & 0xff) << ","; 912 outs() << " current version " 913 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 914 << ((dl.dylib.current_version >> 8) & 0xff) << "." 915 << (dl.dylib.current_version & 0xff) << ")\n"; 916 } 917 } else { 918 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 919 if (Load.C.cmd == MachO::LC_ID_DYLIB) 920 outs() << "LC_ID_DYLIB "; 921 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 922 outs() << "LC_LOAD_DYLIB "; 923 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 924 outs() << "LC_LOAD_WEAK_DYLIB "; 925 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 926 outs() << "LC_LAZY_LOAD_DYLIB "; 927 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 928 outs() << "LC_REEXPORT_DYLIB "; 929 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 930 outs() << "LC_LOAD_UPWARD_DYLIB "; 931 else 932 outs() << "LC_??? "; 933 outs() << "command " << Index++ << "\n"; 934 } 935 } 936 } 937 } 938 939 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 940 941 static void CreateSymbolAddressMap(MachOObjectFile *O, 942 SymbolAddressMap *AddrMap) { 943 // Create a map of symbol addresses to symbol names. 944 for (const SymbolRef &Symbol : O->symbols()) { 945 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 946 if (!STOrErr) 947 report_error(O->getFileName(), STOrErr.takeError()); 948 SymbolRef::Type ST = *STOrErr; 949 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 950 ST == SymbolRef::ST_Other) { 951 uint64_t Address = Symbol.getValue(); 952 Expected<StringRef> SymNameOrErr = Symbol.getName(); 953 if (!SymNameOrErr) 954 report_error(O->getFileName(), SymNameOrErr.takeError()); 955 StringRef SymName = *SymNameOrErr; 956 if (!SymName.startswith(".objc")) 957 (*AddrMap)[Address] = SymName; 958 } 959 } 960 } 961 962 // GuessSymbolName is passed the address of what might be a symbol and a 963 // pointer to the SymbolAddressMap. It returns the name of a symbol 964 // with that address or nullptr if no symbol is found with that address. 965 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 966 const char *SymbolName = nullptr; 967 // A DenseMap can't lookup up some values. 968 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 969 StringRef name = AddrMap->lookup(value); 970 if (!name.empty()) 971 SymbolName = name.data(); 972 } 973 return SymbolName; 974 } 975 976 static void DumpCstringChar(const char c) { 977 char p[2]; 978 p[0] = c; 979 p[1] = '\0'; 980 outs().write_escaped(p); 981 } 982 983 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 984 uint32_t sect_size, uint64_t sect_addr, 985 bool print_addresses) { 986 for (uint32_t i = 0; i < sect_size; i++) { 987 if (print_addresses) { 988 if (O->is64Bit()) 989 outs() << format("%016" PRIx64, sect_addr + i) << " "; 990 else 991 outs() << format("%08" PRIx64, sect_addr + i) << " "; 992 } 993 for (; i < sect_size && sect[i] != '\0'; i++) 994 DumpCstringChar(sect[i]); 995 if (i < sect_size && sect[i] == '\0') 996 outs() << "\n"; 997 } 998 } 999 1000 static void DumpLiteral4(uint32_t l, float f) { 1001 outs() << format("0x%08" PRIx32, l); 1002 if ((l & 0x7f800000) != 0x7f800000) 1003 outs() << format(" (%.16e)\n", f); 1004 else { 1005 if (l == 0x7f800000) 1006 outs() << " (+Infinity)\n"; 1007 else if (l == 0xff800000) 1008 outs() << " (-Infinity)\n"; 1009 else if ((l & 0x00400000) == 0x00400000) 1010 outs() << " (non-signaling Not-a-Number)\n"; 1011 else 1012 outs() << " (signaling Not-a-Number)\n"; 1013 } 1014 } 1015 1016 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 1017 uint32_t sect_size, uint64_t sect_addr, 1018 bool print_addresses) { 1019 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 1020 if (print_addresses) { 1021 if (O->is64Bit()) 1022 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1023 else 1024 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1025 } 1026 float f; 1027 memcpy(&f, sect + i, sizeof(float)); 1028 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1029 sys::swapByteOrder(f); 1030 uint32_t l; 1031 memcpy(&l, sect + i, sizeof(uint32_t)); 1032 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1033 sys::swapByteOrder(l); 1034 DumpLiteral4(l, f); 1035 } 1036 } 1037 1038 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 1039 double d) { 1040 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 1041 uint32_t Hi, Lo; 1042 Hi = (O->isLittleEndian()) ? l1 : l0; 1043 Lo = (O->isLittleEndian()) ? l0 : l1; 1044 1045 // Hi is the high word, so this is equivalent to if(isfinite(d)) 1046 if ((Hi & 0x7ff00000) != 0x7ff00000) 1047 outs() << format(" (%.16e)\n", d); 1048 else { 1049 if (Hi == 0x7ff00000 && Lo == 0) 1050 outs() << " (+Infinity)\n"; 1051 else if (Hi == 0xfff00000 && Lo == 0) 1052 outs() << " (-Infinity)\n"; 1053 else if ((Hi & 0x00080000) == 0x00080000) 1054 outs() << " (non-signaling Not-a-Number)\n"; 1055 else 1056 outs() << " (signaling Not-a-Number)\n"; 1057 } 1058 } 1059 1060 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 1061 uint32_t sect_size, uint64_t sect_addr, 1062 bool print_addresses) { 1063 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 1064 if (print_addresses) { 1065 if (O->is64Bit()) 1066 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1067 else 1068 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1069 } 1070 double d; 1071 memcpy(&d, sect + i, sizeof(double)); 1072 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1073 sys::swapByteOrder(d); 1074 uint32_t l0, l1; 1075 memcpy(&l0, sect + i, sizeof(uint32_t)); 1076 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1077 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1078 sys::swapByteOrder(l0); 1079 sys::swapByteOrder(l1); 1080 } 1081 DumpLiteral8(O, l0, l1, d); 1082 } 1083 } 1084 1085 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 1086 outs() << format("0x%08" PRIx32, l0) << " "; 1087 outs() << format("0x%08" PRIx32, l1) << " "; 1088 outs() << format("0x%08" PRIx32, l2) << " "; 1089 outs() << format("0x%08" PRIx32, l3) << "\n"; 1090 } 1091 1092 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 1093 uint32_t sect_size, uint64_t sect_addr, 1094 bool print_addresses) { 1095 for (uint32_t i = 0; i < sect_size; i += 16) { 1096 if (print_addresses) { 1097 if (O->is64Bit()) 1098 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1099 else 1100 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1101 } 1102 uint32_t l0, l1, l2, l3; 1103 memcpy(&l0, sect + i, sizeof(uint32_t)); 1104 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1105 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 1106 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1107 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1108 sys::swapByteOrder(l0); 1109 sys::swapByteOrder(l1); 1110 sys::swapByteOrder(l2); 1111 sys::swapByteOrder(l3); 1112 } 1113 DumpLiteral16(l0, l1, l2, l3); 1114 } 1115 } 1116 1117 static void DumpLiteralPointerSection(MachOObjectFile *O, 1118 const SectionRef &Section, 1119 const char *sect, uint32_t sect_size, 1120 uint64_t sect_addr, 1121 bool print_addresses) { 1122 // Collect the literal sections in this Mach-O file. 1123 std::vector<SectionRef> LiteralSections; 1124 for (const SectionRef &Section : O->sections()) { 1125 DataRefImpl Ref = Section.getRawDataRefImpl(); 1126 uint32_t section_type; 1127 if (O->is64Bit()) { 1128 const MachO::section_64 Sec = O->getSection64(Ref); 1129 section_type = Sec.flags & MachO::SECTION_TYPE; 1130 } else { 1131 const MachO::section Sec = O->getSection(Ref); 1132 section_type = Sec.flags & MachO::SECTION_TYPE; 1133 } 1134 if (section_type == MachO::S_CSTRING_LITERALS || 1135 section_type == MachO::S_4BYTE_LITERALS || 1136 section_type == MachO::S_8BYTE_LITERALS || 1137 section_type == MachO::S_16BYTE_LITERALS) 1138 LiteralSections.push_back(Section); 1139 } 1140 1141 // Set the size of the literal pointer. 1142 uint32_t lp_size = O->is64Bit() ? 8 : 4; 1143 1144 // Collect the external relocation symbols for the literal pointers. 1145 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1146 for (const RelocationRef &Reloc : Section.relocations()) { 1147 DataRefImpl Rel; 1148 MachO::any_relocation_info RE; 1149 bool isExtern = false; 1150 Rel = Reloc.getRawDataRefImpl(); 1151 RE = O->getRelocation(Rel); 1152 isExtern = O->getPlainRelocationExternal(RE); 1153 if (isExtern) { 1154 uint64_t RelocOffset = Reloc.getOffset(); 1155 symbol_iterator RelocSym = Reloc.getSymbol(); 1156 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1157 } 1158 } 1159 array_pod_sort(Relocs.begin(), Relocs.end()); 1160 1161 // Dump each literal pointer. 1162 for (uint32_t i = 0; i < sect_size; i += lp_size) { 1163 if (print_addresses) { 1164 if (O->is64Bit()) 1165 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1166 else 1167 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1168 } 1169 uint64_t lp; 1170 if (O->is64Bit()) { 1171 memcpy(&lp, sect + i, sizeof(uint64_t)); 1172 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1173 sys::swapByteOrder(lp); 1174 } else { 1175 uint32_t li; 1176 memcpy(&li, sect + i, sizeof(uint32_t)); 1177 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1178 sys::swapByteOrder(li); 1179 lp = li; 1180 } 1181 1182 // First look for an external relocation entry for this literal pointer. 1183 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1184 return P.first == i; 1185 }); 1186 if (Reloc != Relocs.end()) { 1187 symbol_iterator RelocSym = Reloc->second; 1188 Expected<StringRef> SymName = RelocSym->getName(); 1189 if (!SymName) 1190 report_error(O->getFileName(), SymName.takeError()); 1191 outs() << "external relocation entry for symbol:" << *SymName << "\n"; 1192 continue; 1193 } 1194 1195 // For local references see what the section the literal pointer points to. 1196 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 1197 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 1198 }); 1199 if (Sect == LiteralSections.end()) { 1200 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 1201 continue; 1202 } 1203 1204 uint64_t SectAddress = Sect->getAddress(); 1205 uint64_t SectSize = Sect->getSize(); 1206 1207 StringRef SectName; 1208 Sect->getName(SectName); 1209 DataRefImpl Ref = Sect->getRawDataRefImpl(); 1210 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 1211 outs() << SegmentName << ":" << SectName << ":"; 1212 1213 uint32_t section_type; 1214 if (O->is64Bit()) { 1215 const MachO::section_64 Sec = O->getSection64(Ref); 1216 section_type = Sec.flags & MachO::SECTION_TYPE; 1217 } else { 1218 const MachO::section Sec = O->getSection(Ref); 1219 section_type = Sec.flags & MachO::SECTION_TYPE; 1220 } 1221 1222 StringRef BytesStr; 1223 Sect->getContents(BytesStr); 1224 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 1225 1226 switch (section_type) { 1227 case MachO::S_CSTRING_LITERALS: 1228 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 1229 i++) { 1230 DumpCstringChar(Contents[i]); 1231 } 1232 outs() << "\n"; 1233 break; 1234 case MachO::S_4BYTE_LITERALS: 1235 float f; 1236 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 1237 uint32_t l; 1238 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 1239 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1240 sys::swapByteOrder(f); 1241 sys::swapByteOrder(l); 1242 } 1243 DumpLiteral4(l, f); 1244 break; 1245 case MachO::S_8BYTE_LITERALS: { 1246 double d; 1247 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 1248 uint32_t l0, l1; 1249 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1250 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1251 sizeof(uint32_t)); 1252 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1253 sys::swapByteOrder(f); 1254 sys::swapByteOrder(l0); 1255 sys::swapByteOrder(l1); 1256 } 1257 DumpLiteral8(O, l0, l1, d); 1258 break; 1259 } 1260 case MachO::S_16BYTE_LITERALS: { 1261 uint32_t l0, l1, l2, l3; 1262 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1263 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1264 sizeof(uint32_t)); 1265 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 1266 sizeof(uint32_t)); 1267 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 1268 sizeof(uint32_t)); 1269 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1270 sys::swapByteOrder(l0); 1271 sys::swapByteOrder(l1); 1272 sys::swapByteOrder(l2); 1273 sys::swapByteOrder(l3); 1274 } 1275 DumpLiteral16(l0, l1, l2, l3); 1276 break; 1277 } 1278 } 1279 } 1280 } 1281 1282 static void DumpInitTermPointerSection(MachOObjectFile *O, 1283 const SectionRef &Section, 1284 const char *sect, 1285 uint32_t sect_size, uint64_t sect_addr, 1286 SymbolAddressMap *AddrMap, 1287 bool verbose) { 1288 uint32_t stride; 1289 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 1290 1291 // Collect the external relocation symbols for the pointers. 1292 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1293 for (const RelocationRef &Reloc : Section.relocations()) { 1294 DataRefImpl Rel; 1295 MachO::any_relocation_info RE; 1296 bool isExtern = false; 1297 Rel = Reloc.getRawDataRefImpl(); 1298 RE = O->getRelocation(Rel); 1299 isExtern = O->getPlainRelocationExternal(RE); 1300 if (isExtern) { 1301 uint64_t RelocOffset = Reloc.getOffset(); 1302 symbol_iterator RelocSym = Reloc.getSymbol(); 1303 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1304 } 1305 } 1306 array_pod_sort(Relocs.begin(), Relocs.end()); 1307 1308 for (uint32_t i = 0; i < sect_size; i += stride) { 1309 const char *SymbolName = nullptr; 1310 uint64_t p; 1311 if (O->is64Bit()) { 1312 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 1313 uint64_t pointer_value; 1314 memcpy(&pointer_value, sect + i, stride); 1315 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1316 sys::swapByteOrder(pointer_value); 1317 outs() << format("0x%016" PRIx64, pointer_value); 1318 p = pointer_value; 1319 } else { 1320 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 1321 uint32_t pointer_value; 1322 memcpy(&pointer_value, sect + i, stride); 1323 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1324 sys::swapByteOrder(pointer_value); 1325 outs() << format("0x%08" PRIx32, pointer_value); 1326 p = pointer_value; 1327 } 1328 if (verbose) { 1329 // First look for an external relocation entry for this pointer. 1330 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1331 return P.first == i; 1332 }); 1333 if (Reloc != Relocs.end()) { 1334 symbol_iterator RelocSym = Reloc->second; 1335 Expected<StringRef> SymName = RelocSym->getName(); 1336 if (!SymName) 1337 report_error(O->getFileName(), SymName.takeError()); 1338 outs() << " " << *SymName; 1339 } else { 1340 SymbolName = GuessSymbolName(p, AddrMap); 1341 if (SymbolName) 1342 outs() << " " << SymbolName; 1343 } 1344 } 1345 outs() << "\n"; 1346 } 1347 } 1348 1349 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 1350 uint32_t size, uint64_t addr) { 1351 uint32_t cputype = O->getHeader().cputype; 1352 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 1353 uint32_t j; 1354 for (uint32_t i = 0; i < size; i += j, addr += j) { 1355 if (O->is64Bit()) 1356 outs() << format("%016" PRIx64, addr) << "\t"; 1357 else 1358 outs() << format("%08" PRIx64, addr) << "\t"; 1359 for (j = 0; j < 16 && i + j < size; j++) { 1360 uint8_t byte_word = *(sect + i + j); 1361 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1362 } 1363 outs() << "\n"; 1364 } 1365 } else { 1366 uint32_t j; 1367 for (uint32_t i = 0; i < size; i += j, addr += j) { 1368 if (O->is64Bit()) 1369 outs() << format("%016" PRIx64, addr) << "\t"; 1370 else 1371 outs() << format("%08" PRIx64, addr) << "\t"; 1372 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 1373 j += sizeof(int32_t)) { 1374 if (i + j + sizeof(int32_t) <= size) { 1375 uint32_t long_word; 1376 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1377 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1378 sys::swapByteOrder(long_word); 1379 outs() << format("%08" PRIx32, long_word) << " "; 1380 } else { 1381 for (uint32_t k = 0; i + j + k < size; k++) { 1382 uint8_t byte_word = *(sect + i + j + k); 1383 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1384 } 1385 } 1386 } 1387 outs() << "\n"; 1388 } 1389 } 1390 } 1391 1392 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1393 StringRef DisSegName, StringRef DisSectName); 1394 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1395 uint32_t size, uint32_t addr); 1396 #ifdef HAVE_LIBXAR 1397 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 1398 uint32_t size, bool verbose, 1399 bool PrintXarHeader, bool PrintXarFileHeaders, 1400 std::string XarMemberName); 1401 #endif // defined(HAVE_LIBXAR) 1402 1403 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1404 bool verbose) { 1405 SymbolAddressMap AddrMap; 1406 if (verbose) 1407 CreateSymbolAddressMap(O, &AddrMap); 1408 1409 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1410 StringRef DumpSection = FilterSections[i]; 1411 std::pair<StringRef, StringRef> DumpSegSectName; 1412 DumpSegSectName = DumpSection.split(','); 1413 StringRef DumpSegName, DumpSectName; 1414 if (DumpSegSectName.second.size()) { 1415 DumpSegName = DumpSegSectName.first; 1416 DumpSectName = DumpSegSectName.second; 1417 } else { 1418 DumpSegName = ""; 1419 DumpSectName = DumpSegSectName.first; 1420 } 1421 for (const SectionRef &Section : O->sections()) { 1422 StringRef SectName; 1423 Section.getName(SectName); 1424 DataRefImpl Ref = Section.getRawDataRefImpl(); 1425 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1426 if ((DumpSegName.empty() || SegName == DumpSegName) && 1427 (SectName == DumpSectName)) { 1428 1429 uint32_t section_flags; 1430 if (O->is64Bit()) { 1431 const MachO::section_64 Sec = O->getSection64(Ref); 1432 section_flags = Sec.flags; 1433 1434 } else { 1435 const MachO::section Sec = O->getSection(Ref); 1436 section_flags = Sec.flags; 1437 } 1438 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1439 1440 StringRef BytesStr; 1441 Section.getContents(BytesStr); 1442 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1443 uint32_t sect_size = BytesStr.size(); 1444 uint64_t sect_addr = Section.getAddress(); 1445 1446 outs() << "Contents of (" << SegName << "," << SectName 1447 << ") section\n"; 1448 1449 if (verbose) { 1450 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1451 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1452 DisassembleMachO(Filename, O, SegName, SectName); 1453 continue; 1454 } 1455 if (SegName == "__TEXT" && SectName == "__info_plist") { 1456 outs() << sect; 1457 continue; 1458 } 1459 if (SegName == "__OBJC" && SectName == "__protocol") { 1460 DumpProtocolSection(O, sect, sect_size, sect_addr); 1461 continue; 1462 } 1463 #ifdef HAVE_LIBXAR 1464 if (SegName == "__LLVM" && SectName == "__bundle") { 1465 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands, 1466 ArchiveHeaders, ""); 1467 continue; 1468 } 1469 #endif // defined(HAVE_LIBXAR) 1470 switch (section_type) { 1471 case MachO::S_REGULAR: 1472 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1473 break; 1474 case MachO::S_ZEROFILL: 1475 outs() << "zerofill section and has no contents in the file\n"; 1476 break; 1477 case MachO::S_CSTRING_LITERALS: 1478 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1479 break; 1480 case MachO::S_4BYTE_LITERALS: 1481 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1482 break; 1483 case MachO::S_8BYTE_LITERALS: 1484 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1485 break; 1486 case MachO::S_16BYTE_LITERALS: 1487 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1488 break; 1489 case MachO::S_LITERAL_POINTERS: 1490 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1491 !NoLeadingAddr); 1492 break; 1493 case MachO::S_MOD_INIT_FUNC_POINTERS: 1494 case MachO::S_MOD_TERM_FUNC_POINTERS: 1495 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr, 1496 &AddrMap, verbose); 1497 break; 1498 default: 1499 outs() << "Unknown section type (" 1500 << format("0x%08" PRIx32, section_type) << ")\n"; 1501 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1502 break; 1503 } 1504 } else { 1505 if (section_type == MachO::S_ZEROFILL) 1506 outs() << "zerofill section and has no contents in the file\n"; 1507 else 1508 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1509 } 1510 } 1511 } 1512 } 1513 } 1514 1515 static void DumpInfoPlistSectionContents(StringRef Filename, 1516 MachOObjectFile *O) { 1517 for (const SectionRef &Section : O->sections()) { 1518 StringRef SectName; 1519 Section.getName(SectName); 1520 DataRefImpl Ref = Section.getRawDataRefImpl(); 1521 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1522 if (SegName == "__TEXT" && SectName == "__info_plist") { 1523 if (!NoLeadingHeaders) 1524 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1525 StringRef BytesStr; 1526 Section.getContents(BytesStr); 1527 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1528 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 1529 return; 1530 } 1531 } 1532 } 1533 1534 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1535 // and if it is and there is a list of architecture flags is specified then 1536 // check to make sure this Mach-O file is one of those architectures or all 1537 // architectures were specified. If not then an error is generated and this 1538 // routine returns false. Else it returns true. 1539 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1540 auto *MachO = dyn_cast<MachOObjectFile>(O); 1541 1542 if (!MachO || ArchAll || ArchFlags.empty()) 1543 return true; 1544 1545 MachO::mach_header H; 1546 MachO::mach_header_64 H_64; 1547 Triple T; 1548 const char *McpuDefault, *ArchFlag; 1549 if (MachO->is64Bit()) { 1550 H_64 = MachO->MachOObjectFile::getHeader64(); 1551 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 1552 &McpuDefault, &ArchFlag); 1553 } else { 1554 H = MachO->MachOObjectFile::getHeader(); 1555 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 1556 &McpuDefault, &ArchFlag); 1557 } 1558 const std::string ArchFlagName(ArchFlag); 1559 if (none_of(ArchFlags, [&](const std::string &Name) { 1560 return Name == ArchFlagName; 1561 })) { 1562 errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n"; 1563 return false; 1564 } 1565 return true; 1566 } 1567 1568 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 1569 1570 // ProcessMachO() is passed a single opened Mach-O file, which may be an 1571 // archive member and or in a slice of a universal file. It prints the 1572 // the file name and header info and then processes it according to the 1573 // command line options. 1574 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 1575 StringRef ArchiveMemberName = StringRef(), 1576 StringRef ArchitectureName = StringRef()) { 1577 // If we are doing some processing here on the Mach-O file print the header 1578 // info. And don't print it otherwise like in the case of printing the 1579 // UniversalHeaders or ArchiveHeaders. 1580 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || 1581 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || 1582 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData || 1583 (FilterSections.size() != 0)) { 1584 if (!NoLeadingHeaders) { 1585 outs() << Name; 1586 if (!ArchiveMemberName.empty()) 1587 outs() << '(' << ArchiveMemberName << ')'; 1588 if (!ArchitectureName.empty()) 1589 outs() << " (architecture " << ArchitectureName << ")"; 1590 outs() << ":\n"; 1591 } 1592 } 1593 // To use the report_error() form with an ArchiveName and FileName set 1594 // these up based on what is passed for Name and ArchiveMemberName. 1595 StringRef ArchiveName; 1596 StringRef FileName; 1597 if (!ArchiveMemberName.empty()) { 1598 ArchiveName = Name; 1599 FileName = ArchiveMemberName; 1600 } else { 1601 ArchiveName = StringRef(); 1602 FileName = Name; 1603 } 1604 1605 // If we need the symbol table to do the operation then check it here to 1606 // produce a good error message as to where the Mach-O file comes from in 1607 // the error message. 1608 if (Disassemble || IndirectSymbols || FilterSections.size() != 0 || 1609 UnwindInfo) 1610 if (Error Err = MachOOF->checkSymbolTable()) 1611 report_error(ArchiveName, FileName, std::move(Err), ArchitectureName); 1612 1613 if (Disassemble) { 1614 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE && 1615 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64) 1616 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text"); 1617 else 1618 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 1619 } 1620 if (IndirectSymbols) 1621 PrintIndirectSymbols(MachOOF, !NonVerbose); 1622 if (DataInCode) 1623 PrintDataInCodeTable(MachOOF, !NonVerbose); 1624 if (LinkOptHints) 1625 PrintLinkOptHints(MachOOF); 1626 if (Relocations) 1627 PrintRelocations(MachOOF, !NonVerbose); 1628 if (SectionHeaders) 1629 PrintSectionHeaders(MachOOF); 1630 if (SectionContents) 1631 PrintSectionContents(MachOOF); 1632 if (FilterSections.size() != 0) 1633 DumpSectionContents(FileName, MachOOF, !NonVerbose); 1634 if (InfoPlist) 1635 DumpInfoPlistSectionContents(FileName, MachOOF); 1636 if (DylibsUsed) 1637 PrintDylibs(MachOOF, false); 1638 if (DylibId) 1639 PrintDylibs(MachOOF, true); 1640 if (SymbolTable) 1641 PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName); 1642 if (UnwindInfo) 1643 printMachOUnwindInfo(MachOOF); 1644 if (PrivateHeaders) { 1645 printMachOFileHeader(MachOOF); 1646 printMachOLoadCommands(MachOOF); 1647 } 1648 if (FirstPrivateHeader) 1649 printMachOFileHeader(MachOOF); 1650 if (ObjcMetaData) 1651 printObjcMetaData(MachOOF, !NonVerbose); 1652 if (ExportsTrie) 1653 printExportsTrie(MachOOF); 1654 if (Rebase) 1655 printRebaseTable(MachOOF); 1656 if (Bind) 1657 printBindTable(MachOOF); 1658 if (LazyBind) 1659 printLazyBindTable(MachOOF); 1660 if (WeakBind) 1661 printWeakBindTable(MachOOF); 1662 1663 if (DwarfDumpType != DIDT_Null) { 1664 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF); 1665 // Dump the complete DWARF structure. 1666 DIDumpOptions DumpOpts; 1667 DumpOpts.DumpType = DwarfDumpType; 1668 DICtx->dump(outs(), DumpOpts); 1669 } 1670 } 1671 1672 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 1673 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 1674 outs() << " cputype (" << cputype << ")\n"; 1675 outs() << " cpusubtype (" << cpusubtype << ")\n"; 1676 } 1677 1678 // printCPUType() helps print_fat_headers by printing the cputype and 1679 // pusubtype (symbolically for the one's it knows about). 1680 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 1681 switch (cputype) { 1682 case MachO::CPU_TYPE_I386: 1683 switch (cpusubtype) { 1684 case MachO::CPU_SUBTYPE_I386_ALL: 1685 outs() << " cputype CPU_TYPE_I386\n"; 1686 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 1687 break; 1688 default: 1689 printUnknownCPUType(cputype, cpusubtype); 1690 break; 1691 } 1692 break; 1693 case MachO::CPU_TYPE_X86_64: 1694 switch (cpusubtype) { 1695 case MachO::CPU_SUBTYPE_X86_64_ALL: 1696 outs() << " cputype CPU_TYPE_X86_64\n"; 1697 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 1698 break; 1699 case MachO::CPU_SUBTYPE_X86_64_H: 1700 outs() << " cputype CPU_TYPE_X86_64\n"; 1701 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 1702 break; 1703 default: 1704 printUnknownCPUType(cputype, cpusubtype); 1705 break; 1706 } 1707 break; 1708 case MachO::CPU_TYPE_ARM: 1709 switch (cpusubtype) { 1710 case MachO::CPU_SUBTYPE_ARM_ALL: 1711 outs() << " cputype CPU_TYPE_ARM\n"; 1712 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 1713 break; 1714 case MachO::CPU_SUBTYPE_ARM_V4T: 1715 outs() << " cputype CPU_TYPE_ARM\n"; 1716 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 1717 break; 1718 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1719 outs() << " cputype CPU_TYPE_ARM\n"; 1720 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 1721 break; 1722 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1723 outs() << " cputype CPU_TYPE_ARM\n"; 1724 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 1725 break; 1726 case MachO::CPU_SUBTYPE_ARM_V6: 1727 outs() << " cputype CPU_TYPE_ARM\n"; 1728 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 1729 break; 1730 case MachO::CPU_SUBTYPE_ARM_V6M: 1731 outs() << " cputype CPU_TYPE_ARM\n"; 1732 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 1733 break; 1734 case MachO::CPU_SUBTYPE_ARM_V7: 1735 outs() << " cputype CPU_TYPE_ARM\n"; 1736 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 1737 break; 1738 case MachO::CPU_SUBTYPE_ARM_V7EM: 1739 outs() << " cputype CPU_TYPE_ARM\n"; 1740 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 1741 break; 1742 case MachO::CPU_SUBTYPE_ARM_V7K: 1743 outs() << " cputype CPU_TYPE_ARM\n"; 1744 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 1745 break; 1746 case MachO::CPU_SUBTYPE_ARM_V7M: 1747 outs() << " cputype CPU_TYPE_ARM\n"; 1748 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 1749 break; 1750 case MachO::CPU_SUBTYPE_ARM_V7S: 1751 outs() << " cputype CPU_TYPE_ARM\n"; 1752 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 1753 break; 1754 default: 1755 printUnknownCPUType(cputype, cpusubtype); 1756 break; 1757 } 1758 break; 1759 case MachO::CPU_TYPE_ARM64: 1760 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 1761 case MachO::CPU_SUBTYPE_ARM64_ALL: 1762 outs() << " cputype CPU_TYPE_ARM64\n"; 1763 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 1764 break; 1765 default: 1766 printUnknownCPUType(cputype, cpusubtype); 1767 break; 1768 } 1769 break; 1770 default: 1771 printUnknownCPUType(cputype, cpusubtype); 1772 break; 1773 } 1774 } 1775 1776 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 1777 bool verbose) { 1778 outs() << "Fat headers\n"; 1779 if (verbose) { 1780 if (UB->getMagic() == MachO::FAT_MAGIC) 1781 outs() << "fat_magic FAT_MAGIC\n"; 1782 else // UB->getMagic() == MachO::FAT_MAGIC_64 1783 outs() << "fat_magic FAT_MAGIC_64\n"; 1784 } else 1785 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 1786 1787 uint32_t nfat_arch = UB->getNumberOfObjects(); 1788 StringRef Buf = UB->getData(); 1789 uint64_t size = Buf.size(); 1790 uint64_t big_size = sizeof(struct MachO::fat_header) + 1791 nfat_arch * sizeof(struct MachO::fat_arch); 1792 outs() << "nfat_arch " << UB->getNumberOfObjects(); 1793 if (nfat_arch == 0) 1794 outs() << " (malformed, contains zero architecture types)\n"; 1795 else if (big_size > size) 1796 outs() << " (malformed, architectures past end of file)\n"; 1797 else 1798 outs() << "\n"; 1799 1800 for (uint32_t i = 0; i < nfat_arch; ++i) { 1801 MachOUniversalBinary::ObjectForArch OFA(UB, i); 1802 uint32_t cputype = OFA.getCPUType(); 1803 uint32_t cpusubtype = OFA.getCPUSubType(); 1804 outs() << "architecture "; 1805 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 1806 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 1807 uint32_t other_cputype = other_OFA.getCPUType(); 1808 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 1809 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 1810 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 1811 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 1812 outs() << "(illegal duplicate architecture) "; 1813 break; 1814 } 1815 } 1816 if (verbose) { 1817 outs() << OFA.getArchFlagName() << "\n"; 1818 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 1819 } else { 1820 outs() << i << "\n"; 1821 outs() << " cputype " << cputype << "\n"; 1822 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 1823 << "\n"; 1824 } 1825 if (verbose && 1826 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 1827 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 1828 else 1829 outs() << " capabilities " 1830 << format("0x%" PRIx32, 1831 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 1832 outs() << " offset " << OFA.getOffset(); 1833 if (OFA.getOffset() > size) 1834 outs() << " (past end of file)"; 1835 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0) 1836 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 1837 outs() << "\n"; 1838 outs() << " size " << OFA.getSize(); 1839 big_size = OFA.getOffset() + OFA.getSize(); 1840 if (big_size > size) 1841 outs() << " (past end of file)"; 1842 outs() << "\n"; 1843 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 1844 << ")\n"; 1845 } 1846 } 1847 1848 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 1849 bool verbose, bool print_offset, 1850 StringRef ArchitectureName = StringRef()) { 1851 if (print_offset) 1852 outs() << C.getChildOffset() << "\t"; 1853 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode(); 1854 if (!ModeOrErr) 1855 report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName); 1856 sys::fs::perms Mode = ModeOrErr.get(); 1857 if (verbose) { 1858 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 1859 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 1860 outs() << "-"; 1861 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 1862 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 1863 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 1864 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 1865 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 1866 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 1867 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 1868 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 1869 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 1870 } else { 1871 outs() << format("0%o ", Mode); 1872 } 1873 1874 Expected<unsigned> UIDOrErr = C.getUID(); 1875 if (!UIDOrErr) 1876 report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName); 1877 unsigned UID = UIDOrErr.get(); 1878 outs() << format("%3d/", UID); 1879 Expected<unsigned> GIDOrErr = C.getGID(); 1880 if (!GIDOrErr) 1881 report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName); 1882 unsigned GID = GIDOrErr.get(); 1883 outs() << format("%-3d ", GID); 1884 Expected<uint64_t> Size = C.getRawSize(); 1885 if (!Size) 1886 report_error(Filename, C, Size.takeError(), ArchitectureName); 1887 outs() << format("%5" PRId64, Size.get()) << " "; 1888 1889 StringRef RawLastModified = C.getRawLastModified(); 1890 if (verbose) { 1891 unsigned Seconds; 1892 if (RawLastModified.getAsInteger(10, Seconds)) 1893 outs() << "(date: \"" << RawLastModified 1894 << "\" contains non-decimal chars) "; 1895 else { 1896 // Since cime(3) returns a 26 character string of the form: 1897 // "Sun Sep 16 01:03:52 1973\n\0" 1898 // just print 24 characters. 1899 time_t t = Seconds; 1900 outs() << format("%.24s ", ctime(&t)); 1901 } 1902 } else { 1903 outs() << RawLastModified << " "; 1904 } 1905 1906 if (verbose) { 1907 Expected<StringRef> NameOrErr = C.getName(); 1908 if (!NameOrErr) { 1909 consumeError(NameOrErr.takeError()); 1910 Expected<StringRef> NameOrErr = C.getRawName(); 1911 if (!NameOrErr) 1912 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1913 StringRef RawName = NameOrErr.get(); 1914 outs() << RawName << "\n"; 1915 } else { 1916 StringRef Name = NameOrErr.get(); 1917 outs() << Name << "\n"; 1918 } 1919 } else { 1920 Expected<StringRef> NameOrErr = C.getRawName(); 1921 if (!NameOrErr) 1922 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1923 StringRef RawName = NameOrErr.get(); 1924 outs() << RawName << "\n"; 1925 } 1926 } 1927 1928 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 1929 bool print_offset, 1930 StringRef ArchitectureName = StringRef()) { 1931 Error Err = Error::success(); 1932 ; 1933 for (const auto &C : A->children(Err, false)) 1934 printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName); 1935 1936 if (Err) 1937 report_error(StringRef(), Filename, std::move(Err), ArchitectureName); 1938 } 1939 1940 static bool ValidateArchFlags() { 1941 // Check for -arch all and verifiy the -arch flags are valid. 1942 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 1943 if (ArchFlags[i] == "all") { 1944 ArchAll = true; 1945 } else { 1946 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 1947 errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] + 1948 "'for the -arch option\n"; 1949 return false; 1950 } 1951 } 1952 } 1953 return true; 1954 } 1955 1956 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 1957 // -arch flags selecting just those slices as specified by them and also parses 1958 // archive files. Then for each individual Mach-O file ProcessMachO() is 1959 // called to process the file based on the command line options. 1960 void llvm::ParseInputMachO(StringRef Filename) { 1961 if (!ValidateArchFlags()) 1962 return; 1963 1964 // Attempt to open the binary. 1965 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 1966 if (!BinaryOrErr) { 1967 if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 1968 report_error(Filename, std::move(E)); 1969 else 1970 outs() << Filename << ": is not an object file\n"; 1971 return; 1972 } 1973 Binary &Bin = *BinaryOrErr.get().getBinary(); 1974 1975 if (Archive *A = dyn_cast<Archive>(&Bin)) { 1976 outs() << "Archive : " << Filename << "\n"; 1977 if (ArchiveHeaders) 1978 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets); 1979 1980 Error Err = Error::success(); 1981 for (auto &C : A->children(Err)) { 1982 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 1983 if (!ChildOrErr) { 1984 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 1985 report_error(Filename, C, std::move(E)); 1986 continue; 1987 } 1988 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 1989 if (!checkMachOAndArchFlags(O, Filename)) 1990 return; 1991 ProcessMachO(Filename, O, O->getFileName()); 1992 } 1993 } 1994 if (Err) 1995 report_error(Filename, std::move(Err)); 1996 return; 1997 } 1998 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 1999 ParseInputMachO(UB); 2000 return; 2001 } 2002 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2003 if (!checkMachOAndArchFlags(O, Filename)) 2004 return; 2005 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) 2006 ProcessMachO(Filename, MachOOF); 2007 else 2008 errs() << "llvm-objdump: '" << Filename << "': " 2009 << "Object is not a Mach-O file type.\n"; 2010 return; 2011 } 2012 llvm_unreachable("Input object can't be invalid at this point"); 2013 } 2014 2015 void llvm::ParseInputMachO(MachOUniversalBinary *UB) { 2016 if (!ValidateArchFlags()) 2017 return; 2018 2019 auto Filename = UB->getFileName(); 2020 2021 if (UniversalHeaders) 2022 printMachOUniversalHeaders(UB, !NonVerbose); 2023 2024 // If we have a list of architecture flags specified dump only those. 2025 if (!ArchAll && ArchFlags.size() != 0) { 2026 // Look for a slice in the universal binary that matches each ArchFlag. 2027 bool ArchFound; 2028 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2029 ArchFound = false; 2030 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2031 E = UB->end_objects(); 2032 I != E; ++I) { 2033 if (ArchFlags[i] == I->getArchFlagName()) { 2034 ArchFound = true; 2035 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2036 I->getAsObjectFile(); 2037 std::string ArchitectureName = ""; 2038 if (ArchFlags.size() > 1) 2039 ArchitectureName = I->getArchFlagName(); 2040 if (ObjOrErr) { 2041 ObjectFile &O = *ObjOrErr.get(); 2042 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2043 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2044 } else if (auto E = isNotObjectErrorInvalidFileType( 2045 ObjOrErr.takeError())) { 2046 report_error(Filename, StringRef(), std::move(E), 2047 ArchitectureName); 2048 continue; 2049 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2050 I->getAsArchive()) { 2051 std::unique_ptr<Archive> &A = *AOrErr; 2052 outs() << "Archive : " << Filename; 2053 if (!ArchitectureName.empty()) 2054 outs() << " (architecture " << ArchitectureName << ")"; 2055 outs() << "\n"; 2056 if (ArchiveHeaders) 2057 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2058 ArchiveMemberOffsets, ArchitectureName); 2059 Error Err = Error::success(); 2060 for (auto &C : A->children(Err)) { 2061 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2062 if (!ChildOrErr) { 2063 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2064 report_error(Filename, C, std::move(E), ArchitectureName); 2065 continue; 2066 } 2067 if (MachOObjectFile *O = 2068 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2069 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2070 } 2071 if (Err) 2072 report_error(Filename, std::move(Err)); 2073 } else { 2074 consumeError(AOrErr.takeError()); 2075 error("Mach-O universal file: " + Filename + " for " + 2076 "architecture " + StringRef(I->getArchFlagName()) + 2077 " is not a Mach-O file or an archive file"); 2078 } 2079 } 2080 } 2081 if (!ArchFound) { 2082 errs() << "llvm-objdump: file: " + Filename + " does not contain " 2083 << "architecture: " + ArchFlags[i] + "\n"; 2084 return; 2085 } 2086 } 2087 return; 2088 } 2089 // No architecture flags were specified so if this contains a slice that 2090 // matches the host architecture dump only that. 2091 if (!ArchAll) { 2092 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2093 E = UB->end_objects(); 2094 I != E; ++I) { 2095 if (MachOObjectFile::getHostArch().getArchName() == 2096 I->getArchFlagName()) { 2097 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2098 std::string ArchiveName; 2099 ArchiveName.clear(); 2100 if (ObjOrErr) { 2101 ObjectFile &O = *ObjOrErr.get(); 2102 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2103 ProcessMachO(Filename, MachOOF); 2104 } else if (auto E = isNotObjectErrorInvalidFileType( 2105 ObjOrErr.takeError())) { 2106 report_error(Filename, std::move(E)); 2107 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2108 I->getAsArchive()) { 2109 std::unique_ptr<Archive> &A = *AOrErr; 2110 outs() << "Archive : " << Filename << "\n"; 2111 if (ArchiveHeaders) 2112 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2113 ArchiveMemberOffsets); 2114 Error Err = Error::success(); 2115 for (auto &C : A->children(Err)) { 2116 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2117 if (!ChildOrErr) { 2118 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2119 report_error(Filename, C, std::move(E)); 2120 continue; 2121 } 2122 if (MachOObjectFile *O = 2123 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2124 ProcessMachO(Filename, O, O->getFileName()); 2125 } 2126 if (Err) 2127 report_error(Filename, std::move(Err)); 2128 } else { 2129 consumeError(AOrErr.takeError()); 2130 error("Mach-O universal file: " + Filename + " for architecture " + 2131 StringRef(I->getArchFlagName()) + 2132 " is not a Mach-O file or an archive file"); 2133 } 2134 return; 2135 } 2136 } 2137 } 2138 // Either all architectures have been specified or none have been specified 2139 // and this does not contain the host architecture so dump all the slices. 2140 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2141 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2142 E = UB->end_objects(); 2143 I != E; ++I) { 2144 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2145 std::string ArchitectureName = ""; 2146 if (moreThanOneArch) 2147 ArchitectureName = I->getArchFlagName(); 2148 if (ObjOrErr) { 2149 ObjectFile &Obj = *ObjOrErr.get(); 2150 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2151 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2152 } else if (auto E = isNotObjectErrorInvalidFileType( 2153 ObjOrErr.takeError())) { 2154 report_error(StringRef(), Filename, std::move(E), ArchitectureName); 2155 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2156 I->getAsArchive()) { 2157 std::unique_ptr<Archive> &A = *AOrErr; 2158 outs() << "Archive : " << Filename; 2159 if (!ArchitectureName.empty()) 2160 outs() << " (architecture " << ArchitectureName << ")"; 2161 outs() << "\n"; 2162 if (ArchiveHeaders) 2163 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2164 ArchiveMemberOffsets, ArchitectureName); 2165 Error Err = Error::success(); 2166 for (auto &C : A->children(Err)) { 2167 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2168 if (!ChildOrErr) { 2169 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2170 report_error(Filename, C, std::move(E), ArchitectureName); 2171 continue; 2172 } 2173 if (MachOObjectFile *O = 2174 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2175 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2176 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2177 ArchitectureName); 2178 } 2179 } 2180 if (Err) 2181 report_error(Filename, std::move(Err)); 2182 } else { 2183 consumeError(AOrErr.takeError()); 2184 error("Mach-O universal file: " + Filename + " for architecture " + 2185 StringRef(I->getArchFlagName()) + 2186 " is not a Mach-O file or an archive file"); 2187 } 2188 } 2189 } 2190 2191 // The block of info used by the Symbolizer call backs. 2192 struct DisassembleInfo { 2193 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, 2194 std::vector<SectionRef> *Sections, bool verbose) 2195 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {} 2196 bool verbose; 2197 MachOObjectFile *O; 2198 SectionRef S; 2199 SymbolAddressMap *AddrMap; 2200 std::vector<SectionRef> *Sections; 2201 const char *class_name = nullptr; 2202 const char *selector_name = nullptr; 2203 std::unique_ptr<char[]> method = nullptr; 2204 char *demangled_name = nullptr; 2205 uint64_t adrp_addr = 0; 2206 uint32_t adrp_inst = 0; 2207 std::unique_ptr<SymbolAddressMap> bindtable; 2208 uint32_t depth = 0; 2209 }; 2210 2211 // SymbolizerGetOpInfo() is the operand information call back function. 2212 // This is called to get the symbolic information for operand(s) of an 2213 // instruction when it is being done. This routine does this from 2214 // the relocation information, symbol table, etc. That block of information 2215 // is a pointer to the struct DisassembleInfo that was passed when the 2216 // disassembler context was created and passed to back to here when 2217 // called back by the disassembler for instruction operands that could have 2218 // relocation information. The address of the instruction containing operand is 2219 // at the Pc parameter. The immediate value the operand has is passed in 2220 // op_info->Value and is at Offset past the start of the instruction and has a 2221 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2222 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2223 // names and addends of the symbolic expression to add for the operand. The 2224 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2225 // information is returned then this function returns 1 else it returns 0. 2226 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2227 uint64_t Size, int TagType, void *TagBuf) { 2228 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2229 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2230 uint64_t value = op_info->Value; 2231 2232 // Make sure all fields returned are zero if we don't set them. 2233 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2234 op_info->Value = value; 2235 2236 // If the TagType is not the value 1 which it code knows about or if no 2237 // verbose symbolic information is wanted then just return 0, indicating no 2238 // information is being returned. 2239 if (TagType != 1 || !info->verbose) 2240 return 0; 2241 2242 unsigned int Arch = info->O->getArch(); 2243 if (Arch == Triple::x86) { 2244 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2245 return 0; 2246 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2247 // TODO: 2248 // Search the external relocation entries of a fully linked image 2249 // (if any) for an entry that matches this segment offset. 2250 // uint32_t seg_offset = (Pc + Offset); 2251 return 0; 2252 } 2253 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2254 // for an entry for this section offset. 2255 uint32_t sect_addr = info->S.getAddress(); 2256 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2257 bool reloc_found = false; 2258 DataRefImpl Rel; 2259 MachO::any_relocation_info RE; 2260 bool isExtern = false; 2261 SymbolRef Symbol; 2262 bool r_scattered = false; 2263 uint32_t r_value, pair_r_value, r_type; 2264 for (const RelocationRef &Reloc : info->S.relocations()) { 2265 uint64_t RelocOffset = Reloc.getOffset(); 2266 if (RelocOffset == sect_offset) { 2267 Rel = Reloc.getRawDataRefImpl(); 2268 RE = info->O->getRelocation(Rel); 2269 r_type = info->O->getAnyRelocationType(RE); 2270 r_scattered = info->O->isRelocationScattered(RE); 2271 if (r_scattered) { 2272 r_value = info->O->getScatteredRelocationValue(RE); 2273 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2274 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2275 DataRefImpl RelNext = Rel; 2276 info->O->moveRelocationNext(RelNext); 2277 MachO::any_relocation_info RENext; 2278 RENext = info->O->getRelocation(RelNext); 2279 if (info->O->isRelocationScattered(RENext)) 2280 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2281 else 2282 return 0; 2283 } 2284 } else { 2285 isExtern = info->O->getPlainRelocationExternal(RE); 2286 if (isExtern) { 2287 symbol_iterator RelocSym = Reloc.getSymbol(); 2288 Symbol = *RelocSym; 2289 } 2290 } 2291 reloc_found = true; 2292 break; 2293 } 2294 } 2295 if (reloc_found && isExtern) { 2296 Expected<StringRef> SymName = Symbol.getName(); 2297 if (!SymName) 2298 report_error(info->O->getFileName(), SymName.takeError()); 2299 const char *name = SymName->data(); 2300 op_info->AddSymbol.Present = 1; 2301 op_info->AddSymbol.Name = name; 2302 // For i386 extern relocation entries the value in the instruction is 2303 // the offset from the symbol, and value is already set in op_info->Value. 2304 return 1; 2305 } 2306 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2307 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2308 const char *add = GuessSymbolName(r_value, info->AddrMap); 2309 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2310 uint32_t offset = value - (r_value - pair_r_value); 2311 op_info->AddSymbol.Present = 1; 2312 if (add != nullptr) 2313 op_info->AddSymbol.Name = add; 2314 else 2315 op_info->AddSymbol.Value = r_value; 2316 op_info->SubtractSymbol.Present = 1; 2317 if (sub != nullptr) 2318 op_info->SubtractSymbol.Name = sub; 2319 else 2320 op_info->SubtractSymbol.Value = pair_r_value; 2321 op_info->Value = offset; 2322 return 1; 2323 } 2324 return 0; 2325 } 2326 if (Arch == Triple::x86_64) { 2327 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2328 return 0; 2329 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2330 // relocation entries of a linked image (if any) for an entry that matches 2331 // this segment offset. 2332 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2333 uint64_t seg_offset = Pc + Offset; 2334 bool reloc_found = false; 2335 DataRefImpl Rel; 2336 MachO::any_relocation_info RE; 2337 bool isExtern = false; 2338 SymbolRef Symbol; 2339 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2340 uint64_t RelocOffset = Reloc.getOffset(); 2341 if (RelocOffset == seg_offset) { 2342 Rel = Reloc.getRawDataRefImpl(); 2343 RE = info->O->getRelocation(Rel); 2344 // external relocation entries should always be external. 2345 isExtern = info->O->getPlainRelocationExternal(RE); 2346 if (isExtern) { 2347 symbol_iterator RelocSym = Reloc.getSymbol(); 2348 Symbol = *RelocSym; 2349 } 2350 reloc_found = true; 2351 break; 2352 } 2353 } 2354 if (reloc_found && isExtern) { 2355 // The Value passed in will be adjusted by the Pc if the instruction 2356 // adds the Pc. But for x86_64 external relocation entries the Value 2357 // is the offset from the external symbol. 2358 if (info->O->getAnyRelocationPCRel(RE)) 2359 op_info->Value -= Pc + Offset + Size; 2360 Expected<StringRef> SymName = Symbol.getName(); 2361 if (!SymName) 2362 report_error(info->O->getFileName(), SymName.takeError()); 2363 const char *name = SymName->data(); 2364 op_info->AddSymbol.Present = 1; 2365 op_info->AddSymbol.Name = name; 2366 return 1; 2367 } 2368 return 0; 2369 } 2370 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2371 // for an entry for this section offset. 2372 uint64_t sect_addr = info->S.getAddress(); 2373 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2374 bool reloc_found = false; 2375 DataRefImpl Rel; 2376 MachO::any_relocation_info RE; 2377 bool isExtern = false; 2378 SymbolRef Symbol; 2379 for (const RelocationRef &Reloc : info->S.relocations()) { 2380 uint64_t RelocOffset = Reloc.getOffset(); 2381 if (RelocOffset == sect_offset) { 2382 Rel = Reloc.getRawDataRefImpl(); 2383 RE = info->O->getRelocation(Rel); 2384 // NOTE: Scattered relocations don't exist on x86_64. 2385 isExtern = info->O->getPlainRelocationExternal(RE); 2386 if (isExtern) { 2387 symbol_iterator RelocSym = Reloc.getSymbol(); 2388 Symbol = *RelocSym; 2389 } 2390 reloc_found = true; 2391 break; 2392 } 2393 } 2394 if (reloc_found && isExtern) { 2395 // The Value passed in will be adjusted by the Pc if the instruction 2396 // adds the Pc. But for x86_64 external relocation entries the Value 2397 // is the offset from the external symbol. 2398 if (info->O->getAnyRelocationPCRel(RE)) 2399 op_info->Value -= Pc + Offset + Size; 2400 Expected<StringRef> SymName = Symbol.getName(); 2401 if (!SymName) 2402 report_error(info->O->getFileName(), SymName.takeError()); 2403 const char *name = SymName->data(); 2404 unsigned Type = info->O->getAnyRelocationType(RE); 2405 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2406 DataRefImpl RelNext = Rel; 2407 info->O->moveRelocationNext(RelNext); 2408 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2409 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2410 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2411 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2412 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2413 op_info->SubtractSymbol.Present = 1; 2414 op_info->SubtractSymbol.Name = name; 2415 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2416 Symbol = *RelocSymNext; 2417 Expected<StringRef> SymNameNext = Symbol.getName(); 2418 if (!SymNameNext) 2419 report_error(info->O->getFileName(), SymNameNext.takeError()); 2420 name = SymNameNext->data(); 2421 } 2422 } 2423 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 2424 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 2425 op_info->AddSymbol.Present = 1; 2426 op_info->AddSymbol.Name = name; 2427 return 1; 2428 } 2429 return 0; 2430 } 2431 if (Arch == Triple::arm) { 2432 if (Offset != 0 || (Size != 4 && Size != 2)) 2433 return 0; 2434 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2435 // TODO: 2436 // Search the external relocation entries of a fully linked image 2437 // (if any) for an entry that matches this segment offset. 2438 // uint32_t seg_offset = (Pc + Offset); 2439 return 0; 2440 } 2441 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2442 // for an entry for this section offset. 2443 uint32_t sect_addr = info->S.getAddress(); 2444 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2445 DataRefImpl Rel; 2446 MachO::any_relocation_info RE; 2447 bool isExtern = false; 2448 SymbolRef Symbol; 2449 bool r_scattered = false; 2450 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 2451 auto Reloc = 2452 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2453 uint64_t RelocOffset = Reloc.getOffset(); 2454 return RelocOffset == sect_offset; 2455 }); 2456 2457 if (Reloc == info->S.relocations().end()) 2458 return 0; 2459 2460 Rel = Reloc->getRawDataRefImpl(); 2461 RE = info->O->getRelocation(Rel); 2462 r_length = info->O->getAnyRelocationLength(RE); 2463 r_scattered = info->O->isRelocationScattered(RE); 2464 if (r_scattered) { 2465 r_value = info->O->getScatteredRelocationValue(RE); 2466 r_type = info->O->getScatteredRelocationType(RE); 2467 } else { 2468 r_type = info->O->getAnyRelocationType(RE); 2469 isExtern = info->O->getPlainRelocationExternal(RE); 2470 if (isExtern) { 2471 symbol_iterator RelocSym = Reloc->getSymbol(); 2472 Symbol = *RelocSym; 2473 } 2474 } 2475 if (r_type == MachO::ARM_RELOC_HALF || 2476 r_type == MachO::ARM_RELOC_SECTDIFF || 2477 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 2478 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2479 DataRefImpl RelNext = Rel; 2480 info->O->moveRelocationNext(RelNext); 2481 MachO::any_relocation_info RENext; 2482 RENext = info->O->getRelocation(RelNext); 2483 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 2484 if (info->O->isRelocationScattered(RENext)) 2485 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2486 } 2487 2488 if (isExtern) { 2489 Expected<StringRef> SymName = Symbol.getName(); 2490 if (!SymName) 2491 report_error(info->O->getFileName(), SymName.takeError()); 2492 const char *name = SymName->data(); 2493 op_info->AddSymbol.Present = 1; 2494 op_info->AddSymbol.Name = name; 2495 switch (r_type) { 2496 case MachO::ARM_RELOC_HALF: 2497 if ((r_length & 0x1) == 1) { 2498 op_info->Value = value << 16 | other_half; 2499 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2500 } else { 2501 op_info->Value = other_half << 16 | value; 2502 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2503 } 2504 break; 2505 default: 2506 break; 2507 } 2508 return 1; 2509 } 2510 // If we have a branch that is not an external relocation entry then 2511 // return 0 so the code in tryAddingSymbolicOperand() can use the 2512 // SymbolLookUp call back with the branch target address to look up the 2513 // symbol and possibility add an annotation for a symbol stub. 2514 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 2515 r_type == MachO::ARM_THUMB_RELOC_BR22)) 2516 return 0; 2517 2518 uint32_t offset = 0; 2519 if (r_type == MachO::ARM_RELOC_HALF || 2520 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2521 if ((r_length & 0x1) == 1) 2522 value = value << 16 | other_half; 2523 else 2524 value = other_half << 16 | value; 2525 } 2526 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 2527 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 2528 offset = value - r_value; 2529 value = r_value; 2530 } 2531 2532 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2533 if ((r_length & 0x1) == 1) 2534 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2535 else 2536 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2537 const char *add = GuessSymbolName(r_value, info->AddrMap); 2538 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2539 int32_t offset = value - (r_value - pair_r_value); 2540 op_info->AddSymbol.Present = 1; 2541 if (add != nullptr) 2542 op_info->AddSymbol.Name = add; 2543 else 2544 op_info->AddSymbol.Value = r_value; 2545 op_info->SubtractSymbol.Present = 1; 2546 if (sub != nullptr) 2547 op_info->SubtractSymbol.Name = sub; 2548 else 2549 op_info->SubtractSymbol.Value = pair_r_value; 2550 op_info->Value = offset; 2551 return 1; 2552 } 2553 2554 op_info->AddSymbol.Present = 1; 2555 op_info->Value = offset; 2556 if (r_type == MachO::ARM_RELOC_HALF) { 2557 if ((r_length & 0x1) == 1) 2558 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2559 else 2560 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2561 } 2562 const char *add = GuessSymbolName(value, info->AddrMap); 2563 if (add != nullptr) { 2564 op_info->AddSymbol.Name = add; 2565 return 1; 2566 } 2567 op_info->AddSymbol.Value = value; 2568 return 1; 2569 } 2570 if (Arch == Triple::aarch64) { 2571 if (Offset != 0 || Size != 4) 2572 return 0; 2573 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2574 // TODO: 2575 // Search the external relocation entries of a fully linked image 2576 // (if any) for an entry that matches this segment offset. 2577 // uint64_t seg_offset = (Pc + Offset); 2578 return 0; 2579 } 2580 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2581 // for an entry for this section offset. 2582 uint64_t sect_addr = info->S.getAddress(); 2583 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2584 auto Reloc = 2585 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2586 uint64_t RelocOffset = Reloc.getOffset(); 2587 return RelocOffset == sect_offset; 2588 }); 2589 2590 if (Reloc == info->S.relocations().end()) 2591 return 0; 2592 2593 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2594 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 2595 uint32_t r_type = info->O->getAnyRelocationType(RE); 2596 if (r_type == MachO::ARM64_RELOC_ADDEND) { 2597 DataRefImpl RelNext = Rel; 2598 info->O->moveRelocationNext(RelNext); 2599 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2600 if (value == 0) { 2601 value = info->O->getPlainRelocationSymbolNum(RENext); 2602 op_info->Value = value; 2603 } 2604 } 2605 // NOTE: Scattered relocations don't exist on arm64. 2606 if (!info->O->getPlainRelocationExternal(RE)) 2607 return 0; 2608 Expected<StringRef> SymName = Reloc->getSymbol()->getName(); 2609 if (!SymName) 2610 report_error(info->O->getFileName(), SymName.takeError()); 2611 const char *name = SymName->data(); 2612 op_info->AddSymbol.Present = 1; 2613 op_info->AddSymbol.Name = name; 2614 2615 switch (r_type) { 2616 case MachO::ARM64_RELOC_PAGE21: 2617 /* @page */ 2618 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 2619 break; 2620 case MachO::ARM64_RELOC_PAGEOFF12: 2621 /* @pageoff */ 2622 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 2623 break; 2624 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 2625 /* @gotpage */ 2626 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 2627 break; 2628 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 2629 /* @gotpageoff */ 2630 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 2631 break; 2632 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 2633 /* @tvlppage is not implemented in llvm-mc */ 2634 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 2635 break; 2636 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 2637 /* @tvlppageoff is not implemented in llvm-mc */ 2638 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 2639 break; 2640 default: 2641 case MachO::ARM64_RELOC_BRANCH26: 2642 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 2643 break; 2644 } 2645 return 1; 2646 } 2647 return 0; 2648 } 2649 2650 // GuessCstringPointer is passed the address of what might be a pointer to a 2651 // literal string in a cstring section. If that address is in a cstring section 2652 // it returns a pointer to that string. Else it returns nullptr. 2653 static const char *GuessCstringPointer(uint64_t ReferenceValue, 2654 struct DisassembleInfo *info) { 2655 for (const auto &Load : info->O->load_commands()) { 2656 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2657 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2658 for (unsigned J = 0; J < Seg.nsects; ++J) { 2659 MachO::section_64 Sec = info->O->getSection64(Load, J); 2660 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2661 if (section_type == MachO::S_CSTRING_LITERALS && 2662 ReferenceValue >= Sec.addr && 2663 ReferenceValue < Sec.addr + Sec.size) { 2664 uint64_t sect_offset = ReferenceValue - Sec.addr; 2665 uint64_t object_offset = Sec.offset + sect_offset; 2666 StringRef MachOContents = info->O->getData(); 2667 uint64_t object_size = MachOContents.size(); 2668 const char *object_addr = (const char *)MachOContents.data(); 2669 if (object_offset < object_size) { 2670 const char *name = object_addr + object_offset; 2671 return name; 2672 } else { 2673 return nullptr; 2674 } 2675 } 2676 } 2677 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2678 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2679 for (unsigned J = 0; J < Seg.nsects; ++J) { 2680 MachO::section Sec = info->O->getSection(Load, J); 2681 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2682 if (section_type == MachO::S_CSTRING_LITERALS && 2683 ReferenceValue >= Sec.addr && 2684 ReferenceValue < Sec.addr + Sec.size) { 2685 uint64_t sect_offset = ReferenceValue - Sec.addr; 2686 uint64_t object_offset = Sec.offset + sect_offset; 2687 StringRef MachOContents = info->O->getData(); 2688 uint64_t object_size = MachOContents.size(); 2689 const char *object_addr = (const char *)MachOContents.data(); 2690 if (object_offset < object_size) { 2691 const char *name = object_addr + object_offset; 2692 return name; 2693 } else { 2694 return nullptr; 2695 } 2696 } 2697 } 2698 } 2699 } 2700 return nullptr; 2701 } 2702 2703 // GuessIndirectSymbol returns the name of the indirect symbol for the 2704 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 2705 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 2706 // symbol name being referenced by the stub or pointer. 2707 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 2708 struct DisassembleInfo *info) { 2709 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 2710 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 2711 for (const auto &Load : info->O->load_commands()) { 2712 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2713 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2714 for (unsigned J = 0; J < Seg.nsects; ++J) { 2715 MachO::section_64 Sec = info->O->getSection64(Load, J); 2716 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2717 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2718 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2719 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2720 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2721 section_type == MachO::S_SYMBOL_STUBS) && 2722 ReferenceValue >= Sec.addr && 2723 ReferenceValue < Sec.addr + Sec.size) { 2724 uint32_t stride; 2725 if (section_type == MachO::S_SYMBOL_STUBS) 2726 stride = Sec.reserved2; 2727 else 2728 stride = 8; 2729 if (stride == 0) 2730 return nullptr; 2731 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2732 if (index < Dysymtab.nindirectsyms) { 2733 uint32_t indirect_symbol = 2734 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2735 if (indirect_symbol < Symtab.nsyms) { 2736 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2737 SymbolRef Symbol = *Sym; 2738 Expected<StringRef> SymName = Symbol.getName(); 2739 if (!SymName) 2740 report_error(info->O->getFileName(), SymName.takeError()); 2741 const char *name = SymName->data(); 2742 return name; 2743 } 2744 } 2745 } 2746 } 2747 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2748 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2749 for (unsigned J = 0; J < Seg.nsects; ++J) { 2750 MachO::section Sec = info->O->getSection(Load, J); 2751 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2752 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2753 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2754 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2755 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2756 section_type == MachO::S_SYMBOL_STUBS) && 2757 ReferenceValue >= Sec.addr && 2758 ReferenceValue < Sec.addr + Sec.size) { 2759 uint32_t stride; 2760 if (section_type == MachO::S_SYMBOL_STUBS) 2761 stride = Sec.reserved2; 2762 else 2763 stride = 4; 2764 if (stride == 0) 2765 return nullptr; 2766 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2767 if (index < Dysymtab.nindirectsyms) { 2768 uint32_t indirect_symbol = 2769 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2770 if (indirect_symbol < Symtab.nsyms) { 2771 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2772 SymbolRef Symbol = *Sym; 2773 Expected<StringRef> SymName = Symbol.getName(); 2774 if (!SymName) 2775 report_error(info->O->getFileName(), SymName.takeError()); 2776 const char *name = SymName->data(); 2777 return name; 2778 } 2779 } 2780 } 2781 } 2782 } 2783 } 2784 return nullptr; 2785 } 2786 2787 // method_reference() is called passing it the ReferenceName that might be 2788 // a reference it to an Objective-C method call. If so then it allocates and 2789 // assembles a method call string with the values last seen and saved in 2790 // the DisassembleInfo's class_name and selector_name fields. This is saved 2791 // into the method field of the info and any previous string is free'ed. 2792 // Then the class_name field in the info is set to nullptr. The method call 2793 // string is set into ReferenceName and ReferenceType is set to 2794 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 2795 // then both ReferenceType and ReferenceName are left unchanged. 2796 static void method_reference(struct DisassembleInfo *info, 2797 uint64_t *ReferenceType, 2798 const char **ReferenceName) { 2799 unsigned int Arch = info->O->getArch(); 2800 if (*ReferenceName != nullptr) { 2801 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 2802 if (info->selector_name != nullptr) { 2803 if (info->class_name != nullptr) { 2804 info->method = llvm::make_unique<char[]>( 2805 5 + strlen(info->class_name) + strlen(info->selector_name)); 2806 char *method = info->method.get(); 2807 if (method != nullptr) { 2808 strcpy(method, "+["); 2809 strcat(method, info->class_name); 2810 strcat(method, " "); 2811 strcat(method, info->selector_name); 2812 strcat(method, "]"); 2813 *ReferenceName = method; 2814 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2815 } 2816 } else { 2817 info->method = 2818 llvm::make_unique<char[]>(9 + strlen(info->selector_name)); 2819 char *method = info->method.get(); 2820 if (method != nullptr) { 2821 if (Arch == Triple::x86_64) 2822 strcpy(method, "-[%rdi "); 2823 else if (Arch == Triple::aarch64) 2824 strcpy(method, "-[x0 "); 2825 else 2826 strcpy(method, "-[r? "); 2827 strcat(method, info->selector_name); 2828 strcat(method, "]"); 2829 *ReferenceName = method; 2830 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2831 } 2832 } 2833 info->class_name = nullptr; 2834 } 2835 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 2836 if (info->selector_name != nullptr) { 2837 info->method = 2838 llvm::make_unique<char[]>(17 + strlen(info->selector_name)); 2839 char *method = info->method.get(); 2840 if (method != nullptr) { 2841 if (Arch == Triple::x86_64) 2842 strcpy(method, "-[[%rdi super] "); 2843 else if (Arch == Triple::aarch64) 2844 strcpy(method, "-[[x0 super] "); 2845 else 2846 strcpy(method, "-[[r? super] "); 2847 strcat(method, info->selector_name); 2848 strcat(method, "]"); 2849 *ReferenceName = method; 2850 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2851 } 2852 info->class_name = nullptr; 2853 } 2854 } 2855 } 2856 } 2857 2858 // GuessPointerPointer() is passed the address of what might be a pointer to 2859 // a reference to an Objective-C class, selector, message ref or cfstring. 2860 // If so the value of the pointer is returned and one of the booleans are set 2861 // to true. If not zero is returned and all the booleans are set to false. 2862 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 2863 struct DisassembleInfo *info, 2864 bool &classref, bool &selref, bool &msgref, 2865 bool &cfstring) { 2866 classref = false; 2867 selref = false; 2868 msgref = false; 2869 cfstring = false; 2870 for (const auto &Load : info->O->load_commands()) { 2871 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2872 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2873 for (unsigned J = 0; J < Seg.nsects; ++J) { 2874 MachO::section_64 Sec = info->O->getSection64(Load, J); 2875 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 2876 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2877 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 2878 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 2879 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 2880 ReferenceValue >= Sec.addr && 2881 ReferenceValue < Sec.addr + Sec.size) { 2882 uint64_t sect_offset = ReferenceValue - Sec.addr; 2883 uint64_t object_offset = Sec.offset + sect_offset; 2884 StringRef MachOContents = info->O->getData(); 2885 uint64_t object_size = MachOContents.size(); 2886 const char *object_addr = (const char *)MachOContents.data(); 2887 if (object_offset < object_size) { 2888 uint64_t pointer_value; 2889 memcpy(&pointer_value, object_addr + object_offset, 2890 sizeof(uint64_t)); 2891 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2892 sys::swapByteOrder(pointer_value); 2893 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 2894 selref = true; 2895 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2896 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 2897 classref = true; 2898 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 2899 ReferenceValue + 8 < Sec.addr + Sec.size) { 2900 msgref = true; 2901 memcpy(&pointer_value, object_addr + object_offset + 8, 2902 sizeof(uint64_t)); 2903 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2904 sys::swapByteOrder(pointer_value); 2905 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 2906 cfstring = true; 2907 return pointer_value; 2908 } else { 2909 return 0; 2910 } 2911 } 2912 } 2913 } 2914 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 2915 } 2916 return 0; 2917 } 2918 2919 // get_pointer_64 returns a pointer to the bytes in the object file at the 2920 // Address from a section in the Mach-O file. And indirectly returns the 2921 // offset into the section, number of bytes left in the section past the offset 2922 // and which section is was being referenced. If the Address is not in a 2923 // section nullptr is returned. 2924 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 2925 uint32_t &left, SectionRef &S, 2926 DisassembleInfo *info, 2927 bool objc_only = false) { 2928 offset = 0; 2929 left = 0; 2930 S = SectionRef(); 2931 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 2932 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 2933 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 2934 if (SectSize == 0) 2935 continue; 2936 if (objc_only) { 2937 StringRef SectName; 2938 ((*(info->Sections))[SectIdx]).getName(SectName); 2939 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 2940 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 2941 if (SegName != "__OBJC" && SectName != "__cstring") 2942 continue; 2943 } 2944 if (Address >= SectAddress && Address < SectAddress + SectSize) { 2945 S = (*(info->Sections))[SectIdx]; 2946 offset = Address - SectAddress; 2947 left = SectSize - offset; 2948 StringRef SectContents; 2949 ((*(info->Sections))[SectIdx]).getContents(SectContents); 2950 return SectContents.data() + offset; 2951 } 2952 } 2953 return nullptr; 2954 } 2955 2956 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 2957 uint32_t &left, SectionRef &S, 2958 DisassembleInfo *info, 2959 bool objc_only = false) { 2960 return get_pointer_64(Address, offset, left, S, info, objc_only); 2961 } 2962 2963 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 2964 // the symbol indirectly through n_value. Based on the relocation information 2965 // for the specified section offset in the specified section reference. 2966 // If no relocation information is found and a non-zero ReferenceValue for the 2967 // symbol is passed, look up that address in the info's AddrMap. 2968 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 2969 DisassembleInfo *info, uint64_t &n_value, 2970 uint64_t ReferenceValue = 0) { 2971 n_value = 0; 2972 if (!info->verbose) 2973 return nullptr; 2974 2975 // See if there is an external relocation entry at the sect_offset. 2976 bool reloc_found = false; 2977 DataRefImpl Rel; 2978 MachO::any_relocation_info RE; 2979 bool isExtern = false; 2980 SymbolRef Symbol; 2981 for (const RelocationRef &Reloc : S.relocations()) { 2982 uint64_t RelocOffset = Reloc.getOffset(); 2983 if (RelocOffset == sect_offset) { 2984 Rel = Reloc.getRawDataRefImpl(); 2985 RE = info->O->getRelocation(Rel); 2986 if (info->O->isRelocationScattered(RE)) 2987 continue; 2988 isExtern = info->O->getPlainRelocationExternal(RE); 2989 if (isExtern) { 2990 symbol_iterator RelocSym = Reloc.getSymbol(); 2991 Symbol = *RelocSym; 2992 } 2993 reloc_found = true; 2994 break; 2995 } 2996 } 2997 // If there is an external relocation entry for a symbol in this section 2998 // at this section_offset then use that symbol's value for the n_value 2999 // and return its name. 3000 const char *SymbolName = nullptr; 3001 if (reloc_found && isExtern) { 3002 n_value = Symbol.getValue(); 3003 Expected<StringRef> NameOrError = Symbol.getName(); 3004 if (!NameOrError) 3005 report_error(info->O->getFileName(), NameOrError.takeError()); 3006 StringRef Name = *NameOrError; 3007 if (!Name.empty()) { 3008 SymbolName = Name.data(); 3009 return SymbolName; 3010 } 3011 } 3012 3013 // TODO: For fully linked images, look through the external relocation 3014 // entries off the dynamic symtab command. For these the r_offset is from the 3015 // start of the first writeable segment in the Mach-O file. So the offset 3016 // to this section from that segment is passed to this routine by the caller, 3017 // as the database_offset. Which is the difference of the section's starting 3018 // address and the first writable segment. 3019 // 3020 // NOTE: need add passing the database_offset to this routine. 3021 3022 // We did not find an external relocation entry so look up the ReferenceValue 3023 // as an address of a symbol and if found return that symbol's name. 3024 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 3025 3026 return SymbolName; 3027 } 3028 3029 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 3030 DisassembleInfo *info, 3031 uint32_t ReferenceValue) { 3032 uint64_t n_value64; 3033 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 3034 } 3035 3036 // These are structs in the Objective-C meta data and read to produce the 3037 // comments for disassembly. While these are part of the ABI they are no 3038 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 3039 // . 3040 3041 // The cfstring object in a 64-bit Mach-O file. 3042 struct cfstring64_t { 3043 uint64_t isa; // class64_t * (64-bit pointer) 3044 uint64_t flags; // flag bits 3045 uint64_t characters; // char * (64-bit pointer) 3046 uint64_t length; // number of non-NULL characters in above 3047 }; 3048 3049 // The class object in a 64-bit Mach-O file. 3050 struct class64_t { 3051 uint64_t isa; // class64_t * (64-bit pointer) 3052 uint64_t superclass; // class64_t * (64-bit pointer) 3053 uint64_t cache; // Cache (64-bit pointer) 3054 uint64_t vtable; // IMP * (64-bit pointer) 3055 uint64_t data; // class_ro64_t * (64-bit pointer) 3056 }; 3057 3058 struct class32_t { 3059 uint32_t isa; /* class32_t * (32-bit pointer) */ 3060 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3061 uint32_t cache; /* Cache (32-bit pointer) */ 3062 uint32_t vtable; /* IMP * (32-bit pointer) */ 3063 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3064 }; 3065 3066 struct class_ro64_t { 3067 uint32_t flags; 3068 uint32_t instanceStart; 3069 uint32_t instanceSize; 3070 uint32_t reserved; 3071 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3072 uint64_t name; // const char * (64-bit pointer) 3073 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3074 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3075 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3076 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3077 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3078 }; 3079 3080 struct class_ro32_t { 3081 uint32_t flags; 3082 uint32_t instanceStart; 3083 uint32_t instanceSize; 3084 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3085 uint32_t name; /* const char * (32-bit pointer) */ 3086 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3087 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3088 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3089 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3090 uint32_t baseProperties; /* const struct objc_property_list * 3091 (32-bit pointer) */ 3092 }; 3093 3094 /* Values for class_ro{64,32}_t->flags */ 3095 #define RO_META (1 << 0) 3096 #define RO_ROOT (1 << 1) 3097 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3098 3099 struct method_list64_t { 3100 uint32_t entsize; 3101 uint32_t count; 3102 /* struct method64_t first; These structures follow inline */ 3103 }; 3104 3105 struct method_list32_t { 3106 uint32_t entsize; 3107 uint32_t count; 3108 /* struct method32_t first; These structures follow inline */ 3109 }; 3110 3111 struct method64_t { 3112 uint64_t name; /* SEL (64-bit pointer) */ 3113 uint64_t types; /* const char * (64-bit pointer) */ 3114 uint64_t imp; /* IMP (64-bit pointer) */ 3115 }; 3116 3117 struct method32_t { 3118 uint32_t name; /* SEL (32-bit pointer) */ 3119 uint32_t types; /* const char * (32-bit pointer) */ 3120 uint32_t imp; /* IMP (32-bit pointer) */ 3121 }; 3122 3123 struct protocol_list64_t { 3124 uint64_t count; /* uintptr_t (a 64-bit value) */ 3125 /* struct protocol64_t * list[0]; These pointers follow inline */ 3126 }; 3127 3128 struct protocol_list32_t { 3129 uint32_t count; /* uintptr_t (a 32-bit value) */ 3130 /* struct protocol32_t * list[0]; These pointers follow inline */ 3131 }; 3132 3133 struct protocol64_t { 3134 uint64_t isa; /* id * (64-bit pointer) */ 3135 uint64_t name; /* const char * (64-bit pointer) */ 3136 uint64_t protocols; /* struct protocol_list64_t * 3137 (64-bit pointer) */ 3138 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3139 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3140 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3141 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3142 uint64_t instanceProperties; /* struct objc_property_list * 3143 (64-bit pointer) */ 3144 }; 3145 3146 struct protocol32_t { 3147 uint32_t isa; /* id * (32-bit pointer) */ 3148 uint32_t name; /* const char * (32-bit pointer) */ 3149 uint32_t protocols; /* struct protocol_list_t * 3150 (32-bit pointer) */ 3151 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3152 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3153 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3154 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3155 uint32_t instanceProperties; /* struct objc_property_list * 3156 (32-bit pointer) */ 3157 }; 3158 3159 struct ivar_list64_t { 3160 uint32_t entsize; 3161 uint32_t count; 3162 /* struct ivar64_t first; These structures follow inline */ 3163 }; 3164 3165 struct ivar_list32_t { 3166 uint32_t entsize; 3167 uint32_t count; 3168 /* struct ivar32_t first; These structures follow inline */ 3169 }; 3170 3171 struct ivar64_t { 3172 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3173 uint64_t name; /* const char * (64-bit pointer) */ 3174 uint64_t type; /* const char * (64-bit pointer) */ 3175 uint32_t alignment; 3176 uint32_t size; 3177 }; 3178 3179 struct ivar32_t { 3180 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3181 uint32_t name; /* const char * (32-bit pointer) */ 3182 uint32_t type; /* const char * (32-bit pointer) */ 3183 uint32_t alignment; 3184 uint32_t size; 3185 }; 3186 3187 struct objc_property_list64 { 3188 uint32_t entsize; 3189 uint32_t count; 3190 /* struct objc_property64 first; These structures follow inline */ 3191 }; 3192 3193 struct objc_property_list32 { 3194 uint32_t entsize; 3195 uint32_t count; 3196 /* struct objc_property32 first; These structures follow inline */ 3197 }; 3198 3199 struct objc_property64 { 3200 uint64_t name; /* const char * (64-bit pointer) */ 3201 uint64_t attributes; /* const char * (64-bit pointer) */ 3202 }; 3203 3204 struct objc_property32 { 3205 uint32_t name; /* const char * (32-bit pointer) */ 3206 uint32_t attributes; /* const char * (32-bit pointer) */ 3207 }; 3208 3209 struct category64_t { 3210 uint64_t name; /* const char * (64-bit pointer) */ 3211 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3212 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3213 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3214 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3215 uint64_t instanceProperties; /* struct objc_property_list * 3216 (64-bit pointer) */ 3217 }; 3218 3219 struct category32_t { 3220 uint32_t name; /* const char * (32-bit pointer) */ 3221 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3222 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3223 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3224 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3225 uint32_t instanceProperties; /* struct objc_property_list * 3226 (32-bit pointer) */ 3227 }; 3228 3229 struct objc_image_info64 { 3230 uint32_t version; 3231 uint32_t flags; 3232 }; 3233 struct objc_image_info32 { 3234 uint32_t version; 3235 uint32_t flags; 3236 }; 3237 struct imageInfo_t { 3238 uint32_t version; 3239 uint32_t flags; 3240 }; 3241 /* masks for objc_image_info.flags */ 3242 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3243 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3244 #define OBJC_IMAGE_IS_SIMULATED (1 << 5) 3245 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6) 3246 3247 struct message_ref64 { 3248 uint64_t imp; /* IMP (64-bit pointer) */ 3249 uint64_t sel; /* SEL (64-bit pointer) */ 3250 }; 3251 3252 struct message_ref32 { 3253 uint32_t imp; /* IMP (32-bit pointer) */ 3254 uint32_t sel; /* SEL (32-bit pointer) */ 3255 }; 3256 3257 // Objective-C 1 (32-bit only) meta data structs. 3258 3259 struct objc_module_t { 3260 uint32_t version; 3261 uint32_t size; 3262 uint32_t name; /* char * (32-bit pointer) */ 3263 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3264 }; 3265 3266 struct objc_symtab_t { 3267 uint32_t sel_ref_cnt; 3268 uint32_t refs; /* SEL * (32-bit pointer) */ 3269 uint16_t cls_def_cnt; 3270 uint16_t cat_def_cnt; 3271 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3272 }; 3273 3274 struct objc_class_t { 3275 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3276 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3277 uint32_t name; /* const char * (32-bit pointer) */ 3278 int32_t version; 3279 int32_t info; 3280 int32_t instance_size; 3281 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3282 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3283 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3284 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3285 }; 3286 3287 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3288 // class is not a metaclass 3289 #define CLS_CLASS 0x1 3290 // class is a metaclass 3291 #define CLS_META 0x2 3292 3293 struct objc_category_t { 3294 uint32_t category_name; /* char * (32-bit pointer) */ 3295 uint32_t class_name; /* char * (32-bit pointer) */ 3296 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3297 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3298 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3299 }; 3300 3301 struct objc_ivar_t { 3302 uint32_t ivar_name; /* char * (32-bit pointer) */ 3303 uint32_t ivar_type; /* char * (32-bit pointer) */ 3304 int32_t ivar_offset; 3305 }; 3306 3307 struct objc_ivar_list_t { 3308 int32_t ivar_count; 3309 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3310 }; 3311 3312 struct objc_method_list_t { 3313 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3314 int32_t method_count; 3315 // struct objc_method_t method_list[1]; /* variable length structure */ 3316 }; 3317 3318 struct objc_method_t { 3319 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3320 uint32_t method_types; /* char * (32-bit pointer) */ 3321 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3322 (32-bit pointer) */ 3323 }; 3324 3325 struct objc_protocol_list_t { 3326 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3327 int32_t count; 3328 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3329 // (32-bit pointer) */ 3330 }; 3331 3332 struct objc_protocol_t { 3333 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3334 uint32_t protocol_name; /* char * (32-bit pointer) */ 3335 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3336 uint32_t instance_methods; /* struct objc_method_description_list * 3337 (32-bit pointer) */ 3338 uint32_t class_methods; /* struct objc_method_description_list * 3339 (32-bit pointer) */ 3340 }; 3341 3342 struct objc_method_description_list_t { 3343 int32_t count; 3344 // struct objc_method_description_t list[1]; 3345 }; 3346 3347 struct objc_method_description_t { 3348 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3349 uint32_t types; /* char * (32-bit pointer) */ 3350 }; 3351 3352 inline void swapStruct(struct cfstring64_t &cfs) { 3353 sys::swapByteOrder(cfs.isa); 3354 sys::swapByteOrder(cfs.flags); 3355 sys::swapByteOrder(cfs.characters); 3356 sys::swapByteOrder(cfs.length); 3357 } 3358 3359 inline void swapStruct(struct class64_t &c) { 3360 sys::swapByteOrder(c.isa); 3361 sys::swapByteOrder(c.superclass); 3362 sys::swapByteOrder(c.cache); 3363 sys::swapByteOrder(c.vtable); 3364 sys::swapByteOrder(c.data); 3365 } 3366 3367 inline void swapStruct(struct class32_t &c) { 3368 sys::swapByteOrder(c.isa); 3369 sys::swapByteOrder(c.superclass); 3370 sys::swapByteOrder(c.cache); 3371 sys::swapByteOrder(c.vtable); 3372 sys::swapByteOrder(c.data); 3373 } 3374 3375 inline void swapStruct(struct class_ro64_t &cro) { 3376 sys::swapByteOrder(cro.flags); 3377 sys::swapByteOrder(cro.instanceStart); 3378 sys::swapByteOrder(cro.instanceSize); 3379 sys::swapByteOrder(cro.reserved); 3380 sys::swapByteOrder(cro.ivarLayout); 3381 sys::swapByteOrder(cro.name); 3382 sys::swapByteOrder(cro.baseMethods); 3383 sys::swapByteOrder(cro.baseProtocols); 3384 sys::swapByteOrder(cro.ivars); 3385 sys::swapByteOrder(cro.weakIvarLayout); 3386 sys::swapByteOrder(cro.baseProperties); 3387 } 3388 3389 inline void swapStruct(struct class_ro32_t &cro) { 3390 sys::swapByteOrder(cro.flags); 3391 sys::swapByteOrder(cro.instanceStart); 3392 sys::swapByteOrder(cro.instanceSize); 3393 sys::swapByteOrder(cro.ivarLayout); 3394 sys::swapByteOrder(cro.name); 3395 sys::swapByteOrder(cro.baseMethods); 3396 sys::swapByteOrder(cro.baseProtocols); 3397 sys::swapByteOrder(cro.ivars); 3398 sys::swapByteOrder(cro.weakIvarLayout); 3399 sys::swapByteOrder(cro.baseProperties); 3400 } 3401 3402 inline void swapStruct(struct method_list64_t &ml) { 3403 sys::swapByteOrder(ml.entsize); 3404 sys::swapByteOrder(ml.count); 3405 } 3406 3407 inline void swapStruct(struct method_list32_t &ml) { 3408 sys::swapByteOrder(ml.entsize); 3409 sys::swapByteOrder(ml.count); 3410 } 3411 3412 inline void swapStruct(struct method64_t &m) { 3413 sys::swapByteOrder(m.name); 3414 sys::swapByteOrder(m.types); 3415 sys::swapByteOrder(m.imp); 3416 } 3417 3418 inline void swapStruct(struct method32_t &m) { 3419 sys::swapByteOrder(m.name); 3420 sys::swapByteOrder(m.types); 3421 sys::swapByteOrder(m.imp); 3422 } 3423 3424 inline void swapStruct(struct protocol_list64_t &pl) { 3425 sys::swapByteOrder(pl.count); 3426 } 3427 3428 inline void swapStruct(struct protocol_list32_t &pl) { 3429 sys::swapByteOrder(pl.count); 3430 } 3431 3432 inline void swapStruct(struct protocol64_t &p) { 3433 sys::swapByteOrder(p.isa); 3434 sys::swapByteOrder(p.name); 3435 sys::swapByteOrder(p.protocols); 3436 sys::swapByteOrder(p.instanceMethods); 3437 sys::swapByteOrder(p.classMethods); 3438 sys::swapByteOrder(p.optionalInstanceMethods); 3439 sys::swapByteOrder(p.optionalClassMethods); 3440 sys::swapByteOrder(p.instanceProperties); 3441 } 3442 3443 inline void swapStruct(struct protocol32_t &p) { 3444 sys::swapByteOrder(p.isa); 3445 sys::swapByteOrder(p.name); 3446 sys::swapByteOrder(p.protocols); 3447 sys::swapByteOrder(p.instanceMethods); 3448 sys::swapByteOrder(p.classMethods); 3449 sys::swapByteOrder(p.optionalInstanceMethods); 3450 sys::swapByteOrder(p.optionalClassMethods); 3451 sys::swapByteOrder(p.instanceProperties); 3452 } 3453 3454 inline void swapStruct(struct ivar_list64_t &il) { 3455 sys::swapByteOrder(il.entsize); 3456 sys::swapByteOrder(il.count); 3457 } 3458 3459 inline void swapStruct(struct ivar_list32_t &il) { 3460 sys::swapByteOrder(il.entsize); 3461 sys::swapByteOrder(il.count); 3462 } 3463 3464 inline void swapStruct(struct ivar64_t &i) { 3465 sys::swapByteOrder(i.offset); 3466 sys::swapByteOrder(i.name); 3467 sys::swapByteOrder(i.type); 3468 sys::swapByteOrder(i.alignment); 3469 sys::swapByteOrder(i.size); 3470 } 3471 3472 inline void swapStruct(struct ivar32_t &i) { 3473 sys::swapByteOrder(i.offset); 3474 sys::swapByteOrder(i.name); 3475 sys::swapByteOrder(i.type); 3476 sys::swapByteOrder(i.alignment); 3477 sys::swapByteOrder(i.size); 3478 } 3479 3480 inline void swapStruct(struct objc_property_list64 &pl) { 3481 sys::swapByteOrder(pl.entsize); 3482 sys::swapByteOrder(pl.count); 3483 } 3484 3485 inline void swapStruct(struct objc_property_list32 &pl) { 3486 sys::swapByteOrder(pl.entsize); 3487 sys::swapByteOrder(pl.count); 3488 } 3489 3490 inline void swapStruct(struct objc_property64 &op) { 3491 sys::swapByteOrder(op.name); 3492 sys::swapByteOrder(op.attributes); 3493 } 3494 3495 inline void swapStruct(struct objc_property32 &op) { 3496 sys::swapByteOrder(op.name); 3497 sys::swapByteOrder(op.attributes); 3498 } 3499 3500 inline void swapStruct(struct category64_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 category32_t &c) { 3510 sys::swapByteOrder(c.name); 3511 sys::swapByteOrder(c.cls); 3512 sys::swapByteOrder(c.instanceMethods); 3513 sys::swapByteOrder(c.classMethods); 3514 sys::swapByteOrder(c.protocols); 3515 sys::swapByteOrder(c.instanceProperties); 3516 } 3517 3518 inline void swapStruct(struct objc_image_info64 &o) { 3519 sys::swapByteOrder(o.version); 3520 sys::swapByteOrder(o.flags); 3521 } 3522 3523 inline void swapStruct(struct objc_image_info32 &o) { 3524 sys::swapByteOrder(o.version); 3525 sys::swapByteOrder(o.flags); 3526 } 3527 3528 inline void swapStruct(struct imageInfo_t &o) { 3529 sys::swapByteOrder(o.version); 3530 sys::swapByteOrder(o.flags); 3531 } 3532 3533 inline void swapStruct(struct message_ref64 &mr) { 3534 sys::swapByteOrder(mr.imp); 3535 sys::swapByteOrder(mr.sel); 3536 } 3537 3538 inline void swapStruct(struct message_ref32 &mr) { 3539 sys::swapByteOrder(mr.imp); 3540 sys::swapByteOrder(mr.sel); 3541 } 3542 3543 inline void swapStruct(struct objc_module_t &module) { 3544 sys::swapByteOrder(module.version); 3545 sys::swapByteOrder(module.size); 3546 sys::swapByteOrder(module.name); 3547 sys::swapByteOrder(module.symtab); 3548 } 3549 3550 inline void swapStruct(struct objc_symtab_t &symtab) { 3551 sys::swapByteOrder(symtab.sel_ref_cnt); 3552 sys::swapByteOrder(symtab.refs); 3553 sys::swapByteOrder(symtab.cls_def_cnt); 3554 sys::swapByteOrder(symtab.cat_def_cnt); 3555 } 3556 3557 inline void swapStruct(struct objc_class_t &objc_class) { 3558 sys::swapByteOrder(objc_class.isa); 3559 sys::swapByteOrder(objc_class.super_class); 3560 sys::swapByteOrder(objc_class.name); 3561 sys::swapByteOrder(objc_class.version); 3562 sys::swapByteOrder(objc_class.info); 3563 sys::swapByteOrder(objc_class.instance_size); 3564 sys::swapByteOrder(objc_class.ivars); 3565 sys::swapByteOrder(objc_class.methodLists); 3566 sys::swapByteOrder(objc_class.cache); 3567 sys::swapByteOrder(objc_class.protocols); 3568 } 3569 3570 inline void swapStruct(struct objc_category_t &objc_category) { 3571 sys::swapByteOrder(objc_category.category_name); 3572 sys::swapByteOrder(objc_category.class_name); 3573 sys::swapByteOrder(objc_category.instance_methods); 3574 sys::swapByteOrder(objc_category.class_methods); 3575 sys::swapByteOrder(objc_category.protocols); 3576 } 3577 3578 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 3579 sys::swapByteOrder(objc_ivar_list.ivar_count); 3580 } 3581 3582 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 3583 sys::swapByteOrder(objc_ivar.ivar_name); 3584 sys::swapByteOrder(objc_ivar.ivar_type); 3585 sys::swapByteOrder(objc_ivar.ivar_offset); 3586 } 3587 3588 inline void swapStruct(struct objc_method_list_t &method_list) { 3589 sys::swapByteOrder(method_list.obsolete); 3590 sys::swapByteOrder(method_list.method_count); 3591 } 3592 3593 inline void swapStruct(struct objc_method_t &method) { 3594 sys::swapByteOrder(method.method_name); 3595 sys::swapByteOrder(method.method_types); 3596 sys::swapByteOrder(method.method_imp); 3597 } 3598 3599 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 3600 sys::swapByteOrder(protocol_list.next); 3601 sys::swapByteOrder(protocol_list.count); 3602 } 3603 3604 inline void swapStruct(struct objc_protocol_t &protocol) { 3605 sys::swapByteOrder(protocol.isa); 3606 sys::swapByteOrder(protocol.protocol_name); 3607 sys::swapByteOrder(protocol.protocol_list); 3608 sys::swapByteOrder(protocol.instance_methods); 3609 sys::swapByteOrder(protocol.class_methods); 3610 } 3611 3612 inline void swapStruct(struct objc_method_description_list_t &mdl) { 3613 sys::swapByteOrder(mdl.count); 3614 } 3615 3616 inline void swapStruct(struct objc_method_description_t &md) { 3617 sys::swapByteOrder(md.name); 3618 sys::swapByteOrder(md.types); 3619 } 3620 3621 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 3622 struct DisassembleInfo *info); 3623 3624 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 3625 // to an Objective-C class and returns the class name. It is also passed the 3626 // address of the pointer, so when the pointer is zero as it can be in an .o 3627 // file, that is used to look for an external relocation entry with a symbol 3628 // name. 3629 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 3630 uint64_t ReferenceValue, 3631 struct DisassembleInfo *info) { 3632 const char *r; 3633 uint32_t offset, left; 3634 SectionRef S; 3635 3636 // The pointer_value can be 0 in an object file and have a relocation 3637 // entry for the class symbol at the ReferenceValue (the address of the 3638 // pointer). 3639 if (pointer_value == 0) { 3640 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3641 if (r == nullptr || left < sizeof(uint64_t)) 3642 return nullptr; 3643 uint64_t n_value; 3644 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3645 if (symbol_name == nullptr) 3646 return nullptr; 3647 const char *class_name = strrchr(symbol_name, '$'); 3648 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 3649 return class_name + 2; 3650 else 3651 return nullptr; 3652 } 3653 3654 // The case were the pointer_value is non-zero and points to a class defined 3655 // in this Mach-O file. 3656 r = get_pointer_64(pointer_value, offset, left, S, info); 3657 if (r == nullptr || left < sizeof(struct class64_t)) 3658 return nullptr; 3659 struct class64_t c; 3660 memcpy(&c, r, sizeof(struct class64_t)); 3661 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3662 swapStruct(c); 3663 if (c.data == 0) 3664 return nullptr; 3665 r = get_pointer_64(c.data, offset, left, S, info); 3666 if (r == nullptr || left < sizeof(struct class_ro64_t)) 3667 return nullptr; 3668 struct class_ro64_t cro; 3669 memcpy(&cro, r, sizeof(struct class_ro64_t)); 3670 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3671 swapStruct(cro); 3672 if (cro.name == 0) 3673 return nullptr; 3674 const char *name = get_pointer_64(cro.name, offset, left, S, info); 3675 return name; 3676 } 3677 3678 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 3679 // pointer to a cfstring and returns its name or nullptr. 3680 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 3681 struct DisassembleInfo *info) { 3682 const char *r, *name; 3683 uint32_t offset, left; 3684 SectionRef S; 3685 struct cfstring64_t cfs; 3686 uint64_t cfs_characters; 3687 3688 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3689 if (r == nullptr || left < sizeof(struct cfstring64_t)) 3690 return nullptr; 3691 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 3692 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3693 swapStruct(cfs); 3694 if (cfs.characters == 0) { 3695 uint64_t n_value; 3696 const char *symbol_name = get_symbol_64( 3697 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 3698 if (symbol_name == nullptr) 3699 return nullptr; 3700 cfs_characters = n_value; 3701 } else 3702 cfs_characters = cfs.characters; 3703 name = get_pointer_64(cfs_characters, offset, left, S, info); 3704 3705 return name; 3706 } 3707 3708 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 3709 // of a pointer to an Objective-C selector reference when the pointer value is 3710 // zero as in a .o file and is likely to have a external relocation entry with 3711 // who's symbol's n_value is the real pointer to the selector name. If that is 3712 // the case the real pointer to the selector name is returned else 0 is 3713 // returned 3714 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 3715 struct DisassembleInfo *info) { 3716 uint32_t offset, left; 3717 SectionRef S; 3718 3719 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 3720 if (r == nullptr || left < sizeof(uint64_t)) 3721 return 0; 3722 uint64_t n_value; 3723 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3724 if (symbol_name == nullptr) 3725 return 0; 3726 return n_value; 3727 } 3728 3729 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 3730 const char *sectname) { 3731 for (const SectionRef &Section : O->sections()) { 3732 StringRef SectName; 3733 Section.getName(SectName); 3734 DataRefImpl Ref = Section.getRawDataRefImpl(); 3735 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3736 if (SegName == segname && SectName == sectname) 3737 return Section; 3738 } 3739 return SectionRef(); 3740 } 3741 3742 static void 3743 walk_pointer_list_64(const char *listname, const SectionRef S, 3744 MachOObjectFile *O, struct DisassembleInfo *info, 3745 void (*func)(uint64_t, struct DisassembleInfo *info)) { 3746 if (S == SectionRef()) 3747 return; 3748 3749 StringRef SectName; 3750 S.getName(SectName); 3751 DataRefImpl Ref = S.getRawDataRefImpl(); 3752 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3753 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3754 3755 StringRef BytesStr; 3756 S.getContents(BytesStr); 3757 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3758 3759 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 3760 uint32_t left = S.getSize() - i; 3761 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 3762 uint64_t p = 0; 3763 memcpy(&p, Contents + i, size); 3764 if (i + sizeof(uint64_t) > S.getSize()) 3765 outs() << listname << " list pointer extends past end of (" << SegName 3766 << "," << SectName << ") section\n"; 3767 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 3768 3769 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3770 sys::swapByteOrder(p); 3771 3772 uint64_t n_value = 0; 3773 const char *name = get_symbol_64(i, S, info, n_value, p); 3774 if (name == nullptr) 3775 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 3776 3777 if (n_value != 0) { 3778 outs() << format("0x%" PRIx64, n_value); 3779 if (p != 0) 3780 outs() << " + " << format("0x%" PRIx64, p); 3781 } else 3782 outs() << format("0x%" PRIx64, p); 3783 if (name != nullptr) 3784 outs() << " " << name; 3785 outs() << "\n"; 3786 3787 p += n_value; 3788 if (func) 3789 func(p, info); 3790 } 3791 } 3792 3793 static void 3794 walk_pointer_list_32(const char *listname, const SectionRef S, 3795 MachOObjectFile *O, struct DisassembleInfo *info, 3796 void (*func)(uint32_t, struct DisassembleInfo *info)) { 3797 if (S == SectionRef()) 3798 return; 3799 3800 StringRef SectName; 3801 S.getName(SectName); 3802 DataRefImpl Ref = S.getRawDataRefImpl(); 3803 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3804 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3805 3806 StringRef BytesStr; 3807 S.getContents(BytesStr); 3808 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3809 3810 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 3811 uint32_t left = S.getSize() - i; 3812 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 3813 uint32_t p = 0; 3814 memcpy(&p, Contents + i, size); 3815 if (i + sizeof(uint32_t) > S.getSize()) 3816 outs() << listname << " list pointer extends past end of (" << SegName 3817 << "," << SectName << ") section\n"; 3818 uint32_t Address = S.getAddress() + i; 3819 outs() << format("%08" PRIx32, Address) << " "; 3820 3821 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3822 sys::swapByteOrder(p); 3823 outs() << format("0x%" PRIx32, p); 3824 3825 const char *name = get_symbol_32(i, S, info, p); 3826 if (name != nullptr) 3827 outs() << " " << name; 3828 outs() << "\n"; 3829 3830 if (func) 3831 func(p, info); 3832 } 3833 } 3834 3835 static void print_layout_map(const char *layout_map, uint32_t left) { 3836 if (layout_map == nullptr) 3837 return; 3838 outs() << " layout map: "; 3839 do { 3840 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 3841 left--; 3842 layout_map++; 3843 } while (*layout_map != '\0' && left != 0); 3844 outs() << "\n"; 3845 } 3846 3847 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 3848 uint32_t offset, left; 3849 SectionRef S; 3850 const char *layout_map; 3851 3852 if (p == 0) 3853 return; 3854 layout_map = get_pointer_64(p, offset, left, S, info); 3855 print_layout_map(layout_map, left); 3856 } 3857 3858 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 3859 uint32_t offset, left; 3860 SectionRef S; 3861 const char *layout_map; 3862 3863 if (p == 0) 3864 return; 3865 layout_map = get_pointer_32(p, offset, left, S, info); 3866 print_layout_map(layout_map, left); 3867 } 3868 3869 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 3870 const char *indent) { 3871 struct method_list64_t ml; 3872 struct method64_t m; 3873 const char *r; 3874 uint32_t offset, xoffset, left, i; 3875 SectionRef S, xS; 3876 const char *name, *sym_name; 3877 uint64_t n_value; 3878 3879 r = get_pointer_64(p, offset, left, S, info); 3880 if (r == nullptr) 3881 return; 3882 memset(&ml, '\0', sizeof(struct method_list64_t)); 3883 if (left < sizeof(struct method_list64_t)) { 3884 memcpy(&ml, r, left); 3885 outs() << " (method_list_t entends past the end of the section)\n"; 3886 } else 3887 memcpy(&ml, r, sizeof(struct method_list64_t)); 3888 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3889 swapStruct(ml); 3890 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3891 outs() << indent << "\t\t count " << ml.count << "\n"; 3892 3893 p += sizeof(struct method_list64_t); 3894 offset += sizeof(struct method_list64_t); 3895 for (i = 0; i < ml.count; i++) { 3896 r = get_pointer_64(p, offset, left, S, info); 3897 if (r == nullptr) 3898 return; 3899 memset(&m, '\0', sizeof(struct method64_t)); 3900 if (left < sizeof(struct method64_t)) { 3901 memcpy(&m, r, left); 3902 outs() << indent << " (method_t extends past the end of the section)\n"; 3903 } else 3904 memcpy(&m, r, sizeof(struct method64_t)); 3905 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3906 swapStruct(m); 3907 3908 outs() << indent << "\t\t name "; 3909 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 3910 info, n_value, m.name); 3911 if (n_value != 0) { 3912 if (info->verbose && sym_name != nullptr) 3913 outs() << sym_name; 3914 else 3915 outs() << format("0x%" PRIx64, n_value); 3916 if (m.name != 0) 3917 outs() << " + " << format("0x%" PRIx64, m.name); 3918 } else 3919 outs() << format("0x%" PRIx64, m.name); 3920 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 3921 if (name != nullptr) 3922 outs() << format(" %.*s", left, name); 3923 outs() << "\n"; 3924 3925 outs() << indent << "\t\t types "; 3926 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 3927 info, n_value, m.types); 3928 if (n_value != 0) { 3929 if (info->verbose && sym_name != nullptr) 3930 outs() << sym_name; 3931 else 3932 outs() << format("0x%" PRIx64, n_value); 3933 if (m.types != 0) 3934 outs() << " + " << format("0x%" PRIx64, m.types); 3935 } else 3936 outs() << format("0x%" PRIx64, m.types); 3937 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 3938 if (name != nullptr) 3939 outs() << format(" %.*s", left, name); 3940 outs() << "\n"; 3941 3942 outs() << indent << "\t\t imp "; 3943 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 3944 n_value, m.imp); 3945 if (info->verbose && name == nullptr) { 3946 if (n_value != 0) { 3947 outs() << format("0x%" PRIx64, n_value) << " "; 3948 if (m.imp != 0) 3949 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 3950 } else 3951 outs() << format("0x%" PRIx64, m.imp) << " "; 3952 } 3953 if (name != nullptr) 3954 outs() << name; 3955 outs() << "\n"; 3956 3957 p += sizeof(struct method64_t); 3958 offset += sizeof(struct method64_t); 3959 } 3960 } 3961 3962 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 3963 const char *indent) { 3964 struct method_list32_t ml; 3965 struct method32_t m; 3966 const char *r, *name; 3967 uint32_t offset, xoffset, left, i; 3968 SectionRef S, xS; 3969 3970 r = get_pointer_32(p, offset, left, S, info); 3971 if (r == nullptr) 3972 return; 3973 memset(&ml, '\0', sizeof(struct method_list32_t)); 3974 if (left < sizeof(struct method_list32_t)) { 3975 memcpy(&ml, r, left); 3976 outs() << " (method_list_t entends past the end of the section)\n"; 3977 } else 3978 memcpy(&ml, r, sizeof(struct method_list32_t)); 3979 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3980 swapStruct(ml); 3981 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3982 outs() << indent << "\t\t count " << ml.count << "\n"; 3983 3984 p += sizeof(struct method_list32_t); 3985 offset += sizeof(struct method_list32_t); 3986 for (i = 0; i < ml.count; i++) { 3987 r = get_pointer_32(p, offset, left, S, info); 3988 if (r == nullptr) 3989 return; 3990 memset(&m, '\0', sizeof(struct method32_t)); 3991 if (left < sizeof(struct method32_t)) { 3992 memcpy(&ml, r, left); 3993 outs() << indent << " (method_t entends past the end of the section)\n"; 3994 } else 3995 memcpy(&m, r, sizeof(struct method32_t)); 3996 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3997 swapStruct(m); 3998 3999 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 4000 name = get_pointer_32(m.name, xoffset, left, xS, info); 4001 if (name != nullptr) 4002 outs() << format(" %.*s", left, name); 4003 outs() << "\n"; 4004 4005 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 4006 name = get_pointer_32(m.types, xoffset, left, xS, info); 4007 if (name != nullptr) 4008 outs() << format(" %.*s", left, name); 4009 outs() << "\n"; 4010 4011 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4012 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 4013 m.imp); 4014 if (name != nullptr) 4015 outs() << " " << name; 4016 outs() << "\n"; 4017 4018 p += sizeof(struct method32_t); 4019 offset += sizeof(struct method32_t); 4020 } 4021 } 4022 4023 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 4024 uint32_t offset, left, xleft; 4025 SectionRef S; 4026 struct objc_method_list_t method_list; 4027 struct objc_method_t method; 4028 const char *r, *methods, *name, *SymbolName; 4029 int32_t i; 4030 4031 r = get_pointer_32(p, offset, left, S, info, true); 4032 if (r == nullptr) 4033 return true; 4034 4035 outs() << "\n"; 4036 if (left > sizeof(struct objc_method_list_t)) { 4037 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 4038 } else { 4039 outs() << "\t\t objc_method_list extends past end of the section\n"; 4040 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 4041 memcpy(&method_list, r, left); 4042 } 4043 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4044 swapStruct(method_list); 4045 4046 outs() << "\t\t obsolete " 4047 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4048 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4049 4050 methods = r + sizeof(struct objc_method_list_t); 4051 for (i = 0; i < method_list.method_count; i++) { 4052 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4053 outs() << "\t\t remaining method's extend past the of the section\n"; 4054 break; 4055 } 4056 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4057 sizeof(struct objc_method_t)); 4058 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4059 swapStruct(method); 4060 4061 outs() << "\t\t method_name " 4062 << format("0x%08" PRIx32, method.method_name); 4063 if (info->verbose) { 4064 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4065 if (name != nullptr) 4066 outs() << format(" %.*s", xleft, name); 4067 else 4068 outs() << " (not in an __OBJC section)"; 4069 } 4070 outs() << "\n"; 4071 4072 outs() << "\t\t method_types " 4073 << format("0x%08" PRIx32, method.method_types); 4074 if (info->verbose) { 4075 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4076 if (name != nullptr) 4077 outs() << format(" %.*s", xleft, name); 4078 else 4079 outs() << " (not in an __OBJC section)"; 4080 } 4081 outs() << "\n"; 4082 4083 outs() << "\t\t method_imp " 4084 << format("0x%08" PRIx32, method.method_imp) << " "; 4085 if (info->verbose) { 4086 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4087 if (SymbolName != nullptr) 4088 outs() << SymbolName; 4089 } 4090 outs() << "\n"; 4091 } 4092 return false; 4093 } 4094 4095 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4096 struct protocol_list64_t pl; 4097 uint64_t q, n_value; 4098 struct protocol64_t pc; 4099 const char *r; 4100 uint32_t offset, xoffset, left, i; 4101 SectionRef S, xS; 4102 const char *name, *sym_name; 4103 4104 r = get_pointer_64(p, offset, left, S, info); 4105 if (r == nullptr) 4106 return; 4107 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4108 if (left < sizeof(struct protocol_list64_t)) { 4109 memcpy(&pl, r, left); 4110 outs() << " (protocol_list_t entends past the end of the section)\n"; 4111 } else 4112 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4113 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4114 swapStruct(pl); 4115 outs() << " count " << pl.count << "\n"; 4116 4117 p += sizeof(struct protocol_list64_t); 4118 offset += sizeof(struct protocol_list64_t); 4119 for (i = 0; i < pl.count; i++) { 4120 r = get_pointer_64(p, offset, left, S, info); 4121 if (r == nullptr) 4122 return; 4123 q = 0; 4124 if (left < sizeof(uint64_t)) { 4125 memcpy(&q, r, left); 4126 outs() << " (protocol_t * entends past the end of the section)\n"; 4127 } else 4128 memcpy(&q, r, sizeof(uint64_t)); 4129 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4130 sys::swapByteOrder(q); 4131 4132 outs() << "\t\t list[" << i << "] "; 4133 sym_name = get_symbol_64(offset, S, info, n_value, q); 4134 if (n_value != 0) { 4135 if (info->verbose && sym_name != nullptr) 4136 outs() << sym_name; 4137 else 4138 outs() << format("0x%" PRIx64, n_value); 4139 if (q != 0) 4140 outs() << " + " << format("0x%" PRIx64, q); 4141 } else 4142 outs() << format("0x%" PRIx64, q); 4143 outs() << " (struct protocol_t *)\n"; 4144 4145 r = get_pointer_64(q + n_value, offset, left, S, info); 4146 if (r == nullptr) 4147 return; 4148 memset(&pc, '\0', sizeof(struct protocol64_t)); 4149 if (left < sizeof(struct protocol64_t)) { 4150 memcpy(&pc, r, left); 4151 outs() << " (protocol_t entends past the end of the section)\n"; 4152 } else 4153 memcpy(&pc, r, sizeof(struct protocol64_t)); 4154 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4155 swapStruct(pc); 4156 4157 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4158 4159 outs() << "\t\t\t name "; 4160 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4161 info, n_value, pc.name); 4162 if (n_value != 0) { 4163 if (info->verbose && sym_name != nullptr) 4164 outs() << sym_name; 4165 else 4166 outs() << format("0x%" PRIx64, n_value); 4167 if (pc.name != 0) 4168 outs() << " + " << format("0x%" PRIx64, pc.name); 4169 } else 4170 outs() << format("0x%" PRIx64, pc.name); 4171 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4172 if (name != nullptr) 4173 outs() << format(" %.*s", left, name); 4174 outs() << "\n"; 4175 4176 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4177 4178 outs() << "\t\t instanceMethods "; 4179 sym_name = 4180 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4181 S, info, n_value, pc.instanceMethods); 4182 if (n_value != 0) { 4183 if (info->verbose && sym_name != nullptr) 4184 outs() << sym_name; 4185 else 4186 outs() << format("0x%" PRIx64, n_value); 4187 if (pc.instanceMethods != 0) 4188 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4189 } else 4190 outs() << format("0x%" PRIx64, pc.instanceMethods); 4191 outs() << " (struct method_list_t *)\n"; 4192 if (pc.instanceMethods + n_value != 0) 4193 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4194 4195 outs() << "\t\t classMethods "; 4196 sym_name = 4197 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4198 info, n_value, pc.classMethods); 4199 if (n_value != 0) { 4200 if (info->verbose && sym_name != nullptr) 4201 outs() << sym_name; 4202 else 4203 outs() << format("0x%" PRIx64, n_value); 4204 if (pc.classMethods != 0) 4205 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4206 } else 4207 outs() << format("0x%" PRIx64, pc.classMethods); 4208 outs() << " (struct method_list_t *)\n"; 4209 if (pc.classMethods + n_value != 0) 4210 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4211 4212 outs() << "\t optionalInstanceMethods " 4213 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4214 outs() << "\t optionalClassMethods " 4215 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4216 outs() << "\t instanceProperties " 4217 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4218 4219 p += sizeof(uint64_t); 4220 offset += sizeof(uint64_t); 4221 } 4222 } 4223 4224 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4225 struct protocol_list32_t pl; 4226 uint32_t q; 4227 struct protocol32_t pc; 4228 const char *r; 4229 uint32_t offset, xoffset, left, i; 4230 SectionRef S, xS; 4231 const char *name; 4232 4233 r = get_pointer_32(p, offset, left, S, info); 4234 if (r == nullptr) 4235 return; 4236 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4237 if (left < sizeof(struct protocol_list32_t)) { 4238 memcpy(&pl, r, left); 4239 outs() << " (protocol_list_t entends past the end of the section)\n"; 4240 } else 4241 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4242 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4243 swapStruct(pl); 4244 outs() << " count " << pl.count << "\n"; 4245 4246 p += sizeof(struct protocol_list32_t); 4247 offset += sizeof(struct protocol_list32_t); 4248 for (i = 0; i < pl.count; i++) { 4249 r = get_pointer_32(p, offset, left, S, info); 4250 if (r == nullptr) 4251 return; 4252 q = 0; 4253 if (left < sizeof(uint32_t)) { 4254 memcpy(&q, r, left); 4255 outs() << " (protocol_t * entends past the end of the section)\n"; 4256 } else 4257 memcpy(&q, r, sizeof(uint32_t)); 4258 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4259 sys::swapByteOrder(q); 4260 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4261 << " (struct protocol_t *)\n"; 4262 r = get_pointer_32(q, offset, left, S, info); 4263 if (r == nullptr) 4264 return; 4265 memset(&pc, '\0', sizeof(struct protocol32_t)); 4266 if (left < sizeof(struct protocol32_t)) { 4267 memcpy(&pc, r, left); 4268 outs() << " (protocol_t entends past the end of the section)\n"; 4269 } else 4270 memcpy(&pc, r, sizeof(struct protocol32_t)); 4271 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4272 swapStruct(pc); 4273 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4274 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4275 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4276 if (name != nullptr) 4277 outs() << format(" %.*s", left, name); 4278 outs() << "\n"; 4279 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4280 outs() << "\t\t instanceMethods " 4281 << format("0x%" PRIx32, pc.instanceMethods) 4282 << " (struct method_list_t *)\n"; 4283 if (pc.instanceMethods != 0) 4284 print_method_list32_t(pc.instanceMethods, info, "\t"); 4285 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4286 << " (struct method_list_t *)\n"; 4287 if (pc.classMethods != 0) 4288 print_method_list32_t(pc.classMethods, info, "\t"); 4289 outs() << "\t optionalInstanceMethods " 4290 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4291 outs() << "\t optionalClassMethods " 4292 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4293 outs() << "\t instanceProperties " 4294 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4295 p += sizeof(uint32_t); 4296 offset += sizeof(uint32_t); 4297 } 4298 } 4299 4300 static void print_indent(uint32_t indent) { 4301 for (uint32_t i = 0; i < indent;) { 4302 if (indent - i >= 8) { 4303 outs() << "\t"; 4304 i += 8; 4305 } else { 4306 for (uint32_t j = i; j < indent; j++) 4307 outs() << " "; 4308 return; 4309 } 4310 } 4311 } 4312 4313 static bool print_method_description_list(uint32_t p, uint32_t indent, 4314 struct DisassembleInfo *info) { 4315 uint32_t offset, left, xleft; 4316 SectionRef S; 4317 struct objc_method_description_list_t mdl; 4318 struct objc_method_description_t md; 4319 const char *r, *list, *name; 4320 int32_t i; 4321 4322 r = get_pointer_32(p, offset, left, S, info, true); 4323 if (r == nullptr) 4324 return true; 4325 4326 outs() << "\n"; 4327 if (left > sizeof(struct objc_method_description_list_t)) { 4328 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 4329 } else { 4330 print_indent(indent); 4331 outs() << " objc_method_description_list extends past end of the section\n"; 4332 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 4333 memcpy(&mdl, r, left); 4334 } 4335 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4336 swapStruct(mdl); 4337 4338 print_indent(indent); 4339 outs() << " count " << mdl.count << "\n"; 4340 4341 list = r + sizeof(struct objc_method_description_list_t); 4342 for (i = 0; i < mdl.count; i++) { 4343 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 4344 print_indent(indent); 4345 outs() << " remaining list entries extend past the of the section\n"; 4346 break; 4347 } 4348 print_indent(indent); 4349 outs() << " list[" << i << "]\n"; 4350 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 4351 sizeof(struct objc_method_description_t)); 4352 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4353 swapStruct(md); 4354 4355 print_indent(indent); 4356 outs() << " name " << format("0x%08" PRIx32, md.name); 4357 if (info->verbose) { 4358 name = get_pointer_32(md.name, offset, xleft, S, info, true); 4359 if (name != nullptr) 4360 outs() << format(" %.*s", xleft, name); 4361 else 4362 outs() << " (not in an __OBJC section)"; 4363 } 4364 outs() << "\n"; 4365 4366 print_indent(indent); 4367 outs() << " types " << format("0x%08" PRIx32, md.types); 4368 if (info->verbose) { 4369 name = get_pointer_32(md.types, offset, xleft, S, info, true); 4370 if (name != nullptr) 4371 outs() << format(" %.*s", xleft, name); 4372 else 4373 outs() << " (not in an __OBJC section)"; 4374 } 4375 outs() << "\n"; 4376 } 4377 return false; 4378 } 4379 4380 static bool print_protocol_list(uint32_t p, uint32_t indent, 4381 struct DisassembleInfo *info); 4382 4383 static bool print_protocol(uint32_t p, uint32_t indent, 4384 struct DisassembleInfo *info) { 4385 uint32_t offset, left; 4386 SectionRef S; 4387 struct objc_protocol_t protocol; 4388 const char *r, *name; 4389 4390 r = get_pointer_32(p, offset, left, S, info, true); 4391 if (r == nullptr) 4392 return true; 4393 4394 outs() << "\n"; 4395 if (left >= sizeof(struct objc_protocol_t)) { 4396 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 4397 } else { 4398 print_indent(indent); 4399 outs() << " Protocol extends past end of the section\n"; 4400 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 4401 memcpy(&protocol, r, left); 4402 } 4403 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4404 swapStruct(protocol); 4405 4406 print_indent(indent); 4407 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 4408 << "\n"; 4409 4410 print_indent(indent); 4411 outs() << " protocol_name " 4412 << format("0x%08" PRIx32, protocol.protocol_name); 4413 if (info->verbose) { 4414 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 4415 if (name != nullptr) 4416 outs() << format(" %.*s", left, name); 4417 else 4418 outs() << " (not in an __OBJC section)"; 4419 } 4420 outs() << "\n"; 4421 4422 print_indent(indent); 4423 outs() << " protocol_list " 4424 << format("0x%08" PRIx32, protocol.protocol_list); 4425 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 4426 outs() << " (not in an __OBJC section)\n"; 4427 4428 print_indent(indent); 4429 outs() << " instance_methods " 4430 << format("0x%08" PRIx32, protocol.instance_methods); 4431 if (print_method_description_list(protocol.instance_methods, indent, info)) 4432 outs() << " (not in an __OBJC section)\n"; 4433 4434 print_indent(indent); 4435 outs() << " class_methods " 4436 << format("0x%08" PRIx32, protocol.class_methods); 4437 if (print_method_description_list(protocol.class_methods, indent, info)) 4438 outs() << " (not in an __OBJC section)\n"; 4439 4440 return false; 4441 } 4442 4443 static bool print_protocol_list(uint32_t p, uint32_t indent, 4444 struct DisassembleInfo *info) { 4445 uint32_t offset, left, l; 4446 SectionRef S; 4447 struct objc_protocol_list_t protocol_list; 4448 const char *r, *list; 4449 int32_t i; 4450 4451 r = get_pointer_32(p, offset, left, S, info, true); 4452 if (r == nullptr) 4453 return true; 4454 4455 outs() << "\n"; 4456 if (left > sizeof(struct objc_protocol_list_t)) { 4457 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 4458 } else { 4459 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 4460 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 4461 memcpy(&protocol_list, r, left); 4462 } 4463 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4464 swapStruct(protocol_list); 4465 4466 print_indent(indent); 4467 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 4468 << "\n"; 4469 print_indent(indent); 4470 outs() << " count " << protocol_list.count << "\n"; 4471 4472 list = r + sizeof(struct objc_protocol_list_t); 4473 for (i = 0; i < protocol_list.count; i++) { 4474 if ((i + 1) * sizeof(uint32_t) > left) { 4475 outs() << "\t\t remaining list entries extend past the of the section\n"; 4476 break; 4477 } 4478 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 4479 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4480 sys::swapByteOrder(l); 4481 4482 print_indent(indent); 4483 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 4484 if (print_protocol(l, indent, info)) 4485 outs() << "(not in an __OBJC section)\n"; 4486 } 4487 return false; 4488 } 4489 4490 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 4491 struct ivar_list64_t il; 4492 struct ivar64_t i; 4493 const char *r; 4494 uint32_t offset, xoffset, left, j; 4495 SectionRef S, xS; 4496 const char *name, *sym_name, *ivar_offset_p; 4497 uint64_t ivar_offset, n_value; 4498 4499 r = get_pointer_64(p, offset, left, S, info); 4500 if (r == nullptr) 4501 return; 4502 memset(&il, '\0', sizeof(struct ivar_list64_t)); 4503 if (left < sizeof(struct ivar_list64_t)) { 4504 memcpy(&il, r, left); 4505 outs() << " (ivar_list_t entends past the end of the section)\n"; 4506 } else 4507 memcpy(&il, r, sizeof(struct ivar_list64_t)); 4508 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4509 swapStruct(il); 4510 outs() << " entsize " << il.entsize << "\n"; 4511 outs() << " count " << il.count << "\n"; 4512 4513 p += sizeof(struct ivar_list64_t); 4514 offset += sizeof(struct ivar_list64_t); 4515 for (j = 0; j < il.count; j++) { 4516 r = get_pointer_64(p, offset, left, S, info); 4517 if (r == nullptr) 4518 return; 4519 memset(&i, '\0', sizeof(struct ivar64_t)); 4520 if (left < sizeof(struct ivar64_t)) { 4521 memcpy(&i, r, left); 4522 outs() << " (ivar_t entends past the end of the section)\n"; 4523 } else 4524 memcpy(&i, r, sizeof(struct ivar64_t)); 4525 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4526 swapStruct(i); 4527 4528 outs() << "\t\t\t offset "; 4529 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 4530 info, n_value, i.offset); 4531 if (n_value != 0) { 4532 if (info->verbose && sym_name != nullptr) 4533 outs() << sym_name; 4534 else 4535 outs() << format("0x%" PRIx64, n_value); 4536 if (i.offset != 0) 4537 outs() << " + " << format("0x%" PRIx64, i.offset); 4538 } else 4539 outs() << format("0x%" PRIx64, i.offset); 4540 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 4541 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4542 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4543 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4544 sys::swapByteOrder(ivar_offset); 4545 outs() << " " << ivar_offset << "\n"; 4546 } else 4547 outs() << "\n"; 4548 4549 outs() << "\t\t\t name "; 4550 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 4551 n_value, i.name); 4552 if (n_value != 0) { 4553 if (info->verbose && sym_name != nullptr) 4554 outs() << sym_name; 4555 else 4556 outs() << format("0x%" PRIx64, n_value); 4557 if (i.name != 0) 4558 outs() << " + " << format("0x%" PRIx64, i.name); 4559 } else 4560 outs() << format("0x%" PRIx64, i.name); 4561 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 4562 if (name != nullptr) 4563 outs() << format(" %.*s", left, name); 4564 outs() << "\n"; 4565 4566 outs() << "\t\t\t type "; 4567 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 4568 n_value, i.name); 4569 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 4570 if (n_value != 0) { 4571 if (info->verbose && sym_name != nullptr) 4572 outs() << sym_name; 4573 else 4574 outs() << format("0x%" PRIx64, n_value); 4575 if (i.type != 0) 4576 outs() << " + " << format("0x%" PRIx64, i.type); 4577 } else 4578 outs() << format("0x%" PRIx64, i.type); 4579 if (name != nullptr) 4580 outs() << format(" %.*s", left, name); 4581 outs() << "\n"; 4582 4583 outs() << "\t\t\talignment " << i.alignment << "\n"; 4584 outs() << "\t\t\t size " << i.size << "\n"; 4585 4586 p += sizeof(struct ivar64_t); 4587 offset += sizeof(struct ivar64_t); 4588 } 4589 } 4590 4591 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 4592 struct ivar_list32_t il; 4593 struct ivar32_t i; 4594 const char *r; 4595 uint32_t offset, xoffset, left, j; 4596 SectionRef S, xS; 4597 const char *name, *ivar_offset_p; 4598 uint32_t ivar_offset; 4599 4600 r = get_pointer_32(p, offset, left, S, info); 4601 if (r == nullptr) 4602 return; 4603 memset(&il, '\0', sizeof(struct ivar_list32_t)); 4604 if (left < sizeof(struct ivar_list32_t)) { 4605 memcpy(&il, r, left); 4606 outs() << " (ivar_list_t entends past the end of the section)\n"; 4607 } else 4608 memcpy(&il, r, sizeof(struct ivar_list32_t)); 4609 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4610 swapStruct(il); 4611 outs() << " entsize " << il.entsize << "\n"; 4612 outs() << " count " << il.count << "\n"; 4613 4614 p += sizeof(struct ivar_list32_t); 4615 offset += sizeof(struct ivar_list32_t); 4616 for (j = 0; j < il.count; j++) { 4617 r = get_pointer_32(p, offset, left, S, info); 4618 if (r == nullptr) 4619 return; 4620 memset(&i, '\0', sizeof(struct ivar32_t)); 4621 if (left < sizeof(struct ivar32_t)) { 4622 memcpy(&i, r, left); 4623 outs() << " (ivar_t entends past the end of the section)\n"; 4624 } else 4625 memcpy(&i, r, sizeof(struct ivar32_t)); 4626 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4627 swapStruct(i); 4628 4629 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 4630 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 4631 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4632 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4633 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4634 sys::swapByteOrder(ivar_offset); 4635 outs() << " " << ivar_offset << "\n"; 4636 } else 4637 outs() << "\n"; 4638 4639 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 4640 name = get_pointer_32(i.name, xoffset, left, xS, info); 4641 if (name != nullptr) 4642 outs() << format(" %.*s", left, name); 4643 outs() << "\n"; 4644 4645 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 4646 name = get_pointer_32(i.type, xoffset, left, xS, info); 4647 if (name != nullptr) 4648 outs() << format(" %.*s", left, name); 4649 outs() << "\n"; 4650 4651 outs() << "\t\t\talignment " << i.alignment << "\n"; 4652 outs() << "\t\t\t size " << i.size << "\n"; 4653 4654 p += sizeof(struct ivar32_t); 4655 offset += sizeof(struct ivar32_t); 4656 } 4657 } 4658 4659 static void print_objc_property_list64(uint64_t p, 4660 struct DisassembleInfo *info) { 4661 struct objc_property_list64 opl; 4662 struct objc_property64 op; 4663 const char *r; 4664 uint32_t offset, xoffset, left, j; 4665 SectionRef S, xS; 4666 const char *name, *sym_name; 4667 uint64_t n_value; 4668 4669 r = get_pointer_64(p, offset, left, S, info); 4670 if (r == nullptr) 4671 return; 4672 memset(&opl, '\0', sizeof(struct objc_property_list64)); 4673 if (left < sizeof(struct objc_property_list64)) { 4674 memcpy(&opl, r, left); 4675 outs() << " (objc_property_list entends past the end of the section)\n"; 4676 } else 4677 memcpy(&opl, r, sizeof(struct objc_property_list64)); 4678 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4679 swapStruct(opl); 4680 outs() << " entsize " << opl.entsize << "\n"; 4681 outs() << " count " << opl.count << "\n"; 4682 4683 p += sizeof(struct objc_property_list64); 4684 offset += sizeof(struct objc_property_list64); 4685 for (j = 0; j < opl.count; j++) { 4686 r = get_pointer_64(p, offset, left, S, info); 4687 if (r == nullptr) 4688 return; 4689 memset(&op, '\0', sizeof(struct objc_property64)); 4690 if (left < sizeof(struct objc_property64)) { 4691 memcpy(&op, r, left); 4692 outs() << " (objc_property entends past the end of the section)\n"; 4693 } else 4694 memcpy(&op, r, sizeof(struct objc_property64)); 4695 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4696 swapStruct(op); 4697 4698 outs() << "\t\t\t name "; 4699 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 4700 info, n_value, op.name); 4701 if (n_value != 0) { 4702 if (info->verbose && sym_name != nullptr) 4703 outs() << sym_name; 4704 else 4705 outs() << format("0x%" PRIx64, n_value); 4706 if (op.name != 0) 4707 outs() << " + " << format("0x%" PRIx64, op.name); 4708 } else 4709 outs() << format("0x%" PRIx64, op.name); 4710 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 4711 if (name != nullptr) 4712 outs() << format(" %.*s", left, name); 4713 outs() << "\n"; 4714 4715 outs() << "\t\t\tattributes "; 4716 sym_name = 4717 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 4718 info, n_value, op.attributes); 4719 if (n_value != 0) { 4720 if (info->verbose && sym_name != nullptr) 4721 outs() << sym_name; 4722 else 4723 outs() << format("0x%" PRIx64, n_value); 4724 if (op.attributes != 0) 4725 outs() << " + " << format("0x%" PRIx64, op.attributes); 4726 } else 4727 outs() << format("0x%" PRIx64, op.attributes); 4728 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 4729 if (name != nullptr) 4730 outs() << format(" %.*s", left, name); 4731 outs() << "\n"; 4732 4733 p += sizeof(struct objc_property64); 4734 offset += sizeof(struct objc_property64); 4735 } 4736 } 4737 4738 static void print_objc_property_list32(uint32_t p, 4739 struct DisassembleInfo *info) { 4740 struct objc_property_list32 opl; 4741 struct objc_property32 op; 4742 const char *r; 4743 uint32_t offset, xoffset, left, j; 4744 SectionRef S, xS; 4745 const char *name; 4746 4747 r = get_pointer_32(p, offset, left, S, info); 4748 if (r == nullptr) 4749 return; 4750 memset(&opl, '\0', sizeof(struct objc_property_list32)); 4751 if (left < sizeof(struct objc_property_list32)) { 4752 memcpy(&opl, r, left); 4753 outs() << " (objc_property_list entends past the end of the section)\n"; 4754 } else 4755 memcpy(&opl, r, sizeof(struct objc_property_list32)); 4756 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4757 swapStruct(opl); 4758 outs() << " entsize " << opl.entsize << "\n"; 4759 outs() << " count " << opl.count << "\n"; 4760 4761 p += sizeof(struct objc_property_list32); 4762 offset += sizeof(struct objc_property_list32); 4763 for (j = 0; j < opl.count; j++) { 4764 r = get_pointer_32(p, offset, left, S, info); 4765 if (r == nullptr) 4766 return; 4767 memset(&op, '\0', sizeof(struct objc_property32)); 4768 if (left < sizeof(struct objc_property32)) { 4769 memcpy(&op, r, left); 4770 outs() << " (objc_property entends past the end of the section)\n"; 4771 } else 4772 memcpy(&op, r, sizeof(struct objc_property32)); 4773 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4774 swapStruct(op); 4775 4776 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 4777 name = get_pointer_32(op.name, xoffset, left, xS, info); 4778 if (name != nullptr) 4779 outs() << format(" %.*s", left, name); 4780 outs() << "\n"; 4781 4782 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 4783 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 4784 if (name != nullptr) 4785 outs() << format(" %.*s", left, name); 4786 outs() << "\n"; 4787 4788 p += sizeof(struct objc_property32); 4789 offset += sizeof(struct objc_property32); 4790 } 4791 } 4792 4793 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 4794 bool &is_meta_class) { 4795 struct class_ro64_t cro; 4796 const char *r; 4797 uint32_t offset, xoffset, left; 4798 SectionRef S, xS; 4799 const char *name, *sym_name; 4800 uint64_t n_value; 4801 4802 r = get_pointer_64(p, offset, left, S, info); 4803 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4804 return false; 4805 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4806 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4807 swapStruct(cro); 4808 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4809 if (cro.flags & RO_META) 4810 outs() << " RO_META"; 4811 if (cro.flags & RO_ROOT) 4812 outs() << " RO_ROOT"; 4813 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4814 outs() << " RO_HAS_CXX_STRUCTORS"; 4815 outs() << "\n"; 4816 outs() << " instanceStart " << cro.instanceStart << "\n"; 4817 outs() << " instanceSize " << cro.instanceSize << "\n"; 4818 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 4819 << "\n"; 4820 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 4821 << "\n"; 4822 print_layout_map64(cro.ivarLayout, info); 4823 4824 outs() << " name "; 4825 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 4826 info, n_value, cro.name); 4827 if (n_value != 0) { 4828 if (info->verbose && sym_name != nullptr) 4829 outs() << sym_name; 4830 else 4831 outs() << format("0x%" PRIx64, n_value); 4832 if (cro.name != 0) 4833 outs() << " + " << format("0x%" PRIx64, cro.name); 4834 } else 4835 outs() << format("0x%" PRIx64, cro.name); 4836 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 4837 if (name != nullptr) 4838 outs() << format(" %.*s", left, name); 4839 outs() << "\n"; 4840 4841 outs() << " baseMethods "; 4842 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 4843 S, info, n_value, cro.baseMethods); 4844 if (n_value != 0) { 4845 if (info->verbose && sym_name != nullptr) 4846 outs() << sym_name; 4847 else 4848 outs() << format("0x%" PRIx64, n_value); 4849 if (cro.baseMethods != 0) 4850 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 4851 } else 4852 outs() << format("0x%" PRIx64, cro.baseMethods); 4853 outs() << " (struct method_list_t *)\n"; 4854 if (cro.baseMethods + n_value != 0) 4855 print_method_list64_t(cro.baseMethods + n_value, info, ""); 4856 4857 outs() << " baseProtocols "; 4858 sym_name = 4859 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 4860 info, n_value, cro.baseProtocols); 4861 if (n_value != 0) { 4862 if (info->verbose && sym_name != nullptr) 4863 outs() << sym_name; 4864 else 4865 outs() << format("0x%" PRIx64, n_value); 4866 if (cro.baseProtocols != 0) 4867 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 4868 } else 4869 outs() << format("0x%" PRIx64, cro.baseProtocols); 4870 outs() << "\n"; 4871 if (cro.baseProtocols + n_value != 0) 4872 print_protocol_list64_t(cro.baseProtocols + n_value, info); 4873 4874 outs() << " ivars "; 4875 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 4876 info, n_value, cro.ivars); 4877 if (n_value != 0) { 4878 if (info->verbose && sym_name != nullptr) 4879 outs() << sym_name; 4880 else 4881 outs() << format("0x%" PRIx64, n_value); 4882 if (cro.ivars != 0) 4883 outs() << " + " << format("0x%" PRIx64, cro.ivars); 4884 } else 4885 outs() << format("0x%" PRIx64, cro.ivars); 4886 outs() << "\n"; 4887 if (cro.ivars + n_value != 0) 4888 print_ivar_list64_t(cro.ivars + n_value, info); 4889 4890 outs() << " weakIvarLayout "; 4891 sym_name = 4892 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 4893 info, n_value, cro.weakIvarLayout); 4894 if (n_value != 0) { 4895 if (info->verbose && sym_name != nullptr) 4896 outs() << sym_name; 4897 else 4898 outs() << format("0x%" PRIx64, n_value); 4899 if (cro.weakIvarLayout != 0) 4900 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 4901 } else 4902 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 4903 outs() << "\n"; 4904 print_layout_map64(cro.weakIvarLayout + n_value, info); 4905 4906 outs() << " baseProperties "; 4907 sym_name = 4908 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 4909 info, n_value, cro.baseProperties); 4910 if (n_value != 0) { 4911 if (info->verbose && sym_name != nullptr) 4912 outs() << sym_name; 4913 else 4914 outs() << format("0x%" PRIx64, n_value); 4915 if (cro.baseProperties != 0) 4916 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 4917 } else 4918 outs() << format("0x%" PRIx64, cro.baseProperties); 4919 outs() << "\n"; 4920 if (cro.baseProperties + n_value != 0) 4921 print_objc_property_list64(cro.baseProperties + n_value, info); 4922 4923 is_meta_class = (cro.flags & RO_META) != 0; 4924 return true; 4925 } 4926 4927 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 4928 bool &is_meta_class) { 4929 struct class_ro32_t cro; 4930 const char *r; 4931 uint32_t offset, xoffset, left; 4932 SectionRef S, xS; 4933 const char *name; 4934 4935 r = get_pointer_32(p, offset, left, S, info); 4936 if (r == nullptr) 4937 return false; 4938 memset(&cro, '\0', sizeof(struct class_ro32_t)); 4939 if (left < sizeof(struct class_ro32_t)) { 4940 memcpy(&cro, r, left); 4941 outs() << " (class_ro_t entends past the end of the section)\n"; 4942 } else 4943 memcpy(&cro, r, sizeof(struct class_ro32_t)); 4944 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4945 swapStruct(cro); 4946 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4947 if (cro.flags & RO_META) 4948 outs() << " RO_META"; 4949 if (cro.flags & RO_ROOT) 4950 outs() << " RO_ROOT"; 4951 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4952 outs() << " RO_HAS_CXX_STRUCTORS"; 4953 outs() << "\n"; 4954 outs() << " instanceStart " << cro.instanceStart << "\n"; 4955 outs() << " instanceSize " << cro.instanceSize << "\n"; 4956 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 4957 << "\n"; 4958 print_layout_map32(cro.ivarLayout, info); 4959 4960 outs() << " name " << format("0x%" PRIx32, cro.name); 4961 name = get_pointer_32(cro.name, xoffset, left, xS, info); 4962 if (name != nullptr) 4963 outs() << format(" %.*s", left, name); 4964 outs() << "\n"; 4965 4966 outs() << " baseMethods " 4967 << format("0x%" PRIx32, cro.baseMethods) 4968 << " (struct method_list_t *)\n"; 4969 if (cro.baseMethods != 0) 4970 print_method_list32_t(cro.baseMethods, info, ""); 4971 4972 outs() << " baseProtocols " 4973 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 4974 if (cro.baseProtocols != 0) 4975 print_protocol_list32_t(cro.baseProtocols, info); 4976 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 4977 << "\n"; 4978 if (cro.ivars != 0) 4979 print_ivar_list32_t(cro.ivars, info); 4980 outs() << " weakIvarLayout " 4981 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 4982 print_layout_map32(cro.weakIvarLayout, info); 4983 outs() << " baseProperties " 4984 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 4985 if (cro.baseProperties != 0) 4986 print_objc_property_list32(cro.baseProperties, info); 4987 is_meta_class = (cro.flags & RO_META) != 0; 4988 return true; 4989 } 4990 4991 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 4992 struct class64_t c; 4993 const char *r; 4994 uint32_t offset, left; 4995 SectionRef S; 4996 const char *name; 4997 uint64_t isa_n_value, n_value; 4998 4999 r = get_pointer_64(p, offset, left, S, info); 5000 if (r == nullptr || left < sizeof(struct class64_t)) 5001 return; 5002 memcpy(&c, r, sizeof(struct class64_t)); 5003 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5004 swapStruct(c); 5005 5006 outs() << " isa " << format("0x%" PRIx64, c.isa); 5007 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 5008 isa_n_value, c.isa); 5009 if (name != nullptr) 5010 outs() << " " << name; 5011 outs() << "\n"; 5012 5013 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 5014 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 5015 n_value, c.superclass); 5016 if (name != nullptr) 5017 outs() << " " << name; 5018 else { 5019 name = get_dyld_bind_info_symbolname(S.getAddress() + 5020 offset + offsetof(struct class64_t, superclass), info); 5021 if (name != nullptr) 5022 outs() << " " << name; 5023 } 5024 outs() << "\n"; 5025 5026 outs() << " cache " << format("0x%" PRIx64, c.cache); 5027 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 5028 n_value, c.cache); 5029 if (name != nullptr) 5030 outs() << " " << name; 5031 outs() << "\n"; 5032 5033 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 5034 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 5035 n_value, c.vtable); 5036 if (name != nullptr) 5037 outs() << " " << name; 5038 outs() << "\n"; 5039 5040 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 5041 n_value, c.data); 5042 outs() << " data "; 5043 if (n_value != 0) { 5044 if (info->verbose && name != nullptr) 5045 outs() << name; 5046 else 5047 outs() << format("0x%" PRIx64, n_value); 5048 if (c.data != 0) 5049 outs() << " + " << format("0x%" PRIx64, c.data); 5050 } else 5051 outs() << format("0x%" PRIx64, c.data); 5052 outs() << " (struct class_ro_t *)"; 5053 5054 // This is a Swift class if some of the low bits of the pointer are set. 5055 if ((c.data + n_value) & 0x7) 5056 outs() << " Swift class"; 5057 outs() << "\n"; 5058 bool is_meta_class; 5059 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5060 return; 5061 5062 if (!is_meta_class && 5063 c.isa + isa_n_value != p && 5064 c.isa + isa_n_value != 0 && 5065 info->depth < 100) { 5066 info->depth++; 5067 outs() << "Meta Class\n"; 5068 print_class64_t(c.isa + isa_n_value, info); 5069 } 5070 } 5071 5072 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5073 struct class32_t c; 5074 const char *r; 5075 uint32_t offset, left; 5076 SectionRef S; 5077 const char *name; 5078 5079 r = get_pointer_32(p, offset, left, S, info); 5080 if (r == nullptr) 5081 return; 5082 memset(&c, '\0', sizeof(struct class32_t)); 5083 if (left < sizeof(struct class32_t)) { 5084 memcpy(&c, r, left); 5085 outs() << " (class_t entends past the end of the section)\n"; 5086 } else 5087 memcpy(&c, r, sizeof(struct class32_t)); 5088 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5089 swapStruct(c); 5090 5091 outs() << " isa " << format("0x%" PRIx32, c.isa); 5092 name = 5093 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5094 if (name != nullptr) 5095 outs() << " " << name; 5096 outs() << "\n"; 5097 5098 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5099 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5100 c.superclass); 5101 if (name != nullptr) 5102 outs() << " " << name; 5103 outs() << "\n"; 5104 5105 outs() << " cache " << format("0x%" PRIx32, c.cache); 5106 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5107 c.cache); 5108 if (name != nullptr) 5109 outs() << " " << name; 5110 outs() << "\n"; 5111 5112 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5113 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5114 c.vtable); 5115 if (name != nullptr) 5116 outs() << " " << name; 5117 outs() << "\n"; 5118 5119 name = 5120 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5121 outs() << " data " << format("0x%" PRIx32, c.data) 5122 << " (struct class_ro_t *)"; 5123 5124 // This is a Swift class if some of the low bits of the pointer are set. 5125 if (c.data & 0x3) 5126 outs() << " Swift class"; 5127 outs() << "\n"; 5128 bool is_meta_class; 5129 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5130 return; 5131 5132 if (!is_meta_class) { 5133 outs() << "Meta Class\n"; 5134 print_class32_t(c.isa, info); 5135 } 5136 } 5137 5138 static void print_objc_class_t(struct objc_class_t *objc_class, 5139 struct DisassembleInfo *info) { 5140 uint32_t offset, left, xleft; 5141 const char *name, *p, *ivar_list; 5142 SectionRef S; 5143 int32_t i; 5144 struct objc_ivar_list_t objc_ivar_list; 5145 struct objc_ivar_t ivar; 5146 5147 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5148 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5149 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5150 if (name != nullptr) 5151 outs() << format(" %.*s", left, name); 5152 else 5153 outs() << " (not in an __OBJC section)"; 5154 } 5155 outs() << "\n"; 5156 5157 outs() << "\t super_class " 5158 << format("0x%08" PRIx32, objc_class->super_class); 5159 if (info->verbose) { 5160 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5161 if (name != nullptr) 5162 outs() << format(" %.*s", left, name); 5163 else 5164 outs() << " (not in an __OBJC section)"; 5165 } 5166 outs() << "\n"; 5167 5168 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5169 if (info->verbose) { 5170 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5171 if (name != nullptr) 5172 outs() << format(" %.*s", left, name); 5173 else 5174 outs() << " (not in an __OBJC section)"; 5175 } 5176 outs() << "\n"; 5177 5178 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5179 << "\n"; 5180 5181 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5182 if (info->verbose) { 5183 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5184 outs() << " CLS_CLASS"; 5185 else if (CLS_GETINFO(objc_class, CLS_META)) 5186 outs() << " CLS_META"; 5187 } 5188 outs() << "\n"; 5189 5190 outs() << "\t instance_size " 5191 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5192 5193 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5194 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5195 if (p != nullptr) { 5196 if (left > sizeof(struct objc_ivar_list_t)) { 5197 outs() << "\n"; 5198 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5199 } else { 5200 outs() << " (entends past the end of the section)\n"; 5201 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5202 memcpy(&objc_ivar_list, p, left); 5203 } 5204 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5205 swapStruct(objc_ivar_list); 5206 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5207 ivar_list = p + sizeof(struct objc_ivar_list_t); 5208 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5209 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5210 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5211 break; 5212 } 5213 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5214 sizeof(struct objc_ivar_t)); 5215 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5216 swapStruct(ivar); 5217 5218 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5219 if (info->verbose) { 5220 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5221 if (name != nullptr) 5222 outs() << format(" %.*s", xleft, name); 5223 else 5224 outs() << " (not in an __OBJC section)"; 5225 } 5226 outs() << "\n"; 5227 5228 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5229 if (info->verbose) { 5230 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5231 if (name != nullptr) 5232 outs() << format(" %.*s", xleft, name); 5233 else 5234 outs() << " (not in an __OBJC section)"; 5235 } 5236 outs() << "\n"; 5237 5238 outs() << "\t\t ivar_offset " 5239 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5240 } 5241 } else { 5242 outs() << " (not in an __OBJC section)\n"; 5243 } 5244 5245 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5246 if (print_method_list(objc_class->methodLists, info)) 5247 outs() << " (not in an __OBJC section)\n"; 5248 5249 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5250 << "\n"; 5251 5252 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5253 if (print_protocol_list(objc_class->protocols, 16, info)) 5254 outs() << " (not in an __OBJC section)\n"; 5255 } 5256 5257 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5258 struct DisassembleInfo *info) { 5259 uint32_t offset, left; 5260 const char *name; 5261 SectionRef S; 5262 5263 outs() << "\t category name " 5264 << format("0x%08" PRIx32, objc_category->category_name); 5265 if (info->verbose) { 5266 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5267 true); 5268 if (name != nullptr) 5269 outs() << format(" %.*s", left, name); 5270 else 5271 outs() << " (not in an __OBJC section)"; 5272 } 5273 outs() << "\n"; 5274 5275 outs() << "\t\t class name " 5276 << format("0x%08" PRIx32, objc_category->class_name); 5277 if (info->verbose) { 5278 name = 5279 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5280 if (name != nullptr) 5281 outs() << format(" %.*s", left, name); 5282 else 5283 outs() << " (not in an __OBJC section)"; 5284 } 5285 outs() << "\n"; 5286 5287 outs() << "\t instance methods " 5288 << format("0x%08" PRIx32, objc_category->instance_methods); 5289 if (print_method_list(objc_category->instance_methods, info)) 5290 outs() << " (not in an __OBJC section)\n"; 5291 5292 outs() << "\t class methods " 5293 << format("0x%08" PRIx32, objc_category->class_methods); 5294 if (print_method_list(objc_category->class_methods, info)) 5295 outs() << " (not in an __OBJC section)\n"; 5296 } 5297 5298 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5299 struct category64_t c; 5300 const char *r; 5301 uint32_t offset, xoffset, left; 5302 SectionRef S, xS; 5303 const char *name, *sym_name; 5304 uint64_t n_value; 5305 5306 r = get_pointer_64(p, offset, left, S, info); 5307 if (r == nullptr) 5308 return; 5309 memset(&c, '\0', sizeof(struct category64_t)); 5310 if (left < sizeof(struct category64_t)) { 5311 memcpy(&c, r, left); 5312 outs() << " (category_t entends past the end of the section)\n"; 5313 } else 5314 memcpy(&c, r, sizeof(struct category64_t)); 5315 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5316 swapStruct(c); 5317 5318 outs() << " name "; 5319 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 5320 info, n_value, c.name); 5321 if (n_value != 0) { 5322 if (info->verbose && sym_name != nullptr) 5323 outs() << sym_name; 5324 else 5325 outs() << format("0x%" PRIx64, n_value); 5326 if (c.name != 0) 5327 outs() << " + " << format("0x%" PRIx64, c.name); 5328 } else 5329 outs() << format("0x%" PRIx64, c.name); 5330 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 5331 if (name != nullptr) 5332 outs() << format(" %.*s", left, name); 5333 outs() << "\n"; 5334 5335 outs() << " cls "; 5336 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 5337 n_value, c.cls); 5338 if (n_value != 0) { 5339 if (info->verbose && sym_name != nullptr) 5340 outs() << sym_name; 5341 else 5342 outs() << format("0x%" PRIx64, n_value); 5343 if (c.cls != 0) 5344 outs() << " + " << format("0x%" PRIx64, c.cls); 5345 } else 5346 outs() << format("0x%" PRIx64, c.cls); 5347 outs() << "\n"; 5348 if (c.cls + n_value != 0) 5349 print_class64_t(c.cls + n_value, info); 5350 5351 outs() << " instanceMethods "; 5352 sym_name = 5353 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 5354 info, n_value, c.instanceMethods); 5355 if (n_value != 0) { 5356 if (info->verbose && sym_name != nullptr) 5357 outs() << sym_name; 5358 else 5359 outs() << format("0x%" PRIx64, n_value); 5360 if (c.instanceMethods != 0) 5361 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 5362 } else 5363 outs() << format("0x%" PRIx64, c.instanceMethods); 5364 outs() << "\n"; 5365 if (c.instanceMethods + n_value != 0) 5366 print_method_list64_t(c.instanceMethods + n_value, info, ""); 5367 5368 outs() << " classMethods "; 5369 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 5370 S, info, n_value, c.classMethods); 5371 if (n_value != 0) { 5372 if (info->verbose && sym_name != nullptr) 5373 outs() << sym_name; 5374 else 5375 outs() << format("0x%" PRIx64, n_value); 5376 if (c.classMethods != 0) 5377 outs() << " + " << format("0x%" PRIx64, c.classMethods); 5378 } else 5379 outs() << format("0x%" PRIx64, c.classMethods); 5380 outs() << "\n"; 5381 if (c.classMethods + n_value != 0) 5382 print_method_list64_t(c.classMethods + n_value, info, ""); 5383 5384 outs() << " protocols "; 5385 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 5386 info, n_value, c.protocols); 5387 if (n_value != 0) { 5388 if (info->verbose && sym_name != nullptr) 5389 outs() << sym_name; 5390 else 5391 outs() << format("0x%" PRIx64, n_value); 5392 if (c.protocols != 0) 5393 outs() << " + " << format("0x%" PRIx64, c.protocols); 5394 } else 5395 outs() << format("0x%" PRIx64, c.protocols); 5396 outs() << "\n"; 5397 if (c.protocols + n_value != 0) 5398 print_protocol_list64_t(c.protocols + n_value, info); 5399 5400 outs() << "instanceProperties "; 5401 sym_name = 5402 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 5403 S, info, n_value, c.instanceProperties); 5404 if (n_value != 0) { 5405 if (info->verbose && sym_name != nullptr) 5406 outs() << sym_name; 5407 else 5408 outs() << format("0x%" PRIx64, n_value); 5409 if (c.instanceProperties != 0) 5410 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 5411 } else 5412 outs() << format("0x%" PRIx64, c.instanceProperties); 5413 outs() << "\n"; 5414 if (c.instanceProperties + n_value != 0) 5415 print_objc_property_list64(c.instanceProperties + n_value, info); 5416 } 5417 5418 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 5419 struct category32_t c; 5420 const char *r; 5421 uint32_t offset, left; 5422 SectionRef S, xS; 5423 const char *name; 5424 5425 r = get_pointer_32(p, offset, left, S, info); 5426 if (r == nullptr) 5427 return; 5428 memset(&c, '\0', sizeof(struct category32_t)); 5429 if (left < sizeof(struct category32_t)) { 5430 memcpy(&c, r, left); 5431 outs() << " (category_t entends past the end of the section)\n"; 5432 } else 5433 memcpy(&c, r, sizeof(struct category32_t)); 5434 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5435 swapStruct(c); 5436 5437 outs() << " name " << format("0x%" PRIx32, c.name); 5438 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 5439 c.name); 5440 if (name) 5441 outs() << " " << name; 5442 outs() << "\n"; 5443 5444 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 5445 if (c.cls != 0) 5446 print_class32_t(c.cls, info); 5447 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 5448 << "\n"; 5449 if (c.instanceMethods != 0) 5450 print_method_list32_t(c.instanceMethods, info, ""); 5451 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 5452 << "\n"; 5453 if (c.classMethods != 0) 5454 print_method_list32_t(c.classMethods, info, ""); 5455 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 5456 if (c.protocols != 0) 5457 print_protocol_list32_t(c.protocols, info); 5458 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 5459 << "\n"; 5460 if (c.instanceProperties != 0) 5461 print_objc_property_list32(c.instanceProperties, info); 5462 } 5463 5464 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 5465 uint32_t i, left, offset, xoffset; 5466 uint64_t p, n_value; 5467 struct message_ref64 mr; 5468 const char *name, *sym_name; 5469 const char *r; 5470 SectionRef xS; 5471 5472 if (S == SectionRef()) 5473 return; 5474 5475 StringRef SectName; 5476 S.getName(SectName); 5477 DataRefImpl Ref = S.getRawDataRefImpl(); 5478 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5479 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5480 offset = 0; 5481 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5482 p = S.getAddress() + i; 5483 r = get_pointer_64(p, offset, left, S, info); 5484 if (r == nullptr) 5485 return; 5486 memset(&mr, '\0', sizeof(struct message_ref64)); 5487 if (left < sizeof(struct message_ref64)) { 5488 memcpy(&mr, r, left); 5489 outs() << " (message_ref entends past the end of the section)\n"; 5490 } else 5491 memcpy(&mr, r, sizeof(struct message_ref64)); 5492 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5493 swapStruct(mr); 5494 5495 outs() << " imp "; 5496 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 5497 n_value, mr.imp); 5498 if (n_value != 0) { 5499 outs() << format("0x%" PRIx64, n_value) << " "; 5500 if (mr.imp != 0) 5501 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 5502 } else 5503 outs() << format("0x%" PRIx64, mr.imp) << " "; 5504 if (name != nullptr) 5505 outs() << " " << name; 5506 outs() << "\n"; 5507 5508 outs() << " sel "; 5509 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 5510 info, n_value, mr.sel); 5511 if (n_value != 0) { 5512 if (info->verbose && sym_name != nullptr) 5513 outs() << sym_name; 5514 else 5515 outs() << format("0x%" PRIx64, n_value); 5516 if (mr.sel != 0) 5517 outs() << " + " << format("0x%" PRIx64, mr.sel); 5518 } else 5519 outs() << format("0x%" PRIx64, mr.sel); 5520 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 5521 if (name != nullptr) 5522 outs() << format(" %.*s", left, name); 5523 outs() << "\n"; 5524 5525 offset += sizeof(struct message_ref64); 5526 } 5527 } 5528 5529 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 5530 uint32_t i, left, offset, xoffset, p; 5531 struct message_ref32 mr; 5532 const char *name, *r; 5533 SectionRef xS; 5534 5535 if (S == SectionRef()) 5536 return; 5537 5538 StringRef SectName; 5539 S.getName(SectName); 5540 DataRefImpl Ref = S.getRawDataRefImpl(); 5541 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5542 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5543 offset = 0; 5544 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5545 p = S.getAddress() + i; 5546 r = get_pointer_32(p, offset, left, S, info); 5547 if (r == nullptr) 5548 return; 5549 memset(&mr, '\0', sizeof(struct message_ref32)); 5550 if (left < sizeof(struct message_ref32)) { 5551 memcpy(&mr, r, left); 5552 outs() << " (message_ref entends past the end of the section)\n"; 5553 } else 5554 memcpy(&mr, r, sizeof(struct message_ref32)); 5555 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5556 swapStruct(mr); 5557 5558 outs() << " imp " << format("0x%" PRIx32, mr.imp); 5559 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 5560 mr.imp); 5561 if (name != nullptr) 5562 outs() << " " << name; 5563 outs() << "\n"; 5564 5565 outs() << " sel " << format("0x%" PRIx32, mr.sel); 5566 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 5567 if (name != nullptr) 5568 outs() << " " << name; 5569 outs() << "\n"; 5570 5571 offset += sizeof(struct message_ref32); 5572 } 5573 } 5574 5575 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 5576 uint32_t left, offset, swift_version; 5577 uint64_t p; 5578 struct objc_image_info64 o; 5579 const char *r; 5580 5581 if (S == SectionRef()) 5582 return; 5583 5584 StringRef SectName; 5585 S.getName(SectName); 5586 DataRefImpl Ref = S.getRawDataRefImpl(); 5587 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5588 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5589 p = S.getAddress(); 5590 r = get_pointer_64(p, offset, left, S, info); 5591 if (r == nullptr) 5592 return; 5593 memset(&o, '\0', sizeof(struct objc_image_info64)); 5594 if (left < sizeof(struct objc_image_info64)) { 5595 memcpy(&o, r, left); 5596 outs() << " (objc_image_info entends past the end of the section)\n"; 5597 } else 5598 memcpy(&o, r, sizeof(struct objc_image_info64)); 5599 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5600 swapStruct(o); 5601 outs() << " version " << o.version << "\n"; 5602 outs() << " flags " << format("0x%" PRIx32, o.flags); 5603 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5604 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5605 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5606 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5607 if (o.flags & OBJC_IMAGE_IS_SIMULATED) 5608 outs() << " OBJC_IMAGE_IS_SIMULATED"; 5609 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES) 5610 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES"; 5611 swift_version = (o.flags >> 8) & 0xff; 5612 if (swift_version != 0) { 5613 if (swift_version == 1) 5614 outs() << " Swift 1.0"; 5615 else if (swift_version == 2) 5616 outs() << " Swift 1.1"; 5617 else if(swift_version == 3) 5618 outs() << " Swift 2.0"; 5619 else if(swift_version == 4) 5620 outs() << " Swift 3.0"; 5621 else if(swift_version == 5) 5622 outs() << " Swift 4.0"; 5623 else if(swift_version == 6) 5624 outs() << " Swift 4.1"; 5625 else 5626 outs() << " unknown future Swift version (" << swift_version << ")"; 5627 } 5628 outs() << "\n"; 5629 } 5630 5631 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 5632 uint32_t left, offset, swift_version, p; 5633 struct objc_image_info32 o; 5634 const char *r; 5635 5636 if (S == SectionRef()) 5637 return; 5638 5639 StringRef SectName; 5640 S.getName(SectName); 5641 DataRefImpl Ref = S.getRawDataRefImpl(); 5642 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5643 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5644 p = S.getAddress(); 5645 r = get_pointer_32(p, offset, left, S, info); 5646 if (r == nullptr) 5647 return; 5648 memset(&o, '\0', sizeof(struct objc_image_info32)); 5649 if (left < sizeof(struct objc_image_info32)) { 5650 memcpy(&o, r, left); 5651 outs() << " (objc_image_info entends past the end of the section)\n"; 5652 } else 5653 memcpy(&o, r, sizeof(struct objc_image_info32)); 5654 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5655 swapStruct(o); 5656 outs() << " version " << o.version << "\n"; 5657 outs() << " flags " << format("0x%" PRIx32, o.flags); 5658 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5659 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5660 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5661 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5662 swift_version = (o.flags >> 8) & 0xff; 5663 if (swift_version != 0) { 5664 if (swift_version == 1) 5665 outs() << " Swift 1.0"; 5666 else if (swift_version == 2) 5667 outs() << " Swift 1.1"; 5668 else if(swift_version == 3) 5669 outs() << " Swift 2.0"; 5670 else if(swift_version == 4) 5671 outs() << " Swift 3.0"; 5672 else if(swift_version == 5) 5673 outs() << " Swift 4.0"; 5674 else if(swift_version == 6) 5675 outs() << " Swift 4.1"; 5676 else 5677 outs() << " unknown future Swift version (" << swift_version << ")"; 5678 } 5679 outs() << "\n"; 5680 } 5681 5682 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 5683 uint32_t left, offset, p; 5684 struct imageInfo_t o; 5685 const char *r; 5686 5687 StringRef SectName; 5688 S.getName(SectName); 5689 DataRefImpl Ref = S.getRawDataRefImpl(); 5690 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5691 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5692 p = S.getAddress(); 5693 r = get_pointer_32(p, offset, left, S, info); 5694 if (r == nullptr) 5695 return; 5696 memset(&o, '\0', sizeof(struct imageInfo_t)); 5697 if (left < sizeof(struct imageInfo_t)) { 5698 memcpy(&o, r, left); 5699 outs() << " (imageInfo entends past the end of the section)\n"; 5700 } else 5701 memcpy(&o, r, sizeof(struct imageInfo_t)); 5702 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5703 swapStruct(o); 5704 outs() << " version " << o.version << "\n"; 5705 outs() << " flags " << format("0x%" PRIx32, o.flags); 5706 if (o.flags & 0x1) 5707 outs() << " F&C"; 5708 if (o.flags & 0x2) 5709 outs() << " GC"; 5710 if (o.flags & 0x4) 5711 outs() << " GC-only"; 5712 else 5713 outs() << " RR"; 5714 outs() << "\n"; 5715 } 5716 5717 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 5718 SymbolAddressMap AddrMap; 5719 if (verbose) 5720 CreateSymbolAddressMap(O, &AddrMap); 5721 5722 std::vector<SectionRef> Sections; 5723 for (const SectionRef &Section : O->sections()) { 5724 StringRef SectName; 5725 Section.getName(SectName); 5726 Sections.push_back(Section); 5727 } 5728 5729 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 5730 5731 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5732 if (CL == SectionRef()) 5733 CL = get_section(O, "__DATA", "__objc_classlist"); 5734 if (CL == SectionRef()) 5735 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5736 if (CL == SectionRef()) 5737 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5738 info.S = CL; 5739 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 5740 5741 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5742 if (CR == SectionRef()) 5743 CR = get_section(O, "__DATA", "__objc_classrefs"); 5744 if (CR == SectionRef()) 5745 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5746 if (CR == SectionRef()) 5747 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5748 info.S = CR; 5749 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 5750 5751 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5752 if (SR == SectionRef()) 5753 SR = get_section(O, "__DATA", "__objc_superrefs"); 5754 if (SR == SectionRef()) 5755 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5756 if (SR == SectionRef()) 5757 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5758 info.S = SR; 5759 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 5760 5761 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5762 if (CA == SectionRef()) 5763 CA = get_section(O, "__DATA", "__objc_catlist"); 5764 if (CA == SectionRef()) 5765 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5766 if (CA == SectionRef()) 5767 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5768 info.S = CA; 5769 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 5770 5771 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5772 if (PL == SectionRef()) 5773 PL = get_section(O, "__DATA", "__objc_protolist"); 5774 if (PL == SectionRef()) 5775 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5776 if (PL == SectionRef()) 5777 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5778 info.S = PL; 5779 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 5780 5781 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5782 if (MR == SectionRef()) 5783 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5784 if (MR == SectionRef()) 5785 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5786 if (MR == SectionRef()) 5787 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5788 info.S = MR; 5789 print_message_refs64(MR, &info); 5790 5791 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5792 if (II == SectionRef()) 5793 II = get_section(O, "__DATA", "__objc_imageinfo"); 5794 if (II == SectionRef()) 5795 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5796 if (II == SectionRef()) 5797 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5798 info.S = II; 5799 print_image_info64(II, &info); 5800 } 5801 5802 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5803 SymbolAddressMap AddrMap; 5804 if (verbose) 5805 CreateSymbolAddressMap(O, &AddrMap); 5806 5807 std::vector<SectionRef> Sections; 5808 for (const SectionRef &Section : O->sections()) { 5809 StringRef SectName; 5810 Section.getName(SectName); 5811 Sections.push_back(Section); 5812 } 5813 5814 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 5815 5816 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5817 if (CL == SectionRef()) 5818 CL = get_section(O, "__DATA", "__objc_classlist"); 5819 if (CL == SectionRef()) 5820 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5821 if (CL == SectionRef()) 5822 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5823 info.S = CL; 5824 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 5825 5826 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5827 if (CR == SectionRef()) 5828 CR = get_section(O, "__DATA", "__objc_classrefs"); 5829 if (CR == SectionRef()) 5830 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5831 if (CR == SectionRef()) 5832 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5833 info.S = CR; 5834 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 5835 5836 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5837 if (SR == SectionRef()) 5838 SR = get_section(O, "__DATA", "__objc_superrefs"); 5839 if (SR == SectionRef()) 5840 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5841 if (SR == SectionRef()) 5842 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5843 info.S = SR; 5844 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 5845 5846 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5847 if (CA == SectionRef()) 5848 CA = get_section(O, "__DATA", "__objc_catlist"); 5849 if (CA == SectionRef()) 5850 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5851 if (CA == SectionRef()) 5852 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5853 info.S = CA; 5854 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 5855 5856 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5857 if (PL == SectionRef()) 5858 PL = get_section(O, "__DATA", "__objc_protolist"); 5859 if (PL == SectionRef()) 5860 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5861 if (PL == SectionRef()) 5862 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5863 info.S = PL; 5864 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 5865 5866 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5867 if (MR == SectionRef()) 5868 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5869 if (MR == SectionRef()) 5870 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5871 if (MR == SectionRef()) 5872 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5873 info.S = MR; 5874 print_message_refs32(MR, &info); 5875 5876 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5877 if (II == SectionRef()) 5878 II = get_section(O, "__DATA", "__objc_imageinfo"); 5879 if (II == SectionRef()) 5880 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5881 if (II == SectionRef()) 5882 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5883 info.S = II; 5884 print_image_info32(II, &info); 5885 } 5886 5887 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5888 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 5889 const char *r, *name, *defs; 5890 struct objc_module_t module; 5891 SectionRef S, xS; 5892 struct objc_symtab_t symtab; 5893 struct objc_class_t objc_class; 5894 struct objc_category_t objc_category; 5895 5896 outs() << "Objective-C segment\n"; 5897 S = get_section(O, "__OBJC", "__module_info"); 5898 if (S == SectionRef()) 5899 return false; 5900 5901 SymbolAddressMap AddrMap; 5902 if (verbose) 5903 CreateSymbolAddressMap(O, &AddrMap); 5904 5905 std::vector<SectionRef> Sections; 5906 for (const SectionRef &Section : O->sections()) { 5907 StringRef SectName; 5908 Section.getName(SectName); 5909 Sections.push_back(Section); 5910 } 5911 5912 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 5913 5914 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 5915 p = S.getAddress() + i; 5916 r = get_pointer_32(p, offset, left, S, &info, true); 5917 if (r == nullptr) 5918 return true; 5919 memset(&module, '\0', sizeof(struct objc_module_t)); 5920 if (left < sizeof(struct objc_module_t)) { 5921 memcpy(&module, r, left); 5922 outs() << " (module extends past end of __module_info section)\n"; 5923 } else 5924 memcpy(&module, r, sizeof(struct objc_module_t)); 5925 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5926 swapStruct(module); 5927 5928 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 5929 outs() << " version " << module.version << "\n"; 5930 outs() << " size " << module.size << "\n"; 5931 outs() << " name "; 5932 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 5933 if (name != nullptr) 5934 outs() << format("%.*s", left, name); 5935 else 5936 outs() << format("0x%08" PRIx32, module.name) 5937 << "(not in an __OBJC section)"; 5938 outs() << "\n"; 5939 5940 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 5941 if (module.symtab == 0 || r == nullptr) { 5942 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 5943 << " (not in an __OBJC section)\n"; 5944 continue; 5945 } 5946 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 5947 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 5948 defs_left = 0; 5949 defs = nullptr; 5950 if (left < sizeof(struct objc_symtab_t)) { 5951 memcpy(&symtab, r, left); 5952 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 5953 } else { 5954 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 5955 if (left > sizeof(struct objc_symtab_t)) { 5956 defs_left = left - sizeof(struct objc_symtab_t); 5957 defs = r + sizeof(struct objc_symtab_t); 5958 } 5959 } 5960 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5961 swapStruct(symtab); 5962 5963 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 5964 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 5965 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 5966 if (r == nullptr) 5967 outs() << " (not in an __OBJC section)"; 5968 outs() << "\n"; 5969 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 5970 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 5971 if (symtab.cls_def_cnt > 0) 5972 outs() << "\tClass Definitions\n"; 5973 for (j = 0; j < symtab.cls_def_cnt; j++) { 5974 if ((j + 1) * sizeof(uint32_t) > defs_left) { 5975 outs() << "\t(remaining class defs entries entends past the end of the " 5976 << "section)\n"; 5977 break; 5978 } 5979 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 5980 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5981 sys::swapByteOrder(def); 5982 5983 r = get_pointer_32(def, xoffset, left, xS, &info, true); 5984 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 5985 if (r != nullptr) { 5986 if (left > sizeof(struct objc_class_t)) { 5987 outs() << "\n"; 5988 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 5989 } else { 5990 outs() << " (entends past the end of the section)\n"; 5991 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 5992 memcpy(&objc_class, r, left); 5993 } 5994 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5995 swapStruct(objc_class); 5996 print_objc_class_t(&objc_class, &info); 5997 } else { 5998 outs() << "(not in an __OBJC section)\n"; 5999 } 6000 6001 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 6002 outs() << "\tMeta Class"; 6003 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 6004 if (r != nullptr) { 6005 if (left > sizeof(struct objc_class_t)) { 6006 outs() << "\n"; 6007 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6008 } else { 6009 outs() << " (entends past the end of the section)\n"; 6010 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6011 memcpy(&objc_class, r, left); 6012 } 6013 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6014 swapStruct(objc_class); 6015 print_objc_class_t(&objc_class, &info); 6016 } else { 6017 outs() << "(not in an __OBJC section)\n"; 6018 } 6019 } 6020 } 6021 if (symtab.cat_def_cnt > 0) 6022 outs() << "\tCategory Definitions\n"; 6023 for (j = 0; j < symtab.cat_def_cnt; j++) { 6024 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 6025 outs() << "\t(remaining category defs entries entends past the end of " 6026 << "the section)\n"; 6027 break; 6028 } 6029 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6030 sizeof(uint32_t)); 6031 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6032 sys::swapByteOrder(def); 6033 6034 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6035 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6036 << format("0x%08" PRIx32, def); 6037 if (r != nullptr) { 6038 if (left > sizeof(struct objc_category_t)) { 6039 outs() << "\n"; 6040 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6041 } else { 6042 outs() << " (entends past the end of the section)\n"; 6043 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6044 memcpy(&objc_category, r, left); 6045 } 6046 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6047 swapStruct(objc_category); 6048 print_objc_objc_category_t(&objc_category, &info); 6049 } else { 6050 outs() << "(not in an __OBJC section)\n"; 6051 } 6052 } 6053 } 6054 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6055 if (II != SectionRef()) 6056 print_image_info(II, &info); 6057 6058 return true; 6059 } 6060 6061 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6062 uint32_t size, uint32_t addr) { 6063 SymbolAddressMap AddrMap; 6064 CreateSymbolAddressMap(O, &AddrMap); 6065 6066 std::vector<SectionRef> Sections; 6067 for (const SectionRef &Section : O->sections()) { 6068 StringRef SectName; 6069 Section.getName(SectName); 6070 Sections.push_back(Section); 6071 } 6072 6073 struct DisassembleInfo info(O, &AddrMap, &Sections, true); 6074 6075 const char *p; 6076 struct objc_protocol_t protocol; 6077 uint32_t left, paddr; 6078 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6079 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6080 left = size - (p - sect); 6081 if (left < sizeof(struct objc_protocol_t)) { 6082 outs() << "Protocol extends past end of __protocol section\n"; 6083 memcpy(&protocol, p, left); 6084 } else 6085 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6086 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6087 swapStruct(protocol); 6088 paddr = addr + (p - sect); 6089 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6090 if (print_protocol(paddr, 0, &info)) 6091 outs() << "(not in an __OBJC section)\n"; 6092 } 6093 } 6094 6095 #ifdef HAVE_LIBXAR 6096 inline void swapStruct(struct xar_header &xar) { 6097 sys::swapByteOrder(xar.magic); 6098 sys::swapByteOrder(xar.size); 6099 sys::swapByteOrder(xar.version); 6100 sys::swapByteOrder(xar.toc_length_compressed); 6101 sys::swapByteOrder(xar.toc_length_uncompressed); 6102 sys::swapByteOrder(xar.cksum_alg); 6103 } 6104 6105 static void PrintModeVerbose(uint32_t mode) { 6106 switch(mode & S_IFMT){ 6107 case S_IFDIR: 6108 outs() << "d"; 6109 break; 6110 case S_IFCHR: 6111 outs() << "c"; 6112 break; 6113 case S_IFBLK: 6114 outs() << "b"; 6115 break; 6116 case S_IFREG: 6117 outs() << "-"; 6118 break; 6119 case S_IFLNK: 6120 outs() << "l"; 6121 break; 6122 case S_IFSOCK: 6123 outs() << "s"; 6124 break; 6125 default: 6126 outs() << "?"; 6127 break; 6128 } 6129 6130 /* owner permissions */ 6131 if(mode & S_IREAD) 6132 outs() << "r"; 6133 else 6134 outs() << "-"; 6135 if(mode & S_IWRITE) 6136 outs() << "w"; 6137 else 6138 outs() << "-"; 6139 if(mode & S_ISUID) 6140 outs() << "s"; 6141 else if(mode & S_IEXEC) 6142 outs() << "x"; 6143 else 6144 outs() << "-"; 6145 6146 /* group permissions */ 6147 if(mode & (S_IREAD >> 3)) 6148 outs() << "r"; 6149 else 6150 outs() << "-"; 6151 if(mode & (S_IWRITE >> 3)) 6152 outs() << "w"; 6153 else 6154 outs() << "-"; 6155 if(mode & S_ISGID) 6156 outs() << "s"; 6157 else if(mode & (S_IEXEC >> 3)) 6158 outs() << "x"; 6159 else 6160 outs() << "-"; 6161 6162 /* other permissions */ 6163 if(mode & (S_IREAD >> 6)) 6164 outs() << "r"; 6165 else 6166 outs() << "-"; 6167 if(mode & (S_IWRITE >> 6)) 6168 outs() << "w"; 6169 else 6170 outs() << "-"; 6171 if(mode & S_ISVTX) 6172 outs() << "t"; 6173 else if(mode & (S_IEXEC >> 6)) 6174 outs() << "x"; 6175 else 6176 outs() << "-"; 6177 } 6178 6179 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { 6180 xar_file_t xf; 6181 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; 6182 char *endp; 6183 uint32_t mode_value; 6184 6185 ScopedXarIter xi; 6186 if (!xi) { 6187 errs() << "Can't obtain an xar iterator for xar archive " 6188 << XarFilename << "\n"; 6189 return; 6190 } 6191 6192 // Go through the xar's files. 6193 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { 6194 ScopedXarIter xp; 6195 if(!xp){ 6196 errs() << "Can't obtain an xar iterator for xar archive " 6197 << XarFilename << "\n"; 6198 return; 6199 } 6200 type = nullptr; 6201 mode = nullptr; 6202 user = nullptr; 6203 group = nullptr; 6204 size = nullptr; 6205 mtime = nullptr; 6206 name = nullptr; 6207 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6208 const char *val = nullptr; 6209 xar_prop_get(xf, key, &val); 6210 #if 0 // Useful for debugging. 6211 outs() << "key: " << key << " value: " << val << "\n"; 6212 #endif 6213 if(strcmp(key, "type") == 0) 6214 type = val; 6215 if(strcmp(key, "mode") == 0) 6216 mode = val; 6217 if(strcmp(key, "user") == 0) 6218 user = val; 6219 if(strcmp(key, "group") == 0) 6220 group = val; 6221 if(strcmp(key, "data/size") == 0) 6222 size = val; 6223 if(strcmp(key, "mtime") == 0) 6224 mtime = val; 6225 if(strcmp(key, "name") == 0) 6226 name = val; 6227 } 6228 if(mode != nullptr){ 6229 mode_value = strtoul(mode, &endp, 8); 6230 if(*endp != '\0') 6231 outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; 6232 if(strcmp(type, "file") == 0) 6233 mode_value |= S_IFREG; 6234 PrintModeVerbose(mode_value); 6235 outs() << " "; 6236 } 6237 if(user != nullptr) 6238 outs() << format("%10s/", user); 6239 if(group != nullptr) 6240 outs() << format("%-10s ", group); 6241 if(size != nullptr) 6242 outs() << format("%7s ", size); 6243 if(mtime != nullptr){ 6244 for(m = mtime; *m != 'T' && *m != '\0'; m++) 6245 outs() << *m; 6246 if(*m == 'T') 6247 m++; 6248 outs() << " "; 6249 for( ; *m != 'Z' && *m != '\0'; m++) 6250 outs() << *m; 6251 outs() << " "; 6252 } 6253 if(name != nullptr) 6254 outs() << name; 6255 outs() << "\n"; 6256 } 6257 } 6258 6259 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 6260 uint32_t size, bool verbose, 6261 bool PrintXarHeader, bool PrintXarFileHeaders, 6262 std::string XarMemberName) { 6263 if(size < sizeof(struct xar_header)) { 6264 outs() << "size of (__LLVM,__bundle) section too small (smaller than size " 6265 "of struct xar_header)\n"; 6266 return; 6267 } 6268 struct xar_header XarHeader; 6269 memcpy(&XarHeader, sect, sizeof(struct xar_header)); 6270 if (sys::IsLittleEndianHost) 6271 swapStruct(XarHeader); 6272 if (PrintXarHeader) { 6273 if (!XarMemberName.empty()) 6274 outs() << "In xar member " << XarMemberName << ": "; 6275 else 6276 outs() << "For (__LLVM,__bundle) section: "; 6277 outs() << "xar header\n"; 6278 if (XarHeader.magic == XAR_HEADER_MAGIC) 6279 outs() << " magic XAR_HEADER_MAGIC\n"; 6280 else 6281 outs() << " magic " 6282 << format_hex(XarHeader.magic, 10, true) 6283 << " (not XAR_HEADER_MAGIC)\n"; 6284 outs() << " size " << XarHeader.size << "\n"; 6285 outs() << " version " << XarHeader.version << "\n"; 6286 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed 6287 << "\n"; 6288 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed 6289 << "\n"; 6290 outs() << " cksum_alg "; 6291 switch (XarHeader.cksum_alg) { 6292 case XAR_CKSUM_NONE: 6293 outs() << "XAR_CKSUM_NONE\n"; 6294 break; 6295 case XAR_CKSUM_SHA1: 6296 outs() << "XAR_CKSUM_SHA1\n"; 6297 break; 6298 case XAR_CKSUM_MD5: 6299 outs() << "XAR_CKSUM_MD5\n"; 6300 break; 6301 #ifdef XAR_CKSUM_SHA256 6302 case XAR_CKSUM_SHA256: 6303 outs() << "XAR_CKSUM_SHA256\n"; 6304 break; 6305 #endif 6306 #ifdef XAR_CKSUM_SHA512 6307 case XAR_CKSUM_SHA512: 6308 outs() << "XAR_CKSUM_SHA512\n"; 6309 break; 6310 #endif 6311 default: 6312 outs() << XarHeader.cksum_alg << "\n"; 6313 } 6314 } 6315 6316 SmallString<128> XarFilename; 6317 int FD; 6318 std::error_code XarEC = 6319 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); 6320 if (XarEC) { 6321 errs() << XarEC.message() << "\n"; 6322 return; 6323 } 6324 ToolOutputFile XarFile(XarFilename, FD); 6325 raw_fd_ostream &XarOut = XarFile.os(); 6326 StringRef XarContents(sect, size); 6327 XarOut << XarContents; 6328 XarOut.close(); 6329 if (XarOut.has_error()) 6330 return; 6331 6332 ScopedXarFile xar(XarFilename.c_str(), READ); 6333 if (!xar) { 6334 errs() << "Can't create temporary xar archive " << XarFilename << "\n"; 6335 return; 6336 } 6337 6338 SmallString<128> TocFilename; 6339 std::error_code TocEC = 6340 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); 6341 if (TocEC) { 6342 errs() << TocEC.message() << "\n"; 6343 return; 6344 } 6345 xar_serialize(xar, TocFilename.c_str()); 6346 6347 if (PrintXarFileHeaders) { 6348 if (!XarMemberName.empty()) 6349 outs() << "In xar member " << XarMemberName << ": "; 6350 else 6351 outs() << "For (__LLVM,__bundle) section: "; 6352 outs() << "xar archive files:\n"; 6353 PrintXarFilesSummary(XarFilename.c_str(), xar); 6354 } 6355 6356 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 6357 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); 6358 if (std::error_code EC = FileOrErr.getError()) { 6359 errs() << EC.message() << "\n"; 6360 return; 6361 } 6362 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 6363 6364 if (!XarMemberName.empty()) 6365 outs() << "In xar member " << XarMemberName << ": "; 6366 else 6367 outs() << "For (__LLVM,__bundle) section: "; 6368 outs() << "xar table of contents:\n"; 6369 outs() << Buffer->getBuffer() << "\n"; 6370 6371 // TODO: Go through the xar's files. 6372 ScopedXarIter xi; 6373 if(!xi){ 6374 errs() << "Can't obtain an xar iterator for xar archive " 6375 << XarFilename.c_str() << "\n"; 6376 return; 6377 } 6378 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ 6379 const char *key; 6380 const char *member_name, *member_type, *member_size_string; 6381 size_t member_size; 6382 6383 ScopedXarIter xp; 6384 if(!xp){ 6385 errs() << "Can't obtain an xar iterator for xar archive " 6386 << XarFilename.c_str() << "\n"; 6387 return; 6388 } 6389 member_name = NULL; 6390 member_type = NULL; 6391 member_size_string = NULL; 6392 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6393 const char *val = nullptr; 6394 xar_prop_get(xf, key, &val); 6395 #if 0 // Useful for debugging. 6396 outs() << "key: " << key << " value: " << val << "\n"; 6397 #endif 6398 if (strcmp(key, "name") == 0) 6399 member_name = val; 6400 if (strcmp(key, "type") == 0) 6401 member_type = val; 6402 if (strcmp(key, "data/size") == 0) 6403 member_size_string = val; 6404 } 6405 /* 6406 * If we find a file with a name, date/size and type properties 6407 * and with the type being "file" see if that is a xar file. 6408 */ 6409 if (member_name != NULL && member_type != NULL && 6410 strcmp(member_type, "file") == 0 && 6411 member_size_string != NULL){ 6412 // Extract the file into a buffer. 6413 char *endptr; 6414 member_size = strtoul(member_size_string, &endptr, 10); 6415 if (*endptr == '\0' && member_size != 0) { 6416 char *buffer; 6417 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { 6418 #if 0 // Useful for debugging. 6419 outs() << "xar member: " << member_name << " extracted\n"; 6420 #endif 6421 // Set the XarMemberName we want to see printed in the header. 6422 std::string OldXarMemberName; 6423 // If XarMemberName is already set this is nested. So 6424 // save the old name and create the nested name. 6425 if (!XarMemberName.empty()) { 6426 OldXarMemberName = XarMemberName; 6427 XarMemberName = 6428 (Twine("[") + XarMemberName + "]" + member_name).str(); 6429 } else { 6430 OldXarMemberName = ""; 6431 XarMemberName = member_name; 6432 } 6433 // See if this is could be a xar file (nested). 6434 if (member_size >= sizeof(struct xar_header)) { 6435 #if 0 // Useful for debugging. 6436 outs() << "could be a xar file: " << member_name << "\n"; 6437 #endif 6438 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); 6439 if (sys::IsLittleEndianHost) 6440 swapStruct(XarHeader); 6441 if (XarHeader.magic == XAR_HEADER_MAGIC) 6442 DumpBitcodeSection(O, buffer, member_size, verbose, 6443 PrintXarHeader, PrintXarFileHeaders, 6444 XarMemberName); 6445 } 6446 XarMemberName = OldXarMemberName; 6447 delete buffer; 6448 } 6449 } 6450 } 6451 } 6452 } 6453 #endif // defined(HAVE_LIBXAR) 6454 6455 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6456 if (O->is64Bit()) 6457 printObjc2_64bit_MetaData(O, verbose); 6458 else { 6459 MachO::mach_header H; 6460 H = O->getHeader(); 6461 if (H.cputype == MachO::CPU_TYPE_ARM) 6462 printObjc2_32bit_MetaData(O, verbose); 6463 else { 6464 // This is the 32-bit non-arm cputype case. Which is normally 6465 // the first Objective-C ABI. But it may be the case of a 6466 // binary for the iOS simulator which is the second Objective-C 6467 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6468 // and return false. 6469 if (!printObjc1_32bit_MetaData(O, verbose)) 6470 printObjc2_32bit_MetaData(O, verbose); 6471 } 6472 } 6473 } 6474 6475 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6476 // for the address passed in as ReferenceValue for printing as a comment with 6477 // the instruction and also returns the corresponding type of that item 6478 // indirectly through ReferenceType. 6479 // 6480 // If ReferenceValue is an address of literal cstring then a pointer to the 6481 // cstring is returned and ReferenceType is set to 6482 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6483 // 6484 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6485 // Class ref that name is returned and the ReferenceType is set accordingly. 6486 // 6487 // Lastly, literals which are Symbol address in a literal pool are looked for 6488 // and if found the symbol name is returned and ReferenceType is set to 6489 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6490 // 6491 // If there is no item in the Mach-O file for the address passed in as 6492 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6493 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6494 uint64_t ReferencePC, 6495 uint64_t *ReferenceType, 6496 struct DisassembleInfo *info) { 6497 // First see if there is an external relocation entry at the ReferencePC. 6498 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6499 uint64_t sect_addr = info->S.getAddress(); 6500 uint64_t sect_offset = ReferencePC - sect_addr; 6501 bool reloc_found = false; 6502 DataRefImpl Rel; 6503 MachO::any_relocation_info RE; 6504 bool isExtern = false; 6505 SymbolRef Symbol; 6506 for (const RelocationRef &Reloc : info->S.relocations()) { 6507 uint64_t RelocOffset = Reloc.getOffset(); 6508 if (RelocOffset == sect_offset) { 6509 Rel = Reloc.getRawDataRefImpl(); 6510 RE = info->O->getRelocation(Rel); 6511 if (info->O->isRelocationScattered(RE)) 6512 continue; 6513 isExtern = info->O->getPlainRelocationExternal(RE); 6514 if (isExtern) { 6515 symbol_iterator RelocSym = Reloc.getSymbol(); 6516 Symbol = *RelocSym; 6517 } 6518 reloc_found = true; 6519 break; 6520 } 6521 } 6522 // If there is an external relocation entry for a symbol in a section 6523 // then used that symbol's value for the value of the reference. 6524 if (reloc_found && isExtern) { 6525 if (info->O->getAnyRelocationPCRel(RE)) { 6526 unsigned Type = info->O->getAnyRelocationType(RE); 6527 if (Type == MachO::X86_64_RELOC_SIGNED) { 6528 ReferenceValue = Symbol.getValue(); 6529 } 6530 } 6531 } 6532 } 6533 6534 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6535 // Message refs and Class refs. 6536 bool classref, selref, msgref, cfstring; 6537 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6538 selref, msgref, cfstring); 6539 if (classref && pointer_value == 0) { 6540 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6541 // And the pointer_value in that section is typically zero as it will be 6542 // set by dyld as part of the "bind information". 6543 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6544 if (name != nullptr) { 6545 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6546 const char *class_name = strrchr(name, '$'); 6547 if (class_name != nullptr && class_name[1] == '_' && 6548 class_name[2] != '\0') { 6549 info->class_name = class_name + 2; 6550 return name; 6551 } 6552 } 6553 } 6554 6555 if (classref) { 6556 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6557 const char *name = 6558 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6559 if (name != nullptr) 6560 info->class_name = name; 6561 else 6562 name = "bad class ref"; 6563 return name; 6564 } 6565 6566 if (cfstring) { 6567 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6568 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6569 return name; 6570 } 6571 6572 if (selref && pointer_value == 0) 6573 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6574 6575 if (pointer_value != 0) 6576 ReferenceValue = pointer_value; 6577 6578 const char *name = GuessCstringPointer(ReferenceValue, info); 6579 if (name) { 6580 if (pointer_value != 0 && selref) { 6581 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6582 info->selector_name = name; 6583 } else if (pointer_value != 0 && msgref) { 6584 info->class_name = nullptr; 6585 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6586 info->selector_name = name; 6587 } else 6588 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6589 return name; 6590 } 6591 6592 // Lastly look for an indirect symbol with this ReferenceValue which is in 6593 // a literal pool. If found return that symbol name. 6594 name = GuessIndirectSymbol(ReferenceValue, info); 6595 if (name) { 6596 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6597 return name; 6598 } 6599 6600 return nullptr; 6601 } 6602 6603 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6604 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6605 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6606 // is created and returns the symbol name that matches the ReferenceValue or 6607 // nullptr if none. The ReferenceType is passed in for the IN type of 6608 // reference the instruction is making from the values in defined in the header 6609 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6610 // Out type and the ReferenceName will also be set which is added as a comment 6611 // to the disassembled instruction. 6612 // 6613 // If the symbol name is a C++ mangled name then the demangled name is 6614 // returned through ReferenceName and ReferenceType is set to 6615 // LLVMDisassembler_ReferenceType_DeMangled_Name . 6616 // 6617 // When this is called to get a symbol name for a branch target then the 6618 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 6619 // SymbolValue will be looked for in the indirect symbol table to determine if 6620 // it is an address for a symbol stub. If so then the symbol name for that 6621 // stub is returned indirectly through ReferenceName and then ReferenceType is 6622 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 6623 // 6624 // When this is called with an value loaded via a PC relative load then 6625 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 6626 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 6627 // or an Objective-C meta data reference. If so the output ReferenceType is 6628 // set to correspond to that as well as setting the ReferenceName. 6629 static const char *SymbolizerSymbolLookUp(void *DisInfo, 6630 uint64_t ReferenceValue, 6631 uint64_t *ReferenceType, 6632 uint64_t ReferencePC, 6633 const char **ReferenceName) { 6634 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 6635 // If no verbose symbolic information is wanted then just return nullptr. 6636 if (!info->verbose) { 6637 *ReferenceName = nullptr; 6638 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6639 return nullptr; 6640 } 6641 6642 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 6643 6644 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 6645 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 6646 if (*ReferenceName != nullptr) { 6647 method_reference(info, ReferenceType, ReferenceName); 6648 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 6649 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 6650 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6651 if (info->demangled_name != nullptr) 6652 free(info->demangled_name); 6653 int status; 6654 info->demangled_name = 6655 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6656 if (info->demangled_name != nullptr) { 6657 *ReferenceName = info->demangled_name; 6658 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6659 } else 6660 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6661 } else 6662 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6663 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 6664 *ReferenceName = 6665 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6666 if (*ReferenceName) 6667 method_reference(info, ReferenceType, ReferenceName); 6668 else 6669 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6670 // If this is arm64 and the reference is an adrp instruction save the 6671 // instruction, passed in ReferenceValue and the address of the instruction 6672 // for use later if we see and add immediate instruction. 6673 } else if (info->O->getArch() == Triple::aarch64 && 6674 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 6675 info->adrp_inst = ReferenceValue; 6676 info->adrp_addr = ReferencePC; 6677 SymbolName = nullptr; 6678 *ReferenceName = nullptr; 6679 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6680 // If this is arm64 and reference is an add immediate instruction and we 6681 // have 6682 // seen an adrp instruction just before it and the adrp's Xd register 6683 // matches 6684 // this add's Xn register reconstruct the value being referenced and look to 6685 // see if it is a literal pointer. Note the add immediate instruction is 6686 // passed in ReferenceValue. 6687 } else if (info->O->getArch() == Triple::aarch64 && 6688 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 6689 ReferencePC - 4 == info->adrp_addr && 6690 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6691 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6692 uint32_t addxri_inst; 6693 uint64_t adrp_imm, addxri_imm; 6694 6695 adrp_imm = 6696 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6697 if (info->adrp_inst & 0x0200000) 6698 adrp_imm |= 0xfffffffffc000000LL; 6699 6700 addxri_inst = ReferenceValue; 6701 addxri_imm = (addxri_inst >> 10) & 0xfff; 6702 if (((addxri_inst >> 22) & 0x3) == 1) 6703 addxri_imm <<= 12; 6704 6705 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6706 (adrp_imm << 12) + addxri_imm; 6707 6708 *ReferenceName = 6709 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6710 if (*ReferenceName == nullptr) 6711 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6712 // If this is arm64 and the reference is a load register instruction and we 6713 // have seen an adrp instruction just before it and the adrp's Xd register 6714 // matches this add's Xn register reconstruct the value being referenced and 6715 // look to see if it is a literal pointer. Note the load register 6716 // instruction is passed in ReferenceValue. 6717 } else if (info->O->getArch() == Triple::aarch64 && 6718 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 6719 ReferencePC - 4 == info->adrp_addr && 6720 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6721 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6722 uint32_t ldrxui_inst; 6723 uint64_t adrp_imm, ldrxui_imm; 6724 6725 adrp_imm = 6726 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6727 if (info->adrp_inst & 0x0200000) 6728 adrp_imm |= 0xfffffffffc000000LL; 6729 6730 ldrxui_inst = ReferenceValue; 6731 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 6732 6733 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6734 (adrp_imm << 12) + (ldrxui_imm << 3); 6735 6736 *ReferenceName = 6737 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6738 if (*ReferenceName == nullptr) 6739 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6740 } 6741 // If this arm64 and is an load register (PC-relative) instruction the 6742 // ReferenceValue is the PC plus the immediate value. 6743 else if (info->O->getArch() == Triple::aarch64 && 6744 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 6745 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 6746 *ReferenceName = 6747 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6748 if (*ReferenceName == nullptr) 6749 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6750 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6751 if (info->demangled_name != nullptr) 6752 free(info->demangled_name); 6753 int status; 6754 info->demangled_name = 6755 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6756 if (info->demangled_name != nullptr) { 6757 *ReferenceName = info->demangled_name; 6758 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6759 } 6760 } 6761 else { 6762 *ReferenceName = nullptr; 6763 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6764 } 6765 6766 return SymbolName; 6767 } 6768 6769 /// Emits the comments that are stored in the CommentStream. 6770 /// Each comment in the CommentStream must end with a newline. 6771 static void emitComments(raw_svector_ostream &CommentStream, 6772 SmallString<128> &CommentsToEmit, 6773 formatted_raw_ostream &FormattedOS, 6774 const MCAsmInfo &MAI) { 6775 // Flush the stream before taking its content. 6776 StringRef Comments = CommentsToEmit.str(); 6777 // Get the default information for printing a comment. 6778 StringRef CommentBegin = MAI.getCommentString(); 6779 unsigned CommentColumn = MAI.getCommentColumn(); 6780 bool IsFirst = true; 6781 while (!Comments.empty()) { 6782 if (!IsFirst) 6783 FormattedOS << '\n'; 6784 // Emit a line of comments. 6785 FormattedOS.PadToColumn(CommentColumn); 6786 size_t Position = Comments.find('\n'); 6787 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 6788 // Move after the newline character. 6789 Comments = Comments.substr(Position + 1); 6790 IsFirst = false; 6791 } 6792 FormattedOS.flush(); 6793 6794 // Tell the comment stream that the vector changed underneath it. 6795 CommentsToEmit.clear(); 6796 } 6797 6798 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 6799 StringRef DisSegName, StringRef DisSectName) { 6800 const char *McpuDefault = nullptr; 6801 const Target *ThumbTarget = nullptr; 6802 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 6803 if (!TheTarget) { 6804 // GetTarget prints out stuff. 6805 return; 6806 } 6807 std::string MachOMCPU; 6808 if (MCPU.empty() && McpuDefault) 6809 MachOMCPU = McpuDefault; 6810 else 6811 MachOMCPU = MCPU; 6812 6813 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 6814 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 6815 if (ThumbTarget) 6816 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 6817 6818 // Package up features to be passed to target/subtarget 6819 std::string FeaturesStr; 6820 if (MAttrs.size()) { 6821 SubtargetFeatures Features; 6822 for (unsigned i = 0; i != MAttrs.size(); ++i) 6823 Features.AddFeature(MAttrs[i]); 6824 FeaturesStr = Features.getString(); 6825 } 6826 6827 // Set up disassembler. 6828 std::unique_ptr<const MCRegisterInfo> MRI( 6829 TheTarget->createMCRegInfo(TripleName)); 6830 std::unique_ptr<const MCAsmInfo> AsmInfo( 6831 TheTarget->createMCAsmInfo(*MRI, TripleName)); 6832 std::unique_ptr<const MCSubtargetInfo> STI( 6833 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 6834 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 6835 std::unique_ptr<MCDisassembler> DisAsm( 6836 TheTarget->createMCDisassembler(*STI, Ctx)); 6837 std::unique_ptr<MCSymbolizer> Symbolizer; 6838 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false); 6839 std::unique_ptr<MCRelocationInfo> RelInfo( 6840 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 6841 if (RelInfo) { 6842 Symbolizer.reset(TheTarget->createMCSymbolizer( 6843 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6844 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 6845 DisAsm->setSymbolizer(std::move(Symbolizer)); 6846 } 6847 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 6848 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 6849 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 6850 // Set the display preference for hex vs. decimal immediates. 6851 IP->setPrintImmHex(PrintImmHex); 6852 // Comment stream and backing vector. 6853 SmallString<128> CommentsToEmit; 6854 raw_svector_ostream CommentStream(CommentsToEmit); 6855 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 6856 // if it is done then arm64 comments for string literals don't get printed 6857 // and some constant get printed instead and not setting it causes intel 6858 // (32-bit and 64-bit) comments printed with different spacing before the 6859 // comment causing different diffs with the 'C' disassembler library API. 6860 // IP->setCommentStream(CommentStream); 6861 6862 if (!AsmInfo || !STI || !DisAsm || !IP) { 6863 errs() << "error: couldn't initialize disassembler for target " 6864 << TripleName << '\n'; 6865 return; 6866 } 6867 6868 // Set up separate thumb disassembler if needed. 6869 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 6870 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 6871 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 6872 std::unique_ptr<MCDisassembler> ThumbDisAsm; 6873 std::unique_ptr<MCInstPrinter> ThumbIP; 6874 std::unique_ptr<MCContext> ThumbCtx; 6875 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 6876 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false); 6877 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 6878 if (ThumbTarget) { 6879 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 6880 ThumbAsmInfo.reset( 6881 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName)); 6882 ThumbSTI.reset( 6883 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 6884 FeaturesStr)); 6885 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 6886 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 6887 MCContext *PtrThumbCtx = ThumbCtx.get(); 6888 ThumbRelInfo.reset( 6889 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 6890 if (ThumbRelInfo) { 6891 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 6892 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6893 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 6894 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 6895 } 6896 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 6897 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 6898 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 6899 *ThumbInstrInfo, *ThumbMRI)); 6900 // Set the display preference for hex vs. decimal immediates. 6901 ThumbIP->setPrintImmHex(PrintImmHex); 6902 } 6903 6904 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) { 6905 errs() << "error: couldn't initialize disassembler for target " 6906 << ThumbTripleName << '\n'; 6907 return; 6908 } 6909 6910 MachO::mach_header Header = MachOOF->getHeader(); 6911 6912 // FIXME: Using the -cfg command line option, this code used to be able to 6913 // annotate relocations with the referenced symbol's name, and if this was 6914 // inside a __[cf]string section, the data it points to. This is now replaced 6915 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 6916 std::vector<SectionRef> Sections; 6917 std::vector<SymbolRef> Symbols; 6918 SmallVector<uint64_t, 8> FoundFns; 6919 uint64_t BaseSegmentAddress; 6920 6921 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 6922 BaseSegmentAddress); 6923 6924 // Sort the symbols by address, just in case they didn't come in that way. 6925 llvm::sort(Symbols, SymbolSorter()); 6926 6927 // Build a data in code table that is sorted on by the address of each entry. 6928 uint64_t BaseAddress = 0; 6929 if (Header.filetype == MachO::MH_OBJECT) 6930 BaseAddress = Sections[0].getAddress(); 6931 else 6932 BaseAddress = BaseSegmentAddress; 6933 DiceTable Dices; 6934 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 6935 DI != DE; ++DI) { 6936 uint32_t Offset; 6937 DI->getOffset(Offset); 6938 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 6939 } 6940 array_pod_sort(Dices.begin(), Dices.end()); 6941 6942 #ifndef NDEBUG 6943 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); 6944 #else 6945 raw_ostream &DebugOut = nulls(); 6946 #endif 6947 6948 std::unique_ptr<DIContext> diContext; 6949 ObjectFile *DbgObj = MachOOF; 6950 std::unique_ptr<MemoryBuffer> DSYMBuf; 6951 // Try to find debug info and set up the DIContext for it. 6952 if (UseDbg) { 6953 // A separate DSym file path was specified, parse it as a macho file, 6954 // get the sections and supply it to the section name parsing machinery. 6955 if (!DSYMFile.empty()) { 6956 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 6957 MemoryBuffer::getFileOrSTDIN(DSYMFile); 6958 if (std::error_code EC = BufOrErr.getError()) { 6959 errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n'; 6960 return; 6961 } 6962 Expected<std::unique_ptr<MachOObjectFile>> DbgObjCheck = 6963 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()); 6964 6965 if (DbgObjCheck.takeError()) 6966 report_error(MachOOF->getFileName(), DbgObjCheck.takeError()); 6967 DbgObj = DbgObjCheck.get().release(); 6968 // We need to keep the file alive, because we're replacing DbgObj with it. 6969 DSYMBuf = std::move(BufOrErr.get()); 6970 } 6971 6972 // Setup the DIContext 6973 diContext = DWARFContext::create(*DbgObj); 6974 } 6975 6976 if (FilterSections.size() == 0) 6977 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 6978 6979 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 6980 StringRef SectName; 6981 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName) 6982 continue; 6983 6984 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 6985 6986 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 6987 if (SegmentName != DisSegName) 6988 continue; 6989 6990 StringRef BytesStr; 6991 Sections[SectIdx].getContents(BytesStr); 6992 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()), 6993 BytesStr.size()); 6994 uint64_t SectAddress = Sections[SectIdx].getAddress(); 6995 6996 bool symbolTableWorked = false; 6997 6998 // Create a map of symbol addresses to symbol names for use by 6999 // the SymbolizerSymbolLookUp() routine. 7000 SymbolAddressMap AddrMap; 7001 bool DisSymNameFound = false; 7002 for (const SymbolRef &Symbol : MachOOF->symbols()) { 7003 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 7004 if (!STOrErr) 7005 report_error(MachOOF->getFileName(), STOrErr.takeError()); 7006 SymbolRef::Type ST = *STOrErr; 7007 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 7008 ST == SymbolRef::ST_Other) { 7009 uint64_t Address = Symbol.getValue(); 7010 Expected<StringRef> SymNameOrErr = Symbol.getName(); 7011 if (!SymNameOrErr) 7012 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 7013 StringRef SymName = *SymNameOrErr; 7014 AddrMap[Address] = SymName; 7015 if (!DisSymName.empty() && DisSymName == SymName) 7016 DisSymNameFound = true; 7017 } 7018 } 7019 if (!DisSymName.empty() && !DisSymNameFound) { 7020 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 7021 return; 7022 } 7023 // Set up the block of info used by the Symbolizer call backs. 7024 SymbolizerInfo.verbose = !NoSymbolicOperands; 7025 SymbolizerInfo.O = MachOOF; 7026 SymbolizerInfo.S = Sections[SectIdx]; 7027 SymbolizerInfo.AddrMap = &AddrMap; 7028 SymbolizerInfo.Sections = &Sections; 7029 // Same for the ThumbSymbolizer 7030 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands; 7031 ThumbSymbolizerInfo.O = MachOOF; 7032 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7033 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7034 ThumbSymbolizerInfo.Sections = &Sections; 7035 7036 unsigned int Arch = MachOOF->getArch(); 7037 7038 // Skip all symbols if this is a stubs file. 7039 if (Bytes.size() == 0) 7040 return; 7041 7042 // If the section has symbols but no symbol at the start of the section 7043 // these are used to make sure the bytes before the first symbol are 7044 // disassembled. 7045 bool FirstSymbol = true; 7046 bool FirstSymbolAtSectionStart = true; 7047 7048 // Disassemble symbol by symbol. 7049 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7050 Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName(); 7051 if (!SymNameOrErr) 7052 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 7053 StringRef SymName = *SymNameOrErr; 7054 7055 Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType(); 7056 if (!STOrErr) 7057 report_error(MachOOF->getFileName(), STOrErr.takeError()); 7058 SymbolRef::Type ST = *STOrErr; 7059 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7060 continue; 7061 7062 // Make sure the symbol is defined in this section. 7063 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7064 if (!containsSym) { 7065 if (!DisSymName.empty() && DisSymName == SymName) { 7066 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7067 return; 7068 } 7069 continue; 7070 } 7071 // The __mh_execute_header is special and we need to deal with that fact 7072 // this symbol is before the start of the (__TEXT,__text) section and at the 7073 // address of the start of the __TEXT segment. This is because this symbol 7074 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7075 // start of the section in a standard MH_EXECUTE filetype. 7076 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7077 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7078 return; 7079 } 7080 // When this code is trying to disassemble a symbol at a time and in the 7081 // case there is only the __mh_execute_header symbol left as in a stripped 7082 // executable, we need to deal with this by ignoring this symbol so the 7083 // whole section is disassembled and this symbol is then not displayed. 7084 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7085 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7086 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7087 continue; 7088 7089 // If we are only disassembling one symbol see if this is that symbol. 7090 if (!DisSymName.empty() && DisSymName != SymName) 7091 continue; 7092 7093 // Start at the address of the symbol relative to the section's address. 7094 uint64_t SectSize = Sections[SectIdx].getSize(); 7095 uint64_t Start = Symbols[SymIdx].getValue(); 7096 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7097 Start -= SectionAddress; 7098 7099 if (Start > SectSize) { 7100 outs() << "section data ends, " << SymName 7101 << " lies outside valid range\n"; 7102 return; 7103 } 7104 7105 // Stop disassembling either at the beginning of the next symbol or at 7106 // the end of the section. 7107 bool containsNextSym = false; 7108 uint64_t NextSym = 0; 7109 uint64_t NextSymIdx = SymIdx + 1; 7110 while (Symbols.size() > NextSymIdx) { 7111 Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType(); 7112 if (!STOrErr) 7113 report_error(MachOOF->getFileName(), STOrErr.takeError()); 7114 SymbolRef::Type NextSymType = *STOrErr; 7115 if (NextSymType == SymbolRef::ST_Function) { 7116 containsNextSym = 7117 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7118 NextSym = Symbols[NextSymIdx].getValue(); 7119 NextSym -= SectionAddress; 7120 break; 7121 } 7122 ++NextSymIdx; 7123 } 7124 7125 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7126 uint64_t Size; 7127 7128 symbolTableWorked = true; 7129 7130 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7131 bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb; 7132 7133 // We only need the dedicated Thumb target if there's a real choice 7134 // (i.e. we're not targeting M-class) and the function is Thumb. 7135 bool UseThumbTarget = IsThumb && ThumbTarget; 7136 7137 // If we are not specifying a symbol to start disassembly with and this 7138 // is the first symbol in the section but not at the start of the section 7139 // then move the disassembly index to the start of the section and 7140 // don't print the symbol name just yet. This is so the bytes before the 7141 // first symbol are disassembled. 7142 uint64_t SymbolStart = Start; 7143 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7144 FirstSymbolAtSectionStart = false; 7145 Start = 0; 7146 } 7147 else 7148 outs() << SymName << ":\n"; 7149 7150 DILineInfo lastLine; 7151 for (uint64_t Index = Start; Index < End; Index += Size) { 7152 MCInst Inst; 7153 7154 // If this is the first symbol in the section and it was not at the 7155 // start of the section, see if we are at its Index now and if so print 7156 // the symbol name. 7157 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7158 outs() << SymName << ":\n"; 7159 7160 uint64_t PC = SectAddress + Index; 7161 if (!NoLeadingAddr) { 7162 if (FullLeadingAddr) { 7163 if (MachOOF->is64Bit()) 7164 outs() << format("%016" PRIx64, PC); 7165 else 7166 outs() << format("%08" PRIx64, PC); 7167 } else { 7168 outs() << format("%8" PRIx64 ":", PC); 7169 } 7170 } 7171 if (!NoShowRawInsn || Arch == Triple::arm) 7172 outs() << "\t"; 7173 7174 // Check the data in code table here to see if this is data not an 7175 // instruction to be disassembled. 7176 DiceTable Dice; 7177 Dice.push_back(std::make_pair(PC, DiceRef())); 7178 dice_table_iterator DTI = 7179 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 7180 compareDiceTableEntries); 7181 if (DTI != Dices.end()) { 7182 uint16_t Length; 7183 DTI->second.getLength(Length); 7184 uint16_t Kind; 7185 DTI->second.getKind(Kind); 7186 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind); 7187 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 7188 (PC == (DTI->first + Length - 1)) && (Length & 1)) 7189 Size++; 7190 continue; 7191 } 7192 7193 SmallVector<char, 64> AnnotationsBytes; 7194 raw_svector_ostream Annotations(AnnotationsBytes); 7195 7196 bool gotInst; 7197 if (UseThumbTarget) 7198 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7199 PC, DebugOut, Annotations); 7200 else 7201 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7202 DebugOut, Annotations); 7203 if (gotInst) { 7204 if (!NoShowRawInsn || Arch == Triple::arm) { 7205 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); 7206 } 7207 formatted_raw_ostream FormattedOS(outs()); 7208 StringRef AnnotationsStr = Annotations.str(); 7209 if (UseThumbTarget) 7210 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI); 7211 else 7212 IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI); 7213 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7214 7215 // Print debug info. 7216 if (diContext) { 7217 DILineInfo dli = diContext->getLineInfoForAddress(PC); 7218 // Print valid line info if it changed. 7219 if (dli != lastLine && dli.Line != 0) 7220 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7221 << dli.Column; 7222 lastLine = dli; 7223 } 7224 outs() << "\n"; 7225 } else { 7226 unsigned int Arch = MachOOF->getArch(); 7227 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7228 outs() << format("\t.byte 0x%02x #bad opcode\n", 7229 *(Bytes.data() + Index) & 0xff); 7230 Size = 1; // skip exactly one illegible byte and move on. 7231 } else if (Arch == Triple::aarch64 || 7232 (Arch == Triple::arm && !IsThumb)) { 7233 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7234 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7235 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7236 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7237 outs() << format("\t.long\t0x%08x\n", opcode); 7238 Size = 4; 7239 } else if (Arch == Triple::arm) { 7240 assert(IsThumb && "ARM mode should have been dealt with above"); 7241 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7242 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7243 outs() << format("\t.short\t0x%04x\n", opcode); 7244 Size = 2; 7245 } else{ 7246 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 7247 if (Size == 0) 7248 Size = 1; // skip illegible bytes 7249 } 7250 } 7251 } 7252 // Now that we are done disassembled the first symbol set the bool that 7253 // were doing this to false. 7254 FirstSymbol = false; 7255 } 7256 if (!symbolTableWorked) { 7257 // Reading the symbol table didn't work, disassemble the whole section. 7258 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7259 uint64_t SectSize = Sections[SectIdx].getSize(); 7260 uint64_t InstSize; 7261 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7262 MCInst Inst; 7263 7264 uint64_t PC = SectAddress + Index; 7265 SmallVector<char, 64> AnnotationsBytes; 7266 raw_svector_ostream Annotations(AnnotationsBytes); 7267 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7268 DebugOut, Annotations)) { 7269 if (!NoLeadingAddr) { 7270 if (FullLeadingAddr) { 7271 if (MachOOF->is64Bit()) 7272 outs() << format("%016" PRIx64, PC); 7273 else 7274 outs() << format("%08" PRIx64, PC); 7275 } else { 7276 outs() << format("%8" PRIx64 ":", PC); 7277 } 7278 } 7279 if (!NoShowRawInsn || Arch == Triple::arm) { 7280 outs() << "\t"; 7281 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); 7282 } 7283 StringRef AnnotationsStr = Annotations.str(); 7284 IP->printInst(&Inst, outs(), AnnotationsStr, *STI); 7285 outs() << "\n"; 7286 } else { 7287 unsigned int Arch = MachOOF->getArch(); 7288 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7289 outs() << format("\t.byte 0x%02x #bad opcode\n", 7290 *(Bytes.data() + Index) & 0xff); 7291 InstSize = 1; // skip exactly one illegible byte and move on. 7292 } else { 7293 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 7294 if (InstSize == 0) 7295 InstSize = 1; // skip illegible bytes 7296 } 7297 } 7298 } 7299 } 7300 // The TripleName's need to be reset if we are called again for a different 7301 // archtecture. 7302 TripleName = ""; 7303 ThumbTripleName = ""; 7304 7305 if (SymbolizerInfo.demangled_name != nullptr) 7306 free(SymbolizerInfo.demangled_name); 7307 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7308 free(ThumbSymbolizerInfo.demangled_name); 7309 } 7310 } 7311 7312 //===----------------------------------------------------------------------===// 7313 // __compact_unwind section dumping 7314 //===----------------------------------------------------------------------===// 7315 7316 namespace { 7317 7318 template <typename T> 7319 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7320 using llvm::support::little; 7321 using llvm::support::unaligned; 7322 7323 if (Offset + sizeof(T) > Contents.size()) { 7324 outs() << "warning: attempt to read past end of buffer\n"; 7325 return T(); 7326 } 7327 7328 uint64_t Val = 7329 support::endian::read<T, little, unaligned>(Contents.data() + Offset); 7330 return Val; 7331 } 7332 7333 template <typename T> 7334 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7335 T Val = read<T>(Contents, Offset); 7336 Offset += sizeof(T); 7337 return Val; 7338 } 7339 7340 struct CompactUnwindEntry { 7341 uint32_t OffsetInSection; 7342 7343 uint64_t FunctionAddr; 7344 uint32_t Length; 7345 uint32_t CompactEncoding; 7346 uint64_t PersonalityAddr; 7347 uint64_t LSDAAddr; 7348 7349 RelocationRef FunctionReloc; 7350 RelocationRef PersonalityReloc; 7351 RelocationRef LSDAReloc; 7352 7353 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7354 : OffsetInSection(Offset) { 7355 if (Is64) 7356 read<uint64_t>(Contents, Offset); 7357 else 7358 read<uint32_t>(Contents, Offset); 7359 } 7360 7361 private: 7362 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7363 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7364 Length = readNext<uint32_t>(Contents, Offset); 7365 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7366 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7367 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7368 } 7369 }; 7370 } 7371 7372 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7373 /// and data being relocated, determine the best base Name and Addend to use for 7374 /// display purposes. 7375 /// 7376 /// 1. An Extern relocation will directly reference a symbol (and the data is 7377 /// then already an addend), so use that. 7378 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7379 // a symbol before it in the same section, and use the offset from there. 7380 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7381 /// referenced section. 7382 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7383 std::map<uint64_t, SymbolRef> &Symbols, 7384 const RelocationRef &Reloc, uint64_t Addr, 7385 StringRef &Name, uint64_t &Addend) { 7386 if (Reloc.getSymbol() != Obj->symbol_end()) { 7387 Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName(); 7388 if (!NameOrErr) 7389 report_error(Obj->getFileName(), NameOrErr.takeError()); 7390 Name = *NameOrErr; 7391 Addend = Addr; 7392 return; 7393 } 7394 7395 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7396 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7397 7398 uint64_t SectionAddr = RelocSection.getAddress(); 7399 7400 auto Sym = Symbols.upper_bound(Addr); 7401 if (Sym == Symbols.begin()) { 7402 // The first symbol in the object is after this reference, the best we can 7403 // do is section-relative notation. 7404 RelocSection.getName(Name); 7405 Addend = Addr - SectionAddr; 7406 return; 7407 } 7408 7409 // Go back one so that SymbolAddress <= Addr. 7410 --Sym; 7411 7412 auto SectOrErr = Sym->second.getSection(); 7413 if (!SectOrErr) 7414 report_error(Obj->getFileName(), SectOrErr.takeError()); 7415 section_iterator SymSection = *SectOrErr; 7416 if (RelocSection == *SymSection) { 7417 // There's a valid symbol in the same section before this reference. 7418 Expected<StringRef> NameOrErr = Sym->second.getName(); 7419 if (!NameOrErr) 7420 report_error(Obj->getFileName(), NameOrErr.takeError()); 7421 Name = *NameOrErr; 7422 Addend = Addr - Sym->first; 7423 return; 7424 } 7425 7426 // There is a symbol before this reference, but it's in a different 7427 // section. Probably not helpful to mention it, so use the section name. 7428 RelocSection.getName(Name); 7429 Addend = Addr - SectionAddr; 7430 } 7431 7432 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7433 std::map<uint64_t, SymbolRef> &Symbols, 7434 const RelocationRef &Reloc, uint64_t Addr) { 7435 StringRef Name; 7436 uint64_t Addend; 7437 7438 if (!Reloc.getObject()) 7439 return; 7440 7441 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7442 7443 outs() << Name; 7444 if (Addend) 7445 outs() << " + " << format("0x%" PRIx64, Addend); 7446 } 7447 7448 static void 7449 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7450 std::map<uint64_t, SymbolRef> &Symbols, 7451 const SectionRef &CompactUnwind) { 7452 7453 if (!Obj->isLittleEndian()) { 7454 outs() << "Skipping big-endian __compact_unwind section\n"; 7455 return; 7456 } 7457 7458 bool Is64 = Obj->is64Bit(); 7459 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7460 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7461 7462 StringRef Contents; 7463 CompactUnwind.getContents(Contents); 7464 7465 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7466 7467 // First populate the initial raw offsets, encodings and so on from the entry. 7468 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7469 CompactUnwindEntry Entry(Contents, Offset, Is64); 7470 CompactUnwinds.push_back(Entry); 7471 } 7472 7473 // Next we need to look at the relocations to find out what objects are 7474 // actually being referred to. 7475 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7476 uint64_t RelocAddress = Reloc.getOffset(); 7477 7478 uint32_t EntryIdx = RelocAddress / EntrySize; 7479 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7480 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7481 7482 if (OffsetInEntry == 0) 7483 Entry.FunctionReloc = Reloc; 7484 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7485 Entry.PersonalityReloc = Reloc; 7486 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7487 Entry.LSDAReloc = Reloc; 7488 else { 7489 outs() << "Invalid relocation in __compact_unwind section\n"; 7490 return; 7491 } 7492 } 7493 7494 // Finally, we're ready to print the data we've gathered. 7495 outs() << "Contents of __compact_unwind section:\n"; 7496 for (auto &Entry : CompactUnwinds) { 7497 outs() << " Entry at offset " 7498 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7499 7500 // 1. Start of the region this entry applies to. 7501 outs() << " start: " << format("0x%" PRIx64, 7502 Entry.FunctionAddr) << ' '; 7503 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7504 outs() << '\n'; 7505 7506 // 2. Length of the region this entry applies to. 7507 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7508 << '\n'; 7509 // 3. The 32-bit compact encoding. 7510 outs() << " compact encoding: " 7511 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7512 7513 // 4. The personality function, if present. 7514 if (Entry.PersonalityReloc.getObject()) { 7515 outs() << " personality function: " 7516 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7517 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7518 Entry.PersonalityAddr); 7519 outs() << '\n'; 7520 } 7521 7522 // 5. This entry's language-specific data area. 7523 if (Entry.LSDAReloc.getObject()) { 7524 outs() << " LSDA: " << format("0x%" PRIx64, 7525 Entry.LSDAAddr) << ' '; 7526 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7527 outs() << '\n'; 7528 } 7529 } 7530 } 7531 7532 //===----------------------------------------------------------------------===// 7533 // __unwind_info section dumping 7534 //===----------------------------------------------------------------------===// 7535 7536 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 7537 ptrdiff_t Pos = 0; 7538 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7539 (void)Kind; 7540 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7541 7542 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7543 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7544 7545 Pos = EntriesStart; 7546 for (unsigned i = 0; i < NumEntries; ++i) { 7547 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 7548 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7549 7550 outs() << " [" << i << "]: " 7551 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7552 << ", " 7553 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7554 } 7555 } 7556 7557 static void printCompressedSecondLevelUnwindPage( 7558 StringRef PageData, uint32_t FunctionBase, 7559 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7560 ptrdiff_t Pos = 0; 7561 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7562 (void)Kind; 7563 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 7564 7565 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7566 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7567 7568 uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos); 7569 readNext<uint16_t>(PageData, Pos); 7570 StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos); 7571 7572 Pos = EntriesStart; 7573 for (unsigned i = 0; i < NumEntries; ++i) { 7574 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 7575 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 7576 uint32_t EncodingIdx = Entry >> 24; 7577 7578 uint32_t Encoding; 7579 if (EncodingIdx < CommonEncodings.size()) 7580 Encoding = CommonEncodings[EncodingIdx]; 7581 else 7582 Encoding = read<uint32_t>(PageEncodings, 7583 sizeof(uint32_t) * 7584 (EncodingIdx - CommonEncodings.size())); 7585 7586 outs() << " [" << i << "]: " 7587 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7588 << ", " 7589 << "encoding[" << EncodingIdx 7590 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 7591 } 7592 } 7593 7594 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 7595 std::map<uint64_t, SymbolRef> &Symbols, 7596 const SectionRef &UnwindInfo) { 7597 7598 if (!Obj->isLittleEndian()) { 7599 outs() << "Skipping big-endian __unwind_info section\n"; 7600 return; 7601 } 7602 7603 outs() << "Contents of __unwind_info section:\n"; 7604 7605 StringRef Contents; 7606 UnwindInfo.getContents(Contents); 7607 ptrdiff_t Pos = 0; 7608 7609 //===---------------------------------- 7610 // Section header 7611 //===---------------------------------- 7612 7613 uint32_t Version = readNext<uint32_t>(Contents, Pos); 7614 outs() << " Version: " 7615 << format("0x%" PRIx32, Version) << '\n'; 7616 if (Version != 1) { 7617 outs() << " Skipping section with unknown version\n"; 7618 return; 7619 } 7620 7621 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 7622 outs() << " Common encodings array section offset: " 7623 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 7624 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 7625 outs() << " Number of common encodings in array: " 7626 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 7627 7628 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 7629 outs() << " Personality function array section offset: " 7630 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 7631 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 7632 outs() << " Number of personality functions in array: " 7633 << format("0x%" PRIx32, NumPersonalities) << '\n'; 7634 7635 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 7636 outs() << " Index array section offset: " 7637 << format("0x%" PRIx32, IndicesStart) << '\n'; 7638 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 7639 outs() << " Number of indices in array: " 7640 << format("0x%" PRIx32, NumIndices) << '\n'; 7641 7642 //===---------------------------------- 7643 // A shared list of common encodings 7644 //===---------------------------------- 7645 7646 // These occupy indices in the range [0, N] whenever an encoding is referenced 7647 // from a compressed 2nd level index table. In practice the linker only 7648 // creates ~128 of these, so that indices are available to embed encodings in 7649 // the 2nd level index. 7650 7651 SmallVector<uint32_t, 64> CommonEncodings; 7652 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 7653 Pos = CommonEncodingsStart; 7654 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 7655 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 7656 CommonEncodings.push_back(Encoding); 7657 7658 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 7659 << '\n'; 7660 } 7661 7662 //===---------------------------------- 7663 // Personality functions used in this executable 7664 //===---------------------------------- 7665 7666 // There should be only a handful of these (one per source language, 7667 // roughly). Particularly since they only get 2 bits in the compact encoding. 7668 7669 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 7670 Pos = PersonalitiesStart; 7671 for (unsigned i = 0; i < NumPersonalities; ++i) { 7672 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 7673 outs() << " personality[" << i + 1 7674 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 7675 } 7676 7677 //===---------------------------------- 7678 // The level 1 index entries 7679 //===---------------------------------- 7680 7681 // These specify an approximate place to start searching for the more detailed 7682 // information, sorted by PC. 7683 7684 struct IndexEntry { 7685 uint32_t FunctionOffset; 7686 uint32_t SecondLevelPageStart; 7687 uint32_t LSDAStart; 7688 }; 7689 7690 SmallVector<IndexEntry, 4> IndexEntries; 7691 7692 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 7693 Pos = IndicesStart; 7694 for (unsigned i = 0; i < NumIndices; ++i) { 7695 IndexEntry Entry; 7696 7697 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 7698 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 7699 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 7700 IndexEntries.push_back(Entry); 7701 7702 outs() << " [" << i << "]: " 7703 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 7704 << ", " 7705 << "2nd level page offset=" 7706 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 7707 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 7708 } 7709 7710 //===---------------------------------- 7711 // Next come the LSDA tables 7712 //===---------------------------------- 7713 7714 // The LSDA layout is rather implicit: it's a contiguous array of entries from 7715 // the first top-level index's LSDAOffset to the last (sentinel). 7716 7717 outs() << " LSDA descriptors:\n"; 7718 Pos = IndexEntries[0].LSDAStart; 7719 const uint32_t LSDASize = 2 * sizeof(uint32_t); 7720 int NumLSDAs = 7721 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 7722 7723 for (int i = 0; i < NumLSDAs; ++i) { 7724 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 7725 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 7726 outs() << " [" << i << "]: " 7727 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7728 << ", " 7729 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 7730 } 7731 7732 //===---------------------------------- 7733 // Finally, the 2nd level indices 7734 //===---------------------------------- 7735 7736 // Generally these are 4K in size, and have 2 possible forms: 7737 // + Regular stores up to 511 entries with disparate encodings 7738 // + Compressed stores up to 1021 entries if few enough compact encoding 7739 // values are used. 7740 outs() << " Second level indices:\n"; 7741 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 7742 // The final sentinel top-level index has no associated 2nd level page 7743 if (IndexEntries[i].SecondLevelPageStart == 0) 7744 break; 7745 7746 outs() << " Second level index[" << i << "]: " 7747 << "offset in section=" 7748 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 7749 << ", " 7750 << "base function offset=" 7751 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 7752 7753 Pos = IndexEntries[i].SecondLevelPageStart; 7754 if (Pos + sizeof(uint32_t) > Contents.size()) { 7755 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 7756 continue; 7757 } 7758 7759 uint32_t Kind = 7760 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 7761 if (Kind == 2) 7762 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 7763 else if (Kind == 3) 7764 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 7765 IndexEntries[i].FunctionOffset, 7766 CommonEncodings); 7767 else 7768 outs() << " Skipping 2nd level page with unknown kind " << Kind 7769 << '\n'; 7770 } 7771 } 7772 7773 void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { 7774 std::map<uint64_t, SymbolRef> Symbols; 7775 for (const SymbolRef &SymRef : Obj->symbols()) { 7776 // Discard any undefined or absolute symbols. They're not going to take part 7777 // in the convenience lookup for unwind info and just take up resources. 7778 auto SectOrErr = SymRef.getSection(); 7779 if (!SectOrErr) { 7780 // TODO: Actually report errors helpfully. 7781 consumeError(SectOrErr.takeError()); 7782 continue; 7783 } 7784 section_iterator Section = *SectOrErr; 7785 if (Section == Obj->section_end()) 7786 continue; 7787 7788 uint64_t Addr = SymRef.getValue(); 7789 Symbols.insert(std::make_pair(Addr, SymRef)); 7790 } 7791 7792 for (const SectionRef &Section : Obj->sections()) { 7793 StringRef SectName; 7794 Section.getName(SectName); 7795 if (SectName == "__compact_unwind") 7796 printMachOCompactUnwindSection(Obj, Symbols, Section); 7797 else if (SectName == "__unwind_info") 7798 printMachOUnwindInfoSection(Obj, Symbols, Section); 7799 } 7800 } 7801 7802 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 7803 uint32_t cpusubtype, uint32_t filetype, 7804 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 7805 bool verbose) { 7806 outs() << "Mach header\n"; 7807 outs() << " magic cputype cpusubtype caps filetype ncmds " 7808 "sizeofcmds flags\n"; 7809 if (verbose) { 7810 if (magic == MachO::MH_MAGIC) 7811 outs() << " MH_MAGIC"; 7812 else if (magic == MachO::MH_MAGIC_64) 7813 outs() << "MH_MAGIC_64"; 7814 else 7815 outs() << format(" 0x%08" PRIx32, magic); 7816 switch (cputype) { 7817 case MachO::CPU_TYPE_I386: 7818 outs() << " I386"; 7819 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7820 case MachO::CPU_SUBTYPE_I386_ALL: 7821 outs() << " ALL"; 7822 break; 7823 default: 7824 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7825 break; 7826 } 7827 break; 7828 case MachO::CPU_TYPE_X86_64: 7829 outs() << " X86_64"; 7830 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7831 case MachO::CPU_SUBTYPE_X86_64_ALL: 7832 outs() << " ALL"; 7833 break; 7834 case MachO::CPU_SUBTYPE_X86_64_H: 7835 outs() << " Haswell"; 7836 break; 7837 default: 7838 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7839 break; 7840 } 7841 break; 7842 case MachO::CPU_TYPE_ARM: 7843 outs() << " ARM"; 7844 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7845 case MachO::CPU_SUBTYPE_ARM_ALL: 7846 outs() << " ALL"; 7847 break; 7848 case MachO::CPU_SUBTYPE_ARM_V4T: 7849 outs() << " V4T"; 7850 break; 7851 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 7852 outs() << " V5TEJ"; 7853 break; 7854 case MachO::CPU_SUBTYPE_ARM_XSCALE: 7855 outs() << " XSCALE"; 7856 break; 7857 case MachO::CPU_SUBTYPE_ARM_V6: 7858 outs() << " V6"; 7859 break; 7860 case MachO::CPU_SUBTYPE_ARM_V6M: 7861 outs() << " V6M"; 7862 break; 7863 case MachO::CPU_SUBTYPE_ARM_V7: 7864 outs() << " V7"; 7865 break; 7866 case MachO::CPU_SUBTYPE_ARM_V7EM: 7867 outs() << " V7EM"; 7868 break; 7869 case MachO::CPU_SUBTYPE_ARM_V7K: 7870 outs() << " V7K"; 7871 break; 7872 case MachO::CPU_SUBTYPE_ARM_V7M: 7873 outs() << " V7M"; 7874 break; 7875 case MachO::CPU_SUBTYPE_ARM_V7S: 7876 outs() << " V7S"; 7877 break; 7878 default: 7879 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7880 break; 7881 } 7882 break; 7883 case MachO::CPU_TYPE_ARM64: 7884 outs() << " ARM64"; 7885 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7886 case MachO::CPU_SUBTYPE_ARM64_ALL: 7887 outs() << " ALL"; 7888 break; 7889 default: 7890 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7891 break; 7892 } 7893 break; 7894 case MachO::CPU_TYPE_POWERPC: 7895 outs() << " PPC"; 7896 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7897 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7898 outs() << " ALL"; 7899 break; 7900 default: 7901 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7902 break; 7903 } 7904 break; 7905 case MachO::CPU_TYPE_POWERPC64: 7906 outs() << " PPC64"; 7907 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7908 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7909 outs() << " ALL"; 7910 break; 7911 default: 7912 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7913 break; 7914 } 7915 break; 7916 default: 7917 outs() << format(" %7d", cputype); 7918 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7919 break; 7920 } 7921 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 7922 outs() << " LIB64"; 7923 } else { 7924 outs() << format(" 0x%02" PRIx32, 7925 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 7926 } 7927 switch (filetype) { 7928 case MachO::MH_OBJECT: 7929 outs() << " OBJECT"; 7930 break; 7931 case MachO::MH_EXECUTE: 7932 outs() << " EXECUTE"; 7933 break; 7934 case MachO::MH_FVMLIB: 7935 outs() << " FVMLIB"; 7936 break; 7937 case MachO::MH_CORE: 7938 outs() << " CORE"; 7939 break; 7940 case MachO::MH_PRELOAD: 7941 outs() << " PRELOAD"; 7942 break; 7943 case MachO::MH_DYLIB: 7944 outs() << " DYLIB"; 7945 break; 7946 case MachO::MH_DYLIB_STUB: 7947 outs() << " DYLIB_STUB"; 7948 break; 7949 case MachO::MH_DYLINKER: 7950 outs() << " DYLINKER"; 7951 break; 7952 case MachO::MH_BUNDLE: 7953 outs() << " BUNDLE"; 7954 break; 7955 case MachO::MH_DSYM: 7956 outs() << " DSYM"; 7957 break; 7958 case MachO::MH_KEXT_BUNDLE: 7959 outs() << " KEXTBUNDLE"; 7960 break; 7961 default: 7962 outs() << format(" %10u", filetype); 7963 break; 7964 } 7965 outs() << format(" %5u", ncmds); 7966 outs() << format(" %10u", sizeofcmds); 7967 uint32_t f = flags; 7968 if (f & MachO::MH_NOUNDEFS) { 7969 outs() << " NOUNDEFS"; 7970 f &= ~MachO::MH_NOUNDEFS; 7971 } 7972 if (f & MachO::MH_INCRLINK) { 7973 outs() << " INCRLINK"; 7974 f &= ~MachO::MH_INCRLINK; 7975 } 7976 if (f & MachO::MH_DYLDLINK) { 7977 outs() << " DYLDLINK"; 7978 f &= ~MachO::MH_DYLDLINK; 7979 } 7980 if (f & MachO::MH_BINDATLOAD) { 7981 outs() << " BINDATLOAD"; 7982 f &= ~MachO::MH_BINDATLOAD; 7983 } 7984 if (f & MachO::MH_PREBOUND) { 7985 outs() << " PREBOUND"; 7986 f &= ~MachO::MH_PREBOUND; 7987 } 7988 if (f & MachO::MH_SPLIT_SEGS) { 7989 outs() << " SPLIT_SEGS"; 7990 f &= ~MachO::MH_SPLIT_SEGS; 7991 } 7992 if (f & MachO::MH_LAZY_INIT) { 7993 outs() << " LAZY_INIT"; 7994 f &= ~MachO::MH_LAZY_INIT; 7995 } 7996 if (f & MachO::MH_TWOLEVEL) { 7997 outs() << " TWOLEVEL"; 7998 f &= ~MachO::MH_TWOLEVEL; 7999 } 8000 if (f & MachO::MH_FORCE_FLAT) { 8001 outs() << " FORCE_FLAT"; 8002 f &= ~MachO::MH_FORCE_FLAT; 8003 } 8004 if (f & MachO::MH_NOMULTIDEFS) { 8005 outs() << " NOMULTIDEFS"; 8006 f &= ~MachO::MH_NOMULTIDEFS; 8007 } 8008 if (f & MachO::MH_NOFIXPREBINDING) { 8009 outs() << " NOFIXPREBINDING"; 8010 f &= ~MachO::MH_NOFIXPREBINDING; 8011 } 8012 if (f & MachO::MH_PREBINDABLE) { 8013 outs() << " PREBINDABLE"; 8014 f &= ~MachO::MH_PREBINDABLE; 8015 } 8016 if (f & MachO::MH_ALLMODSBOUND) { 8017 outs() << " ALLMODSBOUND"; 8018 f &= ~MachO::MH_ALLMODSBOUND; 8019 } 8020 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8021 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8022 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8023 } 8024 if (f & MachO::MH_CANONICAL) { 8025 outs() << " CANONICAL"; 8026 f &= ~MachO::MH_CANONICAL; 8027 } 8028 if (f & MachO::MH_WEAK_DEFINES) { 8029 outs() << " WEAK_DEFINES"; 8030 f &= ~MachO::MH_WEAK_DEFINES; 8031 } 8032 if (f & MachO::MH_BINDS_TO_WEAK) { 8033 outs() << " BINDS_TO_WEAK"; 8034 f &= ~MachO::MH_BINDS_TO_WEAK; 8035 } 8036 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8037 outs() << " ALLOW_STACK_EXECUTION"; 8038 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8039 } 8040 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8041 outs() << " DEAD_STRIPPABLE_DYLIB"; 8042 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8043 } 8044 if (f & MachO::MH_PIE) { 8045 outs() << " PIE"; 8046 f &= ~MachO::MH_PIE; 8047 } 8048 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8049 outs() << " NO_REEXPORTED_DYLIBS"; 8050 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8051 } 8052 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8053 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8054 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8055 } 8056 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8057 outs() << " MH_NO_HEAP_EXECUTION"; 8058 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8059 } 8060 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8061 outs() << " APP_EXTENSION_SAFE"; 8062 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8063 } 8064 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8065 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8066 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8067 } 8068 if (f != 0 || flags == 0) 8069 outs() << format(" 0x%08" PRIx32, f); 8070 } else { 8071 outs() << format(" 0x%08" PRIx32, magic); 8072 outs() << format(" %7d", cputype); 8073 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8074 outs() << format(" 0x%02" PRIx32, 8075 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8076 outs() << format(" %10u", filetype); 8077 outs() << format(" %5u", ncmds); 8078 outs() << format(" %10u", sizeofcmds); 8079 outs() << format(" 0x%08" PRIx32, flags); 8080 } 8081 outs() << "\n"; 8082 } 8083 8084 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8085 StringRef SegName, uint64_t vmaddr, 8086 uint64_t vmsize, uint64_t fileoff, 8087 uint64_t filesize, uint32_t maxprot, 8088 uint32_t initprot, uint32_t nsects, 8089 uint32_t flags, uint32_t object_size, 8090 bool verbose) { 8091 uint64_t expected_cmdsize; 8092 if (cmd == MachO::LC_SEGMENT) { 8093 outs() << " cmd LC_SEGMENT\n"; 8094 expected_cmdsize = nsects; 8095 expected_cmdsize *= sizeof(struct MachO::section); 8096 expected_cmdsize += sizeof(struct MachO::segment_command); 8097 } else { 8098 outs() << " cmd LC_SEGMENT_64\n"; 8099 expected_cmdsize = nsects; 8100 expected_cmdsize *= sizeof(struct MachO::section_64); 8101 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8102 } 8103 outs() << " cmdsize " << cmdsize; 8104 if (cmdsize != expected_cmdsize) 8105 outs() << " Inconsistent size\n"; 8106 else 8107 outs() << "\n"; 8108 outs() << " segname " << SegName << "\n"; 8109 if (cmd == MachO::LC_SEGMENT_64) { 8110 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8111 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8112 } else { 8113 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8114 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8115 } 8116 outs() << " fileoff " << fileoff; 8117 if (fileoff > object_size) 8118 outs() << " (past end of file)\n"; 8119 else 8120 outs() << "\n"; 8121 outs() << " filesize " << filesize; 8122 if (fileoff + filesize > object_size) 8123 outs() << " (past end of file)\n"; 8124 else 8125 outs() << "\n"; 8126 if (verbose) { 8127 if ((maxprot & 8128 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8129 MachO::VM_PROT_EXECUTE)) != 0) 8130 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8131 else { 8132 outs() << " maxprot "; 8133 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8134 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8135 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8136 } 8137 if ((initprot & 8138 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8139 MachO::VM_PROT_EXECUTE)) != 0) 8140 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8141 else { 8142 outs() << " initprot "; 8143 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8144 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8145 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8146 } 8147 } else { 8148 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8149 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8150 } 8151 outs() << " nsects " << nsects << "\n"; 8152 if (verbose) { 8153 outs() << " flags"; 8154 if (flags == 0) 8155 outs() << " (none)\n"; 8156 else { 8157 if (flags & MachO::SG_HIGHVM) { 8158 outs() << " HIGHVM"; 8159 flags &= ~MachO::SG_HIGHVM; 8160 } 8161 if (flags & MachO::SG_FVMLIB) { 8162 outs() << " FVMLIB"; 8163 flags &= ~MachO::SG_FVMLIB; 8164 } 8165 if (flags & MachO::SG_NORELOC) { 8166 outs() << " NORELOC"; 8167 flags &= ~MachO::SG_NORELOC; 8168 } 8169 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8170 outs() << " PROTECTED_VERSION_1"; 8171 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8172 } 8173 if (flags) 8174 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8175 else 8176 outs() << "\n"; 8177 } 8178 } else { 8179 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8180 } 8181 } 8182 8183 static void PrintSection(const char *sectname, const char *segname, 8184 uint64_t addr, uint64_t size, uint32_t offset, 8185 uint32_t align, uint32_t reloff, uint32_t nreloc, 8186 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8187 uint32_t cmd, const char *sg_segname, 8188 uint32_t filetype, uint32_t object_size, 8189 bool verbose) { 8190 outs() << "Section\n"; 8191 outs() << " sectname " << format("%.16s\n", sectname); 8192 outs() << " segname " << format("%.16s", segname); 8193 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8194 outs() << " (does not match segment)\n"; 8195 else 8196 outs() << "\n"; 8197 if (cmd == MachO::LC_SEGMENT_64) { 8198 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8199 outs() << " size " << format("0x%016" PRIx64, size); 8200 } else { 8201 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8202 outs() << " size " << format("0x%08" PRIx64, size); 8203 } 8204 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8205 outs() << " (past end of file)\n"; 8206 else 8207 outs() << "\n"; 8208 outs() << " offset " << offset; 8209 if (offset > object_size) 8210 outs() << " (past end of file)\n"; 8211 else 8212 outs() << "\n"; 8213 uint32_t align_shifted = 1 << align; 8214 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8215 outs() << " reloff " << reloff; 8216 if (reloff > object_size) 8217 outs() << " (past end of file)\n"; 8218 else 8219 outs() << "\n"; 8220 outs() << " nreloc " << nreloc; 8221 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8222 outs() << " (past end of file)\n"; 8223 else 8224 outs() << "\n"; 8225 uint32_t section_type = flags & MachO::SECTION_TYPE; 8226 if (verbose) { 8227 outs() << " type"; 8228 if (section_type == MachO::S_REGULAR) 8229 outs() << " S_REGULAR\n"; 8230 else if (section_type == MachO::S_ZEROFILL) 8231 outs() << " S_ZEROFILL\n"; 8232 else if (section_type == MachO::S_CSTRING_LITERALS) 8233 outs() << " S_CSTRING_LITERALS\n"; 8234 else if (section_type == MachO::S_4BYTE_LITERALS) 8235 outs() << " S_4BYTE_LITERALS\n"; 8236 else if (section_type == MachO::S_8BYTE_LITERALS) 8237 outs() << " S_8BYTE_LITERALS\n"; 8238 else if (section_type == MachO::S_16BYTE_LITERALS) 8239 outs() << " S_16BYTE_LITERALS\n"; 8240 else if (section_type == MachO::S_LITERAL_POINTERS) 8241 outs() << " S_LITERAL_POINTERS\n"; 8242 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8243 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8244 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8245 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8246 else if (section_type == MachO::S_SYMBOL_STUBS) 8247 outs() << " S_SYMBOL_STUBS\n"; 8248 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8249 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8250 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8251 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8252 else if (section_type == MachO::S_COALESCED) 8253 outs() << " S_COALESCED\n"; 8254 else if (section_type == MachO::S_INTERPOSING) 8255 outs() << " S_INTERPOSING\n"; 8256 else if (section_type == MachO::S_DTRACE_DOF) 8257 outs() << " S_DTRACE_DOF\n"; 8258 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8259 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8260 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8261 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8262 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8263 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8264 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8265 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8266 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8267 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8268 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8269 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8270 else 8271 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8272 outs() << "attributes"; 8273 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8274 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8275 outs() << " PURE_INSTRUCTIONS"; 8276 if (section_attributes & MachO::S_ATTR_NO_TOC) 8277 outs() << " NO_TOC"; 8278 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8279 outs() << " STRIP_STATIC_SYMS"; 8280 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8281 outs() << " NO_DEAD_STRIP"; 8282 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8283 outs() << " LIVE_SUPPORT"; 8284 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8285 outs() << " SELF_MODIFYING_CODE"; 8286 if (section_attributes & MachO::S_ATTR_DEBUG) 8287 outs() << " DEBUG"; 8288 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8289 outs() << " SOME_INSTRUCTIONS"; 8290 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8291 outs() << " EXT_RELOC"; 8292 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8293 outs() << " LOC_RELOC"; 8294 if (section_attributes == 0) 8295 outs() << " (none)"; 8296 outs() << "\n"; 8297 } else 8298 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8299 outs() << " reserved1 " << reserved1; 8300 if (section_type == MachO::S_SYMBOL_STUBS || 8301 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8302 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8303 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8304 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8305 outs() << " (index into indirect symbol table)\n"; 8306 else 8307 outs() << "\n"; 8308 outs() << " reserved2 " << reserved2; 8309 if (section_type == MachO::S_SYMBOL_STUBS) 8310 outs() << " (size of stubs)\n"; 8311 else 8312 outs() << "\n"; 8313 } 8314 8315 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8316 uint32_t object_size) { 8317 outs() << " cmd LC_SYMTAB\n"; 8318 outs() << " cmdsize " << st.cmdsize; 8319 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8320 outs() << " Incorrect size\n"; 8321 else 8322 outs() << "\n"; 8323 outs() << " symoff " << st.symoff; 8324 if (st.symoff > object_size) 8325 outs() << " (past end of file)\n"; 8326 else 8327 outs() << "\n"; 8328 outs() << " nsyms " << st.nsyms; 8329 uint64_t big_size; 8330 if (Is64Bit) { 8331 big_size = st.nsyms; 8332 big_size *= sizeof(struct MachO::nlist_64); 8333 big_size += st.symoff; 8334 if (big_size > object_size) 8335 outs() << " (past end of file)\n"; 8336 else 8337 outs() << "\n"; 8338 } else { 8339 big_size = st.nsyms; 8340 big_size *= sizeof(struct MachO::nlist); 8341 big_size += st.symoff; 8342 if (big_size > object_size) 8343 outs() << " (past end of file)\n"; 8344 else 8345 outs() << "\n"; 8346 } 8347 outs() << " stroff " << st.stroff; 8348 if (st.stroff > object_size) 8349 outs() << " (past end of file)\n"; 8350 else 8351 outs() << "\n"; 8352 outs() << " strsize " << st.strsize; 8353 big_size = st.stroff; 8354 big_size += st.strsize; 8355 if (big_size > object_size) 8356 outs() << " (past end of file)\n"; 8357 else 8358 outs() << "\n"; 8359 } 8360 8361 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8362 uint32_t nsyms, uint32_t object_size, 8363 bool Is64Bit) { 8364 outs() << " cmd LC_DYSYMTAB\n"; 8365 outs() << " cmdsize " << dyst.cmdsize; 8366 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8367 outs() << " Incorrect size\n"; 8368 else 8369 outs() << "\n"; 8370 outs() << " ilocalsym " << dyst.ilocalsym; 8371 if (dyst.ilocalsym > nsyms) 8372 outs() << " (greater than the number of symbols)\n"; 8373 else 8374 outs() << "\n"; 8375 outs() << " nlocalsym " << dyst.nlocalsym; 8376 uint64_t big_size; 8377 big_size = dyst.ilocalsym; 8378 big_size += dyst.nlocalsym; 8379 if (big_size > nsyms) 8380 outs() << " (past the end of the symbol table)\n"; 8381 else 8382 outs() << "\n"; 8383 outs() << " iextdefsym " << dyst.iextdefsym; 8384 if (dyst.iextdefsym > nsyms) 8385 outs() << " (greater than the number of symbols)\n"; 8386 else 8387 outs() << "\n"; 8388 outs() << " nextdefsym " << dyst.nextdefsym; 8389 big_size = dyst.iextdefsym; 8390 big_size += dyst.nextdefsym; 8391 if (big_size > nsyms) 8392 outs() << " (past the end of the symbol table)\n"; 8393 else 8394 outs() << "\n"; 8395 outs() << " iundefsym " << dyst.iundefsym; 8396 if (dyst.iundefsym > nsyms) 8397 outs() << " (greater than the number of symbols)\n"; 8398 else 8399 outs() << "\n"; 8400 outs() << " nundefsym " << dyst.nundefsym; 8401 big_size = dyst.iundefsym; 8402 big_size += dyst.nundefsym; 8403 if (big_size > nsyms) 8404 outs() << " (past the end of the symbol table)\n"; 8405 else 8406 outs() << "\n"; 8407 outs() << " tocoff " << dyst.tocoff; 8408 if (dyst.tocoff > object_size) 8409 outs() << " (past end of file)\n"; 8410 else 8411 outs() << "\n"; 8412 outs() << " ntoc " << dyst.ntoc; 8413 big_size = dyst.ntoc; 8414 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8415 big_size += dyst.tocoff; 8416 if (big_size > object_size) 8417 outs() << " (past end of file)\n"; 8418 else 8419 outs() << "\n"; 8420 outs() << " modtaboff " << dyst.modtaboff; 8421 if (dyst.modtaboff > object_size) 8422 outs() << " (past end of file)\n"; 8423 else 8424 outs() << "\n"; 8425 outs() << " nmodtab " << dyst.nmodtab; 8426 uint64_t modtabend; 8427 if (Is64Bit) { 8428 modtabend = dyst.nmodtab; 8429 modtabend *= sizeof(struct MachO::dylib_module_64); 8430 modtabend += dyst.modtaboff; 8431 } else { 8432 modtabend = dyst.nmodtab; 8433 modtabend *= sizeof(struct MachO::dylib_module); 8434 modtabend += dyst.modtaboff; 8435 } 8436 if (modtabend > object_size) 8437 outs() << " (past end of file)\n"; 8438 else 8439 outs() << "\n"; 8440 outs() << " extrefsymoff " << dyst.extrefsymoff; 8441 if (dyst.extrefsymoff > object_size) 8442 outs() << " (past end of file)\n"; 8443 else 8444 outs() << "\n"; 8445 outs() << " nextrefsyms " << dyst.nextrefsyms; 8446 big_size = dyst.nextrefsyms; 8447 big_size *= sizeof(struct MachO::dylib_reference); 8448 big_size += dyst.extrefsymoff; 8449 if (big_size > object_size) 8450 outs() << " (past end of file)\n"; 8451 else 8452 outs() << "\n"; 8453 outs() << " indirectsymoff " << dyst.indirectsymoff; 8454 if (dyst.indirectsymoff > object_size) 8455 outs() << " (past end of file)\n"; 8456 else 8457 outs() << "\n"; 8458 outs() << " nindirectsyms " << dyst.nindirectsyms; 8459 big_size = dyst.nindirectsyms; 8460 big_size *= sizeof(uint32_t); 8461 big_size += dyst.indirectsymoff; 8462 if (big_size > object_size) 8463 outs() << " (past end of file)\n"; 8464 else 8465 outs() << "\n"; 8466 outs() << " extreloff " << dyst.extreloff; 8467 if (dyst.extreloff > object_size) 8468 outs() << " (past end of file)\n"; 8469 else 8470 outs() << "\n"; 8471 outs() << " nextrel " << dyst.nextrel; 8472 big_size = dyst.nextrel; 8473 big_size *= sizeof(struct MachO::relocation_info); 8474 big_size += dyst.extreloff; 8475 if (big_size > object_size) 8476 outs() << " (past end of file)\n"; 8477 else 8478 outs() << "\n"; 8479 outs() << " locreloff " << dyst.locreloff; 8480 if (dyst.locreloff > object_size) 8481 outs() << " (past end of file)\n"; 8482 else 8483 outs() << "\n"; 8484 outs() << " nlocrel " << dyst.nlocrel; 8485 big_size = dyst.nlocrel; 8486 big_size *= sizeof(struct MachO::relocation_info); 8487 big_size += dyst.locreloff; 8488 if (big_size > object_size) 8489 outs() << " (past end of file)\n"; 8490 else 8491 outs() << "\n"; 8492 } 8493 8494 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8495 uint32_t object_size) { 8496 if (dc.cmd == MachO::LC_DYLD_INFO) 8497 outs() << " cmd LC_DYLD_INFO\n"; 8498 else 8499 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8500 outs() << " cmdsize " << dc.cmdsize; 8501 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8502 outs() << " Incorrect size\n"; 8503 else 8504 outs() << "\n"; 8505 outs() << " rebase_off " << dc.rebase_off; 8506 if (dc.rebase_off > object_size) 8507 outs() << " (past end of file)\n"; 8508 else 8509 outs() << "\n"; 8510 outs() << " rebase_size " << dc.rebase_size; 8511 uint64_t big_size; 8512 big_size = dc.rebase_off; 8513 big_size += dc.rebase_size; 8514 if (big_size > object_size) 8515 outs() << " (past end of file)\n"; 8516 else 8517 outs() << "\n"; 8518 outs() << " bind_off " << dc.bind_off; 8519 if (dc.bind_off > object_size) 8520 outs() << " (past end of file)\n"; 8521 else 8522 outs() << "\n"; 8523 outs() << " bind_size " << dc.bind_size; 8524 big_size = dc.bind_off; 8525 big_size += dc.bind_size; 8526 if (big_size > object_size) 8527 outs() << " (past end of file)\n"; 8528 else 8529 outs() << "\n"; 8530 outs() << " weak_bind_off " << dc.weak_bind_off; 8531 if (dc.weak_bind_off > object_size) 8532 outs() << " (past end of file)\n"; 8533 else 8534 outs() << "\n"; 8535 outs() << " weak_bind_size " << dc.weak_bind_size; 8536 big_size = dc.weak_bind_off; 8537 big_size += dc.weak_bind_size; 8538 if (big_size > object_size) 8539 outs() << " (past end of file)\n"; 8540 else 8541 outs() << "\n"; 8542 outs() << " lazy_bind_off " << dc.lazy_bind_off; 8543 if (dc.lazy_bind_off > object_size) 8544 outs() << " (past end of file)\n"; 8545 else 8546 outs() << "\n"; 8547 outs() << " lazy_bind_size " << dc.lazy_bind_size; 8548 big_size = dc.lazy_bind_off; 8549 big_size += dc.lazy_bind_size; 8550 if (big_size > object_size) 8551 outs() << " (past end of file)\n"; 8552 else 8553 outs() << "\n"; 8554 outs() << " export_off " << dc.export_off; 8555 if (dc.export_off > object_size) 8556 outs() << " (past end of file)\n"; 8557 else 8558 outs() << "\n"; 8559 outs() << " export_size " << dc.export_size; 8560 big_size = dc.export_off; 8561 big_size += dc.export_size; 8562 if (big_size > object_size) 8563 outs() << " (past end of file)\n"; 8564 else 8565 outs() << "\n"; 8566 } 8567 8568 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 8569 const char *Ptr) { 8570 if (dyld.cmd == MachO::LC_ID_DYLINKER) 8571 outs() << " cmd LC_ID_DYLINKER\n"; 8572 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 8573 outs() << " cmd LC_LOAD_DYLINKER\n"; 8574 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 8575 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 8576 else 8577 outs() << " cmd ?(" << dyld.cmd << ")\n"; 8578 outs() << " cmdsize " << dyld.cmdsize; 8579 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 8580 outs() << " Incorrect size\n"; 8581 else 8582 outs() << "\n"; 8583 if (dyld.name >= dyld.cmdsize) 8584 outs() << " name ?(bad offset " << dyld.name << ")\n"; 8585 else { 8586 const char *P = (const char *)(Ptr) + dyld.name; 8587 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 8588 } 8589 } 8590 8591 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 8592 outs() << " cmd LC_UUID\n"; 8593 outs() << " cmdsize " << uuid.cmdsize; 8594 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 8595 outs() << " Incorrect size\n"; 8596 else 8597 outs() << "\n"; 8598 outs() << " uuid "; 8599 for (int i = 0; i < 16; ++i) { 8600 outs() << format("%02" PRIX32, uuid.uuid[i]); 8601 if (i == 3 || i == 5 || i == 7 || i == 9) 8602 outs() << "-"; 8603 } 8604 outs() << "\n"; 8605 } 8606 8607 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 8608 outs() << " cmd LC_RPATH\n"; 8609 outs() << " cmdsize " << rpath.cmdsize; 8610 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 8611 outs() << " Incorrect size\n"; 8612 else 8613 outs() << "\n"; 8614 if (rpath.path >= rpath.cmdsize) 8615 outs() << " path ?(bad offset " << rpath.path << ")\n"; 8616 else { 8617 const char *P = (const char *)(Ptr) + rpath.path; 8618 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 8619 } 8620 } 8621 8622 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 8623 StringRef LoadCmdName; 8624 switch (vd.cmd) { 8625 case MachO::LC_VERSION_MIN_MACOSX: 8626 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 8627 break; 8628 case MachO::LC_VERSION_MIN_IPHONEOS: 8629 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 8630 break; 8631 case MachO::LC_VERSION_MIN_TVOS: 8632 LoadCmdName = "LC_VERSION_MIN_TVOS"; 8633 break; 8634 case MachO::LC_VERSION_MIN_WATCHOS: 8635 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 8636 break; 8637 default: 8638 llvm_unreachable("Unknown version min load command"); 8639 } 8640 8641 outs() << " cmd " << LoadCmdName << '\n'; 8642 outs() << " cmdsize " << vd.cmdsize; 8643 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 8644 outs() << " Incorrect size\n"; 8645 else 8646 outs() << "\n"; 8647 outs() << " version " 8648 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 8649 << MachOObjectFile::getVersionMinMinor(vd, false); 8650 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 8651 if (Update != 0) 8652 outs() << "." << Update; 8653 outs() << "\n"; 8654 if (vd.sdk == 0) 8655 outs() << " sdk n/a"; 8656 else { 8657 outs() << " sdk " 8658 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 8659 << MachOObjectFile::getVersionMinMinor(vd, true); 8660 } 8661 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 8662 if (Update != 0) 8663 outs() << "." << Update; 8664 outs() << "\n"; 8665 } 8666 8667 static void PrintNoteLoadCommand(MachO::note_command Nt) { 8668 outs() << " cmd LC_NOTE\n"; 8669 outs() << " cmdsize " << Nt.cmdsize; 8670 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 8671 outs() << " Incorrect size\n"; 8672 else 8673 outs() << "\n"; 8674 const char *d = Nt.data_owner; 8675 outs() << "data_owner " << format("%.16s\n", d); 8676 outs() << " offset " << Nt.offset << "\n"; 8677 outs() << " size " << Nt.size << "\n"; 8678 } 8679 8680 static void PrintBuildToolVersion(MachO::build_tool_version bv) { 8681 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; 8682 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 8683 << "\n"; 8684 } 8685 8686 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 8687 MachO::build_version_command bd) { 8688 outs() << " cmd LC_BUILD_VERSION\n"; 8689 outs() << " cmdsize " << bd.cmdsize; 8690 if (bd.cmdsize != 8691 sizeof(struct MachO::build_version_command) + 8692 bd.ntools * sizeof(struct MachO::build_tool_version)) 8693 outs() << " Incorrect size\n"; 8694 else 8695 outs() << "\n"; 8696 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) 8697 << "\n"; 8698 if (bd.sdk) 8699 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 8700 << "\n"; 8701 else 8702 outs() << " sdk n/a\n"; 8703 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 8704 << "\n"; 8705 outs() << " ntools " << bd.ntools << "\n"; 8706 for (unsigned i = 0; i < bd.ntools; ++i) { 8707 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 8708 PrintBuildToolVersion(bv); 8709 } 8710 } 8711 8712 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 8713 outs() << " cmd LC_SOURCE_VERSION\n"; 8714 outs() << " cmdsize " << sd.cmdsize; 8715 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 8716 outs() << " Incorrect size\n"; 8717 else 8718 outs() << "\n"; 8719 uint64_t a = (sd.version >> 40) & 0xffffff; 8720 uint64_t b = (sd.version >> 30) & 0x3ff; 8721 uint64_t c = (sd.version >> 20) & 0x3ff; 8722 uint64_t d = (sd.version >> 10) & 0x3ff; 8723 uint64_t e = sd.version & 0x3ff; 8724 outs() << " version " << a << "." << b; 8725 if (e != 0) 8726 outs() << "." << c << "." << d << "." << e; 8727 else if (d != 0) 8728 outs() << "." << c << "." << d; 8729 else if (c != 0) 8730 outs() << "." << c; 8731 outs() << "\n"; 8732 } 8733 8734 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 8735 outs() << " cmd LC_MAIN\n"; 8736 outs() << " cmdsize " << ep.cmdsize; 8737 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 8738 outs() << " Incorrect size\n"; 8739 else 8740 outs() << "\n"; 8741 outs() << " entryoff " << ep.entryoff << "\n"; 8742 outs() << " stacksize " << ep.stacksize << "\n"; 8743 } 8744 8745 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 8746 uint32_t object_size) { 8747 outs() << " cmd LC_ENCRYPTION_INFO\n"; 8748 outs() << " cmdsize " << ec.cmdsize; 8749 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 8750 outs() << " Incorrect size\n"; 8751 else 8752 outs() << "\n"; 8753 outs() << " cryptoff " << ec.cryptoff; 8754 if (ec.cryptoff > object_size) 8755 outs() << " (past end of file)\n"; 8756 else 8757 outs() << "\n"; 8758 outs() << " cryptsize " << ec.cryptsize; 8759 if (ec.cryptsize > object_size) 8760 outs() << " (past end of file)\n"; 8761 else 8762 outs() << "\n"; 8763 outs() << " cryptid " << ec.cryptid << "\n"; 8764 } 8765 8766 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 8767 uint32_t object_size) { 8768 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 8769 outs() << " cmdsize " << ec.cmdsize; 8770 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 8771 outs() << " Incorrect size\n"; 8772 else 8773 outs() << "\n"; 8774 outs() << " cryptoff " << ec.cryptoff; 8775 if (ec.cryptoff > object_size) 8776 outs() << " (past end of file)\n"; 8777 else 8778 outs() << "\n"; 8779 outs() << " cryptsize " << ec.cryptsize; 8780 if (ec.cryptsize > object_size) 8781 outs() << " (past end of file)\n"; 8782 else 8783 outs() << "\n"; 8784 outs() << " cryptid " << ec.cryptid << "\n"; 8785 outs() << " pad " << ec.pad << "\n"; 8786 } 8787 8788 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 8789 const char *Ptr) { 8790 outs() << " cmd LC_LINKER_OPTION\n"; 8791 outs() << " cmdsize " << lo.cmdsize; 8792 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 8793 outs() << " Incorrect size\n"; 8794 else 8795 outs() << "\n"; 8796 outs() << " count " << lo.count << "\n"; 8797 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 8798 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 8799 uint32_t i = 0; 8800 while (left > 0) { 8801 while (*string == '\0' && left > 0) { 8802 string++; 8803 left--; 8804 } 8805 if (left > 0) { 8806 i++; 8807 outs() << " string #" << i << " " << format("%.*s\n", left, string); 8808 uint32_t NullPos = StringRef(string, left).find('\0'); 8809 uint32_t len = std::min(NullPos, left) + 1; 8810 string += len; 8811 left -= len; 8812 } 8813 } 8814 if (lo.count != i) 8815 outs() << " count " << lo.count << " does not match number of strings " 8816 << i << "\n"; 8817 } 8818 8819 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 8820 const char *Ptr) { 8821 outs() << " cmd LC_SUB_FRAMEWORK\n"; 8822 outs() << " cmdsize " << sub.cmdsize; 8823 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 8824 outs() << " Incorrect size\n"; 8825 else 8826 outs() << "\n"; 8827 if (sub.umbrella < sub.cmdsize) { 8828 const char *P = Ptr + sub.umbrella; 8829 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 8830 } else { 8831 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 8832 } 8833 } 8834 8835 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 8836 const char *Ptr) { 8837 outs() << " cmd LC_SUB_UMBRELLA\n"; 8838 outs() << " cmdsize " << sub.cmdsize; 8839 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 8840 outs() << " Incorrect size\n"; 8841 else 8842 outs() << "\n"; 8843 if (sub.sub_umbrella < sub.cmdsize) { 8844 const char *P = Ptr + sub.sub_umbrella; 8845 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 8846 } else { 8847 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 8848 } 8849 } 8850 8851 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 8852 const char *Ptr) { 8853 outs() << " cmd LC_SUB_LIBRARY\n"; 8854 outs() << " cmdsize " << sub.cmdsize; 8855 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 8856 outs() << " Incorrect size\n"; 8857 else 8858 outs() << "\n"; 8859 if (sub.sub_library < sub.cmdsize) { 8860 const char *P = Ptr + sub.sub_library; 8861 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 8862 } else { 8863 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 8864 } 8865 } 8866 8867 static void PrintSubClientCommand(MachO::sub_client_command sub, 8868 const char *Ptr) { 8869 outs() << " cmd LC_SUB_CLIENT\n"; 8870 outs() << " cmdsize " << sub.cmdsize; 8871 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 8872 outs() << " Incorrect size\n"; 8873 else 8874 outs() << "\n"; 8875 if (sub.client < sub.cmdsize) { 8876 const char *P = Ptr + sub.client; 8877 outs() << " client " << P << " (offset " << sub.client << ")\n"; 8878 } else { 8879 outs() << " client ?(bad offset " << sub.client << ")\n"; 8880 } 8881 } 8882 8883 static void PrintRoutinesCommand(MachO::routines_command r) { 8884 outs() << " cmd LC_ROUTINES\n"; 8885 outs() << " cmdsize " << r.cmdsize; 8886 if (r.cmdsize != sizeof(struct MachO::routines_command)) 8887 outs() << " Incorrect size\n"; 8888 else 8889 outs() << "\n"; 8890 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 8891 outs() << " init_module " << r.init_module << "\n"; 8892 outs() << " reserved1 " << r.reserved1 << "\n"; 8893 outs() << " reserved2 " << r.reserved2 << "\n"; 8894 outs() << " reserved3 " << r.reserved3 << "\n"; 8895 outs() << " reserved4 " << r.reserved4 << "\n"; 8896 outs() << " reserved5 " << r.reserved5 << "\n"; 8897 outs() << " reserved6 " << r.reserved6 << "\n"; 8898 } 8899 8900 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 8901 outs() << " cmd LC_ROUTINES_64\n"; 8902 outs() << " cmdsize " << r.cmdsize; 8903 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 8904 outs() << " Incorrect size\n"; 8905 else 8906 outs() << "\n"; 8907 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 8908 outs() << " init_module " << r.init_module << "\n"; 8909 outs() << " reserved1 " << r.reserved1 << "\n"; 8910 outs() << " reserved2 " << r.reserved2 << "\n"; 8911 outs() << " reserved3 " << r.reserved3 << "\n"; 8912 outs() << " reserved4 " << r.reserved4 << "\n"; 8913 outs() << " reserved5 " << r.reserved5 << "\n"; 8914 outs() << " reserved6 " << r.reserved6 << "\n"; 8915 } 8916 8917 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 8918 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 8919 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 8920 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 8921 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 8922 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 8923 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 8924 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 8925 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 8926 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 8927 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 8928 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 8929 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 8930 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 8931 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 8932 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 8933 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 8934 } 8935 8936 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 8937 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 8938 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 8939 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 8940 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 8941 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 8942 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 8943 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 8944 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 8945 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 8946 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 8947 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 8948 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 8949 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 8950 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 8951 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 8952 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 8953 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 8954 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 8955 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 8956 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 8957 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 8958 } 8959 8960 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 8961 uint32_t f; 8962 outs() << "\t mmst_reg "; 8963 for (f = 0; f < 10; f++) 8964 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 8965 outs() << "\n"; 8966 outs() << "\t mmst_rsrv "; 8967 for (f = 0; f < 6; f++) 8968 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 8969 outs() << "\n"; 8970 } 8971 8972 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 8973 uint32_t f; 8974 outs() << "\t xmm_reg "; 8975 for (f = 0; f < 16; f++) 8976 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 8977 outs() << "\n"; 8978 } 8979 8980 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 8981 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 8982 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 8983 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 8984 outs() << " denorm " << fpu.fpu_fcw.denorm; 8985 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 8986 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 8987 outs() << " undfl " << fpu.fpu_fcw.undfl; 8988 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 8989 outs() << "\t\t pc "; 8990 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 8991 outs() << "FP_PREC_24B "; 8992 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 8993 outs() << "FP_PREC_53B "; 8994 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 8995 outs() << "FP_PREC_64B "; 8996 else 8997 outs() << fpu.fpu_fcw.pc << " "; 8998 outs() << "rc "; 8999 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 9000 outs() << "FP_RND_NEAR "; 9001 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 9002 outs() << "FP_RND_DOWN "; 9003 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 9004 outs() << "FP_RND_UP "; 9005 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 9006 outs() << "FP_CHOP "; 9007 outs() << "\n"; 9008 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 9009 outs() << " denorm " << fpu.fpu_fsw.denorm; 9010 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 9011 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 9012 outs() << " undfl " << fpu.fpu_fsw.undfl; 9013 outs() << " precis " << fpu.fpu_fsw.precis; 9014 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 9015 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9016 outs() << " c0 " << fpu.fpu_fsw.c0; 9017 outs() << " c1 " << fpu.fpu_fsw.c1; 9018 outs() << " c2 " << fpu.fpu_fsw.c2; 9019 outs() << " tos " << fpu.fpu_fsw.tos; 9020 outs() << " c3 " << fpu.fpu_fsw.c3; 9021 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9022 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9023 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9024 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9025 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9026 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9027 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9028 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9029 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9030 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9031 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9032 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9033 outs() << "\n"; 9034 outs() << "\t fpu_stmm0:\n"; 9035 Print_mmst_reg(fpu.fpu_stmm0); 9036 outs() << "\t fpu_stmm1:\n"; 9037 Print_mmst_reg(fpu.fpu_stmm1); 9038 outs() << "\t fpu_stmm2:\n"; 9039 Print_mmst_reg(fpu.fpu_stmm2); 9040 outs() << "\t fpu_stmm3:\n"; 9041 Print_mmst_reg(fpu.fpu_stmm3); 9042 outs() << "\t fpu_stmm4:\n"; 9043 Print_mmst_reg(fpu.fpu_stmm4); 9044 outs() << "\t fpu_stmm5:\n"; 9045 Print_mmst_reg(fpu.fpu_stmm5); 9046 outs() << "\t fpu_stmm6:\n"; 9047 Print_mmst_reg(fpu.fpu_stmm6); 9048 outs() << "\t fpu_stmm7:\n"; 9049 Print_mmst_reg(fpu.fpu_stmm7); 9050 outs() << "\t fpu_xmm0:\n"; 9051 Print_xmm_reg(fpu.fpu_xmm0); 9052 outs() << "\t fpu_xmm1:\n"; 9053 Print_xmm_reg(fpu.fpu_xmm1); 9054 outs() << "\t fpu_xmm2:\n"; 9055 Print_xmm_reg(fpu.fpu_xmm2); 9056 outs() << "\t fpu_xmm3:\n"; 9057 Print_xmm_reg(fpu.fpu_xmm3); 9058 outs() << "\t fpu_xmm4:\n"; 9059 Print_xmm_reg(fpu.fpu_xmm4); 9060 outs() << "\t fpu_xmm5:\n"; 9061 Print_xmm_reg(fpu.fpu_xmm5); 9062 outs() << "\t fpu_xmm6:\n"; 9063 Print_xmm_reg(fpu.fpu_xmm6); 9064 outs() << "\t fpu_xmm7:\n"; 9065 Print_xmm_reg(fpu.fpu_xmm7); 9066 outs() << "\t fpu_xmm8:\n"; 9067 Print_xmm_reg(fpu.fpu_xmm8); 9068 outs() << "\t fpu_xmm9:\n"; 9069 Print_xmm_reg(fpu.fpu_xmm9); 9070 outs() << "\t fpu_xmm10:\n"; 9071 Print_xmm_reg(fpu.fpu_xmm10); 9072 outs() << "\t fpu_xmm11:\n"; 9073 Print_xmm_reg(fpu.fpu_xmm11); 9074 outs() << "\t fpu_xmm12:\n"; 9075 Print_xmm_reg(fpu.fpu_xmm12); 9076 outs() << "\t fpu_xmm13:\n"; 9077 Print_xmm_reg(fpu.fpu_xmm13); 9078 outs() << "\t fpu_xmm14:\n"; 9079 Print_xmm_reg(fpu.fpu_xmm14); 9080 outs() << "\t fpu_xmm15:\n"; 9081 Print_xmm_reg(fpu.fpu_xmm15); 9082 outs() << "\t fpu_rsrv4:\n"; 9083 for (uint32_t f = 0; f < 6; f++) { 9084 outs() << "\t "; 9085 for (uint32_t g = 0; g < 16; g++) 9086 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9087 outs() << "\n"; 9088 } 9089 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9090 outs() << "\n"; 9091 } 9092 9093 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9094 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9095 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9096 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9097 } 9098 9099 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9100 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9101 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9102 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9103 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9104 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9105 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9106 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9107 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9108 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9109 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9110 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9111 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9112 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9113 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9114 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9115 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9116 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9117 } 9118 9119 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9120 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9121 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9122 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9123 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9124 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9125 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9126 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9127 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9128 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9129 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9130 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9131 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9132 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9133 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9134 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9135 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9136 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9137 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9138 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9139 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9140 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9141 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9142 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9143 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9144 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9145 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9146 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9147 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9148 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9149 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9150 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9151 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9152 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9153 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9154 } 9155 9156 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9157 bool isLittleEndian, uint32_t cputype) { 9158 if (t.cmd == MachO::LC_THREAD) 9159 outs() << " cmd LC_THREAD\n"; 9160 else if (t.cmd == MachO::LC_UNIXTHREAD) 9161 outs() << " cmd LC_UNIXTHREAD\n"; 9162 else 9163 outs() << " cmd " << t.cmd << " (unknown)\n"; 9164 outs() << " cmdsize " << t.cmdsize; 9165 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9166 outs() << " Incorrect size\n"; 9167 else 9168 outs() << "\n"; 9169 9170 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9171 const char *end = Ptr + t.cmdsize; 9172 uint32_t flavor, count, left; 9173 if (cputype == MachO::CPU_TYPE_I386) { 9174 while (begin < end) { 9175 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9176 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9177 begin += sizeof(uint32_t); 9178 } else { 9179 flavor = 0; 9180 begin = end; 9181 } 9182 if (isLittleEndian != sys::IsLittleEndianHost) 9183 sys::swapByteOrder(flavor); 9184 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9185 memcpy((char *)&count, begin, sizeof(uint32_t)); 9186 begin += sizeof(uint32_t); 9187 } else { 9188 count = 0; 9189 begin = end; 9190 } 9191 if (isLittleEndian != sys::IsLittleEndianHost) 9192 sys::swapByteOrder(count); 9193 if (flavor == MachO::x86_THREAD_STATE32) { 9194 outs() << " flavor i386_THREAD_STATE\n"; 9195 if (count == MachO::x86_THREAD_STATE32_COUNT) 9196 outs() << " count i386_THREAD_STATE_COUNT\n"; 9197 else 9198 outs() << " count " << count 9199 << " (not x86_THREAD_STATE32_COUNT)\n"; 9200 MachO::x86_thread_state32_t cpu32; 9201 left = end - begin; 9202 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9203 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9204 begin += sizeof(MachO::x86_thread_state32_t); 9205 } else { 9206 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9207 memcpy(&cpu32, begin, left); 9208 begin += left; 9209 } 9210 if (isLittleEndian != sys::IsLittleEndianHost) 9211 swapStruct(cpu32); 9212 Print_x86_thread_state32_t(cpu32); 9213 } else if (flavor == MachO::x86_THREAD_STATE) { 9214 outs() << " flavor x86_THREAD_STATE\n"; 9215 if (count == MachO::x86_THREAD_STATE_COUNT) 9216 outs() << " count x86_THREAD_STATE_COUNT\n"; 9217 else 9218 outs() << " count " << count 9219 << " (not x86_THREAD_STATE_COUNT)\n"; 9220 struct MachO::x86_thread_state_t ts; 9221 left = end - begin; 9222 if (left >= sizeof(MachO::x86_thread_state_t)) { 9223 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9224 begin += sizeof(MachO::x86_thread_state_t); 9225 } else { 9226 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9227 memcpy(&ts, begin, left); 9228 begin += left; 9229 } 9230 if (isLittleEndian != sys::IsLittleEndianHost) 9231 swapStruct(ts); 9232 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9233 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9234 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9235 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9236 else 9237 outs() << "tsh.count " << ts.tsh.count 9238 << " (not x86_THREAD_STATE32_COUNT\n"; 9239 Print_x86_thread_state32_t(ts.uts.ts32); 9240 } else { 9241 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9242 << ts.tsh.count << "\n"; 9243 } 9244 } else { 9245 outs() << " flavor " << flavor << " (unknown)\n"; 9246 outs() << " count " << count << "\n"; 9247 outs() << " state (unknown)\n"; 9248 begin += count * sizeof(uint32_t); 9249 } 9250 } 9251 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9252 while (begin < end) { 9253 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9254 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9255 begin += sizeof(uint32_t); 9256 } else { 9257 flavor = 0; 9258 begin = end; 9259 } 9260 if (isLittleEndian != sys::IsLittleEndianHost) 9261 sys::swapByteOrder(flavor); 9262 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9263 memcpy((char *)&count, begin, sizeof(uint32_t)); 9264 begin += sizeof(uint32_t); 9265 } else { 9266 count = 0; 9267 begin = end; 9268 } 9269 if (isLittleEndian != sys::IsLittleEndianHost) 9270 sys::swapByteOrder(count); 9271 if (flavor == MachO::x86_THREAD_STATE64) { 9272 outs() << " flavor x86_THREAD_STATE64\n"; 9273 if (count == MachO::x86_THREAD_STATE64_COUNT) 9274 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9275 else 9276 outs() << " count " << count 9277 << " (not x86_THREAD_STATE64_COUNT)\n"; 9278 MachO::x86_thread_state64_t cpu64; 9279 left = end - begin; 9280 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9281 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9282 begin += sizeof(MachO::x86_thread_state64_t); 9283 } else { 9284 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9285 memcpy(&cpu64, begin, left); 9286 begin += left; 9287 } 9288 if (isLittleEndian != sys::IsLittleEndianHost) 9289 swapStruct(cpu64); 9290 Print_x86_thread_state64_t(cpu64); 9291 } else if (flavor == MachO::x86_THREAD_STATE) { 9292 outs() << " flavor x86_THREAD_STATE\n"; 9293 if (count == MachO::x86_THREAD_STATE_COUNT) 9294 outs() << " count x86_THREAD_STATE_COUNT\n"; 9295 else 9296 outs() << " count " << count 9297 << " (not x86_THREAD_STATE_COUNT)\n"; 9298 struct MachO::x86_thread_state_t ts; 9299 left = end - begin; 9300 if (left >= sizeof(MachO::x86_thread_state_t)) { 9301 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9302 begin += sizeof(MachO::x86_thread_state_t); 9303 } else { 9304 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9305 memcpy(&ts, begin, left); 9306 begin += left; 9307 } 9308 if (isLittleEndian != sys::IsLittleEndianHost) 9309 swapStruct(ts); 9310 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9311 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9312 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9313 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9314 else 9315 outs() << "tsh.count " << ts.tsh.count 9316 << " (not x86_THREAD_STATE64_COUNT\n"; 9317 Print_x86_thread_state64_t(ts.uts.ts64); 9318 } else { 9319 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9320 << ts.tsh.count << "\n"; 9321 } 9322 } else if (flavor == MachO::x86_FLOAT_STATE) { 9323 outs() << " flavor x86_FLOAT_STATE\n"; 9324 if (count == MachO::x86_FLOAT_STATE_COUNT) 9325 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9326 else 9327 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9328 struct MachO::x86_float_state_t fs; 9329 left = end - begin; 9330 if (left >= sizeof(MachO::x86_float_state_t)) { 9331 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9332 begin += sizeof(MachO::x86_float_state_t); 9333 } else { 9334 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9335 memcpy(&fs, begin, left); 9336 begin += left; 9337 } 9338 if (isLittleEndian != sys::IsLittleEndianHost) 9339 swapStruct(fs); 9340 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9341 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9342 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9343 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9344 else 9345 outs() << "fsh.count " << fs.fsh.count 9346 << " (not x86_FLOAT_STATE64_COUNT\n"; 9347 Print_x86_float_state_t(fs.ufs.fs64); 9348 } else { 9349 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9350 << fs.fsh.count << "\n"; 9351 } 9352 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9353 outs() << " flavor x86_EXCEPTION_STATE\n"; 9354 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9355 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9356 else 9357 outs() << " count " << count 9358 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9359 struct MachO::x86_exception_state_t es; 9360 left = end - begin; 9361 if (left >= sizeof(MachO::x86_exception_state_t)) { 9362 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9363 begin += sizeof(MachO::x86_exception_state_t); 9364 } else { 9365 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9366 memcpy(&es, begin, left); 9367 begin += left; 9368 } 9369 if (isLittleEndian != sys::IsLittleEndianHost) 9370 swapStruct(es); 9371 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9372 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9373 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9374 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9375 else 9376 outs() << "\t esh.count " << es.esh.count 9377 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9378 Print_x86_exception_state_t(es.ues.es64); 9379 } else { 9380 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9381 << es.esh.count << "\n"; 9382 } 9383 } else if (flavor == MachO::x86_EXCEPTION_STATE64) { 9384 outs() << " flavor x86_EXCEPTION_STATE64\n"; 9385 if (count == MachO::x86_EXCEPTION_STATE64_COUNT) 9386 outs() << " count x86_EXCEPTION_STATE64_COUNT\n"; 9387 else 9388 outs() << " count " << count 9389 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; 9390 struct MachO::x86_exception_state64_t es64; 9391 left = end - begin; 9392 if (left >= sizeof(MachO::x86_exception_state64_t)) { 9393 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); 9394 begin += sizeof(MachO::x86_exception_state64_t); 9395 } else { 9396 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); 9397 memcpy(&es64, begin, left); 9398 begin += left; 9399 } 9400 if (isLittleEndian != sys::IsLittleEndianHost) 9401 swapStruct(es64); 9402 Print_x86_exception_state_t(es64); 9403 } else { 9404 outs() << " flavor " << flavor << " (unknown)\n"; 9405 outs() << " count " << count << "\n"; 9406 outs() << " state (unknown)\n"; 9407 begin += count * sizeof(uint32_t); 9408 } 9409 } 9410 } else if (cputype == MachO::CPU_TYPE_ARM) { 9411 while (begin < end) { 9412 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9413 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9414 begin += sizeof(uint32_t); 9415 } else { 9416 flavor = 0; 9417 begin = end; 9418 } 9419 if (isLittleEndian != sys::IsLittleEndianHost) 9420 sys::swapByteOrder(flavor); 9421 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9422 memcpy((char *)&count, begin, sizeof(uint32_t)); 9423 begin += sizeof(uint32_t); 9424 } else { 9425 count = 0; 9426 begin = end; 9427 } 9428 if (isLittleEndian != sys::IsLittleEndianHost) 9429 sys::swapByteOrder(count); 9430 if (flavor == MachO::ARM_THREAD_STATE) { 9431 outs() << " flavor ARM_THREAD_STATE\n"; 9432 if (count == MachO::ARM_THREAD_STATE_COUNT) 9433 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9434 else 9435 outs() << " count " << count 9436 << " (not ARM_THREAD_STATE_COUNT)\n"; 9437 MachO::arm_thread_state32_t cpu32; 9438 left = end - begin; 9439 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9440 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9441 begin += sizeof(MachO::arm_thread_state32_t); 9442 } else { 9443 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9444 memcpy(&cpu32, begin, left); 9445 begin += left; 9446 } 9447 if (isLittleEndian != sys::IsLittleEndianHost) 9448 swapStruct(cpu32); 9449 Print_arm_thread_state32_t(cpu32); 9450 } else { 9451 outs() << " flavor " << flavor << " (unknown)\n"; 9452 outs() << " count " << count << "\n"; 9453 outs() << " state (unknown)\n"; 9454 begin += count * sizeof(uint32_t); 9455 } 9456 } 9457 } else if (cputype == MachO::CPU_TYPE_ARM64) { 9458 while (begin < end) { 9459 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9460 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9461 begin += sizeof(uint32_t); 9462 } else { 9463 flavor = 0; 9464 begin = end; 9465 } 9466 if (isLittleEndian != sys::IsLittleEndianHost) 9467 sys::swapByteOrder(flavor); 9468 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9469 memcpy((char *)&count, begin, sizeof(uint32_t)); 9470 begin += sizeof(uint32_t); 9471 } else { 9472 count = 0; 9473 begin = end; 9474 } 9475 if (isLittleEndian != sys::IsLittleEndianHost) 9476 sys::swapByteOrder(count); 9477 if (flavor == MachO::ARM_THREAD_STATE64) { 9478 outs() << " flavor ARM_THREAD_STATE64\n"; 9479 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9480 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9481 else 9482 outs() << " count " << count 9483 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9484 MachO::arm_thread_state64_t cpu64; 9485 left = end - begin; 9486 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9487 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9488 begin += sizeof(MachO::arm_thread_state64_t); 9489 } else { 9490 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9491 memcpy(&cpu64, begin, left); 9492 begin += left; 9493 } 9494 if (isLittleEndian != sys::IsLittleEndianHost) 9495 swapStruct(cpu64); 9496 Print_arm_thread_state64_t(cpu64); 9497 } else { 9498 outs() << " flavor " << flavor << " (unknown)\n"; 9499 outs() << " count " << count << "\n"; 9500 outs() << " state (unknown)\n"; 9501 begin += count * sizeof(uint32_t); 9502 } 9503 } 9504 } else { 9505 while (begin < end) { 9506 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9507 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9508 begin += sizeof(uint32_t); 9509 } else { 9510 flavor = 0; 9511 begin = end; 9512 } 9513 if (isLittleEndian != sys::IsLittleEndianHost) 9514 sys::swapByteOrder(flavor); 9515 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9516 memcpy((char *)&count, begin, sizeof(uint32_t)); 9517 begin += sizeof(uint32_t); 9518 } else { 9519 count = 0; 9520 begin = end; 9521 } 9522 if (isLittleEndian != sys::IsLittleEndianHost) 9523 sys::swapByteOrder(count); 9524 outs() << " flavor " << flavor << "\n"; 9525 outs() << " count " << count << "\n"; 9526 outs() << " state (Unknown cputype/cpusubtype)\n"; 9527 begin += count * sizeof(uint32_t); 9528 } 9529 } 9530 } 9531 9532 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 9533 if (dl.cmd == MachO::LC_ID_DYLIB) 9534 outs() << " cmd LC_ID_DYLIB\n"; 9535 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 9536 outs() << " cmd LC_LOAD_DYLIB\n"; 9537 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 9538 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 9539 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 9540 outs() << " cmd LC_REEXPORT_DYLIB\n"; 9541 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 9542 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 9543 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 9544 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 9545 else 9546 outs() << " cmd " << dl.cmd << " (unknown)\n"; 9547 outs() << " cmdsize " << dl.cmdsize; 9548 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 9549 outs() << " Incorrect size\n"; 9550 else 9551 outs() << "\n"; 9552 if (dl.dylib.name < dl.cmdsize) { 9553 const char *P = (const char *)(Ptr) + dl.dylib.name; 9554 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 9555 } else { 9556 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 9557 } 9558 outs() << " time stamp " << dl.dylib.timestamp << " "; 9559 time_t t = dl.dylib.timestamp; 9560 outs() << ctime(&t); 9561 outs() << " current version "; 9562 if (dl.dylib.current_version == 0xffffffff) 9563 outs() << "n/a\n"; 9564 else 9565 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 9566 << ((dl.dylib.current_version >> 8) & 0xff) << "." 9567 << (dl.dylib.current_version & 0xff) << "\n"; 9568 outs() << "compatibility version "; 9569 if (dl.dylib.compatibility_version == 0xffffffff) 9570 outs() << "n/a\n"; 9571 else 9572 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 9573 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 9574 << (dl.dylib.compatibility_version & 0xff) << "\n"; 9575 } 9576 9577 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 9578 uint32_t object_size) { 9579 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 9580 outs() << " cmd LC_CODE_SIGNATURE\n"; 9581 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 9582 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 9583 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 9584 outs() << " cmd LC_FUNCTION_STARTS\n"; 9585 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 9586 outs() << " cmd LC_DATA_IN_CODE\n"; 9587 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 9588 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 9589 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 9590 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 9591 else 9592 outs() << " cmd " << ld.cmd << " (?)\n"; 9593 outs() << " cmdsize " << ld.cmdsize; 9594 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 9595 outs() << " Incorrect size\n"; 9596 else 9597 outs() << "\n"; 9598 outs() << " dataoff " << ld.dataoff; 9599 if (ld.dataoff > object_size) 9600 outs() << " (past end of file)\n"; 9601 else 9602 outs() << "\n"; 9603 outs() << " datasize " << ld.datasize; 9604 uint64_t big_size = ld.dataoff; 9605 big_size += ld.datasize; 9606 if (big_size > object_size) 9607 outs() << " (past end of file)\n"; 9608 else 9609 outs() << "\n"; 9610 } 9611 9612 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 9613 uint32_t cputype, bool verbose) { 9614 StringRef Buf = Obj->getData(); 9615 unsigned Index = 0; 9616 for (const auto &Command : Obj->load_commands()) { 9617 outs() << "Load command " << Index++ << "\n"; 9618 if (Command.C.cmd == MachO::LC_SEGMENT) { 9619 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 9620 const char *sg_segname = SLC.segname; 9621 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 9622 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 9623 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 9624 verbose); 9625 for (unsigned j = 0; j < SLC.nsects; j++) { 9626 MachO::section S = Obj->getSection(Command, j); 9627 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 9628 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 9629 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 9630 } 9631 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9632 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 9633 const char *sg_segname = SLC_64.segname; 9634 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 9635 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 9636 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 9637 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 9638 for (unsigned j = 0; j < SLC_64.nsects; j++) { 9639 MachO::section_64 S_64 = Obj->getSection64(Command, j); 9640 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 9641 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 9642 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 9643 sg_segname, filetype, Buf.size(), verbose); 9644 } 9645 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 9646 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9647 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 9648 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 9649 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 9650 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9651 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 9652 Obj->is64Bit()); 9653 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 9654 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 9655 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 9656 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 9657 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 9658 Command.C.cmd == MachO::LC_ID_DYLINKER || 9659 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 9660 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 9661 PrintDyldLoadCommand(Dyld, Command.Ptr); 9662 } else if (Command.C.cmd == MachO::LC_UUID) { 9663 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 9664 PrintUuidLoadCommand(Uuid); 9665 } else if (Command.C.cmd == MachO::LC_RPATH) { 9666 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 9667 PrintRpathLoadCommand(Rpath, Command.Ptr); 9668 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 9669 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 9670 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 9671 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 9672 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 9673 PrintVersionMinLoadCommand(Vd); 9674 } else if (Command.C.cmd == MachO::LC_NOTE) { 9675 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 9676 PrintNoteLoadCommand(Nt); 9677 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 9678 MachO::build_version_command Bv = 9679 Obj->getBuildVersionLoadCommand(Command); 9680 PrintBuildVersionLoadCommand(Obj, Bv); 9681 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 9682 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 9683 PrintSourceVersionCommand(Sd); 9684 } else if (Command.C.cmd == MachO::LC_MAIN) { 9685 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 9686 PrintEntryPointCommand(Ep); 9687 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 9688 MachO::encryption_info_command Ei = 9689 Obj->getEncryptionInfoCommand(Command); 9690 PrintEncryptionInfoCommand(Ei, Buf.size()); 9691 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 9692 MachO::encryption_info_command_64 Ei = 9693 Obj->getEncryptionInfoCommand64(Command); 9694 PrintEncryptionInfoCommand64(Ei, Buf.size()); 9695 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 9696 MachO::linker_option_command Lo = 9697 Obj->getLinkerOptionLoadCommand(Command); 9698 PrintLinkerOptionCommand(Lo, Command.Ptr); 9699 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 9700 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 9701 PrintSubFrameworkCommand(Sf, Command.Ptr); 9702 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 9703 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 9704 PrintSubUmbrellaCommand(Sf, Command.Ptr); 9705 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 9706 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 9707 PrintSubLibraryCommand(Sl, Command.Ptr); 9708 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 9709 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 9710 PrintSubClientCommand(Sc, Command.Ptr); 9711 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 9712 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 9713 PrintRoutinesCommand(Rc); 9714 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 9715 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 9716 PrintRoutinesCommand64(Rc); 9717 } else if (Command.C.cmd == MachO::LC_THREAD || 9718 Command.C.cmd == MachO::LC_UNIXTHREAD) { 9719 MachO::thread_command Tc = Obj->getThreadCommand(Command); 9720 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 9721 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 9722 Command.C.cmd == MachO::LC_ID_DYLIB || 9723 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 9724 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 9725 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 9726 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 9727 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 9728 PrintDylibCommand(Dl, Command.Ptr); 9729 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 9730 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 9731 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 9732 Command.C.cmd == MachO::LC_DATA_IN_CODE || 9733 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 9734 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 9735 MachO::linkedit_data_command Ld = 9736 Obj->getLinkeditDataLoadCommand(Command); 9737 PrintLinkEditDataCommand(Ld, Buf.size()); 9738 } else { 9739 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 9740 << ")\n"; 9741 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 9742 // TODO: get and print the raw bytes of the load command. 9743 } 9744 // TODO: print all the other kinds of load commands. 9745 } 9746 } 9747 9748 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 9749 if (Obj->is64Bit()) { 9750 MachO::mach_header_64 H_64; 9751 H_64 = Obj->getHeader64(); 9752 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 9753 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 9754 } else { 9755 MachO::mach_header H; 9756 H = Obj->getHeader(); 9757 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 9758 H.sizeofcmds, H.flags, verbose); 9759 } 9760 } 9761 9762 void llvm::printMachOFileHeader(const object::ObjectFile *Obj) { 9763 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9764 PrintMachHeader(file, !NonVerbose); 9765 } 9766 9767 void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) { 9768 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9769 uint32_t filetype = 0; 9770 uint32_t cputype = 0; 9771 if (file->is64Bit()) { 9772 MachO::mach_header_64 H_64; 9773 H_64 = file->getHeader64(); 9774 filetype = H_64.filetype; 9775 cputype = H_64.cputype; 9776 } else { 9777 MachO::mach_header H; 9778 H = file->getHeader(); 9779 filetype = H.filetype; 9780 cputype = H.cputype; 9781 } 9782 PrintLoadCommands(file, filetype, cputype, !NonVerbose); 9783 } 9784 9785 //===----------------------------------------------------------------------===// 9786 // export trie dumping 9787 //===----------------------------------------------------------------------===// 9788 9789 void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) { 9790 uint64_t BaseSegmentAddress = 0; 9791 for (const auto &Command : Obj->load_commands()) { 9792 if (Command.C.cmd == MachO::LC_SEGMENT) { 9793 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 9794 if (Seg.fileoff == 0 && Seg.filesize != 0) { 9795 BaseSegmentAddress = Seg.vmaddr; 9796 break; 9797 } 9798 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9799 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 9800 if (Seg.fileoff == 0 && Seg.filesize != 0) { 9801 BaseSegmentAddress = Seg.vmaddr; 9802 break; 9803 } 9804 } 9805 } 9806 Error Err = Error::success(); 9807 for (const llvm::object::ExportEntry &Entry : Obj->exports(Err)) { 9808 uint64_t Flags = Entry.flags(); 9809 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 9810 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 9811 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9812 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 9813 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9814 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 9815 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 9816 if (ReExport) 9817 outs() << "[re-export] "; 9818 else 9819 outs() << format("0x%08llX ", 9820 Entry.address() + BaseSegmentAddress); 9821 outs() << Entry.name(); 9822 if (WeakDef || ThreadLocal || Resolver || Abs) { 9823 bool NeedsComma = false; 9824 outs() << " ["; 9825 if (WeakDef) { 9826 outs() << "weak_def"; 9827 NeedsComma = true; 9828 } 9829 if (ThreadLocal) { 9830 if (NeedsComma) 9831 outs() << ", "; 9832 outs() << "per-thread"; 9833 NeedsComma = true; 9834 } 9835 if (Abs) { 9836 if (NeedsComma) 9837 outs() << ", "; 9838 outs() << "absolute"; 9839 NeedsComma = true; 9840 } 9841 if (Resolver) { 9842 if (NeedsComma) 9843 outs() << ", "; 9844 outs() << format("resolver=0x%08llX", Entry.other()); 9845 NeedsComma = true; 9846 } 9847 outs() << "]"; 9848 } 9849 if (ReExport) { 9850 StringRef DylibName = "unknown"; 9851 int Ordinal = Entry.other() - 1; 9852 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 9853 if (Entry.otherName().empty()) 9854 outs() << " (from " << DylibName << ")"; 9855 else 9856 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 9857 } 9858 outs() << "\n"; 9859 } 9860 if (Err) 9861 report_error(Obj->getFileName(), std::move(Err)); 9862 } 9863 9864 //===----------------------------------------------------------------------===// 9865 // rebase table dumping 9866 //===----------------------------------------------------------------------===// 9867 9868 void llvm::printMachORebaseTable(object::MachOObjectFile *Obj) { 9869 outs() << "segment section address type\n"; 9870 Error Err = Error::success(); 9871 for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 9872 StringRef SegmentName = Entry.segmentName(); 9873 StringRef SectionName = Entry.sectionName(); 9874 uint64_t Address = Entry.address(); 9875 9876 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 9877 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 9878 SegmentName.str().c_str(), SectionName.str().c_str(), 9879 Address, Entry.typeName().str().c_str()); 9880 } 9881 if (Err) 9882 report_error(Obj->getFileName(), std::move(Err)); 9883 } 9884 9885 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 9886 StringRef DylibName; 9887 switch (Ordinal) { 9888 case MachO::BIND_SPECIAL_DYLIB_SELF: 9889 return "this-image"; 9890 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 9891 return "main-executable"; 9892 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 9893 return "flat-namespace"; 9894 default: 9895 if (Ordinal > 0) { 9896 std::error_code EC = 9897 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 9898 if (EC) 9899 return "<<bad library ordinal>>"; 9900 return DylibName; 9901 } 9902 } 9903 return "<<unknown special ordinal>>"; 9904 } 9905 9906 //===----------------------------------------------------------------------===// 9907 // bind table dumping 9908 //===----------------------------------------------------------------------===// 9909 9910 void llvm::printMachOBindTable(object::MachOObjectFile *Obj) { 9911 // Build table of sections so names can used in final output. 9912 outs() << "segment section address type " 9913 "addend dylib symbol\n"; 9914 Error Err = Error::success(); 9915 for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 9916 StringRef SegmentName = Entry.segmentName(); 9917 StringRef SectionName = Entry.sectionName(); 9918 uint64_t Address = Entry.address(); 9919 9920 // Table lines look like: 9921 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 9922 StringRef Attr; 9923 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 9924 Attr = " (weak_import)"; 9925 outs() << left_justify(SegmentName, 8) << " " 9926 << left_justify(SectionName, 18) << " " 9927 << format_hex(Address, 10, true) << " " 9928 << left_justify(Entry.typeName(), 8) << " " 9929 << format_decimal(Entry.addend(), 8) << " " 9930 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9931 << Entry.symbolName() << Attr << "\n"; 9932 } 9933 if (Err) 9934 report_error(Obj->getFileName(), std::move(Err)); 9935 } 9936 9937 //===----------------------------------------------------------------------===// 9938 // lazy bind table dumping 9939 //===----------------------------------------------------------------------===// 9940 9941 void llvm::printMachOLazyBindTable(object::MachOObjectFile *Obj) { 9942 outs() << "segment section address " 9943 "dylib symbol\n"; 9944 Error Err = Error::success(); 9945 for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 9946 StringRef SegmentName = Entry.segmentName(); 9947 StringRef SectionName = Entry.sectionName(); 9948 uint64_t Address = Entry.address(); 9949 9950 // Table lines look like: 9951 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 9952 outs() << left_justify(SegmentName, 8) << " " 9953 << left_justify(SectionName, 18) << " " 9954 << format_hex(Address, 10, true) << " " 9955 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9956 << Entry.symbolName() << "\n"; 9957 } 9958 if (Err) 9959 report_error(Obj->getFileName(), std::move(Err)); 9960 } 9961 9962 //===----------------------------------------------------------------------===// 9963 // weak bind table dumping 9964 //===----------------------------------------------------------------------===// 9965 9966 void llvm::printMachOWeakBindTable(object::MachOObjectFile *Obj) { 9967 outs() << "segment section address " 9968 "type addend symbol\n"; 9969 Error Err = Error::success(); 9970 for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 9971 // Strong symbols don't have a location to update. 9972 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 9973 outs() << " strong " 9974 << Entry.symbolName() << "\n"; 9975 continue; 9976 } 9977 StringRef SegmentName = Entry.segmentName(); 9978 StringRef SectionName = Entry.sectionName(); 9979 uint64_t Address = Entry.address(); 9980 9981 // Table lines look like: 9982 // __DATA __data 0x00001000 pointer 0 _foo 9983 outs() << left_justify(SegmentName, 8) << " " 9984 << left_justify(SectionName, 18) << " " 9985 << format_hex(Address, 10, true) << " " 9986 << left_justify(Entry.typeName(), 8) << " " 9987 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 9988 << "\n"; 9989 } 9990 if (Err) 9991 report_error(Obj->getFileName(), std::move(Err)); 9992 } 9993 9994 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 9995 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 9996 // information for that address. If the address is found its binding symbol 9997 // name is returned. If not nullptr is returned. 9998 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 9999 struct DisassembleInfo *info) { 10000 if (info->bindtable == nullptr) { 10001 info->bindtable = llvm::make_unique<SymbolAddressMap>(); 10002 Error Err = Error::success(); 10003 for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 10004 uint64_t Address = Entry.address(); 10005 StringRef name = Entry.symbolName(); 10006 if (!name.empty()) 10007 (*info->bindtable)[Address] = name; 10008 } 10009 if (Err) 10010 report_error(info->O->getFileName(), std::move(Err)); 10011 } 10012 auto name = info->bindtable->lookup(ReferenceValue); 10013 return !name.empty() ? name.data() : nullptr; 10014 } 10015 10016