1 //===-- MachODump.cpp - Object file dumping utility for llvm --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the MachO-specific dumper for llvm-objdump. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm-objdump.h" 15 #include "llvm-c/Disassembler.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/BinaryFormat/MachO.h" 20 #include "llvm/Config/config.h" 21 #include "llvm/DebugInfo/DIContext.h" 22 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 23 #include "llvm/Demangle/Demangle.h" 24 #include "llvm/MC/MCAsmInfo.h" 25 #include "llvm/MC/MCContext.h" 26 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 27 #include "llvm/MC/MCInst.h" 28 #include "llvm/MC/MCInstPrinter.h" 29 #include "llvm/MC/MCInstrDesc.h" 30 #include "llvm/MC/MCInstrInfo.h" 31 #include "llvm/MC/MCRegisterInfo.h" 32 #include "llvm/MC/MCSubtargetInfo.h" 33 #include "llvm/Object/MachO.h" 34 #include "llvm/Object/MachOUniversal.h" 35 #include "llvm/Support/Casting.h" 36 #include "llvm/Support/CommandLine.h" 37 #include "llvm/Support/Debug.h" 38 #include "llvm/Support/Endian.h" 39 #include "llvm/Support/Format.h" 40 #include "llvm/Support/FormattedStream.h" 41 #include "llvm/Support/GraphWriter.h" 42 #include "llvm/Support/LEB128.h" 43 #include "llvm/Support/MemoryBuffer.h" 44 #include "llvm/Support/TargetRegistry.h" 45 #include "llvm/Support/TargetSelect.h" 46 #include "llvm/Support/ToolOutputFile.h" 47 #include "llvm/Support/raw_ostream.h" 48 #include <algorithm> 49 #include <cstring> 50 #include <system_error> 51 52 #ifdef HAVE_LIBXAR 53 extern "C" { 54 #include <xar/xar.h> 55 } 56 #endif 57 58 using namespace llvm; 59 using namespace object; 60 61 static cl::opt<bool> 62 UseDbg("g", 63 cl::desc("Print line information from debug info if available")); 64 65 static cl::opt<std::string> DSYMFile("dsym", 66 cl::desc("Use .dSYM file for debug info")); 67 68 static cl::opt<bool> FullLeadingAddr("full-leading-addr", 69 cl::desc("Print full leading address")); 70 71 static cl::opt<bool> NoLeadingHeaders("no-leading-headers", 72 cl::desc("Print no leading headers")); 73 74 cl::opt<bool> llvm::UniversalHeaders("universal-headers", 75 cl::desc("Print Mach-O universal headers " 76 "(requires -macho)")); 77 78 cl::opt<bool> 79 llvm::ArchiveHeaders("archive-headers", 80 cl::desc("Print archive headers for Mach-O archives " 81 "(requires -macho)")); 82 83 cl::opt<bool> 84 ArchiveMemberOffsets("archive-member-offsets", 85 cl::desc("Print the offset to each archive member for " 86 "Mach-O archives (requires -macho and " 87 "-archive-headers)")); 88 89 cl::opt<bool> 90 llvm::IndirectSymbols("indirect-symbols", 91 cl::desc("Print indirect symbol table for Mach-O " 92 "objects (requires -macho)")); 93 94 cl::opt<bool> 95 llvm::DataInCode("data-in-code", 96 cl::desc("Print the data in code table for Mach-O objects " 97 "(requires -macho)")); 98 99 cl::opt<bool> 100 llvm::LinkOptHints("link-opt-hints", 101 cl::desc("Print the linker optimization hints for " 102 "Mach-O objects (requires -macho)")); 103 104 cl::opt<bool> 105 llvm::InfoPlist("info-plist", 106 cl::desc("Print the info plist section as strings for " 107 "Mach-O objects (requires -macho)")); 108 109 cl::opt<bool> 110 llvm::DylibsUsed("dylibs-used", 111 cl::desc("Print the shared libraries used for linked " 112 "Mach-O files (requires -macho)")); 113 114 cl::opt<bool> 115 llvm::DylibId("dylib-id", 116 cl::desc("Print the shared library's id for the dylib Mach-O " 117 "file (requires -macho)")); 118 119 cl::opt<bool> 120 llvm::NonVerbose("non-verbose", 121 cl::desc("Print the info for Mach-O objects in " 122 "non-verbose or numeric form (requires -macho)")); 123 124 cl::opt<bool> 125 llvm::ObjcMetaData("objc-meta-data", 126 cl::desc("Print the Objective-C runtime meta data for " 127 "Mach-O files (requires -macho)")); 128 129 cl::opt<std::string> llvm::DisSymName( 130 "dis-symname", 131 cl::desc("disassemble just this symbol's instructions (requires -macho)")); 132 133 static cl::opt<bool> NoSymbolicOperands( 134 "no-symbolic-operands", 135 cl::desc("do not symbolic operands when disassembling (requires -macho)")); 136 137 static cl::list<std::string> 138 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 139 cl::ZeroOrMore); 140 141 bool ArchAll = false; 142 143 static std::string ThumbTripleName; 144 145 static const Target *GetTarget(const MachOObjectFile *MachOObj, 146 const char **McpuDefault, 147 const Target **ThumbTarget) { 148 // Figure out the target triple. 149 llvm::Triple TT(TripleName); 150 if (TripleName.empty()) { 151 TT = MachOObj->getArchTriple(McpuDefault); 152 TripleName = TT.str(); 153 } 154 155 if (TT.getArch() == Triple::arm) { 156 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs 157 // that support ARM are also capable of Thumb mode. 158 llvm::Triple ThumbTriple = TT; 159 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str(); 160 ThumbTriple.setArchName(ThumbName); 161 ThumbTripleName = ThumbTriple.str(); 162 } 163 164 // Get the target specific parser. 165 std::string Error; 166 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 167 if (TheTarget && ThumbTripleName.empty()) 168 return TheTarget; 169 170 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 171 if (*ThumbTarget) 172 return TheTarget; 173 174 errs() << "llvm-objdump: error: unable to get target for '"; 175 if (!TheTarget) 176 errs() << TripleName; 177 else 178 errs() << ThumbTripleName; 179 errs() << "', see --version and --triple.\n"; 180 return nullptr; 181 } 182 183 struct SymbolSorter { 184 bool operator()(const SymbolRef &A, const SymbolRef &B) { 185 Expected<SymbolRef::Type> ATypeOrErr = A.getType(); 186 if (!ATypeOrErr) 187 report_error(A.getObject()->getFileName(), ATypeOrErr.takeError()); 188 SymbolRef::Type AType = *ATypeOrErr; 189 Expected<SymbolRef::Type> BTypeOrErr = B.getType(); 190 if (!BTypeOrErr) 191 report_error(B.getObject()->getFileName(), BTypeOrErr.takeError()); 192 SymbolRef::Type BType = *BTypeOrErr; 193 uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue(); 194 uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue(); 195 return AAddr < BAddr; 196 } 197 }; 198 199 // Types for the storted data in code table that is built before disassembly 200 // and the predicate function to sort them. 201 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 202 typedef std::vector<DiceTableEntry> DiceTable; 203 typedef DiceTable::iterator dice_table_iterator; 204 205 #ifdef HAVE_LIBXAR 206 namespace { 207 struct ScopedXarFile { 208 xar_t xar; 209 ScopedXarFile(const char *filename, int32_t flags) 210 : xar(xar_open(filename, flags)) {} 211 ~ScopedXarFile() { 212 if (xar) 213 xar_close(xar); 214 } 215 ScopedXarFile(const ScopedXarFile &) = delete; 216 ScopedXarFile &operator=(const ScopedXarFile &) = delete; 217 operator xar_t() { return xar; } 218 }; 219 220 struct ScopedXarIter { 221 xar_iter_t iter; 222 ScopedXarIter() : iter(xar_iter_new()) {} 223 ~ScopedXarIter() { 224 if (iter) 225 xar_iter_free(iter); 226 } 227 ScopedXarIter(const ScopedXarIter &) = delete; 228 ScopedXarIter &operator=(const ScopedXarIter &) = delete; 229 operator xar_iter_t() { return iter; } 230 }; 231 } // namespace 232 #endif // defined(HAVE_LIBXAR) 233 234 // This is used to search for a data in code table entry for the PC being 235 // disassembled. The j parameter has the PC in j.first. A single data in code 236 // table entry can cover many bytes for each of its Kind's. So if the offset, 237 // aka the i.first value, of the data in code table entry plus its Length 238 // covers the PC being searched for this will return true. If not it will 239 // return false. 240 static bool compareDiceTableEntries(const DiceTableEntry &i, 241 const DiceTableEntry &j) { 242 uint16_t Length; 243 i.second.getLength(Length); 244 245 return j.first >= i.first && j.first < i.first + Length; 246 } 247 248 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 249 unsigned short Kind) { 250 uint32_t Value, Size = 1; 251 252 switch (Kind) { 253 default: 254 case MachO::DICE_KIND_DATA: 255 if (Length >= 4) { 256 if (!NoShowRawInsn) 257 dumpBytes(makeArrayRef(bytes, 4), outs()); 258 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 259 outs() << "\t.long " << Value; 260 Size = 4; 261 } else if (Length >= 2) { 262 if (!NoShowRawInsn) 263 dumpBytes(makeArrayRef(bytes, 2), outs()); 264 Value = bytes[1] << 8 | bytes[0]; 265 outs() << "\t.short " << Value; 266 Size = 2; 267 } else { 268 if (!NoShowRawInsn) 269 dumpBytes(makeArrayRef(bytes, 2), outs()); 270 Value = bytes[0]; 271 outs() << "\t.byte " << Value; 272 Size = 1; 273 } 274 if (Kind == MachO::DICE_KIND_DATA) 275 outs() << "\t@ KIND_DATA\n"; 276 else 277 outs() << "\t@ data in code kind = " << Kind << "\n"; 278 break; 279 case MachO::DICE_KIND_JUMP_TABLE8: 280 if (!NoShowRawInsn) 281 dumpBytes(makeArrayRef(bytes, 1), outs()); 282 Value = bytes[0]; 283 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 284 Size = 1; 285 break; 286 case MachO::DICE_KIND_JUMP_TABLE16: 287 if (!NoShowRawInsn) 288 dumpBytes(makeArrayRef(bytes, 2), outs()); 289 Value = bytes[1] << 8 | bytes[0]; 290 outs() << "\t.short " << format("%5u", Value & 0xffff) 291 << "\t@ KIND_JUMP_TABLE16\n"; 292 Size = 2; 293 break; 294 case MachO::DICE_KIND_JUMP_TABLE32: 295 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 296 if (!NoShowRawInsn) 297 dumpBytes(makeArrayRef(bytes, 4), outs()); 298 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 299 outs() << "\t.long " << Value; 300 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 301 outs() << "\t@ KIND_JUMP_TABLE32\n"; 302 else 303 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 304 Size = 4; 305 break; 306 } 307 return Size; 308 } 309 310 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 311 std::vector<SectionRef> &Sections, 312 std::vector<SymbolRef> &Symbols, 313 SmallVectorImpl<uint64_t> &FoundFns, 314 uint64_t &BaseSegmentAddress) { 315 for (const SymbolRef &Symbol : MachOObj->symbols()) { 316 Expected<StringRef> SymName = Symbol.getName(); 317 if (!SymName) 318 report_error(MachOObj->getFileName(), SymName.takeError()); 319 if (!SymName->startswith("ltmp")) 320 Symbols.push_back(Symbol); 321 } 322 323 for (const SectionRef &Section : MachOObj->sections()) { 324 StringRef SectName; 325 Section.getName(SectName); 326 Sections.push_back(Section); 327 } 328 329 bool BaseSegmentAddressSet = false; 330 for (const auto &Command : MachOObj->load_commands()) { 331 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 332 // We found a function starts segment, parse the addresses for later 333 // consumption. 334 MachO::linkedit_data_command LLC = 335 MachOObj->getLinkeditDataLoadCommand(Command); 336 337 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 338 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 339 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 340 StringRef SegName = SLC.segname; 341 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 342 BaseSegmentAddressSet = true; 343 BaseSegmentAddress = SLC.vmaddr; 344 } 345 } 346 } 347 } 348 349 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 350 uint32_t n, uint32_t count, 351 uint32_t stride, uint64_t addr) { 352 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 353 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 354 if (n > nindirectsyms) 355 outs() << " (entries start past the end of the indirect symbol " 356 "table) (reserved1 field greater than the table size)"; 357 else if (n + count > nindirectsyms) 358 outs() << " (entries extends past the end of the indirect symbol " 359 "table)"; 360 outs() << "\n"; 361 uint32_t cputype = O->getHeader().cputype; 362 if (cputype & MachO::CPU_ARCH_ABI64) 363 outs() << "address index"; 364 else 365 outs() << "address index"; 366 if (verbose) 367 outs() << " name\n"; 368 else 369 outs() << "\n"; 370 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 371 if (cputype & MachO::CPU_ARCH_ABI64) 372 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 373 else 374 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 375 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 376 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 377 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 378 outs() << "LOCAL\n"; 379 continue; 380 } 381 if (indirect_symbol == 382 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 383 outs() << "LOCAL ABSOLUTE\n"; 384 continue; 385 } 386 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 387 outs() << "ABSOLUTE\n"; 388 continue; 389 } 390 outs() << format("%5u ", indirect_symbol); 391 if (verbose) { 392 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 393 if (indirect_symbol < Symtab.nsyms) { 394 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 395 SymbolRef Symbol = *Sym; 396 Expected<StringRef> SymName = Symbol.getName(); 397 if (!SymName) 398 report_error(O->getFileName(), SymName.takeError()); 399 outs() << *SymName; 400 } else { 401 outs() << "?"; 402 } 403 } 404 outs() << "\n"; 405 } 406 } 407 408 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 409 for (const auto &Load : O->load_commands()) { 410 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 411 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 412 for (unsigned J = 0; J < Seg.nsects; ++J) { 413 MachO::section_64 Sec = O->getSection64(Load, J); 414 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 415 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 416 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 417 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 418 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 419 section_type == MachO::S_SYMBOL_STUBS) { 420 uint32_t stride; 421 if (section_type == MachO::S_SYMBOL_STUBS) 422 stride = Sec.reserved2; 423 else 424 stride = 8; 425 if (stride == 0) { 426 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 427 << Sec.sectname << ") " 428 << "(size of stubs in reserved2 field is zero)\n"; 429 continue; 430 } 431 uint32_t count = Sec.size / stride; 432 outs() << "Indirect symbols for (" << Sec.segname << "," 433 << Sec.sectname << ") " << count << " entries"; 434 uint32_t n = Sec.reserved1; 435 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 436 } 437 } 438 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 439 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 440 for (unsigned J = 0; J < Seg.nsects; ++J) { 441 MachO::section Sec = O->getSection(Load, J); 442 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 443 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 444 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 445 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 446 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 447 section_type == MachO::S_SYMBOL_STUBS) { 448 uint32_t stride; 449 if (section_type == MachO::S_SYMBOL_STUBS) 450 stride = Sec.reserved2; 451 else 452 stride = 4; 453 if (stride == 0) { 454 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 455 << Sec.sectname << ") " 456 << "(size of stubs in reserved2 field is zero)\n"; 457 continue; 458 } 459 uint32_t count = Sec.size / stride; 460 outs() << "Indirect symbols for (" << Sec.segname << "," 461 << Sec.sectname << ") " << count << " entries"; 462 uint32_t n = Sec.reserved1; 463 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 464 } 465 } 466 } 467 } 468 } 469 470 static void PrintRType(const uint64_t cputype, const unsigned r_type) { 471 static char const *generic_r_types[] = { 472 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ", 473 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", 474 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 475 }; 476 static char const *x86_64_r_types[] = { 477 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", 478 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ", 479 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 480 }; 481 static char const *arm_r_types[] = { 482 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", 483 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ", 484 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 485 }; 486 static char const *arm64_r_types[] = { 487 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", 488 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", 489 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 490 }; 491 492 if (r_type > 0xf){ 493 outs() << format("%-7u", r_type) << " "; 494 return; 495 } 496 switch (cputype) { 497 case MachO::CPU_TYPE_I386: 498 outs() << generic_r_types[r_type]; 499 break; 500 case MachO::CPU_TYPE_X86_64: 501 outs() << x86_64_r_types[r_type]; 502 break; 503 case MachO::CPU_TYPE_ARM: 504 outs() << arm_r_types[r_type]; 505 break; 506 case MachO::CPU_TYPE_ARM64: 507 outs() << arm64_r_types[r_type]; 508 break; 509 default: 510 outs() << format("%-7u ", r_type); 511 } 512 } 513 514 static void PrintRLength(const uint64_t cputype, const unsigned r_type, 515 const unsigned r_length, const bool previous_arm_half){ 516 if (cputype == MachO::CPU_TYPE_ARM && 517 (r_type == llvm::MachO::ARM_RELOC_HALF || 518 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF || 519 previous_arm_half == true)) { 520 if ((r_length & 0x1) == 0) 521 outs() << "lo/"; 522 else 523 outs() << "hi/"; 524 if ((r_length & 0x1) == 0) 525 outs() << "arm "; 526 else 527 outs() << "thm "; 528 } else { 529 switch (r_length) { 530 case 0: 531 outs() << "byte "; 532 break; 533 case 1: 534 outs() << "word "; 535 break; 536 case 2: 537 outs() << "long "; 538 break; 539 case 3: 540 if (cputype == MachO::CPU_TYPE_X86_64) 541 outs() << "quad "; 542 else 543 outs() << format("?(%2d) ", r_length); 544 break; 545 default: 546 outs() << format("?(%2d) ", r_length); 547 } 548 } 549 } 550 551 static void PrintRelocationEntries(const MachOObjectFile *O, 552 const relocation_iterator Begin, 553 const relocation_iterator End, 554 const uint64_t cputype, 555 const bool verbose) { 556 const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 557 bool previous_arm_half = false; 558 bool previous_sectdiff = false; 559 uint32_t sectdiff_r_type = 0; 560 561 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { 562 const DataRefImpl Rel = Reloc->getRawDataRefImpl(); 563 const MachO::any_relocation_info RE = O->getRelocation(Rel); 564 const unsigned r_type = O->getAnyRelocationType(RE); 565 const bool r_scattered = O->isRelocationScattered(RE); 566 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); 567 const unsigned r_length = O->getAnyRelocationLength(RE); 568 const unsigned r_address = O->getAnyRelocationAddress(RE); 569 const bool r_extern = (r_scattered ? false : 570 O->getPlainRelocationExternal(RE)); 571 const uint32_t r_value = (r_scattered ? 572 O->getScatteredRelocationValue(RE) : 0); 573 const unsigned r_symbolnum = (r_scattered ? 0 : 574 O->getPlainRelocationSymbolNum(RE)); 575 576 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { 577 if (verbose) { 578 // scattered: address 579 if ((cputype == MachO::CPU_TYPE_I386 && 580 r_type == llvm::MachO::GENERIC_RELOC_PAIR) || 581 (cputype == MachO::CPU_TYPE_ARM && 582 r_type == llvm::MachO::ARM_RELOC_PAIR)) 583 outs() << " "; 584 else 585 outs() << format("%08x ", (unsigned int)r_address); 586 587 // scattered: pcrel 588 if (r_pcrel) 589 outs() << "True "; 590 else 591 outs() << "False "; 592 593 // scattered: length 594 PrintRLength(cputype, r_type, r_length, previous_arm_half); 595 596 // scattered: extern & type 597 outs() << "n/a "; 598 PrintRType(cputype, r_type); 599 600 // scattered: scattered & value 601 outs() << format("True 0x%08x", (unsigned int)r_value); 602 if (previous_sectdiff == false) { 603 if ((cputype == MachO::CPU_TYPE_ARM && 604 r_type == llvm::MachO::ARM_RELOC_PAIR)) 605 outs() << format(" half = 0x%04x ", (unsigned int)r_address); 606 } 607 else if (cputype == MachO::CPU_TYPE_ARM && 608 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF) 609 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); 610 if ((cputype == MachO::CPU_TYPE_I386 && 611 (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF || 612 r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || 613 (cputype == MachO::CPU_TYPE_ARM && 614 (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF || 615 sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF || 616 sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) { 617 previous_sectdiff = true; 618 sectdiff_r_type = r_type; 619 } 620 else { 621 previous_sectdiff = false; 622 sectdiff_r_type = 0; 623 } 624 if (cputype == MachO::CPU_TYPE_ARM && 625 (r_type == llvm::MachO::ARM_RELOC_HALF || 626 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) 627 previous_arm_half = true; 628 else 629 previous_arm_half = false; 630 outs() << "\n"; 631 } 632 else { 633 // scattered: address pcrel length extern type scattered value 634 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n", 635 (unsigned int)r_address, r_pcrel, r_length, r_type, 636 (unsigned int)r_value); 637 } 638 } 639 else { 640 if (verbose) { 641 // plain: address 642 if (cputype == MachO::CPU_TYPE_ARM && 643 r_type == llvm::MachO::ARM_RELOC_PAIR) 644 outs() << " "; 645 else 646 outs() << format("%08x ", (unsigned int)r_address); 647 648 // plain: pcrel 649 if (r_pcrel) 650 outs() << "True "; 651 else 652 outs() << "False "; 653 654 // plain: length 655 PrintRLength(cputype, r_type, r_length, previous_arm_half); 656 657 if (r_extern) { 658 // plain: extern & type & scattered 659 outs() << "True "; 660 PrintRType(cputype, r_type); 661 outs() << "False "; 662 663 // plain: symbolnum/value 664 if (r_symbolnum > Symtab.nsyms) 665 outs() << format("?(%d)\n", r_symbolnum); 666 else { 667 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); 668 Expected<StringRef> SymNameNext = Symbol.getName(); 669 const char *name = NULL; 670 if (SymNameNext) 671 name = SymNameNext->data(); 672 if (name == NULL) 673 outs() << format("?(%d)\n", r_symbolnum); 674 else 675 outs() << name << "\n"; 676 } 677 } 678 else { 679 // plain: extern & type & scattered 680 outs() << "False "; 681 PrintRType(cputype, r_type); 682 outs() << "False "; 683 684 // plain: symbolnum/value 685 if (cputype == MachO::CPU_TYPE_ARM && 686 r_type == llvm::MachO::ARM_RELOC_PAIR) 687 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); 688 else if (cputype == MachO::CPU_TYPE_ARM64 && 689 r_type == llvm::MachO::ARM64_RELOC_ADDEND) 690 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); 691 else { 692 outs() << format("%d ", r_symbolnum); 693 if (r_symbolnum == llvm::MachO::R_ABS) 694 outs() << "R_ABS\n"; 695 else { 696 // in this case, r_symbolnum is actually a 1-based section number 697 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; 698 if (r_symbolnum > 0 && r_symbolnum <= nsects) { 699 llvm::object::DataRefImpl DRI; 700 DRI.d.a = r_symbolnum-1; 701 StringRef SegName = O->getSectionFinalSegmentName(DRI); 702 StringRef SectName; 703 if (O->getSectionName(DRI, SectName)) 704 outs() << "(?,?)\n"; 705 else 706 outs() << "(" << SegName << "," << SectName << ")\n"; 707 } 708 else { 709 outs() << "(?,?)\n"; 710 } 711 } 712 } 713 } 714 if (cputype == MachO::CPU_TYPE_ARM && 715 (r_type == llvm::MachO::ARM_RELOC_HALF || 716 r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)) 717 previous_arm_half = true; 718 else 719 previous_arm_half = false; 720 } 721 else { 722 // plain: address pcrel length extern type scattered symbolnum/section 723 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n", 724 (unsigned int)r_address, r_pcrel, r_length, r_extern, 725 r_type, r_symbolnum); 726 } 727 } 728 } 729 } 730 731 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { 732 const uint64_t cputype = O->getHeader().cputype; 733 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 734 if (Dysymtab.nextrel != 0) { 735 outs() << "External relocation information " << Dysymtab.nextrel 736 << " entries"; 737 outs() << "\naddress pcrel length extern type scattered " 738 "symbolnum/value\n"; 739 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, 740 verbose); 741 } 742 if (Dysymtab.nlocrel != 0) { 743 outs() << format("Local relocation information %u entries", 744 Dysymtab.nlocrel); 745 outs() << "\naddress pcrel length extern type scattered " 746 "symbolnum/value\n"; 747 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, 748 verbose); 749 } 750 for (const auto &Load : O->load_commands()) { 751 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 752 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 753 for (unsigned J = 0; J < Seg.nsects; ++J) { 754 const MachO::section_64 Sec = O->getSection64(Load, J); 755 if (Sec.nreloc != 0) { 756 DataRefImpl DRI; 757 DRI.d.a = J; 758 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 759 StringRef SectName; 760 if (O->getSectionName(DRI, SectName)) 761 outs() << "Relocation information (" << SegName << ",?) " 762 << format("%u entries", Sec.nreloc); 763 else 764 outs() << "Relocation information (" << SegName << "," 765 << SectName << format(") %u entries", Sec.nreloc); 766 outs() << "\naddress pcrel length extern type scattered " 767 "symbolnum/value\n"; 768 PrintRelocationEntries(O, O->section_rel_begin(DRI), 769 O->section_rel_end(DRI), cputype, verbose); 770 } 771 } 772 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 773 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 774 for (unsigned J = 0; J < Seg.nsects; ++J) { 775 const MachO::section Sec = O->getSection(Load, J); 776 if (Sec.nreloc != 0) { 777 DataRefImpl DRI; 778 DRI.d.a = J; 779 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 780 StringRef SectName; 781 if (O->getSectionName(DRI, SectName)) 782 outs() << "Relocation information (" << SegName << ",?) " 783 << format("%u entries", Sec.nreloc); 784 else 785 outs() << "Relocation information (" << SegName << "," 786 << SectName << format(") %u entries", Sec.nreloc); 787 outs() << "\naddress pcrel length extern type scattered " 788 "symbolnum/value\n"; 789 PrintRelocationEntries(O, O->section_rel_begin(DRI), 790 O->section_rel_end(DRI), cputype, verbose); 791 } 792 } 793 } 794 } 795 } 796 797 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 798 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 799 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 800 outs() << "Data in code table (" << nentries << " entries)\n"; 801 outs() << "offset length kind\n"; 802 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 803 ++DI) { 804 uint32_t Offset; 805 DI->getOffset(Offset); 806 outs() << format("0x%08" PRIx32, Offset) << " "; 807 uint16_t Length; 808 DI->getLength(Length); 809 outs() << format("%6u", Length) << " "; 810 uint16_t Kind; 811 DI->getKind(Kind); 812 if (verbose) { 813 switch (Kind) { 814 case MachO::DICE_KIND_DATA: 815 outs() << "DATA"; 816 break; 817 case MachO::DICE_KIND_JUMP_TABLE8: 818 outs() << "JUMP_TABLE8"; 819 break; 820 case MachO::DICE_KIND_JUMP_TABLE16: 821 outs() << "JUMP_TABLE16"; 822 break; 823 case MachO::DICE_KIND_JUMP_TABLE32: 824 outs() << "JUMP_TABLE32"; 825 break; 826 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 827 outs() << "ABS_JUMP_TABLE32"; 828 break; 829 default: 830 outs() << format("0x%04" PRIx32, Kind); 831 break; 832 } 833 } else 834 outs() << format("0x%04" PRIx32, Kind); 835 outs() << "\n"; 836 } 837 } 838 839 static void PrintLinkOptHints(MachOObjectFile *O) { 840 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 841 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 842 uint32_t nloh = LohLC.datasize; 843 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 844 for (uint32_t i = 0; i < nloh;) { 845 unsigned n; 846 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 847 i += n; 848 outs() << " identifier " << identifier << " "; 849 if (i >= nloh) 850 return; 851 switch (identifier) { 852 case 1: 853 outs() << "AdrpAdrp\n"; 854 break; 855 case 2: 856 outs() << "AdrpLdr\n"; 857 break; 858 case 3: 859 outs() << "AdrpAddLdr\n"; 860 break; 861 case 4: 862 outs() << "AdrpLdrGotLdr\n"; 863 break; 864 case 5: 865 outs() << "AdrpAddStr\n"; 866 break; 867 case 6: 868 outs() << "AdrpLdrGotStr\n"; 869 break; 870 case 7: 871 outs() << "AdrpAdd\n"; 872 break; 873 case 8: 874 outs() << "AdrpLdrGot\n"; 875 break; 876 default: 877 outs() << "Unknown identifier value\n"; 878 break; 879 } 880 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 881 i += n; 882 outs() << " narguments " << narguments << "\n"; 883 if (i >= nloh) 884 return; 885 886 for (uint32_t j = 0; j < narguments; j++) { 887 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 888 i += n; 889 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 890 if (i >= nloh) 891 return; 892 } 893 } 894 } 895 896 static void PrintDylibs(MachOObjectFile *O, bool JustId) { 897 unsigned Index = 0; 898 for (const auto &Load : O->load_commands()) { 899 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 900 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 901 Load.C.cmd == MachO::LC_LOAD_DYLIB || 902 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 903 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 904 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 905 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 906 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 907 if (dl.dylib.name < dl.cmdsize) { 908 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 909 if (JustId) 910 outs() << p << "\n"; 911 else { 912 outs() << "\t" << p; 913 outs() << " (compatibility version " 914 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 915 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 916 << (dl.dylib.compatibility_version & 0xff) << ","; 917 outs() << " current version " 918 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 919 << ((dl.dylib.current_version >> 8) & 0xff) << "." 920 << (dl.dylib.current_version & 0xff) << ")\n"; 921 } 922 } else { 923 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 924 if (Load.C.cmd == MachO::LC_ID_DYLIB) 925 outs() << "LC_ID_DYLIB "; 926 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 927 outs() << "LC_LOAD_DYLIB "; 928 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 929 outs() << "LC_LOAD_WEAK_DYLIB "; 930 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 931 outs() << "LC_LAZY_LOAD_DYLIB "; 932 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 933 outs() << "LC_REEXPORT_DYLIB "; 934 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 935 outs() << "LC_LOAD_UPWARD_DYLIB "; 936 else 937 outs() << "LC_??? "; 938 outs() << "command " << Index++ << "\n"; 939 } 940 } 941 } 942 } 943 944 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 945 946 static void CreateSymbolAddressMap(MachOObjectFile *O, 947 SymbolAddressMap *AddrMap) { 948 // Create a map of symbol addresses to symbol names. 949 for (const SymbolRef &Symbol : O->symbols()) { 950 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 951 if (!STOrErr) 952 report_error(O->getFileName(), STOrErr.takeError()); 953 SymbolRef::Type ST = *STOrErr; 954 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 955 ST == SymbolRef::ST_Other) { 956 uint64_t Address = Symbol.getValue(); 957 Expected<StringRef> SymNameOrErr = Symbol.getName(); 958 if (!SymNameOrErr) 959 report_error(O->getFileName(), SymNameOrErr.takeError()); 960 StringRef SymName = *SymNameOrErr; 961 if (!SymName.startswith(".objc")) 962 (*AddrMap)[Address] = SymName; 963 } 964 } 965 } 966 967 // GuessSymbolName is passed the address of what might be a symbol and a 968 // pointer to the SymbolAddressMap. It returns the name of a symbol 969 // with that address or nullptr if no symbol is found with that address. 970 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 971 const char *SymbolName = nullptr; 972 // A DenseMap can't lookup up some values. 973 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 974 StringRef name = AddrMap->lookup(value); 975 if (!name.empty()) 976 SymbolName = name.data(); 977 } 978 return SymbolName; 979 } 980 981 static void DumpCstringChar(const char c) { 982 char p[2]; 983 p[0] = c; 984 p[1] = '\0'; 985 outs().write_escaped(p); 986 } 987 988 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 989 uint32_t sect_size, uint64_t sect_addr, 990 bool print_addresses) { 991 for (uint32_t i = 0; i < sect_size; i++) { 992 if (print_addresses) { 993 if (O->is64Bit()) 994 outs() << format("%016" PRIx64, sect_addr + i) << " "; 995 else 996 outs() << format("%08" PRIx64, sect_addr + i) << " "; 997 } 998 for (; i < sect_size && sect[i] != '\0'; i++) 999 DumpCstringChar(sect[i]); 1000 if (i < sect_size && sect[i] == '\0') 1001 outs() << "\n"; 1002 } 1003 } 1004 1005 static void DumpLiteral4(uint32_t l, float f) { 1006 outs() << format("0x%08" PRIx32, l); 1007 if ((l & 0x7f800000) != 0x7f800000) 1008 outs() << format(" (%.16e)\n", f); 1009 else { 1010 if (l == 0x7f800000) 1011 outs() << " (+Infinity)\n"; 1012 else if (l == 0xff800000) 1013 outs() << " (-Infinity)\n"; 1014 else if ((l & 0x00400000) == 0x00400000) 1015 outs() << " (non-signaling Not-a-Number)\n"; 1016 else 1017 outs() << " (signaling Not-a-Number)\n"; 1018 } 1019 } 1020 1021 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 1022 uint32_t sect_size, uint64_t sect_addr, 1023 bool print_addresses) { 1024 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 1025 if (print_addresses) { 1026 if (O->is64Bit()) 1027 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1028 else 1029 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1030 } 1031 float f; 1032 memcpy(&f, sect + i, sizeof(float)); 1033 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1034 sys::swapByteOrder(f); 1035 uint32_t l; 1036 memcpy(&l, sect + i, sizeof(uint32_t)); 1037 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1038 sys::swapByteOrder(l); 1039 DumpLiteral4(l, f); 1040 } 1041 } 1042 1043 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 1044 double d) { 1045 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 1046 uint32_t Hi, Lo; 1047 Hi = (O->isLittleEndian()) ? l1 : l0; 1048 Lo = (O->isLittleEndian()) ? l0 : l1; 1049 1050 // Hi is the high word, so this is equivalent to if(isfinite(d)) 1051 if ((Hi & 0x7ff00000) != 0x7ff00000) 1052 outs() << format(" (%.16e)\n", d); 1053 else { 1054 if (Hi == 0x7ff00000 && Lo == 0) 1055 outs() << " (+Infinity)\n"; 1056 else if (Hi == 0xfff00000 && Lo == 0) 1057 outs() << " (-Infinity)\n"; 1058 else if ((Hi & 0x00080000) == 0x00080000) 1059 outs() << " (non-signaling Not-a-Number)\n"; 1060 else 1061 outs() << " (signaling Not-a-Number)\n"; 1062 } 1063 } 1064 1065 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 1066 uint32_t sect_size, uint64_t sect_addr, 1067 bool print_addresses) { 1068 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 1069 if (print_addresses) { 1070 if (O->is64Bit()) 1071 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1072 else 1073 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1074 } 1075 double d; 1076 memcpy(&d, sect + i, sizeof(double)); 1077 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1078 sys::swapByteOrder(d); 1079 uint32_t l0, l1; 1080 memcpy(&l0, sect + i, sizeof(uint32_t)); 1081 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1082 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1083 sys::swapByteOrder(l0); 1084 sys::swapByteOrder(l1); 1085 } 1086 DumpLiteral8(O, l0, l1, d); 1087 } 1088 } 1089 1090 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 1091 outs() << format("0x%08" PRIx32, l0) << " "; 1092 outs() << format("0x%08" PRIx32, l1) << " "; 1093 outs() << format("0x%08" PRIx32, l2) << " "; 1094 outs() << format("0x%08" PRIx32, l3) << "\n"; 1095 } 1096 1097 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 1098 uint32_t sect_size, uint64_t sect_addr, 1099 bool print_addresses) { 1100 for (uint32_t i = 0; i < sect_size; i += 16) { 1101 if (print_addresses) { 1102 if (O->is64Bit()) 1103 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1104 else 1105 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1106 } 1107 uint32_t l0, l1, l2, l3; 1108 memcpy(&l0, sect + i, sizeof(uint32_t)); 1109 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1110 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 1111 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1112 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1113 sys::swapByteOrder(l0); 1114 sys::swapByteOrder(l1); 1115 sys::swapByteOrder(l2); 1116 sys::swapByteOrder(l3); 1117 } 1118 DumpLiteral16(l0, l1, l2, l3); 1119 } 1120 } 1121 1122 static void DumpLiteralPointerSection(MachOObjectFile *O, 1123 const SectionRef &Section, 1124 const char *sect, uint32_t sect_size, 1125 uint64_t sect_addr, 1126 bool print_addresses) { 1127 // Collect the literal sections in this Mach-O file. 1128 std::vector<SectionRef> LiteralSections; 1129 for (const SectionRef &Section : O->sections()) { 1130 DataRefImpl Ref = Section.getRawDataRefImpl(); 1131 uint32_t section_type; 1132 if (O->is64Bit()) { 1133 const MachO::section_64 Sec = O->getSection64(Ref); 1134 section_type = Sec.flags & MachO::SECTION_TYPE; 1135 } else { 1136 const MachO::section Sec = O->getSection(Ref); 1137 section_type = Sec.flags & MachO::SECTION_TYPE; 1138 } 1139 if (section_type == MachO::S_CSTRING_LITERALS || 1140 section_type == MachO::S_4BYTE_LITERALS || 1141 section_type == MachO::S_8BYTE_LITERALS || 1142 section_type == MachO::S_16BYTE_LITERALS) 1143 LiteralSections.push_back(Section); 1144 } 1145 1146 // Set the size of the literal pointer. 1147 uint32_t lp_size = O->is64Bit() ? 8 : 4; 1148 1149 // Collect the external relocation symbols for the literal pointers. 1150 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1151 for (const RelocationRef &Reloc : Section.relocations()) { 1152 DataRefImpl Rel; 1153 MachO::any_relocation_info RE; 1154 bool isExtern = false; 1155 Rel = Reloc.getRawDataRefImpl(); 1156 RE = O->getRelocation(Rel); 1157 isExtern = O->getPlainRelocationExternal(RE); 1158 if (isExtern) { 1159 uint64_t RelocOffset = Reloc.getOffset(); 1160 symbol_iterator RelocSym = Reloc.getSymbol(); 1161 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1162 } 1163 } 1164 array_pod_sort(Relocs.begin(), Relocs.end()); 1165 1166 // Dump each literal pointer. 1167 for (uint32_t i = 0; i < sect_size; i += lp_size) { 1168 if (print_addresses) { 1169 if (O->is64Bit()) 1170 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1171 else 1172 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1173 } 1174 uint64_t lp; 1175 if (O->is64Bit()) { 1176 memcpy(&lp, sect + i, sizeof(uint64_t)); 1177 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1178 sys::swapByteOrder(lp); 1179 } else { 1180 uint32_t li; 1181 memcpy(&li, sect + i, sizeof(uint32_t)); 1182 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1183 sys::swapByteOrder(li); 1184 lp = li; 1185 } 1186 1187 // First look for an external relocation entry for this literal pointer. 1188 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1189 return P.first == i; 1190 }); 1191 if (Reloc != Relocs.end()) { 1192 symbol_iterator RelocSym = Reloc->second; 1193 Expected<StringRef> SymName = RelocSym->getName(); 1194 if (!SymName) 1195 report_error(O->getFileName(), SymName.takeError()); 1196 outs() << "external relocation entry for symbol:" << *SymName << "\n"; 1197 continue; 1198 } 1199 1200 // For local references see what the section the literal pointer points to. 1201 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 1202 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 1203 }); 1204 if (Sect == LiteralSections.end()) { 1205 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 1206 continue; 1207 } 1208 1209 uint64_t SectAddress = Sect->getAddress(); 1210 uint64_t SectSize = Sect->getSize(); 1211 1212 StringRef SectName; 1213 Sect->getName(SectName); 1214 DataRefImpl Ref = Sect->getRawDataRefImpl(); 1215 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 1216 outs() << SegmentName << ":" << SectName << ":"; 1217 1218 uint32_t section_type; 1219 if (O->is64Bit()) { 1220 const MachO::section_64 Sec = O->getSection64(Ref); 1221 section_type = Sec.flags & MachO::SECTION_TYPE; 1222 } else { 1223 const MachO::section Sec = O->getSection(Ref); 1224 section_type = Sec.flags & MachO::SECTION_TYPE; 1225 } 1226 1227 StringRef BytesStr; 1228 Sect->getContents(BytesStr); 1229 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 1230 1231 switch (section_type) { 1232 case MachO::S_CSTRING_LITERALS: 1233 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 1234 i++) { 1235 DumpCstringChar(Contents[i]); 1236 } 1237 outs() << "\n"; 1238 break; 1239 case MachO::S_4BYTE_LITERALS: 1240 float f; 1241 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 1242 uint32_t l; 1243 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 1244 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1245 sys::swapByteOrder(f); 1246 sys::swapByteOrder(l); 1247 } 1248 DumpLiteral4(l, f); 1249 break; 1250 case MachO::S_8BYTE_LITERALS: { 1251 double d; 1252 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 1253 uint32_t l0, l1; 1254 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1255 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1256 sizeof(uint32_t)); 1257 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1258 sys::swapByteOrder(f); 1259 sys::swapByteOrder(l0); 1260 sys::swapByteOrder(l1); 1261 } 1262 DumpLiteral8(O, l0, l1, d); 1263 break; 1264 } 1265 case MachO::S_16BYTE_LITERALS: { 1266 uint32_t l0, l1, l2, l3; 1267 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1268 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1269 sizeof(uint32_t)); 1270 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 1271 sizeof(uint32_t)); 1272 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 1273 sizeof(uint32_t)); 1274 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1275 sys::swapByteOrder(l0); 1276 sys::swapByteOrder(l1); 1277 sys::swapByteOrder(l2); 1278 sys::swapByteOrder(l3); 1279 } 1280 DumpLiteral16(l0, l1, l2, l3); 1281 break; 1282 } 1283 } 1284 } 1285 } 1286 1287 static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect, 1288 uint32_t sect_size, uint64_t sect_addr, 1289 SymbolAddressMap *AddrMap, 1290 bool verbose) { 1291 uint32_t stride; 1292 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 1293 for (uint32_t i = 0; i < sect_size; i += stride) { 1294 const char *SymbolName = nullptr; 1295 if (O->is64Bit()) { 1296 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 1297 uint64_t pointer_value; 1298 memcpy(&pointer_value, sect + i, stride); 1299 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1300 sys::swapByteOrder(pointer_value); 1301 outs() << format("0x%016" PRIx64, pointer_value); 1302 if (verbose) 1303 SymbolName = GuessSymbolName(pointer_value, AddrMap); 1304 } else { 1305 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 1306 uint32_t pointer_value; 1307 memcpy(&pointer_value, sect + i, stride); 1308 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1309 sys::swapByteOrder(pointer_value); 1310 outs() << format("0x%08" PRIx32, pointer_value); 1311 if (verbose) 1312 SymbolName = GuessSymbolName(pointer_value, AddrMap); 1313 } 1314 if (SymbolName) 1315 outs() << " " << SymbolName; 1316 outs() << "\n"; 1317 } 1318 } 1319 1320 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 1321 uint32_t size, uint64_t addr) { 1322 uint32_t cputype = O->getHeader().cputype; 1323 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 1324 uint32_t j; 1325 for (uint32_t i = 0; i < size; i += j, addr += j) { 1326 if (O->is64Bit()) 1327 outs() << format("%016" PRIx64, addr) << "\t"; 1328 else 1329 outs() << format("%08" PRIx64, addr) << "\t"; 1330 for (j = 0; j < 16 && i + j < size; j++) { 1331 uint8_t byte_word = *(sect + i + j); 1332 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1333 } 1334 outs() << "\n"; 1335 } 1336 } else { 1337 uint32_t j; 1338 for (uint32_t i = 0; i < size; i += j, addr += j) { 1339 if (O->is64Bit()) 1340 outs() << format("%016" PRIx64, addr) << "\t"; 1341 else 1342 outs() << format("%08" PRIx64, addr) << "\t"; 1343 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 1344 j += sizeof(int32_t)) { 1345 if (i + j + sizeof(int32_t) <= size) { 1346 uint32_t long_word; 1347 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1348 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1349 sys::swapByteOrder(long_word); 1350 outs() << format("%08" PRIx32, long_word) << " "; 1351 } else { 1352 for (uint32_t k = 0; i + j + k < size; k++) { 1353 uint8_t byte_word = *(sect + i + j + k); 1354 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1355 } 1356 } 1357 } 1358 outs() << "\n"; 1359 } 1360 } 1361 } 1362 1363 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1364 StringRef DisSegName, StringRef DisSectName); 1365 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1366 uint32_t size, uint32_t addr); 1367 #ifdef HAVE_LIBXAR 1368 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 1369 uint32_t size, bool verbose, 1370 bool PrintXarHeader, bool PrintXarFileHeaders, 1371 std::string XarMemberName); 1372 #endif // defined(HAVE_LIBXAR) 1373 1374 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1375 bool verbose) { 1376 SymbolAddressMap AddrMap; 1377 if (verbose) 1378 CreateSymbolAddressMap(O, &AddrMap); 1379 1380 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1381 StringRef DumpSection = FilterSections[i]; 1382 std::pair<StringRef, StringRef> DumpSegSectName; 1383 DumpSegSectName = DumpSection.split(','); 1384 StringRef DumpSegName, DumpSectName; 1385 if (DumpSegSectName.second.size()) { 1386 DumpSegName = DumpSegSectName.first; 1387 DumpSectName = DumpSegSectName.second; 1388 } else { 1389 DumpSegName = ""; 1390 DumpSectName = DumpSegSectName.first; 1391 } 1392 for (const SectionRef &Section : O->sections()) { 1393 StringRef SectName; 1394 Section.getName(SectName); 1395 DataRefImpl Ref = Section.getRawDataRefImpl(); 1396 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1397 if ((DumpSegName.empty() || SegName == DumpSegName) && 1398 (SectName == DumpSectName)) { 1399 1400 uint32_t section_flags; 1401 if (O->is64Bit()) { 1402 const MachO::section_64 Sec = O->getSection64(Ref); 1403 section_flags = Sec.flags; 1404 1405 } else { 1406 const MachO::section Sec = O->getSection(Ref); 1407 section_flags = Sec.flags; 1408 } 1409 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1410 1411 StringRef BytesStr; 1412 Section.getContents(BytesStr); 1413 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1414 uint32_t sect_size = BytesStr.size(); 1415 uint64_t sect_addr = Section.getAddress(); 1416 1417 outs() << "Contents of (" << SegName << "," << SectName 1418 << ") section\n"; 1419 1420 if (verbose) { 1421 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1422 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1423 DisassembleMachO(Filename, O, SegName, SectName); 1424 continue; 1425 } 1426 if (SegName == "__TEXT" && SectName == "__info_plist") { 1427 outs() << sect; 1428 continue; 1429 } 1430 if (SegName == "__OBJC" && SectName == "__protocol") { 1431 DumpProtocolSection(O, sect, sect_size, sect_addr); 1432 continue; 1433 } 1434 #ifdef HAVE_LIBXAR 1435 if (SegName == "__LLVM" && SectName == "__bundle") { 1436 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands, 1437 ArchiveHeaders, ""); 1438 continue; 1439 } 1440 #endif // defined(HAVE_LIBXAR) 1441 switch (section_type) { 1442 case MachO::S_REGULAR: 1443 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1444 break; 1445 case MachO::S_ZEROFILL: 1446 outs() << "zerofill section and has no contents in the file\n"; 1447 break; 1448 case MachO::S_CSTRING_LITERALS: 1449 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1450 break; 1451 case MachO::S_4BYTE_LITERALS: 1452 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1453 break; 1454 case MachO::S_8BYTE_LITERALS: 1455 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1456 break; 1457 case MachO::S_16BYTE_LITERALS: 1458 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1459 break; 1460 case MachO::S_LITERAL_POINTERS: 1461 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1462 !NoLeadingAddr); 1463 break; 1464 case MachO::S_MOD_INIT_FUNC_POINTERS: 1465 case MachO::S_MOD_TERM_FUNC_POINTERS: 1466 DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap, 1467 verbose); 1468 break; 1469 default: 1470 outs() << "Unknown section type (" 1471 << format("0x%08" PRIx32, section_type) << ")\n"; 1472 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1473 break; 1474 } 1475 } else { 1476 if (section_type == MachO::S_ZEROFILL) 1477 outs() << "zerofill section and has no contents in the file\n"; 1478 else 1479 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1480 } 1481 } 1482 } 1483 } 1484 } 1485 1486 static void DumpInfoPlistSectionContents(StringRef Filename, 1487 MachOObjectFile *O) { 1488 for (const SectionRef &Section : O->sections()) { 1489 StringRef SectName; 1490 Section.getName(SectName); 1491 DataRefImpl Ref = Section.getRawDataRefImpl(); 1492 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1493 if (SegName == "__TEXT" && SectName == "__info_plist") { 1494 if (!NoLeadingHeaders) 1495 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1496 StringRef BytesStr; 1497 Section.getContents(BytesStr); 1498 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1499 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 1500 return; 1501 } 1502 } 1503 } 1504 1505 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1506 // and if it is and there is a list of architecture flags is specified then 1507 // check to make sure this Mach-O file is one of those architectures or all 1508 // architectures were specified. If not then an error is generated and this 1509 // routine returns false. Else it returns true. 1510 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1511 auto *MachO = dyn_cast<MachOObjectFile>(O); 1512 1513 if (!MachO || ArchAll || ArchFlags.empty()) 1514 return true; 1515 1516 MachO::mach_header H; 1517 MachO::mach_header_64 H_64; 1518 Triple T; 1519 const char *McpuDefault, *ArchFlag; 1520 if (MachO->is64Bit()) { 1521 H_64 = MachO->MachOObjectFile::getHeader64(); 1522 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 1523 &McpuDefault, &ArchFlag); 1524 } else { 1525 H = MachO->MachOObjectFile::getHeader(); 1526 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 1527 &McpuDefault, &ArchFlag); 1528 } 1529 const std::string ArchFlagName(ArchFlag); 1530 if (none_of(ArchFlags, [&](const std::string &Name) { 1531 return Name == ArchFlagName; 1532 })) { 1533 errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n"; 1534 return false; 1535 } 1536 return true; 1537 } 1538 1539 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 1540 1541 // ProcessMachO() is passed a single opened Mach-O file, which may be an 1542 // archive member and or in a slice of a universal file. It prints the 1543 // the file name and header info and then processes it according to the 1544 // command line options. 1545 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 1546 StringRef ArchiveMemberName = StringRef(), 1547 StringRef ArchitectureName = StringRef()) { 1548 // If we are doing some processing here on the Mach-O file print the header 1549 // info. And don't print it otherwise like in the case of printing the 1550 // UniversalHeaders or ArchiveHeaders. 1551 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || 1552 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || 1553 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData || 1554 (FilterSections.size() != 0)) { 1555 if (!NoLeadingHeaders) { 1556 outs() << Name; 1557 if (!ArchiveMemberName.empty()) 1558 outs() << '(' << ArchiveMemberName << ')'; 1559 if (!ArchitectureName.empty()) 1560 outs() << " (architecture " << ArchitectureName << ")"; 1561 outs() << ":\n"; 1562 } 1563 } 1564 // To use the report_error() form with an ArchiveName and FileName set 1565 // these up based on what is passed for Name and ArchiveMemberName. 1566 StringRef ArchiveName; 1567 StringRef FileName; 1568 if (!ArchiveMemberName.empty()) { 1569 ArchiveName = Name; 1570 FileName = ArchiveMemberName; 1571 } else { 1572 ArchiveName = StringRef(); 1573 FileName = Name; 1574 } 1575 1576 // If we need the symbol table to do the operation then check it here to 1577 // produce a good error message as to where the Mach-O file comes from in 1578 // the error message. 1579 if (Disassemble || IndirectSymbols || FilterSections.size() != 0 || 1580 UnwindInfo) 1581 if (Error Err = MachOOF->checkSymbolTable()) 1582 report_error(ArchiveName, FileName, std::move(Err), ArchitectureName); 1583 1584 if (Disassemble) { 1585 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE && 1586 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64) 1587 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text"); 1588 else 1589 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 1590 } 1591 if (IndirectSymbols) 1592 PrintIndirectSymbols(MachOOF, !NonVerbose); 1593 if (DataInCode) 1594 PrintDataInCodeTable(MachOOF, !NonVerbose); 1595 if (LinkOptHints) 1596 PrintLinkOptHints(MachOOF); 1597 if (Relocations) 1598 PrintRelocations(MachOOF, !NonVerbose); 1599 if (SectionHeaders) 1600 PrintSectionHeaders(MachOOF); 1601 if (SectionContents) 1602 PrintSectionContents(MachOOF); 1603 if (FilterSections.size() != 0) 1604 DumpSectionContents(FileName, MachOOF, !NonVerbose); 1605 if (InfoPlist) 1606 DumpInfoPlistSectionContents(FileName, MachOOF); 1607 if (DylibsUsed) 1608 PrintDylibs(MachOOF, false); 1609 if (DylibId) 1610 PrintDylibs(MachOOF, true); 1611 if (SymbolTable) 1612 PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName); 1613 if (UnwindInfo) 1614 printMachOUnwindInfo(MachOOF); 1615 if (PrivateHeaders) { 1616 printMachOFileHeader(MachOOF); 1617 printMachOLoadCommands(MachOOF); 1618 } 1619 if (FirstPrivateHeader) 1620 printMachOFileHeader(MachOOF); 1621 if (ObjcMetaData) 1622 printObjcMetaData(MachOOF, !NonVerbose); 1623 if (ExportsTrie) 1624 printExportsTrie(MachOOF); 1625 if (Rebase) 1626 printRebaseTable(MachOOF); 1627 if (Bind) 1628 printBindTable(MachOOF); 1629 if (LazyBind) 1630 printLazyBindTable(MachOOF); 1631 if (WeakBind) 1632 printWeakBindTable(MachOOF); 1633 1634 if (DwarfDumpType != DIDT_Null) { 1635 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF); 1636 // Dump the complete DWARF structure. 1637 DIDumpOptions DumpOpts; 1638 DumpOpts.DumpType = DwarfDumpType; 1639 DICtx->dump(outs(), DumpOpts); 1640 } 1641 } 1642 1643 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 1644 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 1645 outs() << " cputype (" << cputype << ")\n"; 1646 outs() << " cpusubtype (" << cpusubtype << ")\n"; 1647 } 1648 1649 // printCPUType() helps print_fat_headers by printing the cputype and 1650 // pusubtype (symbolically for the one's it knows about). 1651 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 1652 switch (cputype) { 1653 case MachO::CPU_TYPE_I386: 1654 switch (cpusubtype) { 1655 case MachO::CPU_SUBTYPE_I386_ALL: 1656 outs() << " cputype CPU_TYPE_I386\n"; 1657 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 1658 break; 1659 default: 1660 printUnknownCPUType(cputype, cpusubtype); 1661 break; 1662 } 1663 break; 1664 case MachO::CPU_TYPE_X86_64: 1665 switch (cpusubtype) { 1666 case MachO::CPU_SUBTYPE_X86_64_ALL: 1667 outs() << " cputype CPU_TYPE_X86_64\n"; 1668 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 1669 break; 1670 case MachO::CPU_SUBTYPE_X86_64_H: 1671 outs() << " cputype CPU_TYPE_X86_64\n"; 1672 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 1673 break; 1674 default: 1675 printUnknownCPUType(cputype, cpusubtype); 1676 break; 1677 } 1678 break; 1679 case MachO::CPU_TYPE_ARM: 1680 switch (cpusubtype) { 1681 case MachO::CPU_SUBTYPE_ARM_ALL: 1682 outs() << " cputype CPU_TYPE_ARM\n"; 1683 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 1684 break; 1685 case MachO::CPU_SUBTYPE_ARM_V4T: 1686 outs() << " cputype CPU_TYPE_ARM\n"; 1687 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 1688 break; 1689 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1690 outs() << " cputype CPU_TYPE_ARM\n"; 1691 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 1692 break; 1693 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1694 outs() << " cputype CPU_TYPE_ARM\n"; 1695 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 1696 break; 1697 case MachO::CPU_SUBTYPE_ARM_V6: 1698 outs() << " cputype CPU_TYPE_ARM\n"; 1699 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 1700 break; 1701 case MachO::CPU_SUBTYPE_ARM_V6M: 1702 outs() << " cputype CPU_TYPE_ARM\n"; 1703 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 1704 break; 1705 case MachO::CPU_SUBTYPE_ARM_V7: 1706 outs() << " cputype CPU_TYPE_ARM\n"; 1707 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 1708 break; 1709 case MachO::CPU_SUBTYPE_ARM_V7EM: 1710 outs() << " cputype CPU_TYPE_ARM\n"; 1711 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 1712 break; 1713 case MachO::CPU_SUBTYPE_ARM_V7K: 1714 outs() << " cputype CPU_TYPE_ARM\n"; 1715 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 1716 break; 1717 case MachO::CPU_SUBTYPE_ARM_V7M: 1718 outs() << " cputype CPU_TYPE_ARM\n"; 1719 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 1720 break; 1721 case MachO::CPU_SUBTYPE_ARM_V7S: 1722 outs() << " cputype CPU_TYPE_ARM\n"; 1723 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 1724 break; 1725 default: 1726 printUnknownCPUType(cputype, cpusubtype); 1727 break; 1728 } 1729 break; 1730 case MachO::CPU_TYPE_ARM64: 1731 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 1732 case MachO::CPU_SUBTYPE_ARM64_ALL: 1733 outs() << " cputype CPU_TYPE_ARM64\n"; 1734 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 1735 break; 1736 default: 1737 printUnknownCPUType(cputype, cpusubtype); 1738 break; 1739 } 1740 break; 1741 default: 1742 printUnknownCPUType(cputype, cpusubtype); 1743 break; 1744 } 1745 } 1746 1747 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 1748 bool verbose) { 1749 outs() << "Fat headers\n"; 1750 if (verbose) { 1751 if (UB->getMagic() == MachO::FAT_MAGIC) 1752 outs() << "fat_magic FAT_MAGIC\n"; 1753 else // UB->getMagic() == MachO::FAT_MAGIC_64 1754 outs() << "fat_magic FAT_MAGIC_64\n"; 1755 } else 1756 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 1757 1758 uint32_t nfat_arch = UB->getNumberOfObjects(); 1759 StringRef Buf = UB->getData(); 1760 uint64_t size = Buf.size(); 1761 uint64_t big_size = sizeof(struct MachO::fat_header) + 1762 nfat_arch * sizeof(struct MachO::fat_arch); 1763 outs() << "nfat_arch " << UB->getNumberOfObjects(); 1764 if (nfat_arch == 0) 1765 outs() << " (malformed, contains zero architecture types)\n"; 1766 else if (big_size > size) 1767 outs() << " (malformed, architectures past end of file)\n"; 1768 else 1769 outs() << "\n"; 1770 1771 for (uint32_t i = 0; i < nfat_arch; ++i) { 1772 MachOUniversalBinary::ObjectForArch OFA(UB, i); 1773 uint32_t cputype = OFA.getCPUType(); 1774 uint32_t cpusubtype = OFA.getCPUSubType(); 1775 outs() << "architecture "; 1776 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 1777 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 1778 uint32_t other_cputype = other_OFA.getCPUType(); 1779 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 1780 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 1781 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 1782 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 1783 outs() << "(illegal duplicate architecture) "; 1784 break; 1785 } 1786 } 1787 if (verbose) { 1788 outs() << OFA.getArchFlagName() << "\n"; 1789 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 1790 } else { 1791 outs() << i << "\n"; 1792 outs() << " cputype " << cputype << "\n"; 1793 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 1794 << "\n"; 1795 } 1796 if (verbose && 1797 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 1798 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 1799 else 1800 outs() << " capabilities " 1801 << format("0x%" PRIx32, 1802 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 1803 outs() << " offset " << OFA.getOffset(); 1804 if (OFA.getOffset() > size) 1805 outs() << " (past end of file)"; 1806 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0) 1807 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 1808 outs() << "\n"; 1809 outs() << " size " << OFA.getSize(); 1810 big_size = OFA.getOffset() + OFA.getSize(); 1811 if (big_size > size) 1812 outs() << " (past end of file)"; 1813 outs() << "\n"; 1814 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 1815 << ")\n"; 1816 } 1817 } 1818 1819 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 1820 bool verbose, bool print_offset, 1821 StringRef ArchitectureName = StringRef()) { 1822 if (print_offset) 1823 outs() << C.getChildOffset() << "\t"; 1824 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode(); 1825 if (!ModeOrErr) 1826 report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName); 1827 sys::fs::perms Mode = ModeOrErr.get(); 1828 if (verbose) { 1829 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 1830 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 1831 outs() << "-"; 1832 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 1833 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 1834 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 1835 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 1836 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 1837 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 1838 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 1839 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 1840 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 1841 } else { 1842 outs() << format("0%o ", Mode); 1843 } 1844 1845 Expected<unsigned> UIDOrErr = C.getUID(); 1846 if (!UIDOrErr) 1847 report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName); 1848 unsigned UID = UIDOrErr.get(); 1849 outs() << format("%3d/", UID); 1850 Expected<unsigned> GIDOrErr = C.getGID(); 1851 if (!GIDOrErr) 1852 report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName); 1853 unsigned GID = GIDOrErr.get(); 1854 outs() << format("%-3d ", GID); 1855 Expected<uint64_t> Size = C.getRawSize(); 1856 if (!Size) 1857 report_error(Filename, C, Size.takeError(), ArchitectureName); 1858 outs() << format("%5" PRId64, Size.get()) << " "; 1859 1860 StringRef RawLastModified = C.getRawLastModified(); 1861 if (verbose) { 1862 unsigned Seconds; 1863 if (RawLastModified.getAsInteger(10, Seconds)) 1864 outs() << "(date: \"" << RawLastModified 1865 << "\" contains non-decimal chars) "; 1866 else { 1867 // Since cime(3) returns a 26 character string of the form: 1868 // "Sun Sep 16 01:03:52 1973\n\0" 1869 // just print 24 characters. 1870 time_t t = Seconds; 1871 outs() << format("%.24s ", ctime(&t)); 1872 } 1873 } else { 1874 outs() << RawLastModified << " "; 1875 } 1876 1877 if (verbose) { 1878 Expected<StringRef> NameOrErr = C.getName(); 1879 if (!NameOrErr) { 1880 consumeError(NameOrErr.takeError()); 1881 Expected<StringRef> NameOrErr = C.getRawName(); 1882 if (!NameOrErr) 1883 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1884 StringRef RawName = NameOrErr.get(); 1885 outs() << RawName << "\n"; 1886 } else { 1887 StringRef Name = NameOrErr.get(); 1888 outs() << Name << "\n"; 1889 } 1890 } else { 1891 Expected<StringRef> NameOrErr = C.getRawName(); 1892 if (!NameOrErr) 1893 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1894 StringRef RawName = NameOrErr.get(); 1895 outs() << RawName << "\n"; 1896 } 1897 } 1898 1899 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 1900 bool print_offset, 1901 StringRef ArchitectureName = StringRef()) { 1902 Error Err = Error::success(); 1903 ; 1904 for (const auto &C : A->children(Err, false)) 1905 printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName); 1906 1907 if (Err) 1908 report_error(StringRef(), Filename, std::move(Err), ArchitectureName); 1909 } 1910 1911 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 1912 // -arch flags selecting just those slices as specified by them and also parses 1913 // archive files. Then for each individual Mach-O file ProcessMachO() is 1914 // called to process the file based on the command line options. 1915 void llvm::ParseInputMachO(StringRef Filename) { 1916 // Check for -arch all and verifiy the -arch flags are valid. 1917 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 1918 if (ArchFlags[i] == "all") { 1919 ArchAll = true; 1920 } else { 1921 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 1922 errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] + 1923 "'for the -arch option\n"; 1924 return; 1925 } 1926 } 1927 } 1928 1929 // Attempt to open the binary. 1930 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 1931 if (!BinaryOrErr) { 1932 if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 1933 report_error(Filename, std::move(E)); 1934 else 1935 outs() << Filename << ": is not an object file\n"; 1936 return; 1937 } 1938 Binary &Bin = *BinaryOrErr.get().getBinary(); 1939 1940 if (Archive *A = dyn_cast<Archive>(&Bin)) { 1941 outs() << "Archive : " << Filename << "\n"; 1942 if (ArchiveHeaders) 1943 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets); 1944 1945 Error Err = Error::success(); 1946 for (auto &C : A->children(Err)) { 1947 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 1948 if (!ChildOrErr) { 1949 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 1950 report_error(Filename, C, std::move(E)); 1951 continue; 1952 } 1953 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 1954 if (!checkMachOAndArchFlags(O, Filename)) 1955 return; 1956 ProcessMachO(Filename, O, O->getFileName()); 1957 } 1958 } 1959 if (Err) 1960 report_error(Filename, std::move(Err)); 1961 return; 1962 } 1963 if (UniversalHeaders) { 1964 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) 1965 printMachOUniversalHeaders(UB, !NonVerbose); 1966 } 1967 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 1968 // If we have a list of architecture flags specified dump only those. 1969 if (!ArchAll && ArchFlags.size() != 0) { 1970 // Look for a slice in the universal binary that matches each ArchFlag. 1971 bool ArchFound; 1972 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 1973 ArchFound = false; 1974 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 1975 E = UB->end_objects(); 1976 I != E; ++I) { 1977 if (ArchFlags[i] == I->getArchFlagName()) { 1978 ArchFound = true; 1979 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 1980 I->getAsObjectFile(); 1981 std::string ArchitectureName = ""; 1982 if (ArchFlags.size() > 1) 1983 ArchitectureName = I->getArchFlagName(); 1984 if (ObjOrErr) { 1985 ObjectFile &O = *ObjOrErr.get(); 1986 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 1987 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 1988 } else if (auto E = isNotObjectErrorInvalidFileType( 1989 ObjOrErr.takeError())) { 1990 report_error(Filename, StringRef(), std::move(E), 1991 ArchitectureName); 1992 continue; 1993 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 1994 I->getAsArchive()) { 1995 std::unique_ptr<Archive> &A = *AOrErr; 1996 outs() << "Archive : " << Filename; 1997 if (!ArchitectureName.empty()) 1998 outs() << " (architecture " << ArchitectureName << ")"; 1999 outs() << "\n"; 2000 if (ArchiveHeaders) 2001 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2002 ArchiveMemberOffsets, ArchitectureName); 2003 Error Err = Error::success(); 2004 for (auto &C : A->children(Err)) { 2005 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2006 if (!ChildOrErr) { 2007 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2008 report_error(Filename, C, std::move(E), ArchitectureName); 2009 continue; 2010 } 2011 if (MachOObjectFile *O = 2012 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2013 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2014 } 2015 if (Err) 2016 report_error(Filename, std::move(Err)); 2017 } else { 2018 consumeError(AOrErr.takeError()); 2019 error("Mach-O universal file: " + Filename + " for " + 2020 "architecture " + StringRef(I->getArchFlagName()) + 2021 " is not a Mach-O file or an archive file"); 2022 } 2023 } 2024 } 2025 if (!ArchFound) { 2026 errs() << "llvm-objdump: file: " + Filename + " does not contain " 2027 << "architecture: " + ArchFlags[i] + "\n"; 2028 return; 2029 } 2030 } 2031 return; 2032 } 2033 // No architecture flags were specified so if this contains a slice that 2034 // matches the host architecture dump only that. 2035 if (!ArchAll) { 2036 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2037 E = UB->end_objects(); 2038 I != E; ++I) { 2039 if (MachOObjectFile::getHostArch().getArchName() == 2040 I->getArchFlagName()) { 2041 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2042 std::string ArchiveName; 2043 ArchiveName.clear(); 2044 if (ObjOrErr) { 2045 ObjectFile &O = *ObjOrErr.get(); 2046 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2047 ProcessMachO(Filename, MachOOF); 2048 } else if (auto E = isNotObjectErrorInvalidFileType( 2049 ObjOrErr.takeError())) { 2050 report_error(Filename, std::move(E)); 2051 continue; 2052 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2053 I->getAsArchive()) { 2054 std::unique_ptr<Archive> &A = *AOrErr; 2055 outs() << "Archive : " << Filename << "\n"; 2056 if (ArchiveHeaders) 2057 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2058 ArchiveMemberOffsets); 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)); 2065 continue; 2066 } 2067 if (MachOObjectFile *O = 2068 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2069 ProcessMachO(Filename, O, O->getFileName()); 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 architecture " + 2076 StringRef(I->getArchFlagName()) + 2077 " is not a Mach-O file or an archive file"); 2078 } 2079 return; 2080 } 2081 } 2082 } 2083 // Either all architectures have been specified or none have been specified 2084 // and this does not contain the host architecture so dump all the slices. 2085 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2086 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2087 E = UB->end_objects(); 2088 I != E; ++I) { 2089 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2090 std::string ArchitectureName = ""; 2091 if (moreThanOneArch) 2092 ArchitectureName = I->getArchFlagName(); 2093 if (ObjOrErr) { 2094 ObjectFile &Obj = *ObjOrErr.get(); 2095 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2096 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2097 } else if (auto E = isNotObjectErrorInvalidFileType( 2098 ObjOrErr.takeError())) { 2099 report_error(StringRef(), Filename, std::move(E), ArchitectureName); 2100 continue; 2101 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2102 I->getAsArchive()) { 2103 std::unique_ptr<Archive> &A = *AOrErr; 2104 outs() << "Archive : " << Filename; 2105 if (!ArchitectureName.empty()) 2106 outs() << " (architecture " << ArchitectureName << ")"; 2107 outs() << "\n"; 2108 if (ArchiveHeaders) 2109 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2110 ArchiveMemberOffsets, ArchitectureName); 2111 Error Err = Error::success(); 2112 for (auto &C : A->children(Err)) { 2113 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2114 if (!ChildOrErr) { 2115 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2116 report_error(Filename, C, std::move(E), ArchitectureName); 2117 continue; 2118 } 2119 if (MachOObjectFile *O = 2120 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2121 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2122 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2123 ArchitectureName); 2124 } 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 } 2135 return; 2136 } 2137 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2138 if (!checkMachOAndArchFlags(O, Filename)) 2139 return; 2140 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) { 2141 ProcessMachO(Filename, MachOOF); 2142 } else 2143 errs() << "llvm-objdump: '" << Filename << "': " 2144 << "Object is not a Mach-O file type.\n"; 2145 return; 2146 } 2147 llvm_unreachable("Input object can't be invalid at this point"); 2148 } 2149 2150 // The block of info used by the Symbolizer call backs. 2151 struct DisassembleInfo { 2152 bool verbose; 2153 MachOObjectFile *O; 2154 SectionRef S; 2155 SymbolAddressMap *AddrMap; 2156 std::vector<SectionRef> *Sections; 2157 const char *class_name; 2158 const char *selector_name; 2159 char *method; 2160 char *demangled_name; 2161 uint64_t adrp_addr; 2162 uint32_t adrp_inst; 2163 std::unique_ptr<SymbolAddressMap> bindtable; 2164 uint32_t depth; 2165 }; 2166 2167 // SymbolizerGetOpInfo() is the operand information call back function. 2168 // This is called to get the symbolic information for operand(s) of an 2169 // instruction when it is being done. This routine does this from 2170 // the relocation information, symbol table, etc. That block of information 2171 // is a pointer to the struct DisassembleInfo that was passed when the 2172 // disassembler context was created and passed to back to here when 2173 // called back by the disassembler for instruction operands that could have 2174 // relocation information. The address of the instruction containing operand is 2175 // at the Pc parameter. The immediate value the operand has is passed in 2176 // op_info->Value and is at Offset past the start of the instruction and has a 2177 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2178 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2179 // names and addends of the symbolic expression to add for the operand. The 2180 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2181 // information is returned then this function returns 1 else it returns 0. 2182 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2183 uint64_t Size, int TagType, void *TagBuf) { 2184 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2185 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2186 uint64_t value = op_info->Value; 2187 2188 // Make sure all fields returned are zero if we don't set them. 2189 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2190 op_info->Value = value; 2191 2192 // If the TagType is not the value 1 which it code knows about or if no 2193 // verbose symbolic information is wanted then just return 0, indicating no 2194 // information is being returned. 2195 if (TagType != 1 || !info->verbose) 2196 return 0; 2197 2198 unsigned int Arch = info->O->getArch(); 2199 if (Arch == Triple::x86) { 2200 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2201 return 0; 2202 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2203 // TODO: 2204 // Search the external relocation entries of a fully linked image 2205 // (if any) for an entry that matches this segment offset. 2206 // uint32_t seg_offset = (Pc + Offset); 2207 return 0; 2208 } 2209 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2210 // for an entry for this section offset. 2211 uint32_t sect_addr = info->S.getAddress(); 2212 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2213 bool reloc_found = false; 2214 DataRefImpl Rel; 2215 MachO::any_relocation_info RE; 2216 bool isExtern = false; 2217 SymbolRef Symbol; 2218 bool r_scattered = false; 2219 uint32_t r_value, pair_r_value, r_type; 2220 for (const RelocationRef &Reloc : info->S.relocations()) { 2221 uint64_t RelocOffset = Reloc.getOffset(); 2222 if (RelocOffset == sect_offset) { 2223 Rel = Reloc.getRawDataRefImpl(); 2224 RE = info->O->getRelocation(Rel); 2225 r_type = info->O->getAnyRelocationType(RE); 2226 r_scattered = info->O->isRelocationScattered(RE); 2227 if (r_scattered) { 2228 r_value = info->O->getScatteredRelocationValue(RE); 2229 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2230 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2231 DataRefImpl RelNext = Rel; 2232 info->O->moveRelocationNext(RelNext); 2233 MachO::any_relocation_info RENext; 2234 RENext = info->O->getRelocation(RelNext); 2235 if (info->O->isRelocationScattered(RENext)) 2236 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2237 else 2238 return 0; 2239 } 2240 } else { 2241 isExtern = info->O->getPlainRelocationExternal(RE); 2242 if (isExtern) { 2243 symbol_iterator RelocSym = Reloc.getSymbol(); 2244 Symbol = *RelocSym; 2245 } 2246 } 2247 reloc_found = true; 2248 break; 2249 } 2250 } 2251 if (reloc_found && isExtern) { 2252 Expected<StringRef> SymName = Symbol.getName(); 2253 if (!SymName) 2254 report_error(info->O->getFileName(), SymName.takeError()); 2255 const char *name = SymName->data(); 2256 op_info->AddSymbol.Present = 1; 2257 op_info->AddSymbol.Name = name; 2258 // For i386 extern relocation entries the value in the instruction is 2259 // the offset from the symbol, and value is already set in op_info->Value. 2260 return 1; 2261 } 2262 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2263 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2264 const char *add = GuessSymbolName(r_value, info->AddrMap); 2265 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2266 uint32_t offset = value - (r_value - pair_r_value); 2267 op_info->AddSymbol.Present = 1; 2268 if (add != nullptr) 2269 op_info->AddSymbol.Name = add; 2270 else 2271 op_info->AddSymbol.Value = r_value; 2272 op_info->SubtractSymbol.Present = 1; 2273 if (sub != nullptr) 2274 op_info->SubtractSymbol.Name = sub; 2275 else 2276 op_info->SubtractSymbol.Value = pair_r_value; 2277 op_info->Value = offset; 2278 return 1; 2279 } 2280 return 0; 2281 } 2282 if (Arch == Triple::x86_64) { 2283 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2284 return 0; 2285 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2286 // relocation entries of a linked image (if any) for an entry that matches 2287 // this segment offset. 2288 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2289 uint64_t seg_offset = Pc + Offset; 2290 bool reloc_found = false; 2291 DataRefImpl Rel; 2292 MachO::any_relocation_info RE; 2293 bool isExtern = false; 2294 SymbolRef Symbol; 2295 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2296 uint64_t RelocOffset = Reloc.getOffset(); 2297 if (RelocOffset == seg_offset) { 2298 Rel = Reloc.getRawDataRefImpl(); 2299 RE = info->O->getRelocation(Rel); 2300 // external relocation entries should always be external. 2301 isExtern = info->O->getPlainRelocationExternal(RE); 2302 if (isExtern) { 2303 symbol_iterator RelocSym = Reloc.getSymbol(); 2304 Symbol = *RelocSym; 2305 } 2306 reloc_found = true; 2307 break; 2308 } 2309 } 2310 if (reloc_found && isExtern) { 2311 // The Value passed in will be adjusted by the Pc if the instruction 2312 // adds the Pc. But for x86_64 external relocation entries the Value 2313 // is the offset from the external symbol. 2314 if (info->O->getAnyRelocationPCRel(RE)) 2315 op_info->Value -= Pc + Offset + Size; 2316 Expected<StringRef> SymName = Symbol.getName(); 2317 if (!SymName) 2318 report_error(info->O->getFileName(), SymName.takeError()); 2319 const char *name = SymName->data(); 2320 op_info->AddSymbol.Present = 1; 2321 op_info->AddSymbol.Name = name; 2322 return 1; 2323 } 2324 return 0; 2325 } 2326 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2327 // for an entry for this section offset. 2328 uint64_t sect_addr = info->S.getAddress(); 2329 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2330 bool reloc_found = false; 2331 DataRefImpl Rel; 2332 MachO::any_relocation_info RE; 2333 bool isExtern = false; 2334 SymbolRef Symbol; 2335 for (const RelocationRef &Reloc : info->S.relocations()) { 2336 uint64_t RelocOffset = Reloc.getOffset(); 2337 if (RelocOffset == sect_offset) { 2338 Rel = Reloc.getRawDataRefImpl(); 2339 RE = info->O->getRelocation(Rel); 2340 // NOTE: Scattered relocations don't exist on x86_64. 2341 isExtern = info->O->getPlainRelocationExternal(RE); 2342 if (isExtern) { 2343 symbol_iterator RelocSym = Reloc.getSymbol(); 2344 Symbol = *RelocSym; 2345 } 2346 reloc_found = true; 2347 break; 2348 } 2349 } 2350 if (reloc_found && isExtern) { 2351 // The Value passed in will be adjusted by the Pc if the instruction 2352 // adds the Pc. But for x86_64 external relocation entries the Value 2353 // is the offset from the external symbol. 2354 if (info->O->getAnyRelocationPCRel(RE)) 2355 op_info->Value -= Pc + Offset + Size; 2356 Expected<StringRef> SymName = Symbol.getName(); 2357 if (!SymName) 2358 report_error(info->O->getFileName(), SymName.takeError()); 2359 const char *name = SymName->data(); 2360 unsigned Type = info->O->getAnyRelocationType(RE); 2361 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2362 DataRefImpl RelNext = Rel; 2363 info->O->moveRelocationNext(RelNext); 2364 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2365 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2366 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2367 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2368 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2369 op_info->SubtractSymbol.Present = 1; 2370 op_info->SubtractSymbol.Name = name; 2371 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2372 Symbol = *RelocSymNext; 2373 Expected<StringRef> SymNameNext = Symbol.getName(); 2374 if (!SymNameNext) 2375 report_error(info->O->getFileName(), SymNameNext.takeError()); 2376 name = SymNameNext->data(); 2377 } 2378 } 2379 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 2380 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 2381 op_info->AddSymbol.Present = 1; 2382 op_info->AddSymbol.Name = name; 2383 return 1; 2384 } 2385 return 0; 2386 } 2387 if (Arch == Triple::arm) { 2388 if (Offset != 0 || (Size != 4 && Size != 2)) 2389 return 0; 2390 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2391 // TODO: 2392 // Search the external relocation entries of a fully linked image 2393 // (if any) for an entry that matches this segment offset. 2394 // uint32_t seg_offset = (Pc + Offset); 2395 return 0; 2396 } 2397 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2398 // for an entry for this section offset. 2399 uint32_t sect_addr = info->S.getAddress(); 2400 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2401 DataRefImpl Rel; 2402 MachO::any_relocation_info RE; 2403 bool isExtern = false; 2404 SymbolRef Symbol; 2405 bool r_scattered = false; 2406 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 2407 auto Reloc = 2408 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2409 uint64_t RelocOffset = Reloc.getOffset(); 2410 return RelocOffset == sect_offset; 2411 }); 2412 2413 if (Reloc == info->S.relocations().end()) 2414 return 0; 2415 2416 Rel = Reloc->getRawDataRefImpl(); 2417 RE = info->O->getRelocation(Rel); 2418 r_length = info->O->getAnyRelocationLength(RE); 2419 r_scattered = info->O->isRelocationScattered(RE); 2420 if (r_scattered) { 2421 r_value = info->O->getScatteredRelocationValue(RE); 2422 r_type = info->O->getScatteredRelocationType(RE); 2423 } else { 2424 r_type = info->O->getAnyRelocationType(RE); 2425 isExtern = info->O->getPlainRelocationExternal(RE); 2426 if (isExtern) { 2427 symbol_iterator RelocSym = Reloc->getSymbol(); 2428 Symbol = *RelocSym; 2429 } 2430 } 2431 if (r_type == MachO::ARM_RELOC_HALF || 2432 r_type == MachO::ARM_RELOC_SECTDIFF || 2433 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 2434 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2435 DataRefImpl RelNext = Rel; 2436 info->O->moveRelocationNext(RelNext); 2437 MachO::any_relocation_info RENext; 2438 RENext = info->O->getRelocation(RelNext); 2439 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 2440 if (info->O->isRelocationScattered(RENext)) 2441 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2442 } 2443 2444 if (isExtern) { 2445 Expected<StringRef> SymName = Symbol.getName(); 2446 if (!SymName) 2447 report_error(info->O->getFileName(), SymName.takeError()); 2448 const char *name = SymName->data(); 2449 op_info->AddSymbol.Present = 1; 2450 op_info->AddSymbol.Name = name; 2451 switch (r_type) { 2452 case MachO::ARM_RELOC_HALF: 2453 if ((r_length & 0x1) == 1) { 2454 op_info->Value = value << 16 | other_half; 2455 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2456 } else { 2457 op_info->Value = other_half << 16 | value; 2458 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2459 } 2460 break; 2461 default: 2462 break; 2463 } 2464 return 1; 2465 } 2466 // If we have a branch that is not an external relocation entry then 2467 // return 0 so the code in tryAddingSymbolicOperand() can use the 2468 // SymbolLookUp call back with the branch target address to look up the 2469 // symbol and possibility add an annotation for a symbol stub. 2470 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 2471 r_type == MachO::ARM_THUMB_RELOC_BR22)) 2472 return 0; 2473 2474 uint32_t offset = 0; 2475 if (r_type == MachO::ARM_RELOC_HALF || 2476 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2477 if ((r_length & 0x1) == 1) 2478 value = value << 16 | other_half; 2479 else 2480 value = other_half << 16 | value; 2481 } 2482 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 2483 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 2484 offset = value - r_value; 2485 value = r_value; 2486 } 2487 2488 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2489 if ((r_length & 0x1) == 1) 2490 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2491 else 2492 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2493 const char *add = GuessSymbolName(r_value, info->AddrMap); 2494 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2495 int32_t offset = value - (r_value - pair_r_value); 2496 op_info->AddSymbol.Present = 1; 2497 if (add != nullptr) 2498 op_info->AddSymbol.Name = add; 2499 else 2500 op_info->AddSymbol.Value = r_value; 2501 op_info->SubtractSymbol.Present = 1; 2502 if (sub != nullptr) 2503 op_info->SubtractSymbol.Name = sub; 2504 else 2505 op_info->SubtractSymbol.Value = pair_r_value; 2506 op_info->Value = offset; 2507 return 1; 2508 } 2509 2510 op_info->AddSymbol.Present = 1; 2511 op_info->Value = offset; 2512 if (r_type == MachO::ARM_RELOC_HALF) { 2513 if ((r_length & 0x1) == 1) 2514 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2515 else 2516 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2517 } 2518 const char *add = GuessSymbolName(value, info->AddrMap); 2519 if (add != nullptr) { 2520 op_info->AddSymbol.Name = add; 2521 return 1; 2522 } 2523 op_info->AddSymbol.Value = value; 2524 return 1; 2525 } 2526 if (Arch == Triple::aarch64) { 2527 if (Offset != 0 || Size != 4) 2528 return 0; 2529 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2530 // TODO: 2531 // Search the external relocation entries of a fully linked image 2532 // (if any) for an entry that matches this segment offset. 2533 // uint64_t seg_offset = (Pc + Offset); 2534 return 0; 2535 } 2536 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2537 // for an entry for this section offset. 2538 uint64_t sect_addr = info->S.getAddress(); 2539 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2540 auto Reloc = 2541 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2542 uint64_t RelocOffset = Reloc.getOffset(); 2543 return RelocOffset == sect_offset; 2544 }); 2545 2546 if (Reloc == info->S.relocations().end()) 2547 return 0; 2548 2549 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2550 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 2551 uint32_t r_type = info->O->getAnyRelocationType(RE); 2552 if (r_type == MachO::ARM64_RELOC_ADDEND) { 2553 DataRefImpl RelNext = Rel; 2554 info->O->moveRelocationNext(RelNext); 2555 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2556 if (value == 0) { 2557 value = info->O->getPlainRelocationSymbolNum(RENext); 2558 op_info->Value = value; 2559 } 2560 } 2561 // NOTE: Scattered relocations don't exist on arm64. 2562 if (!info->O->getPlainRelocationExternal(RE)) 2563 return 0; 2564 Expected<StringRef> SymName = Reloc->getSymbol()->getName(); 2565 if (!SymName) 2566 report_error(info->O->getFileName(), SymName.takeError()); 2567 const char *name = SymName->data(); 2568 op_info->AddSymbol.Present = 1; 2569 op_info->AddSymbol.Name = name; 2570 2571 switch (r_type) { 2572 case MachO::ARM64_RELOC_PAGE21: 2573 /* @page */ 2574 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 2575 break; 2576 case MachO::ARM64_RELOC_PAGEOFF12: 2577 /* @pageoff */ 2578 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 2579 break; 2580 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 2581 /* @gotpage */ 2582 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 2583 break; 2584 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 2585 /* @gotpageoff */ 2586 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 2587 break; 2588 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 2589 /* @tvlppage is not implemented in llvm-mc */ 2590 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 2591 break; 2592 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 2593 /* @tvlppageoff is not implemented in llvm-mc */ 2594 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 2595 break; 2596 default: 2597 case MachO::ARM64_RELOC_BRANCH26: 2598 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 2599 break; 2600 } 2601 return 1; 2602 } 2603 return 0; 2604 } 2605 2606 // GuessCstringPointer is passed the address of what might be a pointer to a 2607 // literal string in a cstring section. If that address is in a cstring section 2608 // it returns a pointer to that string. Else it returns nullptr. 2609 static const char *GuessCstringPointer(uint64_t ReferenceValue, 2610 struct DisassembleInfo *info) { 2611 for (const auto &Load : info->O->load_commands()) { 2612 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2613 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2614 for (unsigned J = 0; J < Seg.nsects; ++J) { 2615 MachO::section_64 Sec = info->O->getSection64(Load, J); 2616 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2617 if (section_type == MachO::S_CSTRING_LITERALS && 2618 ReferenceValue >= Sec.addr && 2619 ReferenceValue < Sec.addr + Sec.size) { 2620 uint64_t sect_offset = ReferenceValue - Sec.addr; 2621 uint64_t object_offset = Sec.offset + sect_offset; 2622 StringRef MachOContents = info->O->getData(); 2623 uint64_t object_size = MachOContents.size(); 2624 const char *object_addr = (const char *)MachOContents.data(); 2625 if (object_offset < object_size) { 2626 const char *name = object_addr + object_offset; 2627 return name; 2628 } else { 2629 return nullptr; 2630 } 2631 } 2632 } 2633 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2634 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2635 for (unsigned J = 0; J < Seg.nsects; ++J) { 2636 MachO::section Sec = info->O->getSection(Load, J); 2637 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2638 if (section_type == MachO::S_CSTRING_LITERALS && 2639 ReferenceValue >= Sec.addr && 2640 ReferenceValue < Sec.addr + Sec.size) { 2641 uint64_t sect_offset = ReferenceValue - Sec.addr; 2642 uint64_t object_offset = Sec.offset + sect_offset; 2643 StringRef MachOContents = info->O->getData(); 2644 uint64_t object_size = MachOContents.size(); 2645 const char *object_addr = (const char *)MachOContents.data(); 2646 if (object_offset < object_size) { 2647 const char *name = object_addr + object_offset; 2648 return name; 2649 } else { 2650 return nullptr; 2651 } 2652 } 2653 } 2654 } 2655 } 2656 return nullptr; 2657 } 2658 2659 // GuessIndirectSymbol returns the name of the indirect symbol for the 2660 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 2661 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 2662 // symbol name being referenced by the stub or pointer. 2663 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 2664 struct DisassembleInfo *info) { 2665 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 2666 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 2667 for (const auto &Load : info->O->load_commands()) { 2668 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2669 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2670 for (unsigned J = 0; J < Seg.nsects; ++J) { 2671 MachO::section_64 Sec = info->O->getSection64(Load, J); 2672 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2673 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2674 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2675 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2676 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2677 section_type == MachO::S_SYMBOL_STUBS) && 2678 ReferenceValue >= Sec.addr && 2679 ReferenceValue < Sec.addr + Sec.size) { 2680 uint32_t stride; 2681 if (section_type == MachO::S_SYMBOL_STUBS) 2682 stride = Sec.reserved2; 2683 else 2684 stride = 8; 2685 if (stride == 0) 2686 return nullptr; 2687 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2688 if (index < Dysymtab.nindirectsyms) { 2689 uint32_t indirect_symbol = 2690 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2691 if (indirect_symbol < Symtab.nsyms) { 2692 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2693 SymbolRef Symbol = *Sym; 2694 Expected<StringRef> SymName = Symbol.getName(); 2695 if (!SymName) 2696 report_error(info->O->getFileName(), SymName.takeError()); 2697 const char *name = SymName->data(); 2698 return name; 2699 } 2700 } 2701 } 2702 } 2703 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2704 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2705 for (unsigned J = 0; J < Seg.nsects; ++J) { 2706 MachO::section Sec = info->O->getSection(Load, J); 2707 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2708 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2709 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2710 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2711 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2712 section_type == MachO::S_SYMBOL_STUBS) && 2713 ReferenceValue >= Sec.addr && 2714 ReferenceValue < Sec.addr + Sec.size) { 2715 uint32_t stride; 2716 if (section_type == MachO::S_SYMBOL_STUBS) 2717 stride = Sec.reserved2; 2718 else 2719 stride = 4; 2720 if (stride == 0) 2721 return nullptr; 2722 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2723 if (index < Dysymtab.nindirectsyms) { 2724 uint32_t indirect_symbol = 2725 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2726 if (indirect_symbol < Symtab.nsyms) { 2727 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2728 SymbolRef Symbol = *Sym; 2729 Expected<StringRef> SymName = Symbol.getName(); 2730 if (!SymName) 2731 report_error(info->O->getFileName(), SymName.takeError()); 2732 const char *name = SymName->data(); 2733 return name; 2734 } 2735 } 2736 } 2737 } 2738 } 2739 } 2740 return nullptr; 2741 } 2742 2743 // method_reference() is called passing it the ReferenceName that might be 2744 // a reference it to an Objective-C method call. If so then it allocates and 2745 // assembles a method call string with the values last seen and saved in 2746 // the DisassembleInfo's class_name and selector_name fields. This is saved 2747 // into the method field of the info and any previous string is free'ed. 2748 // Then the class_name field in the info is set to nullptr. The method call 2749 // string is set into ReferenceName and ReferenceType is set to 2750 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 2751 // then both ReferenceType and ReferenceName are left unchanged. 2752 static void method_reference(struct DisassembleInfo *info, 2753 uint64_t *ReferenceType, 2754 const char **ReferenceName) { 2755 unsigned int Arch = info->O->getArch(); 2756 if (*ReferenceName != nullptr) { 2757 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 2758 if (info->selector_name != nullptr) { 2759 if (info->method != nullptr) 2760 free(info->method); 2761 if (info->class_name != nullptr) { 2762 info->method = (char *)malloc(5 + strlen(info->class_name) + 2763 strlen(info->selector_name)); 2764 if (info->method != nullptr) { 2765 strcpy(info->method, "+["); 2766 strcat(info->method, info->class_name); 2767 strcat(info->method, " "); 2768 strcat(info->method, info->selector_name); 2769 strcat(info->method, "]"); 2770 *ReferenceName = info->method; 2771 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2772 } 2773 } else { 2774 info->method = (char *)malloc(9 + strlen(info->selector_name)); 2775 if (info->method != nullptr) { 2776 if (Arch == Triple::x86_64) 2777 strcpy(info->method, "-[%rdi "); 2778 else if (Arch == Triple::aarch64) 2779 strcpy(info->method, "-[x0 "); 2780 else 2781 strcpy(info->method, "-[r? "); 2782 strcat(info->method, info->selector_name); 2783 strcat(info->method, "]"); 2784 *ReferenceName = info->method; 2785 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2786 } 2787 } 2788 info->class_name = nullptr; 2789 } 2790 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 2791 if (info->selector_name != nullptr) { 2792 if (info->method != nullptr) 2793 free(info->method); 2794 info->method = (char *)malloc(17 + strlen(info->selector_name)); 2795 if (info->method != nullptr) { 2796 if (Arch == Triple::x86_64) 2797 strcpy(info->method, "-[[%rdi super] "); 2798 else if (Arch == Triple::aarch64) 2799 strcpy(info->method, "-[[x0 super] "); 2800 else 2801 strcpy(info->method, "-[[r? super] "); 2802 strcat(info->method, info->selector_name); 2803 strcat(info->method, "]"); 2804 *ReferenceName = info->method; 2805 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2806 } 2807 info->class_name = nullptr; 2808 } 2809 } 2810 } 2811 } 2812 2813 // GuessPointerPointer() is passed the address of what might be a pointer to 2814 // a reference to an Objective-C class, selector, message ref or cfstring. 2815 // If so the value of the pointer is returned and one of the booleans are set 2816 // to true. If not zero is returned and all the booleans are set to false. 2817 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 2818 struct DisassembleInfo *info, 2819 bool &classref, bool &selref, bool &msgref, 2820 bool &cfstring) { 2821 classref = false; 2822 selref = false; 2823 msgref = false; 2824 cfstring = false; 2825 for (const auto &Load : info->O->load_commands()) { 2826 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2827 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2828 for (unsigned J = 0; J < Seg.nsects; ++J) { 2829 MachO::section_64 Sec = info->O->getSection64(Load, J); 2830 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 2831 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2832 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 2833 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 2834 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 2835 ReferenceValue >= Sec.addr && 2836 ReferenceValue < Sec.addr + Sec.size) { 2837 uint64_t sect_offset = ReferenceValue - Sec.addr; 2838 uint64_t object_offset = Sec.offset + sect_offset; 2839 StringRef MachOContents = info->O->getData(); 2840 uint64_t object_size = MachOContents.size(); 2841 const char *object_addr = (const char *)MachOContents.data(); 2842 if (object_offset < object_size) { 2843 uint64_t pointer_value; 2844 memcpy(&pointer_value, object_addr + object_offset, 2845 sizeof(uint64_t)); 2846 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2847 sys::swapByteOrder(pointer_value); 2848 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 2849 selref = true; 2850 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2851 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 2852 classref = true; 2853 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 2854 ReferenceValue + 8 < Sec.addr + Sec.size) { 2855 msgref = true; 2856 memcpy(&pointer_value, object_addr + object_offset + 8, 2857 sizeof(uint64_t)); 2858 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2859 sys::swapByteOrder(pointer_value); 2860 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 2861 cfstring = true; 2862 return pointer_value; 2863 } else { 2864 return 0; 2865 } 2866 } 2867 } 2868 } 2869 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 2870 } 2871 return 0; 2872 } 2873 2874 // get_pointer_64 returns a pointer to the bytes in the object file at the 2875 // Address from a section in the Mach-O file. And indirectly returns the 2876 // offset into the section, number of bytes left in the section past the offset 2877 // and which section is was being referenced. If the Address is not in a 2878 // section nullptr is returned. 2879 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 2880 uint32_t &left, SectionRef &S, 2881 DisassembleInfo *info, 2882 bool objc_only = false) { 2883 offset = 0; 2884 left = 0; 2885 S = SectionRef(); 2886 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 2887 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 2888 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 2889 if (SectSize == 0) 2890 continue; 2891 if (objc_only) { 2892 StringRef SectName; 2893 ((*(info->Sections))[SectIdx]).getName(SectName); 2894 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 2895 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 2896 if (SegName != "__OBJC" && SectName != "__cstring") 2897 continue; 2898 } 2899 if (Address >= SectAddress && Address < SectAddress + SectSize) { 2900 S = (*(info->Sections))[SectIdx]; 2901 offset = Address - SectAddress; 2902 left = SectSize - offset; 2903 StringRef SectContents; 2904 ((*(info->Sections))[SectIdx]).getContents(SectContents); 2905 return SectContents.data() + offset; 2906 } 2907 } 2908 return nullptr; 2909 } 2910 2911 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 2912 uint32_t &left, SectionRef &S, 2913 DisassembleInfo *info, 2914 bool objc_only = false) { 2915 return get_pointer_64(Address, offset, left, S, info, objc_only); 2916 } 2917 2918 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 2919 // the symbol indirectly through n_value. Based on the relocation information 2920 // for the specified section offset in the specified section reference. 2921 // If no relocation information is found and a non-zero ReferenceValue for the 2922 // symbol is passed, look up that address in the info's AddrMap. 2923 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 2924 DisassembleInfo *info, uint64_t &n_value, 2925 uint64_t ReferenceValue = 0) { 2926 n_value = 0; 2927 if (!info->verbose) 2928 return nullptr; 2929 2930 // See if there is an external relocation entry at the sect_offset. 2931 bool reloc_found = false; 2932 DataRefImpl Rel; 2933 MachO::any_relocation_info RE; 2934 bool isExtern = false; 2935 SymbolRef Symbol; 2936 for (const RelocationRef &Reloc : S.relocations()) { 2937 uint64_t RelocOffset = Reloc.getOffset(); 2938 if (RelocOffset == sect_offset) { 2939 Rel = Reloc.getRawDataRefImpl(); 2940 RE = info->O->getRelocation(Rel); 2941 if (info->O->isRelocationScattered(RE)) 2942 continue; 2943 isExtern = info->O->getPlainRelocationExternal(RE); 2944 if (isExtern) { 2945 symbol_iterator RelocSym = Reloc.getSymbol(); 2946 Symbol = *RelocSym; 2947 } 2948 reloc_found = true; 2949 break; 2950 } 2951 } 2952 // If there is an external relocation entry for a symbol in this section 2953 // at this section_offset then use that symbol's value for the n_value 2954 // and return its name. 2955 const char *SymbolName = nullptr; 2956 if (reloc_found && isExtern) { 2957 n_value = Symbol.getValue(); 2958 Expected<StringRef> NameOrError = Symbol.getName(); 2959 if (!NameOrError) 2960 report_error(info->O->getFileName(), NameOrError.takeError()); 2961 StringRef Name = *NameOrError; 2962 if (!Name.empty()) { 2963 SymbolName = Name.data(); 2964 return SymbolName; 2965 } 2966 } 2967 2968 // TODO: For fully linked images, look through the external relocation 2969 // entries off the dynamic symtab command. For these the r_offset is from the 2970 // start of the first writeable segment in the Mach-O file. So the offset 2971 // to this section from that segment is passed to this routine by the caller, 2972 // as the database_offset. Which is the difference of the section's starting 2973 // address and the first writable segment. 2974 // 2975 // NOTE: need add passing the database_offset to this routine. 2976 2977 // We did not find an external relocation entry so look up the ReferenceValue 2978 // as an address of a symbol and if found return that symbol's name. 2979 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 2980 2981 return SymbolName; 2982 } 2983 2984 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 2985 DisassembleInfo *info, 2986 uint32_t ReferenceValue) { 2987 uint64_t n_value64; 2988 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 2989 } 2990 2991 // These are structs in the Objective-C meta data and read to produce the 2992 // comments for disassembly. While these are part of the ABI they are no 2993 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 2994 // . 2995 2996 // The cfstring object in a 64-bit Mach-O file. 2997 struct cfstring64_t { 2998 uint64_t isa; // class64_t * (64-bit pointer) 2999 uint64_t flags; // flag bits 3000 uint64_t characters; // char * (64-bit pointer) 3001 uint64_t length; // number of non-NULL characters in above 3002 }; 3003 3004 // The class object in a 64-bit Mach-O file. 3005 struct class64_t { 3006 uint64_t isa; // class64_t * (64-bit pointer) 3007 uint64_t superclass; // class64_t * (64-bit pointer) 3008 uint64_t cache; // Cache (64-bit pointer) 3009 uint64_t vtable; // IMP * (64-bit pointer) 3010 uint64_t data; // class_ro64_t * (64-bit pointer) 3011 }; 3012 3013 struct class32_t { 3014 uint32_t isa; /* class32_t * (32-bit pointer) */ 3015 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3016 uint32_t cache; /* Cache (32-bit pointer) */ 3017 uint32_t vtable; /* IMP * (32-bit pointer) */ 3018 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3019 }; 3020 3021 struct class_ro64_t { 3022 uint32_t flags; 3023 uint32_t instanceStart; 3024 uint32_t instanceSize; 3025 uint32_t reserved; 3026 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3027 uint64_t name; // const char * (64-bit pointer) 3028 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3029 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3030 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3031 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3032 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3033 }; 3034 3035 struct class_ro32_t { 3036 uint32_t flags; 3037 uint32_t instanceStart; 3038 uint32_t instanceSize; 3039 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3040 uint32_t name; /* const char * (32-bit pointer) */ 3041 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3042 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3043 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3044 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3045 uint32_t baseProperties; /* const struct objc_property_list * 3046 (32-bit pointer) */ 3047 }; 3048 3049 /* Values for class_ro{64,32}_t->flags */ 3050 #define RO_META (1 << 0) 3051 #define RO_ROOT (1 << 1) 3052 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3053 3054 struct method_list64_t { 3055 uint32_t entsize; 3056 uint32_t count; 3057 /* struct method64_t first; These structures follow inline */ 3058 }; 3059 3060 struct method_list32_t { 3061 uint32_t entsize; 3062 uint32_t count; 3063 /* struct method32_t first; These structures follow inline */ 3064 }; 3065 3066 struct method64_t { 3067 uint64_t name; /* SEL (64-bit pointer) */ 3068 uint64_t types; /* const char * (64-bit pointer) */ 3069 uint64_t imp; /* IMP (64-bit pointer) */ 3070 }; 3071 3072 struct method32_t { 3073 uint32_t name; /* SEL (32-bit pointer) */ 3074 uint32_t types; /* const char * (32-bit pointer) */ 3075 uint32_t imp; /* IMP (32-bit pointer) */ 3076 }; 3077 3078 struct protocol_list64_t { 3079 uint64_t count; /* uintptr_t (a 64-bit value) */ 3080 /* struct protocol64_t * list[0]; These pointers follow inline */ 3081 }; 3082 3083 struct protocol_list32_t { 3084 uint32_t count; /* uintptr_t (a 32-bit value) */ 3085 /* struct protocol32_t * list[0]; These pointers follow inline */ 3086 }; 3087 3088 struct protocol64_t { 3089 uint64_t isa; /* id * (64-bit pointer) */ 3090 uint64_t name; /* const char * (64-bit pointer) */ 3091 uint64_t protocols; /* struct protocol_list64_t * 3092 (64-bit pointer) */ 3093 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3094 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3095 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3096 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3097 uint64_t instanceProperties; /* struct objc_property_list * 3098 (64-bit pointer) */ 3099 }; 3100 3101 struct protocol32_t { 3102 uint32_t isa; /* id * (32-bit pointer) */ 3103 uint32_t name; /* const char * (32-bit pointer) */ 3104 uint32_t protocols; /* struct protocol_list_t * 3105 (32-bit pointer) */ 3106 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3107 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3108 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3109 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3110 uint32_t instanceProperties; /* struct objc_property_list * 3111 (32-bit pointer) */ 3112 }; 3113 3114 struct ivar_list64_t { 3115 uint32_t entsize; 3116 uint32_t count; 3117 /* struct ivar64_t first; These structures follow inline */ 3118 }; 3119 3120 struct ivar_list32_t { 3121 uint32_t entsize; 3122 uint32_t count; 3123 /* struct ivar32_t first; These structures follow inline */ 3124 }; 3125 3126 struct ivar64_t { 3127 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3128 uint64_t name; /* const char * (64-bit pointer) */ 3129 uint64_t type; /* const char * (64-bit pointer) */ 3130 uint32_t alignment; 3131 uint32_t size; 3132 }; 3133 3134 struct ivar32_t { 3135 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3136 uint32_t name; /* const char * (32-bit pointer) */ 3137 uint32_t type; /* const char * (32-bit pointer) */ 3138 uint32_t alignment; 3139 uint32_t size; 3140 }; 3141 3142 struct objc_property_list64 { 3143 uint32_t entsize; 3144 uint32_t count; 3145 /* struct objc_property64 first; These structures follow inline */ 3146 }; 3147 3148 struct objc_property_list32 { 3149 uint32_t entsize; 3150 uint32_t count; 3151 /* struct objc_property32 first; These structures follow inline */ 3152 }; 3153 3154 struct objc_property64 { 3155 uint64_t name; /* const char * (64-bit pointer) */ 3156 uint64_t attributes; /* const char * (64-bit pointer) */ 3157 }; 3158 3159 struct objc_property32 { 3160 uint32_t name; /* const char * (32-bit pointer) */ 3161 uint32_t attributes; /* const char * (32-bit pointer) */ 3162 }; 3163 3164 struct category64_t { 3165 uint64_t name; /* const char * (64-bit pointer) */ 3166 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3167 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3168 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3169 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3170 uint64_t instanceProperties; /* struct objc_property_list * 3171 (64-bit pointer) */ 3172 }; 3173 3174 struct category32_t { 3175 uint32_t name; /* const char * (32-bit pointer) */ 3176 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3177 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3178 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3179 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3180 uint32_t instanceProperties; /* struct objc_property_list * 3181 (32-bit pointer) */ 3182 }; 3183 3184 struct objc_image_info64 { 3185 uint32_t version; 3186 uint32_t flags; 3187 }; 3188 struct objc_image_info32 { 3189 uint32_t version; 3190 uint32_t flags; 3191 }; 3192 struct imageInfo_t { 3193 uint32_t version; 3194 uint32_t flags; 3195 }; 3196 /* masks for objc_image_info.flags */ 3197 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3198 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3199 3200 struct message_ref64 { 3201 uint64_t imp; /* IMP (64-bit pointer) */ 3202 uint64_t sel; /* SEL (64-bit pointer) */ 3203 }; 3204 3205 struct message_ref32 { 3206 uint32_t imp; /* IMP (32-bit pointer) */ 3207 uint32_t sel; /* SEL (32-bit pointer) */ 3208 }; 3209 3210 // Objective-C 1 (32-bit only) meta data structs. 3211 3212 struct objc_module_t { 3213 uint32_t version; 3214 uint32_t size; 3215 uint32_t name; /* char * (32-bit pointer) */ 3216 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3217 }; 3218 3219 struct objc_symtab_t { 3220 uint32_t sel_ref_cnt; 3221 uint32_t refs; /* SEL * (32-bit pointer) */ 3222 uint16_t cls_def_cnt; 3223 uint16_t cat_def_cnt; 3224 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3225 }; 3226 3227 struct objc_class_t { 3228 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3229 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3230 uint32_t name; /* const char * (32-bit pointer) */ 3231 int32_t version; 3232 int32_t info; 3233 int32_t instance_size; 3234 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3235 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3236 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3237 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3238 }; 3239 3240 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3241 // class is not a metaclass 3242 #define CLS_CLASS 0x1 3243 // class is a metaclass 3244 #define CLS_META 0x2 3245 3246 struct objc_category_t { 3247 uint32_t category_name; /* char * (32-bit pointer) */ 3248 uint32_t class_name; /* char * (32-bit pointer) */ 3249 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3250 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3251 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3252 }; 3253 3254 struct objc_ivar_t { 3255 uint32_t ivar_name; /* char * (32-bit pointer) */ 3256 uint32_t ivar_type; /* char * (32-bit pointer) */ 3257 int32_t ivar_offset; 3258 }; 3259 3260 struct objc_ivar_list_t { 3261 int32_t ivar_count; 3262 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3263 }; 3264 3265 struct objc_method_list_t { 3266 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3267 int32_t method_count; 3268 // struct objc_method_t method_list[1]; /* variable length structure */ 3269 }; 3270 3271 struct objc_method_t { 3272 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3273 uint32_t method_types; /* char * (32-bit pointer) */ 3274 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3275 (32-bit pointer) */ 3276 }; 3277 3278 struct objc_protocol_list_t { 3279 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3280 int32_t count; 3281 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3282 // (32-bit pointer) */ 3283 }; 3284 3285 struct objc_protocol_t { 3286 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3287 uint32_t protocol_name; /* char * (32-bit pointer) */ 3288 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3289 uint32_t instance_methods; /* struct objc_method_description_list * 3290 (32-bit pointer) */ 3291 uint32_t class_methods; /* struct objc_method_description_list * 3292 (32-bit pointer) */ 3293 }; 3294 3295 struct objc_method_description_list_t { 3296 int32_t count; 3297 // struct objc_method_description_t list[1]; 3298 }; 3299 3300 struct objc_method_description_t { 3301 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3302 uint32_t types; /* char * (32-bit pointer) */ 3303 }; 3304 3305 inline void swapStruct(struct cfstring64_t &cfs) { 3306 sys::swapByteOrder(cfs.isa); 3307 sys::swapByteOrder(cfs.flags); 3308 sys::swapByteOrder(cfs.characters); 3309 sys::swapByteOrder(cfs.length); 3310 } 3311 3312 inline void swapStruct(struct class64_t &c) { 3313 sys::swapByteOrder(c.isa); 3314 sys::swapByteOrder(c.superclass); 3315 sys::swapByteOrder(c.cache); 3316 sys::swapByteOrder(c.vtable); 3317 sys::swapByteOrder(c.data); 3318 } 3319 3320 inline void swapStruct(struct class32_t &c) { 3321 sys::swapByteOrder(c.isa); 3322 sys::swapByteOrder(c.superclass); 3323 sys::swapByteOrder(c.cache); 3324 sys::swapByteOrder(c.vtable); 3325 sys::swapByteOrder(c.data); 3326 } 3327 3328 inline void swapStruct(struct class_ro64_t &cro) { 3329 sys::swapByteOrder(cro.flags); 3330 sys::swapByteOrder(cro.instanceStart); 3331 sys::swapByteOrder(cro.instanceSize); 3332 sys::swapByteOrder(cro.reserved); 3333 sys::swapByteOrder(cro.ivarLayout); 3334 sys::swapByteOrder(cro.name); 3335 sys::swapByteOrder(cro.baseMethods); 3336 sys::swapByteOrder(cro.baseProtocols); 3337 sys::swapByteOrder(cro.ivars); 3338 sys::swapByteOrder(cro.weakIvarLayout); 3339 sys::swapByteOrder(cro.baseProperties); 3340 } 3341 3342 inline void swapStruct(struct class_ro32_t &cro) { 3343 sys::swapByteOrder(cro.flags); 3344 sys::swapByteOrder(cro.instanceStart); 3345 sys::swapByteOrder(cro.instanceSize); 3346 sys::swapByteOrder(cro.ivarLayout); 3347 sys::swapByteOrder(cro.name); 3348 sys::swapByteOrder(cro.baseMethods); 3349 sys::swapByteOrder(cro.baseProtocols); 3350 sys::swapByteOrder(cro.ivars); 3351 sys::swapByteOrder(cro.weakIvarLayout); 3352 sys::swapByteOrder(cro.baseProperties); 3353 } 3354 3355 inline void swapStruct(struct method_list64_t &ml) { 3356 sys::swapByteOrder(ml.entsize); 3357 sys::swapByteOrder(ml.count); 3358 } 3359 3360 inline void swapStruct(struct method_list32_t &ml) { 3361 sys::swapByteOrder(ml.entsize); 3362 sys::swapByteOrder(ml.count); 3363 } 3364 3365 inline void swapStruct(struct method64_t &m) { 3366 sys::swapByteOrder(m.name); 3367 sys::swapByteOrder(m.types); 3368 sys::swapByteOrder(m.imp); 3369 } 3370 3371 inline void swapStruct(struct method32_t &m) { 3372 sys::swapByteOrder(m.name); 3373 sys::swapByteOrder(m.types); 3374 sys::swapByteOrder(m.imp); 3375 } 3376 3377 inline void swapStruct(struct protocol_list64_t &pl) { 3378 sys::swapByteOrder(pl.count); 3379 } 3380 3381 inline void swapStruct(struct protocol_list32_t &pl) { 3382 sys::swapByteOrder(pl.count); 3383 } 3384 3385 inline void swapStruct(struct protocol64_t &p) { 3386 sys::swapByteOrder(p.isa); 3387 sys::swapByteOrder(p.name); 3388 sys::swapByteOrder(p.protocols); 3389 sys::swapByteOrder(p.instanceMethods); 3390 sys::swapByteOrder(p.classMethods); 3391 sys::swapByteOrder(p.optionalInstanceMethods); 3392 sys::swapByteOrder(p.optionalClassMethods); 3393 sys::swapByteOrder(p.instanceProperties); 3394 } 3395 3396 inline void swapStruct(struct protocol32_t &p) { 3397 sys::swapByteOrder(p.isa); 3398 sys::swapByteOrder(p.name); 3399 sys::swapByteOrder(p.protocols); 3400 sys::swapByteOrder(p.instanceMethods); 3401 sys::swapByteOrder(p.classMethods); 3402 sys::swapByteOrder(p.optionalInstanceMethods); 3403 sys::swapByteOrder(p.optionalClassMethods); 3404 sys::swapByteOrder(p.instanceProperties); 3405 } 3406 3407 inline void swapStruct(struct ivar_list64_t &il) { 3408 sys::swapByteOrder(il.entsize); 3409 sys::swapByteOrder(il.count); 3410 } 3411 3412 inline void swapStruct(struct ivar_list32_t &il) { 3413 sys::swapByteOrder(il.entsize); 3414 sys::swapByteOrder(il.count); 3415 } 3416 3417 inline void swapStruct(struct ivar64_t &i) { 3418 sys::swapByteOrder(i.offset); 3419 sys::swapByteOrder(i.name); 3420 sys::swapByteOrder(i.type); 3421 sys::swapByteOrder(i.alignment); 3422 sys::swapByteOrder(i.size); 3423 } 3424 3425 inline void swapStruct(struct ivar32_t &i) { 3426 sys::swapByteOrder(i.offset); 3427 sys::swapByteOrder(i.name); 3428 sys::swapByteOrder(i.type); 3429 sys::swapByteOrder(i.alignment); 3430 sys::swapByteOrder(i.size); 3431 } 3432 3433 inline void swapStruct(struct objc_property_list64 &pl) { 3434 sys::swapByteOrder(pl.entsize); 3435 sys::swapByteOrder(pl.count); 3436 } 3437 3438 inline void swapStruct(struct objc_property_list32 &pl) { 3439 sys::swapByteOrder(pl.entsize); 3440 sys::swapByteOrder(pl.count); 3441 } 3442 3443 inline void swapStruct(struct objc_property64 &op) { 3444 sys::swapByteOrder(op.name); 3445 sys::swapByteOrder(op.attributes); 3446 } 3447 3448 inline void swapStruct(struct objc_property32 &op) { 3449 sys::swapByteOrder(op.name); 3450 sys::swapByteOrder(op.attributes); 3451 } 3452 3453 inline void swapStruct(struct category64_t &c) { 3454 sys::swapByteOrder(c.name); 3455 sys::swapByteOrder(c.cls); 3456 sys::swapByteOrder(c.instanceMethods); 3457 sys::swapByteOrder(c.classMethods); 3458 sys::swapByteOrder(c.protocols); 3459 sys::swapByteOrder(c.instanceProperties); 3460 } 3461 3462 inline void swapStruct(struct category32_t &c) { 3463 sys::swapByteOrder(c.name); 3464 sys::swapByteOrder(c.cls); 3465 sys::swapByteOrder(c.instanceMethods); 3466 sys::swapByteOrder(c.classMethods); 3467 sys::swapByteOrder(c.protocols); 3468 sys::swapByteOrder(c.instanceProperties); 3469 } 3470 3471 inline void swapStruct(struct objc_image_info64 &o) { 3472 sys::swapByteOrder(o.version); 3473 sys::swapByteOrder(o.flags); 3474 } 3475 3476 inline void swapStruct(struct objc_image_info32 &o) { 3477 sys::swapByteOrder(o.version); 3478 sys::swapByteOrder(o.flags); 3479 } 3480 3481 inline void swapStruct(struct imageInfo_t &o) { 3482 sys::swapByteOrder(o.version); 3483 sys::swapByteOrder(o.flags); 3484 } 3485 3486 inline void swapStruct(struct message_ref64 &mr) { 3487 sys::swapByteOrder(mr.imp); 3488 sys::swapByteOrder(mr.sel); 3489 } 3490 3491 inline void swapStruct(struct message_ref32 &mr) { 3492 sys::swapByteOrder(mr.imp); 3493 sys::swapByteOrder(mr.sel); 3494 } 3495 3496 inline void swapStruct(struct objc_module_t &module) { 3497 sys::swapByteOrder(module.version); 3498 sys::swapByteOrder(module.size); 3499 sys::swapByteOrder(module.name); 3500 sys::swapByteOrder(module.symtab); 3501 } 3502 3503 inline void swapStruct(struct objc_symtab_t &symtab) { 3504 sys::swapByteOrder(symtab.sel_ref_cnt); 3505 sys::swapByteOrder(symtab.refs); 3506 sys::swapByteOrder(symtab.cls_def_cnt); 3507 sys::swapByteOrder(symtab.cat_def_cnt); 3508 } 3509 3510 inline void swapStruct(struct objc_class_t &objc_class) { 3511 sys::swapByteOrder(objc_class.isa); 3512 sys::swapByteOrder(objc_class.super_class); 3513 sys::swapByteOrder(objc_class.name); 3514 sys::swapByteOrder(objc_class.version); 3515 sys::swapByteOrder(objc_class.info); 3516 sys::swapByteOrder(objc_class.instance_size); 3517 sys::swapByteOrder(objc_class.ivars); 3518 sys::swapByteOrder(objc_class.methodLists); 3519 sys::swapByteOrder(objc_class.cache); 3520 sys::swapByteOrder(objc_class.protocols); 3521 } 3522 3523 inline void swapStruct(struct objc_category_t &objc_category) { 3524 sys::swapByteOrder(objc_category.category_name); 3525 sys::swapByteOrder(objc_category.class_name); 3526 sys::swapByteOrder(objc_category.instance_methods); 3527 sys::swapByteOrder(objc_category.class_methods); 3528 sys::swapByteOrder(objc_category.protocols); 3529 } 3530 3531 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 3532 sys::swapByteOrder(objc_ivar_list.ivar_count); 3533 } 3534 3535 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 3536 sys::swapByteOrder(objc_ivar.ivar_name); 3537 sys::swapByteOrder(objc_ivar.ivar_type); 3538 sys::swapByteOrder(objc_ivar.ivar_offset); 3539 } 3540 3541 inline void swapStruct(struct objc_method_list_t &method_list) { 3542 sys::swapByteOrder(method_list.obsolete); 3543 sys::swapByteOrder(method_list.method_count); 3544 } 3545 3546 inline void swapStruct(struct objc_method_t &method) { 3547 sys::swapByteOrder(method.method_name); 3548 sys::swapByteOrder(method.method_types); 3549 sys::swapByteOrder(method.method_imp); 3550 } 3551 3552 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 3553 sys::swapByteOrder(protocol_list.next); 3554 sys::swapByteOrder(protocol_list.count); 3555 } 3556 3557 inline void swapStruct(struct objc_protocol_t &protocol) { 3558 sys::swapByteOrder(protocol.isa); 3559 sys::swapByteOrder(protocol.protocol_name); 3560 sys::swapByteOrder(protocol.protocol_list); 3561 sys::swapByteOrder(protocol.instance_methods); 3562 sys::swapByteOrder(protocol.class_methods); 3563 } 3564 3565 inline void swapStruct(struct objc_method_description_list_t &mdl) { 3566 sys::swapByteOrder(mdl.count); 3567 } 3568 3569 inline void swapStruct(struct objc_method_description_t &md) { 3570 sys::swapByteOrder(md.name); 3571 sys::swapByteOrder(md.types); 3572 } 3573 3574 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 3575 struct DisassembleInfo *info); 3576 3577 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 3578 // to an Objective-C class and returns the class name. It is also passed the 3579 // address of the pointer, so when the pointer is zero as it can be in an .o 3580 // file, that is used to look for an external relocation entry with a symbol 3581 // name. 3582 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 3583 uint64_t ReferenceValue, 3584 struct DisassembleInfo *info) { 3585 const char *r; 3586 uint32_t offset, left; 3587 SectionRef S; 3588 3589 // The pointer_value can be 0 in an object file and have a relocation 3590 // entry for the class symbol at the ReferenceValue (the address of the 3591 // pointer). 3592 if (pointer_value == 0) { 3593 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3594 if (r == nullptr || left < sizeof(uint64_t)) 3595 return nullptr; 3596 uint64_t n_value; 3597 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3598 if (symbol_name == nullptr) 3599 return nullptr; 3600 const char *class_name = strrchr(symbol_name, '$'); 3601 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 3602 return class_name + 2; 3603 else 3604 return nullptr; 3605 } 3606 3607 // The case were the pointer_value is non-zero and points to a class defined 3608 // in this Mach-O file. 3609 r = get_pointer_64(pointer_value, offset, left, S, info); 3610 if (r == nullptr || left < sizeof(struct class64_t)) 3611 return nullptr; 3612 struct class64_t c; 3613 memcpy(&c, r, sizeof(struct class64_t)); 3614 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3615 swapStruct(c); 3616 if (c.data == 0) 3617 return nullptr; 3618 r = get_pointer_64(c.data, offset, left, S, info); 3619 if (r == nullptr || left < sizeof(struct class_ro64_t)) 3620 return nullptr; 3621 struct class_ro64_t cro; 3622 memcpy(&cro, r, sizeof(struct class_ro64_t)); 3623 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3624 swapStruct(cro); 3625 if (cro.name == 0) 3626 return nullptr; 3627 const char *name = get_pointer_64(cro.name, offset, left, S, info); 3628 return name; 3629 } 3630 3631 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 3632 // pointer to a cfstring and returns its name or nullptr. 3633 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 3634 struct DisassembleInfo *info) { 3635 const char *r, *name; 3636 uint32_t offset, left; 3637 SectionRef S; 3638 struct cfstring64_t cfs; 3639 uint64_t cfs_characters; 3640 3641 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3642 if (r == nullptr || left < sizeof(struct cfstring64_t)) 3643 return nullptr; 3644 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 3645 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3646 swapStruct(cfs); 3647 if (cfs.characters == 0) { 3648 uint64_t n_value; 3649 const char *symbol_name = get_symbol_64( 3650 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 3651 if (symbol_name == nullptr) 3652 return nullptr; 3653 cfs_characters = n_value; 3654 } else 3655 cfs_characters = cfs.characters; 3656 name = get_pointer_64(cfs_characters, offset, left, S, info); 3657 3658 return name; 3659 } 3660 3661 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 3662 // of a pointer to an Objective-C selector reference when the pointer value is 3663 // zero as in a .o file and is likely to have a external relocation entry with 3664 // who's symbol's n_value is the real pointer to the selector name. If that is 3665 // the case the real pointer to the selector name is returned else 0 is 3666 // returned 3667 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 3668 struct DisassembleInfo *info) { 3669 uint32_t offset, left; 3670 SectionRef S; 3671 3672 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 3673 if (r == nullptr || left < sizeof(uint64_t)) 3674 return 0; 3675 uint64_t n_value; 3676 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3677 if (symbol_name == nullptr) 3678 return 0; 3679 return n_value; 3680 } 3681 3682 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 3683 const char *sectname) { 3684 for (const SectionRef &Section : O->sections()) { 3685 StringRef SectName; 3686 Section.getName(SectName); 3687 DataRefImpl Ref = Section.getRawDataRefImpl(); 3688 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3689 if (SegName == segname && SectName == sectname) 3690 return Section; 3691 } 3692 return SectionRef(); 3693 } 3694 3695 static void 3696 walk_pointer_list_64(const char *listname, const SectionRef S, 3697 MachOObjectFile *O, struct DisassembleInfo *info, 3698 void (*func)(uint64_t, struct DisassembleInfo *info)) { 3699 if (S == SectionRef()) 3700 return; 3701 3702 StringRef SectName; 3703 S.getName(SectName); 3704 DataRefImpl Ref = S.getRawDataRefImpl(); 3705 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3706 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3707 3708 StringRef BytesStr; 3709 S.getContents(BytesStr); 3710 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3711 3712 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 3713 uint32_t left = S.getSize() - i; 3714 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 3715 uint64_t p = 0; 3716 memcpy(&p, Contents + i, size); 3717 if (i + sizeof(uint64_t) > S.getSize()) 3718 outs() << listname << " list pointer extends past end of (" << SegName 3719 << "," << SectName << ") section\n"; 3720 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 3721 3722 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3723 sys::swapByteOrder(p); 3724 3725 uint64_t n_value = 0; 3726 const char *name = get_symbol_64(i, S, info, n_value, p); 3727 if (name == nullptr) 3728 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 3729 3730 if (n_value != 0) { 3731 outs() << format("0x%" PRIx64, n_value); 3732 if (p != 0) 3733 outs() << " + " << format("0x%" PRIx64, p); 3734 } else 3735 outs() << format("0x%" PRIx64, p); 3736 if (name != nullptr) 3737 outs() << " " << name; 3738 outs() << "\n"; 3739 3740 p += n_value; 3741 if (func) 3742 func(p, info); 3743 } 3744 } 3745 3746 static void 3747 walk_pointer_list_32(const char *listname, const SectionRef S, 3748 MachOObjectFile *O, struct DisassembleInfo *info, 3749 void (*func)(uint32_t, struct DisassembleInfo *info)) { 3750 if (S == SectionRef()) 3751 return; 3752 3753 StringRef SectName; 3754 S.getName(SectName); 3755 DataRefImpl Ref = S.getRawDataRefImpl(); 3756 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3757 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3758 3759 StringRef BytesStr; 3760 S.getContents(BytesStr); 3761 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3762 3763 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 3764 uint32_t left = S.getSize() - i; 3765 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 3766 uint32_t p = 0; 3767 memcpy(&p, Contents + i, size); 3768 if (i + sizeof(uint32_t) > S.getSize()) 3769 outs() << listname << " list pointer extends past end of (" << SegName 3770 << "," << SectName << ") section\n"; 3771 uint32_t Address = S.getAddress() + i; 3772 outs() << format("%08" PRIx32, Address) << " "; 3773 3774 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3775 sys::swapByteOrder(p); 3776 outs() << format("0x%" PRIx32, p); 3777 3778 const char *name = get_symbol_32(i, S, info, p); 3779 if (name != nullptr) 3780 outs() << " " << name; 3781 outs() << "\n"; 3782 3783 if (func) 3784 func(p, info); 3785 } 3786 } 3787 3788 static void print_layout_map(const char *layout_map, uint32_t left) { 3789 if (layout_map == nullptr) 3790 return; 3791 outs() << " layout map: "; 3792 do { 3793 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 3794 left--; 3795 layout_map++; 3796 } while (*layout_map != '\0' && left != 0); 3797 outs() << "\n"; 3798 } 3799 3800 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 3801 uint32_t offset, left; 3802 SectionRef S; 3803 const char *layout_map; 3804 3805 if (p == 0) 3806 return; 3807 layout_map = get_pointer_64(p, offset, left, S, info); 3808 print_layout_map(layout_map, left); 3809 } 3810 3811 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 3812 uint32_t offset, left; 3813 SectionRef S; 3814 const char *layout_map; 3815 3816 if (p == 0) 3817 return; 3818 layout_map = get_pointer_32(p, offset, left, S, info); 3819 print_layout_map(layout_map, left); 3820 } 3821 3822 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 3823 const char *indent) { 3824 struct method_list64_t ml; 3825 struct method64_t m; 3826 const char *r; 3827 uint32_t offset, xoffset, left, i; 3828 SectionRef S, xS; 3829 const char *name, *sym_name; 3830 uint64_t n_value; 3831 3832 r = get_pointer_64(p, offset, left, S, info); 3833 if (r == nullptr) 3834 return; 3835 memset(&ml, '\0', sizeof(struct method_list64_t)); 3836 if (left < sizeof(struct method_list64_t)) { 3837 memcpy(&ml, r, left); 3838 outs() << " (method_list_t entends past the end of the section)\n"; 3839 } else 3840 memcpy(&ml, r, sizeof(struct method_list64_t)); 3841 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3842 swapStruct(ml); 3843 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3844 outs() << indent << "\t\t count " << ml.count << "\n"; 3845 3846 p += sizeof(struct method_list64_t); 3847 offset += sizeof(struct method_list64_t); 3848 for (i = 0; i < ml.count; i++) { 3849 r = get_pointer_64(p, offset, left, S, info); 3850 if (r == nullptr) 3851 return; 3852 memset(&m, '\0', sizeof(struct method64_t)); 3853 if (left < sizeof(struct method64_t)) { 3854 memcpy(&m, r, left); 3855 outs() << indent << " (method_t extends past the end of the section)\n"; 3856 } else 3857 memcpy(&m, r, sizeof(struct method64_t)); 3858 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3859 swapStruct(m); 3860 3861 outs() << indent << "\t\t name "; 3862 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 3863 info, n_value, m.name); 3864 if (n_value != 0) { 3865 if (info->verbose && sym_name != nullptr) 3866 outs() << sym_name; 3867 else 3868 outs() << format("0x%" PRIx64, n_value); 3869 if (m.name != 0) 3870 outs() << " + " << format("0x%" PRIx64, m.name); 3871 } else 3872 outs() << format("0x%" PRIx64, m.name); 3873 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 3874 if (name != nullptr) 3875 outs() << format(" %.*s", left, name); 3876 outs() << "\n"; 3877 3878 outs() << indent << "\t\t types "; 3879 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 3880 info, n_value, m.types); 3881 if (n_value != 0) { 3882 if (info->verbose && sym_name != nullptr) 3883 outs() << sym_name; 3884 else 3885 outs() << format("0x%" PRIx64, n_value); 3886 if (m.types != 0) 3887 outs() << " + " << format("0x%" PRIx64, m.types); 3888 } else 3889 outs() << format("0x%" PRIx64, m.types); 3890 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 3891 if (name != nullptr) 3892 outs() << format(" %.*s", left, name); 3893 outs() << "\n"; 3894 3895 outs() << indent << "\t\t imp "; 3896 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 3897 n_value, m.imp); 3898 if (info->verbose && name == nullptr) { 3899 if (n_value != 0) { 3900 outs() << format("0x%" PRIx64, n_value) << " "; 3901 if (m.imp != 0) 3902 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 3903 } else 3904 outs() << format("0x%" PRIx64, m.imp) << " "; 3905 } 3906 if (name != nullptr) 3907 outs() << name; 3908 outs() << "\n"; 3909 3910 p += sizeof(struct method64_t); 3911 offset += sizeof(struct method64_t); 3912 } 3913 } 3914 3915 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 3916 const char *indent) { 3917 struct method_list32_t ml; 3918 struct method32_t m; 3919 const char *r, *name; 3920 uint32_t offset, xoffset, left, i; 3921 SectionRef S, xS; 3922 3923 r = get_pointer_32(p, offset, left, S, info); 3924 if (r == nullptr) 3925 return; 3926 memset(&ml, '\0', sizeof(struct method_list32_t)); 3927 if (left < sizeof(struct method_list32_t)) { 3928 memcpy(&ml, r, left); 3929 outs() << " (method_list_t entends past the end of the section)\n"; 3930 } else 3931 memcpy(&ml, r, sizeof(struct method_list32_t)); 3932 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3933 swapStruct(ml); 3934 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3935 outs() << indent << "\t\t count " << ml.count << "\n"; 3936 3937 p += sizeof(struct method_list32_t); 3938 offset += sizeof(struct method_list32_t); 3939 for (i = 0; i < ml.count; i++) { 3940 r = get_pointer_32(p, offset, left, S, info); 3941 if (r == nullptr) 3942 return; 3943 memset(&m, '\0', sizeof(struct method32_t)); 3944 if (left < sizeof(struct method32_t)) { 3945 memcpy(&ml, r, left); 3946 outs() << indent << " (method_t entends past the end of the section)\n"; 3947 } else 3948 memcpy(&m, r, sizeof(struct method32_t)); 3949 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3950 swapStruct(m); 3951 3952 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 3953 name = get_pointer_32(m.name, xoffset, left, xS, info); 3954 if (name != nullptr) 3955 outs() << format(" %.*s", left, name); 3956 outs() << "\n"; 3957 3958 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 3959 name = get_pointer_32(m.types, xoffset, left, xS, info); 3960 if (name != nullptr) 3961 outs() << format(" %.*s", left, name); 3962 outs() << "\n"; 3963 3964 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 3965 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 3966 m.imp); 3967 if (name != nullptr) 3968 outs() << " " << name; 3969 outs() << "\n"; 3970 3971 p += sizeof(struct method32_t); 3972 offset += sizeof(struct method32_t); 3973 } 3974 } 3975 3976 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 3977 uint32_t offset, left, xleft; 3978 SectionRef S; 3979 struct objc_method_list_t method_list; 3980 struct objc_method_t method; 3981 const char *r, *methods, *name, *SymbolName; 3982 int32_t i; 3983 3984 r = get_pointer_32(p, offset, left, S, info, true); 3985 if (r == nullptr) 3986 return true; 3987 3988 outs() << "\n"; 3989 if (left > sizeof(struct objc_method_list_t)) { 3990 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 3991 } else { 3992 outs() << "\t\t objc_method_list extends past end of the section\n"; 3993 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 3994 memcpy(&method_list, r, left); 3995 } 3996 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3997 swapStruct(method_list); 3998 3999 outs() << "\t\t obsolete " 4000 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4001 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4002 4003 methods = r + sizeof(struct objc_method_list_t); 4004 for (i = 0; i < method_list.method_count; i++) { 4005 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4006 outs() << "\t\t remaining method's extend past the of the section\n"; 4007 break; 4008 } 4009 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4010 sizeof(struct objc_method_t)); 4011 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4012 swapStruct(method); 4013 4014 outs() << "\t\t method_name " 4015 << format("0x%08" PRIx32, method.method_name); 4016 if (info->verbose) { 4017 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4018 if (name != nullptr) 4019 outs() << format(" %.*s", xleft, name); 4020 else 4021 outs() << " (not in an __OBJC section)"; 4022 } 4023 outs() << "\n"; 4024 4025 outs() << "\t\t method_types " 4026 << format("0x%08" PRIx32, method.method_types); 4027 if (info->verbose) { 4028 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4029 if (name != nullptr) 4030 outs() << format(" %.*s", xleft, name); 4031 else 4032 outs() << " (not in an __OBJC section)"; 4033 } 4034 outs() << "\n"; 4035 4036 outs() << "\t\t method_imp " 4037 << format("0x%08" PRIx32, method.method_imp) << " "; 4038 if (info->verbose) { 4039 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4040 if (SymbolName != nullptr) 4041 outs() << SymbolName; 4042 } 4043 outs() << "\n"; 4044 } 4045 return false; 4046 } 4047 4048 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4049 struct protocol_list64_t pl; 4050 uint64_t q, n_value; 4051 struct protocol64_t pc; 4052 const char *r; 4053 uint32_t offset, xoffset, left, i; 4054 SectionRef S, xS; 4055 const char *name, *sym_name; 4056 4057 r = get_pointer_64(p, offset, left, S, info); 4058 if (r == nullptr) 4059 return; 4060 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4061 if (left < sizeof(struct protocol_list64_t)) { 4062 memcpy(&pl, r, left); 4063 outs() << " (protocol_list_t entends past the end of the section)\n"; 4064 } else 4065 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4066 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4067 swapStruct(pl); 4068 outs() << " count " << pl.count << "\n"; 4069 4070 p += sizeof(struct protocol_list64_t); 4071 offset += sizeof(struct protocol_list64_t); 4072 for (i = 0; i < pl.count; i++) { 4073 r = get_pointer_64(p, offset, left, S, info); 4074 if (r == nullptr) 4075 return; 4076 q = 0; 4077 if (left < sizeof(uint64_t)) { 4078 memcpy(&q, r, left); 4079 outs() << " (protocol_t * entends past the end of the section)\n"; 4080 } else 4081 memcpy(&q, r, sizeof(uint64_t)); 4082 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4083 sys::swapByteOrder(q); 4084 4085 outs() << "\t\t list[" << i << "] "; 4086 sym_name = get_symbol_64(offset, S, info, n_value, q); 4087 if (n_value != 0) { 4088 if (info->verbose && sym_name != nullptr) 4089 outs() << sym_name; 4090 else 4091 outs() << format("0x%" PRIx64, n_value); 4092 if (q != 0) 4093 outs() << " + " << format("0x%" PRIx64, q); 4094 } else 4095 outs() << format("0x%" PRIx64, q); 4096 outs() << " (struct protocol_t *)\n"; 4097 4098 r = get_pointer_64(q + n_value, offset, left, S, info); 4099 if (r == nullptr) 4100 return; 4101 memset(&pc, '\0', sizeof(struct protocol64_t)); 4102 if (left < sizeof(struct protocol64_t)) { 4103 memcpy(&pc, r, left); 4104 outs() << " (protocol_t entends past the end of the section)\n"; 4105 } else 4106 memcpy(&pc, r, sizeof(struct protocol64_t)); 4107 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4108 swapStruct(pc); 4109 4110 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4111 4112 outs() << "\t\t\t name "; 4113 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4114 info, n_value, pc.name); 4115 if (n_value != 0) { 4116 if (info->verbose && sym_name != nullptr) 4117 outs() << sym_name; 4118 else 4119 outs() << format("0x%" PRIx64, n_value); 4120 if (pc.name != 0) 4121 outs() << " + " << format("0x%" PRIx64, pc.name); 4122 } else 4123 outs() << format("0x%" PRIx64, pc.name); 4124 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4125 if (name != nullptr) 4126 outs() << format(" %.*s", left, name); 4127 outs() << "\n"; 4128 4129 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4130 4131 outs() << "\t\t instanceMethods "; 4132 sym_name = 4133 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4134 S, info, n_value, pc.instanceMethods); 4135 if (n_value != 0) { 4136 if (info->verbose && sym_name != nullptr) 4137 outs() << sym_name; 4138 else 4139 outs() << format("0x%" PRIx64, n_value); 4140 if (pc.instanceMethods != 0) 4141 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4142 } else 4143 outs() << format("0x%" PRIx64, pc.instanceMethods); 4144 outs() << " (struct method_list_t *)\n"; 4145 if (pc.instanceMethods + n_value != 0) 4146 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4147 4148 outs() << "\t\t classMethods "; 4149 sym_name = 4150 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4151 info, n_value, pc.classMethods); 4152 if (n_value != 0) { 4153 if (info->verbose && sym_name != nullptr) 4154 outs() << sym_name; 4155 else 4156 outs() << format("0x%" PRIx64, n_value); 4157 if (pc.classMethods != 0) 4158 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4159 } else 4160 outs() << format("0x%" PRIx64, pc.classMethods); 4161 outs() << " (struct method_list_t *)\n"; 4162 if (pc.classMethods + n_value != 0) 4163 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4164 4165 outs() << "\t optionalInstanceMethods " 4166 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4167 outs() << "\t optionalClassMethods " 4168 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4169 outs() << "\t instanceProperties " 4170 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4171 4172 p += sizeof(uint64_t); 4173 offset += sizeof(uint64_t); 4174 } 4175 } 4176 4177 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4178 struct protocol_list32_t pl; 4179 uint32_t q; 4180 struct protocol32_t pc; 4181 const char *r; 4182 uint32_t offset, xoffset, left, i; 4183 SectionRef S, xS; 4184 const char *name; 4185 4186 r = get_pointer_32(p, offset, left, S, info); 4187 if (r == nullptr) 4188 return; 4189 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4190 if (left < sizeof(struct protocol_list32_t)) { 4191 memcpy(&pl, r, left); 4192 outs() << " (protocol_list_t entends past the end of the section)\n"; 4193 } else 4194 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4195 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4196 swapStruct(pl); 4197 outs() << " count " << pl.count << "\n"; 4198 4199 p += sizeof(struct protocol_list32_t); 4200 offset += sizeof(struct protocol_list32_t); 4201 for (i = 0; i < pl.count; i++) { 4202 r = get_pointer_32(p, offset, left, S, info); 4203 if (r == nullptr) 4204 return; 4205 q = 0; 4206 if (left < sizeof(uint32_t)) { 4207 memcpy(&q, r, left); 4208 outs() << " (protocol_t * entends past the end of the section)\n"; 4209 } else 4210 memcpy(&q, r, sizeof(uint32_t)); 4211 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4212 sys::swapByteOrder(q); 4213 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4214 << " (struct protocol_t *)\n"; 4215 r = get_pointer_32(q, offset, left, S, info); 4216 if (r == nullptr) 4217 return; 4218 memset(&pc, '\0', sizeof(struct protocol32_t)); 4219 if (left < sizeof(struct protocol32_t)) { 4220 memcpy(&pc, r, left); 4221 outs() << " (protocol_t entends past the end of the section)\n"; 4222 } else 4223 memcpy(&pc, r, sizeof(struct protocol32_t)); 4224 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4225 swapStruct(pc); 4226 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4227 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4228 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4229 if (name != nullptr) 4230 outs() << format(" %.*s", left, name); 4231 outs() << "\n"; 4232 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4233 outs() << "\t\t instanceMethods " 4234 << format("0x%" PRIx32, pc.instanceMethods) 4235 << " (struct method_list_t *)\n"; 4236 if (pc.instanceMethods != 0) 4237 print_method_list32_t(pc.instanceMethods, info, "\t"); 4238 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4239 << " (struct method_list_t *)\n"; 4240 if (pc.classMethods != 0) 4241 print_method_list32_t(pc.classMethods, info, "\t"); 4242 outs() << "\t optionalInstanceMethods " 4243 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4244 outs() << "\t optionalClassMethods " 4245 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4246 outs() << "\t instanceProperties " 4247 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4248 p += sizeof(uint32_t); 4249 offset += sizeof(uint32_t); 4250 } 4251 } 4252 4253 static void print_indent(uint32_t indent) { 4254 for (uint32_t i = 0; i < indent;) { 4255 if (indent - i >= 8) { 4256 outs() << "\t"; 4257 i += 8; 4258 } else { 4259 for (uint32_t j = i; j < indent; j++) 4260 outs() << " "; 4261 return; 4262 } 4263 } 4264 } 4265 4266 static bool print_method_description_list(uint32_t p, uint32_t indent, 4267 struct DisassembleInfo *info) { 4268 uint32_t offset, left, xleft; 4269 SectionRef S; 4270 struct objc_method_description_list_t mdl; 4271 struct objc_method_description_t md; 4272 const char *r, *list, *name; 4273 int32_t i; 4274 4275 r = get_pointer_32(p, offset, left, S, info, true); 4276 if (r == nullptr) 4277 return true; 4278 4279 outs() << "\n"; 4280 if (left > sizeof(struct objc_method_description_list_t)) { 4281 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 4282 } else { 4283 print_indent(indent); 4284 outs() << " objc_method_description_list extends past end of the section\n"; 4285 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 4286 memcpy(&mdl, r, left); 4287 } 4288 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4289 swapStruct(mdl); 4290 4291 print_indent(indent); 4292 outs() << " count " << mdl.count << "\n"; 4293 4294 list = r + sizeof(struct objc_method_description_list_t); 4295 for (i = 0; i < mdl.count; i++) { 4296 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 4297 print_indent(indent); 4298 outs() << " remaining list entries extend past the of the section\n"; 4299 break; 4300 } 4301 print_indent(indent); 4302 outs() << " list[" << i << "]\n"; 4303 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 4304 sizeof(struct objc_method_description_t)); 4305 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4306 swapStruct(md); 4307 4308 print_indent(indent); 4309 outs() << " name " << format("0x%08" PRIx32, md.name); 4310 if (info->verbose) { 4311 name = get_pointer_32(md.name, offset, xleft, S, info, true); 4312 if (name != nullptr) 4313 outs() << format(" %.*s", xleft, name); 4314 else 4315 outs() << " (not in an __OBJC section)"; 4316 } 4317 outs() << "\n"; 4318 4319 print_indent(indent); 4320 outs() << " types " << format("0x%08" PRIx32, md.types); 4321 if (info->verbose) { 4322 name = get_pointer_32(md.types, offset, xleft, S, info, true); 4323 if (name != nullptr) 4324 outs() << format(" %.*s", xleft, name); 4325 else 4326 outs() << " (not in an __OBJC section)"; 4327 } 4328 outs() << "\n"; 4329 } 4330 return false; 4331 } 4332 4333 static bool print_protocol_list(uint32_t p, uint32_t indent, 4334 struct DisassembleInfo *info); 4335 4336 static bool print_protocol(uint32_t p, uint32_t indent, 4337 struct DisassembleInfo *info) { 4338 uint32_t offset, left; 4339 SectionRef S; 4340 struct objc_protocol_t protocol; 4341 const char *r, *name; 4342 4343 r = get_pointer_32(p, offset, left, S, info, true); 4344 if (r == nullptr) 4345 return true; 4346 4347 outs() << "\n"; 4348 if (left >= sizeof(struct objc_protocol_t)) { 4349 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 4350 } else { 4351 print_indent(indent); 4352 outs() << " Protocol extends past end of the section\n"; 4353 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 4354 memcpy(&protocol, r, left); 4355 } 4356 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4357 swapStruct(protocol); 4358 4359 print_indent(indent); 4360 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 4361 << "\n"; 4362 4363 print_indent(indent); 4364 outs() << " protocol_name " 4365 << format("0x%08" PRIx32, protocol.protocol_name); 4366 if (info->verbose) { 4367 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 4368 if (name != nullptr) 4369 outs() << format(" %.*s", left, name); 4370 else 4371 outs() << " (not in an __OBJC section)"; 4372 } 4373 outs() << "\n"; 4374 4375 print_indent(indent); 4376 outs() << " protocol_list " 4377 << format("0x%08" PRIx32, protocol.protocol_list); 4378 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 4379 outs() << " (not in an __OBJC section)\n"; 4380 4381 print_indent(indent); 4382 outs() << " instance_methods " 4383 << format("0x%08" PRIx32, protocol.instance_methods); 4384 if (print_method_description_list(protocol.instance_methods, indent, info)) 4385 outs() << " (not in an __OBJC section)\n"; 4386 4387 print_indent(indent); 4388 outs() << " class_methods " 4389 << format("0x%08" PRIx32, protocol.class_methods); 4390 if (print_method_description_list(protocol.class_methods, indent, info)) 4391 outs() << " (not in an __OBJC section)\n"; 4392 4393 return false; 4394 } 4395 4396 static bool print_protocol_list(uint32_t p, uint32_t indent, 4397 struct DisassembleInfo *info) { 4398 uint32_t offset, left, l; 4399 SectionRef S; 4400 struct objc_protocol_list_t protocol_list; 4401 const char *r, *list; 4402 int32_t i; 4403 4404 r = get_pointer_32(p, offset, left, S, info, true); 4405 if (r == nullptr) 4406 return true; 4407 4408 outs() << "\n"; 4409 if (left > sizeof(struct objc_protocol_list_t)) { 4410 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 4411 } else { 4412 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 4413 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 4414 memcpy(&protocol_list, r, left); 4415 } 4416 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4417 swapStruct(protocol_list); 4418 4419 print_indent(indent); 4420 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 4421 << "\n"; 4422 print_indent(indent); 4423 outs() << " count " << protocol_list.count << "\n"; 4424 4425 list = r + sizeof(struct objc_protocol_list_t); 4426 for (i = 0; i < protocol_list.count; i++) { 4427 if ((i + 1) * sizeof(uint32_t) > left) { 4428 outs() << "\t\t remaining list entries extend past the of the section\n"; 4429 break; 4430 } 4431 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 4432 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4433 sys::swapByteOrder(l); 4434 4435 print_indent(indent); 4436 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 4437 if (print_protocol(l, indent, info)) 4438 outs() << "(not in an __OBJC section)\n"; 4439 } 4440 return false; 4441 } 4442 4443 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 4444 struct ivar_list64_t il; 4445 struct ivar64_t i; 4446 const char *r; 4447 uint32_t offset, xoffset, left, j; 4448 SectionRef S, xS; 4449 const char *name, *sym_name, *ivar_offset_p; 4450 uint64_t ivar_offset, n_value; 4451 4452 r = get_pointer_64(p, offset, left, S, info); 4453 if (r == nullptr) 4454 return; 4455 memset(&il, '\0', sizeof(struct ivar_list64_t)); 4456 if (left < sizeof(struct ivar_list64_t)) { 4457 memcpy(&il, r, left); 4458 outs() << " (ivar_list_t entends past the end of the section)\n"; 4459 } else 4460 memcpy(&il, r, sizeof(struct ivar_list64_t)); 4461 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4462 swapStruct(il); 4463 outs() << " entsize " << il.entsize << "\n"; 4464 outs() << " count " << il.count << "\n"; 4465 4466 p += sizeof(struct ivar_list64_t); 4467 offset += sizeof(struct ivar_list64_t); 4468 for (j = 0; j < il.count; j++) { 4469 r = get_pointer_64(p, offset, left, S, info); 4470 if (r == nullptr) 4471 return; 4472 memset(&i, '\0', sizeof(struct ivar64_t)); 4473 if (left < sizeof(struct ivar64_t)) { 4474 memcpy(&i, r, left); 4475 outs() << " (ivar_t entends past the end of the section)\n"; 4476 } else 4477 memcpy(&i, r, sizeof(struct ivar64_t)); 4478 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4479 swapStruct(i); 4480 4481 outs() << "\t\t\t offset "; 4482 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 4483 info, n_value, i.offset); 4484 if (n_value != 0) { 4485 if (info->verbose && sym_name != nullptr) 4486 outs() << sym_name; 4487 else 4488 outs() << format("0x%" PRIx64, n_value); 4489 if (i.offset != 0) 4490 outs() << " + " << format("0x%" PRIx64, i.offset); 4491 } else 4492 outs() << format("0x%" PRIx64, i.offset); 4493 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 4494 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4495 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4496 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4497 sys::swapByteOrder(ivar_offset); 4498 outs() << " " << ivar_offset << "\n"; 4499 } else 4500 outs() << "\n"; 4501 4502 outs() << "\t\t\t name "; 4503 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 4504 n_value, i.name); 4505 if (n_value != 0) { 4506 if (info->verbose && sym_name != nullptr) 4507 outs() << sym_name; 4508 else 4509 outs() << format("0x%" PRIx64, n_value); 4510 if (i.name != 0) 4511 outs() << " + " << format("0x%" PRIx64, i.name); 4512 } else 4513 outs() << format("0x%" PRIx64, i.name); 4514 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 4515 if (name != nullptr) 4516 outs() << format(" %.*s", left, name); 4517 outs() << "\n"; 4518 4519 outs() << "\t\t\t type "; 4520 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 4521 n_value, i.name); 4522 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 4523 if (n_value != 0) { 4524 if (info->verbose && sym_name != nullptr) 4525 outs() << sym_name; 4526 else 4527 outs() << format("0x%" PRIx64, n_value); 4528 if (i.type != 0) 4529 outs() << " + " << format("0x%" PRIx64, i.type); 4530 } else 4531 outs() << format("0x%" PRIx64, i.type); 4532 if (name != nullptr) 4533 outs() << format(" %.*s", left, name); 4534 outs() << "\n"; 4535 4536 outs() << "\t\t\talignment " << i.alignment << "\n"; 4537 outs() << "\t\t\t size " << i.size << "\n"; 4538 4539 p += sizeof(struct ivar64_t); 4540 offset += sizeof(struct ivar64_t); 4541 } 4542 } 4543 4544 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 4545 struct ivar_list32_t il; 4546 struct ivar32_t i; 4547 const char *r; 4548 uint32_t offset, xoffset, left, j; 4549 SectionRef S, xS; 4550 const char *name, *ivar_offset_p; 4551 uint32_t ivar_offset; 4552 4553 r = get_pointer_32(p, offset, left, S, info); 4554 if (r == nullptr) 4555 return; 4556 memset(&il, '\0', sizeof(struct ivar_list32_t)); 4557 if (left < sizeof(struct ivar_list32_t)) { 4558 memcpy(&il, r, left); 4559 outs() << " (ivar_list_t entends past the end of the section)\n"; 4560 } else 4561 memcpy(&il, r, sizeof(struct ivar_list32_t)); 4562 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4563 swapStruct(il); 4564 outs() << " entsize " << il.entsize << "\n"; 4565 outs() << " count " << il.count << "\n"; 4566 4567 p += sizeof(struct ivar_list32_t); 4568 offset += sizeof(struct ivar_list32_t); 4569 for (j = 0; j < il.count; j++) { 4570 r = get_pointer_32(p, offset, left, S, info); 4571 if (r == nullptr) 4572 return; 4573 memset(&i, '\0', sizeof(struct ivar32_t)); 4574 if (left < sizeof(struct ivar32_t)) { 4575 memcpy(&i, r, left); 4576 outs() << " (ivar_t entends past the end of the section)\n"; 4577 } else 4578 memcpy(&i, r, sizeof(struct ivar32_t)); 4579 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4580 swapStruct(i); 4581 4582 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 4583 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 4584 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4585 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4586 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4587 sys::swapByteOrder(ivar_offset); 4588 outs() << " " << ivar_offset << "\n"; 4589 } else 4590 outs() << "\n"; 4591 4592 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 4593 name = get_pointer_32(i.name, xoffset, left, xS, info); 4594 if (name != nullptr) 4595 outs() << format(" %.*s", left, name); 4596 outs() << "\n"; 4597 4598 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 4599 name = get_pointer_32(i.type, xoffset, left, xS, info); 4600 if (name != nullptr) 4601 outs() << format(" %.*s", left, name); 4602 outs() << "\n"; 4603 4604 outs() << "\t\t\talignment " << i.alignment << "\n"; 4605 outs() << "\t\t\t size " << i.size << "\n"; 4606 4607 p += sizeof(struct ivar32_t); 4608 offset += sizeof(struct ivar32_t); 4609 } 4610 } 4611 4612 static void print_objc_property_list64(uint64_t p, 4613 struct DisassembleInfo *info) { 4614 struct objc_property_list64 opl; 4615 struct objc_property64 op; 4616 const char *r; 4617 uint32_t offset, xoffset, left, j; 4618 SectionRef S, xS; 4619 const char *name, *sym_name; 4620 uint64_t n_value; 4621 4622 r = get_pointer_64(p, offset, left, S, info); 4623 if (r == nullptr) 4624 return; 4625 memset(&opl, '\0', sizeof(struct objc_property_list64)); 4626 if (left < sizeof(struct objc_property_list64)) { 4627 memcpy(&opl, r, left); 4628 outs() << " (objc_property_list entends past the end of the section)\n"; 4629 } else 4630 memcpy(&opl, r, sizeof(struct objc_property_list64)); 4631 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4632 swapStruct(opl); 4633 outs() << " entsize " << opl.entsize << "\n"; 4634 outs() << " count " << opl.count << "\n"; 4635 4636 p += sizeof(struct objc_property_list64); 4637 offset += sizeof(struct objc_property_list64); 4638 for (j = 0; j < opl.count; j++) { 4639 r = get_pointer_64(p, offset, left, S, info); 4640 if (r == nullptr) 4641 return; 4642 memset(&op, '\0', sizeof(struct objc_property64)); 4643 if (left < sizeof(struct objc_property64)) { 4644 memcpy(&op, r, left); 4645 outs() << " (objc_property entends past the end of the section)\n"; 4646 } else 4647 memcpy(&op, r, sizeof(struct objc_property64)); 4648 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4649 swapStruct(op); 4650 4651 outs() << "\t\t\t name "; 4652 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 4653 info, n_value, op.name); 4654 if (n_value != 0) { 4655 if (info->verbose && sym_name != nullptr) 4656 outs() << sym_name; 4657 else 4658 outs() << format("0x%" PRIx64, n_value); 4659 if (op.name != 0) 4660 outs() << " + " << format("0x%" PRIx64, op.name); 4661 } else 4662 outs() << format("0x%" PRIx64, op.name); 4663 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 4664 if (name != nullptr) 4665 outs() << format(" %.*s", left, name); 4666 outs() << "\n"; 4667 4668 outs() << "\t\t\tattributes "; 4669 sym_name = 4670 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 4671 info, n_value, op.attributes); 4672 if (n_value != 0) { 4673 if (info->verbose && sym_name != nullptr) 4674 outs() << sym_name; 4675 else 4676 outs() << format("0x%" PRIx64, n_value); 4677 if (op.attributes != 0) 4678 outs() << " + " << format("0x%" PRIx64, op.attributes); 4679 } else 4680 outs() << format("0x%" PRIx64, op.attributes); 4681 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 4682 if (name != nullptr) 4683 outs() << format(" %.*s", left, name); 4684 outs() << "\n"; 4685 4686 p += sizeof(struct objc_property64); 4687 offset += sizeof(struct objc_property64); 4688 } 4689 } 4690 4691 static void print_objc_property_list32(uint32_t p, 4692 struct DisassembleInfo *info) { 4693 struct objc_property_list32 opl; 4694 struct objc_property32 op; 4695 const char *r; 4696 uint32_t offset, xoffset, left, j; 4697 SectionRef S, xS; 4698 const char *name; 4699 4700 r = get_pointer_32(p, offset, left, S, info); 4701 if (r == nullptr) 4702 return; 4703 memset(&opl, '\0', sizeof(struct objc_property_list32)); 4704 if (left < sizeof(struct objc_property_list32)) { 4705 memcpy(&opl, r, left); 4706 outs() << " (objc_property_list entends past the end of the section)\n"; 4707 } else 4708 memcpy(&opl, r, sizeof(struct objc_property_list32)); 4709 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4710 swapStruct(opl); 4711 outs() << " entsize " << opl.entsize << "\n"; 4712 outs() << " count " << opl.count << "\n"; 4713 4714 p += sizeof(struct objc_property_list32); 4715 offset += sizeof(struct objc_property_list32); 4716 for (j = 0; j < opl.count; j++) { 4717 r = get_pointer_32(p, offset, left, S, info); 4718 if (r == nullptr) 4719 return; 4720 memset(&op, '\0', sizeof(struct objc_property32)); 4721 if (left < sizeof(struct objc_property32)) { 4722 memcpy(&op, r, left); 4723 outs() << " (objc_property entends past the end of the section)\n"; 4724 } else 4725 memcpy(&op, r, sizeof(struct objc_property32)); 4726 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4727 swapStruct(op); 4728 4729 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 4730 name = get_pointer_32(op.name, xoffset, left, xS, info); 4731 if (name != nullptr) 4732 outs() << format(" %.*s", left, name); 4733 outs() << "\n"; 4734 4735 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 4736 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 4737 if (name != nullptr) 4738 outs() << format(" %.*s", left, name); 4739 outs() << "\n"; 4740 4741 p += sizeof(struct objc_property32); 4742 offset += sizeof(struct objc_property32); 4743 } 4744 } 4745 4746 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 4747 bool &is_meta_class) { 4748 struct class_ro64_t cro; 4749 const char *r; 4750 uint32_t offset, xoffset, left; 4751 SectionRef S, xS; 4752 const char *name, *sym_name; 4753 uint64_t n_value; 4754 4755 r = get_pointer_64(p, offset, left, S, info); 4756 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4757 return false; 4758 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4759 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4760 swapStruct(cro); 4761 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4762 if (cro.flags & RO_META) 4763 outs() << " RO_META"; 4764 if (cro.flags & RO_ROOT) 4765 outs() << " RO_ROOT"; 4766 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4767 outs() << " RO_HAS_CXX_STRUCTORS"; 4768 outs() << "\n"; 4769 outs() << " instanceStart " << cro.instanceStart << "\n"; 4770 outs() << " instanceSize " << cro.instanceSize << "\n"; 4771 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 4772 << "\n"; 4773 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 4774 << "\n"; 4775 print_layout_map64(cro.ivarLayout, info); 4776 4777 outs() << " name "; 4778 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 4779 info, n_value, cro.name); 4780 if (n_value != 0) { 4781 if (info->verbose && sym_name != nullptr) 4782 outs() << sym_name; 4783 else 4784 outs() << format("0x%" PRIx64, n_value); 4785 if (cro.name != 0) 4786 outs() << " + " << format("0x%" PRIx64, cro.name); 4787 } else 4788 outs() << format("0x%" PRIx64, cro.name); 4789 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 4790 if (name != nullptr) 4791 outs() << format(" %.*s", left, name); 4792 outs() << "\n"; 4793 4794 outs() << " baseMethods "; 4795 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 4796 S, info, n_value, cro.baseMethods); 4797 if (n_value != 0) { 4798 if (info->verbose && sym_name != nullptr) 4799 outs() << sym_name; 4800 else 4801 outs() << format("0x%" PRIx64, n_value); 4802 if (cro.baseMethods != 0) 4803 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 4804 } else 4805 outs() << format("0x%" PRIx64, cro.baseMethods); 4806 outs() << " (struct method_list_t *)\n"; 4807 if (cro.baseMethods + n_value != 0) 4808 print_method_list64_t(cro.baseMethods + n_value, info, ""); 4809 4810 outs() << " baseProtocols "; 4811 sym_name = 4812 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 4813 info, n_value, cro.baseProtocols); 4814 if (n_value != 0) { 4815 if (info->verbose && sym_name != nullptr) 4816 outs() << sym_name; 4817 else 4818 outs() << format("0x%" PRIx64, n_value); 4819 if (cro.baseProtocols != 0) 4820 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 4821 } else 4822 outs() << format("0x%" PRIx64, cro.baseProtocols); 4823 outs() << "\n"; 4824 if (cro.baseProtocols + n_value != 0) 4825 print_protocol_list64_t(cro.baseProtocols + n_value, info); 4826 4827 outs() << " ivars "; 4828 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 4829 info, n_value, cro.ivars); 4830 if (n_value != 0) { 4831 if (info->verbose && sym_name != nullptr) 4832 outs() << sym_name; 4833 else 4834 outs() << format("0x%" PRIx64, n_value); 4835 if (cro.ivars != 0) 4836 outs() << " + " << format("0x%" PRIx64, cro.ivars); 4837 } else 4838 outs() << format("0x%" PRIx64, cro.ivars); 4839 outs() << "\n"; 4840 if (cro.ivars + n_value != 0) 4841 print_ivar_list64_t(cro.ivars + n_value, info); 4842 4843 outs() << " weakIvarLayout "; 4844 sym_name = 4845 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 4846 info, n_value, cro.weakIvarLayout); 4847 if (n_value != 0) { 4848 if (info->verbose && sym_name != nullptr) 4849 outs() << sym_name; 4850 else 4851 outs() << format("0x%" PRIx64, n_value); 4852 if (cro.weakIvarLayout != 0) 4853 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 4854 } else 4855 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 4856 outs() << "\n"; 4857 print_layout_map64(cro.weakIvarLayout + n_value, info); 4858 4859 outs() << " baseProperties "; 4860 sym_name = 4861 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 4862 info, n_value, cro.baseProperties); 4863 if (n_value != 0) { 4864 if (info->verbose && sym_name != nullptr) 4865 outs() << sym_name; 4866 else 4867 outs() << format("0x%" PRIx64, n_value); 4868 if (cro.baseProperties != 0) 4869 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 4870 } else 4871 outs() << format("0x%" PRIx64, cro.baseProperties); 4872 outs() << "\n"; 4873 if (cro.baseProperties + n_value != 0) 4874 print_objc_property_list64(cro.baseProperties + n_value, info); 4875 4876 is_meta_class = (cro.flags & RO_META) != 0; 4877 return true; 4878 } 4879 4880 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 4881 bool &is_meta_class) { 4882 struct class_ro32_t cro; 4883 const char *r; 4884 uint32_t offset, xoffset, left; 4885 SectionRef S, xS; 4886 const char *name; 4887 4888 r = get_pointer_32(p, offset, left, S, info); 4889 if (r == nullptr) 4890 return false; 4891 memset(&cro, '\0', sizeof(struct class_ro32_t)); 4892 if (left < sizeof(struct class_ro32_t)) { 4893 memcpy(&cro, r, left); 4894 outs() << " (class_ro_t entends past the end of the section)\n"; 4895 } else 4896 memcpy(&cro, r, sizeof(struct class_ro32_t)); 4897 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4898 swapStruct(cro); 4899 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4900 if (cro.flags & RO_META) 4901 outs() << " RO_META"; 4902 if (cro.flags & RO_ROOT) 4903 outs() << " RO_ROOT"; 4904 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4905 outs() << " RO_HAS_CXX_STRUCTORS"; 4906 outs() << "\n"; 4907 outs() << " instanceStart " << cro.instanceStart << "\n"; 4908 outs() << " instanceSize " << cro.instanceSize << "\n"; 4909 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 4910 << "\n"; 4911 print_layout_map32(cro.ivarLayout, info); 4912 4913 outs() << " name " << format("0x%" PRIx32, cro.name); 4914 name = get_pointer_32(cro.name, xoffset, left, xS, info); 4915 if (name != nullptr) 4916 outs() << format(" %.*s", left, name); 4917 outs() << "\n"; 4918 4919 outs() << " baseMethods " 4920 << format("0x%" PRIx32, cro.baseMethods) 4921 << " (struct method_list_t *)\n"; 4922 if (cro.baseMethods != 0) 4923 print_method_list32_t(cro.baseMethods, info, ""); 4924 4925 outs() << " baseProtocols " 4926 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 4927 if (cro.baseProtocols != 0) 4928 print_protocol_list32_t(cro.baseProtocols, info); 4929 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 4930 << "\n"; 4931 if (cro.ivars != 0) 4932 print_ivar_list32_t(cro.ivars, info); 4933 outs() << " weakIvarLayout " 4934 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 4935 print_layout_map32(cro.weakIvarLayout, info); 4936 outs() << " baseProperties " 4937 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 4938 if (cro.baseProperties != 0) 4939 print_objc_property_list32(cro.baseProperties, info); 4940 is_meta_class = (cro.flags & RO_META) != 0; 4941 return true; 4942 } 4943 4944 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 4945 struct class64_t c; 4946 const char *r; 4947 uint32_t offset, left; 4948 SectionRef S; 4949 const char *name; 4950 uint64_t isa_n_value, n_value; 4951 4952 r = get_pointer_64(p, offset, left, S, info); 4953 if (r == nullptr || left < sizeof(struct class64_t)) 4954 return; 4955 memcpy(&c, r, sizeof(struct class64_t)); 4956 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4957 swapStruct(c); 4958 4959 outs() << " isa " << format("0x%" PRIx64, c.isa); 4960 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 4961 isa_n_value, c.isa); 4962 if (name != nullptr) 4963 outs() << " " << name; 4964 outs() << "\n"; 4965 4966 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 4967 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 4968 n_value, c.superclass); 4969 if (name != nullptr) 4970 outs() << " " << name; 4971 else { 4972 name = get_dyld_bind_info_symbolname(S.getAddress() + 4973 offset + offsetof(struct class64_t, superclass), info); 4974 if (name != nullptr) 4975 outs() << " " << name; 4976 } 4977 outs() << "\n"; 4978 4979 outs() << " cache " << format("0x%" PRIx64, c.cache); 4980 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 4981 n_value, c.cache); 4982 if (name != nullptr) 4983 outs() << " " << name; 4984 outs() << "\n"; 4985 4986 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 4987 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 4988 n_value, c.vtable); 4989 if (name != nullptr) 4990 outs() << " " << name; 4991 outs() << "\n"; 4992 4993 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 4994 n_value, c.data); 4995 outs() << " data "; 4996 if (n_value != 0) { 4997 if (info->verbose && name != nullptr) 4998 outs() << name; 4999 else 5000 outs() << format("0x%" PRIx64, n_value); 5001 if (c.data != 0) 5002 outs() << " + " << format("0x%" PRIx64, c.data); 5003 } else 5004 outs() << format("0x%" PRIx64, c.data); 5005 outs() << " (struct class_ro_t *)"; 5006 5007 // This is a Swift class if some of the low bits of the pointer are set. 5008 if ((c.data + n_value) & 0x7) 5009 outs() << " Swift class"; 5010 outs() << "\n"; 5011 bool is_meta_class; 5012 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5013 return; 5014 5015 if (!is_meta_class && 5016 c.isa + isa_n_value != p && 5017 c.isa + isa_n_value != 0 && 5018 info->depth < 100) { 5019 info->depth++; 5020 outs() << "Meta Class\n"; 5021 print_class64_t(c.isa + isa_n_value, info); 5022 } 5023 } 5024 5025 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5026 struct class32_t c; 5027 const char *r; 5028 uint32_t offset, left; 5029 SectionRef S; 5030 const char *name; 5031 5032 r = get_pointer_32(p, offset, left, S, info); 5033 if (r == nullptr) 5034 return; 5035 memset(&c, '\0', sizeof(struct class32_t)); 5036 if (left < sizeof(struct class32_t)) { 5037 memcpy(&c, r, left); 5038 outs() << " (class_t entends past the end of the section)\n"; 5039 } else 5040 memcpy(&c, r, sizeof(struct class32_t)); 5041 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5042 swapStruct(c); 5043 5044 outs() << " isa " << format("0x%" PRIx32, c.isa); 5045 name = 5046 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5047 if (name != nullptr) 5048 outs() << " " << name; 5049 outs() << "\n"; 5050 5051 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5052 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5053 c.superclass); 5054 if (name != nullptr) 5055 outs() << " " << name; 5056 outs() << "\n"; 5057 5058 outs() << " cache " << format("0x%" PRIx32, c.cache); 5059 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5060 c.cache); 5061 if (name != nullptr) 5062 outs() << " " << name; 5063 outs() << "\n"; 5064 5065 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5066 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5067 c.vtable); 5068 if (name != nullptr) 5069 outs() << " " << name; 5070 outs() << "\n"; 5071 5072 name = 5073 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5074 outs() << " data " << format("0x%" PRIx32, c.data) 5075 << " (struct class_ro_t *)"; 5076 5077 // This is a Swift class if some of the low bits of the pointer are set. 5078 if (c.data & 0x3) 5079 outs() << " Swift class"; 5080 outs() << "\n"; 5081 bool is_meta_class; 5082 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5083 return; 5084 5085 if (!is_meta_class) { 5086 outs() << "Meta Class\n"; 5087 print_class32_t(c.isa, info); 5088 } 5089 } 5090 5091 static void print_objc_class_t(struct objc_class_t *objc_class, 5092 struct DisassembleInfo *info) { 5093 uint32_t offset, left, xleft; 5094 const char *name, *p, *ivar_list; 5095 SectionRef S; 5096 int32_t i; 5097 struct objc_ivar_list_t objc_ivar_list; 5098 struct objc_ivar_t ivar; 5099 5100 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5101 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5102 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5103 if (name != nullptr) 5104 outs() << format(" %.*s", left, name); 5105 else 5106 outs() << " (not in an __OBJC section)"; 5107 } 5108 outs() << "\n"; 5109 5110 outs() << "\t super_class " 5111 << format("0x%08" PRIx32, objc_class->super_class); 5112 if (info->verbose) { 5113 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5114 if (name != nullptr) 5115 outs() << format(" %.*s", left, name); 5116 else 5117 outs() << " (not in an __OBJC section)"; 5118 } 5119 outs() << "\n"; 5120 5121 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5122 if (info->verbose) { 5123 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5124 if (name != nullptr) 5125 outs() << format(" %.*s", left, name); 5126 else 5127 outs() << " (not in an __OBJC section)"; 5128 } 5129 outs() << "\n"; 5130 5131 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5132 << "\n"; 5133 5134 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5135 if (info->verbose) { 5136 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5137 outs() << " CLS_CLASS"; 5138 else if (CLS_GETINFO(objc_class, CLS_META)) 5139 outs() << " CLS_META"; 5140 } 5141 outs() << "\n"; 5142 5143 outs() << "\t instance_size " 5144 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5145 5146 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5147 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5148 if (p != nullptr) { 5149 if (left > sizeof(struct objc_ivar_list_t)) { 5150 outs() << "\n"; 5151 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5152 } else { 5153 outs() << " (entends past the end of the section)\n"; 5154 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5155 memcpy(&objc_ivar_list, p, left); 5156 } 5157 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5158 swapStruct(objc_ivar_list); 5159 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5160 ivar_list = p + sizeof(struct objc_ivar_list_t); 5161 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5162 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5163 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5164 break; 5165 } 5166 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5167 sizeof(struct objc_ivar_t)); 5168 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5169 swapStruct(ivar); 5170 5171 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5172 if (info->verbose) { 5173 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5174 if (name != nullptr) 5175 outs() << format(" %.*s", xleft, name); 5176 else 5177 outs() << " (not in an __OBJC section)"; 5178 } 5179 outs() << "\n"; 5180 5181 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5182 if (info->verbose) { 5183 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5184 if (name != nullptr) 5185 outs() << format(" %.*s", xleft, name); 5186 else 5187 outs() << " (not in an __OBJC section)"; 5188 } 5189 outs() << "\n"; 5190 5191 outs() << "\t\t ivar_offset " 5192 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5193 } 5194 } else { 5195 outs() << " (not in an __OBJC section)\n"; 5196 } 5197 5198 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5199 if (print_method_list(objc_class->methodLists, info)) 5200 outs() << " (not in an __OBJC section)\n"; 5201 5202 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5203 << "\n"; 5204 5205 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5206 if (print_protocol_list(objc_class->protocols, 16, info)) 5207 outs() << " (not in an __OBJC section)\n"; 5208 } 5209 5210 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5211 struct DisassembleInfo *info) { 5212 uint32_t offset, left; 5213 const char *name; 5214 SectionRef S; 5215 5216 outs() << "\t category name " 5217 << format("0x%08" PRIx32, objc_category->category_name); 5218 if (info->verbose) { 5219 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5220 true); 5221 if (name != nullptr) 5222 outs() << format(" %.*s", left, name); 5223 else 5224 outs() << " (not in an __OBJC section)"; 5225 } 5226 outs() << "\n"; 5227 5228 outs() << "\t\t class name " 5229 << format("0x%08" PRIx32, objc_category->class_name); 5230 if (info->verbose) { 5231 name = 5232 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5233 if (name != nullptr) 5234 outs() << format(" %.*s", left, name); 5235 else 5236 outs() << " (not in an __OBJC section)"; 5237 } 5238 outs() << "\n"; 5239 5240 outs() << "\t instance methods " 5241 << format("0x%08" PRIx32, objc_category->instance_methods); 5242 if (print_method_list(objc_category->instance_methods, info)) 5243 outs() << " (not in an __OBJC section)\n"; 5244 5245 outs() << "\t class methods " 5246 << format("0x%08" PRIx32, objc_category->class_methods); 5247 if (print_method_list(objc_category->class_methods, info)) 5248 outs() << " (not in an __OBJC section)\n"; 5249 } 5250 5251 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5252 struct category64_t c; 5253 const char *r; 5254 uint32_t offset, xoffset, left; 5255 SectionRef S, xS; 5256 const char *name, *sym_name; 5257 uint64_t n_value; 5258 5259 r = get_pointer_64(p, offset, left, S, info); 5260 if (r == nullptr) 5261 return; 5262 memset(&c, '\0', sizeof(struct category64_t)); 5263 if (left < sizeof(struct category64_t)) { 5264 memcpy(&c, r, left); 5265 outs() << " (category_t entends past the end of the section)\n"; 5266 } else 5267 memcpy(&c, r, sizeof(struct category64_t)); 5268 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5269 swapStruct(c); 5270 5271 outs() << " name "; 5272 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 5273 info, n_value, c.name); 5274 if (n_value != 0) { 5275 if (info->verbose && sym_name != nullptr) 5276 outs() << sym_name; 5277 else 5278 outs() << format("0x%" PRIx64, n_value); 5279 if (c.name != 0) 5280 outs() << " + " << format("0x%" PRIx64, c.name); 5281 } else 5282 outs() << format("0x%" PRIx64, c.name); 5283 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 5284 if (name != nullptr) 5285 outs() << format(" %.*s", left, name); 5286 outs() << "\n"; 5287 5288 outs() << " cls "; 5289 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 5290 n_value, c.cls); 5291 if (n_value != 0) { 5292 if (info->verbose && sym_name != nullptr) 5293 outs() << sym_name; 5294 else 5295 outs() << format("0x%" PRIx64, n_value); 5296 if (c.cls != 0) 5297 outs() << " + " << format("0x%" PRIx64, c.cls); 5298 } else 5299 outs() << format("0x%" PRIx64, c.cls); 5300 outs() << "\n"; 5301 if (c.cls + n_value != 0) 5302 print_class64_t(c.cls + n_value, info); 5303 5304 outs() << " instanceMethods "; 5305 sym_name = 5306 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 5307 info, n_value, c.instanceMethods); 5308 if (n_value != 0) { 5309 if (info->verbose && sym_name != nullptr) 5310 outs() << sym_name; 5311 else 5312 outs() << format("0x%" PRIx64, n_value); 5313 if (c.instanceMethods != 0) 5314 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 5315 } else 5316 outs() << format("0x%" PRIx64, c.instanceMethods); 5317 outs() << "\n"; 5318 if (c.instanceMethods + n_value != 0) 5319 print_method_list64_t(c.instanceMethods + n_value, info, ""); 5320 5321 outs() << " classMethods "; 5322 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 5323 S, info, n_value, c.classMethods); 5324 if (n_value != 0) { 5325 if (info->verbose && sym_name != nullptr) 5326 outs() << sym_name; 5327 else 5328 outs() << format("0x%" PRIx64, n_value); 5329 if (c.classMethods != 0) 5330 outs() << " + " << format("0x%" PRIx64, c.classMethods); 5331 } else 5332 outs() << format("0x%" PRIx64, c.classMethods); 5333 outs() << "\n"; 5334 if (c.classMethods + n_value != 0) 5335 print_method_list64_t(c.classMethods + n_value, info, ""); 5336 5337 outs() << " protocols "; 5338 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 5339 info, n_value, c.protocols); 5340 if (n_value != 0) { 5341 if (info->verbose && sym_name != nullptr) 5342 outs() << sym_name; 5343 else 5344 outs() << format("0x%" PRIx64, n_value); 5345 if (c.protocols != 0) 5346 outs() << " + " << format("0x%" PRIx64, c.protocols); 5347 } else 5348 outs() << format("0x%" PRIx64, c.protocols); 5349 outs() << "\n"; 5350 if (c.protocols + n_value != 0) 5351 print_protocol_list64_t(c.protocols + n_value, info); 5352 5353 outs() << "instanceProperties "; 5354 sym_name = 5355 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 5356 S, info, n_value, c.instanceProperties); 5357 if (n_value != 0) { 5358 if (info->verbose && sym_name != nullptr) 5359 outs() << sym_name; 5360 else 5361 outs() << format("0x%" PRIx64, n_value); 5362 if (c.instanceProperties != 0) 5363 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 5364 } else 5365 outs() << format("0x%" PRIx64, c.instanceProperties); 5366 outs() << "\n"; 5367 if (c.instanceProperties + n_value != 0) 5368 print_objc_property_list64(c.instanceProperties + n_value, info); 5369 } 5370 5371 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 5372 struct category32_t c; 5373 const char *r; 5374 uint32_t offset, left; 5375 SectionRef S, xS; 5376 const char *name; 5377 5378 r = get_pointer_32(p, offset, left, S, info); 5379 if (r == nullptr) 5380 return; 5381 memset(&c, '\0', sizeof(struct category32_t)); 5382 if (left < sizeof(struct category32_t)) { 5383 memcpy(&c, r, left); 5384 outs() << " (category_t entends past the end of the section)\n"; 5385 } else 5386 memcpy(&c, r, sizeof(struct category32_t)); 5387 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5388 swapStruct(c); 5389 5390 outs() << " name " << format("0x%" PRIx32, c.name); 5391 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 5392 c.name); 5393 if (name) 5394 outs() << " " << name; 5395 outs() << "\n"; 5396 5397 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 5398 if (c.cls != 0) 5399 print_class32_t(c.cls, info); 5400 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 5401 << "\n"; 5402 if (c.instanceMethods != 0) 5403 print_method_list32_t(c.instanceMethods, info, ""); 5404 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 5405 << "\n"; 5406 if (c.classMethods != 0) 5407 print_method_list32_t(c.classMethods, info, ""); 5408 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 5409 if (c.protocols != 0) 5410 print_protocol_list32_t(c.protocols, info); 5411 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 5412 << "\n"; 5413 if (c.instanceProperties != 0) 5414 print_objc_property_list32(c.instanceProperties, info); 5415 } 5416 5417 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 5418 uint32_t i, left, offset, xoffset; 5419 uint64_t p, n_value; 5420 struct message_ref64 mr; 5421 const char *name, *sym_name; 5422 const char *r; 5423 SectionRef xS; 5424 5425 if (S == SectionRef()) 5426 return; 5427 5428 StringRef SectName; 5429 S.getName(SectName); 5430 DataRefImpl Ref = S.getRawDataRefImpl(); 5431 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5432 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5433 offset = 0; 5434 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5435 p = S.getAddress() + i; 5436 r = get_pointer_64(p, offset, left, S, info); 5437 if (r == nullptr) 5438 return; 5439 memset(&mr, '\0', sizeof(struct message_ref64)); 5440 if (left < sizeof(struct message_ref64)) { 5441 memcpy(&mr, r, left); 5442 outs() << " (message_ref entends past the end of the section)\n"; 5443 } else 5444 memcpy(&mr, r, sizeof(struct message_ref64)); 5445 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5446 swapStruct(mr); 5447 5448 outs() << " imp "; 5449 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 5450 n_value, mr.imp); 5451 if (n_value != 0) { 5452 outs() << format("0x%" PRIx64, n_value) << " "; 5453 if (mr.imp != 0) 5454 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 5455 } else 5456 outs() << format("0x%" PRIx64, mr.imp) << " "; 5457 if (name != nullptr) 5458 outs() << " " << name; 5459 outs() << "\n"; 5460 5461 outs() << " sel "; 5462 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 5463 info, n_value, mr.sel); 5464 if (n_value != 0) { 5465 if (info->verbose && sym_name != nullptr) 5466 outs() << sym_name; 5467 else 5468 outs() << format("0x%" PRIx64, n_value); 5469 if (mr.sel != 0) 5470 outs() << " + " << format("0x%" PRIx64, mr.sel); 5471 } else 5472 outs() << format("0x%" PRIx64, mr.sel); 5473 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 5474 if (name != nullptr) 5475 outs() << format(" %.*s", left, name); 5476 outs() << "\n"; 5477 5478 offset += sizeof(struct message_ref64); 5479 } 5480 } 5481 5482 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 5483 uint32_t i, left, offset, xoffset, p; 5484 struct message_ref32 mr; 5485 const char *name, *r; 5486 SectionRef xS; 5487 5488 if (S == SectionRef()) 5489 return; 5490 5491 StringRef SectName; 5492 S.getName(SectName); 5493 DataRefImpl Ref = S.getRawDataRefImpl(); 5494 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5495 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5496 offset = 0; 5497 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5498 p = S.getAddress() + i; 5499 r = get_pointer_32(p, offset, left, S, info); 5500 if (r == nullptr) 5501 return; 5502 memset(&mr, '\0', sizeof(struct message_ref32)); 5503 if (left < sizeof(struct message_ref32)) { 5504 memcpy(&mr, r, left); 5505 outs() << " (message_ref entends past the end of the section)\n"; 5506 } else 5507 memcpy(&mr, r, sizeof(struct message_ref32)); 5508 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5509 swapStruct(mr); 5510 5511 outs() << " imp " << format("0x%" PRIx32, mr.imp); 5512 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 5513 mr.imp); 5514 if (name != nullptr) 5515 outs() << " " << name; 5516 outs() << "\n"; 5517 5518 outs() << " sel " << format("0x%" PRIx32, mr.sel); 5519 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 5520 if (name != nullptr) 5521 outs() << " " << name; 5522 outs() << "\n"; 5523 5524 offset += sizeof(struct message_ref32); 5525 } 5526 } 5527 5528 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 5529 uint32_t left, offset, swift_version; 5530 uint64_t p; 5531 struct objc_image_info64 o; 5532 const char *r; 5533 5534 if (S == SectionRef()) 5535 return; 5536 5537 StringRef SectName; 5538 S.getName(SectName); 5539 DataRefImpl Ref = S.getRawDataRefImpl(); 5540 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5541 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5542 p = S.getAddress(); 5543 r = get_pointer_64(p, offset, left, S, info); 5544 if (r == nullptr) 5545 return; 5546 memset(&o, '\0', sizeof(struct objc_image_info64)); 5547 if (left < sizeof(struct objc_image_info64)) { 5548 memcpy(&o, r, left); 5549 outs() << " (objc_image_info entends past the end of the section)\n"; 5550 } else 5551 memcpy(&o, r, sizeof(struct objc_image_info64)); 5552 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5553 swapStruct(o); 5554 outs() << " version " << o.version << "\n"; 5555 outs() << " flags " << format("0x%" PRIx32, o.flags); 5556 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5557 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5558 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5559 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5560 swift_version = (o.flags >> 8) & 0xff; 5561 if (swift_version != 0) { 5562 if (swift_version == 1) 5563 outs() << " Swift 1.0"; 5564 else if (swift_version == 2) 5565 outs() << " Swift 1.1"; 5566 else 5567 outs() << " unknown future Swift version (" << swift_version << ")"; 5568 } 5569 outs() << "\n"; 5570 } 5571 5572 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 5573 uint32_t left, offset, swift_version, p; 5574 struct objc_image_info32 o; 5575 const char *r; 5576 5577 if (S == SectionRef()) 5578 return; 5579 5580 StringRef SectName; 5581 S.getName(SectName); 5582 DataRefImpl Ref = S.getRawDataRefImpl(); 5583 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5584 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5585 p = S.getAddress(); 5586 r = get_pointer_32(p, offset, left, S, info); 5587 if (r == nullptr) 5588 return; 5589 memset(&o, '\0', sizeof(struct objc_image_info32)); 5590 if (left < sizeof(struct objc_image_info32)) { 5591 memcpy(&o, r, left); 5592 outs() << " (objc_image_info entends past the end of the section)\n"; 5593 } else 5594 memcpy(&o, r, sizeof(struct objc_image_info32)); 5595 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5596 swapStruct(o); 5597 outs() << " version " << o.version << "\n"; 5598 outs() << " flags " << format("0x%" PRIx32, o.flags); 5599 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5600 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5601 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5602 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5603 swift_version = (o.flags >> 8) & 0xff; 5604 if (swift_version != 0) { 5605 if (swift_version == 1) 5606 outs() << " Swift 1.0"; 5607 else if (swift_version == 2) 5608 outs() << " Swift 1.1"; 5609 else 5610 outs() << " unknown future Swift version (" << swift_version << ")"; 5611 } 5612 outs() << "\n"; 5613 } 5614 5615 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 5616 uint32_t left, offset, p; 5617 struct imageInfo_t o; 5618 const char *r; 5619 5620 StringRef SectName; 5621 S.getName(SectName); 5622 DataRefImpl Ref = S.getRawDataRefImpl(); 5623 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5624 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5625 p = S.getAddress(); 5626 r = get_pointer_32(p, offset, left, S, info); 5627 if (r == nullptr) 5628 return; 5629 memset(&o, '\0', sizeof(struct imageInfo_t)); 5630 if (left < sizeof(struct imageInfo_t)) { 5631 memcpy(&o, r, left); 5632 outs() << " (imageInfo entends past the end of the section)\n"; 5633 } else 5634 memcpy(&o, r, sizeof(struct imageInfo_t)); 5635 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5636 swapStruct(o); 5637 outs() << " version " << o.version << "\n"; 5638 outs() << " flags " << format("0x%" PRIx32, o.flags); 5639 if (o.flags & 0x1) 5640 outs() << " F&C"; 5641 if (o.flags & 0x2) 5642 outs() << " GC"; 5643 if (o.flags & 0x4) 5644 outs() << " GC-only"; 5645 else 5646 outs() << " RR"; 5647 outs() << "\n"; 5648 } 5649 5650 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 5651 SymbolAddressMap AddrMap; 5652 if (verbose) 5653 CreateSymbolAddressMap(O, &AddrMap); 5654 5655 std::vector<SectionRef> Sections; 5656 for (const SectionRef &Section : O->sections()) { 5657 StringRef SectName; 5658 Section.getName(SectName); 5659 Sections.push_back(Section); 5660 } 5661 5662 struct DisassembleInfo info; 5663 // Set up the block of info used by the Symbolizer call backs. 5664 info.verbose = verbose; 5665 info.O = O; 5666 info.AddrMap = &AddrMap; 5667 info.Sections = &Sections; 5668 info.class_name = nullptr; 5669 info.selector_name = nullptr; 5670 info.method = nullptr; 5671 info.demangled_name = nullptr; 5672 info.bindtable = nullptr; 5673 info.adrp_addr = 0; 5674 info.adrp_inst = 0; 5675 5676 info.depth = 0; 5677 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5678 if (CL == SectionRef()) 5679 CL = get_section(O, "__DATA", "__objc_classlist"); 5680 if (CL == SectionRef()) 5681 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5682 if (CL == SectionRef()) 5683 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5684 info.S = CL; 5685 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 5686 5687 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5688 if (CR == SectionRef()) 5689 CR = get_section(O, "__DATA", "__objc_classrefs"); 5690 if (CR == SectionRef()) 5691 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5692 if (CR == SectionRef()) 5693 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5694 info.S = CR; 5695 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 5696 5697 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5698 if (SR == SectionRef()) 5699 SR = get_section(O, "__DATA", "__objc_superrefs"); 5700 if (SR == SectionRef()) 5701 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5702 if (SR == SectionRef()) 5703 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5704 info.S = SR; 5705 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 5706 5707 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5708 if (CA == SectionRef()) 5709 CA = get_section(O, "__DATA", "__objc_catlist"); 5710 if (CA == SectionRef()) 5711 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5712 if (CA == SectionRef()) 5713 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5714 info.S = CA; 5715 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 5716 5717 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5718 if (PL == SectionRef()) 5719 PL = get_section(O, "__DATA", "__objc_protolist"); 5720 if (PL == SectionRef()) 5721 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5722 if (PL == SectionRef()) 5723 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5724 info.S = PL; 5725 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 5726 5727 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5728 if (MR == SectionRef()) 5729 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5730 if (MR == SectionRef()) 5731 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5732 if (MR == SectionRef()) 5733 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5734 info.S = MR; 5735 print_message_refs64(MR, &info); 5736 5737 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5738 if (II == SectionRef()) 5739 II = get_section(O, "__DATA", "__objc_imageinfo"); 5740 if (II == SectionRef()) 5741 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5742 if (II == SectionRef()) 5743 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5744 info.S = II; 5745 print_image_info64(II, &info); 5746 } 5747 5748 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5749 SymbolAddressMap AddrMap; 5750 if (verbose) 5751 CreateSymbolAddressMap(O, &AddrMap); 5752 5753 std::vector<SectionRef> Sections; 5754 for (const SectionRef &Section : O->sections()) { 5755 StringRef SectName; 5756 Section.getName(SectName); 5757 Sections.push_back(Section); 5758 } 5759 5760 struct DisassembleInfo info; 5761 // Set up the block of info used by the Symbolizer call backs. 5762 info.verbose = verbose; 5763 info.O = O; 5764 info.AddrMap = &AddrMap; 5765 info.Sections = &Sections; 5766 info.class_name = nullptr; 5767 info.selector_name = nullptr; 5768 info.method = nullptr; 5769 info.demangled_name = nullptr; 5770 info.bindtable = nullptr; 5771 info.adrp_addr = 0; 5772 info.adrp_inst = 0; 5773 5774 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5775 if (CL == SectionRef()) 5776 CL = get_section(O, "__DATA", "__objc_classlist"); 5777 if (CL == SectionRef()) 5778 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5779 if (CL == SectionRef()) 5780 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5781 info.S = CL; 5782 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 5783 5784 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5785 if (CR == SectionRef()) 5786 CR = get_section(O, "__DATA", "__objc_classrefs"); 5787 if (CR == SectionRef()) 5788 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5789 if (CR == SectionRef()) 5790 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5791 info.S = CR; 5792 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 5793 5794 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5795 if (SR == SectionRef()) 5796 SR = get_section(O, "__DATA", "__objc_superrefs"); 5797 if (SR == SectionRef()) 5798 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5799 if (SR == SectionRef()) 5800 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5801 info.S = SR; 5802 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 5803 5804 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5805 if (CA == SectionRef()) 5806 CA = get_section(O, "__DATA", "__objc_catlist"); 5807 if (CA == SectionRef()) 5808 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5809 if (CA == SectionRef()) 5810 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5811 info.S = CA; 5812 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 5813 5814 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5815 if (PL == SectionRef()) 5816 PL = get_section(O, "__DATA", "__objc_protolist"); 5817 if (PL == SectionRef()) 5818 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5819 if (PL == SectionRef()) 5820 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5821 info.S = PL; 5822 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 5823 5824 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5825 if (MR == SectionRef()) 5826 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5827 if (MR == SectionRef()) 5828 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5829 if (MR == SectionRef()) 5830 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5831 info.S = MR; 5832 print_message_refs32(MR, &info); 5833 5834 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5835 if (II == SectionRef()) 5836 II = get_section(O, "__DATA", "__objc_imageinfo"); 5837 if (II == SectionRef()) 5838 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5839 if (II == SectionRef()) 5840 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5841 info.S = II; 5842 print_image_info32(II, &info); 5843 } 5844 5845 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5846 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 5847 const char *r, *name, *defs; 5848 struct objc_module_t module; 5849 SectionRef S, xS; 5850 struct objc_symtab_t symtab; 5851 struct objc_class_t objc_class; 5852 struct objc_category_t objc_category; 5853 5854 outs() << "Objective-C segment\n"; 5855 S = get_section(O, "__OBJC", "__module_info"); 5856 if (S == SectionRef()) 5857 return false; 5858 5859 SymbolAddressMap AddrMap; 5860 if (verbose) 5861 CreateSymbolAddressMap(O, &AddrMap); 5862 5863 std::vector<SectionRef> Sections; 5864 for (const SectionRef &Section : O->sections()) { 5865 StringRef SectName; 5866 Section.getName(SectName); 5867 Sections.push_back(Section); 5868 } 5869 5870 struct DisassembleInfo info; 5871 // Set up the block of info used by the Symbolizer call backs. 5872 info.verbose = verbose; 5873 info.O = O; 5874 info.AddrMap = &AddrMap; 5875 info.Sections = &Sections; 5876 info.class_name = nullptr; 5877 info.selector_name = nullptr; 5878 info.method = nullptr; 5879 info.demangled_name = nullptr; 5880 info.bindtable = nullptr; 5881 info.adrp_addr = 0; 5882 info.adrp_inst = 0; 5883 5884 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 5885 p = S.getAddress() + i; 5886 r = get_pointer_32(p, offset, left, S, &info, true); 5887 if (r == nullptr) 5888 return true; 5889 memset(&module, '\0', sizeof(struct objc_module_t)); 5890 if (left < sizeof(struct objc_module_t)) { 5891 memcpy(&module, r, left); 5892 outs() << " (module extends past end of __module_info section)\n"; 5893 } else 5894 memcpy(&module, r, sizeof(struct objc_module_t)); 5895 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5896 swapStruct(module); 5897 5898 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 5899 outs() << " version " << module.version << "\n"; 5900 outs() << " size " << module.size << "\n"; 5901 outs() << " name "; 5902 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 5903 if (name != nullptr) 5904 outs() << format("%.*s", left, name); 5905 else 5906 outs() << format("0x%08" PRIx32, module.name) 5907 << "(not in an __OBJC section)"; 5908 outs() << "\n"; 5909 5910 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 5911 if (module.symtab == 0 || r == nullptr) { 5912 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 5913 << " (not in an __OBJC section)\n"; 5914 continue; 5915 } 5916 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 5917 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 5918 defs_left = 0; 5919 defs = nullptr; 5920 if (left < sizeof(struct objc_symtab_t)) { 5921 memcpy(&symtab, r, left); 5922 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 5923 } else { 5924 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 5925 if (left > sizeof(struct objc_symtab_t)) { 5926 defs_left = left - sizeof(struct objc_symtab_t); 5927 defs = r + sizeof(struct objc_symtab_t); 5928 } 5929 } 5930 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5931 swapStruct(symtab); 5932 5933 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 5934 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 5935 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 5936 if (r == nullptr) 5937 outs() << " (not in an __OBJC section)"; 5938 outs() << "\n"; 5939 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 5940 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 5941 if (symtab.cls_def_cnt > 0) 5942 outs() << "\tClass Definitions\n"; 5943 for (j = 0; j < symtab.cls_def_cnt; j++) { 5944 if ((j + 1) * sizeof(uint32_t) > defs_left) { 5945 outs() << "\t(remaining class defs entries entends past the end of the " 5946 << "section)\n"; 5947 break; 5948 } 5949 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 5950 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5951 sys::swapByteOrder(def); 5952 5953 r = get_pointer_32(def, xoffset, left, xS, &info, true); 5954 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 5955 if (r != nullptr) { 5956 if (left > sizeof(struct objc_class_t)) { 5957 outs() << "\n"; 5958 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 5959 } else { 5960 outs() << " (entends past the end of the section)\n"; 5961 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 5962 memcpy(&objc_class, r, left); 5963 } 5964 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5965 swapStruct(objc_class); 5966 print_objc_class_t(&objc_class, &info); 5967 } else { 5968 outs() << "(not in an __OBJC section)\n"; 5969 } 5970 5971 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 5972 outs() << "\tMeta Class"; 5973 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 5974 if (r != nullptr) { 5975 if (left > sizeof(struct objc_class_t)) { 5976 outs() << "\n"; 5977 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 5978 } else { 5979 outs() << " (entends past the end of the section)\n"; 5980 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 5981 memcpy(&objc_class, r, left); 5982 } 5983 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5984 swapStruct(objc_class); 5985 print_objc_class_t(&objc_class, &info); 5986 } else { 5987 outs() << "(not in an __OBJC section)\n"; 5988 } 5989 } 5990 } 5991 if (symtab.cat_def_cnt > 0) 5992 outs() << "\tCategory Definitions\n"; 5993 for (j = 0; j < symtab.cat_def_cnt; j++) { 5994 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 5995 outs() << "\t(remaining category defs entries entends past the end of " 5996 << "the section)\n"; 5997 break; 5998 } 5999 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6000 sizeof(uint32_t)); 6001 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6002 sys::swapByteOrder(def); 6003 6004 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6005 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6006 << format("0x%08" PRIx32, def); 6007 if (r != nullptr) { 6008 if (left > sizeof(struct objc_category_t)) { 6009 outs() << "\n"; 6010 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6011 } else { 6012 outs() << " (entends past the end of the section)\n"; 6013 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6014 memcpy(&objc_category, r, left); 6015 } 6016 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6017 swapStruct(objc_category); 6018 print_objc_objc_category_t(&objc_category, &info); 6019 } else { 6020 outs() << "(not in an __OBJC section)\n"; 6021 } 6022 } 6023 } 6024 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6025 if (II != SectionRef()) 6026 print_image_info(II, &info); 6027 6028 return true; 6029 } 6030 6031 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6032 uint32_t size, uint32_t addr) { 6033 SymbolAddressMap AddrMap; 6034 CreateSymbolAddressMap(O, &AddrMap); 6035 6036 std::vector<SectionRef> Sections; 6037 for (const SectionRef &Section : O->sections()) { 6038 StringRef SectName; 6039 Section.getName(SectName); 6040 Sections.push_back(Section); 6041 } 6042 6043 struct DisassembleInfo info; 6044 // Set up the block of info used by the Symbolizer call backs. 6045 info.verbose = true; 6046 info.O = O; 6047 info.AddrMap = &AddrMap; 6048 info.Sections = &Sections; 6049 info.class_name = nullptr; 6050 info.selector_name = nullptr; 6051 info.method = nullptr; 6052 info.demangled_name = nullptr; 6053 info.bindtable = nullptr; 6054 info.adrp_addr = 0; 6055 info.adrp_inst = 0; 6056 6057 const char *p; 6058 struct objc_protocol_t protocol; 6059 uint32_t left, paddr; 6060 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6061 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6062 left = size - (p - sect); 6063 if (left < sizeof(struct objc_protocol_t)) { 6064 outs() << "Protocol extends past end of __protocol section\n"; 6065 memcpy(&protocol, p, left); 6066 } else 6067 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6068 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6069 swapStruct(protocol); 6070 paddr = addr + (p - sect); 6071 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6072 if (print_protocol(paddr, 0, &info)) 6073 outs() << "(not in an __OBJC section)\n"; 6074 } 6075 } 6076 6077 #ifdef HAVE_LIBXAR 6078 inline void swapStruct(struct xar_header &xar) { 6079 sys::swapByteOrder(xar.magic); 6080 sys::swapByteOrder(xar.size); 6081 sys::swapByteOrder(xar.version); 6082 sys::swapByteOrder(xar.toc_length_compressed); 6083 sys::swapByteOrder(xar.toc_length_uncompressed); 6084 sys::swapByteOrder(xar.cksum_alg); 6085 } 6086 6087 static void PrintModeVerbose(uint32_t mode) { 6088 switch(mode & S_IFMT){ 6089 case S_IFDIR: 6090 outs() << "d"; 6091 break; 6092 case S_IFCHR: 6093 outs() << "c"; 6094 break; 6095 case S_IFBLK: 6096 outs() << "b"; 6097 break; 6098 case S_IFREG: 6099 outs() << "-"; 6100 break; 6101 case S_IFLNK: 6102 outs() << "l"; 6103 break; 6104 case S_IFSOCK: 6105 outs() << "s"; 6106 break; 6107 default: 6108 outs() << "?"; 6109 break; 6110 } 6111 6112 /* owner permissions */ 6113 if(mode & S_IREAD) 6114 outs() << "r"; 6115 else 6116 outs() << "-"; 6117 if(mode & S_IWRITE) 6118 outs() << "w"; 6119 else 6120 outs() << "-"; 6121 if(mode & S_ISUID) 6122 outs() << "s"; 6123 else if(mode & S_IEXEC) 6124 outs() << "x"; 6125 else 6126 outs() << "-"; 6127 6128 /* group permissions */ 6129 if(mode & (S_IREAD >> 3)) 6130 outs() << "r"; 6131 else 6132 outs() << "-"; 6133 if(mode & (S_IWRITE >> 3)) 6134 outs() << "w"; 6135 else 6136 outs() << "-"; 6137 if(mode & S_ISGID) 6138 outs() << "s"; 6139 else if(mode & (S_IEXEC >> 3)) 6140 outs() << "x"; 6141 else 6142 outs() << "-"; 6143 6144 /* other permissions */ 6145 if(mode & (S_IREAD >> 6)) 6146 outs() << "r"; 6147 else 6148 outs() << "-"; 6149 if(mode & (S_IWRITE >> 6)) 6150 outs() << "w"; 6151 else 6152 outs() << "-"; 6153 if(mode & S_ISVTX) 6154 outs() << "t"; 6155 else if(mode & (S_IEXEC >> 6)) 6156 outs() << "x"; 6157 else 6158 outs() << "-"; 6159 } 6160 6161 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { 6162 xar_file_t xf; 6163 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; 6164 char *endp; 6165 uint32_t mode_value; 6166 6167 ScopedXarIter xi; 6168 if (!xi) { 6169 errs() << "Can't obtain an xar iterator for xar archive " 6170 << XarFilename << "\n"; 6171 return; 6172 } 6173 6174 // Go through the xar's files. 6175 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { 6176 ScopedXarIter xp; 6177 if(!xp){ 6178 errs() << "Can't obtain an xar iterator for xar archive " 6179 << XarFilename << "\n"; 6180 return; 6181 } 6182 type = nullptr; 6183 mode = nullptr; 6184 user = nullptr; 6185 group = nullptr; 6186 size = nullptr; 6187 mtime = nullptr; 6188 name = nullptr; 6189 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6190 const char *val = nullptr; 6191 xar_prop_get(xf, key, &val); 6192 #if 0 // Useful for debugging. 6193 outs() << "key: " << key << " value: " << val << "\n"; 6194 #endif 6195 if(strcmp(key, "type") == 0) 6196 type = val; 6197 if(strcmp(key, "mode") == 0) 6198 mode = val; 6199 if(strcmp(key, "user") == 0) 6200 user = val; 6201 if(strcmp(key, "group") == 0) 6202 group = val; 6203 if(strcmp(key, "data/size") == 0) 6204 size = val; 6205 if(strcmp(key, "mtime") == 0) 6206 mtime = val; 6207 if(strcmp(key, "name") == 0) 6208 name = val; 6209 } 6210 if(mode != nullptr){ 6211 mode_value = strtoul(mode, &endp, 8); 6212 if(*endp != '\0') 6213 outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; 6214 if(strcmp(type, "file") == 0) 6215 mode_value |= S_IFREG; 6216 PrintModeVerbose(mode_value); 6217 outs() << " "; 6218 } 6219 if(user != nullptr) 6220 outs() << format("%10s/", user); 6221 if(group != nullptr) 6222 outs() << format("%-10s ", group); 6223 if(size != nullptr) 6224 outs() << format("%7s ", size); 6225 if(mtime != nullptr){ 6226 for(m = mtime; *m != 'T' && *m != '\0'; m++) 6227 outs() << *m; 6228 if(*m == 'T') 6229 m++; 6230 outs() << " "; 6231 for( ; *m != 'Z' && *m != '\0'; m++) 6232 outs() << *m; 6233 outs() << " "; 6234 } 6235 if(name != nullptr) 6236 outs() << name; 6237 outs() << "\n"; 6238 } 6239 } 6240 6241 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 6242 uint32_t size, bool verbose, 6243 bool PrintXarHeader, bool PrintXarFileHeaders, 6244 std::string XarMemberName) { 6245 if(size < sizeof(struct xar_header)) { 6246 outs() << "size of (__LLVM,__bundle) section too small (smaller than size " 6247 "of struct xar_header)\n"; 6248 return; 6249 } 6250 struct xar_header XarHeader; 6251 memcpy(&XarHeader, sect, sizeof(struct xar_header)); 6252 if (sys::IsLittleEndianHost) 6253 swapStruct(XarHeader); 6254 if (PrintXarHeader) { 6255 if (!XarMemberName.empty()) 6256 outs() << "In xar member " << XarMemberName << ": "; 6257 else 6258 outs() << "For (__LLVM,__bundle) section: "; 6259 outs() << "xar header\n"; 6260 if (XarHeader.magic == XAR_HEADER_MAGIC) 6261 outs() << " magic XAR_HEADER_MAGIC\n"; 6262 else 6263 outs() << " magic " 6264 << format_hex(XarHeader.magic, 10, true) 6265 << " (not XAR_HEADER_MAGIC)\n"; 6266 outs() << " size " << XarHeader.size << "\n"; 6267 outs() << " version " << XarHeader.version << "\n"; 6268 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed 6269 << "\n"; 6270 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed 6271 << "\n"; 6272 outs() << " cksum_alg "; 6273 switch (XarHeader.cksum_alg) { 6274 case XAR_CKSUM_NONE: 6275 outs() << "XAR_CKSUM_NONE\n"; 6276 break; 6277 case XAR_CKSUM_SHA1: 6278 outs() << "XAR_CKSUM_SHA1\n"; 6279 break; 6280 case XAR_CKSUM_MD5: 6281 outs() << "XAR_CKSUM_MD5\n"; 6282 break; 6283 #ifdef XAR_CKSUM_SHA256 6284 case XAR_CKSUM_SHA256: 6285 outs() << "XAR_CKSUM_SHA256\n"; 6286 break; 6287 #endif 6288 #ifdef XAR_CKSUM_SHA512 6289 case XAR_CKSUM_SHA512: 6290 outs() << "XAR_CKSUM_SHA512\n"; 6291 break; 6292 #endif 6293 default: 6294 outs() << XarHeader.cksum_alg << "\n"; 6295 } 6296 } 6297 6298 SmallString<128> XarFilename; 6299 int FD; 6300 std::error_code XarEC = 6301 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); 6302 if (XarEC) { 6303 errs() << XarEC.message() << "\n"; 6304 return; 6305 } 6306 ToolOutputFile XarFile(XarFilename, FD); 6307 raw_fd_ostream &XarOut = XarFile.os(); 6308 StringRef XarContents(sect, size); 6309 XarOut << XarContents; 6310 XarOut.close(); 6311 if (XarOut.has_error()) 6312 return; 6313 6314 ScopedXarFile xar(XarFilename.c_str(), READ); 6315 if (!xar) { 6316 errs() << "Can't create temporary xar archive " << XarFilename << "\n"; 6317 return; 6318 } 6319 6320 SmallString<128> TocFilename; 6321 std::error_code TocEC = 6322 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); 6323 if (TocEC) { 6324 errs() << TocEC.message() << "\n"; 6325 return; 6326 } 6327 xar_serialize(xar, TocFilename.c_str()); 6328 6329 if (PrintXarFileHeaders) { 6330 if (!XarMemberName.empty()) 6331 outs() << "In xar member " << XarMemberName << ": "; 6332 else 6333 outs() << "For (__LLVM,__bundle) section: "; 6334 outs() << "xar archive files:\n"; 6335 PrintXarFilesSummary(XarFilename.c_str(), xar); 6336 } 6337 6338 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 6339 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); 6340 if (std::error_code EC = FileOrErr.getError()) { 6341 errs() << EC.message() << "\n"; 6342 return; 6343 } 6344 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 6345 6346 if (!XarMemberName.empty()) 6347 outs() << "In xar member " << XarMemberName << ": "; 6348 else 6349 outs() << "For (__LLVM,__bundle) section: "; 6350 outs() << "xar table of contents:\n"; 6351 outs() << Buffer->getBuffer() << "\n"; 6352 6353 // TODO: Go through the xar's files. 6354 ScopedXarIter xi; 6355 if(!xi){ 6356 errs() << "Can't obtain an xar iterator for xar archive " 6357 << XarFilename.c_str() << "\n"; 6358 return; 6359 } 6360 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ 6361 const char *key; 6362 const char *member_name, *member_type, *member_size_string; 6363 size_t member_size; 6364 6365 ScopedXarIter xp; 6366 if(!xp){ 6367 errs() << "Can't obtain an xar iterator for xar archive " 6368 << XarFilename.c_str() << "\n"; 6369 return; 6370 } 6371 member_name = NULL; 6372 member_type = NULL; 6373 member_size_string = NULL; 6374 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6375 const char *val = nullptr; 6376 xar_prop_get(xf, key, &val); 6377 #if 0 // Useful for debugging. 6378 outs() << "key: " << key << " value: " << val << "\n"; 6379 #endif 6380 if (strcmp(key, "name") == 0) 6381 member_name = val; 6382 if (strcmp(key, "type") == 0) 6383 member_type = val; 6384 if (strcmp(key, "data/size") == 0) 6385 member_size_string = val; 6386 } 6387 /* 6388 * If we find a file with a name, date/size and type properties 6389 * and with the type being "file" see if that is a xar file. 6390 */ 6391 if (member_name != NULL && member_type != NULL && 6392 strcmp(member_type, "file") == 0 && 6393 member_size_string != NULL){ 6394 // Extract the file into a buffer. 6395 char *endptr; 6396 member_size = strtoul(member_size_string, &endptr, 10); 6397 if (*endptr == '\0' && member_size != 0) { 6398 char *buffer; 6399 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { 6400 #if 0 // Useful for debugging. 6401 outs() << "xar member: " << member_name << " extracted\n"; 6402 #endif 6403 // Set the XarMemberName we want to see printed in the header. 6404 std::string OldXarMemberName; 6405 // If XarMemberName is already set this is nested. So 6406 // save the old name and create the nested name. 6407 if (!XarMemberName.empty()) { 6408 OldXarMemberName = XarMemberName; 6409 XarMemberName = 6410 (Twine("[") + XarMemberName + "]" + member_name).str(); 6411 } else { 6412 OldXarMemberName = ""; 6413 XarMemberName = member_name; 6414 } 6415 // See if this is could be a xar file (nested). 6416 if (member_size >= sizeof(struct xar_header)) { 6417 #if 0 // Useful for debugging. 6418 outs() << "could be a xar file: " << member_name << "\n"; 6419 #endif 6420 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); 6421 if (sys::IsLittleEndianHost) 6422 swapStruct(XarHeader); 6423 if (XarHeader.magic == XAR_HEADER_MAGIC) 6424 DumpBitcodeSection(O, buffer, member_size, verbose, 6425 PrintXarHeader, PrintXarFileHeaders, 6426 XarMemberName); 6427 } 6428 XarMemberName = OldXarMemberName; 6429 delete buffer; 6430 } 6431 } 6432 } 6433 } 6434 } 6435 #endif // defined(HAVE_LIBXAR) 6436 6437 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6438 if (O->is64Bit()) 6439 printObjc2_64bit_MetaData(O, verbose); 6440 else { 6441 MachO::mach_header H; 6442 H = O->getHeader(); 6443 if (H.cputype == MachO::CPU_TYPE_ARM) 6444 printObjc2_32bit_MetaData(O, verbose); 6445 else { 6446 // This is the 32-bit non-arm cputype case. Which is normally 6447 // the first Objective-C ABI. But it may be the case of a 6448 // binary for the iOS simulator which is the second Objective-C 6449 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6450 // and return false. 6451 if (!printObjc1_32bit_MetaData(O, verbose)) 6452 printObjc2_32bit_MetaData(O, verbose); 6453 } 6454 } 6455 } 6456 6457 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6458 // for the address passed in as ReferenceValue for printing as a comment with 6459 // the instruction and also returns the corresponding type of that item 6460 // indirectly through ReferenceType. 6461 // 6462 // If ReferenceValue is an address of literal cstring then a pointer to the 6463 // cstring is returned and ReferenceType is set to 6464 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6465 // 6466 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6467 // Class ref that name is returned and the ReferenceType is set accordingly. 6468 // 6469 // Lastly, literals which are Symbol address in a literal pool are looked for 6470 // and if found the symbol name is returned and ReferenceType is set to 6471 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6472 // 6473 // If there is no item in the Mach-O file for the address passed in as 6474 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6475 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6476 uint64_t ReferencePC, 6477 uint64_t *ReferenceType, 6478 struct DisassembleInfo *info) { 6479 // First see if there is an external relocation entry at the ReferencePC. 6480 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6481 uint64_t sect_addr = info->S.getAddress(); 6482 uint64_t sect_offset = ReferencePC - sect_addr; 6483 bool reloc_found = false; 6484 DataRefImpl Rel; 6485 MachO::any_relocation_info RE; 6486 bool isExtern = false; 6487 SymbolRef Symbol; 6488 for (const RelocationRef &Reloc : info->S.relocations()) { 6489 uint64_t RelocOffset = Reloc.getOffset(); 6490 if (RelocOffset == sect_offset) { 6491 Rel = Reloc.getRawDataRefImpl(); 6492 RE = info->O->getRelocation(Rel); 6493 if (info->O->isRelocationScattered(RE)) 6494 continue; 6495 isExtern = info->O->getPlainRelocationExternal(RE); 6496 if (isExtern) { 6497 symbol_iterator RelocSym = Reloc.getSymbol(); 6498 Symbol = *RelocSym; 6499 } 6500 reloc_found = true; 6501 break; 6502 } 6503 } 6504 // If there is an external relocation entry for a symbol in a section 6505 // then used that symbol's value for the value of the reference. 6506 if (reloc_found && isExtern) { 6507 if (info->O->getAnyRelocationPCRel(RE)) { 6508 unsigned Type = info->O->getAnyRelocationType(RE); 6509 if (Type == MachO::X86_64_RELOC_SIGNED) { 6510 ReferenceValue = Symbol.getValue(); 6511 } 6512 } 6513 } 6514 } 6515 6516 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6517 // Message refs and Class refs. 6518 bool classref, selref, msgref, cfstring; 6519 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6520 selref, msgref, cfstring); 6521 if (classref && pointer_value == 0) { 6522 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6523 // And the pointer_value in that section is typically zero as it will be 6524 // set by dyld as part of the "bind information". 6525 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6526 if (name != nullptr) { 6527 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6528 const char *class_name = strrchr(name, '$'); 6529 if (class_name != nullptr && class_name[1] == '_' && 6530 class_name[2] != '\0') { 6531 info->class_name = class_name + 2; 6532 return name; 6533 } 6534 } 6535 } 6536 6537 if (classref) { 6538 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6539 const char *name = 6540 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6541 if (name != nullptr) 6542 info->class_name = name; 6543 else 6544 name = "bad class ref"; 6545 return name; 6546 } 6547 6548 if (cfstring) { 6549 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6550 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6551 return name; 6552 } 6553 6554 if (selref && pointer_value == 0) 6555 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6556 6557 if (pointer_value != 0) 6558 ReferenceValue = pointer_value; 6559 6560 const char *name = GuessCstringPointer(ReferenceValue, info); 6561 if (name) { 6562 if (pointer_value != 0 && selref) { 6563 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6564 info->selector_name = name; 6565 } else if (pointer_value != 0 && msgref) { 6566 info->class_name = nullptr; 6567 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6568 info->selector_name = name; 6569 } else 6570 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6571 return name; 6572 } 6573 6574 // Lastly look for an indirect symbol with this ReferenceValue which is in 6575 // a literal pool. If found return that symbol name. 6576 name = GuessIndirectSymbol(ReferenceValue, info); 6577 if (name) { 6578 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6579 return name; 6580 } 6581 6582 return nullptr; 6583 } 6584 6585 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6586 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6587 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6588 // is created and returns the symbol name that matches the ReferenceValue or 6589 // nullptr if none. The ReferenceType is passed in for the IN type of 6590 // reference the instruction is making from the values in defined in the header 6591 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6592 // Out type and the ReferenceName will also be set which is added as a comment 6593 // to the disassembled instruction. 6594 // 6595 // If the symbol name is a C++ mangled name then the demangled name is 6596 // returned through ReferenceName and ReferenceType is set to 6597 // LLVMDisassembler_ReferenceType_DeMangled_Name . 6598 // 6599 // When this is called to get a symbol name for a branch target then the 6600 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 6601 // SymbolValue will be looked for in the indirect symbol table to determine if 6602 // it is an address for a symbol stub. If so then the symbol name for that 6603 // stub is returned indirectly through ReferenceName and then ReferenceType is 6604 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 6605 // 6606 // When this is called with an value loaded via a PC relative load then 6607 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 6608 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 6609 // or an Objective-C meta data reference. If so the output ReferenceType is 6610 // set to correspond to that as well as setting the ReferenceName. 6611 static const char *SymbolizerSymbolLookUp(void *DisInfo, 6612 uint64_t ReferenceValue, 6613 uint64_t *ReferenceType, 6614 uint64_t ReferencePC, 6615 const char **ReferenceName) { 6616 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 6617 // If no verbose symbolic information is wanted then just return nullptr. 6618 if (!info->verbose) { 6619 *ReferenceName = nullptr; 6620 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6621 return nullptr; 6622 } 6623 6624 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 6625 6626 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 6627 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 6628 if (*ReferenceName != nullptr) { 6629 method_reference(info, ReferenceType, ReferenceName); 6630 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 6631 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 6632 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6633 if (info->demangled_name != nullptr) 6634 free(info->demangled_name); 6635 int status; 6636 info->demangled_name = 6637 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6638 if (info->demangled_name != nullptr) { 6639 *ReferenceName = info->demangled_name; 6640 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6641 } else 6642 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6643 } else 6644 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6645 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 6646 *ReferenceName = 6647 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6648 if (*ReferenceName) 6649 method_reference(info, ReferenceType, ReferenceName); 6650 else 6651 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6652 // If this is arm64 and the reference is an adrp instruction save the 6653 // instruction, passed in ReferenceValue and the address of the instruction 6654 // for use later if we see and add immediate instruction. 6655 } else if (info->O->getArch() == Triple::aarch64 && 6656 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 6657 info->adrp_inst = ReferenceValue; 6658 info->adrp_addr = ReferencePC; 6659 SymbolName = nullptr; 6660 *ReferenceName = nullptr; 6661 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6662 // If this is arm64 and reference is an add immediate instruction and we 6663 // have 6664 // seen an adrp instruction just before it and the adrp's Xd register 6665 // matches 6666 // this add's Xn register reconstruct the value being referenced and look to 6667 // see if it is a literal pointer. Note the add immediate instruction is 6668 // passed in ReferenceValue. 6669 } else if (info->O->getArch() == Triple::aarch64 && 6670 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 6671 ReferencePC - 4 == info->adrp_addr && 6672 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6673 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6674 uint32_t addxri_inst; 6675 uint64_t adrp_imm, addxri_imm; 6676 6677 adrp_imm = 6678 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6679 if (info->adrp_inst & 0x0200000) 6680 adrp_imm |= 0xfffffffffc000000LL; 6681 6682 addxri_inst = ReferenceValue; 6683 addxri_imm = (addxri_inst >> 10) & 0xfff; 6684 if (((addxri_inst >> 22) & 0x3) == 1) 6685 addxri_imm <<= 12; 6686 6687 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6688 (adrp_imm << 12) + addxri_imm; 6689 6690 *ReferenceName = 6691 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6692 if (*ReferenceName == nullptr) 6693 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6694 // If this is arm64 and the reference is a load register instruction and we 6695 // have seen an adrp instruction just before it and the adrp's Xd register 6696 // matches this add's Xn register reconstruct the value being referenced and 6697 // look to see if it is a literal pointer. Note the load register 6698 // instruction is passed in ReferenceValue. 6699 } else if (info->O->getArch() == Triple::aarch64 && 6700 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 6701 ReferencePC - 4 == info->adrp_addr && 6702 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6703 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6704 uint32_t ldrxui_inst; 6705 uint64_t adrp_imm, ldrxui_imm; 6706 6707 adrp_imm = 6708 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6709 if (info->adrp_inst & 0x0200000) 6710 adrp_imm |= 0xfffffffffc000000LL; 6711 6712 ldrxui_inst = ReferenceValue; 6713 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 6714 6715 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6716 (adrp_imm << 12) + (ldrxui_imm << 3); 6717 6718 *ReferenceName = 6719 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6720 if (*ReferenceName == nullptr) 6721 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6722 } 6723 // If this arm64 and is an load register (PC-relative) instruction the 6724 // ReferenceValue is the PC plus the immediate value. 6725 else if (info->O->getArch() == Triple::aarch64 && 6726 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 6727 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 6728 *ReferenceName = 6729 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6730 if (*ReferenceName == nullptr) 6731 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6732 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6733 if (info->demangled_name != nullptr) 6734 free(info->demangled_name); 6735 int status; 6736 info->demangled_name = 6737 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6738 if (info->demangled_name != nullptr) { 6739 *ReferenceName = info->demangled_name; 6740 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6741 } 6742 } 6743 else { 6744 *ReferenceName = nullptr; 6745 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6746 } 6747 6748 return SymbolName; 6749 } 6750 6751 /// \brief Emits the comments that are stored in the CommentStream. 6752 /// Each comment in the CommentStream must end with a newline. 6753 static void emitComments(raw_svector_ostream &CommentStream, 6754 SmallString<128> &CommentsToEmit, 6755 formatted_raw_ostream &FormattedOS, 6756 const MCAsmInfo &MAI) { 6757 // Flush the stream before taking its content. 6758 StringRef Comments = CommentsToEmit.str(); 6759 // Get the default information for printing a comment. 6760 StringRef CommentBegin = MAI.getCommentString(); 6761 unsigned CommentColumn = MAI.getCommentColumn(); 6762 bool IsFirst = true; 6763 while (!Comments.empty()) { 6764 if (!IsFirst) 6765 FormattedOS << '\n'; 6766 // Emit a line of comments. 6767 FormattedOS.PadToColumn(CommentColumn); 6768 size_t Position = Comments.find('\n'); 6769 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 6770 // Move after the newline character. 6771 Comments = Comments.substr(Position + 1); 6772 IsFirst = false; 6773 } 6774 FormattedOS.flush(); 6775 6776 // Tell the comment stream that the vector changed underneath it. 6777 CommentsToEmit.clear(); 6778 } 6779 6780 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 6781 StringRef DisSegName, StringRef DisSectName) { 6782 const char *McpuDefault = nullptr; 6783 const Target *ThumbTarget = nullptr; 6784 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 6785 if (!TheTarget) { 6786 // GetTarget prints out stuff. 6787 return; 6788 } 6789 std::string MachOMCPU; 6790 if (MCPU.empty() && McpuDefault) 6791 MachOMCPU = McpuDefault; 6792 else 6793 MachOMCPU = MCPU; 6794 6795 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 6796 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 6797 if (ThumbTarget) 6798 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 6799 6800 // Package up features to be passed to target/subtarget 6801 std::string FeaturesStr; 6802 if (MAttrs.size()) { 6803 SubtargetFeatures Features; 6804 for (unsigned i = 0; i != MAttrs.size(); ++i) 6805 Features.AddFeature(MAttrs[i]); 6806 FeaturesStr = Features.getString(); 6807 } 6808 6809 // Set up disassembler. 6810 std::unique_ptr<const MCRegisterInfo> MRI( 6811 TheTarget->createMCRegInfo(TripleName)); 6812 std::unique_ptr<const MCAsmInfo> AsmInfo( 6813 TheTarget->createMCAsmInfo(*MRI, TripleName)); 6814 std::unique_ptr<const MCSubtargetInfo> STI( 6815 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 6816 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 6817 std::unique_ptr<MCDisassembler> DisAsm( 6818 TheTarget->createMCDisassembler(*STI, Ctx)); 6819 std::unique_ptr<MCSymbolizer> Symbolizer; 6820 struct DisassembleInfo SymbolizerInfo; 6821 std::unique_ptr<MCRelocationInfo> RelInfo( 6822 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 6823 if (RelInfo) { 6824 Symbolizer.reset(TheTarget->createMCSymbolizer( 6825 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6826 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 6827 DisAsm->setSymbolizer(std::move(Symbolizer)); 6828 } 6829 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 6830 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 6831 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 6832 // Set the display preference for hex vs. decimal immediates. 6833 IP->setPrintImmHex(PrintImmHex); 6834 // Comment stream and backing vector. 6835 SmallString<128> CommentsToEmit; 6836 raw_svector_ostream CommentStream(CommentsToEmit); 6837 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 6838 // if it is done then arm64 comments for string literals don't get printed 6839 // and some constant get printed instead and not setting it causes intel 6840 // (32-bit and 64-bit) comments printed with different spacing before the 6841 // comment causing different diffs with the 'C' disassembler library API. 6842 // IP->setCommentStream(CommentStream); 6843 6844 if (!AsmInfo || !STI || !DisAsm || !IP) { 6845 errs() << "error: couldn't initialize disassembler for target " 6846 << TripleName << '\n'; 6847 return; 6848 } 6849 6850 // Set up separate thumb disassembler if needed. 6851 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 6852 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 6853 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 6854 std::unique_ptr<MCDisassembler> ThumbDisAsm; 6855 std::unique_ptr<MCInstPrinter> ThumbIP; 6856 std::unique_ptr<MCContext> ThumbCtx; 6857 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 6858 struct DisassembleInfo ThumbSymbolizerInfo; 6859 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 6860 if (ThumbTarget) { 6861 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 6862 ThumbAsmInfo.reset( 6863 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName)); 6864 ThumbSTI.reset( 6865 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 6866 FeaturesStr)); 6867 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 6868 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 6869 MCContext *PtrThumbCtx = ThumbCtx.get(); 6870 ThumbRelInfo.reset( 6871 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 6872 if (ThumbRelInfo) { 6873 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 6874 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6875 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 6876 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 6877 } 6878 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 6879 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 6880 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 6881 *ThumbInstrInfo, *ThumbMRI)); 6882 // Set the display preference for hex vs. decimal immediates. 6883 ThumbIP->setPrintImmHex(PrintImmHex); 6884 } 6885 6886 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) { 6887 errs() << "error: couldn't initialize disassembler for target " 6888 << ThumbTripleName << '\n'; 6889 return; 6890 } 6891 6892 MachO::mach_header Header = MachOOF->getHeader(); 6893 6894 // FIXME: Using the -cfg command line option, this code used to be able to 6895 // annotate relocations with the referenced symbol's name, and if this was 6896 // inside a __[cf]string section, the data it points to. This is now replaced 6897 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 6898 std::vector<SectionRef> Sections; 6899 std::vector<SymbolRef> Symbols; 6900 SmallVector<uint64_t, 8> FoundFns; 6901 uint64_t BaseSegmentAddress; 6902 6903 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 6904 BaseSegmentAddress); 6905 6906 // Sort the symbols by address, just in case they didn't come in that way. 6907 std::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); 6908 6909 // Build a data in code table that is sorted on by the address of each entry. 6910 uint64_t BaseAddress = 0; 6911 if (Header.filetype == MachO::MH_OBJECT) 6912 BaseAddress = Sections[0].getAddress(); 6913 else 6914 BaseAddress = BaseSegmentAddress; 6915 DiceTable Dices; 6916 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 6917 DI != DE; ++DI) { 6918 uint32_t Offset; 6919 DI->getOffset(Offset); 6920 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 6921 } 6922 array_pod_sort(Dices.begin(), Dices.end()); 6923 6924 #ifndef NDEBUG 6925 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); 6926 #else 6927 raw_ostream &DebugOut = nulls(); 6928 #endif 6929 6930 std::unique_ptr<DIContext> diContext; 6931 ObjectFile *DbgObj = MachOOF; 6932 // Try to find debug info and set up the DIContext for it. 6933 if (UseDbg) { 6934 // A separate DSym file path was specified, parse it as a macho file, 6935 // get the sections and supply it to the section name parsing machinery. 6936 if (!DSYMFile.empty()) { 6937 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 6938 MemoryBuffer::getFileOrSTDIN(DSYMFile); 6939 if (std::error_code EC = BufOrErr.getError()) { 6940 errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n'; 6941 return; 6942 } 6943 DbgObj = 6944 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()) 6945 .get() 6946 .release(); 6947 } 6948 6949 // Setup the DIContext 6950 diContext = DWARFContext::create(*DbgObj); 6951 } 6952 6953 if (FilterSections.size() == 0) 6954 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 6955 6956 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 6957 StringRef SectName; 6958 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName) 6959 continue; 6960 6961 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 6962 6963 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 6964 if (SegmentName != DisSegName) 6965 continue; 6966 6967 StringRef BytesStr; 6968 Sections[SectIdx].getContents(BytesStr); 6969 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()), 6970 BytesStr.size()); 6971 uint64_t SectAddress = Sections[SectIdx].getAddress(); 6972 6973 bool symbolTableWorked = false; 6974 6975 // Create a map of symbol addresses to symbol names for use by 6976 // the SymbolizerSymbolLookUp() routine. 6977 SymbolAddressMap AddrMap; 6978 bool DisSymNameFound = false; 6979 for (const SymbolRef &Symbol : MachOOF->symbols()) { 6980 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 6981 if (!STOrErr) 6982 report_error(MachOOF->getFileName(), STOrErr.takeError()); 6983 SymbolRef::Type ST = *STOrErr; 6984 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 6985 ST == SymbolRef::ST_Other) { 6986 uint64_t Address = Symbol.getValue(); 6987 Expected<StringRef> SymNameOrErr = Symbol.getName(); 6988 if (!SymNameOrErr) 6989 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 6990 StringRef SymName = *SymNameOrErr; 6991 AddrMap[Address] = SymName; 6992 if (!DisSymName.empty() && DisSymName == SymName) 6993 DisSymNameFound = true; 6994 } 6995 } 6996 if (!DisSymName.empty() && !DisSymNameFound) { 6997 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 6998 return; 6999 } 7000 // Set up the block of info used by the Symbolizer call backs. 7001 SymbolizerInfo.verbose = !NoSymbolicOperands; 7002 SymbolizerInfo.O = MachOOF; 7003 SymbolizerInfo.S = Sections[SectIdx]; 7004 SymbolizerInfo.AddrMap = &AddrMap; 7005 SymbolizerInfo.Sections = &Sections; 7006 SymbolizerInfo.class_name = nullptr; 7007 SymbolizerInfo.selector_name = nullptr; 7008 SymbolizerInfo.method = nullptr; 7009 SymbolizerInfo.demangled_name = nullptr; 7010 SymbolizerInfo.bindtable = nullptr; 7011 SymbolizerInfo.adrp_addr = 0; 7012 SymbolizerInfo.adrp_inst = 0; 7013 // Same for the ThumbSymbolizer 7014 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands; 7015 ThumbSymbolizerInfo.O = MachOOF; 7016 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7017 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7018 ThumbSymbolizerInfo.Sections = &Sections; 7019 ThumbSymbolizerInfo.class_name = nullptr; 7020 ThumbSymbolizerInfo.selector_name = nullptr; 7021 ThumbSymbolizerInfo.method = nullptr; 7022 ThumbSymbolizerInfo.demangled_name = nullptr; 7023 ThumbSymbolizerInfo.bindtable = nullptr; 7024 ThumbSymbolizerInfo.adrp_addr = 0; 7025 ThumbSymbolizerInfo.adrp_inst = 0; 7026 7027 unsigned int Arch = MachOOF->getArch(); 7028 7029 // Skip all symbols if this is a stubs file. 7030 if (Bytes.size() == 0) 7031 return; 7032 7033 // If the section has symbols but no symbol at the start of the section 7034 // these are used to make sure the bytes before the first symbol are 7035 // disassembled. 7036 bool FirstSymbol = true; 7037 bool FirstSymbolAtSectionStart = true; 7038 7039 // Disassemble symbol by symbol. 7040 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7041 Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName(); 7042 if (!SymNameOrErr) 7043 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 7044 StringRef SymName = *SymNameOrErr; 7045 7046 Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType(); 7047 if (!STOrErr) 7048 report_error(MachOOF->getFileName(), STOrErr.takeError()); 7049 SymbolRef::Type ST = *STOrErr; 7050 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7051 continue; 7052 7053 // Make sure the symbol is defined in this section. 7054 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7055 if (!containsSym) { 7056 if (!DisSymName.empty() && DisSymName == SymName) { 7057 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7058 return; 7059 } 7060 continue; 7061 } 7062 // The __mh_execute_header is special and we need to deal with that fact 7063 // this symbol is before the start of the (__TEXT,__text) section and at the 7064 // address of the start of the __TEXT segment. This is because this symbol 7065 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7066 // start of the section in a standard MH_EXECUTE filetype. 7067 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7068 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7069 return; 7070 } 7071 // When this code is trying to disassemble a symbol at a time and in the 7072 // case there is only the __mh_execute_header symbol left as in a stripped 7073 // executable, we need to deal with this by ignoring this symbol so the 7074 // whole section is disassembled and this symbol is then not displayed. 7075 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7076 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7077 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7078 continue; 7079 7080 // If we are only disassembling one symbol see if this is that symbol. 7081 if (!DisSymName.empty() && DisSymName != SymName) 7082 continue; 7083 7084 // Start at the address of the symbol relative to the section's address. 7085 uint64_t SectSize = Sections[SectIdx].getSize(); 7086 uint64_t Start = Symbols[SymIdx].getValue(); 7087 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7088 Start -= SectionAddress; 7089 7090 if (Start > SectSize) { 7091 outs() << "section data ends, " << SymName 7092 << " lies outside valid range\n"; 7093 return; 7094 } 7095 7096 // Stop disassembling either at the beginning of the next symbol or at 7097 // the end of the section. 7098 bool containsNextSym = false; 7099 uint64_t NextSym = 0; 7100 uint64_t NextSymIdx = SymIdx + 1; 7101 while (Symbols.size() > NextSymIdx) { 7102 Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType(); 7103 if (!STOrErr) 7104 report_error(MachOOF->getFileName(), STOrErr.takeError()); 7105 SymbolRef::Type NextSymType = *STOrErr; 7106 if (NextSymType == SymbolRef::ST_Function) { 7107 containsNextSym = 7108 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7109 NextSym = Symbols[NextSymIdx].getValue(); 7110 NextSym -= SectionAddress; 7111 break; 7112 } 7113 ++NextSymIdx; 7114 } 7115 7116 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7117 uint64_t Size; 7118 7119 symbolTableWorked = true; 7120 7121 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7122 bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb; 7123 7124 // We only need the dedicated Thumb target if there's a real choice 7125 // (i.e. we're not targeting M-class) and the function is Thumb. 7126 bool UseThumbTarget = IsThumb && ThumbTarget; 7127 7128 // If we are not specifying a symbol to start disassembly with and this 7129 // is the first symbol in the section but not at the start of the section 7130 // then move the disassembly index to the start of the section and 7131 // don't print the symbol name just yet. This is so the bytes before the 7132 // first symbol are disassembled. 7133 uint64_t SymbolStart = Start; 7134 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7135 FirstSymbolAtSectionStart = false; 7136 Start = 0; 7137 } 7138 else 7139 outs() << SymName << ":\n"; 7140 7141 DILineInfo lastLine; 7142 for (uint64_t Index = Start; Index < End; Index += Size) { 7143 MCInst Inst; 7144 7145 // If this is the first symbol in the section and it was not at the 7146 // start of the section, see if we are at its Index now and if so print 7147 // the symbol name. 7148 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7149 outs() << SymName << ":\n"; 7150 7151 uint64_t PC = SectAddress + Index; 7152 if (!NoLeadingAddr) { 7153 if (FullLeadingAddr) { 7154 if (MachOOF->is64Bit()) 7155 outs() << format("%016" PRIx64, PC); 7156 else 7157 outs() << format("%08" PRIx64, PC); 7158 } else { 7159 outs() << format("%8" PRIx64 ":", PC); 7160 } 7161 } 7162 if (!NoShowRawInsn || Arch == Triple::arm) 7163 outs() << "\t"; 7164 7165 // Check the data in code table here to see if this is data not an 7166 // instruction to be disassembled. 7167 DiceTable Dice; 7168 Dice.push_back(std::make_pair(PC, DiceRef())); 7169 dice_table_iterator DTI = 7170 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 7171 compareDiceTableEntries); 7172 if (DTI != Dices.end()) { 7173 uint16_t Length; 7174 DTI->second.getLength(Length); 7175 uint16_t Kind; 7176 DTI->second.getKind(Kind); 7177 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind); 7178 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 7179 (PC == (DTI->first + Length - 1)) && (Length & 1)) 7180 Size++; 7181 continue; 7182 } 7183 7184 SmallVector<char, 64> AnnotationsBytes; 7185 raw_svector_ostream Annotations(AnnotationsBytes); 7186 7187 bool gotInst; 7188 if (UseThumbTarget) 7189 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7190 PC, DebugOut, Annotations); 7191 else 7192 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7193 DebugOut, Annotations); 7194 if (gotInst) { 7195 if (!NoShowRawInsn || Arch == Triple::arm) { 7196 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); 7197 } 7198 formatted_raw_ostream FormattedOS(outs()); 7199 StringRef AnnotationsStr = Annotations.str(); 7200 if (UseThumbTarget) 7201 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI); 7202 else 7203 IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI); 7204 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7205 7206 // Print debug info. 7207 if (diContext) { 7208 DILineInfo dli = diContext->getLineInfoForAddress(PC); 7209 // Print valid line info if it changed. 7210 if (dli != lastLine && dli.Line != 0) 7211 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7212 << dli.Column; 7213 lastLine = dli; 7214 } 7215 outs() << "\n"; 7216 } else { 7217 unsigned int Arch = MachOOF->getArch(); 7218 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7219 outs() << format("\t.byte 0x%02x #bad opcode\n", 7220 *(Bytes.data() + Index) & 0xff); 7221 Size = 1; // skip exactly one illegible byte and move on. 7222 } else if (Arch == Triple::aarch64 || 7223 (Arch == Triple::arm && !IsThumb)) { 7224 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7225 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7226 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7227 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7228 outs() << format("\t.long\t0x%08x\n", opcode); 7229 Size = 4; 7230 } else if (Arch == Triple::arm) { 7231 assert(IsThumb && "ARM mode should have been dealt with above"); 7232 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7233 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7234 outs() << format("\t.short\t0x%04x\n", opcode); 7235 Size = 2; 7236 } else{ 7237 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 7238 if (Size == 0) 7239 Size = 1; // skip illegible bytes 7240 } 7241 } 7242 } 7243 // Now that we are done disassembled the first symbol set the bool that 7244 // were doing this to false. 7245 FirstSymbol = false; 7246 } 7247 if (!symbolTableWorked) { 7248 // Reading the symbol table didn't work, disassemble the whole section. 7249 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7250 uint64_t SectSize = Sections[SectIdx].getSize(); 7251 uint64_t InstSize; 7252 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7253 MCInst Inst; 7254 7255 uint64_t PC = SectAddress + Index; 7256 SmallVector<char, 64> AnnotationsBytes; 7257 raw_svector_ostream Annotations(AnnotationsBytes); 7258 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7259 DebugOut, Annotations)) { 7260 if (!NoLeadingAddr) { 7261 if (FullLeadingAddr) { 7262 if (MachOOF->is64Bit()) 7263 outs() << format("%016" PRIx64, PC); 7264 else 7265 outs() << format("%08" PRIx64, PC); 7266 } else { 7267 outs() << format("%8" PRIx64 ":", PC); 7268 } 7269 } 7270 if (!NoShowRawInsn || Arch == Triple::arm) { 7271 outs() << "\t"; 7272 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); 7273 } 7274 StringRef AnnotationsStr = Annotations.str(); 7275 IP->printInst(&Inst, outs(), AnnotationsStr, *STI); 7276 outs() << "\n"; 7277 } else { 7278 unsigned int Arch = MachOOF->getArch(); 7279 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7280 outs() << format("\t.byte 0x%02x #bad opcode\n", 7281 *(Bytes.data() + Index) & 0xff); 7282 InstSize = 1; // skip exactly one illegible byte and move on. 7283 } else { 7284 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 7285 if (InstSize == 0) 7286 InstSize = 1; // skip illegible bytes 7287 } 7288 } 7289 } 7290 } 7291 // The TripleName's need to be reset if we are called again for a different 7292 // archtecture. 7293 TripleName = ""; 7294 ThumbTripleName = ""; 7295 7296 if (SymbolizerInfo.method != nullptr) 7297 free(SymbolizerInfo.method); 7298 if (SymbolizerInfo.demangled_name != nullptr) 7299 free(SymbolizerInfo.demangled_name); 7300 if (ThumbSymbolizerInfo.method != nullptr) 7301 free(ThumbSymbolizerInfo.method); 7302 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7303 free(ThumbSymbolizerInfo.demangled_name); 7304 } 7305 } 7306 7307 //===----------------------------------------------------------------------===// 7308 // __compact_unwind section dumping 7309 //===----------------------------------------------------------------------===// 7310 7311 namespace { 7312 7313 template <typename T> 7314 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7315 using llvm::support::little; 7316 using llvm::support::unaligned; 7317 7318 if (Offset + sizeof(T) > Contents.size()) { 7319 outs() << "warning: attempt to read past end of buffer\n"; 7320 return T(); 7321 } 7322 7323 uint64_t Val = 7324 support::endian::read<T, little, unaligned>(Contents.data() + Offset); 7325 return Val; 7326 } 7327 7328 template <typename T> 7329 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7330 T Val = read<T>(Contents, Offset); 7331 Offset += sizeof(T); 7332 return Val; 7333 } 7334 7335 struct CompactUnwindEntry { 7336 uint32_t OffsetInSection; 7337 7338 uint64_t FunctionAddr; 7339 uint32_t Length; 7340 uint32_t CompactEncoding; 7341 uint64_t PersonalityAddr; 7342 uint64_t LSDAAddr; 7343 7344 RelocationRef FunctionReloc; 7345 RelocationRef PersonalityReloc; 7346 RelocationRef LSDAReloc; 7347 7348 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7349 : OffsetInSection(Offset) { 7350 if (Is64) 7351 read<uint64_t>(Contents, Offset); 7352 else 7353 read<uint32_t>(Contents, Offset); 7354 } 7355 7356 private: 7357 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7358 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7359 Length = readNext<uint32_t>(Contents, Offset); 7360 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7361 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7362 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7363 } 7364 }; 7365 } 7366 7367 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7368 /// and data being relocated, determine the best base Name and Addend to use for 7369 /// display purposes. 7370 /// 7371 /// 1. An Extern relocation will directly reference a symbol (and the data is 7372 /// then already an addend), so use that. 7373 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7374 // a symbol before it in the same section, and use the offset from there. 7375 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7376 /// referenced section. 7377 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7378 std::map<uint64_t, SymbolRef> &Symbols, 7379 const RelocationRef &Reloc, uint64_t Addr, 7380 StringRef &Name, uint64_t &Addend) { 7381 if (Reloc.getSymbol() != Obj->symbol_end()) { 7382 Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName(); 7383 if (!NameOrErr) 7384 report_error(Obj->getFileName(), NameOrErr.takeError()); 7385 Name = *NameOrErr; 7386 Addend = Addr; 7387 return; 7388 } 7389 7390 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7391 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7392 7393 uint64_t SectionAddr = RelocSection.getAddress(); 7394 7395 auto Sym = Symbols.upper_bound(Addr); 7396 if (Sym == Symbols.begin()) { 7397 // The first symbol in the object is after this reference, the best we can 7398 // do is section-relative notation. 7399 RelocSection.getName(Name); 7400 Addend = Addr - SectionAddr; 7401 return; 7402 } 7403 7404 // Go back one so that SymbolAddress <= Addr. 7405 --Sym; 7406 7407 auto SectOrErr = Sym->second.getSection(); 7408 if (!SectOrErr) 7409 report_error(Obj->getFileName(), SectOrErr.takeError()); 7410 section_iterator SymSection = *SectOrErr; 7411 if (RelocSection == *SymSection) { 7412 // There's a valid symbol in the same section before this reference. 7413 Expected<StringRef> NameOrErr = Sym->second.getName(); 7414 if (!NameOrErr) 7415 report_error(Obj->getFileName(), NameOrErr.takeError()); 7416 Name = *NameOrErr; 7417 Addend = Addr - Sym->first; 7418 return; 7419 } 7420 7421 // There is a symbol before this reference, but it's in a different 7422 // section. Probably not helpful to mention it, so use the section name. 7423 RelocSection.getName(Name); 7424 Addend = Addr - SectionAddr; 7425 } 7426 7427 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7428 std::map<uint64_t, SymbolRef> &Symbols, 7429 const RelocationRef &Reloc, uint64_t Addr) { 7430 StringRef Name; 7431 uint64_t Addend; 7432 7433 if (!Reloc.getObject()) 7434 return; 7435 7436 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7437 7438 outs() << Name; 7439 if (Addend) 7440 outs() << " + " << format("0x%" PRIx64, Addend); 7441 } 7442 7443 static void 7444 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7445 std::map<uint64_t, SymbolRef> &Symbols, 7446 const SectionRef &CompactUnwind) { 7447 7448 if (!Obj->isLittleEndian()) { 7449 outs() << "Skipping big-endian __compact_unwind section\n"; 7450 return; 7451 } 7452 7453 bool Is64 = Obj->is64Bit(); 7454 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7455 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7456 7457 StringRef Contents; 7458 CompactUnwind.getContents(Contents); 7459 7460 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7461 7462 // First populate the initial raw offsets, encodings and so on from the entry. 7463 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7464 CompactUnwindEntry Entry(Contents, Offset, Is64); 7465 CompactUnwinds.push_back(Entry); 7466 } 7467 7468 // Next we need to look at the relocations to find out what objects are 7469 // actually being referred to. 7470 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7471 uint64_t RelocAddress = Reloc.getOffset(); 7472 7473 uint32_t EntryIdx = RelocAddress / EntrySize; 7474 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7475 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7476 7477 if (OffsetInEntry == 0) 7478 Entry.FunctionReloc = Reloc; 7479 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7480 Entry.PersonalityReloc = Reloc; 7481 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7482 Entry.LSDAReloc = Reloc; 7483 else { 7484 outs() << "Invalid relocation in __compact_unwind section\n"; 7485 return; 7486 } 7487 } 7488 7489 // Finally, we're ready to print the data we've gathered. 7490 outs() << "Contents of __compact_unwind section:\n"; 7491 for (auto &Entry : CompactUnwinds) { 7492 outs() << " Entry at offset " 7493 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7494 7495 // 1. Start of the region this entry applies to. 7496 outs() << " start: " << format("0x%" PRIx64, 7497 Entry.FunctionAddr) << ' '; 7498 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7499 outs() << '\n'; 7500 7501 // 2. Length of the region this entry applies to. 7502 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7503 << '\n'; 7504 // 3. The 32-bit compact encoding. 7505 outs() << " compact encoding: " 7506 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7507 7508 // 4. The personality function, if present. 7509 if (Entry.PersonalityReloc.getObject()) { 7510 outs() << " personality function: " 7511 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7512 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7513 Entry.PersonalityAddr); 7514 outs() << '\n'; 7515 } 7516 7517 // 5. This entry's language-specific data area. 7518 if (Entry.LSDAReloc.getObject()) { 7519 outs() << " LSDA: " << format("0x%" PRIx64, 7520 Entry.LSDAAddr) << ' '; 7521 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7522 outs() << '\n'; 7523 } 7524 } 7525 } 7526 7527 //===----------------------------------------------------------------------===// 7528 // __unwind_info section dumping 7529 //===----------------------------------------------------------------------===// 7530 7531 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 7532 ptrdiff_t Pos = 0; 7533 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7534 (void)Kind; 7535 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7536 7537 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7538 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7539 7540 Pos = EntriesStart; 7541 for (unsigned i = 0; i < NumEntries; ++i) { 7542 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 7543 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7544 7545 outs() << " [" << i << "]: " 7546 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7547 << ", " 7548 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7549 } 7550 } 7551 7552 static void printCompressedSecondLevelUnwindPage( 7553 StringRef PageData, uint32_t FunctionBase, 7554 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7555 ptrdiff_t Pos = 0; 7556 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7557 (void)Kind; 7558 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 7559 7560 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7561 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7562 7563 uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos); 7564 readNext<uint16_t>(PageData, Pos); 7565 StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos); 7566 7567 Pos = EntriesStart; 7568 for (unsigned i = 0; i < NumEntries; ++i) { 7569 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 7570 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 7571 uint32_t EncodingIdx = Entry >> 24; 7572 7573 uint32_t Encoding; 7574 if (EncodingIdx < CommonEncodings.size()) 7575 Encoding = CommonEncodings[EncodingIdx]; 7576 else 7577 Encoding = read<uint32_t>(PageEncodings, 7578 sizeof(uint32_t) * 7579 (EncodingIdx - CommonEncodings.size())); 7580 7581 outs() << " [" << i << "]: " 7582 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7583 << ", " 7584 << "encoding[" << EncodingIdx 7585 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 7586 } 7587 } 7588 7589 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 7590 std::map<uint64_t, SymbolRef> &Symbols, 7591 const SectionRef &UnwindInfo) { 7592 7593 if (!Obj->isLittleEndian()) { 7594 outs() << "Skipping big-endian __unwind_info section\n"; 7595 return; 7596 } 7597 7598 outs() << "Contents of __unwind_info section:\n"; 7599 7600 StringRef Contents; 7601 UnwindInfo.getContents(Contents); 7602 ptrdiff_t Pos = 0; 7603 7604 //===---------------------------------- 7605 // Section header 7606 //===---------------------------------- 7607 7608 uint32_t Version = readNext<uint32_t>(Contents, Pos); 7609 outs() << " Version: " 7610 << format("0x%" PRIx32, Version) << '\n'; 7611 if (Version != 1) { 7612 outs() << " Skipping section with unknown version\n"; 7613 return; 7614 } 7615 7616 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 7617 outs() << " Common encodings array section offset: " 7618 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 7619 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 7620 outs() << " Number of common encodings in array: " 7621 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 7622 7623 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 7624 outs() << " Personality function array section offset: " 7625 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 7626 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 7627 outs() << " Number of personality functions in array: " 7628 << format("0x%" PRIx32, NumPersonalities) << '\n'; 7629 7630 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 7631 outs() << " Index array section offset: " 7632 << format("0x%" PRIx32, IndicesStart) << '\n'; 7633 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 7634 outs() << " Number of indices in array: " 7635 << format("0x%" PRIx32, NumIndices) << '\n'; 7636 7637 //===---------------------------------- 7638 // A shared list of common encodings 7639 //===---------------------------------- 7640 7641 // These occupy indices in the range [0, N] whenever an encoding is referenced 7642 // from a compressed 2nd level index table. In practice the linker only 7643 // creates ~128 of these, so that indices are available to embed encodings in 7644 // the 2nd level index. 7645 7646 SmallVector<uint32_t, 64> CommonEncodings; 7647 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 7648 Pos = CommonEncodingsStart; 7649 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 7650 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 7651 CommonEncodings.push_back(Encoding); 7652 7653 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 7654 << '\n'; 7655 } 7656 7657 //===---------------------------------- 7658 // Personality functions used in this executable 7659 //===---------------------------------- 7660 7661 // There should be only a handful of these (one per source language, 7662 // roughly). Particularly since they only get 2 bits in the compact encoding. 7663 7664 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 7665 Pos = PersonalitiesStart; 7666 for (unsigned i = 0; i < NumPersonalities; ++i) { 7667 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 7668 outs() << " personality[" << i + 1 7669 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 7670 } 7671 7672 //===---------------------------------- 7673 // The level 1 index entries 7674 //===---------------------------------- 7675 7676 // These specify an approximate place to start searching for the more detailed 7677 // information, sorted by PC. 7678 7679 struct IndexEntry { 7680 uint32_t FunctionOffset; 7681 uint32_t SecondLevelPageStart; 7682 uint32_t LSDAStart; 7683 }; 7684 7685 SmallVector<IndexEntry, 4> IndexEntries; 7686 7687 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 7688 Pos = IndicesStart; 7689 for (unsigned i = 0; i < NumIndices; ++i) { 7690 IndexEntry Entry; 7691 7692 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 7693 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 7694 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 7695 IndexEntries.push_back(Entry); 7696 7697 outs() << " [" << i << "]: " 7698 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 7699 << ", " 7700 << "2nd level page offset=" 7701 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 7702 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 7703 } 7704 7705 //===---------------------------------- 7706 // Next come the LSDA tables 7707 //===---------------------------------- 7708 7709 // The LSDA layout is rather implicit: it's a contiguous array of entries from 7710 // the first top-level index's LSDAOffset to the last (sentinel). 7711 7712 outs() << " LSDA descriptors:\n"; 7713 Pos = IndexEntries[0].LSDAStart; 7714 const uint32_t LSDASize = 2 * sizeof(uint32_t); 7715 int NumLSDAs = 7716 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 7717 7718 for (int i = 0; i < NumLSDAs; ++i) { 7719 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 7720 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 7721 outs() << " [" << i << "]: " 7722 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7723 << ", " 7724 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 7725 } 7726 7727 //===---------------------------------- 7728 // Finally, the 2nd level indices 7729 //===---------------------------------- 7730 7731 // Generally these are 4K in size, and have 2 possible forms: 7732 // + Regular stores up to 511 entries with disparate encodings 7733 // + Compressed stores up to 1021 entries if few enough compact encoding 7734 // values are used. 7735 outs() << " Second level indices:\n"; 7736 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 7737 // The final sentinel top-level index has no associated 2nd level page 7738 if (IndexEntries[i].SecondLevelPageStart == 0) 7739 break; 7740 7741 outs() << " Second level index[" << i << "]: " 7742 << "offset in section=" 7743 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 7744 << ", " 7745 << "base function offset=" 7746 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 7747 7748 Pos = IndexEntries[i].SecondLevelPageStart; 7749 if (Pos + sizeof(uint32_t) > Contents.size()) { 7750 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 7751 continue; 7752 } 7753 7754 uint32_t Kind = 7755 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 7756 if (Kind == 2) 7757 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 7758 else if (Kind == 3) 7759 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 7760 IndexEntries[i].FunctionOffset, 7761 CommonEncodings); 7762 else 7763 outs() << " Skipping 2nd level page with unknown kind " << Kind 7764 << '\n'; 7765 } 7766 } 7767 7768 void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { 7769 std::map<uint64_t, SymbolRef> Symbols; 7770 for (const SymbolRef &SymRef : Obj->symbols()) { 7771 // Discard any undefined or absolute symbols. They're not going to take part 7772 // in the convenience lookup for unwind info and just take up resources. 7773 auto SectOrErr = SymRef.getSection(); 7774 if (!SectOrErr) { 7775 // TODO: Actually report errors helpfully. 7776 consumeError(SectOrErr.takeError()); 7777 continue; 7778 } 7779 section_iterator Section = *SectOrErr; 7780 if (Section == Obj->section_end()) 7781 continue; 7782 7783 uint64_t Addr = SymRef.getValue(); 7784 Symbols.insert(std::make_pair(Addr, SymRef)); 7785 } 7786 7787 for (const SectionRef &Section : Obj->sections()) { 7788 StringRef SectName; 7789 Section.getName(SectName); 7790 if (SectName == "__compact_unwind") 7791 printMachOCompactUnwindSection(Obj, Symbols, Section); 7792 else if (SectName == "__unwind_info") 7793 printMachOUnwindInfoSection(Obj, Symbols, Section); 7794 } 7795 } 7796 7797 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 7798 uint32_t cpusubtype, uint32_t filetype, 7799 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 7800 bool verbose) { 7801 outs() << "Mach header\n"; 7802 outs() << " magic cputype cpusubtype caps filetype ncmds " 7803 "sizeofcmds flags\n"; 7804 if (verbose) { 7805 if (magic == MachO::MH_MAGIC) 7806 outs() << " MH_MAGIC"; 7807 else if (magic == MachO::MH_MAGIC_64) 7808 outs() << "MH_MAGIC_64"; 7809 else 7810 outs() << format(" 0x%08" PRIx32, magic); 7811 switch (cputype) { 7812 case MachO::CPU_TYPE_I386: 7813 outs() << " I386"; 7814 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7815 case MachO::CPU_SUBTYPE_I386_ALL: 7816 outs() << " ALL"; 7817 break; 7818 default: 7819 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7820 break; 7821 } 7822 break; 7823 case MachO::CPU_TYPE_X86_64: 7824 outs() << " X86_64"; 7825 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7826 case MachO::CPU_SUBTYPE_X86_64_ALL: 7827 outs() << " ALL"; 7828 break; 7829 case MachO::CPU_SUBTYPE_X86_64_H: 7830 outs() << " Haswell"; 7831 break; 7832 default: 7833 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7834 break; 7835 } 7836 break; 7837 case MachO::CPU_TYPE_ARM: 7838 outs() << " ARM"; 7839 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7840 case MachO::CPU_SUBTYPE_ARM_ALL: 7841 outs() << " ALL"; 7842 break; 7843 case MachO::CPU_SUBTYPE_ARM_V4T: 7844 outs() << " V4T"; 7845 break; 7846 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 7847 outs() << " V5TEJ"; 7848 break; 7849 case MachO::CPU_SUBTYPE_ARM_XSCALE: 7850 outs() << " XSCALE"; 7851 break; 7852 case MachO::CPU_SUBTYPE_ARM_V6: 7853 outs() << " V6"; 7854 break; 7855 case MachO::CPU_SUBTYPE_ARM_V6M: 7856 outs() << " V6M"; 7857 break; 7858 case MachO::CPU_SUBTYPE_ARM_V7: 7859 outs() << " V7"; 7860 break; 7861 case MachO::CPU_SUBTYPE_ARM_V7EM: 7862 outs() << " V7EM"; 7863 break; 7864 case MachO::CPU_SUBTYPE_ARM_V7K: 7865 outs() << " V7K"; 7866 break; 7867 case MachO::CPU_SUBTYPE_ARM_V7M: 7868 outs() << " V7M"; 7869 break; 7870 case MachO::CPU_SUBTYPE_ARM_V7S: 7871 outs() << " V7S"; 7872 break; 7873 default: 7874 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7875 break; 7876 } 7877 break; 7878 case MachO::CPU_TYPE_ARM64: 7879 outs() << " ARM64"; 7880 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7881 case MachO::CPU_SUBTYPE_ARM64_ALL: 7882 outs() << " ALL"; 7883 break; 7884 default: 7885 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7886 break; 7887 } 7888 break; 7889 case MachO::CPU_TYPE_POWERPC: 7890 outs() << " PPC"; 7891 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7892 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7893 outs() << " ALL"; 7894 break; 7895 default: 7896 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7897 break; 7898 } 7899 break; 7900 case MachO::CPU_TYPE_POWERPC64: 7901 outs() << " PPC64"; 7902 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7903 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7904 outs() << " ALL"; 7905 break; 7906 default: 7907 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7908 break; 7909 } 7910 break; 7911 default: 7912 outs() << format(" %7d", cputype); 7913 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7914 break; 7915 } 7916 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 7917 outs() << " LIB64"; 7918 } else { 7919 outs() << format(" 0x%02" PRIx32, 7920 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 7921 } 7922 switch (filetype) { 7923 case MachO::MH_OBJECT: 7924 outs() << " OBJECT"; 7925 break; 7926 case MachO::MH_EXECUTE: 7927 outs() << " EXECUTE"; 7928 break; 7929 case MachO::MH_FVMLIB: 7930 outs() << " FVMLIB"; 7931 break; 7932 case MachO::MH_CORE: 7933 outs() << " CORE"; 7934 break; 7935 case MachO::MH_PRELOAD: 7936 outs() << " PRELOAD"; 7937 break; 7938 case MachO::MH_DYLIB: 7939 outs() << " DYLIB"; 7940 break; 7941 case MachO::MH_DYLIB_STUB: 7942 outs() << " DYLIB_STUB"; 7943 break; 7944 case MachO::MH_DYLINKER: 7945 outs() << " DYLINKER"; 7946 break; 7947 case MachO::MH_BUNDLE: 7948 outs() << " BUNDLE"; 7949 break; 7950 case MachO::MH_DSYM: 7951 outs() << " DSYM"; 7952 break; 7953 case MachO::MH_KEXT_BUNDLE: 7954 outs() << " KEXTBUNDLE"; 7955 break; 7956 default: 7957 outs() << format(" %10u", filetype); 7958 break; 7959 } 7960 outs() << format(" %5u", ncmds); 7961 outs() << format(" %10u", sizeofcmds); 7962 uint32_t f = flags; 7963 if (f & MachO::MH_NOUNDEFS) { 7964 outs() << " NOUNDEFS"; 7965 f &= ~MachO::MH_NOUNDEFS; 7966 } 7967 if (f & MachO::MH_INCRLINK) { 7968 outs() << " INCRLINK"; 7969 f &= ~MachO::MH_INCRLINK; 7970 } 7971 if (f & MachO::MH_DYLDLINK) { 7972 outs() << " DYLDLINK"; 7973 f &= ~MachO::MH_DYLDLINK; 7974 } 7975 if (f & MachO::MH_BINDATLOAD) { 7976 outs() << " BINDATLOAD"; 7977 f &= ~MachO::MH_BINDATLOAD; 7978 } 7979 if (f & MachO::MH_PREBOUND) { 7980 outs() << " PREBOUND"; 7981 f &= ~MachO::MH_PREBOUND; 7982 } 7983 if (f & MachO::MH_SPLIT_SEGS) { 7984 outs() << " SPLIT_SEGS"; 7985 f &= ~MachO::MH_SPLIT_SEGS; 7986 } 7987 if (f & MachO::MH_LAZY_INIT) { 7988 outs() << " LAZY_INIT"; 7989 f &= ~MachO::MH_LAZY_INIT; 7990 } 7991 if (f & MachO::MH_TWOLEVEL) { 7992 outs() << " TWOLEVEL"; 7993 f &= ~MachO::MH_TWOLEVEL; 7994 } 7995 if (f & MachO::MH_FORCE_FLAT) { 7996 outs() << " FORCE_FLAT"; 7997 f &= ~MachO::MH_FORCE_FLAT; 7998 } 7999 if (f & MachO::MH_NOMULTIDEFS) { 8000 outs() << " NOMULTIDEFS"; 8001 f &= ~MachO::MH_NOMULTIDEFS; 8002 } 8003 if (f & MachO::MH_NOFIXPREBINDING) { 8004 outs() << " NOFIXPREBINDING"; 8005 f &= ~MachO::MH_NOFIXPREBINDING; 8006 } 8007 if (f & MachO::MH_PREBINDABLE) { 8008 outs() << " PREBINDABLE"; 8009 f &= ~MachO::MH_PREBINDABLE; 8010 } 8011 if (f & MachO::MH_ALLMODSBOUND) { 8012 outs() << " ALLMODSBOUND"; 8013 f &= ~MachO::MH_ALLMODSBOUND; 8014 } 8015 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8016 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8017 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8018 } 8019 if (f & MachO::MH_CANONICAL) { 8020 outs() << " CANONICAL"; 8021 f &= ~MachO::MH_CANONICAL; 8022 } 8023 if (f & MachO::MH_WEAK_DEFINES) { 8024 outs() << " WEAK_DEFINES"; 8025 f &= ~MachO::MH_WEAK_DEFINES; 8026 } 8027 if (f & MachO::MH_BINDS_TO_WEAK) { 8028 outs() << " BINDS_TO_WEAK"; 8029 f &= ~MachO::MH_BINDS_TO_WEAK; 8030 } 8031 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8032 outs() << " ALLOW_STACK_EXECUTION"; 8033 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8034 } 8035 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8036 outs() << " DEAD_STRIPPABLE_DYLIB"; 8037 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8038 } 8039 if (f & MachO::MH_PIE) { 8040 outs() << " PIE"; 8041 f &= ~MachO::MH_PIE; 8042 } 8043 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8044 outs() << " NO_REEXPORTED_DYLIBS"; 8045 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8046 } 8047 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8048 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8049 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8050 } 8051 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8052 outs() << " MH_NO_HEAP_EXECUTION"; 8053 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8054 } 8055 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8056 outs() << " APP_EXTENSION_SAFE"; 8057 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8058 } 8059 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8060 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8061 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8062 } 8063 if (f != 0 || flags == 0) 8064 outs() << format(" 0x%08" PRIx32, f); 8065 } else { 8066 outs() << format(" 0x%08" PRIx32, magic); 8067 outs() << format(" %7d", cputype); 8068 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8069 outs() << format(" 0x%02" PRIx32, 8070 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8071 outs() << format(" %10u", filetype); 8072 outs() << format(" %5u", ncmds); 8073 outs() << format(" %10u", sizeofcmds); 8074 outs() << format(" 0x%08" PRIx32, flags); 8075 } 8076 outs() << "\n"; 8077 } 8078 8079 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8080 StringRef SegName, uint64_t vmaddr, 8081 uint64_t vmsize, uint64_t fileoff, 8082 uint64_t filesize, uint32_t maxprot, 8083 uint32_t initprot, uint32_t nsects, 8084 uint32_t flags, uint32_t object_size, 8085 bool verbose) { 8086 uint64_t expected_cmdsize; 8087 if (cmd == MachO::LC_SEGMENT) { 8088 outs() << " cmd LC_SEGMENT\n"; 8089 expected_cmdsize = nsects; 8090 expected_cmdsize *= sizeof(struct MachO::section); 8091 expected_cmdsize += sizeof(struct MachO::segment_command); 8092 } else { 8093 outs() << " cmd LC_SEGMENT_64\n"; 8094 expected_cmdsize = nsects; 8095 expected_cmdsize *= sizeof(struct MachO::section_64); 8096 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8097 } 8098 outs() << " cmdsize " << cmdsize; 8099 if (cmdsize != expected_cmdsize) 8100 outs() << " Inconsistent size\n"; 8101 else 8102 outs() << "\n"; 8103 outs() << " segname " << SegName << "\n"; 8104 if (cmd == MachO::LC_SEGMENT_64) { 8105 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8106 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8107 } else { 8108 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8109 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8110 } 8111 outs() << " fileoff " << fileoff; 8112 if (fileoff > object_size) 8113 outs() << " (past end of file)\n"; 8114 else 8115 outs() << "\n"; 8116 outs() << " filesize " << filesize; 8117 if (fileoff + filesize > object_size) 8118 outs() << " (past end of file)\n"; 8119 else 8120 outs() << "\n"; 8121 if (verbose) { 8122 if ((maxprot & 8123 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8124 MachO::VM_PROT_EXECUTE)) != 0) 8125 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8126 else { 8127 outs() << " maxprot "; 8128 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8129 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8130 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8131 } 8132 if ((initprot & 8133 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8134 MachO::VM_PROT_EXECUTE)) != 0) 8135 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8136 else { 8137 outs() << " initprot "; 8138 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8139 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8140 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8141 } 8142 } else { 8143 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8144 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8145 } 8146 outs() << " nsects " << nsects << "\n"; 8147 if (verbose) { 8148 outs() << " flags"; 8149 if (flags == 0) 8150 outs() << " (none)\n"; 8151 else { 8152 if (flags & MachO::SG_HIGHVM) { 8153 outs() << " HIGHVM"; 8154 flags &= ~MachO::SG_HIGHVM; 8155 } 8156 if (flags & MachO::SG_FVMLIB) { 8157 outs() << " FVMLIB"; 8158 flags &= ~MachO::SG_FVMLIB; 8159 } 8160 if (flags & MachO::SG_NORELOC) { 8161 outs() << " NORELOC"; 8162 flags &= ~MachO::SG_NORELOC; 8163 } 8164 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8165 outs() << " PROTECTED_VERSION_1"; 8166 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8167 } 8168 if (flags) 8169 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8170 else 8171 outs() << "\n"; 8172 } 8173 } else { 8174 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8175 } 8176 } 8177 8178 static void PrintSection(const char *sectname, const char *segname, 8179 uint64_t addr, uint64_t size, uint32_t offset, 8180 uint32_t align, uint32_t reloff, uint32_t nreloc, 8181 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8182 uint32_t cmd, const char *sg_segname, 8183 uint32_t filetype, uint32_t object_size, 8184 bool verbose) { 8185 outs() << "Section\n"; 8186 outs() << " sectname " << format("%.16s\n", sectname); 8187 outs() << " segname " << format("%.16s", segname); 8188 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8189 outs() << " (does not match segment)\n"; 8190 else 8191 outs() << "\n"; 8192 if (cmd == MachO::LC_SEGMENT_64) { 8193 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8194 outs() << " size " << format("0x%016" PRIx64, size); 8195 } else { 8196 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8197 outs() << " size " << format("0x%08" PRIx64, size); 8198 } 8199 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8200 outs() << " (past end of file)\n"; 8201 else 8202 outs() << "\n"; 8203 outs() << " offset " << offset; 8204 if (offset > object_size) 8205 outs() << " (past end of file)\n"; 8206 else 8207 outs() << "\n"; 8208 uint32_t align_shifted = 1 << align; 8209 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8210 outs() << " reloff " << reloff; 8211 if (reloff > object_size) 8212 outs() << " (past end of file)\n"; 8213 else 8214 outs() << "\n"; 8215 outs() << " nreloc " << nreloc; 8216 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8217 outs() << " (past end of file)\n"; 8218 else 8219 outs() << "\n"; 8220 uint32_t section_type = flags & MachO::SECTION_TYPE; 8221 if (verbose) { 8222 outs() << " type"; 8223 if (section_type == MachO::S_REGULAR) 8224 outs() << " S_REGULAR\n"; 8225 else if (section_type == MachO::S_ZEROFILL) 8226 outs() << " S_ZEROFILL\n"; 8227 else if (section_type == MachO::S_CSTRING_LITERALS) 8228 outs() << " S_CSTRING_LITERALS\n"; 8229 else if (section_type == MachO::S_4BYTE_LITERALS) 8230 outs() << " S_4BYTE_LITERALS\n"; 8231 else if (section_type == MachO::S_8BYTE_LITERALS) 8232 outs() << " S_8BYTE_LITERALS\n"; 8233 else if (section_type == MachO::S_16BYTE_LITERALS) 8234 outs() << " S_16BYTE_LITERALS\n"; 8235 else if (section_type == MachO::S_LITERAL_POINTERS) 8236 outs() << " S_LITERAL_POINTERS\n"; 8237 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8238 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8239 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8240 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8241 else if (section_type == MachO::S_SYMBOL_STUBS) 8242 outs() << " S_SYMBOL_STUBS\n"; 8243 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8244 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8245 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8246 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8247 else if (section_type == MachO::S_COALESCED) 8248 outs() << " S_COALESCED\n"; 8249 else if (section_type == MachO::S_INTERPOSING) 8250 outs() << " S_INTERPOSING\n"; 8251 else if (section_type == MachO::S_DTRACE_DOF) 8252 outs() << " S_DTRACE_DOF\n"; 8253 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8254 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8255 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8256 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8257 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8258 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8259 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8260 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8261 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8262 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8263 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8264 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8265 else 8266 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8267 outs() << "attributes"; 8268 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8269 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8270 outs() << " PURE_INSTRUCTIONS"; 8271 if (section_attributes & MachO::S_ATTR_NO_TOC) 8272 outs() << " NO_TOC"; 8273 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8274 outs() << " STRIP_STATIC_SYMS"; 8275 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8276 outs() << " NO_DEAD_STRIP"; 8277 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8278 outs() << " LIVE_SUPPORT"; 8279 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8280 outs() << " SELF_MODIFYING_CODE"; 8281 if (section_attributes & MachO::S_ATTR_DEBUG) 8282 outs() << " DEBUG"; 8283 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8284 outs() << " SOME_INSTRUCTIONS"; 8285 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8286 outs() << " EXT_RELOC"; 8287 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8288 outs() << " LOC_RELOC"; 8289 if (section_attributes == 0) 8290 outs() << " (none)"; 8291 outs() << "\n"; 8292 } else 8293 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8294 outs() << " reserved1 " << reserved1; 8295 if (section_type == MachO::S_SYMBOL_STUBS || 8296 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8297 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8298 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8299 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8300 outs() << " (index into indirect symbol table)\n"; 8301 else 8302 outs() << "\n"; 8303 outs() << " reserved2 " << reserved2; 8304 if (section_type == MachO::S_SYMBOL_STUBS) 8305 outs() << " (size of stubs)\n"; 8306 else 8307 outs() << "\n"; 8308 } 8309 8310 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8311 uint32_t object_size) { 8312 outs() << " cmd LC_SYMTAB\n"; 8313 outs() << " cmdsize " << st.cmdsize; 8314 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8315 outs() << " Incorrect size\n"; 8316 else 8317 outs() << "\n"; 8318 outs() << " symoff " << st.symoff; 8319 if (st.symoff > object_size) 8320 outs() << " (past end of file)\n"; 8321 else 8322 outs() << "\n"; 8323 outs() << " nsyms " << st.nsyms; 8324 uint64_t big_size; 8325 if (Is64Bit) { 8326 big_size = st.nsyms; 8327 big_size *= sizeof(struct MachO::nlist_64); 8328 big_size += st.symoff; 8329 if (big_size > object_size) 8330 outs() << " (past end of file)\n"; 8331 else 8332 outs() << "\n"; 8333 } else { 8334 big_size = st.nsyms; 8335 big_size *= sizeof(struct MachO::nlist); 8336 big_size += st.symoff; 8337 if (big_size > object_size) 8338 outs() << " (past end of file)\n"; 8339 else 8340 outs() << "\n"; 8341 } 8342 outs() << " stroff " << st.stroff; 8343 if (st.stroff > object_size) 8344 outs() << " (past end of file)\n"; 8345 else 8346 outs() << "\n"; 8347 outs() << " strsize " << st.strsize; 8348 big_size = st.stroff; 8349 big_size += st.strsize; 8350 if (big_size > object_size) 8351 outs() << " (past end of file)\n"; 8352 else 8353 outs() << "\n"; 8354 } 8355 8356 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8357 uint32_t nsyms, uint32_t object_size, 8358 bool Is64Bit) { 8359 outs() << " cmd LC_DYSYMTAB\n"; 8360 outs() << " cmdsize " << dyst.cmdsize; 8361 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8362 outs() << " Incorrect size\n"; 8363 else 8364 outs() << "\n"; 8365 outs() << " ilocalsym " << dyst.ilocalsym; 8366 if (dyst.ilocalsym > nsyms) 8367 outs() << " (greater than the number of symbols)\n"; 8368 else 8369 outs() << "\n"; 8370 outs() << " nlocalsym " << dyst.nlocalsym; 8371 uint64_t big_size; 8372 big_size = dyst.ilocalsym; 8373 big_size += dyst.nlocalsym; 8374 if (big_size > nsyms) 8375 outs() << " (past the end of the symbol table)\n"; 8376 else 8377 outs() << "\n"; 8378 outs() << " iextdefsym " << dyst.iextdefsym; 8379 if (dyst.iextdefsym > nsyms) 8380 outs() << " (greater than the number of symbols)\n"; 8381 else 8382 outs() << "\n"; 8383 outs() << " nextdefsym " << dyst.nextdefsym; 8384 big_size = dyst.iextdefsym; 8385 big_size += dyst.nextdefsym; 8386 if (big_size > nsyms) 8387 outs() << " (past the end of the symbol table)\n"; 8388 else 8389 outs() << "\n"; 8390 outs() << " iundefsym " << dyst.iundefsym; 8391 if (dyst.iundefsym > nsyms) 8392 outs() << " (greater than the number of symbols)\n"; 8393 else 8394 outs() << "\n"; 8395 outs() << " nundefsym " << dyst.nundefsym; 8396 big_size = dyst.iundefsym; 8397 big_size += dyst.nundefsym; 8398 if (big_size > nsyms) 8399 outs() << " (past the end of the symbol table)\n"; 8400 else 8401 outs() << "\n"; 8402 outs() << " tocoff " << dyst.tocoff; 8403 if (dyst.tocoff > object_size) 8404 outs() << " (past end of file)\n"; 8405 else 8406 outs() << "\n"; 8407 outs() << " ntoc " << dyst.ntoc; 8408 big_size = dyst.ntoc; 8409 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8410 big_size += dyst.tocoff; 8411 if (big_size > object_size) 8412 outs() << " (past end of file)\n"; 8413 else 8414 outs() << "\n"; 8415 outs() << " modtaboff " << dyst.modtaboff; 8416 if (dyst.modtaboff > object_size) 8417 outs() << " (past end of file)\n"; 8418 else 8419 outs() << "\n"; 8420 outs() << " nmodtab " << dyst.nmodtab; 8421 uint64_t modtabend; 8422 if (Is64Bit) { 8423 modtabend = dyst.nmodtab; 8424 modtabend *= sizeof(struct MachO::dylib_module_64); 8425 modtabend += dyst.modtaboff; 8426 } else { 8427 modtabend = dyst.nmodtab; 8428 modtabend *= sizeof(struct MachO::dylib_module); 8429 modtabend += dyst.modtaboff; 8430 } 8431 if (modtabend > object_size) 8432 outs() << " (past end of file)\n"; 8433 else 8434 outs() << "\n"; 8435 outs() << " extrefsymoff " << dyst.extrefsymoff; 8436 if (dyst.extrefsymoff > object_size) 8437 outs() << " (past end of file)\n"; 8438 else 8439 outs() << "\n"; 8440 outs() << " nextrefsyms " << dyst.nextrefsyms; 8441 big_size = dyst.nextrefsyms; 8442 big_size *= sizeof(struct MachO::dylib_reference); 8443 big_size += dyst.extrefsymoff; 8444 if (big_size > object_size) 8445 outs() << " (past end of file)\n"; 8446 else 8447 outs() << "\n"; 8448 outs() << " indirectsymoff " << dyst.indirectsymoff; 8449 if (dyst.indirectsymoff > object_size) 8450 outs() << " (past end of file)\n"; 8451 else 8452 outs() << "\n"; 8453 outs() << " nindirectsyms " << dyst.nindirectsyms; 8454 big_size = dyst.nindirectsyms; 8455 big_size *= sizeof(uint32_t); 8456 big_size += dyst.indirectsymoff; 8457 if (big_size > object_size) 8458 outs() << " (past end of file)\n"; 8459 else 8460 outs() << "\n"; 8461 outs() << " extreloff " << dyst.extreloff; 8462 if (dyst.extreloff > object_size) 8463 outs() << " (past end of file)\n"; 8464 else 8465 outs() << "\n"; 8466 outs() << " nextrel " << dyst.nextrel; 8467 big_size = dyst.nextrel; 8468 big_size *= sizeof(struct MachO::relocation_info); 8469 big_size += dyst.extreloff; 8470 if (big_size > object_size) 8471 outs() << " (past end of file)\n"; 8472 else 8473 outs() << "\n"; 8474 outs() << " locreloff " << dyst.locreloff; 8475 if (dyst.locreloff > object_size) 8476 outs() << " (past end of file)\n"; 8477 else 8478 outs() << "\n"; 8479 outs() << " nlocrel " << dyst.nlocrel; 8480 big_size = dyst.nlocrel; 8481 big_size *= sizeof(struct MachO::relocation_info); 8482 big_size += dyst.locreloff; 8483 if (big_size > object_size) 8484 outs() << " (past end of file)\n"; 8485 else 8486 outs() << "\n"; 8487 } 8488 8489 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8490 uint32_t object_size) { 8491 if (dc.cmd == MachO::LC_DYLD_INFO) 8492 outs() << " cmd LC_DYLD_INFO\n"; 8493 else 8494 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8495 outs() << " cmdsize " << dc.cmdsize; 8496 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8497 outs() << " Incorrect size\n"; 8498 else 8499 outs() << "\n"; 8500 outs() << " rebase_off " << dc.rebase_off; 8501 if (dc.rebase_off > object_size) 8502 outs() << " (past end of file)\n"; 8503 else 8504 outs() << "\n"; 8505 outs() << " rebase_size " << dc.rebase_size; 8506 uint64_t big_size; 8507 big_size = dc.rebase_off; 8508 big_size += dc.rebase_size; 8509 if (big_size > object_size) 8510 outs() << " (past end of file)\n"; 8511 else 8512 outs() << "\n"; 8513 outs() << " bind_off " << dc.bind_off; 8514 if (dc.bind_off > object_size) 8515 outs() << " (past end of file)\n"; 8516 else 8517 outs() << "\n"; 8518 outs() << " bind_size " << dc.bind_size; 8519 big_size = dc.bind_off; 8520 big_size += dc.bind_size; 8521 if (big_size > object_size) 8522 outs() << " (past end of file)\n"; 8523 else 8524 outs() << "\n"; 8525 outs() << " weak_bind_off " << dc.weak_bind_off; 8526 if (dc.weak_bind_off > object_size) 8527 outs() << " (past end of file)\n"; 8528 else 8529 outs() << "\n"; 8530 outs() << " weak_bind_size " << dc.weak_bind_size; 8531 big_size = dc.weak_bind_off; 8532 big_size += dc.weak_bind_size; 8533 if (big_size > object_size) 8534 outs() << " (past end of file)\n"; 8535 else 8536 outs() << "\n"; 8537 outs() << " lazy_bind_off " << dc.lazy_bind_off; 8538 if (dc.lazy_bind_off > object_size) 8539 outs() << " (past end of file)\n"; 8540 else 8541 outs() << "\n"; 8542 outs() << " lazy_bind_size " << dc.lazy_bind_size; 8543 big_size = dc.lazy_bind_off; 8544 big_size += dc.lazy_bind_size; 8545 if (big_size > object_size) 8546 outs() << " (past end of file)\n"; 8547 else 8548 outs() << "\n"; 8549 outs() << " export_off " << dc.export_off; 8550 if (dc.export_off > object_size) 8551 outs() << " (past end of file)\n"; 8552 else 8553 outs() << "\n"; 8554 outs() << " export_size " << dc.export_size; 8555 big_size = dc.export_off; 8556 big_size += dc.export_size; 8557 if (big_size > object_size) 8558 outs() << " (past end of file)\n"; 8559 else 8560 outs() << "\n"; 8561 } 8562 8563 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 8564 const char *Ptr) { 8565 if (dyld.cmd == MachO::LC_ID_DYLINKER) 8566 outs() << " cmd LC_ID_DYLINKER\n"; 8567 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 8568 outs() << " cmd LC_LOAD_DYLINKER\n"; 8569 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 8570 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 8571 else 8572 outs() << " cmd ?(" << dyld.cmd << ")\n"; 8573 outs() << " cmdsize " << dyld.cmdsize; 8574 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 8575 outs() << " Incorrect size\n"; 8576 else 8577 outs() << "\n"; 8578 if (dyld.name >= dyld.cmdsize) 8579 outs() << " name ?(bad offset " << dyld.name << ")\n"; 8580 else { 8581 const char *P = (const char *)(Ptr) + dyld.name; 8582 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 8583 } 8584 } 8585 8586 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 8587 outs() << " cmd LC_UUID\n"; 8588 outs() << " cmdsize " << uuid.cmdsize; 8589 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 8590 outs() << " Incorrect size\n"; 8591 else 8592 outs() << "\n"; 8593 outs() << " uuid "; 8594 for (int i = 0; i < 16; ++i) { 8595 outs() << format("%02" PRIX32, uuid.uuid[i]); 8596 if (i == 3 || i == 5 || i == 7 || i == 9) 8597 outs() << "-"; 8598 } 8599 outs() << "\n"; 8600 } 8601 8602 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 8603 outs() << " cmd LC_RPATH\n"; 8604 outs() << " cmdsize " << rpath.cmdsize; 8605 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 8606 outs() << " Incorrect size\n"; 8607 else 8608 outs() << "\n"; 8609 if (rpath.path >= rpath.cmdsize) 8610 outs() << " path ?(bad offset " << rpath.path << ")\n"; 8611 else { 8612 const char *P = (const char *)(Ptr) + rpath.path; 8613 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 8614 } 8615 } 8616 8617 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 8618 StringRef LoadCmdName; 8619 switch (vd.cmd) { 8620 case MachO::LC_VERSION_MIN_MACOSX: 8621 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 8622 break; 8623 case MachO::LC_VERSION_MIN_IPHONEOS: 8624 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 8625 break; 8626 case MachO::LC_VERSION_MIN_TVOS: 8627 LoadCmdName = "LC_VERSION_MIN_TVOS"; 8628 break; 8629 case MachO::LC_VERSION_MIN_WATCHOS: 8630 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 8631 break; 8632 default: 8633 llvm_unreachable("Unknown version min load command"); 8634 } 8635 8636 outs() << " cmd " << LoadCmdName << '\n'; 8637 outs() << " cmdsize " << vd.cmdsize; 8638 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 8639 outs() << " Incorrect size\n"; 8640 else 8641 outs() << "\n"; 8642 outs() << " version " 8643 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 8644 << MachOObjectFile::getVersionMinMinor(vd, false); 8645 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 8646 if (Update != 0) 8647 outs() << "." << Update; 8648 outs() << "\n"; 8649 if (vd.sdk == 0) 8650 outs() << " sdk n/a"; 8651 else { 8652 outs() << " sdk " 8653 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 8654 << MachOObjectFile::getVersionMinMinor(vd, true); 8655 } 8656 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 8657 if (Update != 0) 8658 outs() << "." << Update; 8659 outs() << "\n"; 8660 } 8661 8662 static void PrintNoteLoadCommand(MachO::note_command Nt) { 8663 outs() << " cmd LC_NOTE\n"; 8664 outs() << " cmdsize " << Nt.cmdsize; 8665 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 8666 outs() << " Incorrect size\n"; 8667 else 8668 outs() << "\n"; 8669 const char *d = Nt.data_owner; 8670 outs() << "data_owner " << format("%.16s\n", d); 8671 outs() << " offset " << Nt.offset << "\n"; 8672 outs() << " size " << Nt.size << "\n"; 8673 } 8674 8675 static void PrintBuildToolVersion(MachO::build_tool_version bv) { 8676 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; 8677 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 8678 << "\n"; 8679 } 8680 8681 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 8682 MachO::build_version_command bd) { 8683 outs() << " cmd LC_BUILD_VERSION\n"; 8684 outs() << " cmdsize " << bd.cmdsize; 8685 if (bd.cmdsize != 8686 sizeof(struct MachO::build_version_command) + 8687 bd.ntools * sizeof(struct MachO::build_tool_version)) 8688 outs() << " Incorrect size\n"; 8689 else 8690 outs() << "\n"; 8691 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) 8692 << "\n"; 8693 if (bd.sdk) 8694 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 8695 << "\n"; 8696 else 8697 outs() << " sdk n/a\n"; 8698 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 8699 << "\n"; 8700 outs() << " ntools " << bd.ntools << "\n"; 8701 for (unsigned i = 0; i < bd.ntools; ++i) { 8702 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 8703 PrintBuildToolVersion(bv); 8704 } 8705 } 8706 8707 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 8708 outs() << " cmd LC_SOURCE_VERSION\n"; 8709 outs() << " cmdsize " << sd.cmdsize; 8710 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 8711 outs() << " Incorrect size\n"; 8712 else 8713 outs() << "\n"; 8714 uint64_t a = (sd.version >> 40) & 0xffffff; 8715 uint64_t b = (sd.version >> 30) & 0x3ff; 8716 uint64_t c = (sd.version >> 20) & 0x3ff; 8717 uint64_t d = (sd.version >> 10) & 0x3ff; 8718 uint64_t e = sd.version & 0x3ff; 8719 outs() << " version " << a << "." << b; 8720 if (e != 0) 8721 outs() << "." << c << "." << d << "." << e; 8722 else if (d != 0) 8723 outs() << "." << c << "." << d; 8724 else if (c != 0) 8725 outs() << "." << c; 8726 outs() << "\n"; 8727 } 8728 8729 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 8730 outs() << " cmd LC_MAIN\n"; 8731 outs() << " cmdsize " << ep.cmdsize; 8732 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 8733 outs() << " Incorrect size\n"; 8734 else 8735 outs() << "\n"; 8736 outs() << " entryoff " << ep.entryoff << "\n"; 8737 outs() << " stacksize " << ep.stacksize << "\n"; 8738 } 8739 8740 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 8741 uint32_t object_size) { 8742 outs() << " cmd LC_ENCRYPTION_INFO\n"; 8743 outs() << " cmdsize " << ec.cmdsize; 8744 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 8745 outs() << " Incorrect size\n"; 8746 else 8747 outs() << "\n"; 8748 outs() << " cryptoff " << ec.cryptoff; 8749 if (ec.cryptoff > object_size) 8750 outs() << " (past end of file)\n"; 8751 else 8752 outs() << "\n"; 8753 outs() << " cryptsize " << ec.cryptsize; 8754 if (ec.cryptsize > object_size) 8755 outs() << " (past end of file)\n"; 8756 else 8757 outs() << "\n"; 8758 outs() << " cryptid " << ec.cryptid << "\n"; 8759 } 8760 8761 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 8762 uint32_t object_size) { 8763 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 8764 outs() << " cmdsize " << ec.cmdsize; 8765 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 8766 outs() << " Incorrect size\n"; 8767 else 8768 outs() << "\n"; 8769 outs() << " cryptoff " << ec.cryptoff; 8770 if (ec.cryptoff > object_size) 8771 outs() << " (past end of file)\n"; 8772 else 8773 outs() << "\n"; 8774 outs() << " cryptsize " << ec.cryptsize; 8775 if (ec.cryptsize > object_size) 8776 outs() << " (past end of file)\n"; 8777 else 8778 outs() << "\n"; 8779 outs() << " cryptid " << ec.cryptid << "\n"; 8780 outs() << " pad " << ec.pad << "\n"; 8781 } 8782 8783 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 8784 const char *Ptr) { 8785 outs() << " cmd LC_LINKER_OPTION\n"; 8786 outs() << " cmdsize " << lo.cmdsize; 8787 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 8788 outs() << " Incorrect size\n"; 8789 else 8790 outs() << "\n"; 8791 outs() << " count " << lo.count << "\n"; 8792 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 8793 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 8794 uint32_t i = 0; 8795 while (left > 0) { 8796 while (*string == '\0' && left > 0) { 8797 string++; 8798 left--; 8799 } 8800 if (left > 0) { 8801 i++; 8802 outs() << " string #" << i << " " << format("%.*s\n", left, string); 8803 uint32_t NullPos = StringRef(string, left).find('\0'); 8804 uint32_t len = std::min(NullPos, left) + 1; 8805 string += len; 8806 left -= len; 8807 } 8808 } 8809 if (lo.count != i) 8810 outs() << " count " << lo.count << " does not match number of strings " 8811 << i << "\n"; 8812 } 8813 8814 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 8815 const char *Ptr) { 8816 outs() << " cmd LC_SUB_FRAMEWORK\n"; 8817 outs() << " cmdsize " << sub.cmdsize; 8818 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 8819 outs() << " Incorrect size\n"; 8820 else 8821 outs() << "\n"; 8822 if (sub.umbrella < sub.cmdsize) { 8823 const char *P = Ptr + sub.umbrella; 8824 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 8825 } else { 8826 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 8827 } 8828 } 8829 8830 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 8831 const char *Ptr) { 8832 outs() << " cmd LC_SUB_UMBRELLA\n"; 8833 outs() << " cmdsize " << sub.cmdsize; 8834 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 8835 outs() << " Incorrect size\n"; 8836 else 8837 outs() << "\n"; 8838 if (sub.sub_umbrella < sub.cmdsize) { 8839 const char *P = Ptr + sub.sub_umbrella; 8840 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 8841 } else { 8842 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 8843 } 8844 } 8845 8846 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 8847 const char *Ptr) { 8848 outs() << " cmd LC_SUB_LIBRARY\n"; 8849 outs() << " cmdsize " << sub.cmdsize; 8850 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 8851 outs() << " Incorrect size\n"; 8852 else 8853 outs() << "\n"; 8854 if (sub.sub_library < sub.cmdsize) { 8855 const char *P = Ptr + sub.sub_library; 8856 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 8857 } else { 8858 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 8859 } 8860 } 8861 8862 static void PrintSubClientCommand(MachO::sub_client_command sub, 8863 const char *Ptr) { 8864 outs() << " cmd LC_SUB_CLIENT\n"; 8865 outs() << " cmdsize " << sub.cmdsize; 8866 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 8867 outs() << " Incorrect size\n"; 8868 else 8869 outs() << "\n"; 8870 if (sub.client < sub.cmdsize) { 8871 const char *P = Ptr + sub.client; 8872 outs() << " client " << P << " (offset " << sub.client << ")\n"; 8873 } else { 8874 outs() << " client ?(bad offset " << sub.client << ")\n"; 8875 } 8876 } 8877 8878 static void PrintRoutinesCommand(MachO::routines_command r) { 8879 outs() << " cmd LC_ROUTINES\n"; 8880 outs() << " cmdsize " << r.cmdsize; 8881 if (r.cmdsize != sizeof(struct MachO::routines_command)) 8882 outs() << " Incorrect size\n"; 8883 else 8884 outs() << "\n"; 8885 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 8886 outs() << " init_module " << r.init_module << "\n"; 8887 outs() << " reserved1 " << r.reserved1 << "\n"; 8888 outs() << " reserved2 " << r.reserved2 << "\n"; 8889 outs() << " reserved3 " << r.reserved3 << "\n"; 8890 outs() << " reserved4 " << r.reserved4 << "\n"; 8891 outs() << " reserved5 " << r.reserved5 << "\n"; 8892 outs() << " reserved6 " << r.reserved6 << "\n"; 8893 } 8894 8895 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 8896 outs() << " cmd LC_ROUTINES_64\n"; 8897 outs() << " cmdsize " << r.cmdsize; 8898 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 8899 outs() << " Incorrect size\n"; 8900 else 8901 outs() << "\n"; 8902 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 8903 outs() << " init_module " << r.init_module << "\n"; 8904 outs() << " reserved1 " << r.reserved1 << "\n"; 8905 outs() << " reserved2 " << r.reserved2 << "\n"; 8906 outs() << " reserved3 " << r.reserved3 << "\n"; 8907 outs() << " reserved4 " << r.reserved4 << "\n"; 8908 outs() << " reserved5 " << r.reserved5 << "\n"; 8909 outs() << " reserved6 " << r.reserved6 << "\n"; 8910 } 8911 8912 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 8913 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 8914 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 8915 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 8916 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 8917 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 8918 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 8919 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 8920 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 8921 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 8922 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 8923 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 8924 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 8925 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 8926 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 8927 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 8928 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 8929 } 8930 8931 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 8932 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 8933 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 8934 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 8935 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 8936 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 8937 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 8938 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 8939 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 8940 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 8941 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 8942 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 8943 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 8944 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 8945 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 8946 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 8947 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 8948 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 8949 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 8950 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 8951 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 8952 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 8953 } 8954 8955 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 8956 uint32_t f; 8957 outs() << "\t mmst_reg "; 8958 for (f = 0; f < 10; f++) 8959 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 8960 outs() << "\n"; 8961 outs() << "\t mmst_rsrv "; 8962 for (f = 0; f < 6; f++) 8963 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 8964 outs() << "\n"; 8965 } 8966 8967 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 8968 uint32_t f; 8969 outs() << "\t xmm_reg "; 8970 for (f = 0; f < 16; f++) 8971 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 8972 outs() << "\n"; 8973 } 8974 8975 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 8976 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 8977 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 8978 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 8979 outs() << " denorm " << fpu.fpu_fcw.denorm; 8980 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 8981 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 8982 outs() << " undfl " << fpu.fpu_fcw.undfl; 8983 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 8984 outs() << "\t\t pc "; 8985 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 8986 outs() << "FP_PREC_24B "; 8987 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 8988 outs() << "FP_PREC_53B "; 8989 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 8990 outs() << "FP_PREC_64B "; 8991 else 8992 outs() << fpu.fpu_fcw.pc << " "; 8993 outs() << "rc "; 8994 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 8995 outs() << "FP_RND_NEAR "; 8996 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 8997 outs() << "FP_RND_DOWN "; 8998 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 8999 outs() << "FP_RND_UP "; 9000 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 9001 outs() << "FP_CHOP "; 9002 outs() << "\n"; 9003 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 9004 outs() << " denorm " << fpu.fpu_fsw.denorm; 9005 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 9006 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 9007 outs() << " undfl " << fpu.fpu_fsw.undfl; 9008 outs() << " precis " << fpu.fpu_fsw.precis; 9009 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 9010 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9011 outs() << " c0 " << fpu.fpu_fsw.c0; 9012 outs() << " c1 " << fpu.fpu_fsw.c1; 9013 outs() << " c2 " << fpu.fpu_fsw.c2; 9014 outs() << " tos " << fpu.fpu_fsw.tos; 9015 outs() << " c3 " << fpu.fpu_fsw.c3; 9016 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9017 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9018 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9019 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9020 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9021 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9022 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9023 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9024 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9025 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9026 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9027 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9028 outs() << "\n"; 9029 outs() << "\t fpu_stmm0:\n"; 9030 Print_mmst_reg(fpu.fpu_stmm0); 9031 outs() << "\t fpu_stmm1:\n"; 9032 Print_mmst_reg(fpu.fpu_stmm1); 9033 outs() << "\t fpu_stmm2:\n"; 9034 Print_mmst_reg(fpu.fpu_stmm2); 9035 outs() << "\t fpu_stmm3:\n"; 9036 Print_mmst_reg(fpu.fpu_stmm3); 9037 outs() << "\t fpu_stmm4:\n"; 9038 Print_mmst_reg(fpu.fpu_stmm4); 9039 outs() << "\t fpu_stmm5:\n"; 9040 Print_mmst_reg(fpu.fpu_stmm5); 9041 outs() << "\t fpu_stmm6:\n"; 9042 Print_mmst_reg(fpu.fpu_stmm6); 9043 outs() << "\t fpu_stmm7:\n"; 9044 Print_mmst_reg(fpu.fpu_stmm7); 9045 outs() << "\t fpu_xmm0:\n"; 9046 Print_xmm_reg(fpu.fpu_xmm0); 9047 outs() << "\t fpu_xmm1:\n"; 9048 Print_xmm_reg(fpu.fpu_xmm1); 9049 outs() << "\t fpu_xmm2:\n"; 9050 Print_xmm_reg(fpu.fpu_xmm2); 9051 outs() << "\t fpu_xmm3:\n"; 9052 Print_xmm_reg(fpu.fpu_xmm3); 9053 outs() << "\t fpu_xmm4:\n"; 9054 Print_xmm_reg(fpu.fpu_xmm4); 9055 outs() << "\t fpu_xmm5:\n"; 9056 Print_xmm_reg(fpu.fpu_xmm5); 9057 outs() << "\t fpu_xmm6:\n"; 9058 Print_xmm_reg(fpu.fpu_xmm6); 9059 outs() << "\t fpu_xmm7:\n"; 9060 Print_xmm_reg(fpu.fpu_xmm7); 9061 outs() << "\t fpu_xmm8:\n"; 9062 Print_xmm_reg(fpu.fpu_xmm8); 9063 outs() << "\t fpu_xmm9:\n"; 9064 Print_xmm_reg(fpu.fpu_xmm9); 9065 outs() << "\t fpu_xmm10:\n"; 9066 Print_xmm_reg(fpu.fpu_xmm10); 9067 outs() << "\t fpu_xmm11:\n"; 9068 Print_xmm_reg(fpu.fpu_xmm11); 9069 outs() << "\t fpu_xmm12:\n"; 9070 Print_xmm_reg(fpu.fpu_xmm12); 9071 outs() << "\t fpu_xmm13:\n"; 9072 Print_xmm_reg(fpu.fpu_xmm13); 9073 outs() << "\t fpu_xmm14:\n"; 9074 Print_xmm_reg(fpu.fpu_xmm14); 9075 outs() << "\t fpu_xmm15:\n"; 9076 Print_xmm_reg(fpu.fpu_xmm15); 9077 outs() << "\t fpu_rsrv4:\n"; 9078 for (uint32_t f = 0; f < 6; f++) { 9079 outs() << "\t "; 9080 for (uint32_t g = 0; g < 16; g++) 9081 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9082 outs() << "\n"; 9083 } 9084 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9085 outs() << "\n"; 9086 } 9087 9088 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9089 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9090 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9091 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9092 } 9093 9094 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9095 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9096 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9097 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9098 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9099 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9100 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9101 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9102 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9103 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9104 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9105 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9106 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9107 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9108 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9109 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9110 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9111 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9112 } 9113 9114 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9115 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9116 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9117 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9118 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9119 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9120 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9121 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9122 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9123 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9124 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9125 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9126 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9127 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9128 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9129 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9130 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9131 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9132 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9133 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9134 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9135 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9136 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9137 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9138 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9139 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9140 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9141 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9142 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9143 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9144 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9145 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9146 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9147 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9148 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9149 } 9150 9151 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9152 bool isLittleEndian, uint32_t cputype) { 9153 if (t.cmd == MachO::LC_THREAD) 9154 outs() << " cmd LC_THREAD\n"; 9155 else if (t.cmd == MachO::LC_UNIXTHREAD) 9156 outs() << " cmd LC_UNIXTHREAD\n"; 9157 else 9158 outs() << " cmd " << t.cmd << " (unknown)\n"; 9159 outs() << " cmdsize " << t.cmdsize; 9160 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9161 outs() << " Incorrect size\n"; 9162 else 9163 outs() << "\n"; 9164 9165 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9166 const char *end = Ptr + t.cmdsize; 9167 uint32_t flavor, count, left; 9168 if (cputype == MachO::CPU_TYPE_I386) { 9169 while (begin < end) { 9170 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9171 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9172 begin += sizeof(uint32_t); 9173 } else { 9174 flavor = 0; 9175 begin = end; 9176 } 9177 if (isLittleEndian != sys::IsLittleEndianHost) 9178 sys::swapByteOrder(flavor); 9179 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9180 memcpy((char *)&count, begin, sizeof(uint32_t)); 9181 begin += sizeof(uint32_t); 9182 } else { 9183 count = 0; 9184 begin = end; 9185 } 9186 if (isLittleEndian != sys::IsLittleEndianHost) 9187 sys::swapByteOrder(count); 9188 if (flavor == MachO::x86_THREAD_STATE32) { 9189 outs() << " flavor i386_THREAD_STATE\n"; 9190 if (count == MachO::x86_THREAD_STATE32_COUNT) 9191 outs() << " count i386_THREAD_STATE_COUNT\n"; 9192 else 9193 outs() << " count " << count 9194 << " (not x86_THREAD_STATE32_COUNT)\n"; 9195 MachO::x86_thread_state32_t cpu32; 9196 left = end - begin; 9197 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9198 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9199 begin += sizeof(MachO::x86_thread_state32_t); 9200 } else { 9201 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9202 memcpy(&cpu32, begin, left); 9203 begin += left; 9204 } 9205 if (isLittleEndian != sys::IsLittleEndianHost) 9206 swapStruct(cpu32); 9207 Print_x86_thread_state32_t(cpu32); 9208 } else if (flavor == MachO::x86_THREAD_STATE) { 9209 outs() << " flavor x86_THREAD_STATE\n"; 9210 if (count == MachO::x86_THREAD_STATE_COUNT) 9211 outs() << " count x86_THREAD_STATE_COUNT\n"; 9212 else 9213 outs() << " count " << count 9214 << " (not x86_THREAD_STATE_COUNT)\n"; 9215 struct MachO::x86_thread_state_t ts; 9216 left = end - begin; 9217 if (left >= sizeof(MachO::x86_thread_state_t)) { 9218 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9219 begin += sizeof(MachO::x86_thread_state_t); 9220 } else { 9221 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9222 memcpy(&ts, begin, left); 9223 begin += left; 9224 } 9225 if (isLittleEndian != sys::IsLittleEndianHost) 9226 swapStruct(ts); 9227 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9228 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9229 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9230 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9231 else 9232 outs() << "tsh.count " << ts.tsh.count 9233 << " (not x86_THREAD_STATE32_COUNT\n"; 9234 Print_x86_thread_state32_t(ts.uts.ts32); 9235 } else { 9236 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9237 << ts.tsh.count << "\n"; 9238 } 9239 } else { 9240 outs() << " flavor " << flavor << " (unknown)\n"; 9241 outs() << " count " << count << "\n"; 9242 outs() << " state (unknown)\n"; 9243 begin += count * sizeof(uint32_t); 9244 } 9245 } 9246 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9247 while (begin < end) { 9248 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9249 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9250 begin += sizeof(uint32_t); 9251 } else { 9252 flavor = 0; 9253 begin = end; 9254 } 9255 if (isLittleEndian != sys::IsLittleEndianHost) 9256 sys::swapByteOrder(flavor); 9257 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9258 memcpy((char *)&count, begin, sizeof(uint32_t)); 9259 begin += sizeof(uint32_t); 9260 } else { 9261 count = 0; 9262 begin = end; 9263 } 9264 if (isLittleEndian != sys::IsLittleEndianHost) 9265 sys::swapByteOrder(count); 9266 if (flavor == MachO::x86_THREAD_STATE64) { 9267 outs() << " flavor x86_THREAD_STATE64\n"; 9268 if (count == MachO::x86_THREAD_STATE64_COUNT) 9269 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9270 else 9271 outs() << " count " << count 9272 << " (not x86_THREAD_STATE64_COUNT)\n"; 9273 MachO::x86_thread_state64_t cpu64; 9274 left = end - begin; 9275 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9276 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9277 begin += sizeof(MachO::x86_thread_state64_t); 9278 } else { 9279 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9280 memcpy(&cpu64, begin, left); 9281 begin += left; 9282 } 9283 if (isLittleEndian != sys::IsLittleEndianHost) 9284 swapStruct(cpu64); 9285 Print_x86_thread_state64_t(cpu64); 9286 } else if (flavor == MachO::x86_THREAD_STATE) { 9287 outs() << " flavor x86_THREAD_STATE\n"; 9288 if (count == MachO::x86_THREAD_STATE_COUNT) 9289 outs() << " count x86_THREAD_STATE_COUNT\n"; 9290 else 9291 outs() << " count " << count 9292 << " (not x86_THREAD_STATE_COUNT)\n"; 9293 struct MachO::x86_thread_state_t ts; 9294 left = end - begin; 9295 if (left >= sizeof(MachO::x86_thread_state_t)) { 9296 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9297 begin += sizeof(MachO::x86_thread_state_t); 9298 } else { 9299 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9300 memcpy(&ts, begin, left); 9301 begin += left; 9302 } 9303 if (isLittleEndian != sys::IsLittleEndianHost) 9304 swapStruct(ts); 9305 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9306 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9307 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9308 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9309 else 9310 outs() << "tsh.count " << ts.tsh.count 9311 << " (not x86_THREAD_STATE64_COUNT\n"; 9312 Print_x86_thread_state64_t(ts.uts.ts64); 9313 } else { 9314 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9315 << ts.tsh.count << "\n"; 9316 } 9317 } else if (flavor == MachO::x86_FLOAT_STATE) { 9318 outs() << " flavor x86_FLOAT_STATE\n"; 9319 if (count == MachO::x86_FLOAT_STATE_COUNT) 9320 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9321 else 9322 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9323 struct MachO::x86_float_state_t fs; 9324 left = end - begin; 9325 if (left >= sizeof(MachO::x86_float_state_t)) { 9326 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9327 begin += sizeof(MachO::x86_float_state_t); 9328 } else { 9329 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9330 memcpy(&fs, begin, left); 9331 begin += left; 9332 } 9333 if (isLittleEndian != sys::IsLittleEndianHost) 9334 swapStruct(fs); 9335 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9336 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9337 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9338 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9339 else 9340 outs() << "fsh.count " << fs.fsh.count 9341 << " (not x86_FLOAT_STATE64_COUNT\n"; 9342 Print_x86_float_state_t(fs.ufs.fs64); 9343 } else { 9344 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9345 << fs.fsh.count << "\n"; 9346 } 9347 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9348 outs() << " flavor x86_EXCEPTION_STATE\n"; 9349 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9350 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9351 else 9352 outs() << " count " << count 9353 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9354 struct MachO::x86_exception_state_t es; 9355 left = end - begin; 9356 if (left >= sizeof(MachO::x86_exception_state_t)) { 9357 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9358 begin += sizeof(MachO::x86_exception_state_t); 9359 } else { 9360 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9361 memcpy(&es, begin, left); 9362 begin += left; 9363 } 9364 if (isLittleEndian != sys::IsLittleEndianHost) 9365 swapStruct(es); 9366 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9367 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9368 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9369 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9370 else 9371 outs() << "\t esh.count " << es.esh.count 9372 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9373 Print_x86_exception_state_t(es.ues.es64); 9374 } else { 9375 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9376 << es.esh.count << "\n"; 9377 } 9378 } else { 9379 outs() << " flavor " << flavor << " (unknown)\n"; 9380 outs() << " count " << count << "\n"; 9381 outs() << " state (unknown)\n"; 9382 begin += count * sizeof(uint32_t); 9383 } 9384 } 9385 } else if (cputype == MachO::CPU_TYPE_ARM) { 9386 while (begin < end) { 9387 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9388 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9389 begin += sizeof(uint32_t); 9390 } else { 9391 flavor = 0; 9392 begin = end; 9393 } 9394 if (isLittleEndian != sys::IsLittleEndianHost) 9395 sys::swapByteOrder(flavor); 9396 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9397 memcpy((char *)&count, begin, sizeof(uint32_t)); 9398 begin += sizeof(uint32_t); 9399 } else { 9400 count = 0; 9401 begin = end; 9402 } 9403 if (isLittleEndian != sys::IsLittleEndianHost) 9404 sys::swapByteOrder(count); 9405 if (flavor == MachO::ARM_THREAD_STATE) { 9406 outs() << " flavor ARM_THREAD_STATE\n"; 9407 if (count == MachO::ARM_THREAD_STATE_COUNT) 9408 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9409 else 9410 outs() << " count " << count 9411 << " (not ARM_THREAD_STATE_COUNT)\n"; 9412 MachO::arm_thread_state32_t cpu32; 9413 left = end - begin; 9414 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9415 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9416 begin += sizeof(MachO::arm_thread_state32_t); 9417 } else { 9418 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9419 memcpy(&cpu32, begin, left); 9420 begin += left; 9421 } 9422 if (isLittleEndian != sys::IsLittleEndianHost) 9423 swapStruct(cpu32); 9424 Print_arm_thread_state32_t(cpu32); 9425 } else { 9426 outs() << " flavor " << flavor << " (unknown)\n"; 9427 outs() << " count " << count << "\n"; 9428 outs() << " state (unknown)\n"; 9429 begin += count * sizeof(uint32_t); 9430 } 9431 } 9432 } else if (cputype == MachO::CPU_TYPE_ARM64) { 9433 while (begin < end) { 9434 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9435 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9436 begin += sizeof(uint32_t); 9437 } else { 9438 flavor = 0; 9439 begin = end; 9440 } 9441 if (isLittleEndian != sys::IsLittleEndianHost) 9442 sys::swapByteOrder(flavor); 9443 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9444 memcpy((char *)&count, begin, sizeof(uint32_t)); 9445 begin += sizeof(uint32_t); 9446 } else { 9447 count = 0; 9448 begin = end; 9449 } 9450 if (isLittleEndian != sys::IsLittleEndianHost) 9451 sys::swapByteOrder(count); 9452 if (flavor == MachO::ARM_THREAD_STATE64) { 9453 outs() << " flavor ARM_THREAD_STATE64\n"; 9454 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9455 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9456 else 9457 outs() << " count " << count 9458 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9459 MachO::arm_thread_state64_t cpu64; 9460 left = end - begin; 9461 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9462 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9463 begin += sizeof(MachO::arm_thread_state64_t); 9464 } else { 9465 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9466 memcpy(&cpu64, begin, left); 9467 begin += left; 9468 } 9469 if (isLittleEndian != sys::IsLittleEndianHost) 9470 swapStruct(cpu64); 9471 Print_arm_thread_state64_t(cpu64); 9472 } else { 9473 outs() << " flavor " << flavor << " (unknown)\n"; 9474 outs() << " count " << count << "\n"; 9475 outs() << " state (unknown)\n"; 9476 begin += count * sizeof(uint32_t); 9477 } 9478 } 9479 } else { 9480 while (begin < end) { 9481 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9482 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9483 begin += sizeof(uint32_t); 9484 } else { 9485 flavor = 0; 9486 begin = end; 9487 } 9488 if (isLittleEndian != sys::IsLittleEndianHost) 9489 sys::swapByteOrder(flavor); 9490 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9491 memcpy((char *)&count, begin, sizeof(uint32_t)); 9492 begin += sizeof(uint32_t); 9493 } else { 9494 count = 0; 9495 begin = end; 9496 } 9497 if (isLittleEndian != sys::IsLittleEndianHost) 9498 sys::swapByteOrder(count); 9499 outs() << " flavor " << flavor << "\n"; 9500 outs() << " count " << count << "\n"; 9501 outs() << " state (Unknown cputype/cpusubtype)\n"; 9502 begin += count * sizeof(uint32_t); 9503 } 9504 } 9505 } 9506 9507 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 9508 if (dl.cmd == MachO::LC_ID_DYLIB) 9509 outs() << " cmd LC_ID_DYLIB\n"; 9510 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 9511 outs() << " cmd LC_LOAD_DYLIB\n"; 9512 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 9513 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 9514 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 9515 outs() << " cmd LC_REEXPORT_DYLIB\n"; 9516 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 9517 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 9518 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 9519 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 9520 else 9521 outs() << " cmd " << dl.cmd << " (unknown)\n"; 9522 outs() << " cmdsize " << dl.cmdsize; 9523 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 9524 outs() << " Incorrect size\n"; 9525 else 9526 outs() << "\n"; 9527 if (dl.dylib.name < dl.cmdsize) { 9528 const char *P = (const char *)(Ptr) + dl.dylib.name; 9529 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 9530 } else { 9531 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 9532 } 9533 outs() << " time stamp " << dl.dylib.timestamp << " "; 9534 time_t t = dl.dylib.timestamp; 9535 outs() << ctime(&t); 9536 outs() << " current version "; 9537 if (dl.dylib.current_version == 0xffffffff) 9538 outs() << "n/a\n"; 9539 else 9540 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 9541 << ((dl.dylib.current_version >> 8) & 0xff) << "." 9542 << (dl.dylib.current_version & 0xff) << "\n"; 9543 outs() << "compatibility version "; 9544 if (dl.dylib.compatibility_version == 0xffffffff) 9545 outs() << "n/a\n"; 9546 else 9547 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 9548 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 9549 << (dl.dylib.compatibility_version & 0xff) << "\n"; 9550 } 9551 9552 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 9553 uint32_t object_size) { 9554 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 9555 outs() << " cmd LC_CODE_SIGNATURE\n"; 9556 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 9557 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 9558 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 9559 outs() << " cmd LC_FUNCTION_STARTS\n"; 9560 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 9561 outs() << " cmd LC_DATA_IN_CODE\n"; 9562 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 9563 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 9564 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 9565 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 9566 else 9567 outs() << " cmd " << ld.cmd << " (?)\n"; 9568 outs() << " cmdsize " << ld.cmdsize; 9569 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 9570 outs() << " Incorrect size\n"; 9571 else 9572 outs() << "\n"; 9573 outs() << " dataoff " << ld.dataoff; 9574 if (ld.dataoff > object_size) 9575 outs() << " (past end of file)\n"; 9576 else 9577 outs() << "\n"; 9578 outs() << " datasize " << ld.datasize; 9579 uint64_t big_size = ld.dataoff; 9580 big_size += ld.datasize; 9581 if (big_size > object_size) 9582 outs() << " (past end of file)\n"; 9583 else 9584 outs() << "\n"; 9585 } 9586 9587 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 9588 uint32_t cputype, bool verbose) { 9589 StringRef Buf = Obj->getData(); 9590 unsigned Index = 0; 9591 for (const auto &Command : Obj->load_commands()) { 9592 outs() << "Load command " << Index++ << "\n"; 9593 if (Command.C.cmd == MachO::LC_SEGMENT) { 9594 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 9595 const char *sg_segname = SLC.segname; 9596 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 9597 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 9598 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 9599 verbose); 9600 for (unsigned j = 0; j < SLC.nsects; j++) { 9601 MachO::section S = Obj->getSection(Command, j); 9602 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 9603 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 9604 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 9605 } 9606 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9607 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 9608 const char *sg_segname = SLC_64.segname; 9609 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 9610 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 9611 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 9612 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 9613 for (unsigned j = 0; j < SLC_64.nsects; j++) { 9614 MachO::section_64 S_64 = Obj->getSection64(Command, j); 9615 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 9616 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 9617 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 9618 sg_segname, filetype, Buf.size(), verbose); 9619 } 9620 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 9621 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9622 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 9623 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 9624 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 9625 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9626 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 9627 Obj->is64Bit()); 9628 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 9629 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 9630 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 9631 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 9632 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 9633 Command.C.cmd == MachO::LC_ID_DYLINKER || 9634 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 9635 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 9636 PrintDyldLoadCommand(Dyld, Command.Ptr); 9637 } else if (Command.C.cmd == MachO::LC_UUID) { 9638 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 9639 PrintUuidLoadCommand(Uuid); 9640 } else if (Command.C.cmd == MachO::LC_RPATH) { 9641 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 9642 PrintRpathLoadCommand(Rpath, Command.Ptr); 9643 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 9644 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 9645 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 9646 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 9647 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 9648 PrintVersionMinLoadCommand(Vd); 9649 } else if (Command.C.cmd == MachO::LC_NOTE) { 9650 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 9651 PrintNoteLoadCommand(Nt); 9652 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 9653 MachO::build_version_command Bv = 9654 Obj->getBuildVersionLoadCommand(Command); 9655 PrintBuildVersionLoadCommand(Obj, Bv); 9656 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 9657 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 9658 PrintSourceVersionCommand(Sd); 9659 } else if (Command.C.cmd == MachO::LC_MAIN) { 9660 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 9661 PrintEntryPointCommand(Ep); 9662 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 9663 MachO::encryption_info_command Ei = 9664 Obj->getEncryptionInfoCommand(Command); 9665 PrintEncryptionInfoCommand(Ei, Buf.size()); 9666 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 9667 MachO::encryption_info_command_64 Ei = 9668 Obj->getEncryptionInfoCommand64(Command); 9669 PrintEncryptionInfoCommand64(Ei, Buf.size()); 9670 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 9671 MachO::linker_option_command Lo = 9672 Obj->getLinkerOptionLoadCommand(Command); 9673 PrintLinkerOptionCommand(Lo, Command.Ptr); 9674 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 9675 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 9676 PrintSubFrameworkCommand(Sf, Command.Ptr); 9677 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 9678 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 9679 PrintSubUmbrellaCommand(Sf, Command.Ptr); 9680 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 9681 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 9682 PrintSubLibraryCommand(Sl, Command.Ptr); 9683 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 9684 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 9685 PrintSubClientCommand(Sc, Command.Ptr); 9686 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 9687 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 9688 PrintRoutinesCommand(Rc); 9689 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 9690 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 9691 PrintRoutinesCommand64(Rc); 9692 } else if (Command.C.cmd == MachO::LC_THREAD || 9693 Command.C.cmd == MachO::LC_UNIXTHREAD) { 9694 MachO::thread_command Tc = Obj->getThreadCommand(Command); 9695 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 9696 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 9697 Command.C.cmd == MachO::LC_ID_DYLIB || 9698 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 9699 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 9700 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 9701 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 9702 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 9703 PrintDylibCommand(Dl, Command.Ptr); 9704 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 9705 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 9706 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 9707 Command.C.cmd == MachO::LC_DATA_IN_CODE || 9708 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 9709 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 9710 MachO::linkedit_data_command Ld = 9711 Obj->getLinkeditDataLoadCommand(Command); 9712 PrintLinkEditDataCommand(Ld, Buf.size()); 9713 } else { 9714 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 9715 << ")\n"; 9716 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 9717 // TODO: get and print the raw bytes of the load command. 9718 } 9719 // TODO: print all the other kinds of load commands. 9720 } 9721 } 9722 9723 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 9724 if (Obj->is64Bit()) { 9725 MachO::mach_header_64 H_64; 9726 H_64 = Obj->getHeader64(); 9727 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 9728 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 9729 } else { 9730 MachO::mach_header H; 9731 H = Obj->getHeader(); 9732 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 9733 H.sizeofcmds, H.flags, verbose); 9734 } 9735 } 9736 9737 void llvm::printMachOFileHeader(const object::ObjectFile *Obj) { 9738 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9739 PrintMachHeader(file, !NonVerbose); 9740 } 9741 9742 void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) { 9743 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9744 uint32_t filetype = 0; 9745 uint32_t cputype = 0; 9746 if (file->is64Bit()) { 9747 MachO::mach_header_64 H_64; 9748 H_64 = file->getHeader64(); 9749 filetype = H_64.filetype; 9750 cputype = H_64.cputype; 9751 } else { 9752 MachO::mach_header H; 9753 H = file->getHeader(); 9754 filetype = H.filetype; 9755 cputype = H.cputype; 9756 } 9757 PrintLoadCommands(file, filetype, cputype, !NonVerbose); 9758 } 9759 9760 //===----------------------------------------------------------------------===// 9761 // export trie dumping 9762 //===----------------------------------------------------------------------===// 9763 9764 void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) { 9765 uint64_t BaseSegmentAddress = 0; 9766 for (const auto &Command : Obj->load_commands()) { 9767 if (Command.C.cmd == MachO::LC_SEGMENT) { 9768 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 9769 if (Seg.fileoff == 0 && Seg.filesize != 0) { 9770 BaseSegmentAddress = Seg.vmaddr; 9771 break; 9772 } 9773 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9774 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 9775 if (Seg.fileoff == 0 && Seg.filesize != 0) { 9776 BaseSegmentAddress = Seg.vmaddr; 9777 break; 9778 } 9779 } 9780 } 9781 Error Err = Error::success(); 9782 for (const llvm::object::ExportEntry &Entry : Obj->exports(Err)) { 9783 uint64_t Flags = Entry.flags(); 9784 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 9785 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 9786 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9787 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 9788 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9789 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 9790 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 9791 if (ReExport) 9792 outs() << "[re-export] "; 9793 else 9794 outs() << format("0x%08llX ", 9795 Entry.address() + BaseSegmentAddress); 9796 outs() << Entry.name(); 9797 if (WeakDef || ThreadLocal || Resolver || Abs) { 9798 bool NeedsComma = false; 9799 outs() << " ["; 9800 if (WeakDef) { 9801 outs() << "weak_def"; 9802 NeedsComma = true; 9803 } 9804 if (ThreadLocal) { 9805 if (NeedsComma) 9806 outs() << ", "; 9807 outs() << "per-thread"; 9808 NeedsComma = true; 9809 } 9810 if (Abs) { 9811 if (NeedsComma) 9812 outs() << ", "; 9813 outs() << "absolute"; 9814 NeedsComma = true; 9815 } 9816 if (Resolver) { 9817 if (NeedsComma) 9818 outs() << ", "; 9819 outs() << format("resolver=0x%08llX", Entry.other()); 9820 NeedsComma = true; 9821 } 9822 outs() << "]"; 9823 } 9824 if (ReExport) { 9825 StringRef DylibName = "unknown"; 9826 int Ordinal = Entry.other() - 1; 9827 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 9828 if (Entry.otherName().empty()) 9829 outs() << " (from " << DylibName << ")"; 9830 else 9831 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 9832 } 9833 outs() << "\n"; 9834 } 9835 if (Err) 9836 report_error(Obj->getFileName(), std::move(Err)); 9837 } 9838 9839 //===----------------------------------------------------------------------===// 9840 // rebase table dumping 9841 //===----------------------------------------------------------------------===// 9842 9843 void llvm::printMachORebaseTable(object::MachOObjectFile *Obj) { 9844 outs() << "segment section address type\n"; 9845 Error Err = Error::success(); 9846 for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 9847 StringRef SegmentName = Entry.segmentName(); 9848 StringRef SectionName = Entry.sectionName(); 9849 uint64_t Address = Entry.address(); 9850 9851 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 9852 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 9853 SegmentName.str().c_str(), SectionName.str().c_str(), 9854 Address, Entry.typeName().str().c_str()); 9855 } 9856 if (Err) 9857 report_error(Obj->getFileName(), std::move(Err)); 9858 } 9859 9860 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 9861 StringRef DylibName; 9862 switch (Ordinal) { 9863 case MachO::BIND_SPECIAL_DYLIB_SELF: 9864 return "this-image"; 9865 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 9866 return "main-executable"; 9867 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 9868 return "flat-namespace"; 9869 default: 9870 if (Ordinal > 0) { 9871 std::error_code EC = 9872 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 9873 if (EC) 9874 return "<<bad library ordinal>>"; 9875 return DylibName; 9876 } 9877 } 9878 return "<<unknown special ordinal>>"; 9879 } 9880 9881 //===----------------------------------------------------------------------===// 9882 // bind table dumping 9883 //===----------------------------------------------------------------------===// 9884 9885 void llvm::printMachOBindTable(object::MachOObjectFile *Obj) { 9886 // Build table of sections so names can used in final output. 9887 outs() << "segment section address type " 9888 "addend dylib symbol\n"; 9889 Error Err = Error::success(); 9890 for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 9891 StringRef SegmentName = Entry.segmentName(); 9892 StringRef SectionName = Entry.sectionName(); 9893 uint64_t Address = Entry.address(); 9894 9895 // Table lines look like: 9896 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 9897 StringRef Attr; 9898 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 9899 Attr = " (weak_import)"; 9900 outs() << left_justify(SegmentName, 8) << " " 9901 << left_justify(SectionName, 18) << " " 9902 << format_hex(Address, 10, true) << " " 9903 << left_justify(Entry.typeName(), 8) << " " 9904 << format_decimal(Entry.addend(), 8) << " " 9905 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9906 << Entry.symbolName() << Attr << "\n"; 9907 } 9908 if (Err) 9909 report_error(Obj->getFileName(), std::move(Err)); 9910 } 9911 9912 //===----------------------------------------------------------------------===// 9913 // lazy bind table dumping 9914 //===----------------------------------------------------------------------===// 9915 9916 void llvm::printMachOLazyBindTable(object::MachOObjectFile *Obj) { 9917 outs() << "segment section address " 9918 "dylib symbol\n"; 9919 Error Err = Error::success(); 9920 for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 9921 StringRef SegmentName = Entry.segmentName(); 9922 StringRef SectionName = Entry.sectionName(); 9923 uint64_t Address = Entry.address(); 9924 9925 // Table lines look like: 9926 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 9927 outs() << left_justify(SegmentName, 8) << " " 9928 << left_justify(SectionName, 18) << " " 9929 << format_hex(Address, 10, true) << " " 9930 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9931 << Entry.symbolName() << "\n"; 9932 } 9933 if (Err) 9934 report_error(Obj->getFileName(), std::move(Err)); 9935 } 9936 9937 //===----------------------------------------------------------------------===// 9938 // weak bind table dumping 9939 //===----------------------------------------------------------------------===// 9940 9941 void llvm::printMachOWeakBindTable(object::MachOObjectFile *Obj) { 9942 outs() << "segment section address " 9943 "type addend symbol\n"; 9944 Error Err = Error::success(); 9945 for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 9946 // Strong symbols don't have a location to update. 9947 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 9948 outs() << " strong " 9949 << Entry.symbolName() << "\n"; 9950 continue; 9951 } 9952 StringRef SegmentName = Entry.segmentName(); 9953 StringRef SectionName = Entry.sectionName(); 9954 uint64_t Address = Entry.address(); 9955 9956 // Table lines look like: 9957 // __DATA __data 0x00001000 pointer 0 _foo 9958 outs() << left_justify(SegmentName, 8) << " " 9959 << left_justify(SectionName, 18) << " " 9960 << format_hex(Address, 10, true) << " " 9961 << left_justify(Entry.typeName(), 8) << " " 9962 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 9963 << "\n"; 9964 } 9965 if (Err) 9966 report_error(Obj->getFileName(), std::move(Err)); 9967 } 9968 9969 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 9970 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 9971 // information for that address. If the address is found its binding symbol 9972 // name is returned. If not nullptr is returned. 9973 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 9974 struct DisassembleInfo *info) { 9975 if (info->bindtable == nullptr) { 9976 info->bindtable = llvm::make_unique<SymbolAddressMap>(); 9977 Error Err = Error::success(); 9978 for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 9979 uint64_t Address = Entry.address(); 9980 StringRef name = Entry.symbolName(); 9981 if (!name.empty()) 9982 (*info->bindtable)[Address] = name; 9983 } 9984 if (Err) 9985 report_error(info->O->getFileName(), std::move(Err)); 9986 } 9987 auto name = info->bindtable->lookup(ReferenceValue); 9988 return !name.empty() ? name.data() : nullptr; 9989 } 9990 9991