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/Object/MachO.h" 15 #include "llvm-objdump.h" 16 #include "llvm-c/Disassembler.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/StringExtras.h" 19 #include "llvm/ADT/Triple.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/MachOUniversal.h" 34 #include "llvm/Support/Casting.h" 35 #include "llvm/Support/CommandLine.h" 36 #include "llvm/Support/Debug.h" 37 #include "llvm/Support/Endian.h" 38 #include "llvm/Support/Format.h" 39 #include "llvm/Support/FormattedStream.h" 40 #include "llvm/Support/GraphWriter.h" 41 #include "llvm/Support/LEB128.h" 42 #include "llvm/Support/MachO.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 // This is used to search for a data in code table entry for the PC being 206 // disassembled. The j parameter has the PC in j.first. A single data in code 207 // table entry can cover many bytes for each of its Kind's. So if the offset, 208 // aka the i.first value, of the data in code table entry plus its Length 209 // covers the PC being searched for this will return true. If not it will 210 // return false. 211 static bool compareDiceTableEntries(const DiceTableEntry &i, 212 const DiceTableEntry &j) { 213 uint16_t Length; 214 i.second.getLength(Length); 215 216 return j.first >= i.first && j.first < i.first + Length; 217 } 218 219 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 220 unsigned short Kind) { 221 uint32_t Value, Size = 1; 222 223 switch (Kind) { 224 default: 225 case MachO::DICE_KIND_DATA: 226 if (Length >= 4) { 227 if (!NoShowRawInsn) 228 dumpBytes(makeArrayRef(bytes, 4), outs()); 229 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 230 outs() << "\t.long " << Value; 231 Size = 4; 232 } else if (Length >= 2) { 233 if (!NoShowRawInsn) 234 dumpBytes(makeArrayRef(bytes, 2), outs()); 235 Value = bytes[1] << 8 | bytes[0]; 236 outs() << "\t.short " << Value; 237 Size = 2; 238 } else { 239 if (!NoShowRawInsn) 240 dumpBytes(makeArrayRef(bytes, 2), outs()); 241 Value = bytes[0]; 242 outs() << "\t.byte " << Value; 243 Size = 1; 244 } 245 if (Kind == MachO::DICE_KIND_DATA) 246 outs() << "\t@ KIND_DATA\n"; 247 else 248 outs() << "\t@ data in code kind = " << Kind << "\n"; 249 break; 250 case MachO::DICE_KIND_JUMP_TABLE8: 251 if (!NoShowRawInsn) 252 dumpBytes(makeArrayRef(bytes, 1), outs()); 253 Value = bytes[0]; 254 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 255 Size = 1; 256 break; 257 case MachO::DICE_KIND_JUMP_TABLE16: 258 if (!NoShowRawInsn) 259 dumpBytes(makeArrayRef(bytes, 2), outs()); 260 Value = bytes[1] << 8 | bytes[0]; 261 outs() << "\t.short " << format("%5u", Value & 0xffff) 262 << "\t@ KIND_JUMP_TABLE16\n"; 263 Size = 2; 264 break; 265 case MachO::DICE_KIND_JUMP_TABLE32: 266 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 267 if (!NoShowRawInsn) 268 dumpBytes(makeArrayRef(bytes, 4), outs()); 269 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 270 outs() << "\t.long " << Value; 271 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 272 outs() << "\t@ KIND_JUMP_TABLE32\n"; 273 else 274 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 275 Size = 4; 276 break; 277 } 278 return Size; 279 } 280 281 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 282 std::vector<SectionRef> &Sections, 283 std::vector<SymbolRef> &Symbols, 284 SmallVectorImpl<uint64_t> &FoundFns, 285 uint64_t &BaseSegmentAddress) { 286 for (const SymbolRef &Symbol : MachOObj->symbols()) { 287 Expected<StringRef> SymName = Symbol.getName(); 288 if (!SymName) 289 report_error(MachOObj->getFileName(), SymName.takeError()); 290 if (!SymName->startswith("ltmp")) 291 Symbols.push_back(Symbol); 292 } 293 294 for (const SectionRef &Section : MachOObj->sections()) { 295 StringRef SectName; 296 Section.getName(SectName); 297 Sections.push_back(Section); 298 } 299 300 bool BaseSegmentAddressSet = false; 301 for (const auto &Command : MachOObj->load_commands()) { 302 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 303 // We found a function starts segment, parse the addresses for later 304 // consumption. 305 MachO::linkedit_data_command LLC = 306 MachOObj->getLinkeditDataLoadCommand(Command); 307 308 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 309 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 310 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 311 StringRef SegName = SLC.segname; 312 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 313 BaseSegmentAddressSet = true; 314 BaseSegmentAddress = SLC.vmaddr; 315 } 316 } 317 } 318 } 319 320 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 321 uint32_t n, uint32_t count, 322 uint32_t stride, uint64_t addr) { 323 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 324 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 325 if (n > nindirectsyms) 326 outs() << " (entries start past the end of the indirect symbol " 327 "table) (reserved1 field greater than the table size)"; 328 else if (n + count > nindirectsyms) 329 outs() << " (entries extends past the end of the indirect symbol " 330 "table)"; 331 outs() << "\n"; 332 uint32_t cputype = O->getHeader().cputype; 333 if (cputype & MachO::CPU_ARCH_ABI64) 334 outs() << "address index"; 335 else 336 outs() << "address index"; 337 if (verbose) 338 outs() << " name\n"; 339 else 340 outs() << "\n"; 341 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 342 if (cputype & MachO::CPU_ARCH_ABI64) 343 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 344 else 345 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 346 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 347 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 348 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 349 outs() << "LOCAL\n"; 350 continue; 351 } 352 if (indirect_symbol == 353 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 354 outs() << "LOCAL ABSOLUTE\n"; 355 continue; 356 } 357 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 358 outs() << "ABSOLUTE\n"; 359 continue; 360 } 361 outs() << format("%5u ", indirect_symbol); 362 if (verbose) { 363 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 364 if (indirect_symbol < Symtab.nsyms) { 365 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 366 SymbolRef Symbol = *Sym; 367 Expected<StringRef> SymName = Symbol.getName(); 368 if (!SymName) 369 report_error(O->getFileName(), SymName.takeError()); 370 outs() << *SymName; 371 } else { 372 outs() << "?"; 373 } 374 } 375 outs() << "\n"; 376 } 377 } 378 379 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 380 for (const auto &Load : O->load_commands()) { 381 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 382 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 383 for (unsigned J = 0; J < Seg.nsects; ++J) { 384 MachO::section_64 Sec = O->getSection64(Load, J); 385 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 386 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 387 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 388 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 389 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 390 section_type == MachO::S_SYMBOL_STUBS) { 391 uint32_t stride; 392 if (section_type == MachO::S_SYMBOL_STUBS) 393 stride = Sec.reserved2; 394 else 395 stride = 8; 396 if (stride == 0) { 397 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 398 << Sec.sectname << ") " 399 << "(size of stubs in reserved2 field is zero)\n"; 400 continue; 401 } 402 uint32_t count = Sec.size / stride; 403 outs() << "Indirect symbols for (" << Sec.segname << "," 404 << Sec.sectname << ") " << count << " entries"; 405 uint32_t n = Sec.reserved1; 406 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 407 } 408 } 409 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 410 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 411 for (unsigned J = 0; J < Seg.nsects; ++J) { 412 MachO::section Sec = O->getSection(Load, J); 413 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 414 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 415 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 416 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 417 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 418 section_type == MachO::S_SYMBOL_STUBS) { 419 uint32_t stride; 420 if (section_type == MachO::S_SYMBOL_STUBS) 421 stride = Sec.reserved2; 422 else 423 stride = 4; 424 if (stride == 0) { 425 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 426 << Sec.sectname << ") " 427 << "(size of stubs in reserved2 field is zero)\n"; 428 continue; 429 } 430 uint32_t count = Sec.size / stride; 431 outs() << "Indirect symbols for (" << Sec.segname << "," 432 << Sec.sectname << ") " << count << " entries"; 433 uint32_t n = Sec.reserved1; 434 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 435 } 436 } 437 } 438 } 439 } 440 441 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 442 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 443 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 444 outs() << "Data in code table (" << nentries << " entries)\n"; 445 outs() << "offset length kind\n"; 446 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 447 ++DI) { 448 uint32_t Offset; 449 DI->getOffset(Offset); 450 outs() << format("0x%08" PRIx32, Offset) << " "; 451 uint16_t Length; 452 DI->getLength(Length); 453 outs() << format("%6u", Length) << " "; 454 uint16_t Kind; 455 DI->getKind(Kind); 456 if (verbose) { 457 switch (Kind) { 458 case MachO::DICE_KIND_DATA: 459 outs() << "DATA"; 460 break; 461 case MachO::DICE_KIND_JUMP_TABLE8: 462 outs() << "JUMP_TABLE8"; 463 break; 464 case MachO::DICE_KIND_JUMP_TABLE16: 465 outs() << "JUMP_TABLE16"; 466 break; 467 case MachO::DICE_KIND_JUMP_TABLE32: 468 outs() << "JUMP_TABLE32"; 469 break; 470 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 471 outs() << "ABS_JUMP_TABLE32"; 472 break; 473 default: 474 outs() << format("0x%04" PRIx32, Kind); 475 break; 476 } 477 } else 478 outs() << format("0x%04" PRIx32, Kind); 479 outs() << "\n"; 480 } 481 } 482 483 static void PrintLinkOptHints(MachOObjectFile *O) { 484 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 485 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 486 uint32_t nloh = LohLC.datasize; 487 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 488 for (uint32_t i = 0; i < nloh;) { 489 unsigned n; 490 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 491 i += n; 492 outs() << " identifier " << identifier << " "; 493 if (i >= nloh) 494 return; 495 switch (identifier) { 496 case 1: 497 outs() << "AdrpAdrp\n"; 498 break; 499 case 2: 500 outs() << "AdrpLdr\n"; 501 break; 502 case 3: 503 outs() << "AdrpAddLdr\n"; 504 break; 505 case 4: 506 outs() << "AdrpLdrGotLdr\n"; 507 break; 508 case 5: 509 outs() << "AdrpAddStr\n"; 510 break; 511 case 6: 512 outs() << "AdrpLdrGotStr\n"; 513 break; 514 case 7: 515 outs() << "AdrpAdd\n"; 516 break; 517 case 8: 518 outs() << "AdrpLdrGot\n"; 519 break; 520 default: 521 outs() << "Unknown identifier value\n"; 522 break; 523 } 524 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 525 i += n; 526 outs() << " narguments " << narguments << "\n"; 527 if (i >= nloh) 528 return; 529 530 for (uint32_t j = 0; j < narguments; j++) { 531 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 532 i += n; 533 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 534 if (i >= nloh) 535 return; 536 } 537 } 538 } 539 540 static void PrintDylibs(MachOObjectFile *O, bool JustId) { 541 unsigned Index = 0; 542 for (const auto &Load : O->load_commands()) { 543 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 544 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 545 Load.C.cmd == MachO::LC_LOAD_DYLIB || 546 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 547 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 548 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 549 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 550 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 551 if (dl.dylib.name < dl.cmdsize) { 552 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 553 if (JustId) 554 outs() << p << "\n"; 555 else { 556 outs() << "\t" << p; 557 outs() << " (compatibility version " 558 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 559 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 560 << (dl.dylib.compatibility_version & 0xff) << ","; 561 outs() << " current version " 562 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 563 << ((dl.dylib.current_version >> 8) & 0xff) << "." 564 << (dl.dylib.current_version & 0xff) << ")\n"; 565 } 566 } else { 567 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 568 if (Load.C.cmd == MachO::LC_ID_DYLIB) 569 outs() << "LC_ID_DYLIB "; 570 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 571 outs() << "LC_LOAD_DYLIB "; 572 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 573 outs() << "LC_LOAD_WEAK_DYLIB "; 574 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 575 outs() << "LC_LAZY_LOAD_DYLIB "; 576 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 577 outs() << "LC_REEXPORT_DYLIB "; 578 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 579 outs() << "LC_LOAD_UPWARD_DYLIB "; 580 else 581 outs() << "LC_??? "; 582 outs() << "command " << Index++ << "\n"; 583 } 584 } 585 } 586 } 587 588 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 589 590 static void CreateSymbolAddressMap(MachOObjectFile *O, 591 SymbolAddressMap *AddrMap) { 592 // Create a map of symbol addresses to symbol names. 593 for (const SymbolRef &Symbol : O->symbols()) { 594 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 595 if (!STOrErr) 596 report_error(O->getFileName(), STOrErr.takeError()); 597 SymbolRef::Type ST = *STOrErr; 598 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 599 ST == SymbolRef::ST_Other) { 600 uint64_t Address = Symbol.getValue(); 601 Expected<StringRef> SymNameOrErr = Symbol.getName(); 602 if (!SymNameOrErr) 603 report_error(O->getFileName(), SymNameOrErr.takeError()); 604 StringRef SymName = *SymNameOrErr; 605 if (!SymName.startswith(".objc")) 606 (*AddrMap)[Address] = SymName; 607 } 608 } 609 } 610 611 // GuessSymbolName is passed the address of what might be a symbol and a 612 // pointer to the SymbolAddressMap. It returns the name of a symbol 613 // with that address or nullptr if no symbol is found with that address. 614 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 615 const char *SymbolName = nullptr; 616 // A DenseMap can't lookup up some values. 617 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 618 StringRef name = AddrMap->lookup(value); 619 if (!name.empty()) 620 SymbolName = name.data(); 621 } 622 return SymbolName; 623 } 624 625 static void DumpCstringChar(const char c) { 626 char p[2]; 627 p[0] = c; 628 p[1] = '\0'; 629 outs().write_escaped(p); 630 } 631 632 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 633 uint32_t sect_size, uint64_t sect_addr, 634 bool print_addresses) { 635 for (uint32_t i = 0; i < sect_size; i++) { 636 if (print_addresses) { 637 if (O->is64Bit()) 638 outs() << format("%016" PRIx64, sect_addr + i) << " "; 639 else 640 outs() << format("%08" PRIx64, sect_addr + i) << " "; 641 } 642 for (; i < sect_size && sect[i] != '\0'; i++) 643 DumpCstringChar(sect[i]); 644 if (i < sect_size && sect[i] == '\0') 645 outs() << "\n"; 646 } 647 } 648 649 static void DumpLiteral4(uint32_t l, float f) { 650 outs() << format("0x%08" PRIx32, l); 651 if ((l & 0x7f800000) != 0x7f800000) 652 outs() << format(" (%.16e)\n", f); 653 else { 654 if (l == 0x7f800000) 655 outs() << " (+Infinity)\n"; 656 else if (l == 0xff800000) 657 outs() << " (-Infinity)\n"; 658 else if ((l & 0x00400000) == 0x00400000) 659 outs() << " (non-signaling Not-a-Number)\n"; 660 else 661 outs() << " (signaling Not-a-Number)\n"; 662 } 663 } 664 665 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 666 uint32_t sect_size, uint64_t sect_addr, 667 bool print_addresses) { 668 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 669 if (print_addresses) { 670 if (O->is64Bit()) 671 outs() << format("%016" PRIx64, sect_addr + i) << " "; 672 else 673 outs() << format("%08" PRIx64, sect_addr + i) << " "; 674 } 675 float f; 676 memcpy(&f, sect + i, sizeof(float)); 677 if (O->isLittleEndian() != sys::IsLittleEndianHost) 678 sys::swapByteOrder(f); 679 uint32_t l; 680 memcpy(&l, sect + i, sizeof(uint32_t)); 681 if (O->isLittleEndian() != sys::IsLittleEndianHost) 682 sys::swapByteOrder(l); 683 DumpLiteral4(l, f); 684 } 685 } 686 687 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 688 double d) { 689 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 690 uint32_t Hi, Lo; 691 Hi = (O->isLittleEndian()) ? l1 : l0; 692 Lo = (O->isLittleEndian()) ? l0 : l1; 693 694 // Hi is the high word, so this is equivalent to if(isfinite(d)) 695 if ((Hi & 0x7ff00000) != 0x7ff00000) 696 outs() << format(" (%.16e)\n", d); 697 else { 698 if (Hi == 0x7ff00000 && Lo == 0) 699 outs() << " (+Infinity)\n"; 700 else if (Hi == 0xfff00000 && Lo == 0) 701 outs() << " (-Infinity)\n"; 702 else if ((Hi & 0x00080000) == 0x00080000) 703 outs() << " (non-signaling Not-a-Number)\n"; 704 else 705 outs() << " (signaling Not-a-Number)\n"; 706 } 707 } 708 709 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 710 uint32_t sect_size, uint64_t sect_addr, 711 bool print_addresses) { 712 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 713 if (print_addresses) { 714 if (O->is64Bit()) 715 outs() << format("%016" PRIx64, sect_addr + i) << " "; 716 else 717 outs() << format("%08" PRIx64, sect_addr + i) << " "; 718 } 719 double d; 720 memcpy(&d, sect + i, sizeof(double)); 721 if (O->isLittleEndian() != sys::IsLittleEndianHost) 722 sys::swapByteOrder(d); 723 uint32_t l0, l1; 724 memcpy(&l0, sect + i, sizeof(uint32_t)); 725 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 726 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 727 sys::swapByteOrder(l0); 728 sys::swapByteOrder(l1); 729 } 730 DumpLiteral8(O, l0, l1, d); 731 } 732 } 733 734 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 735 outs() << format("0x%08" PRIx32, l0) << " "; 736 outs() << format("0x%08" PRIx32, l1) << " "; 737 outs() << format("0x%08" PRIx32, l2) << " "; 738 outs() << format("0x%08" PRIx32, l3) << "\n"; 739 } 740 741 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 742 uint32_t sect_size, uint64_t sect_addr, 743 bool print_addresses) { 744 for (uint32_t i = 0; i < sect_size; i += 16) { 745 if (print_addresses) { 746 if (O->is64Bit()) 747 outs() << format("%016" PRIx64, sect_addr + i) << " "; 748 else 749 outs() << format("%08" PRIx64, sect_addr + i) << " "; 750 } 751 uint32_t l0, l1, l2, l3; 752 memcpy(&l0, sect + i, sizeof(uint32_t)); 753 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 754 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 755 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 756 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 757 sys::swapByteOrder(l0); 758 sys::swapByteOrder(l1); 759 sys::swapByteOrder(l2); 760 sys::swapByteOrder(l3); 761 } 762 DumpLiteral16(l0, l1, l2, l3); 763 } 764 } 765 766 static void DumpLiteralPointerSection(MachOObjectFile *O, 767 const SectionRef &Section, 768 const char *sect, uint32_t sect_size, 769 uint64_t sect_addr, 770 bool print_addresses) { 771 // Collect the literal sections in this Mach-O file. 772 std::vector<SectionRef> LiteralSections; 773 for (const SectionRef &Section : O->sections()) { 774 DataRefImpl Ref = Section.getRawDataRefImpl(); 775 uint32_t section_type; 776 if (O->is64Bit()) { 777 const MachO::section_64 Sec = O->getSection64(Ref); 778 section_type = Sec.flags & MachO::SECTION_TYPE; 779 } else { 780 const MachO::section Sec = O->getSection(Ref); 781 section_type = Sec.flags & MachO::SECTION_TYPE; 782 } 783 if (section_type == MachO::S_CSTRING_LITERALS || 784 section_type == MachO::S_4BYTE_LITERALS || 785 section_type == MachO::S_8BYTE_LITERALS || 786 section_type == MachO::S_16BYTE_LITERALS) 787 LiteralSections.push_back(Section); 788 } 789 790 // Set the size of the literal pointer. 791 uint32_t lp_size = O->is64Bit() ? 8 : 4; 792 793 // Collect the external relocation symbols for the literal pointers. 794 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 795 for (const RelocationRef &Reloc : Section.relocations()) { 796 DataRefImpl Rel; 797 MachO::any_relocation_info RE; 798 bool isExtern = false; 799 Rel = Reloc.getRawDataRefImpl(); 800 RE = O->getRelocation(Rel); 801 isExtern = O->getPlainRelocationExternal(RE); 802 if (isExtern) { 803 uint64_t RelocOffset = Reloc.getOffset(); 804 symbol_iterator RelocSym = Reloc.getSymbol(); 805 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 806 } 807 } 808 array_pod_sort(Relocs.begin(), Relocs.end()); 809 810 // Dump each literal pointer. 811 for (uint32_t i = 0; i < sect_size; i += lp_size) { 812 if (print_addresses) { 813 if (O->is64Bit()) 814 outs() << format("%016" PRIx64, sect_addr + i) << " "; 815 else 816 outs() << format("%08" PRIx64, sect_addr + i) << " "; 817 } 818 uint64_t lp; 819 if (O->is64Bit()) { 820 memcpy(&lp, sect + i, sizeof(uint64_t)); 821 if (O->isLittleEndian() != sys::IsLittleEndianHost) 822 sys::swapByteOrder(lp); 823 } else { 824 uint32_t li; 825 memcpy(&li, sect + i, sizeof(uint32_t)); 826 if (O->isLittleEndian() != sys::IsLittleEndianHost) 827 sys::swapByteOrder(li); 828 lp = li; 829 } 830 831 // First look for an external relocation entry for this literal pointer. 832 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 833 return P.first == i; 834 }); 835 if (Reloc != Relocs.end()) { 836 symbol_iterator RelocSym = Reloc->second; 837 Expected<StringRef> SymName = RelocSym->getName(); 838 if (!SymName) 839 report_error(O->getFileName(), SymName.takeError()); 840 outs() << "external relocation entry for symbol:" << *SymName << "\n"; 841 continue; 842 } 843 844 // For local references see what the section the literal pointer points to. 845 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 846 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 847 }); 848 if (Sect == LiteralSections.end()) { 849 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 850 continue; 851 } 852 853 uint64_t SectAddress = Sect->getAddress(); 854 uint64_t SectSize = Sect->getSize(); 855 856 StringRef SectName; 857 Sect->getName(SectName); 858 DataRefImpl Ref = Sect->getRawDataRefImpl(); 859 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 860 outs() << SegmentName << ":" << SectName << ":"; 861 862 uint32_t section_type; 863 if (O->is64Bit()) { 864 const MachO::section_64 Sec = O->getSection64(Ref); 865 section_type = Sec.flags & MachO::SECTION_TYPE; 866 } else { 867 const MachO::section Sec = O->getSection(Ref); 868 section_type = Sec.flags & MachO::SECTION_TYPE; 869 } 870 871 StringRef BytesStr; 872 Sect->getContents(BytesStr); 873 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 874 875 switch (section_type) { 876 case MachO::S_CSTRING_LITERALS: 877 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 878 i++) { 879 DumpCstringChar(Contents[i]); 880 } 881 outs() << "\n"; 882 break; 883 case MachO::S_4BYTE_LITERALS: 884 float f; 885 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 886 uint32_t l; 887 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 888 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 889 sys::swapByteOrder(f); 890 sys::swapByteOrder(l); 891 } 892 DumpLiteral4(l, f); 893 break; 894 case MachO::S_8BYTE_LITERALS: { 895 double d; 896 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 897 uint32_t l0, l1; 898 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 899 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 900 sizeof(uint32_t)); 901 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 902 sys::swapByteOrder(f); 903 sys::swapByteOrder(l0); 904 sys::swapByteOrder(l1); 905 } 906 DumpLiteral8(O, l0, l1, d); 907 break; 908 } 909 case MachO::S_16BYTE_LITERALS: { 910 uint32_t l0, l1, l2, l3; 911 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 912 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 913 sizeof(uint32_t)); 914 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 915 sizeof(uint32_t)); 916 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 917 sizeof(uint32_t)); 918 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 919 sys::swapByteOrder(l0); 920 sys::swapByteOrder(l1); 921 sys::swapByteOrder(l2); 922 sys::swapByteOrder(l3); 923 } 924 DumpLiteral16(l0, l1, l2, l3); 925 break; 926 } 927 } 928 } 929 } 930 931 static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect, 932 uint32_t sect_size, uint64_t sect_addr, 933 SymbolAddressMap *AddrMap, 934 bool verbose) { 935 uint32_t stride; 936 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 937 for (uint32_t i = 0; i < sect_size; i += stride) { 938 const char *SymbolName = nullptr; 939 if (O->is64Bit()) { 940 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 941 uint64_t pointer_value; 942 memcpy(&pointer_value, sect + i, stride); 943 if (O->isLittleEndian() != sys::IsLittleEndianHost) 944 sys::swapByteOrder(pointer_value); 945 outs() << format("0x%016" PRIx64, pointer_value); 946 if (verbose) 947 SymbolName = GuessSymbolName(pointer_value, AddrMap); 948 } else { 949 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 950 uint32_t pointer_value; 951 memcpy(&pointer_value, sect + i, stride); 952 if (O->isLittleEndian() != sys::IsLittleEndianHost) 953 sys::swapByteOrder(pointer_value); 954 outs() << format("0x%08" PRIx32, pointer_value); 955 if (verbose) 956 SymbolName = GuessSymbolName(pointer_value, AddrMap); 957 } 958 if (SymbolName) 959 outs() << " " << SymbolName; 960 outs() << "\n"; 961 } 962 } 963 964 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 965 uint32_t size, uint64_t addr) { 966 uint32_t cputype = O->getHeader().cputype; 967 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 968 uint32_t j; 969 for (uint32_t i = 0; i < size; i += j, addr += j) { 970 if (O->is64Bit()) 971 outs() << format("%016" PRIx64, addr) << "\t"; 972 else 973 outs() << format("%08" PRIx64, addr) << "\t"; 974 for (j = 0; j < 16 && i + j < size; j++) { 975 uint8_t byte_word = *(sect + i + j); 976 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 977 } 978 outs() << "\n"; 979 } 980 } else { 981 uint32_t j; 982 for (uint32_t i = 0; i < size; i += j, addr += j) { 983 if (O->is64Bit()) 984 outs() << format("%016" PRIx64, addr) << "\t"; 985 else 986 outs() << format("%08" PRIx64, addr) << "\t"; 987 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 988 j += sizeof(int32_t)) { 989 if (i + j + sizeof(int32_t) <= size) { 990 uint32_t long_word; 991 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 992 if (O->isLittleEndian() != sys::IsLittleEndianHost) 993 sys::swapByteOrder(long_word); 994 outs() << format("%08" PRIx32, long_word) << " "; 995 } else { 996 for (uint32_t k = 0; i + j + k < size; k++) { 997 uint8_t byte_word = *(sect + i + j + k); 998 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 999 } 1000 } 1001 } 1002 outs() << "\n"; 1003 } 1004 } 1005 } 1006 1007 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1008 StringRef DisSegName, StringRef DisSectName); 1009 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1010 uint32_t size, uint32_t addr); 1011 #ifdef HAVE_LIBXAR 1012 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 1013 uint32_t size, bool verbose, 1014 bool PrintXarHeader, bool PrintXarFileHeaders, 1015 std::string XarMemberName); 1016 #endif // defined(HAVE_LIBXAR) 1017 1018 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1019 bool verbose) { 1020 SymbolAddressMap AddrMap; 1021 if (verbose) 1022 CreateSymbolAddressMap(O, &AddrMap); 1023 1024 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1025 StringRef DumpSection = FilterSections[i]; 1026 std::pair<StringRef, StringRef> DumpSegSectName; 1027 DumpSegSectName = DumpSection.split(','); 1028 StringRef DumpSegName, DumpSectName; 1029 if (DumpSegSectName.second.size()) { 1030 DumpSegName = DumpSegSectName.first; 1031 DumpSectName = DumpSegSectName.second; 1032 } else { 1033 DumpSegName = ""; 1034 DumpSectName = DumpSegSectName.first; 1035 } 1036 for (const SectionRef &Section : O->sections()) { 1037 StringRef SectName; 1038 Section.getName(SectName); 1039 DataRefImpl Ref = Section.getRawDataRefImpl(); 1040 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1041 if ((DumpSegName.empty() || SegName == DumpSegName) && 1042 (SectName == DumpSectName)) { 1043 1044 uint32_t section_flags; 1045 if (O->is64Bit()) { 1046 const MachO::section_64 Sec = O->getSection64(Ref); 1047 section_flags = Sec.flags; 1048 1049 } else { 1050 const MachO::section Sec = O->getSection(Ref); 1051 section_flags = Sec.flags; 1052 } 1053 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1054 1055 StringRef BytesStr; 1056 Section.getContents(BytesStr); 1057 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1058 uint32_t sect_size = BytesStr.size(); 1059 uint64_t sect_addr = Section.getAddress(); 1060 1061 outs() << "Contents of (" << SegName << "," << SectName 1062 << ") section\n"; 1063 1064 if (verbose) { 1065 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1066 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1067 DisassembleMachO(Filename, O, SegName, SectName); 1068 continue; 1069 } 1070 if (SegName == "__TEXT" && SectName == "__info_plist") { 1071 outs() << sect; 1072 continue; 1073 } 1074 if (SegName == "__OBJC" && SectName == "__protocol") { 1075 DumpProtocolSection(O, sect, sect_size, sect_addr); 1076 continue; 1077 } 1078 #ifdef HAVE_LIBXAR 1079 if (SegName == "__LLVM" && SectName == "__bundle") { 1080 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands, 1081 ArchiveHeaders, ""); 1082 continue; 1083 } 1084 #endif // defined(HAVE_LIBXAR) 1085 switch (section_type) { 1086 case MachO::S_REGULAR: 1087 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1088 break; 1089 case MachO::S_ZEROFILL: 1090 outs() << "zerofill section and has no contents in the file\n"; 1091 break; 1092 case MachO::S_CSTRING_LITERALS: 1093 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1094 break; 1095 case MachO::S_4BYTE_LITERALS: 1096 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1097 break; 1098 case MachO::S_8BYTE_LITERALS: 1099 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1100 break; 1101 case MachO::S_16BYTE_LITERALS: 1102 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1103 break; 1104 case MachO::S_LITERAL_POINTERS: 1105 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1106 !NoLeadingAddr); 1107 break; 1108 case MachO::S_MOD_INIT_FUNC_POINTERS: 1109 case MachO::S_MOD_TERM_FUNC_POINTERS: 1110 DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap, 1111 verbose); 1112 break; 1113 default: 1114 outs() << "Unknown section type (" 1115 << format("0x%08" PRIx32, section_type) << ")\n"; 1116 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1117 break; 1118 } 1119 } else { 1120 if (section_type == MachO::S_ZEROFILL) 1121 outs() << "zerofill section and has no contents in the file\n"; 1122 else 1123 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1124 } 1125 } 1126 } 1127 } 1128 } 1129 1130 static void DumpInfoPlistSectionContents(StringRef Filename, 1131 MachOObjectFile *O) { 1132 for (const SectionRef &Section : O->sections()) { 1133 StringRef SectName; 1134 Section.getName(SectName); 1135 DataRefImpl Ref = Section.getRawDataRefImpl(); 1136 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1137 if (SegName == "__TEXT" && SectName == "__info_plist") { 1138 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1139 StringRef BytesStr; 1140 Section.getContents(BytesStr); 1141 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1142 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 1143 return; 1144 } 1145 } 1146 } 1147 1148 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1149 // and if it is and there is a list of architecture flags is specified then 1150 // check to make sure this Mach-O file is one of those architectures or all 1151 // architectures were specified. If not then an error is generated and this 1152 // routine returns false. Else it returns true. 1153 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1154 auto *MachO = dyn_cast<MachOObjectFile>(O); 1155 1156 if (!MachO || ArchAll || ArchFlags.empty()) 1157 return true; 1158 1159 MachO::mach_header H; 1160 MachO::mach_header_64 H_64; 1161 Triple T; 1162 const char *McpuDefault, *ArchFlag; 1163 if (MachO->is64Bit()) { 1164 H_64 = MachO->MachOObjectFile::getHeader64(); 1165 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 1166 &McpuDefault, &ArchFlag); 1167 } else { 1168 H = MachO->MachOObjectFile::getHeader(); 1169 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 1170 &McpuDefault, &ArchFlag); 1171 } 1172 const std::string ArchFlagName(ArchFlag); 1173 if (none_of(ArchFlags, [&](const std::string &Name) { 1174 return Name == ArchFlagName; 1175 })) { 1176 errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n"; 1177 return false; 1178 } 1179 return true; 1180 } 1181 1182 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 1183 1184 // ProcessMachO() is passed a single opened Mach-O file, which may be an 1185 // archive member and or in a slice of a universal file. It prints the 1186 // the file name and header info and then processes it according to the 1187 // command line options. 1188 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 1189 StringRef ArchiveMemberName = StringRef(), 1190 StringRef ArchitectureName = StringRef()) { 1191 // If we are doing some processing here on the Mach-O file print the header 1192 // info. And don't print it otherwise like in the case of printing the 1193 // UniversalHeaders or ArchiveHeaders. 1194 if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable || 1195 LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints || 1196 DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) { 1197 if (!NoLeadingHeaders) { 1198 outs() << Name; 1199 if (!ArchiveMemberName.empty()) 1200 outs() << '(' << ArchiveMemberName << ')'; 1201 if (!ArchitectureName.empty()) 1202 outs() << " (architecture " << ArchitectureName << ")"; 1203 outs() << ":\n"; 1204 } 1205 } 1206 // To use the report_error() form with an ArchiveName and FileName set 1207 // these up based on what is passed for Name and ArchiveMemberName. 1208 StringRef ArchiveName; 1209 StringRef FileName; 1210 if (!ArchiveMemberName.empty()) { 1211 ArchiveName = Name; 1212 FileName = ArchiveMemberName; 1213 } else { 1214 ArchiveName = StringRef(); 1215 FileName = Name; 1216 } 1217 1218 // If we need the symbol table to do the operation then check it here to 1219 // produce a good error message as to where the Mach-O file comes from in 1220 // the error message. 1221 if (Disassemble || IndirectSymbols || FilterSections.size() != 0 || 1222 UnwindInfo) 1223 if (Error Err = MachOOF->checkSymbolTable()) 1224 report_error(ArchiveName, FileName, std::move(Err), ArchitectureName); 1225 1226 if (Disassemble) 1227 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 1228 if (IndirectSymbols) 1229 PrintIndirectSymbols(MachOOF, !NonVerbose); 1230 if (DataInCode) 1231 PrintDataInCodeTable(MachOOF, !NonVerbose); 1232 if (LinkOptHints) 1233 PrintLinkOptHints(MachOOF); 1234 if (Relocations) 1235 PrintRelocations(MachOOF); 1236 if (SectionHeaders) 1237 PrintSectionHeaders(MachOOF); 1238 if (SectionContents) 1239 PrintSectionContents(MachOOF); 1240 if (FilterSections.size() != 0) 1241 DumpSectionContents(FileName, MachOOF, !NonVerbose); 1242 if (InfoPlist) 1243 DumpInfoPlistSectionContents(FileName, MachOOF); 1244 if (DylibsUsed) 1245 PrintDylibs(MachOOF, false); 1246 if (DylibId) 1247 PrintDylibs(MachOOF, true); 1248 if (SymbolTable) 1249 PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName); 1250 if (UnwindInfo) 1251 printMachOUnwindInfo(MachOOF); 1252 if (PrivateHeaders) { 1253 printMachOFileHeader(MachOOF); 1254 printMachOLoadCommands(MachOOF); 1255 } 1256 if (FirstPrivateHeader) 1257 printMachOFileHeader(MachOOF); 1258 if (ObjcMetaData) 1259 printObjcMetaData(MachOOF, !NonVerbose); 1260 if (ExportsTrie) 1261 printExportsTrie(MachOOF); 1262 if (Rebase) 1263 printRebaseTable(MachOOF); 1264 if (Bind) 1265 printBindTable(MachOOF); 1266 if (LazyBind) 1267 printLazyBindTable(MachOOF); 1268 if (WeakBind) 1269 printWeakBindTable(MachOOF); 1270 1271 if (DwarfDumpType != DIDT_Null) { 1272 std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*MachOOF)); 1273 // Dump the complete DWARF structure. 1274 DICtx->dump(outs(), DwarfDumpType, true /* DumpEH */); 1275 } 1276 } 1277 1278 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 1279 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 1280 outs() << " cputype (" << cputype << ")\n"; 1281 outs() << " cpusubtype (" << cpusubtype << ")\n"; 1282 } 1283 1284 // printCPUType() helps print_fat_headers by printing the cputype and 1285 // pusubtype (symbolically for the one's it knows about). 1286 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 1287 switch (cputype) { 1288 case MachO::CPU_TYPE_I386: 1289 switch (cpusubtype) { 1290 case MachO::CPU_SUBTYPE_I386_ALL: 1291 outs() << " cputype CPU_TYPE_I386\n"; 1292 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 1293 break; 1294 default: 1295 printUnknownCPUType(cputype, cpusubtype); 1296 break; 1297 } 1298 break; 1299 case MachO::CPU_TYPE_X86_64: 1300 switch (cpusubtype) { 1301 case MachO::CPU_SUBTYPE_X86_64_ALL: 1302 outs() << " cputype CPU_TYPE_X86_64\n"; 1303 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 1304 break; 1305 case MachO::CPU_SUBTYPE_X86_64_H: 1306 outs() << " cputype CPU_TYPE_X86_64\n"; 1307 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 1308 break; 1309 default: 1310 printUnknownCPUType(cputype, cpusubtype); 1311 break; 1312 } 1313 break; 1314 case MachO::CPU_TYPE_ARM: 1315 switch (cpusubtype) { 1316 case MachO::CPU_SUBTYPE_ARM_ALL: 1317 outs() << " cputype CPU_TYPE_ARM\n"; 1318 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 1319 break; 1320 case MachO::CPU_SUBTYPE_ARM_V4T: 1321 outs() << " cputype CPU_TYPE_ARM\n"; 1322 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 1323 break; 1324 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1325 outs() << " cputype CPU_TYPE_ARM\n"; 1326 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 1327 break; 1328 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1329 outs() << " cputype CPU_TYPE_ARM\n"; 1330 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 1331 break; 1332 case MachO::CPU_SUBTYPE_ARM_V6: 1333 outs() << " cputype CPU_TYPE_ARM\n"; 1334 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 1335 break; 1336 case MachO::CPU_SUBTYPE_ARM_V6M: 1337 outs() << " cputype CPU_TYPE_ARM\n"; 1338 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 1339 break; 1340 case MachO::CPU_SUBTYPE_ARM_V7: 1341 outs() << " cputype CPU_TYPE_ARM\n"; 1342 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 1343 break; 1344 case MachO::CPU_SUBTYPE_ARM_V7EM: 1345 outs() << " cputype CPU_TYPE_ARM\n"; 1346 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 1347 break; 1348 case MachO::CPU_SUBTYPE_ARM_V7K: 1349 outs() << " cputype CPU_TYPE_ARM\n"; 1350 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 1351 break; 1352 case MachO::CPU_SUBTYPE_ARM_V7M: 1353 outs() << " cputype CPU_TYPE_ARM\n"; 1354 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 1355 break; 1356 case MachO::CPU_SUBTYPE_ARM_V7S: 1357 outs() << " cputype CPU_TYPE_ARM\n"; 1358 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 1359 break; 1360 default: 1361 printUnknownCPUType(cputype, cpusubtype); 1362 break; 1363 } 1364 break; 1365 case MachO::CPU_TYPE_ARM64: 1366 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 1367 case MachO::CPU_SUBTYPE_ARM64_ALL: 1368 outs() << " cputype CPU_TYPE_ARM64\n"; 1369 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 1370 break; 1371 default: 1372 printUnknownCPUType(cputype, cpusubtype); 1373 break; 1374 } 1375 break; 1376 default: 1377 printUnknownCPUType(cputype, cpusubtype); 1378 break; 1379 } 1380 } 1381 1382 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 1383 bool verbose) { 1384 outs() << "Fat headers\n"; 1385 if (verbose) { 1386 if (UB->getMagic() == MachO::FAT_MAGIC) 1387 outs() << "fat_magic FAT_MAGIC\n"; 1388 else // UB->getMagic() == MachO::FAT_MAGIC_64 1389 outs() << "fat_magic FAT_MAGIC_64\n"; 1390 } else 1391 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 1392 1393 uint32_t nfat_arch = UB->getNumberOfObjects(); 1394 StringRef Buf = UB->getData(); 1395 uint64_t size = Buf.size(); 1396 uint64_t big_size = sizeof(struct MachO::fat_header) + 1397 nfat_arch * sizeof(struct MachO::fat_arch); 1398 outs() << "nfat_arch " << UB->getNumberOfObjects(); 1399 if (nfat_arch == 0) 1400 outs() << " (malformed, contains zero architecture types)\n"; 1401 else if (big_size > size) 1402 outs() << " (malformed, architectures past end of file)\n"; 1403 else 1404 outs() << "\n"; 1405 1406 for (uint32_t i = 0; i < nfat_arch; ++i) { 1407 MachOUniversalBinary::ObjectForArch OFA(UB, i); 1408 uint32_t cputype = OFA.getCPUType(); 1409 uint32_t cpusubtype = OFA.getCPUSubType(); 1410 outs() << "architecture "; 1411 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 1412 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 1413 uint32_t other_cputype = other_OFA.getCPUType(); 1414 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 1415 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 1416 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 1417 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 1418 outs() << "(illegal duplicate architecture) "; 1419 break; 1420 } 1421 } 1422 if (verbose) { 1423 outs() << OFA.getArchFlagName() << "\n"; 1424 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 1425 } else { 1426 outs() << i << "\n"; 1427 outs() << " cputype " << cputype << "\n"; 1428 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 1429 << "\n"; 1430 } 1431 if (verbose && 1432 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 1433 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 1434 else 1435 outs() << " capabilities " 1436 << format("0x%" PRIx32, 1437 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 1438 outs() << " offset " << OFA.getOffset(); 1439 if (OFA.getOffset() > size) 1440 outs() << " (past end of file)"; 1441 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0) 1442 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 1443 outs() << "\n"; 1444 outs() << " size " << OFA.getSize(); 1445 big_size = OFA.getOffset() + OFA.getSize(); 1446 if (big_size > size) 1447 outs() << " (past end of file)"; 1448 outs() << "\n"; 1449 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 1450 << ")\n"; 1451 } 1452 } 1453 1454 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 1455 bool verbose, bool print_offset, 1456 StringRef ArchitectureName = StringRef()) { 1457 if (print_offset) 1458 outs() << C.getChildOffset() << "\t"; 1459 Expected<sys::fs::perms> ModeOrErr = C.getAccessMode(); 1460 if (!ModeOrErr) 1461 report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName); 1462 sys::fs::perms Mode = ModeOrErr.get(); 1463 if (verbose) { 1464 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 1465 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 1466 outs() << "-"; 1467 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 1468 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 1469 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 1470 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 1471 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 1472 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 1473 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 1474 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 1475 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 1476 } else { 1477 outs() << format("0%o ", Mode); 1478 } 1479 1480 Expected<unsigned> UIDOrErr = C.getUID(); 1481 if (!UIDOrErr) 1482 report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName); 1483 unsigned UID = UIDOrErr.get(); 1484 outs() << format("%3d/", UID); 1485 Expected<unsigned> GIDOrErr = C.getGID(); 1486 if (!GIDOrErr) 1487 report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName); 1488 unsigned GID = GIDOrErr.get(); 1489 outs() << format("%-3d ", GID); 1490 Expected<uint64_t> Size = C.getRawSize(); 1491 if (!Size) 1492 report_error(Filename, C, Size.takeError(), ArchitectureName); 1493 outs() << format("%5" PRId64, Size.get()) << " "; 1494 1495 StringRef RawLastModified = C.getRawLastModified(); 1496 if (verbose) { 1497 unsigned Seconds; 1498 if (RawLastModified.getAsInteger(10, Seconds)) 1499 outs() << "(date: \"" << RawLastModified 1500 << "\" contains non-decimal chars) "; 1501 else { 1502 // Since cime(3) returns a 26 character string of the form: 1503 // "Sun Sep 16 01:03:52 1973\n\0" 1504 // just print 24 characters. 1505 time_t t = Seconds; 1506 outs() << format("%.24s ", ctime(&t)); 1507 } 1508 } else { 1509 outs() << RawLastModified << " "; 1510 } 1511 1512 if (verbose) { 1513 Expected<StringRef> NameOrErr = C.getName(); 1514 if (!NameOrErr) { 1515 consumeError(NameOrErr.takeError()); 1516 Expected<StringRef> NameOrErr = C.getRawName(); 1517 if (!NameOrErr) 1518 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1519 StringRef RawName = NameOrErr.get(); 1520 outs() << RawName << "\n"; 1521 } else { 1522 StringRef Name = NameOrErr.get(); 1523 outs() << Name << "\n"; 1524 } 1525 } else { 1526 Expected<StringRef> NameOrErr = C.getRawName(); 1527 if (!NameOrErr) 1528 report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); 1529 StringRef RawName = NameOrErr.get(); 1530 outs() << RawName << "\n"; 1531 } 1532 } 1533 1534 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 1535 bool print_offset, 1536 StringRef ArchitectureName = StringRef()) { 1537 Error Err = Error::success(); 1538 ; 1539 for (const auto &C : A->children(Err, false)) 1540 printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName); 1541 1542 if (Err) 1543 report_error(StringRef(), Filename, std::move(Err), ArchitectureName); 1544 } 1545 1546 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 1547 // -arch flags selecting just those slices as specified by them and also parses 1548 // archive files. Then for each individual Mach-O file ProcessMachO() is 1549 // called to process the file based on the command line options. 1550 void llvm::ParseInputMachO(StringRef Filename) { 1551 // Check for -arch all and verifiy the -arch flags are valid. 1552 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 1553 if (ArchFlags[i] == "all") { 1554 ArchAll = true; 1555 } else { 1556 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 1557 errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] + 1558 "'for the -arch option\n"; 1559 return; 1560 } 1561 } 1562 } 1563 1564 // Attempt to open the binary. 1565 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 1566 if (!BinaryOrErr) { 1567 if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 1568 report_error(Filename, std::move(E)); 1569 else 1570 outs() << Filename << ": is not an object file\n"; 1571 return; 1572 } 1573 Binary &Bin = *BinaryOrErr.get().getBinary(); 1574 1575 if (Archive *A = dyn_cast<Archive>(&Bin)) { 1576 outs() << "Archive : " << Filename << "\n"; 1577 if (ArchiveHeaders) 1578 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets); 1579 1580 Error Err = Error::success(); 1581 for (auto &C : A->children(Err)) { 1582 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 1583 if (!ChildOrErr) { 1584 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 1585 report_error(Filename, C, std::move(E)); 1586 continue; 1587 } 1588 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 1589 if (!checkMachOAndArchFlags(O, Filename)) 1590 return; 1591 ProcessMachO(Filename, O, O->getFileName()); 1592 } 1593 } 1594 if (Err) 1595 report_error(Filename, std::move(Err)); 1596 return; 1597 } 1598 if (UniversalHeaders) { 1599 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) 1600 printMachOUniversalHeaders(UB, !NonVerbose); 1601 } 1602 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 1603 // If we have a list of architecture flags specified dump only those. 1604 if (!ArchAll && ArchFlags.size() != 0) { 1605 // Look for a slice in the universal binary that matches each ArchFlag. 1606 bool ArchFound; 1607 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 1608 ArchFound = false; 1609 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 1610 E = UB->end_objects(); 1611 I != E; ++I) { 1612 if (ArchFlags[i] == I->getArchFlagName()) { 1613 ArchFound = true; 1614 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 1615 I->getAsObjectFile(); 1616 std::string ArchitectureName = ""; 1617 if (ArchFlags.size() > 1) 1618 ArchitectureName = I->getArchFlagName(); 1619 if (ObjOrErr) { 1620 ObjectFile &O = *ObjOrErr.get(); 1621 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 1622 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 1623 } else if (auto E = isNotObjectErrorInvalidFileType( 1624 ObjOrErr.takeError())) { 1625 report_error(Filename, StringRef(), std::move(E), 1626 ArchitectureName); 1627 continue; 1628 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 1629 I->getAsArchive()) { 1630 std::unique_ptr<Archive> &A = *AOrErr; 1631 outs() << "Archive : " << Filename; 1632 if (!ArchitectureName.empty()) 1633 outs() << " (architecture " << ArchitectureName << ")"; 1634 outs() << "\n"; 1635 if (ArchiveHeaders) 1636 printArchiveHeaders(Filename, A.get(), !NonVerbose, 1637 ArchiveMemberOffsets, ArchitectureName); 1638 Error Err = Error::success(); 1639 for (auto &C : A->children(Err)) { 1640 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 1641 if (!ChildOrErr) { 1642 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 1643 report_error(Filename, C, std::move(E), ArchitectureName); 1644 continue; 1645 } 1646 if (MachOObjectFile *O = 1647 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 1648 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 1649 } 1650 if (Err) 1651 report_error(Filename, std::move(Err)); 1652 } else { 1653 consumeError(AOrErr.takeError()); 1654 error("Mach-O universal file: " + Filename + " for " + 1655 "architecture " + StringRef(I->getArchFlagName()) + 1656 " is not a Mach-O file or an archive file"); 1657 } 1658 } 1659 } 1660 if (!ArchFound) { 1661 errs() << "llvm-objdump: file: " + Filename + " does not contain " 1662 << "architecture: " + ArchFlags[i] + "\n"; 1663 return; 1664 } 1665 } 1666 return; 1667 } 1668 // No architecture flags were specified so if this contains a slice that 1669 // matches the host architecture dump only that. 1670 if (!ArchAll) { 1671 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 1672 E = UB->end_objects(); 1673 I != E; ++I) { 1674 if (MachOObjectFile::getHostArch().getArchName() == 1675 I->getArchFlagName()) { 1676 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 1677 std::string ArchiveName; 1678 ArchiveName.clear(); 1679 if (ObjOrErr) { 1680 ObjectFile &O = *ObjOrErr.get(); 1681 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 1682 ProcessMachO(Filename, MachOOF); 1683 } else if (auto E = isNotObjectErrorInvalidFileType( 1684 ObjOrErr.takeError())) { 1685 report_error(Filename, std::move(E)); 1686 continue; 1687 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 1688 I->getAsArchive()) { 1689 std::unique_ptr<Archive> &A = *AOrErr; 1690 outs() << "Archive : " << Filename << "\n"; 1691 if (ArchiveHeaders) 1692 printArchiveHeaders(Filename, A.get(), !NonVerbose, 1693 ArchiveMemberOffsets); 1694 Error Err = Error::success(); 1695 for (auto &C : A->children(Err)) { 1696 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 1697 if (!ChildOrErr) { 1698 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 1699 report_error(Filename, C, std::move(E)); 1700 continue; 1701 } 1702 if (MachOObjectFile *O = 1703 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 1704 ProcessMachO(Filename, O, O->getFileName()); 1705 } 1706 if (Err) 1707 report_error(Filename, std::move(Err)); 1708 } else { 1709 consumeError(AOrErr.takeError()); 1710 error("Mach-O universal file: " + Filename + " for architecture " + 1711 StringRef(I->getArchFlagName()) + 1712 " is not a Mach-O file or an archive file"); 1713 } 1714 return; 1715 } 1716 } 1717 } 1718 // Either all architectures have been specified or none have been specified 1719 // and this does not contain the host architecture so dump all the slices. 1720 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 1721 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 1722 E = UB->end_objects(); 1723 I != E; ++I) { 1724 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 1725 std::string ArchitectureName = ""; 1726 if (moreThanOneArch) 1727 ArchitectureName = I->getArchFlagName(); 1728 if (ObjOrErr) { 1729 ObjectFile &Obj = *ObjOrErr.get(); 1730 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 1731 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 1732 } else if (auto E = isNotObjectErrorInvalidFileType( 1733 ObjOrErr.takeError())) { 1734 report_error(StringRef(), Filename, std::move(E), ArchitectureName); 1735 continue; 1736 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 1737 I->getAsArchive()) { 1738 std::unique_ptr<Archive> &A = *AOrErr; 1739 outs() << "Archive : " << Filename; 1740 if (!ArchitectureName.empty()) 1741 outs() << " (architecture " << ArchitectureName << ")"; 1742 outs() << "\n"; 1743 if (ArchiveHeaders) 1744 printArchiveHeaders(Filename, A.get(), !NonVerbose, 1745 ArchiveMemberOffsets, ArchitectureName); 1746 Error Err = Error::success(); 1747 for (auto &C : A->children(Err)) { 1748 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 1749 if (!ChildOrErr) { 1750 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 1751 report_error(Filename, C, std::move(E), ArchitectureName); 1752 continue; 1753 } 1754 if (MachOObjectFile *O = 1755 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 1756 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 1757 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 1758 ArchitectureName); 1759 } 1760 } 1761 if (Err) 1762 report_error(Filename, std::move(Err)); 1763 } else { 1764 consumeError(AOrErr.takeError()); 1765 error("Mach-O universal file: " + Filename + " for architecture " + 1766 StringRef(I->getArchFlagName()) + 1767 " is not a Mach-O file or an archive file"); 1768 } 1769 } 1770 return; 1771 } 1772 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 1773 if (!checkMachOAndArchFlags(O, Filename)) 1774 return; 1775 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) { 1776 ProcessMachO(Filename, MachOOF); 1777 } else 1778 errs() << "llvm-objdump: '" << Filename << "': " 1779 << "Object is not a Mach-O file type.\n"; 1780 return; 1781 } 1782 llvm_unreachable("Input object can't be invalid at this point"); 1783 } 1784 1785 // The block of info used by the Symbolizer call backs. 1786 struct DisassembleInfo { 1787 bool verbose; 1788 MachOObjectFile *O; 1789 SectionRef S; 1790 SymbolAddressMap *AddrMap; 1791 std::vector<SectionRef> *Sections; 1792 const char *class_name; 1793 const char *selector_name; 1794 char *method; 1795 char *demangled_name; 1796 uint64_t adrp_addr; 1797 uint32_t adrp_inst; 1798 std::unique_ptr<SymbolAddressMap> bindtable; 1799 uint32_t depth; 1800 }; 1801 1802 // SymbolizerGetOpInfo() is the operand information call back function. 1803 // This is called to get the symbolic information for operand(s) of an 1804 // instruction when it is being done. This routine does this from 1805 // the relocation information, symbol table, etc. That block of information 1806 // is a pointer to the struct DisassembleInfo that was passed when the 1807 // disassembler context was created and passed to back to here when 1808 // called back by the disassembler for instruction operands that could have 1809 // relocation information. The address of the instruction containing operand is 1810 // at the Pc parameter. The immediate value the operand has is passed in 1811 // op_info->Value and is at Offset past the start of the instruction and has a 1812 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 1813 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 1814 // names and addends of the symbolic expression to add for the operand. The 1815 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 1816 // information is returned then this function returns 1 else it returns 0. 1817 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 1818 uint64_t Size, int TagType, void *TagBuf) { 1819 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 1820 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 1821 uint64_t value = op_info->Value; 1822 1823 // Make sure all fields returned are zero if we don't set them. 1824 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 1825 op_info->Value = value; 1826 1827 // If the TagType is not the value 1 which it code knows about or if no 1828 // verbose symbolic information is wanted then just return 0, indicating no 1829 // information is being returned. 1830 if (TagType != 1 || !info->verbose) 1831 return 0; 1832 1833 unsigned int Arch = info->O->getArch(); 1834 if (Arch == Triple::x86) { 1835 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 1836 return 0; 1837 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 1838 // TODO: 1839 // Search the external relocation entries of a fully linked image 1840 // (if any) for an entry that matches this segment offset. 1841 // uint32_t seg_offset = (Pc + Offset); 1842 return 0; 1843 } 1844 // In MH_OBJECT filetypes search the section's relocation entries (if any) 1845 // for an entry for this section offset. 1846 uint32_t sect_addr = info->S.getAddress(); 1847 uint32_t sect_offset = (Pc + Offset) - sect_addr; 1848 bool reloc_found = false; 1849 DataRefImpl Rel; 1850 MachO::any_relocation_info RE; 1851 bool isExtern = false; 1852 SymbolRef Symbol; 1853 bool r_scattered = false; 1854 uint32_t r_value, pair_r_value, r_type; 1855 for (const RelocationRef &Reloc : info->S.relocations()) { 1856 uint64_t RelocOffset = Reloc.getOffset(); 1857 if (RelocOffset == sect_offset) { 1858 Rel = Reloc.getRawDataRefImpl(); 1859 RE = info->O->getRelocation(Rel); 1860 r_type = info->O->getAnyRelocationType(RE); 1861 r_scattered = info->O->isRelocationScattered(RE); 1862 if (r_scattered) { 1863 r_value = info->O->getScatteredRelocationValue(RE); 1864 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 1865 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 1866 DataRefImpl RelNext = Rel; 1867 info->O->moveRelocationNext(RelNext); 1868 MachO::any_relocation_info RENext; 1869 RENext = info->O->getRelocation(RelNext); 1870 if (info->O->isRelocationScattered(RENext)) 1871 pair_r_value = info->O->getScatteredRelocationValue(RENext); 1872 else 1873 return 0; 1874 } 1875 } else { 1876 isExtern = info->O->getPlainRelocationExternal(RE); 1877 if (isExtern) { 1878 symbol_iterator RelocSym = Reloc.getSymbol(); 1879 Symbol = *RelocSym; 1880 } 1881 } 1882 reloc_found = true; 1883 break; 1884 } 1885 } 1886 if (reloc_found && isExtern) { 1887 Expected<StringRef> SymName = Symbol.getName(); 1888 if (!SymName) 1889 report_error(info->O->getFileName(), SymName.takeError()); 1890 const char *name = SymName->data(); 1891 op_info->AddSymbol.Present = 1; 1892 op_info->AddSymbol.Name = name; 1893 // For i386 extern relocation entries the value in the instruction is 1894 // the offset from the symbol, and value is already set in op_info->Value. 1895 return 1; 1896 } 1897 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 1898 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 1899 const char *add = GuessSymbolName(r_value, info->AddrMap); 1900 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 1901 uint32_t offset = value - (r_value - pair_r_value); 1902 op_info->AddSymbol.Present = 1; 1903 if (add != nullptr) 1904 op_info->AddSymbol.Name = add; 1905 else 1906 op_info->AddSymbol.Value = r_value; 1907 op_info->SubtractSymbol.Present = 1; 1908 if (sub != nullptr) 1909 op_info->SubtractSymbol.Name = sub; 1910 else 1911 op_info->SubtractSymbol.Value = pair_r_value; 1912 op_info->Value = offset; 1913 return 1; 1914 } 1915 return 0; 1916 } 1917 if (Arch == Triple::x86_64) { 1918 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 1919 return 0; 1920 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 1921 // TODO: 1922 // Search the external relocation entries of a fully linked image 1923 // (if any) for an entry that matches this segment offset. 1924 // uint64_t seg_offset = (Pc + Offset); 1925 return 0; 1926 } 1927 // In MH_OBJECT filetypes search the section's relocation entries (if any) 1928 // for an entry for this section offset. 1929 uint64_t sect_addr = info->S.getAddress(); 1930 uint64_t sect_offset = (Pc + Offset) - sect_addr; 1931 bool reloc_found = false; 1932 DataRefImpl Rel; 1933 MachO::any_relocation_info RE; 1934 bool isExtern = false; 1935 SymbolRef Symbol; 1936 for (const RelocationRef &Reloc : info->S.relocations()) { 1937 uint64_t RelocOffset = Reloc.getOffset(); 1938 if (RelocOffset == sect_offset) { 1939 Rel = Reloc.getRawDataRefImpl(); 1940 RE = info->O->getRelocation(Rel); 1941 // NOTE: Scattered relocations don't exist on x86_64. 1942 isExtern = info->O->getPlainRelocationExternal(RE); 1943 if (isExtern) { 1944 symbol_iterator RelocSym = Reloc.getSymbol(); 1945 Symbol = *RelocSym; 1946 } 1947 reloc_found = true; 1948 break; 1949 } 1950 } 1951 if (reloc_found && isExtern) { 1952 // The Value passed in will be adjusted by the Pc if the instruction 1953 // adds the Pc. But for x86_64 external relocation entries the Value 1954 // is the offset from the external symbol. 1955 if (info->O->getAnyRelocationPCRel(RE)) 1956 op_info->Value -= Pc + Offset + Size; 1957 Expected<StringRef> SymName = Symbol.getName(); 1958 if (!SymName) 1959 report_error(info->O->getFileName(), SymName.takeError()); 1960 const char *name = SymName->data(); 1961 unsigned Type = info->O->getAnyRelocationType(RE); 1962 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 1963 DataRefImpl RelNext = Rel; 1964 info->O->moveRelocationNext(RelNext); 1965 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 1966 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 1967 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 1968 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 1969 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 1970 op_info->SubtractSymbol.Present = 1; 1971 op_info->SubtractSymbol.Name = name; 1972 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 1973 Symbol = *RelocSymNext; 1974 Expected<StringRef> SymNameNext = Symbol.getName(); 1975 if (!SymNameNext) 1976 report_error(info->O->getFileName(), SymNameNext.takeError()); 1977 name = SymNameNext->data(); 1978 } 1979 } 1980 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 1981 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 1982 op_info->AddSymbol.Present = 1; 1983 op_info->AddSymbol.Name = name; 1984 return 1; 1985 } 1986 return 0; 1987 } 1988 if (Arch == Triple::arm) { 1989 if (Offset != 0 || (Size != 4 && Size != 2)) 1990 return 0; 1991 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 1992 // TODO: 1993 // Search the external relocation entries of a fully linked image 1994 // (if any) for an entry that matches this segment offset. 1995 // uint32_t seg_offset = (Pc + Offset); 1996 return 0; 1997 } 1998 // In MH_OBJECT filetypes search the section's relocation entries (if any) 1999 // for an entry for this section offset. 2000 uint32_t sect_addr = info->S.getAddress(); 2001 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2002 DataRefImpl Rel; 2003 MachO::any_relocation_info RE; 2004 bool isExtern = false; 2005 SymbolRef Symbol; 2006 bool r_scattered = false; 2007 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 2008 auto Reloc = 2009 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2010 uint64_t RelocOffset = Reloc.getOffset(); 2011 return RelocOffset == sect_offset; 2012 }); 2013 2014 if (Reloc == info->S.relocations().end()) 2015 return 0; 2016 2017 Rel = Reloc->getRawDataRefImpl(); 2018 RE = info->O->getRelocation(Rel); 2019 r_length = info->O->getAnyRelocationLength(RE); 2020 r_scattered = info->O->isRelocationScattered(RE); 2021 if (r_scattered) { 2022 r_value = info->O->getScatteredRelocationValue(RE); 2023 r_type = info->O->getScatteredRelocationType(RE); 2024 } else { 2025 r_type = info->O->getAnyRelocationType(RE); 2026 isExtern = info->O->getPlainRelocationExternal(RE); 2027 if (isExtern) { 2028 symbol_iterator RelocSym = Reloc->getSymbol(); 2029 Symbol = *RelocSym; 2030 } 2031 } 2032 if (r_type == MachO::ARM_RELOC_HALF || 2033 r_type == MachO::ARM_RELOC_SECTDIFF || 2034 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 2035 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2036 DataRefImpl RelNext = Rel; 2037 info->O->moveRelocationNext(RelNext); 2038 MachO::any_relocation_info RENext; 2039 RENext = info->O->getRelocation(RelNext); 2040 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 2041 if (info->O->isRelocationScattered(RENext)) 2042 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2043 } 2044 2045 if (isExtern) { 2046 Expected<StringRef> SymName = Symbol.getName(); 2047 if (!SymName) 2048 report_error(info->O->getFileName(), SymName.takeError()); 2049 const char *name = SymName->data(); 2050 op_info->AddSymbol.Present = 1; 2051 op_info->AddSymbol.Name = name; 2052 switch (r_type) { 2053 case MachO::ARM_RELOC_HALF: 2054 if ((r_length & 0x1) == 1) { 2055 op_info->Value = value << 16 | other_half; 2056 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2057 } else { 2058 op_info->Value = other_half << 16 | value; 2059 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2060 } 2061 break; 2062 default: 2063 break; 2064 } 2065 return 1; 2066 } 2067 // If we have a branch that is not an external relocation entry then 2068 // return 0 so the code in tryAddingSymbolicOperand() can use the 2069 // SymbolLookUp call back with the branch target address to look up the 2070 // symbol and possibility add an annotation for a symbol stub. 2071 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 2072 r_type == MachO::ARM_THUMB_RELOC_BR22)) 2073 return 0; 2074 2075 uint32_t offset = 0; 2076 if (r_type == MachO::ARM_RELOC_HALF || 2077 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2078 if ((r_length & 0x1) == 1) 2079 value = value << 16 | other_half; 2080 else 2081 value = other_half << 16 | value; 2082 } 2083 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 2084 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 2085 offset = value - r_value; 2086 value = r_value; 2087 } 2088 2089 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2090 if ((r_length & 0x1) == 1) 2091 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2092 else 2093 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2094 const char *add = GuessSymbolName(r_value, info->AddrMap); 2095 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2096 int32_t offset = value - (r_value - pair_r_value); 2097 op_info->AddSymbol.Present = 1; 2098 if (add != nullptr) 2099 op_info->AddSymbol.Name = add; 2100 else 2101 op_info->AddSymbol.Value = r_value; 2102 op_info->SubtractSymbol.Present = 1; 2103 if (sub != nullptr) 2104 op_info->SubtractSymbol.Name = sub; 2105 else 2106 op_info->SubtractSymbol.Value = pair_r_value; 2107 op_info->Value = offset; 2108 return 1; 2109 } 2110 2111 op_info->AddSymbol.Present = 1; 2112 op_info->Value = offset; 2113 if (r_type == MachO::ARM_RELOC_HALF) { 2114 if ((r_length & 0x1) == 1) 2115 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2116 else 2117 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2118 } 2119 const char *add = GuessSymbolName(value, info->AddrMap); 2120 if (add != nullptr) { 2121 op_info->AddSymbol.Name = add; 2122 return 1; 2123 } 2124 op_info->AddSymbol.Value = value; 2125 return 1; 2126 } 2127 if (Arch == Triple::aarch64) { 2128 if (Offset != 0 || Size != 4) 2129 return 0; 2130 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2131 // TODO: 2132 // Search the external relocation entries of a fully linked image 2133 // (if any) for an entry that matches this segment offset. 2134 // uint64_t seg_offset = (Pc + Offset); 2135 return 0; 2136 } 2137 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2138 // for an entry for this section offset. 2139 uint64_t sect_addr = info->S.getAddress(); 2140 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2141 auto Reloc = 2142 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2143 uint64_t RelocOffset = Reloc.getOffset(); 2144 return RelocOffset == sect_offset; 2145 }); 2146 2147 if (Reloc == info->S.relocations().end()) 2148 return 0; 2149 2150 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2151 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 2152 uint32_t r_type = info->O->getAnyRelocationType(RE); 2153 if (r_type == MachO::ARM64_RELOC_ADDEND) { 2154 DataRefImpl RelNext = Rel; 2155 info->O->moveRelocationNext(RelNext); 2156 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2157 if (value == 0) { 2158 value = info->O->getPlainRelocationSymbolNum(RENext); 2159 op_info->Value = value; 2160 } 2161 } 2162 // NOTE: Scattered relocations don't exist on arm64. 2163 if (!info->O->getPlainRelocationExternal(RE)) 2164 return 0; 2165 Expected<StringRef> SymName = Reloc->getSymbol()->getName(); 2166 if (!SymName) 2167 report_error(info->O->getFileName(), SymName.takeError()); 2168 const char *name = SymName->data(); 2169 op_info->AddSymbol.Present = 1; 2170 op_info->AddSymbol.Name = name; 2171 2172 switch (r_type) { 2173 case MachO::ARM64_RELOC_PAGE21: 2174 /* @page */ 2175 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 2176 break; 2177 case MachO::ARM64_RELOC_PAGEOFF12: 2178 /* @pageoff */ 2179 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 2180 break; 2181 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 2182 /* @gotpage */ 2183 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 2184 break; 2185 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 2186 /* @gotpageoff */ 2187 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 2188 break; 2189 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 2190 /* @tvlppage is not implemented in llvm-mc */ 2191 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 2192 break; 2193 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 2194 /* @tvlppageoff is not implemented in llvm-mc */ 2195 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 2196 break; 2197 default: 2198 case MachO::ARM64_RELOC_BRANCH26: 2199 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 2200 break; 2201 } 2202 return 1; 2203 } 2204 return 0; 2205 } 2206 2207 // GuessCstringPointer is passed the address of what might be a pointer to a 2208 // literal string in a cstring section. If that address is in a cstring section 2209 // it returns a pointer to that string. Else it returns nullptr. 2210 static const char *GuessCstringPointer(uint64_t ReferenceValue, 2211 struct DisassembleInfo *info) { 2212 for (const auto &Load : info->O->load_commands()) { 2213 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2214 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2215 for (unsigned J = 0; J < Seg.nsects; ++J) { 2216 MachO::section_64 Sec = info->O->getSection64(Load, J); 2217 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2218 if (section_type == MachO::S_CSTRING_LITERALS && 2219 ReferenceValue >= Sec.addr && 2220 ReferenceValue < Sec.addr + Sec.size) { 2221 uint64_t sect_offset = ReferenceValue - Sec.addr; 2222 uint64_t object_offset = Sec.offset + sect_offset; 2223 StringRef MachOContents = info->O->getData(); 2224 uint64_t object_size = MachOContents.size(); 2225 const char *object_addr = (const char *)MachOContents.data(); 2226 if (object_offset < object_size) { 2227 const char *name = object_addr + object_offset; 2228 return name; 2229 } else { 2230 return nullptr; 2231 } 2232 } 2233 } 2234 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2235 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2236 for (unsigned J = 0; J < Seg.nsects; ++J) { 2237 MachO::section Sec = info->O->getSection(Load, J); 2238 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2239 if (section_type == MachO::S_CSTRING_LITERALS && 2240 ReferenceValue >= Sec.addr && 2241 ReferenceValue < Sec.addr + Sec.size) { 2242 uint64_t sect_offset = ReferenceValue - Sec.addr; 2243 uint64_t object_offset = Sec.offset + sect_offset; 2244 StringRef MachOContents = info->O->getData(); 2245 uint64_t object_size = MachOContents.size(); 2246 const char *object_addr = (const char *)MachOContents.data(); 2247 if (object_offset < object_size) { 2248 const char *name = object_addr + object_offset; 2249 return name; 2250 } else { 2251 return nullptr; 2252 } 2253 } 2254 } 2255 } 2256 } 2257 return nullptr; 2258 } 2259 2260 // GuessIndirectSymbol returns the name of the indirect symbol for the 2261 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 2262 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 2263 // symbol name being referenced by the stub or pointer. 2264 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 2265 struct DisassembleInfo *info) { 2266 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 2267 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 2268 for (const auto &Load : info->O->load_commands()) { 2269 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2270 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2271 for (unsigned J = 0; J < Seg.nsects; ++J) { 2272 MachO::section_64 Sec = info->O->getSection64(Load, J); 2273 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2274 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2275 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2276 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2277 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2278 section_type == MachO::S_SYMBOL_STUBS) && 2279 ReferenceValue >= Sec.addr && 2280 ReferenceValue < Sec.addr + Sec.size) { 2281 uint32_t stride; 2282 if (section_type == MachO::S_SYMBOL_STUBS) 2283 stride = Sec.reserved2; 2284 else 2285 stride = 8; 2286 if (stride == 0) 2287 return nullptr; 2288 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2289 if (index < Dysymtab.nindirectsyms) { 2290 uint32_t indirect_symbol = 2291 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2292 if (indirect_symbol < Symtab.nsyms) { 2293 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2294 SymbolRef Symbol = *Sym; 2295 Expected<StringRef> SymName = Symbol.getName(); 2296 if (!SymName) 2297 report_error(info->O->getFileName(), SymName.takeError()); 2298 const char *name = SymName->data(); 2299 return name; 2300 } 2301 } 2302 } 2303 } 2304 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2305 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2306 for (unsigned J = 0; J < Seg.nsects; ++J) { 2307 MachO::section Sec = info->O->getSection(Load, J); 2308 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2309 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2310 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2311 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2312 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2313 section_type == MachO::S_SYMBOL_STUBS) && 2314 ReferenceValue >= Sec.addr && 2315 ReferenceValue < Sec.addr + Sec.size) { 2316 uint32_t stride; 2317 if (section_type == MachO::S_SYMBOL_STUBS) 2318 stride = Sec.reserved2; 2319 else 2320 stride = 4; 2321 if (stride == 0) 2322 return nullptr; 2323 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2324 if (index < Dysymtab.nindirectsyms) { 2325 uint32_t indirect_symbol = 2326 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2327 if (indirect_symbol < Symtab.nsyms) { 2328 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2329 SymbolRef Symbol = *Sym; 2330 Expected<StringRef> SymName = Symbol.getName(); 2331 if (!SymName) 2332 report_error(info->O->getFileName(), SymName.takeError()); 2333 const char *name = SymName->data(); 2334 return name; 2335 } 2336 } 2337 } 2338 } 2339 } 2340 } 2341 return nullptr; 2342 } 2343 2344 // method_reference() is called passing it the ReferenceName that might be 2345 // a reference it to an Objective-C method call. If so then it allocates and 2346 // assembles a method call string with the values last seen and saved in 2347 // the DisassembleInfo's class_name and selector_name fields. This is saved 2348 // into the method field of the info and any previous string is free'ed. 2349 // Then the class_name field in the info is set to nullptr. The method call 2350 // string is set into ReferenceName and ReferenceType is set to 2351 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 2352 // then both ReferenceType and ReferenceName are left unchanged. 2353 static void method_reference(struct DisassembleInfo *info, 2354 uint64_t *ReferenceType, 2355 const char **ReferenceName) { 2356 unsigned int Arch = info->O->getArch(); 2357 if (*ReferenceName != nullptr) { 2358 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 2359 if (info->selector_name != nullptr) { 2360 if (info->method != nullptr) 2361 free(info->method); 2362 if (info->class_name != nullptr) { 2363 info->method = (char *)malloc(5 + strlen(info->class_name) + 2364 strlen(info->selector_name)); 2365 if (info->method != nullptr) { 2366 strcpy(info->method, "+["); 2367 strcat(info->method, info->class_name); 2368 strcat(info->method, " "); 2369 strcat(info->method, info->selector_name); 2370 strcat(info->method, "]"); 2371 *ReferenceName = info->method; 2372 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2373 } 2374 } else { 2375 info->method = (char *)malloc(9 + strlen(info->selector_name)); 2376 if (info->method != nullptr) { 2377 if (Arch == Triple::x86_64) 2378 strcpy(info->method, "-[%rdi "); 2379 else if (Arch == Triple::aarch64) 2380 strcpy(info->method, "-[x0 "); 2381 else 2382 strcpy(info->method, "-[r? "); 2383 strcat(info->method, info->selector_name); 2384 strcat(info->method, "]"); 2385 *ReferenceName = info->method; 2386 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2387 } 2388 } 2389 info->class_name = nullptr; 2390 } 2391 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 2392 if (info->selector_name != nullptr) { 2393 if (info->method != nullptr) 2394 free(info->method); 2395 info->method = (char *)malloc(17 + strlen(info->selector_name)); 2396 if (info->method != nullptr) { 2397 if (Arch == Triple::x86_64) 2398 strcpy(info->method, "-[[%rdi super] "); 2399 else if (Arch == Triple::aarch64) 2400 strcpy(info->method, "-[[x0 super] "); 2401 else 2402 strcpy(info->method, "-[[r? super] "); 2403 strcat(info->method, info->selector_name); 2404 strcat(info->method, "]"); 2405 *ReferenceName = info->method; 2406 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2407 } 2408 info->class_name = nullptr; 2409 } 2410 } 2411 } 2412 } 2413 2414 // GuessPointerPointer() is passed the address of what might be a pointer to 2415 // a reference to an Objective-C class, selector, message ref or cfstring. 2416 // If so the value of the pointer is returned and one of the booleans are set 2417 // to true. If not zero is returned and all the booleans are set to false. 2418 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 2419 struct DisassembleInfo *info, 2420 bool &classref, bool &selref, bool &msgref, 2421 bool &cfstring) { 2422 classref = false; 2423 selref = false; 2424 msgref = false; 2425 cfstring = false; 2426 for (const auto &Load : info->O->load_commands()) { 2427 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2428 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2429 for (unsigned J = 0; J < Seg.nsects; ++J) { 2430 MachO::section_64 Sec = info->O->getSection64(Load, J); 2431 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 2432 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2433 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 2434 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 2435 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 2436 ReferenceValue >= Sec.addr && 2437 ReferenceValue < Sec.addr + Sec.size) { 2438 uint64_t sect_offset = ReferenceValue - Sec.addr; 2439 uint64_t object_offset = Sec.offset + sect_offset; 2440 StringRef MachOContents = info->O->getData(); 2441 uint64_t object_size = MachOContents.size(); 2442 const char *object_addr = (const char *)MachOContents.data(); 2443 if (object_offset < object_size) { 2444 uint64_t pointer_value; 2445 memcpy(&pointer_value, object_addr + object_offset, 2446 sizeof(uint64_t)); 2447 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2448 sys::swapByteOrder(pointer_value); 2449 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 2450 selref = true; 2451 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2452 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 2453 classref = true; 2454 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 2455 ReferenceValue + 8 < Sec.addr + Sec.size) { 2456 msgref = true; 2457 memcpy(&pointer_value, object_addr + object_offset + 8, 2458 sizeof(uint64_t)); 2459 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2460 sys::swapByteOrder(pointer_value); 2461 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 2462 cfstring = true; 2463 return pointer_value; 2464 } else { 2465 return 0; 2466 } 2467 } 2468 } 2469 } 2470 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 2471 } 2472 return 0; 2473 } 2474 2475 // get_pointer_64 returns a pointer to the bytes in the object file at the 2476 // Address from a section in the Mach-O file. And indirectly returns the 2477 // offset into the section, number of bytes left in the section past the offset 2478 // and which section is was being referenced. If the Address is not in a 2479 // section nullptr is returned. 2480 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 2481 uint32_t &left, SectionRef &S, 2482 DisassembleInfo *info, 2483 bool objc_only = false) { 2484 offset = 0; 2485 left = 0; 2486 S = SectionRef(); 2487 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 2488 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 2489 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 2490 if (SectSize == 0) 2491 continue; 2492 if (objc_only) { 2493 StringRef SectName; 2494 ((*(info->Sections))[SectIdx]).getName(SectName); 2495 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 2496 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 2497 if (SegName != "__OBJC" && SectName != "__cstring") 2498 continue; 2499 } 2500 if (Address >= SectAddress && Address < SectAddress + SectSize) { 2501 S = (*(info->Sections))[SectIdx]; 2502 offset = Address - SectAddress; 2503 left = SectSize - offset; 2504 StringRef SectContents; 2505 ((*(info->Sections))[SectIdx]).getContents(SectContents); 2506 return SectContents.data() + offset; 2507 } 2508 } 2509 return nullptr; 2510 } 2511 2512 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 2513 uint32_t &left, SectionRef &S, 2514 DisassembleInfo *info, 2515 bool objc_only = false) { 2516 return get_pointer_64(Address, offset, left, S, info, objc_only); 2517 } 2518 2519 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 2520 // the symbol indirectly through n_value. Based on the relocation information 2521 // for the specified section offset in the specified section reference. 2522 // If no relocation information is found and a non-zero ReferenceValue for the 2523 // symbol is passed, look up that address in the info's AddrMap. 2524 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 2525 DisassembleInfo *info, uint64_t &n_value, 2526 uint64_t ReferenceValue = 0) { 2527 n_value = 0; 2528 if (!info->verbose) 2529 return nullptr; 2530 2531 // See if there is an external relocation entry at the sect_offset. 2532 bool reloc_found = false; 2533 DataRefImpl Rel; 2534 MachO::any_relocation_info RE; 2535 bool isExtern = false; 2536 SymbolRef Symbol; 2537 for (const RelocationRef &Reloc : S.relocations()) { 2538 uint64_t RelocOffset = Reloc.getOffset(); 2539 if (RelocOffset == sect_offset) { 2540 Rel = Reloc.getRawDataRefImpl(); 2541 RE = info->O->getRelocation(Rel); 2542 if (info->O->isRelocationScattered(RE)) 2543 continue; 2544 isExtern = info->O->getPlainRelocationExternal(RE); 2545 if (isExtern) { 2546 symbol_iterator RelocSym = Reloc.getSymbol(); 2547 Symbol = *RelocSym; 2548 } 2549 reloc_found = true; 2550 break; 2551 } 2552 } 2553 // If there is an external relocation entry for a symbol in this section 2554 // at this section_offset then use that symbol's value for the n_value 2555 // and return its name. 2556 const char *SymbolName = nullptr; 2557 if (reloc_found && isExtern) { 2558 n_value = Symbol.getValue(); 2559 Expected<StringRef> NameOrError = Symbol.getName(); 2560 if (!NameOrError) 2561 report_error(info->O->getFileName(), NameOrError.takeError()); 2562 StringRef Name = *NameOrError; 2563 if (!Name.empty()) { 2564 SymbolName = Name.data(); 2565 return SymbolName; 2566 } 2567 } 2568 2569 // TODO: For fully linked images, look through the external relocation 2570 // entries off the dynamic symtab command. For these the r_offset is from the 2571 // start of the first writeable segment in the Mach-O file. So the offset 2572 // to this section from that segment is passed to this routine by the caller, 2573 // as the database_offset. Which is the difference of the section's starting 2574 // address and the first writable segment. 2575 // 2576 // NOTE: need add passing the database_offset to this routine. 2577 2578 // We did not find an external relocation entry so look up the ReferenceValue 2579 // as an address of a symbol and if found return that symbol's name. 2580 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 2581 2582 return SymbolName; 2583 } 2584 2585 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 2586 DisassembleInfo *info, 2587 uint32_t ReferenceValue) { 2588 uint64_t n_value64; 2589 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 2590 } 2591 2592 // These are structs in the Objective-C meta data and read to produce the 2593 // comments for disassembly. While these are part of the ABI they are no 2594 // public defintions. So the are here not in include/llvm/Support/MachO.h . 2595 2596 // The cfstring object in a 64-bit Mach-O file. 2597 struct cfstring64_t { 2598 uint64_t isa; // class64_t * (64-bit pointer) 2599 uint64_t flags; // flag bits 2600 uint64_t characters; // char * (64-bit pointer) 2601 uint64_t length; // number of non-NULL characters in above 2602 }; 2603 2604 // The class object in a 64-bit Mach-O file. 2605 struct class64_t { 2606 uint64_t isa; // class64_t * (64-bit pointer) 2607 uint64_t superclass; // class64_t * (64-bit pointer) 2608 uint64_t cache; // Cache (64-bit pointer) 2609 uint64_t vtable; // IMP * (64-bit pointer) 2610 uint64_t data; // class_ro64_t * (64-bit pointer) 2611 }; 2612 2613 struct class32_t { 2614 uint32_t isa; /* class32_t * (32-bit pointer) */ 2615 uint32_t superclass; /* class32_t * (32-bit pointer) */ 2616 uint32_t cache; /* Cache (32-bit pointer) */ 2617 uint32_t vtable; /* IMP * (32-bit pointer) */ 2618 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 2619 }; 2620 2621 struct class_ro64_t { 2622 uint32_t flags; 2623 uint32_t instanceStart; 2624 uint32_t instanceSize; 2625 uint32_t reserved; 2626 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 2627 uint64_t name; // const char * (64-bit pointer) 2628 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 2629 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 2630 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 2631 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 2632 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 2633 }; 2634 2635 struct class_ro32_t { 2636 uint32_t flags; 2637 uint32_t instanceStart; 2638 uint32_t instanceSize; 2639 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 2640 uint32_t name; /* const char * (32-bit pointer) */ 2641 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 2642 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 2643 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 2644 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 2645 uint32_t baseProperties; /* const struct objc_property_list * 2646 (32-bit pointer) */ 2647 }; 2648 2649 /* Values for class_ro{64,32}_t->flags */ 2650 #define RO_META (1 << 0) 2651 #define RO_ROOT (1 << 1) 2652 #define RO_HAS_CXX_STRUCTORS (1 << 2) 2653 2654 struct method_list64_t { 2655 uint32_t entsize; 2656 uint32_t count; 2657 /* struct method64_t first; These structures follow inline */ 2658 }; 2659 2660 struct method_list32_t { 2661 uint32_t entsize; 2662 uint32_t count; 2663 /* struct method32_t first; These structures follow inline */ 2664 }; 2665 2666 struct method64_t { 2667 uint64_t name; /* SEL (64-bit pointer) */ 2668 uint64_t types; /* const char * (64-bit pointer) */ 2669 uint64_t imp; /* IMP (64-bit pointer) */ 2670 }; 2671 2672 struct method32_t { 2673 uint32_t name; /* SEL (32-bit pointer) */ 2674 uint32_t types; /* const char * (32-bit pointer) */ 2675 uint32_t imp; /* IMP (32-bit pointer) */ 2676 }; 2677 2678 struct protocol_list64_t { 2679 uint64_t count; /* uintptr_t (a 64-bit value) */ 2680 /* struct protocol64_t * list[0]; These pointers follow inline */ 2681 }; 2682 2683 struct protocol_list32_t { 2684 uint32_t count; /* uintptr_t (a 32-bit value) */ 2685 /* struct protocol32_t * list[0]; These pointers follow inline */ 2686 }; 2687 2688 struct protocol64_t { 2689 uint64_t isa; /* id * (64-bit pointer) */ 2690 uint64_t name; /* const char * (64-bit pointer) */ 2691 uint64_t protocols; /* struct protocol_list64_t * 2692 (64-bit pointer) */ 2693 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 2694 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 2695 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 2696 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 2697 uint64_t instanceProperties; /* struct objc_property_list * 2698 (64-bit pointer) */ 2699 }; 2700 2701 struct protocol32_t { 2702 uint32_t isa; /* id * (32-bit pointer) */ 2703 uint32_t name; /* const char * (32-bit pointer) */ 2704 uint32_t protocols; /* struct protocol_list_t * 2705 (32-bit pointer) */ 2706 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 2707 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 2708 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 2709 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 2710 uint32_t instanceProperties; /* struct objc_property_list * 2711 (32-bit pointer) */ 2712 }; 2713 2714 struct ivar_list64_t { 2715 uint32_t entsize; 2716 uint32_t count; 2717 /* struct ivar64_t first; These structures follow inline */ 2718 }; 2719 2720 struct ivar_list32_t { 2721 uint32_t entsize; 2722 uint32_t count; 2723 /* struct ivar32_t first; These structures follow inline */ 2724 }; 2725 2726 struct ivar64_t { 2727 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 2728 uint64_t name; /* const char * (64-bit pointer) */ 2729 uint64_t type; /* const char * (64-bit pointer) */ 2730 uint32_t alignment; 2731 uint32_t size; 2732 }; 2733 2734 struct ivar32_t { 2735 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 2736 uint32_t name; /* const char * (32-bit pointer) */ 2737 uint32_t type; /* const char * (32-bit pointer) */ 2738 uint32_t alignment; 2739 uint32_t size; 2740 }; 2741 2742 struct objc_property_list64 { 2743 uint32_t entsize; 2744 uint32_t count; 2745 /* struct objc_property64 first; These structures follow inline */ 2746 }; 2747 2748 struct objc_property_list32 { 2749 uint32_t entsize; 2750 uint32_t count; 2751 /* struct objc_property32 first; These structures follow inline */ 2752 }; 2753 2754 struct objc_property64 { 2755 uint64_t name; /* const char * (64-bit pointer) */ 2756 uint64_t attributes; /* const char * (64-bit pointer) */ 2757 }; 2758 2759 struct objc_property32 { 2760 uint32_t name; /* const char * (32-bit pointer) */ 2761 uint32_t attributes; /* const char * (32-bit pointer) */ 2762 }; 2763 2764 struct category64_t { 2765 uint64_t name; /* const char * (64-bit pointer) */ 2766 uint64_t cls; /* struct class_t * (64-bit pointer) */ 2767 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 2768 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 2769 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 2770 uint64_t instanceProperties; /* struct objc_property_list * 2771 (64-bit pointer) */ 2772 }; 2773 2774 struct category32_t { 2775 uint32_t name; /* const char * (32-bit pointer) */ 2776 uint32_t cls; /* struct class_t * (32-bit pointer) */ 2777 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 2778 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 2779 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 2780 uint32_t instanceProperties; /* struct objc_property_list * 2781 (32-bit pointer) */ 2782 }; 2783 2784 struct objc_image_info64 { 2785 uint32_t version; 2786 uint32_t flags; 2787 }; 2788 struct objc_image_info32 { 2789 uint32_t version; 2790 uint32_t flags; 2791 }; 2792 struct imageInfo_t { 2793 uint32_t version; 2794 uint32_t flags; 2795 }; 2796 /* masks for objc_image_info.flags */ 2797 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 2798 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 2799 2800 struct message_ref64 { 2801 uint64_t imp; /* IMP (64-bit pointer) */ 2802 uint64_t sel; /* SEL (64-bit pointer) */ 2803 }; 2804 2805 struct message_ref32 { 2806 uint32_t imp; /* IMP (32-bit pointer) */ 2807 uint32_t sel; /* SEL (32-bit pointer) */ 2808 }; 2809 2810 // Objective-C 1 (32-bit only) meta data structs. 2811 2812 struct objc_module_t { 2813 uint32_t version; 2814 uint32_t size; 2815 uint32_t name; /* char * (32-bit pointer) */ 2816 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 2817 }; 2818 2819 struct objc_symtab_t { 2820 uint32_t sel_ref_cnt; 2821 uint32_t refs; /* SEL * (32-bit pointer) */ 2822 uint16_t cls_def_cnt; 2823 uint16_t cat_def_cnt; 2824 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 2825 }; 2826 2827 struct objc_class_t { 2828 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 2829 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 2830 uint32_t name; /* const char * (32-bit pointer) */ 2831 int32_t version; 2832 int32_t info; 2833 int32_t instance_size; 2834 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 2835 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 2836 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 2837 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 2838 }; 2839 2840 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 2841 // class is not a metaclass 2842 #define CLS_CLASS 0x1 2843 // class is a metaclass 2844 #define CLS_META 0x2 2845 2846 struct objc_category_t { 2847 uint32_t category_name; /* char * (32-bit pointer) */ 2848 uint32_t class_name; /* char * (32-bit pointer) */ 2849 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 2850 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 2851 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 2852 }; 2853 2854 struct objc_ivar_t { 2855 uint32_t ivar_name; /* char * (32-bit pointer) */ 2856 uint32_t ivar_type; /* char * (32-bit pointer) */ 2857 int32_t ivar_offset; 2858 }; 2859 2860 struct objc_ivar_list_t { 2861 int32_t ivar_count; 2862 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 2863 }; 2864 2865 struct objc_method_list_t { 2866 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 2867 int32_t method_count; 2868 // struct objc_method_t method_list[1]; /* variable length structure */ 2869 }; 2870 2871 struct objc_method_t { 2872 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 2873 uint32_t method_types; /* char * (32-bit pointer) */ 2874 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 2875 (32-bit pointer) */ 2876 }; 2877 2878 struct objc_protocol_list_t { 2879 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 2880 int32_t count; 2881 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 2882 // (32-bit pointer) */ 2883 }; 2884 2885 struct objc_protocol_t { 2886 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 2887 uint32_t protocol_name; /* char * (32-bit pointer) */ 2888 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 2889 uint32_t instance_methods; /* struct objc_method_description_list * 2890 (32-bit pointer) */ 2891 uint32_t class_methods; /* struct objc_method_description_list * 2892 (32-bit pointer) */ 2893 }; 2894 2895 struct objc_method_description_list_t { 2896 int32_t count; 2897 // struct objc_method_description_t list[1]; 2898 }; 2899 2900 struct objc_method_description_t { 2901 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 2902 uint32_t types; /* char * (32-bit pointer) */ 2903 }; 2904 2905 inline void swapStruct(struct cfstring64_t &cfs) { 2906 sys::swapByteOrder(cfs.isa); 2907 sys::swapByteOrder(cfs.flags); 2908 sys::swapByteOrder(cfs.characters); 2909 sys::swapByteOrder(cfs.length); 2910 } 2911 2912 inline void swapStruct(struct class64_t &c) { 2913 sys::swapByteOrder(c.isa); 2914 sys::swapByteOrder(c.superclass); 2915 sys::swapByteOrder(c.cache); 2916 sys::swapByteOrder(c.vtable); 2917 sys::swapByteOrder(c.data); 2918 } 2919 2920 inline void swapStruct(struct class32_t &c) { 2921 sys::swapByteOrder(c.isa); 2922 sys::swapByteOrder(c.superclass); 2923 sys::swapByteOrder(c.cache); 2924 sys::swapByteOrder(c.vtable); 2925 sys::swapByteOrder(c.data); 2926 } 2927 2928 inline void swapStruct(struct class_ro64_t &cro) { 2929 sys::swapByteOrder(cro.flags); 2930 sys::swapByteOrder(cro.instanceStart); 2931 sys::swapByteOrder(cro.instanceSize); 2932 sys::swapByteOrder(cro.reserved); 2933 sys::swapByteOrder(cro.ivarLayout); 2934 sys::swapByteOrder(cro.name); 2935 sys::swapByteOrder(cro.baseMethods); 2936 sys::swapByteOrder(cro.baseProtocols); 2937 sys::swapByteOrder(cro.ivars); 2938 sys::swapByteOrder(cro.weakIvarLayout); 2939 sys::swapByteOrder(cro.baseProperties); 2940 } 2941 2942 inline void swapStruct(struct class_ro32_t &cro) { 2943 sys::swapByteOrder(cro.flags); 2944 sys::swapByteOrder(cro.instanceStart); 2945 sys::swapByteOrder(cro.instanceSize); 2946 sys::swapByteOrder(cro.ivarLayout); 2947 sys::swapByteOrder(cro.name); 2948 sys::swapByteOrder(cro.baseMethods); 2949 sys::swapByteOrder(cro.baseProtocols); 2950 sys::swapByteOrder(cro.ivars); 2951 sys::swapByteOrder(cro.weakIvarLayout); 2952 sys::swapByteOrder(cro.baseProperties); 2953 } 2954 2955 inline void swapStruct(struct method_list64_t &ml) { 2956 sys::swapByteOrder(ml.entsize); 2957 sys::swapByteOrder(ml.count); 2958 } 2959 2960 inline void swapStruct(struct method_list32_t &ml) { 2961 sys::swapByteOrder(ml.entsize); 2962 sys::swapByteOrder(ml.count); 2963 } 2964 2965 inline void swapStruct(struct method64_t &m) { 2966 sys::swapByteOrder(m.name); 2967 sys::swapByteOrder(m.types); 2968 sys::swapByteOrder(m.imp); 2969 } 2970 2971 inline void swapStruct(struct method32_t &m) { 2972 sys::swapByteOrder(m.name); 2973 sys::swapByteOrder(m.types); 2974 sys::swapByteOrder(m.imp); 2975 } 2976 2977 inline void swapStruct(struct protocol_list64_t &pl) { 2978 sys::swapByteOrder(pl.count); 2979 } 2980 2981 inline void swapStruct(struct protocol_list32_t &pl) { 2982 sys::swapByteOrder(pl.count); 2983 } 2984 2985 inline void swapStruct(struct protocol64_t &p) { 2986 sys::swapByteOrder(p.isa); 2987 sys::swapByteOrder(p.name); 2988 sys::swapByteOrder(p.protocols); 2989 sys::swapByteOrder(p.instanceMethods); 2990 sys::swapByteOrder(p.classMethods); 2991 sys::swapByteOrder(p.optionalInstanceMethods); 2992 sys::swapByteOrder(p.optionalClassMethods); 2993 sys::swapByteOrder(p.instanceProperties); 2994 } 2995 2996 inline void swapStruct(struct protocol32_t &p) { 2997 sys::swapByteOrder(p.isa); 2998 sys::swapByteOrder(p.name); 2999 sys::swapByteOrder(p.protocols); 3000 sys::swapByteOrder(p.instanceMethods); 3001 sys::swapByteOrder(p.classMethods); 3002 sys::swapByteOrder(p.optionalInstanceMethods); 3003 sys::swapByteOrder(p.optionalClassMethods); 3004 sys::swapByteOrder(p.instanceProperties); 3005 } 3006 3007 inline void swapStruct(struct ivar_list64_t &il) { 3008 sys::swapByteOrder(il.entsize); 3009 sys::swapByteOrder(il.count); 3010 } 3011 3012 inline void swapStruct(struct ivar_list32_t &il) { 3013 sys::swapByteOrder(il.entsize); 3014 sys::swapByteOrder(il.count); 3015 } 3016 3017 inline void swapStruct(struct ivar64_t &i) { 3018 sys::swapByteOrder(i.offset); 3019 sys::swapByteOrder(i.name); 3020 sys::swapByteOrder(i.type); 3021 sys::swapByteOrder(i.alignment); 3022 sys::swapByteOrder(i.size); 3023 } 3024 3025 inline void swapStruct(struct ivar32_t &i) { 3026 sys::swapByteOrder(i.offset); 3027 sys::swapByteOrder(i.name); 3028 sys::swapByteOrder(i.type); 3029 sys::swapByteOrder(i.alignment); 3030 sys::swapByteOrder(i.size); 3031 } 3032 3033 inline void swapStruct(struct objc_property_list64 &pl) { 3034 sys::swapByteOrder(pl.entsize); 3035 sys::swapByteOrder(pl.count); 3036 } 3037 3038 inline void swapStruct(struct objc_property_list32 &pl) { 3039 sys::swapByteOrder(pl.entsize); 3040 sys::swapByteOrder(pl.count); 3041 } 3042 3043 inline void swapStruct(struct objc_property64 &op) { 3044 sys::swapByteOrder(op.name); 3045 sys::swapByteOrder(op.attributes); 3046 } 3047 3048 inline void swapStruct(struct objc_property32 &op) { 3049 sys::swapByteOrder(op.name); 3050 sys::swapByteOrder(op.attributes); 3051 } 3052 3053 inline void swapStruct(struct category64_t &c) { 3054 sys::swapByteOrder(c.name); 3055 sys::swapByteOrder(c.cls); 3056 sys::swapByteOrder(c.instanceMethods); 3057 sys::swapByteOrder(c.classMethods); 3058 sys::swapByteOrder(c.protocols); 3059 sys::swapByteOrder(c.instanceProperties); 3060 } 3061 3062 inline void swapStruct(struct category32_t &c) { 3063 sys::swapByteOrder(c.name); 3064 sys::swapByteOrder(c.cls); 3065 sys::swapByteOrder(c.instanceMethods); 3066 sys::swapByteOrder(c.classMethods); 3067 sys::swapByteOrder(c.protocols); 3068 sys::swapByteOrder(c.instanceProperties); 3069 } 3070 3071 inline void swapStruct(struct objc_image_info64 &o) { 3072 sys::swapByteOrder(o.version); 3073 sys::swapByteOrder(o.flags); 3074 } 3075 3076 inline void swapStruct(struct objc_image_info32 &o) { 3077 sys::swapByteOrder(o.version); 3078 sys::swapByteOrder(o.flags); 3079 } 3080 3081 inline void swapStruct(struct imageInfo_t &o) { 3082 sys::swapByteOrder(o.version); 3083 sys::swapByteOrder(o.flags); 3084 } 3085 3086 inline void swapStruct(struct message_ref64 &mr) { 3087 sys::swapByteOrder(mr.imp); 3088 sys::swapByteOrder(mr.sel); 3089 } 3090 3091 inline void swapStruct(struct message_ref32 &mr) { 3092 sys::swapByteOrder(mr.imp); 3093 sys::swapByteOrder(mr.sel); 3094 } 3095 3096 inline void swapStruct(struct objc_module_t &module) { 3097 sys::swapByteOrder(module.version); 3098 sys::swapByteOrder(module.size); 3099 sys::swapByteOrder(module.name); 3100 sys::swapByteOrder(module.symtab); 3101 } 3102 3103 inline void swapStruct(struct objc_symtab_t &symtab) { 3104 sys::swapByteOrder(symtab.sel_ref_cnt); 3105 sys::swapByteOrder(symtab.refs); 3106 sys::swapByteOrder(symtab.cls_def_cnt); 3107 sys::swapByteOrder(symtab.cat_def_cnt); 3108 } 3109 3110 inline void swapStruct(struct objc_class_t &objc_class) { 3111 sys::swapByteOrder(objc_class.isa); 3112 sys::swapByteOrder(objc_class.super_class); 3113 sys::swapByteOrder(objc_class.name); 3114 sys::swapByteOrder(objc_class.version); 3115 sys::swapByteOrder(objc_class.info); 3116 sys::swapByteOrder(objc_class.instance_size); 3117 sys::swapByteOrder(objc_class.ivars); 3118 sys::swapByteOrder(objc_class.methodLists); 3119 sys::swapByteOrder(objc_class.cache); 3120 sys::swapByteOrder(objc_class.protocols); 3121 } 3122 3123 inline void swapStruct(struct objc_category_t &objc_category) { 3124 sys::swapByteOrder(objc_category.category_name); 3125 sys::swapByteOrder(objc_category.class_name); 3126 sys::swapByteOrder(objc_category.instance_methods); 3127 sys::swapByteOrder(objc_category.class_methods); 3128 sys::swapByteOrder(objc_category.protocols); 3129 } 3130 3131 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 3132 sys::swapByteOrder(objc_ivar_list.ivar_count); 3133 } 3134 3135 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 3136 sys::swapByteOrder(objc_ivar.ivar_name); 3137 sys::swapByteOrder(objc_ivar.ivar_type); 3138 sys::swapByteOrder(objc_ivar.ivar_offset); 3139 } 3140 3141 inline void swapStruct(struct objc_method_list_t &method_list) { 3142 sys::swapByteOrder(method_list.obsolete); 3143 sys::swapByteOrder(method_list.method_count); 3144 } 3145 3146 inline void swapStruct(struct objc_method_t &method) { 3147 sys::swapByteOrder(method.method_name); 3148 sys::swapByteOrder(method.method_types); 3149 sys::swapByteOrder(method.method_imp); 3150 } 3151 3152 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 3153 sys::swapByteOrder(protocol_list.next); 3154 sys::swapByteOrder(protocol_list.count); 3155 } 3156 3157 inline void swapStruct(struct objc_protocol_t &protocol) { 3158 sys::swapByteOrder(protocol.isa); 3159 sys::swapByteOrder(protocol.protocol_name); 3160 sys::swapByteOrder(protocol.protocol_list); 3161 sys::swapByteOrder(protocol.instance_methods); 3162 sys::swapByteOrder(protocol.class_methods); 3163 } 3164 3165 inline void swapStruct(struct objc_method_description_list_t &mdl) { 3166 sys::swapByteOrder(mdl.count); 3167 } 3168 3169 inline void swapStruct(struct objc_method_description_t &md) { 3170 sys::swapByteOrder(md.name); 3171 sys::swapByteOrder(md.types); 3172 } 3173 3174 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 3175 struct DisassembleInfo *info); 3176 3177 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 3178 // to an Objective-C class and returns the class name. It is also passed the 3179 // address of the pointer, so when the pointer is zero as it can be in an .o 3180 // file, that is used to look for an external relocation entry with a symbol 3181 // name. 3182 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 3183 uint64_t ReferenceValue, 3184 struct DisassembleInfo *info) { 3185 const char *r; 3186 uint32_t offset, left; 3187 SectionRef S; 3188 3189 // The pointer_value can be 0 in an object file and have a relocation 3190 // entry for the class symbol at the ReferenceValue (the address of the 3191 // pointer). 3192 if (pointer_value == 0) { 3193 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3194 if (r == nullptr || left < sizeof(uint64_t)) 3195 return nullptr; 3196 uint64_t n_value; 3197 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3198 if (symbol_name == nullptr) 3199 return nullptr; 3200 const char *class_name = strrchr(symbol_name, '$'); 3201 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 3202 return class_name + 2; 3203 else 3204 return nullptr; 3205 } 3206 3207 // The case were the pointer_value is non-zero and points to a class defined 3208 // in this Mach-O file. 3209 r = get_pointer_64(pointer_value, offset, left, S, info); 3210 if (r == nullptr || left < sizeof(struct class64_t)) 3211 return nullptr; 3212 struct class64_t c; 3213 memcpy(&c, r, sizeof(struct class64_t)); 3214 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3215 swapStruct(c); 3216 if (c.data == 0) 3217 return nullptr; 3218 r = get_pointer_64(c.data, offset, left, S, info); 3219 if (r == nullptr || left < sizeof(struct class_ro64_t)) 3220 return nullptr; 3221 struct class_ro64_t cro; 3222 memcpy(&cro, r, sizeof(struct class_ro64_t)); 3223 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3224 swapStruct(cro); 3225 if (cro.name == 0) 3226 return nullptr; 3227 const char *name = get_pointer_64(cro.name, offset, left, S, info); 3228 return name; 3229 } 3230 3231 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 3232 // pointer to a cfstring and returns its name or nullptr. 3233 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 3234 struct DisassembleInfo *info) { 3235 const char *r, *name; 3236 uint32_t offset, left; 3237 SectionRef S; 3238 struct cfstring64_t cfs; 3239 uint64_t cfs_characters; 3240 3241 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3242 if (r == nullptr || left < sizeof(struct cfstring64_t)) 3243 return nullptr; 3244 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 3245 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3246 swapStruct(cfs); 3247 if (cfs.characters == 0) { 3248 uint64_t n_value; 3249 const char *symbol_name = get_symbol_64( 3250 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 3251 if (symbol_name == nullptr) 3252 return nullptr; 3253 cfs_characters = n_value; 3254 } else 3255 cfs_characters = cfs.characters; 3256 name = get_pointer_64(cfs_characters, offset, left, S, info); 3257 3258 return name; 3259 } 3260 3261 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 3262 // of a pointer to an Objective-C selector reference when the pointer value is 3263 // zero as in a .o file and is likely to have a external relocation entry with 3264 // who's symbol's n_value is the real pointer to the selector name. If that is 3265 // the case the real pointer to the selector name is returned else 0 is 3266 // returned 3267 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 3268 struct DisassembleInfo *info) { 3269 uint32_t offset, left; 3270 SectionRef S; 3271 3272 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 3273 if (r == nullptr || left < sizeof(uint64_t)) 3274 return 0; 3275 uint64_t n_value; 3276 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3277 if (symbol_name == nullptr) 3278 return 0; 3279 return n_value; 3280 } 3281 3282 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 3283 const char *sectname) { 3284 for (const SectionRef &Section : O->sections()) { 3285 StringRef SectName; 3286 Section.getName(SectName); 3287 DataRefImpl Ref = Section.getRawDataRefImpl(); 3288 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3289 if (SegName == segname && SectName == sectname) 3290 return Section; 3291 } 3292 return SectionRef(); 3293 } 3294 3295 static void 3296 walk_pointer_list_64(const char *listname, const SectionRef S, 3297 MachOObjectFile *O, struct DisassembleInfo *info, 3298 void (*func)(uint64_t, struct DisassembleInfo *info)) { 3299 if (S == SectionRef()) 3300 return; 3301 3302 StringRef SectName; 3303 S.getName(SectName); 3304 DataRefImpl Ref = S.getRawDataRefImpl(); 3305 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3306 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3307 3308 StringRef BytesStr; 3309 S.getContents(BytesStr); 3310 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3311 3312 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 3313 uint32_t left = S.getSize() - i; 3314 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 3315 uint64_t p = 0; 3316 memcpy(&p, Contents + i, size); 3317 if (i + sizeof(uint64_t) > S.getSize()) 3318 outs() << listname << " list pointer extends past end of (" << SegName 3319 << "," << SectName << ") section\n"; 3320 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 3321 3322 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3323 sys::swapByteOrder(p); 3324 3325 uint64_t n_value = 0; 3326 const char *name = get_symbol_64(i, S, info, n_value, p); 3327 if (name == nullptr) 3328 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 3329 3330 if (n_value != 0) { 3331 outs() << format("0x%" PRIx64, n_value); 3332 if (p != 0) 3333 outs() << " + " << format("0x%" PRIx64, p); 3334 } else 3335 outs() << format("0x%" PRIx64, p); 3336 if (name != nullptr) 3337 outs() << " " << name; 3338 outs() << "\n"; 3339 3340 p += n_value; 3341 if (func) 3342 func(p, info); 3343 } 3344 } 3345 3346 static void 3347 walk_pointer_list_32(const char *listname, const SectionRef S, 3348 MachOObjectFile *O, struct DisassembleInfo *info, 3349 void (*func)(uint32_t, struct DisassembleInfo *info)) { 3350 if (S == SectionRef()) 3351 return; 3352 3353 StringRef SectName; 3354 S.getName(SectName); 3355 DataRefImpl Ref = S.getRawDataRefImpl(); 3356 StringRef SegName = O->getSectionFinalSegmentName(Ref); 3357 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 3358 3359 StringRef BytesStr; 3360 S.getContents(BytesStr); 3361 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 3362 3363 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 3364 uint32_t left = S.getSize() - i; 3365 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 3366 uint32_t p = 0; 3367 memcpy(&p, Contents + i, size); 3368 if (i + sizeof(uint32_t) > S.getSize()) 3369 outs() << listname << " list pointer extends past end of (" << SegName 3370 << "," << SectName << ") section\n"; 3371 uint32_t Address = S.getAddress() + i; 3372 outs() << format("%08" PRIx32, Address) << " "; 3373 3374 if (O->isLittleEndian() != sys::IsLittleEndianHost) 3375 sys::swapByteOrder(p); 3376 outs() << format("0x%" PRIx32, p); 3377 3378 const char *name = get_symbol_32(i, S, info, p); 3379 if (name != nullptr) 3380 outs() << " " << name; 3381 outs() << "\n"; 3382 3383 if (func) 3384 func(p, info); 3385 } 3386 } 3387 3388 static void print_layout_map(const char *layout_map, uint32_t left) { 3389 if (layout_map == nullptr) 3390 return; 3391 outs() << " layout map: "; 3392 do { 3393 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 3394 left--; 3395 layout_map++; 3396 } while (*layout_map != '\0' && left != 0); 3397 outs() << "\n"; 3398 } 3399 3400 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 3401 uint32_t offset, left; 3402 SectionRef S; 3403 const char *layout_map; 3404 3405 if (p == 0) 3406 return; 3407 layout_map = get_pointer_64(p, offset, left, S, info); 3408 print_layout_map(layout_map, left); 3409 } 3410 3411 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 3412 uint32_t offset, left; 3413 SectionRef S; 3414 const char *layout_map; 3415 3416 if (p == 0) 3417 return; 3418 layout_map = get_pointer_32(p, offset, left, S, info); 3419 print_layout_map(layout_map, left); 3420 } 3421 3422 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 3423 const char *indent) { 3424 struct method_list64_t ml; 3425 struct method64_t m; 3426 const char *r; 3427 uint32_t offset, xoffset, left, i; 3428 SectionRef S, xS; 3429 const char *name, *sym_name; 3430 uint64_t n_value; 3431 3432 r = get_pointer_64(p, offset, left, S, info); 3433 if (r == nullptr) 3434 return; 3435 memset(&ml, '\0', sizeof(struct method_list64_t)); 3436 if (left < sizeof(struct method_list64_t)) { 3437 memcpy(&ml, r, left); 3438 outs() << " (method_list_t entends past the end of the section)\n"; 3439 } else 3440 memcpy(&ml, r, sizeof(struct method_list64_t)); 3441 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3442 swapStruct(ml); 3443 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3444 outs() << indent << "\t\t count " << ml.count << "\n"; 3445 3446 p += sizeof(struct method_list64_t); 3447 offset += sizeof(struct method_list64_t); 3448 for (i = 0; i < ml.count; i++) { 3449 r = get_pointer_64(p, offset, left, S, info); 3450 if (r == nullptr) 3451 return; 3452 memset(&m, '\0', sizeof(struct method64_t)); 3453 if (left < sizeof(struct method64_t)) { 3454 memcpy(&m, r, left); 3455 outs() << indent << " (method_t extends past the end of the section)\n"; 3456 } else 3457 memcpy(&m, r, sizeof(struct method64_t)); 3458 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3459 swapStruct(m); 3460 3461 outs() << indent << "\t\t name "; 3462 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 3463 info, n_value, m.name); 3464 if (n_value != 0) { 3465 if (info->verbose && sym_name != nullptr) 3466 outs() << sym_name; 3467 else 3468 outs() << format("0x%" PRIx64, n_value); 3469 if (m.name != 0) 3470 outs() << " + " << format("0x%" PRIx64, m.name); 3471 } else 3472 outs() << format("0x%" PRIx64, m.name); 3473 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 3474 if (name != nullptr) 3475 outs() << format(" %.*s", left, name); 3476 outs() << "\n"; 3477 3478 outs() << indent << "\t\t types "; 3479 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 3480 info, n_value, m.types); 3481 if (n_value != 0) { 3482 if (info->verbose && sym_name != nullptr) 3483 outs() << sym_name; 3484 else 3485 outs() << format("0x%" PRIx64, n_value); 3486 if (m.types != 0) 3487 outs() << " + " << format("0x%" PRIx64, m.types); 3488 } else 3489 outs() << format("0x%" PRIx64, m.types); 3490 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 3491 if (name != nullptr) 3492 outs() << format(" %.*s", left, name); 3493 outs() << "\n"; 3494 3495 outs() << indent << "\t\t imp "; 3496 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 3497 n_value, m.imp); 3498 if (info->verbose && name == nullptr) { 3499 if (n_value != 0) { 3500 outs() << format("0x%" PRIx64, n_value) << " "; 3501 if (m.imp != 0) 3502 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 3503 } else 3504 outs() << format("0x%" PRIx64, m.imp) << " "; 3505 } 3506 if (name != nullptr) 3507 outs() << name; 3508 outs() << "\n"; 3509 3510 p += sizeof(struct method64_t); 3511 offset += sizeof(struct method64_t); 3512 } 3513 } 3514 3515 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 3516 const char *indent) { 3517 struct method_list32_t ml; 3518 struct method32_t m; 3519 const char *r, *name; 3520 uint32_t offset, xoffset, left, i; 3521 SectionRef S, xS; 3522 3523 r = get_pointer_32(p, offset, left, S, info); 3524 if (r == nullptr) 3525 return; 3526 memset(&ml, '\0', sizeof(struct method_list32_t)); 3527 if (left < sizeof(struct method_list32_t)) { 3528 memcpy(&ml, r, left); 3529 outs() << " (method_list_t entends past the end of the section)\n"; 3530 } else 3531 memcpy(&ml, r, sizeof(struct method_list32_t)); 3532 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3533 swapStruct(ml); 3534 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 3535 outs() << indent << "\t\t count " << ml.count << "\n"; 3536 3537 p += sizeof(struct method_list32_t); 3538 offset += sizeof(struct method_list32_t); 3539 for (i = 0; i < ml.count; i++) { 3540 r = get_pointer_32(p, offset, left, S, info); 3541 if (r == nullptr) 3542 return; 3543 memset(&m, '\0', sizeof(struct method32_t)); 3544 if (left < sizeof(struct method32_t)) { 3545 memcpy(&ml, r, left); 3546 outs() << indent << " (method_t entends past the end of the section)\n"; 3547 } else 3548 memcpy(&m, r, sizeof(struct method32_t)); 3549 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3550 swapStruct(m); 3551 3552 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 3553 name = get_pointer_32(m.name, xoffset, left, xS, info); 3554 if (name != nullptr) 3555 outs() << format(" %.*s", left, name); 3556 outs() << "\n"; 3557 3558 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 3559 name = get_pointer_32(m.types, xoffset, left, xS, info); 3560 if (name != nullptr) 3561 outs() << format(" %.*s", left, name); 3562 outs() << "\n"; 3563 3564 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 3565 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 3566 m.imp); 3567 if (name != nullptr) 3568 outs() << " " << name; 3569 outs() << "\n"; 3570 3571 p += sizeof(struct method32_t); 3572 offset += sizeof(struct method32_t); 3573 } 3574 } 3575 3576 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 3577 uint32_t offset, left, xleft; 3578 SectionRef S; 3579 struct objc_method_list_t method_list; 3580 struct objc_method_t method; 3581 const char *r, *methods, *name, *SymbolName; 3582 int32_t i; 3583 3584 r = get_pointer_32(p, offset, left, S, info, true); 3585 if (r == nullptr) 3586 return true; 3587 3588 outs() << "\n"; 3589 if (left > sizeof(struct objc_method_list_t)) { 3590 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 3591 } else { 3592 outs() << "\t\t objc_method_list extends past end of the section\n"; 3593 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 3594 memcpy(&method_list, r, left); 3595 } 3596 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3597 swapStruct(method_list); 3598 3599 outs() << "\t\t obsolete " 3600 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 3601 outs() << "\t\t method_count " << method_list.method_count << "\n"; 3602 3603 methods = r + sizeof(struct objc_method_list_t); 3604 for (i = 0; i < method_list.method_count; i++) { 3605 if ((i + 1) * sizeof(struct objc_method_t) > left) { 3606 outs() << "\t\t remaining method's extend past the of the section\n"; 3607 break; 3608 } 3609 memcpy(&method, methods + i * sizeof(struct objc_method_t), 3610 sizeof(struct objc_method_t)); 3611 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3612 swapStruct(method); 3613 3614 outs() << "\t\t method_name " 3615 << format("0x%08" PRIx32, method.method_name); 3616 if (info->verbose) { 3617 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 3618 if (name != nullptr) 3619 outs() << format(" %.*s", xleft, name); 3620 else 3621 outs() << " (not in an __OBJC section)"; 3622 } 3623 outs() << "\n"; 3624 3625 outs() << "\t\t method_types " 3626 << format("0x%08" PRIx32, method.method_types); 3627 if (info->verbose) { 3628 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 3629 if (name != nullptr) 3630 outs() << format(" %.*s", xleft, name); 3631 else 3632 outs() << " (not in an __OBJC section)"; 3633 } 3634 outs() << "\n"; 3635 3636 outs() << "\t\t method_imp " 3637 << format("0x%08" PRIx32, method.method_imp) << " "; 3638 if (info->verbose) { 3639 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 3640 if (SymbolName != nullptr) 3641 outs() << SymbolName; 3642 } 3643 outs() << "\n"; 3644 } 3645 return false; 3646 } 3647 3648 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 3649 struct protocol_list64_t pl; 3650 uint64_t q, n_value; 3651 struct protocol64_t pc; 3652 const char *r; 3653 uint32_t offset, xoffset, left, i; 3654 SectionRef S, xS; 3655 const char *name, *sym_name; 3656 3657 r = get_pointer_64(p, offset, left, S, info); 3658 if (r == nullptr) 3659 return; 3660 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 3661 if (left < sizeof(struct protocol_list64_t)) { 3662 memcpy(&pl, r, left); 3663 outs() << " (protocol_list_t entends past the end of the section)\n"; 3664 } else 3665 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 3666 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3667 swapStruct(pl); 3668 outs() << " count " << pl.count << "\n"; 3669 3670 p += sizeof(struct protocol_list64_t); 3671 offset += sizeof(struct protocol_list64_t); 3672 for (i = 0; i < pl.count; i++) { 3673 r = get_pointer_64(p, offset, left, S, info); 3674 if (r == nullptr) 3675 return; 3676 q = 0; 3677 if (left < sizeof(uint64_t)) { 3678 memcpy(&q, r, left); 3679 outs() << " (protocol_t * entends past the end of the section)\n"; 3680 } else 3681 memcpy(&q, r, sizeof(uint64_t)); 3682 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3683 sys::swapByteOrder(q); 3684 3685 outs() << "\t\t list[" << i << "] "; 3686 sym_name = get_symbol_64(offset, S, info, n_value, q); 3687 if (n_value != 0) { 3688 if (info->verbose && sym_name != nullptr) 3689 outs() << sym_name; 3690 else 3691 outs() << format("0x%" PRIx64, n_value); 3692 if (q != 0) 3693 outs() << " + " << format("0x%" PRIx64, q); 3694 } else 3695 outs() << format("0x%" PRIx64, q); 3696 outs() << " (struct protocol_t *)\n"; 3697 3698 r = get_pointer_64(q + n_value, offset, left, S, info); 3699 if (r == nullptr) 3700 return; 3701 memset(&pc, '\0', sizeof(struct protocol64_t)); 3702 if (left < sizeof(struct protocol64_t)) { 3703 memcpy(&pc, r, left); 3704 outs() << " (protocol_t entends past the end of the section)\n"; 3705 } else 3706 memcpy(&pc, r, sizeof(struct protocol64_t)); 3707 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3708 swapStruct(pc); 3709 3710 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 3711 3712 outs() << "\t\t\t name "; 3713 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 3714 info, n_value, pc.name); 3715 if (n_value != 0) { 3716 if (info->verbose && sym_name != nullptr) 3717 outs() << sym_name; 3718 else 3719 outs() << format("0x%" PRIx64, n_value); 3720 if (pc.name != 0) 3721 outs() << " + " << format("0x%" PRIx64, pc.name); 3722 } else 3723 outs() << format("0x%" PRIx64, pc.name); 3724 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 3725 if (name != nullptr) 3726 outs() << format(" %.*s", left, name); 3727 outs() << "\n"; 3728 3729 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 3730 3731 outs() << "\t\t instanceMethods "; 3732 sym_name = 3733 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 3734 S, info, n_value, pc.instanceMethods); 3735 if (n_value != 0) { 3736 if (info->verbose && sym_name != nullptr) 3737 outs() << sym_name; 3738 else 3739 outs() << format("0x%" PRIx64, n_value); 3740 if (pc.instanceMethods != 0) 3741 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 3742 } else 3743 outs() << format("0x%" PRIx64, pc.instanceMethods); 3744 outs() << " (struct method_list_t *)\n"; 3745 if (pc.instanceMethods + n_value != 0) 3746 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 3747 3748 outs() << "\t\t classMethods "; 3749 sym_name = 3750 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 3751 info, n_value, pc.classMethods); 3752 if (n_value != 0) { 3753 if (info->verbose && sym_name != nullptr) 3754 outs() << sym_name; 3755 else 3756 outs() << format("0x%" PRIx64, n_value); 3757 if (pc.classMethods != 0) 3758 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 3759 } else 3760 outs() << format("0x%" PRIx64, pc.classMethods); 3761 outs() << " (struct method_list_t *)\n"; 3762 if (pc.classMethods + n_value != 0) 3763 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 3764 3765 outs() << "\t optionalInstanceMethods " 3766 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 3767 outs() << "\t optionalClassMethods " 3768 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 3769 outs() << "\t instanceProperties " 3770 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 3771 3772 p += sizeof(uint64_t); 3773 offset += sizeof(uint64_t); 3774 } 3775 } 3776 3777 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 3778 struct protocol_list32_t pl; 3779 uint32_t q; 3780 struct protocol32_t pc; 3781 const char *r; 3782 uint32_t offset, xoffset, left, i; 3783 SectionRef S, xS; 3784 const char *name; 3785 3786 r = get_pointer_32(p, offset, left, S, info); 3787 if (r == nullptr) 3788 return; 3789 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 3790 if (left < sizeof(struct protocol_list32_t)) { 3791 memcpy(&pl, r, left); 3792 outs() << " (protocol_list_t entends past the end of the section)\n"; 3793 } else 3794 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 3795 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3796 swapStruct(pl); 3797 outs() << " count " << pl.count << "\n"; 3798 3799 p += sizeof(struct protocol_list32_t); 3800 offset += sizeof(struct protocol_list32_t); 3801 for (i = 0; i < pl.count; i++) { 3802 r = get_pointer_32(p, offset, left, S, info); 3803 if (r == nullptr) 3804 return; 3805 q = 0; 3806 if (left < sizeof(uint32_t)) { 3807 memcpy(&q, r, left); 3808 outs() << " (protocol_t * entends past the end of the section)\n"; 3809 } else 3810 memcpy(&q, r, sizeof(uint32_t)); 3811 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3812 sys::swapByteOrder(q); 3813 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 3814 << " (struct protocol_t *)\n"; 3815 r = get_pointer_32(q, offset, left, S, info); 3816 if (r == nullptr) 3817 return; 3818 memset(&pc, '\0', sizeof(struct protocol32_t)); 3819 if (left < sizeof(struct protocol32_t)) { 3820 memcpy(&pc, r, left); 3821 outs() << " (protocol_t entends past the end of the section)\n"; 3822 } else 3823 memcpy(&pc, r, sizeof(struct protocol32_t)); 3824 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3825 swapStruct(pc); 3826 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 3827 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 3828 name = get_pointer_32(pc.name, xoffset, left, xS, info); 3829 if (name != nullptr) 3830 outs() << format(" %.*s", left, name); 3831 outs() << "\n"; 3832 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 3833 outs() << "\t\t instanceMethods " 3834 << format("0x%" PRIx32, pc.instanceMethods) 3835 << " (struct method_list_t *)\n"; 3836 if (pc.instanceMethods != 0) 3837 print_method_list32_t(pc.instanceMethods, info, "\t"); 3838 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 3839 << " (struct method_list_t *)\n"; 3840 if (pc.classMethods != 0) 3841 print_method_list32_t(pc.classMethods, info, "\t"); 3842 outs() << "\t optionalInstanceMethods " 3843 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 3844 outs() << "\t optionalClassMethods " 3845 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 3846 outs() << "\t instanceProperties " 3847 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 3848 p += sizeof(uint32_t); 3849 offset += sizeof(uint32_t); 3850 } 3851 } 3852 3853 static void print_indent(uint32_t indent) { 3854 for (uint32_t i = 0; i < indent;) { 3855 if (indent - i >= 8) { 3856 outs() << "\t"; 3857 i += 8; 3858 } else { 3859 for (uint32_t j = i; j < indent; j++) 3860 outs() << " "; 3861 return; 3862 } 3863 } 3864 } 3865 3866 static bool print_method_description_list(uint32_t p, uint32_t indent, 3867 struct DisassembleInfo *info) { 3868 uint32_t offset, left, xleft; 3869 SectionRef S; 3870 struct objc_method_description_list_t mdl; 3871 struct objc_method_description_t md; 3872 const char *r, *list, *name; 3873 int32_t i; 3874 3875 r = get_pointer_32(p, offset, left, S, info, true); 3876 if (r == nullptr) 3877 return true; 3878 3879 outs() << "\n"; 3880 if (left > sizeof(struct objc_method_description_list_t)) { 3881 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 3882 } else { 3883 print_indent(indent); 3884 outs() << " objc_method_description_list extends past end of the section\n"; 3885 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 3886 memcpy(&mdl, r, left); 3887 } 3888 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3889 swapStruct(mdl); 3890 3891 print_indent(indent); 3892 outs() << " count " << mdl.count << "\n"; 3893 3894 list = r + sizeof(struct objc_method_description_list_t); 3895 for (i = 0; i < mdl.count; i++) { 3896 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 3897 print_indent(indent); 3898 outs() << " remaining list entries extend past the of the section\n"; 3899 break; 3900 } 3901 print_indent(indent); 3902 outs() << " list[" << i << "]\n"; 3903 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 3904 sizeof(struct objc_method_description_t)); 3905 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3906 swapStruct(md); 3907 3908 print_indent(indent); 3909 outs() << " name " << format("0x%08" PRIx32, md.name); 3910 if (info->verbose) { 3911 name = get_pointer_32(md.name, offset, xleft, S, info, true); 3912 if (name != nullptr) 3913 outs() << format(" %.*s", xleft, name); 3914 else 3915 outs() << " (not in an __OBJC section)"; 3916 } 3917 outs() << "\n"; 3918 3919 print_indent(indent); 3920 outs() << " types " << format("0x%08" PRIx32, md.types); 3921 if (info->verbose) { 3922 name = get_pointer_32(md.types, offset, xleft, S, info, true); 3923 if (name != nullptr) 3924 outs() << format(" %.*s", xleft, name); 3925 else 3926 outs() << " (not in an __OBJC section)"; 3927 } 3928 outs() << "\n"; 3929 } 3930 return false; 3931 } 3932 3933 static bool print_protocol_list(uint32_t p, uint32_t indent, 3934 struct DisassembleInfo *info); 3935 3936 static bool print_protocol(uint32_t p, uint32_t indent, 3937 struct DisassembleInfo *info) { 3938 uint32_t offset, left; 3939 SectionRef S; 3940 struct objc_protocol_t protocol; 3941 const char *r, *name; 3942 3943 r = get_pointer_32(p, offset, left, S, info, true); 3944 if (r == nullptr) 3945 return true; 3946 3947 outs() << "\n"; 3948 if (left >= sizeof(struct objc_protocol_t)) { 3949 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 3950 } else { 3951 print_indent(indent); 3952 outs() << " Protocol extends past end of the section\n"; 3953 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 3954 memcpy(&protocol, r, left); 3955 } 3956 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3957 swapStruct(protocol); 3958 3959 print_indent(indent); 3960 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 3961 << "\n"; 3962 3963 print_indent(indent); 3964 outs() << " protocol_name " 3965 << format("0x%08" PRIx32, protocol.protocol_name); 3966 if (info->verbose) { 3967 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 3968 if (name != nullptr) 3969 outs() << format(" %.*s", left, name); 3970 else 3971 outs() << " (not in an __OBJC section)"; 3972 } 3973 outs() << "\n"; 3974 3975 print_indent(indent); 3976 outs() << " protocol_list " 3977 << format("0x%08" PRIx32, protocol.protocol_list); 3978 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 3979 outs() << " (not in an __OBJC section)\n"; 3980 3981 print_indent(indent); 3982 outs() << " instance_methods " 3983 << format("0x%08" PRIx32, protocol.instance_methods); 3984 if (print_method_description_list(protocol.instance_methods, indent, info)) 3985 outs() << " (not in an __OBJC section)\n"; 3986 3987 print_indent(indent); 3988 outs() << " class_methods " 3989 << format("0x%08" PRIx32, protocol.class_methods); 3990 if (print_method_description_list(protocol.class_methods, indent, info)) 3991 outs() << " (not in an __OBJC section)\n"; 3992 3993 return false; 3994 } 3995 3996 static bool print_protocol_list(uint32_t p, uint32_t indent, 3997 struct DisassembleInfo *info) { 3998 uint32_t offset, left, l; 3999 SectionRef S; 4000 struct objc_protocol_list_t protocol_list; 4001 const char *r, *list; 4002 int32_t i; 4003 4004 r = get_pointer_32(p, offset, left, S, info, true); 4005 if (r == nullptr) 4006 return true; 4007 4008 outs() << "\n"; 4009 if (left > sizeof(struct objc_protocol_list_t)) { 4010 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 4011 } else { 4012 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 4013 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 4014 memcpy(&protocol_list, r, left); 4015 } 4016 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4017 swapStruct(protocol_list); 4018 4019 print_indent(indent); 4020 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 4021 << "\n"; 4022 print_indent(indent); 4023 outs() << " count " << protocol_list.count << "\n"; 4024 4025 list = r + sizeof(struct objc_protocol_list_t); 4026 for (i = 0; i < protocol_list.count; i++) { 4027 if ((i + 1) * sizeof(uint32_t) > left) { 4028 outs() << "\t\t remaining list entries extend past the of the section\n"; 4029 break; 4030 } 4031 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 4032 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4033 sys::swapByteOrder(l); 4034 4035 print_indent(indent); 4036 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 4037 if (print_protocol(l, indent, info)) 4038 outs() << "(not in an __OBJC section)\n"; 4039 } 4040 return false; 4041 } 4042 4043 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 4044 struct ivar_list64_t il; 4045 struct ivar64_t i; 4046 const char *r; 4047 uint32_t offset, xoffset, left, j; 4048 SectionRef S, xS; 4049 const char *name, *sym_name, *ivar_offset_p; 4050 uint64_t ivar_offset, n_value; 4051 4052 r = get_pointer_64(p, offset, left, S, info); 4053 if (r == nullptr) 4054 return; 4055 memset(&il, '\0', sizeof(struct ivar_list64_t)); 4056 if (left < sizeof(struct ivar_list64_t)) { 4057 memcpy(&il, r, left); 4058 outs() << " (ivar_list_t entends past the end of the section)\n"; 4059 } else 4060 memcpy(&il, r, sizeof(struct ivar_list64_t)); 4061 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4062 swapStruct(il); 4063 outs() << " entsize " << il.entsize << "\n"; 4064 outs() << " count " << il.count << "\n"; 4065 4066 p += sizeof(struct ivar_list64_t); 4067 offset += sizeof(struct ivar_list64_t); 4068 for (j = 0; j < il.count; j++) { 4069 r = get_pointer_64(p, offset, left, S, info); 4070 if (r == nullptr) 4071 return; 4072 memset(&i, '\0', sizeof(struct ivar64_t)); 4073 if (left < sizeof(struct ivar64_t)) { 4074 memcpy(&i, r, left); 4075 outs() << " (ivar_t entends past the end of the section)\n"; 4076 } else 4077 memcpy(&i, r, sizeof(struct ivar64_t)); 4078 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4079 swapStruct(i); 4080 4081 outs() << "\t\t\t offset "; 4082 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 4083 info, n_value, i.offset); 4084 if (n_value != 0) { 4085 if (info->verbose && sym_name != nullptr) 4086 outs() << sym_name; 4087 else 4088 outs() << format("0x%" PRIx64, n_value); 4089 if (i.offset != 0) 4090 outs() << " + " << format("0x%" PRIx64, i.offset); 4091 } else 4092 outs() << format("0x%" PRIx64, i.offset); 4093 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 4094 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4095 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4096 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4097 sys::swapByteOrder(ivar_offset); 4098 outs() << " " << ivar_offset << "\n"; 4099 } else 4100 outs() << "\n"; 4101 4102 outs() << "\t\t\t name "; 4103 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 4104 n_value, i.name); 4105 if (n_value != 0) { 4106 if (info->verbose && sym_name != nullptr) 4107 outs() << sym_name; 4108 else 4109 outs() << format("0x%" PRIx64, n_value); 4110 if (i.name != 0) 4111 outs() << " + " << format("0x%" PRIx64, i.name); 4112 } else 4113 outs() << format("0x%" PRIx64, i.name); 4114 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 4115 if (name != nullptr) 4116 outs() << format(" %.*s", left, name); 4117 outs() << "\n"; 4118 4119 outs() << "\t\t\t type "; 4120 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 4121 n_value, i.name); 4122 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 4123 if (n_value != 0) { 4124 if (info->verbose && sym_name != nullptr) 4125 outs() << sym_name; 4126 else 4127 outs() << format("0x%" PRIx64, n_value); 4128 if (i.type != 0) 4129 outs() << " + " << format("0x%" PRIx64, i.type); 4130 } else 4131 outs() << format("0x%" PRIx64, i.type); 4132 if (name != nullptr) 4133 outs() << format(" %.*s", left, name); 4134 outs() << "\n"; 4135 4136 outs() << "\t\t\talignment " << i.alignment << "\n"; 4137 outs() << "\t\t\t size " << i.size << "\n"; 4138 4139 p += sizeof(struct ivar64_t); 4140 offset += sizeof(struct ivar64_t); 4141 } 4142 } 4143 4144 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 4145 struct ivar_list32_t il; 4146 struct ivar32_t i; 4147 const char *r; 4148 uint32_t offset, xoffset, left, j; 4149 SectionRef S, xS; 4150 const char *name, *ivar_offset_p; 4151 uint32_t ivar_offset; 4152 4153 r = get_pointer_32(p, offset, left, S, info); 4154 if (r == nullptr) 4155 return; 4156 memset(&il, '\0', sizeof(struct ivar_list32_t)); 4157 if (left < sizeof(struct ivar_list32_t)) { 4158 memcpy(&il, r, left); 4159 outs() << " (ivar_list_t entends past the end of the section)\n"; 4160 } else 4161 memcpy(&il, r, sizeof(struct ivar_list32_t)); 4162 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4163 swapStruct(il); 4164 outs() << " entsize " << il.entsize << "\n"; 4165 outs() << " count " << il.count << "\n"; 4166 4167 p += sizeof(struct ivar_list32_t); 4168 offset += sizeof(struct ivar_list32_t); 4169 for (j = 0; j < il.count; j++) { 4170 r = get_pointer_32(p, offset, left, S, info); 4171 if (r == nullptr) 4172 return; 4173 memset(&i, '\0', sizeof(struct ivar32_t)); 4174 if (left < sizeof(struct ivar32_t)) { 4175 memcpy(&i, r, left); 4176 outs() << " (ivar_t entends past the end of the section)\n"; 4177 } else 4178 memcpy(&i, r, sizeof(struct ivar32_t)); 4179 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4180 swapStruct(i); 4181 4182 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 4183 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 4184 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4185 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4186 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4187 sys::swapByteOrder(ivar_offset); 4188 outs() << " " << ivar_offset << "\n"; 4189 } else 4190 outs() << "\n"; 4191 4192 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 4193 name = get_pointer_32(i.name, xoffset, left, xS, info); 4194 if (name != nullptr) 4195 outs() << format(" %.*s", left, name); 4196 outs() << "\n"; 4197 4198 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 4199 name = get_pointer_32(i.type, xoffset, left, xS, info); 4200 if (name != nullptr) 4201 outs() << format(" %.*s", left, name); 4202 outs() << "\n"; 4203 4204 outs() << "\t\t\talignment " << i.alignment << "\n"; 4205 outs() << "\t\t\t size " << i.size << "\n"; 4206 4207 p += sizeof(struct ivar32_t); 4208 offset += sizeof(struct ivar32_t); 4209 } 4210 } 4211 4212 static void print_objc_property_list64(uint64_t p, 4213 struct DisassembleInfo *info) { 4214 struct objc_property_list64 opl; 4215 struct objc_property64 op; 4216 const char *r; 4217 uint32_t offset, xoffset, left, j; 4218 SectionRef S, xS; 4219 const char *name, *sym_name; 4220 uint64_t n_value; 4221 4222 r = get_pointer_64(p, offset, left, S, info); 4223 if (r == nullptr) 4224 return; 4225 memset(&opl, '\0', sizeof(struct objc_property_list64)); 4226 if (left < sizeof(struct objc_property_list64)) { 4227 memcpy(&opl, r, left); 4228 outs() << " (objc_property_list entends past the end of the section)\n"; 4229 } else 4230 memcpy(&opl, r, sizeof(struct objc_property_list64)); 4231 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4232 swapStruct(opl); 4233 outs() << " entsize " << opl.entsize << "\n"; 4234 outs() << " count " << opl.count << "\n"; 4235 4236 p += sizeof(struct objc_property_list64); 4237 offset += sizeof(struct objc_property_list64); 4238 for (j = 0; j < opl.count; j++) { 4239 r = get_pointer_64(p, offset, left, S, info); 4240 if (r == nullptr) 4241 return; 4242 memset(&op, '\0', sizeof(struct objc_property64)); 4243 if (left < sizeof(struct objc_property64)) { 4244 memcpy(&op, r, left); 4245 outs() << " (objc_property entends past the end of the section)\n"; 4246 } else 4247 memcpy(&op, r, sizeof(struct objc_property64)); 4248 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4249 swapStruct(op); 4250 4251 outs() << "\t\t\t name "; 4252 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 4253 info, n_value, op.name); 4254 if (n_value != 0) { 4255 if (info->verbose && sym_name != nullptr) 4256 outs() << sym_name; 4257 else 4258 outs() << format("0x%" PRIx64, n_value); 4259 if (op.name != 0) 4260 outs() << " + " << format("0x%" PRIx64, op.name); 4261 } else 4262 outs() << format("0x%" PRIx64, op.name); 4263 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 4264 if (name != nullptr) 4265 outs() << format(" %.*s", left, name); 4266 outs() << "\n"; 4267 4268 outs() << "\t\t\tattributes "; 4269 sym_name = 4270 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 4271 info, n_value, op.attributes); 4272 if (n_value != 0) { 4273 if (info->verbose && sym_name != nullptr) 4274 outs() << sym_name; 4275 else 4276 outs() << format("0x%" PRIx64, n_value); 4277 if (op.attributes != 0) 4278 outs() << " + " << format("0x%" PRIx64, op.attributes); 4279 } else 4280 outs() << format("0x%" PRIx64, op.attributes); 4281 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 4282 if (name != nullptr) 4283 outs() << format(" %.*s", left, name); 4284 outs() << "\n"; 4285 4286 p += sizeof(struct objc_property64); 4287 offset += sizeof(struct objc_property64); 4288 } 4289 } 4290 4291 static void print_objc_property_list32(uint32_t p, 4292 struct DisassembleInfo *info) { 4293 struct objc_property_list32 opl; 4294 struct objc_property32 op; 4295 const char *r; 4296 uint32_t offset, xoffset, left, j; 4297 SectionRef S, xS; 4298 const char *name; 4299 4300 r = get_pointer_32(p, offset, left, S, info); 4301 if (r == nullptr) 4302 return; 4303 memset(&opl, '\0', sizeof(struct objc_property_list32)); 4304 if (left < sizeof(struct objc_property_list32)) { 4305 memcpy(&opl, r, left); 4306 outs() << " (objc_property_list entends past the end of the section)\n"; 4307 } else 4308 memcpy(&opl, r, sizeof(struct objc_property_list32)); 4309 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4310 swapStruct(opl); 4311 outs() << " entsize " << opl.entsize << "\n"; 4312 outs() << " count " << opl.count << "\n"; 4313 4314 p += sizeof(struct objc_property_list32); 4315 offset += sizeof(struct objc_property_list32); 4316 for (j = 0; j < opl.count; j++) { 4317 r = get_pointer_32(p, offset, left, S, info); 4318 if (r == nullptr) 4319 return; 4320 memset(&op, '\0', sizeof(struct objc_property32)); 4321 if (left < sizeof(struct objc_property32)) { 4322 memcpy(&op, r, left); 4323 outs() << " (objc_property entends past the end of the section)\n"; 4324 } else 4325 memcpy(&op, r, sizeof(struct objc_property32)); 4326 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4327 swapStruct(op); 4328 4329 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 4330 name = get_pointer_32(op.name, xoffset, left, xS, info); 4331 if (name != nullptr) 4332 outs() << format(" %.*s", left, name); 4333 outs() << "\n"; 4334 4335 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 4336 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 4337 if (name != nullptr) 4338 outs() << format(" %.*s", left, name); 4339 outs() << "\n"; 4340 4341 p += sizeof(struct objc_property32); 4342 offset += sizeof(struct objc_property32); 4343 } 4344 } 4345 4346 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 4347 bool &is_meta_class) { 4348 struct class_ro64_t cro; 4349 const char *r; 4350 uint32_t offset, xoffset, left; 4351 SectionRef S, xS; 4352 const char *name, *sym_name; 4353 uint64_t n_value; 4354 4355 r = get_pointer_64(p, offset, left, S, info); 4356 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4357 return false; 4358 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4359 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4360 swapStruct(cro); 4361 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4362 if (cro.flags & RO_META) 4363 outs() << " RO_META"; 4364 if (cro.flags & RO_ROOT) 4365 outs() << " RO_ROOT"; 4366 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4367 outs() << " RO_HAS_CXX_STRUCTORS"; 4368 outs() << "\n"; 4369 outs() << " instanceStart " << cro.instanceStart << "\n"; 4370 outs() << " instanceSize " << cro.instanceSize << "\n"; 4371 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 4372 << "\n"; 4373 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 4374 << "\n"; 4375 print_layout_map64(cro.ivarLayout, info); 4376 4377 outs() << " name "; 4378 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 4379 info, n_value, cro.name); 4380 if (n_value != 0) { 4381 if (info->verbose && sym_name != nullptr) 4382 outs() << sym_name; 4383 else 4384 outs() << format("0x%" PRIx64, n_value); 4385 if (cro.name != 0) 4386 outs() << " + " << format("0x%" PRIx64, cro.name); 4387 } else 4388 outs() << format("0x%" PRIx64, cro.name); 4389 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 4390 if (name != nullptr) 4391 outs() << format(" %.*s", left, name); 4392 outs() << "\n"; 4393 4394 outs() << " baseMethods "; 4395 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 4396 S, info, n_value, cro.baseMethods); 4397 if (n_value != 0) { 4398 if (info->verbose && sym_name != nullptr) 4399 outs() << sym_name; 4400 else 4401 outs() << format("0x%" PRIx64, n_value); 4402 if (cro.baseMethods != 0) 4403 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 4404 } else 4405 outs() << format("0x%" PRIx64, cro.baseMethods); 4406 outs() << " (struct method_list_t *)\n"; 4407 if (cro.baseMethods + n_value != 0) 4408 print_method_list64_t(cro.baseMethods + n_value, info, ""); 4409 4410 outs() << " baseProtocols "; 4411 sym_name = 4412 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 4413 info, n_value, cro.baseProtocols); 4414 if (n_value != 0) { 4415 if (info->verbose && sym_name != nullptr) 4416 outs() << sym_name; 4417 else 4418 outs() << format("0x%" PRIx64, n_value); 4419 if (cro.baseProtocols != 0) 4420 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 4421 } else 4422 outs() << format("0x%" PRIx64, cro.baseProtocols); 4423 outs() << "\n"; 4424 if (cro.baseProtocols + n_value != 0) 4425 print_protocol_list64_t(cro.baseProtocols + n_value, info); 4426 4427 outs() << " ivars "; 4428 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 4429 info, n_value, cro.ivars); 4430 if (n_value != 0) { 4431 if (info->verbose && sym_name != nullptr) 4432 outs() << sym_name; 4433 else 4434 outs() << format("0x%" PRIx64, n_value); 4435 if (cro.ivars != 0) 4436 outs() << " + " << format("0x%" PRIx64, cro.ivars); 4437 } else 4438 outs() << format("0x%" PRIx64, cro.ivars); 4439 outs() << "\n"; 4440 if (cro.ivars + n_value != 0) 4441 print_ivar_list64_t(cro.ivars + n_value, info); 4442 4443 outs() << " weakIvarLayout "; 4444 sym_name = 4445 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 4446 info, n_value, cro.weakIvarLayout); 4447 if (n_value != 0) { 4448 if (info->verbose && sym_name != nullptr) 4449 outs() << sym_name; 4450 else 4451 outs() << format("0x%" PRIx64, n_value); 4452 if (cro.weakIvarLayout != 0) 4453 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 4454 } else 4455 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 4456 outs() << "\n"; 4457 print_layout_map64(cro.weakIvarLayout + n_value, info); 4458 4459 outs() << " baseProperties "; 4460 sym_name = 4461 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 4462 info, n_value, cro.baseProperties); 4463 if (n_value != 0) { 4464 if (info->verbose && sym_name != nullptr) 4465 outs() << sym_name; 4466 else 4467 outs() << format("0x%" PRIx64, n_value); 4468 if (cro.baseProperties != 0) 4469 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 4470 } else 4471 outs() << format("0x%" PRIx64, cro.baseProperties); 4472 outs() << "\n"; 4473 if (cro.baseProperties + n_value != 0) 4474 print_objc_property_list64(cro.baseProperties + n_value, info); 4475 4476 is_meta_class = (cro.flags & RO_META) != 0; 4477 return true; 4478 } 4479 4480 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 4481 bool &is_meta_class) { 4482 struct class_ro32_t cro; 4483 const char *r; 4484 uint32_t offset, xoffset, left; 4485 SectionRef S, xS; 4486 const char *name; 4487 4488 r = get_pointer_32(p, offset, left, S, info); 4489 if (r == nullptr) 4490 return false; 4491 memset(&cro, '\0', sizeof(struct class_ro32_t)); 4492 if (left < sizeof(struct class_ro32_t)) { 4493 memcpy(&cro, r, left); 4494 outs() << " (class_ro_t entends past the end of the section)\n"; 4495 } else 4496 memcpy(&cro, r, sizeof(struct class_ro32_t)); 4497 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4498 swapStruct(cro); 4499 outs() << " flags " << format("0x%" PRIx32, cro.flags); 4500 if (cro.flags & RO_META) 4501 outs() << " RO_META"; 4502 if (cro.flags & RO_ROOT) 4503 outs() << " RO_ROOT"; 4504 if (cro.flags & RO_HAS_CXX_STRUCTORS) 4505 outs() << " RO_HAS_CXX_STRUCTORS"; 4506 outs() << "\n"; 4507 outs() << " instanceStart " << cro.instanceStart << "\n"; 4508 outs() << " instanceSize " << cro.instanceSize << "\n"; 4509 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 4510 << "\n"; 4511 print_layout_map32(cro.ivarLayout, info); 4512 4513 outs() << " name " << format("0x%" PRIx32, cro.name); 4514 name = get_pointer_32(cro.name, xoffset, left, xS, info); 4515 if (name != nullptr) 4516 outs() << format(" %.*s", left, name); 4517 outs() << "\n"; 4518 4519 outs() << " baseMethods " 4520 << format("0x%" PRIx32, cro.baseMethods) 4521 << " (struct method_list_t *)\n"; 4522 if (cro.baseMethods != 0) 4523 print_method_list32_t(cro.baseMethods, info, ""); 4524 4525 outs() << " baseProtocols " 4526 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 4527 if (cro.baseProtocols != 0) 4528 print_protocol_list32_t(cro.baseProtocols, info); 4529 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 4530 << "\n"; 4531 if (cro.ivars != 0) 4532 print_ivar_list32_t(cro.ivars, info); 4533 outs() << " weakIvarLayout " 4534 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 4535 print_layout_map32(cro.weakIvarLayout, info); 4536 outs() << " baseProperties " 4537 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 4538 if (cro.baseProperties != 0) 4539 print_objc_property_list32(cro.baseProperties, info); 4540 is_meta_class = (cro.flags & RO_META) != 0; 4541 return true; 4542 } 4543 4544 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 4545 struct class64_t c; 4546 const char *r; 4547 uint32_t offset, left; 4548 SectionRef S; 4549 const char *name; 4550 uint64_t isa_n_value, n_value; 4551 4552 r = get_pointer_64(p, offset, left, S, info); 4553 if (r == nullptr || left < sizeof(struct class64_t)) 4554 return; 4555 memcpy(&c, r, sizeof(struct class64_t)); 4556 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4557 swapStruct(c); 4558 4559 outs() << " isa " << format("0x%" PRIx64, c.isa); 4560 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 4561 isa_n_value, c.isa); 4562 if (name != nullptr) 4563 outs() << " " << name; 4564 outs() << "\n"; 4565 4566 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 4567 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 4568 n_value, c.superclass); 4569 if (name != nullptr) 4570 outs() << " " << name; 4571 outs() << "\n"; 4572 4573 outs() << " cache " << format("0x%" PRIx64, c.cache); 4574 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 4575 n_value, c.cache); 4576 if (name != nullptr) 4577 outs() << " " << name; 4578 outs() << "\n"; 4579 4580 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 4581 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 4582 n_value, c.vtable); 4583 if (name != nullptr) 4584 outs() << " " << name; 4585 outs() << "\n"; 4586 4587 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 4588 n_value, c.data); 4589 outs() << " data "; 4590 if (n_value != 0) { 4591 if (info->verbose && name != nullptr) 4592 outs() << name; 4593 else 4594 outs() << format("0x%" PRIx64, n_value); 4595 if (c.data != 0) 4596 outs() << " + " << format("0x%" PRIx64, c.data); 4597 } else 4598 outs() << format("0x%" PRIx64, c.data); 4599 outs() << " (struct class_ro_t *)"; 4600 4601 // This is a Swift class if some of the low bits of the pointer are set. 4602 if ((c.data + n_value) & 0x7) 4603 outs() << " Swift class"; 4604 outs() << "\n"; 4605 bool is_meta_class; 4606 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 4607 return; 4608 4609 if (!is_meta_class && 4610 c.isa + isa_n_value != p && 4611 c.isa + isa_n_value != 0 && 4612 info->depth < 100) { 4613 info->depth++; 4614 outs() << "Meta Class\n"; 4615 print_class64_t(c.isa + isa_n_value, info); 4616 } 4617 } 4618 4619 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 4620 struct class32_t c; 4621 const char *r; 4622 uint32_t offset, left; 4623 SectionRef S; 4624 const char *name; 4625 4626 r = get_pointer_32(p, offset, left, S, info); 4627 if (r == nullptr) 4628 return; 4629 memset(&c, '\0', sizeof(struct class32_t)); 4630 if (left < sizeof(struct class32_t)) { 4631 memcpy(&c, r, left); 4632 outs() << " (class_t entends past the end of the section)\n"; 4633 } else 4634 memcpy(&c, r, sizeof(struct class32_t)); 4635 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4636 swapStruct(c); 4637 4638 outs() << " isa " << format("0x%" PRIx32, c.isa); 4639 name = 4640 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 4641 if (name != nullptr) 4642 outs() << " " << name; 4643 outs() << "\n"; 4644 4645 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 4646 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 4647 c.superclass); 4648 if (name != nullptr) 4649 outs() << " " << name; 4650 outs() << "\n"; 4651 4652 outs() << " cache " << format("0x%" PRIx32, c.cache); 4653 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 4654 c.cache); 4655 if (name != nullptr) 4656 outs() << " " << name; 4657 outs() << "\n"; 4658 4659 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 4660 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 4661 c.vtable); 4662 if (name != nullptr) 4663 outs() << " " << name; 4664 outs() << "\n"; 4665 4666 name = 4667 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 4668 outs() << " data " << format("0x%" PRIx32, c.data) 4669 << " (struct class_ro_t *)"; 4670 4671 // This is a Swift class if some of the low bits of the pointer are set. 4672 if (c.data & 0x3) 4673 outs() << " Swift class"; 4674 outs() << "\n"; 4675 bool is_meta_class; 4676 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 4677 return; 4678 4679 if (!is_meta_class) { 4680 outs() << "Meta Class\n"; 4681 print_class32_t(c.isa, info); 4682 } 4683 } 4684 4685 static void print_objc_class_t(struct objc_class_t *objc_class, 4686 struct DisassembleInfo *info) { 4687 uint32_t offset, left, xleft; 4688 const char *name, *p, *ivar_list; 4689 SectionRef S; 4690 int32_t i; 4691 struct objc_ivar_list_t objc_ivar_list; 4692 struct objc_ivar_t ivar; 4693 4694 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 4695 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 4696 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 4697 if (name != nullptr) 4698 outs() << format(" %.*s", left, name); 4699 else 4700 outs() << " (not in an __OBJC section)"; 4701 } 4702 outs() << "\n"; 4703 4704 outs() << "\t super_class " 4705 << format("0x%08" PRIx32, objc_class->super_class); 4706 if (info->verbose) { 4707 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 4708 if (name != nullptr) 4709 outs() << format(" %.*s", left, name); 4710 else 4711 outs() << " (not in an __OBJC section)"; 4712 } 4713 outs() << "\n"; 4714 4715 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 4716 if (info->verbose) { 4717 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 4718 if (name != nullptr) 4719 outs() << format(" %.*s", left, name); 4720 else 4721 outs() << " (not in an __OBJC section)"; 4722 } 4723 outs() << "\n"; 4724 4725 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 4726 << "\n"; 4727 4728 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 4729 if (info->verbose) { 4730 if (CLS_GETINFO(objc_class, CLS_CLASS)) 4731 outs() << " CLS_CLASS"; 4732 else if (CLS_GETINFO(objc_class, CLS_META)) 4733 outs() << " CLS_META"; 4734 } 4735 outs() << "\n"; 4736 4737 outs() << "\t instance_size " 4738 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 4739 4740 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 4741 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 4742 if (p != nullptr) { 4743 if (left > sizeof(struct objc_ivar_list_t)) { 4744 outs() << "\n"; 4745 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 4746 } else { 4747 outs() << " (entends past the end of the section)\n"; 4748 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 4749 memcpy(&objc_ivar_list, p, left); 4750 } 4751 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4752 swapStruct(objc_ivar_list); 4753 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 4754 ivar_list = p + sizeof(struct objc_ivar_list_t); 4755 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 4756 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 4757 outs() << "\t\t remaining ivar's extend past the of the section\n"; 4758 break; 4759 } 4760 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 4761 sizeof(struct objc_ivar_t)); 4762 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4763 swapStruct(ivar); 4764 4765 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 4766 if (info->verbose) { 4767 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 4768 if (name != nullptr) 4769 outs() << format(" %.*s", xleft, name); 4770 else 4771 outs() << " (not in an __OBJC section)"; 4772 } 4773 outs() << "\n"; 4774 4775 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 4776 if (info->verbose) { 4777 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 4778 if (name != nullptr) 4779 outs() << format(" %.*s", xleft, name); 4780 else 4781 outs() << " (not in an __OBJC section)"; 4782 } 4783 outs() << "\n"; 4784 4785 outs() << "\t\t ivar_offset " 4786 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 4787 } 4788 } else { 4789 outs() << " (not in an __OBJC section)\n"; 4790 } 4791 4792 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 4793 if (print_method_list(objc_class->methodLists, info)) 4794 outs() << " (not in an __OBJC section)\n"; 4795 4796 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 4797 << "\n"; 4798 4799 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 4800 if (print_protocol_list(objc_class->protocols, 16, info)) 4801 outs() << " (not in an __OBJC section)\n"; 4802 } 4803 4804 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 4805 struct DisassembleInfo *info) { 4806 uint32_t offset, left; 4807 const char *name; 4808 SectionRef S; 4809 4810 outs() << "\t category name " 4811 << format("0x%08" PRIx32, objc_category->category_name); 4812 if (info->verbose) { 4813 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 4814 true); 4815 if (name != nullptr) 4816 outs() << format(" %.*s", left, name); 4817 else 4818 outs() << " (not in an __OBJC section)"; 4819 } 4820 outs() << "\n"; 4821 4822 outs() << "\t\t class name " 4823 << format("0x%08" PRIx32, objc_category->class_name); 4824 if (info->verbose) { 4825 name = 4826 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 4827 if (name != nullptr) 4828 outs() << format(" %.*s", left, name); 4829 else 4830 outs() << " (not in an __OBJC section)"; 4831 } 4832 outs() << "\n"; 4833 4834 outs() << "\t instance methods " 4835 << format("0x%08" PRIx32, objc_category->instance_methods); 4836 if (print_method_list(objc_category->instance_methods, info)) 4837 outs() << " (not in an __OBJC section)\n"; 4838 4839 outs() << "\t class methods " 4840 << format("0x%08" PRIx32, objc_category->class_methods); 4841 if (print_method_list(objc_category->class_methods, info)) 4842 outs() << " (not in an __OBJC section)\n"; 4843 } 4844 4845 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 4846 struct category64_t c; 4847 const char *r; 4848 uint32_t offset, xoffset, left; 4849 SectionRef S, xS; 4850 const char *name, *sym_name; 4851 uint64_t n_value; 4852 4853 r = get_pointer_64(p, offset, left, S, info); 4854 if (r == nullptr) 4855 return; 4856 memset(&c, '\0', sizeof(struct category64_t)); 4857 if (left < sizeof(struct category64_t)) { 4858 memcpy(&c, r, left); 4859 outs() << " (category_t entends past the end of the section)\n"; 4860 } else 4861 memcpy(&c, r, sizeof(struct category64_t)); 4862 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4863 swapStruct(c); 4864 4865 outs() << " name "; 4866 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 4867 info, n_value, c.name); 4868 if (n_value != 0) { 4869 if (info->verbose && sym_name != nullptr) 4870 outs() << sym_name; 4871 else 4872 outs() << format("0x%" PRIx64, n_value); 4873 if (c.name != 0) 4874 outs() << " + " << format("0x%" PRIx64, c.name); 4875 } else 4876 outs() << format("0x%" PRIx64, c.name); 4877 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 4878 if (name != nullptr) 4879 outs() << format(" %.*s", left, name); 4880 outs() << "\n"; 4881 4882 outs() << " cls "; 4883 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 4884 n_value, c.cls); 4885 if (n_value != 0) { 4886 if (info->verbose && sym_name != nullptr) 4887 outs() << sym_name; 4888 else 4889 outs() << format("0x%" PRIx64, n_value); 4890 if (c.cls != 0) 4891 outs() << " + " << format("0x%" PRIx64, c.cls); 4892 } else 4893 outs() << format("0x%" PRIx64, c.cls); 4894 outs() << "\n"; 4895 if (c.cls + n_value != 0) 4896 print_class64_t(c.cls + n_value, info); 4897 4898 outs() << " instanceMethods "; 4899 sym_name = 4900 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 4901 info, n_value, c.instanceMethods); 4902 if (n_value != 0) { 4903 if (info->verbose && sym_name != nullptr) 4904 outs() << sym_name; 4905 else 4906 outs() << format("0x%" PRIx64, n_value); 4907 if (c.instanceMethods != 0) 4908 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 4909 } else 4910 outs() << format("0x%" PRIx64, c.instanceMethods); 4911 outs() << "\n"; 4912 if (c.instanceMethods + n_value != 0) 4913 print_method_list64_t(c.instanceMethods + n_value, info, ""); 4914 4915 outs() << " classMethods "; 4916 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 4917 S, info, n_value, c.classMethods); 4918 if (n_value != 0) { 4919 if (info->verbose && sym_name != nullptr) 4920 outs() << sym_name; 4921 else 4922 outs() << format("0x%" PRIx64, n_value); 4923 if (c.classMethods != 0) 4924 outs() << " + " << format("0x%" PRIx64, c.classMethods); 4925 } else 4926 outs() << format("0x%" PRIx64, c.classMethods); 4927 outs() << "\n"; 4928 if (c.classMethods + n_value != 0) 4929 print_method_list64_t(c.classMethods + n_value, info, ""); 4930 4931 outs() << " protocols "; 4932 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 4933 info, n_value, c.protocols); 4934 if (n_value != 0) { 4935 if (info->verbose && sym_name != nullptr) 4936 outs() << sym_name; 4937 else 4938 outs() << format("0x%" PRIx64, n_value); 4939 if (c.protocols != 0) 4940 outs() << " + " << format("0x%" PRIx64, c.protocols); 4941 } else 4942 outs() << format("0x%" PRIx64, c.protocols); 4943 outs() << "\n"; 4944 if (c.protocols + n_value != 0) 4945 print_protocol_list64_t(c.protocols + n_value, info); 4946 4947 outs() << "instanceProperties "; 4948 sym_name = 4949 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 4950 S, info, n_value, c.instanceProperties); 4951 if (n_value != 0) { 4952 if (info->verbose && sym_name != nullptr) 4953 outs() << sym_name; 4954 else 4955 outs() << format("0x%" PRIx64, n_value); 4956 if (c.instanceProperties != 0) 4957 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 4958 } else 4959 outs() << format("0x%" PRIx64, c.instanceProperties); 4960 outs() << "\n"; 4961 if (c.instanceProperties + n_value != 0) 4962 print_objc_property_list64(c.instanceProperties + n_value, info); 4963 } 4964 4965 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 4966 struct category32_t c; 4967 const char *r; 4968 uint32_t offset, left; 4969 SectionRef S, xS; 4970 const char *name; 4971 4972 r = get_pointer_32(p, offset, left, S, info); 4973 if (r == nullptr) 4974 return; 4975 memset(&c, '\0', sizeof(struct category32_t)); 4976 if (left < sizeof(struct category32_t)) { 4977 memcpy(&c, r, left); 4978 outs() << " (category_t entends past the end of the section)\n"; 4979 } else 4980 memcpy(&c, r, sizeof(struct category32_t)); 4981 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4982 swapStruct(c); 4983 4984 outs() << " name " << format("0x%" PRIx32, c.name); 4985 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 4986 c.name); 4987 if (name) 4988 outs() << " " << name; 4989 outs() << "\n"; 4990 4991 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 4992 if (c.cls != 0) 4993 print_class32_t(c.cls, info); 4994 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 4995 << "\n"; 4996 if (c.instanceMethods != 0) 4997 print_method_list32_t(c.instanceMethods, info, ""); 4998 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 4999 << "\n"; 5000 if (c.classMethods != 0) 5001 print_method_list32_t(c.classMethods, info, ""); 5002 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 5003 if (c.protocols != 0) 5004 print_protocol_list32_t(c.protocols, info); 5005 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 5006 << "\n"; 5007 if (c.instanceProperties != 0) 5008 print_objc_property_list32(c.instanceProperties, info); 5009 } 5010 5011 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 5012 uint32_t i, left, offset, xoffset; 5013 uint64_t p, n_value; 5014 struct message_ref64 mr; 5015 const char *name, *sym_name; 5016 const char *r; 5017 SectionRef xS; 5018 5019 if (S == SectionRef()) 5020 return; 5021 5022 StringRef SectName; 5023 S.getName(SectName); 5024 DataRefImpl Ref = S.getRawDataRefImpl(); 5025 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5026 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5027 offset = 0; 5028 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5029 p = S.getAddress() + i; 5030 r = get_pointer_64(p, offset, left, S, info); 5031 if (r == nullptr) 5032 return; 5033 memset(&mr, '\0', sizeof(struct message_ref64)); 5034 if (left < sizeof(struct message_ref64)) { 5035 memcpy(&mr, r, left); 5036 outs() << " (message_ref entends past the end of the section)\n"; 5037 } else 5038 memcpy(&mr, r, sizeof(struct message_ref64)); 5039 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5040 swapStruct(mr); 5041 5042 outs() << " imp "; 5043 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 5044 n_value, mr.imp); 5045 if (n_value != 0) { 5046 outs() << format("0x%" PRIx64, n_value) << " "; 5047 if (mr.imp != 0) 5048 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 5049 } else 5050 outs() << format("0x%" PRIx64, mr.imp) << " "; 5051 if (name != nullptr) 5052 outs() << " " << name; 5053 outs() << "\n"; 5054 5055 outs() << " sel "; 5056 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 5057 info, n_value, mr.sel); 5058 if (n_value != 0) { 5059 if (info->verbose && sym_name != nullptr) 5060 outs() << sym_name; 5061 else 5062 outs() << format("0x%" PRIx64, n_value); 5063 if (mr.sel != 0) 5064 outs() << " + " << format("0x%" PRIx64, mr.sel); 5065 } else 5066 outs() << format("0x%" PRIx64, mr.sel); 5067 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 5068 if (name != nullptr) 5069 outs() << format(" %.*s", left, name); 5070 outs() << "\n"; 5071 5072 offset += sizeof(struct message_ref64); 5073 } 5074 } 5075 5076 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 5077 uint32_t i, left, offset, xoffset, p; 5078 struct message_ref32 mr; 5079 const char *name, *r; 5080 SectionRef xS; 5081 5082 if (S == SectionRef()) 5083 return; 5084 5085 StringRef SectName; 5086 S.getName(SectName); 5087 DataRefImpl Ref = S.getRawDataRefImpl(); 5088 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5089 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5090 offset = 0; 5091 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5092 p = S.getAddress() + i; 5093 r = get_pointer_32(p, offset, left, S, info); 5094 if (r == nullptr) 5095 return; 5096 memset(&mr, '\0', sizeof(struct message_ref32)); 5097 if (left < sizeof(struct message_ref32)) { 5098 memcpy(&mr, r, left); 5099 outs() << " (message_ref entends past the end of the section)\n"; 5100 } else 5101 memcpy(&mr, r, sizeof(struct message_ref32)); 5102 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5103 swapStruct(mr); 5104 5105 outs() << " imp " << format("0x%" PRIx32, mr.imp); 5106 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 5107 mr.imp); 5108 if (name != nullptr) 5109 outs() << " " << name; 5110 outs() << "\n"; 5111 5112 outs() << " sel " << format("0x%" PRIx32, mr.sel); 5113 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 5114 if (name != nullptr) 5115 outs() << " " << name; 5116 outs() << "\n"; 5117 5118 offset += sizeof(struct message_ref32); 5119 } 5120 } 5121 5122 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 5123 uint32_t left, offset, swift_version; 5124 uint64_t p; 5125 struct objc_image_info64 o; 5126 const char *r; 5127 5128 if (S == SectionRef()) 5129 return; 5130 5131 StringRef SectName; 5132 S.getName(SectName); 5133 DataRefImpl Ref = S.getRawDataRefImpl(); 5134 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5135 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5136 p = S.getAddress(); 5137 r = get_pointer_64(p, offset, left, S, info); 5138 if (r == nullptr) 5139 return; 5140 memset(&o, '\0', sizeof(struct objc_image_info64)); 5141 if (left < sizeof(struct objc_image_info64)) { 5142 memcpy(&o, r, left); 5143 outs() << " (objc_image_info entends past the end of the section)\n"; 5144 } else 5145 memcpy(&o, r, sizeof(struct objc_image_info64)); 5146 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5147 swapStruct(o); 5148 outs() << " version " << o.version << "\n"; 5149 outs() << " flags " << format("0x%" PRIx32, o.flags); 5150 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5151 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5152 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5153 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5154 swift_version = (o.flags >> 8) & 0xff; 5155 if (swift_version != 0) { 5156 if (swift_version == 1) 5157 outs() << " Swift 1.0"; 5158 else if (swift_version == 2) 5159 outs() << " Swift 1.1"; 5160 else 5161 outs() << " unknown future Swift version (" << swift_version << ")"; 5162 } 5163 outs() << "\n"; 5164 } 5165 5166 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 5167 uint32_t left, offset, swift_version, p; 5168 struct objc_image_info32 o; 5169 const char *r; 5170 5171 if (S == SectionRef()) 5172 return; 5173 5174 StringRef SectName; 5175 S.getName(SectName); 5176 DataRefImpl Ref = S.getRawDataRefImpl(); 5177 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5178 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5179 p = S.getAddress(); 5180 r = get_pointer_32(p, offset, left, S, info); 5181 if (r == nullptr) 5182 return; 5183 memset(&o, '\0', sizeof(struct objc_image_info32)); 5184 if (left < sizeof(struct objc_image_info32)) { 5185 memcpy(&o, r, left); 5186 outs() << " (objc_image_info entends past the end of the section)\n"; 5187 } else 5188 memcpy(&o, r, sizeof(struct objc_image_info32)); 5189 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5190 swapStruct(o); 5191 outs() << " version " << o.version << "\n"; 5192 outs() << " flags " << format("0x%" PRIx32, o.flags); 5193 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5194 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5195 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5196 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5197 swift_version = (o.flags >> 8) & 0xff; 5198 if (swift_version != 0) { 5199 if (swift_version == 1) 5200 outs() << " Swift 1.0"; 5201 else if (swift_version == 2) 5202 outs() << " Swift 1.1"; 5203 else 5204 outs() << " unknown future Swift version (" << swift_version << ")"; 5205 } 5206 outs() << "\n"; 5207 } 5208 5209 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 5210 uint32_t left, offset, p; 5211 struct imageInfo_t o; 5212 const char *r; 5213 5214 StringRef SectName; 5215 S.getName(SectName); 5216 DataRefImpl Ref = S.getRawDataRefImpl(); 5217 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5218 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5219 p = S.getAddress(); 5220 r = get_pointer_32(p, offset, left, S, info); 5221 if (r == nullptr) 5222 return; 5223 memset(&o, '\0', sizeof(struct imageInfo_t)); 5224 if (left < sizeof(struct imageInfo_t)) { 5225 memcpy(&o, r, left); 5226 outs() << " (imageInfo entends past the end of the section)\n"; 5227 } else 5228 memcpy(&o, r, sizeof(struct imageInfo_t)); 5229 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5230 swapStruct(o); 5231 outs() << " version " << o.version << "\n"; 5232 outs() << " flags " << format("0x%" PRIx32, o.flags); 5233 if (o.flags & 0x1) 5234 outs() << " F&C"; 5235 if (o.flags & 0x2) 5236 outs() << " GC"; 5237 if (o.flags & 0x4) 5238 outs() << " GC-only"; 5239 else 5240 outs() << " RR"; 5241 outs() << "\n"; 5242 } 5243 5244 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 5245 SymbolAddressMap AddrMap; 5246 if (verbose) 5247 CreateSymbolAddressMap(O, &AddrMap); 5248 5249 std::vector<SectionRef> Sections; 5250 for (const SectionRef &Section : O->sections()) { 5251 StringRef SectName; 5252 Section.getName(SectName); 5253 Sections.push_back(Section); 5254 } 5255 5256 struct DisassembleInfo info; 5257 // Set up the block of info used by the Symbolizer call backs. 5258 info.verbose = verbose; 5259 info.O = O; 5260 info.AddrMap = &AddrMap; 5261 info.Sections = &Sections; 5262 info.class_name = nullptr; 5263 info.selector_name = nullptr; 5264 info.method = nullptr; 5265 info.demangled_name = nullptr; 5266 info.bindtable = nullptr; 5267 info.adrp_addr = 0; 5268 info.adrp_inst = 0; 5269 5270 info.depth = 0; 5271 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5272 if (CL == SectionRef()) 5273 CL = get_section(O, "__DATA", "__objc_classlist"); 5274 if (CL == SectionRef()) 5275 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5276 if (CL == SectionRef()) 5277 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5278 info.S = CL; 5279 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 5280 5281 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5282 if (CR == SectionRef()) 5283 CR = get_section(O, "__DATA", "__objc_classrefs"); 5284 if (CR == SectionRef()) 5285 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5286 if (CR == SectionRef()) 5287 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5288 info.S = CR; 5289 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 5290 5291 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5292 if (SR == SectionRef()) 5293 SR = get_section(O, "__DATA", "__objc_superrefs"); 5294 if (SR == SectionRef()) 5295 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5296 if (SR == SectionRef()) 5297 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5298 info.S = SR; 5299 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 5300 5301 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5302 if (CA == SectionRef()) 5303 CA = get_section(O, "__DATA", "__objc_catlist"); 5304 if (CA == SectionRef()) 5305 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5306 if (CA == SectionRef()) 5307 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5308 info.S = CA; 5309 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 5310 5311 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5312 if (PL == SectionRef()) 5313 PL = get_section(O, "__DATA", "__objc_protolist"); 5314 if (PL == SectionRef()) 5315 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5316 if (PL == SectionRef()) 5317 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5318 info.S = PL; 5319 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 5320 5321 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5322 if (MR == SectionRef()) 5323 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5324 if (MR == SectionRef()) 5325 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5326 if (MR == SectionRef()) 5327 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5328 info.S = MR; 5329 print_message_refs64(MR, &info); 5330 5331 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5332 if (II == SectionRef()) 5333 II = get_section(O, "__DATA", "__objc_imageinfo"); 5334 if (II == SectionRef()) 5335 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5336 if (II == SectionRef()) 5337 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5338 info.S = II; 5339 print_image_info64(II, &info); 5340 } 5341 5342 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5343 SymbolAddressMap AddrMap; 5344 if (verbose) 5345 CreateSymbolAddressMap(O, &AddrMap); 5346 5347 std::vector<SectionRef> Sections; 5348 for (const SectionRef &Section : O->sections()) { 5349 StringRef SectName; 5350 Section.getName(SectName); 5351 Sections.push_back(Section); 5352 } 5353 5354 struct DisassembleInfo info; 5355 // Set up the block of info used by the Symbolizer call backs. 5356 info.verbose = verbose; 5357 info.O = O; 5358 info.AddrMap = &AddrMap; 5359 info.Sections = &Sections; 5360 info.class_name = nullptr; 5361 info.selector_name = nullptr; 5362 info.method = nullptr; 5363 info.demangled_name = nullptr; 5364 info.bindtable = nullptr; 5365 info.adrp_addr = 0; 5366 info.adrp_inst = 0; 5367 5368 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 5369 if (CL == SectionRef()) 5370 CL = get_section(O, "__DATA", "__objc_classlist"); 5371 if (CL == SectionRef()) 5372 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 5373 if (CL == SectionRef()) 5374 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 5375 info.S = CL; 5376 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 5377 5378 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 5379 if (CR == SectionRef()) 5380 CR = get_section(O, "__DATA", "__objc_classrefs"); 5381 if (CR == SectionRef()) 5382 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 5383 if (CR == SectionRef()) 5384 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 5385 info.S = CR; 5386 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 5387 5388 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 5389 if (SR == SectionRef()) 5390 SR = get_section(O, "__DATA", "__objc_superrefs"); 5391 if (SR == SectionRef()) 5392 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 5393 if (SR == SectionRef()) 5394 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 5395 info.S = SR; 5396 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 5397 5398 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 5399 if (CA == SectionRef()) 5400 CA = get_section(O, "__DATA", "__objc_catlist"); 5401 if (CA == SectionRef()) 5402 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 5403 if (CA == SectionRef()) 5404 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 5405 info.S = CA; 5406 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 5407 5408 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 5409 if (PL == SectionRef()) 5410 PL = get_section(O, "__DATA", "__objc_protolist"); 5411 if (PL == SectionRef()) 5412 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 5413 if (PL == SectionRef()) 5414 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 5415 info.S = PL; 5416 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 5417 5418 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 5419 if (MR == SectionRef()) 5420 MR = get_section(O, "__DATA", "__objc_msgrefs"); 5421 if (MR == SectionRef()) 5422 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 5423 if (MR == SectionRef()) 5424 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 5425 info.S = MR; 5426 print_message_refs32(MR, &info); 5427 5428 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 5429 if (II == SectionRef()) 5430 II = get_section(O, "__DATA", "__objc_imageinfo"); 5431 if (II == SectionRef()) 5432 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 5433 if (II == SectionRef()) 5434 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 5435 info.S = II; 5436 print_image_info32(II, &info); 5437 } 5438 5439 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 5440 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 5441 const char *r, *name, *defs; 5442 struct objc_module_t module; 5443 SectionRef S, xS; 5444 struct objc_symtab_t symtab; 5445 struct objc_class_t objc_class; 5446 struct objc_category_t objc_category; 5447 5448 outs() << "Objective-C segment\n"; 5449 S = get_section(O, "__OBJC", "__module_info"); 5450 if (S == SectionRef()) 5451 return false; 5452 5453 SymbolAddressMap AddrMap; 5454 if (verbose) 5455 CreateSymbolAddressMap(O, &AddrMap); 5456 5457 std::vector<SectionRef> Sections; 5458 for (const SectionRef &Section : O->sections()) { 5459 StringRef SectName; 5460 Section.getName(SectName); 5461 Sections.push_back(Section); 5462 } 5463 5464 struct DisassembleInfo info; 5465 // Set up the block of info used by the Symbolizer call backs. 5466 info.verbose = verbose; 5467 info.O = O; 5468 info.AddrMap = &AddrMap; 5469 info.Sections = &Sections; 5470 info.class_name = nullptr; 5471 info.selector_name = nullptr; 5472 info.method = nullptr; 5473 info.demangled_name = nullptr; 5474 info.bindtable = nullptr; 5475 info.adrp_addr = 0; 5476 info.adrp_inst = 0; 5477 5478 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 5479 p = S.getAddress() + i; 5480 r = get_pointer_32(p, offset, left, S, &info, true); 5481 if (r == nullptr) 5482 return true; 5483 memset(&module, '\0', sizeof(struct objc_module_t)); 5484 if (left < sizeof(struct objc_module_t)) { 5485 memcpy(&module, r, left); 5486 outs() << " (module extends past end of __module_info section)\n"; 5487 } else 5488 memcpy(&module, r, sizeof(struct objc_module_t)); 5489 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5490 swapStruct(module); 5491 5492 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 5493 outs() << " version " << module.version << "\n"; 5494 outs() << " size " << module.size << "\n"; 5495 outs() << " name "; 5496 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 5497 if (name != nullptr) 5498 outs() << format("%.*s", left, name); 5499 else 5500 outs() << format("0x%08" PRIx32, module.name) 5501 << "(not in an __OBJC section)"; 5502 outs() << "\n"; 5503 5504 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 5505 if (module.symtab == 0 || r == nullptr) { 5506 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 5507 << " (not in an __OBJC section)\n"; 5508 continue; 5509 } 5510 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 5511 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 5512 defs_left = 0; 5513 defs = nullptr; 5514 if (left < sizeof(struct objc_symtab_t)) { 5515 memcpy(&symtab, r, left); 5516 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 5517 } else { 5518 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 5519 if (left > sizeof(struct objc_symtab_t)) { 5520 defs_left = left - sizeof(struct objc_symtab_t); 5521 defs = r + sizeof(struct objc_symtab_t); 5522 } 5523 } 5524 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5525 swapStruct(symtab); 5526 5527 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 5528 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 5529 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 5530 if (r == nullptr) 5531 outs() << " (not in an __OBJC section)"; 5532 outs() << "\n"; 5533 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 5534 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 5535 if (symtab.cls_def_cnt > 0) 5536 outs() << "\tClass Definitions\n"; 5537 for (j = 0; j < symtab.cls_def_cnt; j++) { 5538 if ((j + 1) * sizeof(uint32_t) > defs_left) { 5539 outs() << "\t(remaining class defs entries entends past the end of the " 5540 << "section)\n"; 5541 break; 5542 } 5543 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 5544 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5545 sys::swapByteOrder(def); 5546 5547 r = get_pointer_32(def, xoffset, left, xS, &info, true); 5548 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 5549 if (r != nullptr) { 5550 if (left > sizeof(struct objc_class_t)) { 5551 outs() << "\n"; 5552 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 5553 } else { 5554 outs() << " (entends past the end of the section)\n"; 5555 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 5556 memcpy(&objc_class, r, left); 5557 } 5558 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5559 swapStruct(objc_class); 5560 print_objc_class_t(&objc_class, &info); 5561 } else { 5562 outs() << "(not in an __OBJC section)\n"; 5563 } 5564 5565 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 5566 outs() << "\tMeta Class"; 5567 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 5568 if (r != nullptr) { 5569 if (left > sizeof(struct objc_class_t)) { 5570 outs() << "\n"; 5571 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 5572 } else { 5573 outs() << " (entends past the end of the section)\n"; 5574 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 5575 memcpy(&objc_class, r, left); 5576 } 5577 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5578 swapStruct(objc_class); 5579 print_objc_class_t(&objc_class, &info); 5580 } else { 5581 outs() << "(not in an __OBJC section)\n"; 5582 } 5583 } 5584 } 5585 if (symtab.cat_def_cnt > 0) 5586 outs() << "\tCategory Definitions\n"; 5587 for (j = 0; j < symtab.cat_def_cnt; j++) { 5588 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 5589 outs() << "\t(remaining category defs entries entends past the end of " 5590 << "the section)\n"; 5591 break; 5592 } 5593 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 5594 sizeof(uint32_t)); 5595 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5596 sys::swapByteOrder(def); 5597 5598 r = get_pointer_32(def, xoffset, left, xS, &info, true); 5599 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 5600 << format("0x%08" PRIx32, def); 5601 if (r != nullptr) { 5602 if (left > sizeof(struct objc_category_t)) { 5603 outs() << "\n"; 5604 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 5605 } else { 5606 outs() << " (entends past the end of the section)\n"; 5607 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 5608 memcpy(&objc_category, r, left); 5609 } 5610 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5611 swapStruct(objc_category); 5612 print_objc_objc_category_t(&objc_category, &info); 5613 } else { 5614 outs() << "(not in an __OBJC section)\n"; 5615 } 5616 } 5617 } 5618 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 5619 if (II != SectionRef()) 5620 print_image_info(II, &info); 5621 5622 return true; 5623 } 5624 5625 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 5626 uint32_t size, uint32_t addr) { 5627 SymbolAddressMap AddrMap; 5628 CreateSymbolAddressMap(O, &AddrMap); 5629 5630 std::vector<SectionRef> Sections; 5631 for (const SectionRef &Section : O->sections()) { 5632 StringRef SectName; 5633 Section.getName(SectName); 5634 Sections.push_back(Section); 5635 } 5636 5637 struct DisassembleInfo info; 5638 // Set up the block of info used by the Symbolizer call backs. 5639 info.verbose = true; 5640 info.O = O; 5641 info.AddrMap = &AddrMap; 5642 info.Sections = &Sections; 5643 info.class_name = nullptr; 5644 info.selector_name = nullptr; 5645 info.method = nullptr; 5646 info.demangled_name = nullptr; 5647 info.bindtable = nullptr; 5648 info.adrp_addr = 0; 5649 info.adrp_inst = 0; 5650 5651 const char *p; 5652 struct objc_protocol_t protocol; 5653 uint32_t left, paddr; 5654 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 5655 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 5656 left = size - (p - sect); 5657 if (left < sizeof(struct objc_protocol_t)) { 5658 outs() << "Protocol extends past end of __protocol section\n"; 5659 memcpy(&protocol, p, left); 5660 } else 5661 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 5662 if (O->isLittleEndian() != sys::IsLittleEndianHost) 5663 swapStruct(protocol); 5664 paddr = addr + (p - sect); 5665 outs() << "Protocol " << format("0x%" PRIx32, paddr); 5666 if (print_protocol(paddr, 0, &info)) 5667 outs() << "(not in an __OBJC section)\n"; 5668 } 5669 } 5670 5671 #ifdef HAVE_LIBXAR 5672 inline void swapStruct(struct xar_header &xar) { 5673 sys::swapByteOrder(xar.magic); 5674 sys::swapByteOrder(xar.size); 5675 sys::swapByteOrder(xar.version); 5676 sys::swapByteOrder(xar.toc_length_compressed); 5677 sys::swapByteOrder(xar.toc_length_uncompressed); 5678 sys::swapByteOrder(xar.cksum_alg); 5679 } 5680 5681 static void PrintModeVerbose(uint32_t mode) { 5682 switch(mode & S_IFMT){ 5683 case S_IFDIR: 5684 outs() << "d"; 5685 break; 5686 case S_IFCHR: 5687 outs() << "c"; 5688 break; 5689 case S_IFBLK: 5690 outs() << "b"; 5691 break; 5692 case S_IFREG: 5693 outs() << "-"; 5694 break; 5695 case S_IFLNK: 5696 outs() << "l"; 5697 break; 5698 case S_IFSOCK: 5699 outs() << "s"; 5700 break; 5701 default: 5702 outs() << "?"; 5703 break; 5704 } 5705 5706 /* owner permissions */ 5707 if(mode & S_IREAD) 5708 outs() << "r"; 5709 else 5710 outs() << "-"; 5711 if(mode & S_IWRITE) 5712 outs() << "w"; 5713 else 5714 outs() << "-"; 5715 if(mode & S_ISUID) 5716 outs() << "s"; 5717 else if(mode & S_IEXEC) 5718 outs() << "x"; 5719 else 5720 outs() << "-"; 5721 5722 /* group permissions */ 5723 if(mode & (S_IREAD >> 3)) 5724 outs() << "r"; 5725 else 5726 outs() << "-"; 5727 if(mode & (S_IWRITE >> 3)) 5728 outs() << "w"; 5729 else 5730 outs() << "-"; 5731 if(mode & S_ISGID) 5732 outs() << "s"; 5733 else if(mode & (S_IEXEC >> 3)) 5734 outs() << "x"; 5735 else 5736 outs() << "-"; 5737 5738 /* other permissions */ 5739 if(mode & (S_IREAD >> 6)) 5740 outs() << "r"; 5741 else 5742 outs() << "-"; 5743 if(mode & (S_IWRITE >> 6)) 5744 outs() << "w"; 5745 else 5746 outs() << "-"; 5747 if(mode & S_ISVTX) 5748 outs() << "t"; 5749 else if(mode & (S_IEXEC >> 6)) 5750 outs() << "x"; 5751 else 5752 outs() << "-"; 5753 } 5754 5755 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { 5756 xar_iter_t xi; 5757 xar_file_t xf; 5758 xar_iter_t xp; 5759 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; 5760 char *endp; 5761 uint32_t mode_value; 5762 5763 xi = xar_iter_new(); 5764 if (!xi) { 5765 errs() << "Can't obtain an xar iterator for xar archive " 5766 << XarFilename << "\n"; 5767 return; 5768 } 5769 5770 // Go through the xar's files. 5771 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { 5772 xp = xar_iter_new(); 5773 if(!xp){ 5774 errs() << "Can't obtain an xar iterator for xar archive " 5775 << XarFilename << "\n"; 5776 return; 5777 } 5778 type = nullptr; 5779 mode = nullptr; 5780 user = nullptr; 5781 group = nullptr; 5782 size = nullptr; 5783 mtime = nullptr; 5784 name = nullptr; 5785 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 5786 const char *val = nullptr; 5787 xar_prop_get(xf, key, &val); 5788 #if 0 // Useful for debugging. 5789 outs() << "key: " << key << " value: " << val << "\n"; 5790 #endif 5791 if(strcmp(key, "type") == 0) 5792 type = val; 5793 if(strcmp(key, "mode") == 0) 5794 mode = val; 5795 if(strcmp(key, "user") == 0) 5796 user = val; 5797 if(strcmp(key, "group") == 0) 5798 group = val; 5799 if(strcmp(key, "data/size") == 0) 5800 size = val; 5801 if(strcmp(key, "mtime") == 0) 5802 mtime = val; 5803 if(strcmp(key, "name") == 0) 5804 name = val; 5805 } 5806 if(mode != nullptr){ 5807 mode_value = strtoul(mode, &endp, 8); 5808 if(*endp != '\0') 5809 outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; 5810 if(strcmp(type, "file") == 0) 5811 mode_value |= S_IFREG; 5812 PrintModeVerbose(mode_value); 5813 outs() << " "; 5814 } 5815 if(user != nullptr) 5816 outs() << format("%10s/", user); 5817 if(group != nullptr) 5818 outs() << format("%-10s ", group); 5819 if(size != nullptr) 5820 outs() << format("%7s ", size); 5821 if(mtime != nullptr){ 5822 for(m = mtime; *m != 'T' && *m != '\0'; m++) 5823 outs() << *m; 5824 if(*m == 'T') 5825 m++; 5826 outs() << " "; 5827 for( ; *m != 'Z' && *m != '\0'; m++) 5828 outs() << *m; 5829 outs() << " "; 5830 } 5831 if(name != nullptr) 5832 outs() << name; 5833 outs() << "\n"; 5834 } 5835 } 5836 5837 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 5838 uint32_t size, bool verbose, 5839 bool PrintXarHeader, bool PrintXarFileHeaders, 5840 std::string XarMemberName) { 5841 if(size < sizeof(struct xar_header)) { 5842 outs() << "size of (__LLVM,__bundle) section too small (smaller than size " 5843 "of struct xar_header)\n"; 5844 return; 5845 } 5846 struct xar_header XarHeader; 5847 memcpy(&XarHeader, sect, sizeof(struct xar_header)); 5848 if (sys::IsLittleEndianHost) 5849 swapStruct(XarHeader); 5850 if (PrintXarHeader) { 5851 if (!XarMemberName.empty()) 5852 outs() << "In xar member " << XarMemberName << ": "; 5853 else 5854 outs() << "For (__LLVM,__bundle) section: "; 5855 outs() << "xar header\n"; 5856 if (XarHeader.magic == XAR_HEADER_MAGIC) 5857 outs() << " magic XAR_HEADER_MAGIC\n"; 5858 else 5859 outs() << " magic " 5860 << format_hex(XarHeader.magic, 10, true) 5861 << " (not XAR_HEADER_MAGIC)\n"; 5862 outs() << " size " << XarHeader.size << "\n"; 5863 outs() << " version " << XarHeader.version << "\n"; 5864 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed 5865 << "\n"; 5866 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed 5867 << "\n"; 5868 outs() << " cksum_alg "; 5869 switch (XarHeader.cksum_alg) { 5870 case XAR_CKSUM_NONE: 5871 outs() << "XAR_CKSUM_NONE\n"; 5872 break; 5873 case XAR_CKSUM_SHA1: 5874 outs() << "XAR_CKSUM_SHA1\n"; 5875 break; 5876 case XAR_CKSUM_MD5: 5877 outs() << "XAR_CKSUM_MD5\n"; 5878 break; 5879 #ifdef XAR_CKSUM_SHA256 5880 case XAR_CKSUM_SHA256: 5881 outs() << "XAR_CKSUM_SHA256\n"; 5882 break; 5883 #endif 5884 #ifdef XAR_CKSUM_SHA512 5885 case XAR_CKSUM_SHA512: 5886 outs() << "XAR_CKSUM_SHA512\n"; 5887 break; 5888 #endif 5889 default: 5890 outs() << XarHeader.cksum_alg << "\n"; 5891 } 5892 } 5893 5894 SmallString<128> XarFilename; 5895 int FD; 5896 std::error_code XarEC = 5897 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); 5898 if (XarEC) { 5899 errs() << XarEC.message() << "\n"; 5900 return; 5901 } 5902 tool_output_file XarFile(XarFilename, FD); 5903 raw_fd_ostream &XarOut = XarFile.os(); 5904 StringRef XarContents(sect, size); 5905 XarOut << XarContents; 5906 XarOut.close(); 5907 if (XarOut.has_error()) 5908 return; 5909 5910 xar_t xar = xar_open(XarFilename.c_str(), READ); 5911 if (!xar) { 5912 errs() << "Can't create temporary xar archive " << XarFilename << "\n"; 5913 return; 5914 } 5915 5916 SmallString<128> TocFilename; 5917 std::error_code TocEC = 5918 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); 5919 if (TocEC) { 5920 errs() << TocEC.message() << "\n"; 5921 return; 5922 } 5923 xar_serialize(xar, TocFilename.c_str()); 5924 5925 if (PrintXarFileHeaders) { 5926 if (!XarMemberName.empty()) 5927 outs() << "In xar member " << XarMemberName << ": "; 5928 else 5929 outs() << "For (__LLVM,__bundle) section: "; 5930 outs() << "xar archive files:\n"; 5931 PrintXarFilesSummary(XarFilename.c_str(), xar); 5932 } 5933 5934 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 5935 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); 5936 if (std::error_code EC = FileOrErr.getError()) { 5937 errs() << EC.message() << "\n"; 5938 return; 5939 } 5940 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 5941 5942 if (!XarMemberName.empty()) 5943 outs() << "In xar member " << XarMemberName << ": "; 5944 else 5945 outs() << "For (__LLVM,__bundle) section: "; 5946 outs() << "xar table of contents:\n"; 5947 outs() << Buffer->getBuffer() << "\n"; 5948 5949 // TODO: Go through the xar's files. 5950 xar_iter_t xi = xar_iter_new(); 5951 if(!xi){ 5952 errs() << "Can't obtain an xar iterator for xar archive " 5953 << XarFilename.c_str() << "\n"; 5954 xar_close(xar); 5955 return; 5956 } 5957 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ 5958 const char *key; 5959 xar_iter_t xp; 5960 const char *member_name, *member_type, *member_size_string; 5961 size_t member_size; 5962 5963 xp = xar_iter_new(); 5964 if(!xp){ 5965 errs() << "Can't obtain an xar iterator for xar archive " 5966 << XarFilename.c_str() << "\n"; 5967 xar_close(xar); 5968 return; 5969 } 5970 member_name = NULL; 5971 member_type = NULL; 5972 member_size_string = NULL; 5973 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 5974 const char *val = nullptr; 5975 xar_prop_get(xf, key, &val); 5976 #if 0 // Useful for debugging. 5977 outs() << "key: " << key << " value: " << val << "\n"; 5978 #endif 5979 if(strcmp(key, "name") == 0) 5980 member_name = val; 5981 if(strcmp(key, "type") == 0) 5982 member_type = val; 5983 if(strcmp(key, "data/size") == 0) 5984 member_size_string = val; 5985 } 5986 /* 5987 * If we find a file with a name, date/size and type properties 5988 * and with the type being "file" see if that is a xar file. 5989 */ 5990 if (member_name != NULL && member_type != NULL && 5991 strcmp(member_type, "file") == 0 && 5992 member_size_string != NULL){ 5993 // Extract the file into a buffer. 5994 char *endptr; 5995 member_size = strtoul(member_size_string, &endptr, 10); 5996 if (*endptr == '\0' && member_size != 0) { 5997 char *buffer = (char *) ::operator new (member_size); 5998 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { 5999 #if 0 // Useful for debugging. 6000 outs() << "xar member: " << member_name << " extracted\n"; 6001 #endif 6002 // Set the XarMemberName we want to see printed in the header. 6003 std::string OldXarMemberName; 6004 // If XarMemberName is already set this is nested. So 6005 // save the old name and create the nested name. 6006 if (!XarMemberName.empty()) { 6007 OldXarMemberName = XarMemberName; 6008 XarMemberName = 6009 (Twine("[") + XarMemberName + "]" + member_name).str(); 6010 } else { 6011 OldXarMemberName = ""; 6012 XarMemberName = member_name; 6013 } 6014 // See if this is could be a xar file (nested). 6015 if (member_size >= sizeof(struct xar_header)) { 6016 #if 0 // Useful for debugging. 6017 outs() << "could be a xar file: " << member_name << "\n"; 6018 #endif 6019 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); 6020 if (sys::IsLittleEndianHost) 6021 swapStruct(XarHeader); 6022 if(XarHeader.magic == XAR_HEADER_MAGIC) 6023 DumpBitcodeSection(O, buffer, member_size, verbose, 6024 PrintXarHeader, PrintXarFileHeaders, 6025 XarMemberName); 6026 } 6027 XarMemberName = OldXarMemberName; 6028 } 6029 delete buffer; 6030 } 6031 } 6032 xar_iter_free(xp); 6033 } 6034 xar_close(xar); 6035 } 6036 #endif // defined(HAVE_LIBXAR) 6037 6038 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6039 if (O->is64Bit()) 6040 printObjc2_64bit_MetaData(O, verbose); 6041 else { 6042 MachO::mach_header H; 6043 H = O->getHeader(); 6044 if (H.cputype == MachO::CPU_TYPE_ARM) 6045 printObjc2_32bit_MetaData(O, verbose); 6046 else { 6047 // This is the 32-bit non-arm cputype case. Which is normally 6048 // the first Objective-C ABI. But it may be the case of a 6049 // binary for the iOS simulator which is the second Objective-C 6050 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6051 // and return false. 6052 if (!printObjc1_32bit_MetaData(O, verbose)) 6053 printObjc2_32bit_MetaData(O, verbose); 6054 } 6055 } 6056 } 6057 6058 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6059 // for the address passed in as ReferenceValue for printing as a comment with 6060 // the instruction and also returns the corresponding type of that item 6061 // indirectly through ReferenceType. 6062 // 6063 // If ReferenceValue is an address of literal cstring then a pointer to the 6064 // cstring is returned and ReferenceType is set to 6065 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6066 // 6067 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6068 // Class ref that name is returned and the ReferenceType is set accordingly. 6069 // 6070 // Lastly, literals which are Symbol address in a literal pool are looked for 6071 // and if found the symbol name is returned and ReferenceType is set to 6072 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6073 // 6074 // If there is no item in the Mach-O file for the address passed in as 6075 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6076 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6077 uint64_t ReferencePC, 6078 uint64_t *ReferenceType, 6079 struct DisassembleInfo *info) { 6080 // First see if there is an external relocation entry at the ReferencePC. 6081 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6082 uint64_t sect_addr = info->S.getAddress(); 6083 uint64_t sect_offset = ReferencePC - sect_addr; 6084 bool reloc_found = false; 6085 DataRefImpl Rel; 6086 MachO::any_relocation_info RE; 6087 bool isExtern = false; 6088 SymbolRef Symbol; 6089 for (const RelocationRef &Reloc : info->S.relocations()) { 6090 uint64_t RelocOffset = Reloc.getOffset(); 6091 if (RelocOffset == sect_offset) { 6092 Rel = Reloc.getRawDataRefImpl(); 6093 RE = info->O->getRelocation(Rel); 6094 if (info->O->isRelocationScattered(RE)) 6095 continue; 6096 isExtern = info->O->getPlainRelocationExternal(RE); 6097 if (isExtern) { 6098 symbol_iterator RelocSym = Reloc.getSymbol(); 6099 Symbol = *RelocSym; 6100 } 6101 reloc_found = true; 6102 break; 6103 } 6104 } 6105 // If there is an external relocation entry for a symbol in a section 6106 // then used that symbol's value for the value of the reference. 6107 if (reloc_found && isExtern) { 6108 if (info->O->getAnyRelocationPCRel(RE)) { 6109 unsigned Type = info->O->getAnyRelocationType(RE); 6110 if (Type == MachO::X86_64_RELOC_SIGNED) { 6111 ReferenceValue = Symbol.getValue(); 6112 } 6113 } 6114 } 6115 } 6116 6117 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6118 // Message refs and Class refs. 6119 bool classref, selref, msgref, cfstring; 6120 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6121 selref, msgref, cfstring); 6122 if (classref && pointer_value == 0) { 6123 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6124 // And the pointer_value in that section is typically zero as it will be 6125 // set by dyld as part of the "bind information". 6126 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6127 if (name != nullptr) { 6128 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6129 const char *class_name = strrchr(name, '$'); 6130 if (class_name != nullptr && class_name[1] == '_' && 6131 class_name[2] != '\0') { 6132 info->class_name = class_name + 2; 6133 return name; 6134 } 6135 } 6136 } 6137 6138 if (classref) { 6139 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6140 const char *name = 6141 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6142 if (name != nullptr) 6143 info->class_name = name; 6144 else 6145 name = "bad class ref"; 6146 return name; 6147 } 6148 6149 if (cfstring) { 6150 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6151 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6152 return name; 6153 } 6154 6155 if (selref && pointer_value == 0) 6156 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6157 6158 if (pointer_value != 0) 6159 ReferenceValue = pointer_value; 6160 6161 const char *name = GuessCstringPointer(ReferenceValue, info); 6162 if (name) { 6163 if (pointer_value != 0 && selref) { 6164 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6165 info->selector_name = name; 6166 } else if (pointer_value != 0 && msgref) { 6167 info->class_name = nullptr; 6168 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6169 info->selector_name = name; 6170 } else 6171 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6172 return name; 6173 } 6174 6175 // Lastly look for an indirect symbol with this ReferenceValue which is in 6176 // a literal pool. If found return that symbol name. 6177 name = GuessIndirectSymbol(ReferenceValue, info); 6178 if (name) { 6179 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6180 return name; 6181 } 6182 6183 return nullptr; 6184 } 6185 6186 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6187 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6188 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6189 // is created and returns the symbol name that matches the ReferenceValue or 6190 // nullptr if none. The ReferenceType is passed in for the IN type of 6191 // reference the instruction is making from the values in defined in the header 6192 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6193 // Out type and the ReferenceName will also be set which is added as a comment 6194 // to the disassembled instruction. 6195 // 6196 // If the symbol name is a C++ mangled name then the demangled name is 6197 // returned through ReferenceName and ReferenceType is set to 6198 // LLVMDisassembler_ReferenceType_DeMangled_Name . 6199 // 6200 // When this is called to get a symbol name for a branch target then the 6201 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 6202 // SymbolValue will be looked for in the indirect symbol table to determine if 6203 // it is an address for a symbol stub. If so then the symbol name for that 6204 // stub is returned indirectly through ReferenceName and then ReferenceType is 6205 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 6206 // 6207 // When this is called with an value loaded via a PC relative load then 6208 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 6209 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 6210 // or an Objective-C meta data reference. If so the output ReferenceType is 6211 // set to correspond to that as well as setting the ReferenceName. 6212 static const char *SymbolizerSymbolLookUp(void *DisInfo, 6213 uint64_t ReferenceValue, 6214 uint64_t *ReferenceType, 6215 uint64_t ReferencePC, 6216 const char **ReferenceName) { 6217 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 6218 // If no verbose symbolic information is wanted then just return nullptr. 6219 if (!info->verbose) { 6220 *ReferenceName = nullptr; 6221 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6222 return nullptr; 6223 } 6224 6225 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 6226 6227 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 6228 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 6229 if (*ReferenceName != nullptr) { 6230 method_reference(info, ReferenceType, ReferenceName); 6231 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 6232 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 6233 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6234 if (info->demangled_name != nullptr) 6235 free(info->demangled_name); 6236 int status; 6237 info->demangled_name = 6238 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6239 if (info->demangled_name != nullptr) { 6240 *ReferenceName = info->demangled_name; 6241 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6242 } else 6243 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6244 } else 6245 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6246 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 6247 *ReferenceName = 6248 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6249 if (*ReferenceName) 6250 method_reference(info, ReferenceType, ReferenceName); 6251 else 6252 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6253 // If this is arm64 and the reference is an adrp instruction save the 6254 // instruction, passed in ReferenceValue and the address of the instruction 6255 // for use later if we see and add immediate instruction. 6256 } else if (info->O->getArch() == Triple::aarch64 && 6257 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 6258 info->adrp_inst = ReferenceValue; 6259 info->adrp_addr = ReferencePC; 6260 SymbolName = nullptr; 6261 *ReferenceName = nullptr; 6262 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6263 // If this is arm64 and reference is an add immediate instruction and we 6264 // have 6265 // seen an adrp instruction just before it and the adrp's Xd register 6266 // matches 6267 // this add's Xn register reconstruct the value being referenced and look to 6268 // see if it is a literal pointer. Note the add immediate instruction is 6269 // passed in ReferenceValue. 6270 } else if (info->O->getArch() == Triple::aarch64 && 6271 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 6272 ReferencePC - 4 == info->adrp_addr && 6273 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6274 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6275 uint32_t addxri_inst; 6276 uint64_t adrp_imm, addxri_imm; 6277 6278 adrp_imm = 6279 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6280 if (info->adrp_inst & 0x0200000) 6281 adrp_imm |= 0xfffffffffc000000LL; 6282 6283 addxri_inst = ReferenceValue; 6284 addxri_imm = (addxri_inst >> 10) & 0xfff; 6285 if (((addxri_inst >> 22) & 0x3) == 1) 6286 addxri_imm <<= 12; 6287 6288 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6289 (adrp_imm << 12) + addxri_imm; 6290 6291 *ReferenceName = 6292 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6293 if (*ReferenceName == nullptr) 6294 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6295 // If this is arm64 and the reference is a load register instruction and we 6296 // have seen an adrp instruction just before it and the adrp's Xd register 6297 // matches this add's Xn register reconstruct the value being referenced and 6298 // look to see if it is a literal pointer. Note the load register 6299 // instruction is passed in ReferenceValue. 6300 } else if (info->O->getArch() == Triple::aarch64 && 6301 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 6302 ReferencePC - 4 == info->adrp_addr && 6303 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6304 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6305 uint32_t ldrxui_inst; 6306 uint64_t adrp_imm, ldrxui_imm; 6307 6308 adrp_imm = 6309 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6310 if (info->adrp_inst & 0x0200000) 6311 adrp_imm |= 0xfffffffffc000000LL; 6312 6313 ldrxui_inst = ReferenceValue; 6314 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 6315 6316 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6317 (adrp_imm << 12) + (ldrxui_imm << 3); 6318 6319 *ReferenceName = 6320 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6321 if (*ReferenceName == nullptr) 6322 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6323 } 6324 // If this arm64 and is an load register (PC-relative) instruction the 6325 // ReferenceValue is the PC plus the immediate value. 6326 else if (info->O->getArch() == Triple::aarch64 && 6327 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 6328 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 6329 *ReferenceName = 6330 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6331 if (*ReferenceName == nullptr) 6332 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6333 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6334 if (info->demangled_name != nullptr) 6335 free(info->demangled_name); 6336 int status; 6337 info->demangled_name = 6338 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6339 if (info->demangled_name != nullptr) { 6340 *ReferenceName = info->demangled_name; 6341 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6342 } 6343 } 6344 else { 6345 *ReferenceName = nullptr; 6346 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6347 } 6348 6349 return SymbolName; 6350 } 6351 6352 /// \brief Emits the comments that are stored in the CommentStream. 6353 /// Each comment in the CommentStream must end with a newline. 6354 static void emitComments(raw_svector_ostream &CommentStream, 6355 SmallString<128> &CommentsToEmit, 6356 formatted_raw_ostream &FormattedOS, 6357 const MCAsmInfo &MAI) { 6358 // Flush the stream before taking its content. 6359 StringRef Comments = CommentsToEmit.str(); 6360 // Get the default information for printing a comment. 6361 StringRef CommentBegin = MAI.getCommentString(); 6362 unsigned CommentColumn = MAI.getCommentColumn(); 6363 bool IsFirst = true; 6364 while (!Comments.empty()) { 6365 if (!IsFirst) 6366 FormattedOS << '\n'; 6367 // Emit a line of comments. 6368 FormattedOS.PadToColumn(CommentColumn); 6369 size_t Position = Comments.find('\n'); 6370 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 6371 // Move after the newline character. 6372 Comments = Comments.substr(Position + 1); 6373 IsFirst = false; 6374 } 6375 FormattedOS.flush(); 6376 6377 // Tell the comment stream that the vector changed underneath it. 6378 CommentsToEmit.clear(); 6379 } 6380 6381 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 6382 StringRef DisSegName, StringRef DisSectName) { 6383 const char *McpuDefault = nullptr; 6384 const Target *ThumbTarget = nullptr; 6385 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 6386 if (!TheTarget) { 6387 // GetTarget prints out stuff. 6388 return; 6389 } 6390 if (MCPU.empty() && McpuDefault) 6391 MCPU = McpuDefault; 6392 6393 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 6394 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 6395 if (ThumbTarget) 6396 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 6397 6398 // Package up features to be passed to target/subtarget 6399 std::string FeaturesStr; 6400 if (MAttrs.size()) { 6401 SubtargetFeatures Features; 6402 for (unsigned i = 0; i != MAttrs.size(); ++i) 6403 Features.AddFeature(MAttrs[i]); 6404 FeaturesStr = Features.getString(); 6405 } 6406 6407 // Set up disassembler. 6408 std::unique_ptr<const MCRegisterInfo> MRI( 6409 TheTarget->createMCRegInfo(TripleName)); 6410 std::unique_ptr<const MCAsmInfo> AsmInfo( 6411 TheTarget->createMCAsmInfo(*MRI, TripleName)); 6412 std::unique_ptr<const MCSubtargetInfo> STI( 6413 TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); 6414 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 6415 std::unique_ptr<MCDisassembler> DisAsm( 6416 TheTarget->createMCDisassembler(*STI, Ctx)); 6417 std::unique_ptr<MCSymbolizer> Symbolizer; 6418 struct DisassembleInfo SymbolizerInfo; 6419 std::unique_ptr<MCRelocationInfo> RelInfo( 6420 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 6421 if (RelInfo) { 6422 Symbolizer.reset(TheTarget->createMCSymbolizer( 6423 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6424 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 6425 DisAsm->setSymbolizer(std::move(Symbolizer)); 6426 } 6427 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 6428 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 6429 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 6430 // Set the display preference for hex vs. decimal immediates. 6431 IP->setPrintImmHex(PrintImmHex); 6432 // Comment stream and backing vector. 6433 SmallString<128> CommentsToEmit; 6434 raw_svector_ostream CommentStream(CommentsToEmit); 6435 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 6436 // if it is done then arm64 comments for string literals don't get printed 6437 // and some constant get printed instead and not setting it causes intel 6438 // (32-bit and 64-bit) comments printed with different spacing before the 6439 // comment causing different diffs with the 'C' disassembler library API. 6440 // IP->setCommentStream(CommentStream); 6441 6442 if (!AsmInfo || !STI || !DisAsm || !IP) { 6443 errs() << "error: couldn't initialize disassembler for target " 6444 << TripleName << '\n'; 6445 return; 6446 } 6447 6448 // Set up separate thumb disassembler if needed. 6449 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 6450 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 6451 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 6452 std::unique_ptr<MCDisassembler> ThumbDisAsm; 6453 std::unique_ptr<MCInstPrinter> ThumbIP; 6454 std::unique_ptr<MCContext> ThumbCtx; 6455 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 6456 struct DisassembleInfo ThumbSymbolizerInfo; 6457 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 6458 if (ThumbTarget) { 6459 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 6460 ThumbAsmInfo.reset( 6461 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName)); 6462 ThumbSTI.reset( 6463 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MCPU, FeaturesStr)); 6464 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 6465 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 6466 MCContext *PtrThumbCtx = ThumbCtx.get(); 6467 ThumbRelInfo.reset( 6468 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 6469 if (ThumbRelInfo) { 6470 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 6471 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 6472 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 6473 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 6474 } 6475 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 6476 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 6477 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 6478 *ThumbInstrInfo, *ThumbMRI)); 6479 // Set the display preference for hex vs. decimal immediates. 6480 ThumbIP->setPrintImmHex(PrintImmHex); 6481 } 6482 6483 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) { 6484 errs() << "error: couldn't initialize disassembler for target " 6485 << ThumbTripleName << '\n'; 6486 return; 6487 } 6488 6489 MachO::mach_header Header = MachOOF->getHeader(); 6490 6491 // FIXME: Using the -cfg command line option, this code used to be able to 6492 // annotate relocations with the referenced symbol's name, and if this was 6493 // inside a __[cf]string section, the data it points to. This is now replaced 6494 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 6495 std::vector<SectionRef> Sections; 6496 std::vector<SymbolRef> Symbols; 6497 SmallVector<uint64_t, 8> FoundFns; 6498 uint64_t BaseSegmentAddress; 6499 6500 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 6501 BaseSegmentAddress); 6502 6503 // Sort the symbols by address, just in case they didn't come in that way. 6504 std::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); 6505 6506 // Build a data in code table that is sorted on by the address of each entry. 6507 uint64_t BaseAddress = 0; 6508 if (Header.filetype == MachO::MH_OBJECT) 6509 BaseAddress = Sections[0].getAddress(); 6510 else 6511 BaseAddress = BaseSegmentAddress; 6512 DiceTable Dices; 6513 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 6514 DI != DE; ++DI) { 6515 uint32_t Offset; 6516 DI->getOffset(Offset); 6517 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 6518 } 6519 array_pod_sort(Dices.begin(), Dices.end()); 6520 6521 #ifndef NDEBUG 6522 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); 6523 #else 6524 raw_ostream &DebugOut = nulls(); 6525 #endif 6526 6527 std::unique_ptr<DIContext> diContext; 6528 ObjectFile *DbgObj = MachOOF; 6529 // Try to find debug info and set up the DIContext for it. 6530 if (UseDbg) { 6531 // A separate DSym file path was specified, parse it as a macho file, 6532 // get the sections and supply it to the section name parsing machinery. 6533 if (!DSYMFile.empty()) { 6534 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 6535 MemoryBuffer::getFileOrSTDIN(DSYMFile); 6536 if (std::error_code EC = BufOrErr.getError()) { 6537 errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n'; 6538 return; 6539 } 6540 DbgObj = 6541 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()) 6542 .get() 6543 .release(); 6544 } 6545 6546 // Setup the DIContext 6547 diContext.reset(new DWARFContextInMemory(*DbgObj)); 6548 } 6549 6550 if (FilterSections.size() == 0) 6551 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 6552 6553 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 6554 StringRef SectName; 6555 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName) 6556 continue; 6557 6558 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 6559 6560 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 6561 if (SegmentName != DisSegName) 6562 continue; 6563 6564 StringRef BytesStr; 6565 Sections[SectIdx].getContents(BytesStr); 6566 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()), 6567 BytesStr.size()); 6568 uint64_t SectAddress = Sections[SectIdx].getAddress(); 6569 6570 bool symbolTableWorked = false; 6571 6572 // Create a map of symbol addresses to symbol names for use by 6573 // the SymbolizerSymbolLookUp() routine. 6574 SymbolAddressMap AddrMap; 6575 bool DisSymNameFound = false; 6576 for (const SymbolRef &Symbol : MachOOF->symbols()) { 6577 Expected<SymbolRef::Type> STOrErr = Symbol.getType(); 6578 if (!STOrErr) 6579 report_error(MachOOF->getFileName(), STOrErr.takeError()); 6580 SymbolRef::Type ST = *STOrErr; 6581 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 6582 ST == SymbolRef::ST_Other) { 6583 uint64_t Address = Symbol.getValue(); 6584 Expected<StringRef> SymNameOrErr = Symbol.getName(); 6585 if (!SymNameOrErr) 6586 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 6587 StringRef SymName = *SymNameOrErr; 6588 AddrMap[Address] = SymName; 6589 if (!DisSymName.empty() && DisSymName == SymName) 6590 DisSymNameFound = true; 6591 } 6592 } 6593 if (!DisSymName.empty() && !DisSymNameFound) { 6594 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 6595 return; 6596 } 6597 // Set up the block of info used by the Symbolizer call backs. 6598 SymbolizerInfo.verbose = !NoSymbolicOperands; 6599 SymbolizerInfo.O = MachOOF; 6600 SymbolizerInfo.S = Sections[SectIdx]; 6601 SymbolizerInfo.AddrMap = &AddrMap; 6602 SymbolizerInfo.Sections = &Sections; 6603 SymbolizerInfo.class_name = nullptr; 6604 SymbolizerInfo.selector_name = nullptr; 6605 SymbolizerInfo.method = nullptr; 6606 SymbolizerInfo.demangled_name = nullptr; 6607 SymbolizerInfo.bindtable = nullptr; 6608 SymbolizerInfo.adrp_addr = 0; 6609 SymbolizerInfo.adrp_inst = 0; 6610 // Same for the ThumbSymbolizer 6611 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands; 6612 ThumbSymbolizerInfo.O = MachOOF; 6613 ThumbSymbolizerInfo.S = Sections[SectIdx]; 6614 ThumbSymbolizerInfo.AddrMap = &AddrMap; 6615 ThumbSymbolizerInfo.Sections = &Sections; 6616 ThumbSymbolizerInfo.class_name = nullptr; 6617 ThumbSymbolizerInfo.selector_name = nullptr; 6618 ThumbSymbolizerInfo.method = nullptr; 6619 ThumbSymbolizerInfo.demangled_name = nullptr; 6620 ThumbSymbolizerInfo.bindtable = nullptr; 6621 ThumbSymbolizerInfo.adrp_addr = 0; 6622 ThumbSymbolizerInfo.adrp_inst = 0; 6623 6624 unsigned int Arch = MachOOF->getArch(); 6625 6626 // Skip all symbols if this is a stubs file. 6627 if (Bytes.size() == 0) 6628 return; 6629 6630 // If the section has symbols but no symbol at the start of the section 6631 // these are used to make sure the bytes before the first symbol are 6632 // disassembled. 6633 bool FirstSymbol = true; 6634 bool FirstSymbolAtSectionStart = true; 6635 6636 // Disassemble symbol by symbol. 6637 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 6638 Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName(); 6639 if (!SymNameOrErr) 6640 report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); 6641 StringRef SymName = *SymNameOrErr; 6642 6643 Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType(); 6644 if (!STOrErr) 6645 report_error(MachOOF->getFileName(), STOrErr.takeError()); 6646 SymbolRef::Type ST = *STOrErr; 6647 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 6648 continue; 6649 6650 // Make sure the symbol is defined in this section. 6651 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 6652 if (!containsSym) { 6653 if (!DisSymName.empty() && DisSymName == SymName) { 6654 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 6655 return; 6656 } 6657 continue; 6658 } 6659 // The __mh_execute_header is special and we need to deal with that fact 6660 // this symbol is before the start of the (__TEXT,__text) section and at the 6661 // address of the start of the __TEXT segment. This is because this symbol 6662 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 6663 // start of the section in a standard MH_EXECUTE filetype. 6664 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 6665 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 6666 return; 6667 } 6668 // When this code is trying to disassemble a symbol at a time and in the 6669 // case there is only the __mh_execute_header symbol left as in a stripped 6670 // executable, we need to deal with this by ignoring this symbol so the 6671 // whole section is disassembled and this symbol is then not displayed. 6672 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 6673 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 6674 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 6675 continue; 6676 6677 // If we are only disassembling one symbol see if this is that symbol. 6678 if (!DisSymName.empty() && DisSymName != SymName) 6679 continue; 6680 6681 // Start at the address of the symbol relative to the section's address. 6682 uint64_t SectSize = Sections[SectIdx].getSize(); 6683 uint64_t Start = Symbols[SymIdx].getValue(); 6684 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 6685 Start -= SectionAddress; 6686 6687 if (Start > SectSize) { 6688 outs() << "section data ends, " << SymName 6689 << " lies outside valid range\n"; 6690 return; 6691 } 6692 6693 // Stop disassembling either at the beginning of the next symbol or at 6694 // the end of the section. 6695 bool containsNextSym = false; 6696 uint64_t NextSym = 0; 6697 uint64_t NextSymIdx = SymIdx + 1; 6698 while (Symbols.size() > NextSymIdx) { 6699 Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType(); 6700 if (!STOrErr) 6701 report_error(MachOOF->getFileName(), STOrErr.takeError()); 6702 SymbolRef::Type NextSymType = *STOrErr; 6703 if (NextSymType == SymbolRef::ST_Function) { 6704 containsNextSym = 6705 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 6706 NextSym = Symbols[NextSymIdx].getValue(); 6707 NextSym -= SectionAddress; 6708 break; 6709 } 6710 ++NextSymIdx; 6711 } 6712 6713 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 6714 uint64_t Size; 6715 6716 symbolTableWorked = true; 6717 6718 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 6719 bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb; 6720 6721 // We only need the dedicated Thumb target if there's a real choice 6722 // (i.e. we're not targeting M-class) and the function is Thumb. 6723 bool UseThumbTarget = IsThumb && ThumbTarget; 6724 6725 // If we are not specifying a symbol to start disassembly with and this 6726 // is the first symbol in the section but not at the start of the section 6727 // then move the disassembly index to the start of the section and 6728 // don't print the symbol name just yet. This is so the bytes before the 6729 // first symbol are disassembled. 6730 uint64_t SymbolStart = Start; 6731 if (DisSymName.empty() && FirstSymbol && Start != 0) { 6732 FirstSymbolAtSectionStart = false; 6733 Start = 0; 6734 } 6735 else 6736 outs() << SymName << ":\n"; 6737 6738 DILineInfo lastLine; 6739 for (uint64_t Index = Start; Index < End; Index += Size) { 6740 MCInst Inst; 6741 6742 // If this is the first symbol in the section and it was not at the 6743 // start of the section, see if we are at its Index now and if so print 6744 // the symbol name. 6745 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 6746 outs() << SymName << ":\n"; 6747 6748 uint64_t PC = SectAddress + Index; 6749 if (!NoLeadingAddr) { 6750 if (FullLeadingAddr) { 6751 if (MachOOF->is64Bit()) 6752 outs() << format("%016" PRIx64, PC); 6753 else 6754 outs() << format("%08" PRIx64, PC); 6755 } else { 6756 outs() << format("%8" PRIx64 ":", PC); 6757 } 6758 } 6759 if (!NoShowRawInsn || Arch == Triple::arm) 6760 outs() << "\t"; 6761 6762 // Check the data in code table here to see if this is data not an 6763 // instruction to be disassembled. 6764 DiceTable Dice; 6765 Dice.push_back(std::make_pair(PC, DiceRef())); 6766 dice_table_iterator DTI = 6767 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 6768 compareDiceTableEntries); 6769 if (DTI != Dices.end()) { 6770 uint16_t Length; 6771 DTI->second.getLength(Length); 6772 uint16_t Kind; 6773 DTI->second.getKind(Kind); 6774 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind); 6775 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 6776 (PC == (DTI->first + Length - 1)) && (Length & 1)) 6777 Size++; 6778 continue; 6779 } 6780 6781 SmallVector<char, 64> AnnotationsBytes; 6782 raw_svector_ostream Annotations(AnnotationsBytes); 6783 6784 bool gotInst; 6785 if (UseThumbTarget) 6786 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 6787 PC, DebugOut, Annotations); 6788 else 6789 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 6790 DebugOut, Annotations); 6791 if (gotInst) { 6792 if (!NoShowRawInsn || Arch == Triple::arm) { 6793 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); 6794 } 6795 formatted_raw_ostream FormattedOS(outs()); 6796 StringRef AnnotationsStr = Annotations.str(); 6797 if (UseThumbTarget) 6798 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI); 6799 else 6800 IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI); 6801 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 6802 6803 // Print debug info. 6804 if (diContext) { 6805 DILineInfo dli = diContext->getLineInfoForAddress(PC); 6806 // Print valid line info if it changed. 6807 if (dli != lastLine && dli.Line != 0) 6808 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 6809 << dli.Column; 6810 lastLine = dli; 6811 } 6812 outs() << "\n"; 6813 } else { 6814 unsigned int Arch = MachOOF->getArch(); 6815 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 6816 outs() << format("\t.byte 0x%02x #bad opcode\n", 6817 *(Bytes.data() + Index) & 0xff); 6818 Size = 1; // skip exactly one illegible byte and move on. 6819 } else if (Arch == Triple::aarch64 || 6820 (Arch == Triple::arm && !IsThumb)) { 6821 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 6822 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 6823 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 6824 (*(Bytes.data() + Index + 3) & 0xff) << 24; 6825 outs() << format("\t.long\t0x%08x\n", opcode); 6826 Size = 4; 6827 } else if (Arch == Triple::arm) { 6828 assert(IsThumb && "ARM mode should have been dealt with above"); 6829 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 6830 (*(Bytes.data() + Index + 1) & 0xff) << 8; 6831 outs() << format("\t.short\t0x%04x\n", opcode); 6832 Size = 2; 6833 } else{ 6834 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 6835 if (Size == 0) 6836 Size = 1; // skip illegible bytes 6837 } 6838 } 6839 } 6840 // Now that we are done disassembled the first symbol set the bool that 6841 // were doing this to false. 6842 FirstSymbol = false; 6843 } 6844 if (!symbolTableWorked) { 6845 // Reading the symbol table didn't work, disassemble the whole section. 6846 uint64_t SectAddress = Sections[SectIdx].getAddress(); 6847 uint64_t SectSize = Sections[SectIdx].getSize(); 6848 uint64_t InstSize; 6849 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 6850 MCInst Inst; 6851 6852 uint64_t PC = SectAddress + Index; 6853 SmallVector<char, 64> AnnotationsBytes; 6854 raw_svector_ostream Annotations(AnnotationsBytes); 6855 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 6856 DebugOut, Annotations)) { 6857 if (!NoLeadingAddr) { 6858 if (FullLeadingAddr) { 6859 if (MachOOF->is64Bit()) 6860 outs() << format("%016" PRIx64, PC); 6861 else 6862 outs() << format("%08" PRIx64, PC); 6863 } else { 6864 outs() << format("%8" PRIx64 ":", PC); 6865 } 6866 } 6867 if (!NoShowRawInsn || Arch == Triple::arm) { 6868 outs() << "\t"; 6869 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); 6870 } 6871 StringRef AnnotationsStr = Annotations.str(); 6872 IP->printInst(&Inst, outs(), AnnotationsStr, *STI); 6873 outs() << "\n"; 6874 } else { 6875 unsigned int Arch = MachOOF->getArch(); 6876 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 6877 outs() << format("\t.byte 0x%02x #bad opcode\n", 6878 *(Bytes.data() + Index) & 0xff); 6879 InstSize = 1; // skip exactly one illegible byte and move on. 6880 } else { 6881 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 6882 if (InstSize == 0) 6883 InstSize = 1; // skip illegible bytes 6884 } 6885 } 6886 } 6887 } 6888 // The TripleName's need to be reset if we are called again for a different 6889 // archtecture. 6890 TripleName = ""; 6891 ThumbTripleName = ""; 6892 6893 if (SymbolizerInfo.method != nullptr) 6894 free(SymbolizerInfo.method); 6895 if (SymbolizerInfo.demangled_name != nullptr) 6896 free(SymbolizerInfo.demangled_name); 6897 if (ThumbSymbolizerInfo.method != nullptr) 6898 free(ThumbSymbolizerInfo.method); 6899 if (ThumbSymbolizerInfo.demangled_name != nullptr) 6900 free(ThumbSymbolizerInfo.demangled_name); 6901 } 6902 } 6903 6904 //===----------------------------------------------------------------------===// 6905 // __compact_unwind section dumping 6906 //===----------------------------------------------------------------------===// 6907 6908 namespace { 6909 6910 template <typename T> static uint64_t readNext(const char *&Buf) { 6911 using llvm::support::little; 6912 using llvm::support::unaligned; 6913 6914 uint64_t Val = support::endian::read<T, little, unaligned>(Buf); 6915 Buf += sizeof(T); 6916 return Val; 6917 } 6918 6919 struct CompactUnwindEntry { 6920 uint32_t OffsetInSection; 6921 6922 uint64_t FunctionAddr; 6923 uint32_t Length; 6924 uint32_t CompactEncoding; 6925 uint64_t PersonalityAddr; 6926 uint64_t LSDAAddr; 6927 6928 RelocationRef FunctionReloc; 6929 RelocationRef PersonalityReloc; 6930 RelocationRef LSDAReloc; 6931 6932 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 6933 : OffsetInSection(Offset) { 6934 if (Is64) 6935 read<uint64_t>(Contents.data() + Offset); 6936 else 6937 read<uint32_t>(Contents.data() + Offset); 6938 } 6939 6940 private: 6941 template <typename UIntPtr> void read(const char *Buf) { 6942 FunctionAddr = readNext<UIntPtr>(Buf); 6943 Length = readNext<uint32_t>(Buf); 6944 CompactEncoding = readNext<uint32_t>(Buf); 6945 PersonalityAddr = readNext<UIntPtr>(Buf); 6946 LSDAAddr = readNext<UIntPtr>(Buf); 6947 } 6948 }; 6949 } 6950 6951 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 6952 /// and data being relocated, determine the best base Name and Addend to use for 6953 /// display purposes. 6954 /// 6955 /// 1. An Extern relocation will directly reference a symbol (and the data is 6956 /// then already an addend), so use that. 6957 /// 2. Otherwise the data is an offset in the object file's layout; try to find 6958 // a symbol before it in the same section, and use the offset from there. 6959 /// 3. Finally, if all that fails, fall back to an offset from the start of the 6960 /// referenced section. 6961 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 6962 std::map<uint64_t, SymbolRef> &Symbols, 6963 const RelocationRef &Reloc, uint64_t Addr, 6964 StringRef &Name, uint64_t &Addend) { 6965 if (Reloc.getSymbol() != Obj->symbol_end()) { 6966 Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName(); 6967 if (!NameOrErr) 6968 report_error(Obj->getFileName(), NameOrErr.takeError()); 6969 Name = *NameOrErr; 6970 Addend = Addr; 6971 return; 6972 } 6973 6974 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 6975 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 6976 6977 uint64_t SectionAddr = RelocSection.getAddress(); 6978 6979 auto Sym = Symbols.upper_bound(Addr); 6980 if (Sym == Symbols.begin()) { 6981 // The first symbol in the object is after this reference, the best we can 6982 // do is section-relative notation. 6983 RelocSection.getName(Name); 6984 Addend = Addr - SectionAddr; 6985 return; 6986 } 6987 6988 // Go back one so that SymbolAddress <= Addr. 6989 --Sym; 6990 6991 auto SectOrErr = Sym->second.getSection(); 6992 if (!SectOrErr) 6993 report_error(Obj->getFileName(), SectOrErr.takeError()); 6994 section_iterator SymSection = *SectOrErr; 6995 if (RelocSection == *SymSection) { 6996 // There's a valid symbol in the same section before this reference. 6997 Expected<StringRef> NameOrErr = Sym->second.getName(); 6998 if (!NameOrErr) 6999 report_error(Obj->getFileName(), NameOrErr.takeError()); 7000 Name = *NameOrErr; 7001 Addend = Addr - Sym->first; 7002 return; 7003 } 7004 7005 // There is a symbol before this reference, but it's in a different 7006 // section. Probably not helpful to mention it, so use the section name. 7007 RelocSection.getName(Name); 7008 Addend = Addr - SectionAddr; 7009 } 7010 7011 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7012 std::map<uint64_t, SymbolRef> &Symbols, 7013 const RelocationRef &Reloc, uint64_t Addr) { 7014 StringRef Name; 7015 uint64_t Addend; 7016 7017 if (!Reloc.getObject()) 7018 return; 7019 7020 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7021 7022 outs() << Name; 7023 if (Addend) 7024 outs() << " + " << format("0x%" PRIx64, Addend); 7025 } 7026 7027 static void 7028 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7029 std::map<uint64_t, SymbolRef> &Symbols, 7030 const SectionRef &CompactUnwind) { 7031 7032 if (!Obj->isLittleEndian()) { 7033 outs() << "Skipping big-endian __compact_unwind section\n"; 7034 return; 7035 } 7036 7037 bool Is64 = Obj->is64Bit(); 7038 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7039 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7040 7041 StringRef Contents; 7042 CompactUnwind.getContents(Contents); 7043 7044 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7045 7046 // First populate the initial raw offsets, encodings and so on from the entry. 7047 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7048 CompactUnwindEntry Entry(Contents.data(), Offset, Is64); 7049 CompactUnwinds.push_back(Entry); 7050 } 7051 7052 // Next we need to look at the relocations to find out what objects are 7053 // actually being referred to. 7054 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7055 uint64_t RelocAddress = Reloc.getOffset(); 7056 7057 uint32_t EntryIdx = RelocAddress / EntrySize; 7058 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7059 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7060 7061 if (OffsetInEntry == 0) 7062 Entry.FunctionReloc = Reloc; 7063 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7064 Entry.PersonalityReloc = Reloc; 7065 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7066 Entry.LSDAReloc = Reloc; 7067 else { 7068 outs() << "Invalid relocation in __compact_unwind section\n"; 7069 return; 7070 } 7071 } 7072 7073 // Finally, we're ready to print the data we've gathered. 7074 outs() << "Contents of __compact_unwind section:\n"; 7075 for (auto &Entry : CompactUnwinds) { 7076 outs() << " Entry at offset " 7077 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7078 7079 // 1. Start of the region this entry applies to. 7080 outs() << " start: " << format("0x%" PRIx64, 7081 Entry.FunctionAddr) << ' '; 7082 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7083 outs() << '\n'; 7084 7085 // 2. Length of the region this entry applies to. 7086 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7087 << '\n'; 7088 // 3. The 32-bit compact encoding. 7089 outs() << " compact encoding: " 7090 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7091 7092 // 4. The personality function, if present. 7093 if (Entry.PersonalityReloc.getObject()) { 7094 outs() << " personality function: " 7095 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7096 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7097 Entry.PersonalityAddr); 7098 outs() << '\n'; 7099 } 7100 7101 // 5. This entry's language-specific data area. 7102 if (Entry.LSDAReloc.getObject()) { 7103 outs() << " LSDA: " << format("0x%" PRIx64, 7104 Entry.LSDAAddr) << ' '; 7105 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7106 outs() << '\n'; 7107 } 7108 } 7109 } 7110 7111 //===----------------------------------------------------------------------===// 7112 // __unwind_info section dumping 7113 //===----------------------------------------------------------------------===// 7114 7115 static void printRegularSecondLevelUnwindPage(const char *PageStart) { 7116 const char *Pos = PageStart; 7117 uint32_t Kind = readNext<uint32_t>(Pos); 7118 (void)Kind; 7119 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7120 7121 uint16_t EntriesStart = readNext<uint16_t>(Pos); 7122 uint16_t NumEntries = readNext<uint16_t>(Pos); 7123 7124 Pos = PageStart + EntriesStart; 7125 for (unsigned i = 0; i < NumEntries; ++i) { 7126 uint32_t FunctionOffset = readNext<uint32_t>(Pos); 7127 uint32_t Encoding = readNext<uint32_t>(Pos); 7128 7129 outs() << " [" << i << "]: " 7130 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7131 << ", " 7132 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7133 } 7134 } 7135 7136 static void printCompressedSecondLevelUnwindPage( 7137 const char *PageStart, uint32_t FunctionBase, 7138 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7139 const char *Pos = PageStart; 7140 uint32_t Kind = readNext<uint32_t>(Pos); 7141 (void)Kind; 7142 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 7143 7144 uint16_t EntriesStart = readNext<uint16_t>(Pos); 7145 uint16_t NumEntries = readNext<uint16_t>(Pos); 7146 7147 uint16_t EncodingsStart = readNext<uint16_t>(Pos); 7148 readNext<uint16_t>(Pos); 7149 const auto *PageEncodings = reinterpret_cast<const support::ulittle32_t *>( 7150 PageStart + EncodingsStart); 7151 7152 Pos = PageStart + EntriesStart; 7153 for (unsigned i = 0; i < NumEntries; ++i) { 7154 uint32_t Entry = readNext<uint32_t>(Pos); 7155 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 7156 uint32_t EncodingIdx = Entry >> 24; 7157 7158 uint32_t Encoding; 7159 if (EncodingIdx < CommonEncodings.size()) 7160 Encoding = CommonEncodings[EncodingIdx]; 7161 else 7162 Encoding = PageEncodings[EncodingIdx - CommonEncodings.size()]; 7163 7164 outs() << " [" << i << "]: " 7165 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7166 << ", " 7167 << "encoding[" << EncodingIdx 7168 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 7169 } 7170 } 7171 7172 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 7173 std::map<uint64_t, SymbolRef> &Symbols, 7174 const SectionRef &UnwindInfo) { 7175 7176 if (!Obj->isLittleEndian()) { 7177 outs() << "Skipping big-endian __unwind_info section\n"; 7178 return; 7179 } 7180 7181 outs() << "Contents of __unwind_info section:\n"; 7182 7183 StringRef Contents; 7184 UnwindInfo.getContents(Contents); 7185 const char *Pos = Contents.data(); 7186 7187 //===---------------------------------- 7188 // Section header 7189 //===---------------------------------- 7190 7191 uint32_t Version = readNext<uint32_t>(Pos); 7192 outs() << " Version: " 7193 << format("0x%" PRIx32, Version) << '\n'; 7194 if (Version != 1) { 7195 outs() << " Skipping section with unknown version\n"; 7196 return; 7197 } 7198 7199 uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos); 7200 outs() << " Common encodings array section offset: " 7201 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 7202 uint32_t NumCommonEncodings = readNext<uint32_t>(Pos); 7203 outs() << " Number of common encodings in array: " 7204 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 7205 7206 uint32_t PersonalitiesStart = readNext<uint32_t>(Pos); 7207 outs() << " Personality function array section offset: " 7208 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 7209 uint32_t NumPersonalities = readNext<uint32_t>(Pos); 7210 outs() << " Number of personality functions in array: " 7211 << format("0x%" PRIx32, NumPersonalities) << '\n'; 7212 7213 uint32_t IndicesStart = readNext<uint32_t>(Pos); 7214 outs() << " Index array section offset: " 7215 << format("0x%" PRIx32, IndicesStart) << '\n'; 7216 uint32_t NumIndices = readNext<uint32_t>(Pos); 7217 outs() << " Number of indices in array: " 7218 << format("0x%" PRIx32, NumIndices) << '\n'; 7219 7220 //===---------------------------------- 7221 // A shared list of common encodings 7222 //===---------------------------------- 7223 7224 // These occupy indices in the range [0, N] whenever an encoding is referenced 7225 // from a compressed 2nd level index table. In practice the linker only 7226 // creates ~128 of these, so that indices are available to embed encodings in 7227 // the 2nd level index. 7228 7229 SmallVector<uint32_t, 64> CommonEncodings; 7230 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 7231 Pos = Contents.data() + CommonEncodingsStart; 7232 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 7233 uint32_t Encoding = readNext<uint32_t>(Pos); 7234 CommonEncodings.push_back(Encoding); 7235 7236 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 7237 << '\n'; 7238 } 7239 7240 //===---------------------------------- 7241 // Personality functions used in this executable 7242 //===---------------------------------- 7243 7244 // There should be only a handful of these (one per source language, 7245 // roughly). Particularly since they only get 2 bits in the compact encoding. 7246 7247 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 7248 Pos = Contents.data() + PersonalitiesStart; 7249 for (unsigned i = 0; i < NumPersonalities; ++i) { 7250 uint32_t PersonalityFn = readNext<uint32_t>(Pos); 7251 outs() << " personality[" << i + 1 7252 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 7253 } 7254 7255 //===---------------------------------- 7256 // The level 1 index entries 7257 //===---------------------------------- 7258 7259 // These specify an approximate place to start searching for the more detailed 7260 // information, sorted by PC. 7261 7262 struct IndexEntry { 7263 uint32_t FunctionOffset; 7264 uint32_t SecondLevelPageStart; 7265 uint32_t LSDAStart; 7266 }; 7267 7268 SmallVector<IndexEntry, 4> IndexEntries; 7269 7270 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 7271 Pos = Contents.data() + IndicesStart; 7272 for (unsigned i = 0; i < NumIndices; ++i) { 7273 IndexEntry Entry; 7274 7275 Entry.FunctionOffset = readNext<uint32_t>(Pos); 7276 Entry.SecondLevelPageStart = readNext<uint32_t>(Pos); 7277 Entry.LSDAStart = readNext<uint32_t>(Pos); 7278 IndexEntries.push_back(Entry); 7279 7280 outs() << " [" << i << "]: " 7281 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 7282 << ", " 7283 << "2nd level page offset=" 7284 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 7285 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 7286 } 7287 7288 //===---------------------------------- 7289 // Next come the LSDA tables 7290 //===---------------------------------- 7291 7292 // The LSDA layout is rather implicit: it's a contiguous array of entries from 7293 // the first top-level index's LSDAOffset to the last (sentinel). 7294 7295 outs() << " LSDA descriptors:\n"; 7296 Pos = Contents.data() + IndexEntries[0].LSDAStart; 7297 int NumLSDAs = (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / 7298 (2 * sizeof(uint32_t)); 7299 for (int i = 0; i < NumLSDAs; ++i) { 7300 uint32_t FunctionOffset = readNext<uint32_t>(Pos); 7301 uint32_t LSDAOffset = readNext<uint32_t>(Pos); 7302 outs() << " [" << i << "]: " 7303 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7304 << ", " 7305 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 7306 } 7307 7308 //===---------------------------------- 7309 // Finally, the 2nd level indices 7310 //===---------------------------------- 7311 7312 // Generally these are 4K in size, and have 2 possible forms: 7313 // + Regular stores up to 511 entries with disparate encodings 7314 // + Compressed stores up to 1021 entries if few enough compact encoding 7315 // values are used. 7316 outs() << " Second level indices:\n"; 7317 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 7318 // The final sentinel top-level index has no associated 2nd level page 7319 if (IndexEntries[i].SecondLevelPageStart == 0) 7320 break; 7321 7322 outs() << " Second level index[" << i << "]: " 7323 << "offset in section=" 7324 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 7325 << ", " 7326 << "base function offset=" 7327 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 7328 7329 Pos = Contents.data() + IndexEntries[i].SecondLevelPageStart; 7330 uint32_t Kind = *reinterpret_cast<const support::ulittle32_t *>(Pos); 7331 if (Kind == 2) 7332 printRegularSecondLevelUnwindPage(Pos); 7333 else if (Kind == 3) 7334 printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset, 7335 CommonEncodings); 7336 else 7337 outs() << " Skipping 2nd level page with unknown kind " << Kind 7338 << '\n'; 7339 } 7340 } 7341 7342 void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { 7343 std::map<uint64_t, SymbolRef> Symbols; 7344 for (const SymbolRef &SymRef : Obj->symbols()) { 7345 // Discard any undefined or absolute symbols. They're not going to take part 7346 // in the convenience lookup for unwind info and just take up resources. 7347 auto SectOrErr = SymRef.getSection(); 7348 if (!SectOrErr) { 7349 // TODO: Actually report errors helpfully. 7350 consumeError(SectOrErr.takeError()); 7351 continue; 7352 } 7353 section_iterator Section = *SectOrErr; 7354 if (Section == Obj->section_end()) 7355 continue; 7356 7357 uint64_t Addr = SymRef.getValue(); 7358 Symbols.insert(std::make_pair(Addr, SymRef)); 7359 } 7360 7361 for (const SectionRef &Section : Obj->sections()) { 7362 StringRef SectName; 7363 Section.getName(SectName); 7364 if (SectName == "__compact_unwind") 7365 printMachOCompactUnwindSection(Obj, Symbols, Section); 7366 else if (SectName == "__unwind_info") 7367 printMachOUnwindInfoSection(Obj, Symbols, Section); 7368 } 7369 } 7370 7371 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 7372 uint32_t cpusubtype, uint32_t filetype, 7373 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 7374 bool verbose) { 7375 outs() << "Mach header\n"; 7376 outs() << " magic cputype cpusubtype caps filetype ncmds " 7377 "sizeofcmds flags\n"; 7378 if (verbose) { 7379 if (magic == MachO::MH_MAGIC) 7380 outs() << " MH_MAGIC"; 7381 else if (magic == MachO::MH_MAGIC_64) 7382 outs() << "MH_MAGIC_64"; 7383 else 7384 outs() << format(" 0x%08" PRIx32, magic); 7385 switch (cputype) { 7386 case MachO::CPU_TYPE_I386: 7387 outs() << " I386"; 7388 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7389 case MachO::CPU_SUBTYPE_I386_ALL: 7390 outs() << " ALL"; 7391 break; 7392 default: 7393 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7394 break; 7395 } 7396 break; 7397 case MachO::CPU_TYPE_X86_64: 7398 outs() << " X86_64"; 7399 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7400 case MachO::CPU_SUBTYPE_X86_64_ALL: 7401 outs() << " ALL"; 7402 break; 7403 case MachO::CPU_SUBTYPE_X86_64_H: 7404 outs() << " Haswell"; 7405 break; 7406 default: 7407 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7408 break; 7409 } 7410 break; 7411 case MachO::CPU_TYPE_ARM: 7412 outs() << " ARM"; 7413 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7414 case MachO::CPU_SUBTYPE_ARM_ALL: 7415 outs() << " ALL"; 7416 break; 7417 case MachO::CPU_SUBTYPE_ARM_V4T: 7418 outs() << " V4T"; 7419 break; 7420 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 7421 outs() << " V5TEJ"; 7422 break; 7423 case MachO::CPU_SUBTYPE_ARM_XSCALE: 7424 outs() << " XSCALE"; 7425 break; 7426 case MachO::CPU_SUBTYPE_ARM_V6: 7427 outs() << " V6"; 7428 break; 7429 case MachO::CPU_SUBTYPE_ARM_V6M: 7430 outs() << " V6M"; 7431 break; 7432 case MachO::CPU_SUBTYPE_ARM_V7: 7433 outs() << " V7"; 7434 break; 7435 case MachO::CPU_SUBTYPE_ARM_V7EM: 7436 outs() << " V7EM"; 7437 break; 7438 case MachO::CPU_SUBTYPE_ARM_V7K: 7439 outs() << " V7K"; 7440 break; 7441 case MachO::CPU_SUBTYPE_ARM_V7M: 7442 outs() << " V7M"; 7443 break; 7444 case MachO::CPU_SUBTYPE_ARM_V7S: 7445 outs() << " V7S"; 7446 break; 7447 default: 7448 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7449 break; 7450 } 7451 break; 7452 case MachO::CPU_TYPE_ARM64: 7453 outs() << " ARM64"; 7454 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7455 case MachO::CPU_SUBTYPE_ARM64_ALL: 7456 outs() << " ALL"; 7457 break; 7458 default: 7459 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7460 break; 7461 } 7462 break; 7463 case MachO::CPU_TYPE_POWERPC: 7464 outs() << " PPC"; 7465 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7466 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7467 outs() << " ALL"; 7468 break; 7469 default: 7470 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7471 break; 7472 } 7473 break; 7474 case MachO::CPU_TYPE_POWERPC64: 7475 outs() << " PPC64"; 7476 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 7477 case MachO::CPU_SUBTYPE_POWERPC_ALL: 7478 outs() << " ALL"; 7479 break; 7480 default: 7481 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7482 break; 7483 } 7484 break; 7485 default: 7486 outs() << format(" %7d", cputype); 7487 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7488 break; 7489 } 7490 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 7491 outs() << " LIB64"; 7492 } else { 7493 outs() << format(" 0x%02" PRIx32, 7494 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 7495 } 7496 switch (filetype) { 7497 case MachO::MH_OBJECT: 7498 outs() << " OBJECT"; 7499 break; 7500 case MachO::MH_EXECUTE: 7501 outs() << " EXECUTE"; 7502 break; 7503 case MachO::MH_FVMLIB: 7504 outs() << " FVMLIB"; 7505 break; 7506 case MachO::MH_CORE: 7507 outs() << " CORE"; 7508 break; 7509 case MachO::MH_PRELOAD: 7510 outs() << " PRELOAD"; 7511 break; 7512 case MachO::MH_DYLIB: 7513 outs() << " DYLIB"; 7514 break; 7515 case MachO::MH_DYLIB_STUB: 7516 outs() << " DYLIB_STUB"; 7517 break; 7518 case MachO::MH_DYLINKER: 7519 outs() << " DYLINKER"; 7520 break; 7521 case MachO::MH_BUNDLE: 7522 outs() << " BUNDLE"; 7523 break; 7524 case MachO::MH_DSYM: 7525 outs() << " DSYM"; 7526 break; 7527 case MachO::MH_KEXT_BUNDLE: 7528 outs() << " KEXTBUNDLE"; 7529 break; 7530 default: 7531 outs() << format(" %10u", filetype); 7532 break; 7533 } 7534 outs() << format(" %5u", ncmds); 7535 outs() << format(" %10u", sizeofcmds); 7536 uint32_t f = flags; 7537 if (f & MachO::MH_NOUNDEFS) { 7538 outs() << " NOUNDEFS"; 7539 f &= ~MachO::MH_NOUNDEFS; 7540 } 7541 if (f & MachO::MH_INCRLINK) { 7542 outs() << " INCRLINK"; 7543 f &= ~MachO::MH_INCRLINK; 7544 } 7545 if (f & MachO::MH_DYLDLINK) { 7546 outs() << " DYLDLINK"; 7547 f &= ~MachO::MH_DYLDLINK; 7548 } 7549 if (f & MachO::MH_BINDATLOAD) { 7550 outs() << " BINDATLOAD"; 7551 f &= ~MachO::MH_BINDATLOAD; 7552 } 7553 if (f & MachO::MH_PREBOUND) { 7554 outs() << " PREBOUND"; 7555 f &= ~MachO::MH_PREBOUND; 7556 } 7557 if (f & MachO::MH_SPLIT_SEGS) { 7558 outs() << " SPLIT_SEGS"; 7559 f &= ~MachO::MH_SPLIT_SEGS; 7560 } 7561 if (f & MachO::MH_LAZY_INIT) { 7562 outs() << " LAZY_INIT"; 7563 f &= ~MachO::MH_LAZY_INIT; 7564 } 7565 if (f & MachO::MH_TWOLEVEL) { 7566 outs() << " TWOLEVEL"; 7567 f &= ~MachO::MH_TWOLEVEL; 7568 } 7569 if (f & MachO::MH_FORCE_FLAT) { 7570 outs() << " FORCE_FLAT"; 7571 f &= ~MachO::MH_FORCE_FLAT; 7572 } 7573 if (f & MachO::MH_NOMULTIDEFS) { 7574 outs() << " NOMULTIDEFS"; 7575 f &= ~MachO::MH_NOMULTIDEFS; 7576 } 7577 if (f & MachO::MH_NOFIXPREBINDING) { 7578 outs() << " NOFIXPREBINDING"; 7579 f &= ~MachO::MH_NOFIXPREBINDING; 7580 } 7581 if (f & MachO::MH_PREBINDABLE) { 7582 outs() << " PREBINDABLE"; 7583 f &= ~MachO::MH_PREBINDABLE; 7584 } 7585 if (f & MachO::MH_ALLMODSBOUND) { 7586 outs() << " ALLMODSBOUND"; 7587 f &= ~MachO::MH_ALLMODSBOUND; 7588 } 7589 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 7590 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 7591 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 7592 } 7593 if (f & MachO::MH_CANONICAL) { 7594 outs() << " CANONICAL"; 7595 f &= ~MachO::MH_CANONICAL; 7596 } 7597 if (f & MachO::MH_WEAK_DEFINES) { 7598 outs() << " WEAK_DEFINES"; 7599 f &= ~MachO::MH_WEAK_DEFINES; 7600 } 7601 if (f & MachO::MH_BINDS_TO_WEAK) { 7602 outs() << " BINDS_TO_WEAK"; 7603 f &= ~MachO::MH_BINDS_TO_WEAK; 7604 } 7605 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 7606 outs() << " ALLOW_STACK_EXECUTION"; 7607 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 7608 } 7609 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 7610 outs() << " DEAD_STRIPPABLE_DYLIB"; 7611 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 7612 } 7613 if (f & MachO::MH_PIE) { 7614 outs() << " PIE"; 7615 f &= ~MachO::MH_PIE; 7616 } 7617 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 7618 outs() << " NO_REEXPORTED_DYLIBS"; 7619 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 7620 } 7621 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 7622 outs() << " MH_HAS_TLV_DESCRIPTORS"; 7623 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 7624 } 7625 if (f & MachO::MH_NO_HEAP_EXECUTION) { 7626 outs() << " MH_NO_HEAP_EXECUTION"; 7627 f &= ~MachO::MH_NO_HEAP_EXECUTION; 7628 } 7629 if (f & MachO::MH_APP_EXTENSION_SAFE) { 7630 outs() << " APP_EXTENSION_SAFE"; 7631 f &= ~MachO::MH_APP_EXTENSION_SAFE; 7632 } 7633 if (f != 0 || flags == 0) 7634 outs() << format(" 0x%08" PRIx32, f); 7635 } else { 7636 outs() << format(" 0x%08" PRIx32, magic); 7637 outs() << format(" %7d", cputype); 7638 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 7639 outs() << format(" 0x%02" PRIx32, 7640 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 7641 outs() << format(" %10u", filetype); 7642 outs() << format(" %5u", ncmds); 7643 outs() << format(" %10u", sizeofcmds); 7644 outs() << format(" 0x%08" PRIx32, flags); 7645 } 7646 outs() << "\n"; 7647 } 7648 7649 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 7650 StringRef SegName, uint64_t vmaddr, 7651 uint64_t vmsize, uint64_t fileoff, 7652 uint64_t filesize, uint32_t maxprot, 7653 uint32_t initprot, uint32_t nsects, 7654 uint32_t flags, uint32_t object_size, 7655 bool verbose) { 7656 uint64_t expected_cmdsize; 7657 if (cmd == MachO::LC_SEGMENT) { 7658 outs() << " cmd LC_SEGMENT\n"; 7659 expected_cmdsize = nsects; 7660 expected_cmdsize *= sizeof(struct MachO::section); 7661 expected_cmdsize += sizeof(struct MachO::segment_command); 7662 } else { 7663 outs() << " cmd LC_SEGMENT_64\n"; 7664 expected_cmdsize = nsects; 7665 expected_cmdsize *= sizeof(struct MachO::section_64); 7666 expected_cmdsize += sizeof(struct MachO::segment_command_64); 7667 } 7668 outs() << " cmdsize " << cmdsize; 7669 if (cmdsize != expected_cmdsize) 7670 outs() << " Inconsistent size\n"; 7671 else 7672 outs() << "\n"; 7673 outs() << " segname " << SegName << "\n"; 7674 if (cmd == MachO::LC_SEGMENT_64) { 7675 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 7676 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 7677 } else { 7678 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 7679 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 7680 } 7681 outs() << " fileoff " << fileoff; 7682 if (fileoff > object_size) 7683 outs() << " (past end of file)\n"; 7684 else 7685 outs() << "\n"; 7686 outs() << " filesize " << filesize; 7687 if (fileoff + filesize > object_size) 7688 outs() << " (past end of file)\n"; 7689 else 7690 outs() << "\n"; 7691 if (verbose) { 7692 if ((maxprot & 7693 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 7694 MachO::VM_PROT_EXECUTE)) != 0) 7695 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 7696 else { 7697 outs() << " maxprot "; 7698 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 7699 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 7700 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 7701 } 7702 if ((initprot & 7703 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 7704 MachO::VM_PROT_EXECUTE)) != 0) 7705 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 7706 else { 7707 outs() << " initprot "; 7708 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 7709 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 7710 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 7711 } 7712 } else { 7713 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 7714 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 7715 } 7716 outs() << " nsects " << nsects << "\n"; 7717 if (verbose) { 7718 outs() << " flags"; 7719 if (flags == 0) 7720 outs() << " (none)\n"; 7721 else { 7722 if (flags & MachO::SG_HIGHVM) { 7723 outs() << " HIGHVM"; 7724 flags &= ~MachO::SG_HIGHVM; 7725 } 7726 if (flags & MachO::SG_FVMLIB) { 7727 outs() << " FVMLIB"; 7728 flags &= ~MachO::SG_FVMLIB; 7729 } 7730 if (flags & MachO::SG_NORELOC) { 7731 outs() << " NORELOC"; 7732 flags &= ~MachO::SG_NORELOC; 7733 } 7734 if (flags & MachO::SG_PROTECTED_VERSION_1) { 7735 outs() << " PROTECTED_VERSION_1"; 7736 flags &= ~MachO::SG_PROTECTED_VERSION_1; 7737 } 7738 if (flags) 7739 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 7740 else 7741 outs() << "\n"; 7742 } 7743 } else { 7744 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 7745 } 7746 } 7747 7748 static void PrintSection(const char *sectname, const char *segname, 7749 uint64_t addr, uint64_t size, uint32_t offset, 7750 uint32_t align, uint32_t reloff, uint32_t nreloc, 7751 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 7752 uint32_t cmd, const char *sg_segname, 7753 uint32_t filetype, uint32_t object_size, 7754 bool verbose) { 7755 outs() << "Section\n"; 7756 outs() << " sectname " << format("%.16s\n", sectname); 7757 outs() << " segname " << format("%.16s", segname); 7758 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 7759 outs() << " (does not match segment)\n"; 7760 else 7761 outs() << "\n"; 7762 if (cmd == MachO::LC_SEGMENT_64) { 7763 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 7764 outs() << " size " << format("0x%016" PRIx64, size); 7765 } else { 7766 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 7767 outs() << " size " << format("0x%08" PRIx64, size); 7768 } 7769 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 7770 outs() << " (past end of file)\n"; 7771 else 7772 outs() << "\n"; 7773 outs() << " offset " << offset; 7774 if (offset > object_size) 7775 outs() << " (past end of file)\n"; 7776 else 7777 outs() << "\n"; 7778 uint32_t align_shifted = 1 << align; 7779 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 7780 outs() << " reloff " << reloff; 7781 if (reloff > object_size) 7782 outs() << " (past end of file)\n"; 7783 else 7784 outs() << "\n"; 7785 outs() << " nreloc " << nreloc; 7786 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 7787 outs() << " (past end of file)\n"; 7788 else 7789 outs() << "\n"; 7790 uint32_t section_type = flags & MachO::SECTION_TYPE; 7791 if (verbose) { 7792 outs() << " type"; 7793 if (section_type == MachO::S_REGULAR) 7794 outs() << " S_REGULAR\n"; 7795 else if (section_type == MachO::S_ZEROFILL) 7796 outs() << " S_ZEROFILL\n"; 7797 else if (section_type == MachO::S_CSTRING_LITERALS) 7798 outs() << " S_CSTRING_LITERALS\n"; 7799 else if (section_type == MachO::S_4BYTE_LITERALS) 7800 outs() << " S_4BYTE_LITERALS\n"; 7801 else if (section_type == MachO::S_8BYTE_LITERALS) 7802 outs() << " S_8BYTE_LITERALS\n"; 7803 else if (section_type == MachO::S_16BYTE_LITERALS) 7804 outs() << " S_16BYTE_LITERALS\n"; 7805 else if (section_type == MachO::S_LITERAL_POINTERS) 7806 outs() << " S_LITERAL_POINTERS\n"; 7807 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 7808 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 7809 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 7810 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 7811 else if (section_type == MachO::S_SYMBOL_STUBS) 7812 outs() << " S_SYMBOL_STUBS\n"; 7813 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 7814 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 7815 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 7816 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 7817 else if (section_type == MachO::S_COALESCED) 7818 outs() << " S_COALESCED\n"; 7819 else if (section_type == MachO::S_INTERPOSING) 7820 outs() << " S_INTERPOSING\n"; 7821 else if (section_type == MachO::S_DTRACE_DOF) 7822 outs() << " S_DTRACE_DOF\n"; 7823 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 7824 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 7825 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 7826 outs() << " S_THREAD_LOCAL_REGULAR\n"; 7827 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 7828 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 7829 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 7830 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 7831 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 7832 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 7833 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 7834 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 7835 else 7836 outs() << format("0x%08" PRIx32, section_type) << "\n"; 7837 outs() << "attributes"; 7838 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 7839 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 7840 outs() << " PURE_INSTRUCTIONS"; 7841 if (section_attributes & MachO::S_ATTR_NO_TOC) 7842 outs() << " NO_TOC"; 7843 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 7844 outs() << " STRIP_STATIC_SYMS"; 7845 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 7846 outs() << " NO_DEAD_STRIP"; 7847 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 7848 outs() << " LIVE_SUPPORT"; 7849 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 7850 outs() << " SELF_MODIFYING_CODE"; 7851 if (section_attributes & MachO::S_ATTR_DEBUG) 7852 outs() << " DEBUG"; 7853 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 7854 outs() << " SOME_INSTRUCTIONS"; 7855 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 7856 outs() << " EXT_RELOC"; 7857 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 7858 outs() << " LOC_RELOC"; 7859 if (section_attributes == 0) 7860 outs() << " (none)"; 7861 outs() << "\n"; 7862 } else 7863 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 7864 outs() << " reserved1 " << reserved1; 7865 if (section_type == MachO::S_SYMBOL_STUBS || 7866 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 7867 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 7868 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 7869 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 7870 outs() << " (index into indirect symbol table)\n"; 7871 else 7872 outs() << "\n"; 7873 outs() << " reserved2 " << reserved2; 7874 if (section_type == MachO::S_SYMBOL_STUBS) 7875 outs() << " (size of stubs)\n"; 7876 else 7877 outs() << "\n"; 7878 } 7879 7880 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 7881 uint32_t object_size) { 7882 outs() << " cmd LC_SYMTAB\n"; 7883 outs() << " cmdsize " << st.cmdsize; 7884 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 7885 outs() << " Incorrect size\n"; 7886 else 7887 outs() << "\n"; 7888 outs() << " symoff " << st.symoff; 7889 if (st.symoff > object_size) 7890 outs() << " (past end of file)\n"; 7891 else 7892 outs() << "\n"; 7893 outs() << " nsyms " << st.nsyms; 7894 uint64_t big_size; 7895 if (Is64Bit) { 7896 big_size = st.nsyms; 7897 big_size *= sizeof(struct MachO::nlist_64); 7898 big_size += st.symoff; 7899 if (big_size > object_size) 7900 outs() << " (past end of file)\n"; 7901 else 7902 outs() << "\n"; 7903 } else { 7904 big_size = st.nsyms; 7905 big_size *= sizeof(struct MachO::nlist); 7906 big_size += st.symoff; 7907 if (big_size > object_size) 7908 outs() << " (past end of file)\n"; 7909 else 7910 outs() << "\n"; 7911 } 7912 outs() << " stroff " << st.stroff; 7913 if (st.stroff > object_size) 7914 outs() << " (past end of file)\n"; 7915 else 7916 outs() << "\n"; 7917 outs() << " strsize " << st.strsize; 7918 big_size = st.stroff; 7919 big_size += st.strsize; 7920 if (big_size > object_size) 7921 outs() << " (past end of file)\n"; 7922 else 7923 outs() << "\n"; 7924 } 7925 7926 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 7927 uint32_t nsyms, uint32_t object_size, 7928 bool Is64Bit) { 7929 outs() << " cmd LC_DYSYMTAB\n"; 7930 outs() << " cmdsize " << dyst.cmdsize; 7931 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 7932 outs() << " Incorrect size\n"; 7933 else 7934 outs() << "\n"; 7935 outs() << " ilocalsym " << dyst.ilocalsym; 7936 if (dyst.ilocalsym > nsyms) 7937 outs() << " (greater than the number of symbols)\n"; 7938 else 7939 outs() << "\n"; 7940 outs() << " nlocalsym " << dyst.nlocalsym; 7941 uint64_t big_size; 7942 big_size = dyst.ilocalsym; 7943 big_size += dyst.nlocalsym; 7944 if (big_size > nsyms) 7945 outs() << " (past the end of the symbol table)\n"; 7946 else 7947 outs() << "\n"; 7948 outs() << " iextdefsym " << dyst.iextdefsym; 7949 if (dyst.iextdefsym > nsyms) 7950 outs() << " (greater than the number of symbols)\n"; 7951 else 7952 outs() << "\n"; 7953 outs() << " nextdefsym " << dyst.nextdefsym; 7954 big_size = dyst.iextdefsym; 7955 big_size += dyst.nextdefsym; 7956 if (big_size > nsyms) 7957 outs() << " (past the end of the symbol table)\n"; 7958 else 7959 outs() << "\n"; 7960 outs() << " iundefsym " << dyst.iundefsym; 7961 if (dyst.iundefsym > nsyms) 7962 outs() << " (greater than the number of symbols)\n"; 7963 else 7964 outs() << "\n"; 7965 outs() << " nundefsym " << dyst.nundefsym; 7966 big_size = dyst.iundefsym; 7967 big_size += dyst.nundefsym; 7968 if (big_size > nsyms) 7969 outs() << " (past the end of the symbol table)\n"; 7970 else 7971 outs() << "\n"; 7972 outs() << " tocoff " << dyst.tocoff; 7973 if (dyst.tocoff > object_size) 7974 outs() << " (past end of file)\n"; 7975 else 7976 outs() << "\n"; 7977 outs() << " ntoc " << dyst.ntoc; 7978 big_size = dyst.ntoc; 7979 big_size *= sizeof(struct MachO::dylib_table_of_contents); 7980 big_size += dyst.tocoff; 7981 if (big_size > object_size) 7982 outs() << " (past end of file)\n"; 7983 else 7984 outs() << "\n"; 7985 outs() << " modtaboff " << dyst.modtaboff; 7986 if (dyst.modtaboff > object_size) 7987 outs() << " (past end of file)\n"; 7988 else 7989 outs() << "\n"; 7990 outs() << " nmodtab " << dyst.nmodtab; 7991 uint64_t modtabend; 7992 if (Is64Bit) { 7993 modtabend = dyst.nmodtab; 7994 modtabend *= sizeof(struct MachO::dylib_module_64); 7995 modtabend += dyst.modtaboff; 7996 } else { 7997 modtabend = dyst.nmodtab; 7998 modtabend *= sizeof(struct MachO::dylib_module); 7999 modtabend += dyst.modtaboff; 8000 } 8001 if (modtabend > object_size) 8002 outs() << " (past end of file)\n"; 8003 else 8004 outs() << "\n"; 8005 outs() << " extrefsymoff " << dyst.extrefsymoff; 8006 if (dyst.extrefsymoff > object_size) 8007 outs() << " (past end of file)\n"; 8008 else 8009 outs() << "\n"; 8010 outs() << " nextrefsyms " << dyst.nextrefsyms; 8011 big_size = dyst.nextrefsyms; 8012 big_size *= sizeof(struct MachO::dylib_reference); 8013 big_size += dyst.extrefsymoff; 8014 if (big_size > object_size) 8015 outs() << " (past end of file)\n"; 8016 else 8017 outs() << "\n"; 8018 outs() << " indirectsymoff " << dyst.indirectsymoff; 8019 if (dyst.indirectsymoff > object_size) 8020 outs() << " (past end of file)\n"; 8021 else 8022 outs() << "\n"; 8023 outs() << " nindirectsyms " << dyst.nindirectsyms; 8024 big_size = dyst.nindirectsyms; 8025 big_size *= sizeof(uint32_t); 8026 big_size += dyst.indirectsymoff; 8027 if (big_size > object_size) 8028 outs() << " (past end of file)\n"; 8029 else 8030 outs() << "\n"; 8031 outs() << " extreloff " << dyst.extreloff; 8032 if (dyst.extreloff > object_size) 8033 outs() << " (past end of file)\n"; 8034 else 8035 outs() << "\n"; 8036 outs() << " nextrel " << dyst.nextrel; 8037 big_size = dyst.nextrel; 8038 big_size *= sizeof(struct MachO::relocation_info); 8039 big_size += dyst.extreloff; 8040 if (big_size > object_size) 8041 outs() << " (past end of file)\n"; 8042 else 8043 outs() << "\n"; 8044 outs() << " locreloff " << dyst.locreloff; 8045 if (dyst.locreloff > object_size) 8046 outs() << " (past end of file)\n"; 8047 else 8048 outs() << "\n"; 8049 outs() << " nlocrel " << dyst.nlocrel; 8050 big_size = dyst.nlocrel; 8051 big_size *= sizeof(struct MachO::relocation_info); 8052 big_size += dyst.locreloff; 8053 if (big_size > object_size) 8054 outs() << " (past end of file)\n"; 8055 else 8056 outs() << "\n"; 8057 } 8058 8059 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8060 uint32_t object_size) { 8061 if (dc.cmd == MachO::LC_DYLD_INFO) 8062 outs() << " cmd LC_DYLD_INFO\n"; 8063 else 8064 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8065 outs() << " cmdsize " << dc.cmdsize; 8066 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8067 outs() << " Incorrect size\n"; 8068 else 8069 outs() << "\n"; 8070 outs() << " rebase_off " << dc.rebase_off; 8071 if (dc.rebase_off > object_size) 8072 outs() << " (past end of file)\n"; 8073 else 8074 outs() << "\n"; 8075 outs() << " rebase_size " << dc.rebase_size; 8076 uint64_t big_size; 8077 big_size = dc.rebase_off; 8078 big_size += dc.rebase_size; 8079 if (big_size > object_size) 8080 outs() << " (past end of file)\n"; 8081 else 8082 outs() << "\n"; 8083 outs() << " bind_off " << dc.bind_off; 8084 if (dc.bind_off > object_size) 8085 outs() << " (past end of file)\n"; 8086 else 8087 outs() << "\n"; 8088 outs() << " bind_size " << dc.bind_size; 8089 big_size = dc.bind_off; 8090 big_size += dc.bind_size; 8091 if (big_size > object_size) 8092 outs() << " (past end of file)\n"; 8093 else 8094 outs() << "\n"; 8095 outs() << " weak_bind_off " << dc.weak_bind_off; 8096 if (dc.weak_bind_off > object_size) 8097 outs() << " (past end of file)\n"; 8098 else 8099 outs() << "\n"; 8100 outs() << " weak_bind_size " << dc.weak_bind_size; 8101 big_size = dc.weak_bind_off; 8102 big_size += dc.weak_bind_size; 8103 if (big_size > object_size) 8104 outs() << " (past end of file)\n"; 8105 else 8106 outs() << "\n"; 8107 outs() << " lazy_bind_off " << dc.lazy_bind_off; 8108 if (dc.lazy_bind_off > object_size) 8109 outs() << " (past end of file)\n"; 8110 else 8111 outs() << "\n"; 8112 outs() << " lazy_bind_size " << dc.lazy_bind_size; 8113 big_size = dc.lazy_bind_off; 8114 big_size += dc.lazy_bind_size; 8115 if (big_size > object_size) 8116 outs() << " (past end of file)\n"; 8117 else 8118 outs() << "\n"; 8119 outs() << " export_off " << dc.export_off; 8120 if (dc.export_off > object_size) 8121 outs() << " (past end of file)\n"; 8122 else 8123 outs() << "\n"; 8124 outs() << " export_size " << dc.export_size; 8125 big_size = dc.export_off; 8126 big_size += dc.export_size; 8127 if (big_size > object_size) 8128 outs() << " (past end of file)\n"; 8129 else 8130 outs() << "\n"; 8131 } 8132 8133 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 8134 const char *Ptr) { 8135 if (dyld.cmd == MachO::LC_ID_DYLINKER) 8136 outs() << " cmd LC_ID_DYLINKER\n"; 8137 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 8138 outs() << " cmd LC_LOAD_DYLINKER\n"; 8139 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 8140 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 8141 else 8142 outs() << " cmd ?(" << dyld.cmd << ")\n"; 8143 outs() << " cmdsize " << dyld.cmdsize; 8144 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 8145 outs() << " Incorrect size\n"; 8146 else 8147 outs() << "\n"; 8148 if (dyld.name >= dyld.cmdsize) 8149 outs() << " name ?(bad offset " << dyld.name << ")\n"; 8150 else { 8151 const char *P = (const char *)(Ptr) + dyld.name; 8152 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 8153 } 8154 } 8155 8156 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 8157 outs() << " cmd LC_UUID\n"; 8158 outs() << " cmdsize " << uuid.cmdsize; 8159 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 8160 outs() << " Incorrect size\n"; 8161 else 8162 outs() << "\n"; 8163 outs() << " uuid "; 8164 for (int i = 0; i < 16; ++i) { 8165 outs() << format("%02" PRIX32, uuid.uuid[i]); 8166 if (i == 3 || i == 5 || i == 7 || i == 9) 8167 outs() << "-"; 8168 } 8169 outs() << "\n"; 8170 } 8171 8172 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 8173 outs() << " cmd LC_RPATH\n"; 8174 outs() << " cmdsize " << rpath.cmdsize; 8175 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 8176 outs() << " Incorrect size\n"; 8177 else 8178 outs() << "\n"; 8179 if (rpath.path >= rpath.cmdsize) 8180 outs() << " path ?(bad offset " << rpath.path << ")\n"; 8181 else { 8182 const char *P = (const char *)(Ptr) + rpath.path; 8183 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 8184 } 8185 } 8186 8187 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 8188 StringRef LoadCmdName; 8189 switch (vd.cmd) { 8190 case MachO::LC_VERSION_MIN_MACOSX: 8191 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 8192 break; 8193 case MachO::LC_VERSION_MIN_IPHONEOS: 8194 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 8195 break; 8196 case MachO::LC_VERSION_MIN_TVOS: 8197 LoadCmdName = "LC_VERSION_MIN_TVOS"; 8198 break; 8199 case MachO::LC_VERSION_MIN_WATCHOS: 8200 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 8201 break; 8202 default: 8203 llvm_unreachable("Unknown version min load command"); 8204 } 8205 8206 outs() << " cmd " << LoadCmdName << '\n'; 8207 outs() << " cmdsize " << vd.cmdsize; 8208 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 8209 outs() << " Incorrect size\n"; 8210 else 8211 outs() << "\n"; 8212 outs() << " version " 8213 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 8214 << MachOObjectFile::getVersionMinMinor(vd, false); 8215 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 8216 if (Update != 0) 8217 outs() << "." << Update; 8218 outs() << "\n"; 8219 if (vd.sdk == 0) 8220 outs() << " sdk n/a"; 8221 else { 8222 outs() << " sdk " 8223 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 8224 << MachOObjectFile::getVersionMinMinor(vd, true); 8225 } 8226 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 8227 if (Update != 0) 8228 outs() << "." << Update; 8229 outs() << "\n"; 8230 } 8231 8232 static void PrintNoteLoadCommand(MachO::note_command Nt) { 8233 outs() << " cmd LC_NOTE\n"; 8234 outs() << " cmdsize " << Nt.cmdsize; 8235 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 8236 outs() << " Incorrect size\n"; 8237 else 8238 outs() << "\n"; 8239 const char *d = Nt.data_owner; 8240 outs() << "data_owner " << format("%.16s\n", d); 8241 outs() << " offset " << Nt.offset << "\n"; 8242 outs() << " size " << Nt.size << "\n"; 8243 } 8244 8245 static void PrintBuildToolVersion(MachO::build_tool_version bv) { 8246 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; 8247 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 8248 << "\n"; 8249 } 8250 8251 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 8252 MachO::build_version_command bd) { 8253 outs() << " cmd LC_BUILD_VERSION\n"; 8254 outs() << " cmdsize " << bd.cmdsize; 8255 if (bd.cmdsize != 8256 sizeof(struct MachO::build_version_command) + 8257 bd.ntools * sizeof(struct MachO::build_tool_version)) 8258 outs() << " Incorrect size\n"; 8259 else 8260 outs() << "\n"; 8261 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) 8262 << "\n"; 8263 if (bd.sdk) 8264 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 8265 << "\n"; 8266 else 8267 outs() << " sdk n/a\n"; 8268 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 8269 << "\n"; 8270 outs() << " ntools " << bd.ntools << "\n"; 8271 for (unsigned i = 0; i < bd.ntools; ++i) { 8272 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 8273 PrintBuildToolVersion(bv); 8274 } 8275 } 8276 8277 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 8278 outs() << " cmd LC_SOURCE_VERSION\n"; 8279 outs() << " cmdsize " << sd.cmdsize; 8280 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 8281 outs() << " Incorrect size\n"; 8282 else 8283 outs() << "\n"; 8284 uint64_t a = (sd.version >> 40) & 0xffffff; 8285 uint64_t b = (sd.version >> 30) & 0x3ff; 8286 uint64_t c = (sd.version >> 20) & 0x3ff; 8287 uint64_t d = (sd.version >> 10) & 0x3ff; 8288 uint64_t e = sd.version & 0x3ff; 8289 outs() << " version " << a << "." << b; 8290 if (e != 0) 8291 outs() << "." << c << "." << d << "." << e; 8292 else if (d != 0) 8293 outs() << "." << c << "." << d; 8294 else if (c != 0) 8295 outs() << "." << c; 8296 outs() << "\n"; 8297 } 8298 8299 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 8300 outs() << " cmd LC_MAIN\n"; 8301 outs() << " cmdsize " << ep.cmdsize; 8302 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 8303 outs() << " Incorrect size\n"; 8304 else 8305 outs() << "\n"; 8306 outs() << " entryoff " << ep.entryoff << "\n"; 8307 outs() << " stacksize " << ep.stacksize << "\n"; 8308 } 8309 8310 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 8311 uint32_t object_size) { 8312 outs() << " cmd LC_ENCRYPTION_INFO\n"; 8313 outs() << " cmdsize " << ec.cmdsize; 8314 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 8315 outs() << " Incorrect size\n"; 8316 else 8317 outs() << "\n"; 8318 outs() << " cryptoff " << ec.cryptoff; 8319 if (ec.cryptoff > object_size) 8320 outs() << " (past end of file)\n"; 8321 else 8322 outs() << "\n"; 8323 outs() << " cryptsize " << ec.cryptsize; 8324 if (ec.cryptsize > object_size) 8325 outs() << " (past end of file)\n"; 8326 else 8327 outs() << "\n"; 8328 outs() << " cryptid " << ec.cryptid << "\n"; 8329 } 8330 8331 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 8332 uint32_t object_size) { 8333 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 8334 outs() << " cmdsize " << ec.cmdsize; 8335 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 8336 outs() << " Incorrect size\n"; 8337 else 8338 outs() << "\n"; 8339 outs() << " cryptoff " << ec.cryptoff; 8340 if (ec.cryptoff > object_size) 8341 outs() << " (past end of file)\n"; 8342 else 8343 outs() << "\n"; 8344 outs() << " cryptsize " << ec.cryptsize; 8345 if (ec.cryptsize > object_size) 8346 outs() << " (past end of file)\n"; 8347 else 8348 outs() << "\n"; 8349 outs() << " cryptid " << ec.cryptid << "\n"; 8350 outs() << " pad " << ec.pad << "\n"; 8351 } 8352 8353 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 8354 const char *Ptr) { 8355 outs() << " cmd LC_LINKER_OPTION\n"; 8356 outs() << " cmdsize " << lo.cmdsize; 8357 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 8358 outs() << " Incorrect size\n"; 8359 else 8360 outs() << "\n"; 8361 outs() << " count " << lo.count << "\n"; 8362 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 8363 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 8364 uint32_t i = 0; 8365 while (left > 0) { 8366 while (*string == '\0' && left > 0) { 8367 string++; 8368 left--; 8369 } 8370 if (left > 0) { 8371 i++; 8372 outs() << " string #" << i << " " << format("%.*s\n", left, string); 8373 uint32_t NullPos = StringRef(string, left).find('\0'); 8374 uint32_t len = std::min(NullPos, left) + 1; 8375 string += len; 8376 left -= len; 8377 } 8378 } 8379 if (lo.count != i) 8380 outs() << " count " << lo.count << " does not match number of strings " 8381 << i << "\n"; 8382 } 8383 8384 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 8385 const char *Ptr) { 8386 outs() << " cmd LC_SUB_FRAMEWORK\n"; 8387 outs() << " cmdsize " << sub.cmdsize; 8388 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 8389 outs() << " Incorrect size\n"; 8390 else 8391 outs() << "\n"; 8392 if (sub.umbrella < sub.cmdsize) { 8393 const char *P = Ptr + sub.umbrella; 8394 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 8395 } else { 8396 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 8397 } 8398 } 8399 8400 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 8401 const char *Ptr) { 8402 outs() << " cmd LC_SUB_UMBRELLA\n"; 8403 outs() << " cmdsize " << sub.cmdsize; 8404 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 8405 outs() << " Incorrect size\n"; 8406 else 8407 outs() << "\n"; 8408 if (sub.sub_umbrella < sub.cmdsize) { 8409 const char *P = Ptr + sub.sub_umbrella; 8410 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 8411 } else { 8412 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 8413 } 8414 } 8415 8416 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 8417 const char *Ptr) { 8418 outs() << " cmd LC_SUB_LIBRARY\n"; 8419 outs() << " cmdsize " << sub.cmdsize; 8420 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 8421 outs() << " Incorrect size\n"; 8422 else 8423 outs() << "\n"; 8424 if (sub.sub_library < sub.cmdsize) { 8425 const char *P = Ptr + sub.sub_library; 8426 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 8427 } else { 8428 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 8429 } 8430 } 8431 8432 static void PrintSubClientCommand(MachO::sub_client_command sub, 8433 const char *Ptr) { 8434 outs() << " cmd LC_SUB_CLIENT\n"; 8435 outs() << " cmdsize " << sub.cmdsize; 8436 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 8437 outs() << " Incorrect size\n"; 8438 else 8439 outs() << "\n"; 8440 if (sub.client < sub.cmdsize) { 8441 const char *P = Ptr + sub.client; 8442 outs() << " client " << P << " (offset " << sub.client << ")\n"; 8443 } else { 8444 outs() << " client ?(bad offset " << sub.client << ")\n"; 8445 } 8446 } 8447 8448 static void PrintRoutinesCommand(MachO::routines_command r) { 8449 outs() << " cmd LC_ROUTINES\n"; 8450 outs() << " cmdsize " << r.cmdsize; 8451 if (r.cmdsize != sizeof(struct MachO::routines_command)) 8452 outs() << " Incorrect size\n"; 8453 else 8454 outs() << "\n"; 8455 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 8456 outs() << " init_module " << r.init_module << "\n"; 8457 outs() << " reserved1 " << r.reserved1 << "\n"; 8458 outs() << " reserved2 " << r.reserved2 << "\n"; 8459 outs() << " reserved3 " << r.reserved3 << "\n"; 8460 outs() << " reserved4 " << r.reserved4 << "\n"; 8461 outs() << " reserved5 " << r.reserved5 << "\n"; 8462 outs() << " reserved6 " << r.reserved6 << "\n"; 8463 } 8464 8465 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 8466 outs() << " cmd LC_ROUTINES_64\n"; 8467 outs() << " cmdsize " << r.cmdsize; 8468 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 8469 outs() << " Incorrect size\n"; 8470 else 8471 outs() << "\n"; 8472 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 8473 outs() << " init_module " << r.init_module << "\n"; 8474 outs() << " reserved1 " << r.reserved1 << "\n"; 8475 outs() << " reserved2 " << r.reserved2 << "\n"; 8476 outs() << " reserved3 " << r.reserved3 << "\n"; 8477 outs() << " reserved4 " << r.reserved4 << "\n"; 8478 outs() << " reserved5 " << r.reserved5 << "\n"; 8479 outs() << " reserved6 " << r.reserved6 << "\n"; 8480 } 8481 8482 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 8483 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 8484 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 8485 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 8486 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 8487 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 8488 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 8489 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 8490 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 8491 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 8492 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 8493 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 8494 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 8495 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 8496 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 8497 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 8498 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 8499 } 8500 8501 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 8502 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 8503 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 8504 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 8505 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 8506 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 8507 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 8508 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 8509 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 8510 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 8511 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 8512 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 8513 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 8514 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 8515 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 8516 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 8517 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 8518 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 8519 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 8520 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 8521 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 8522 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 8523 } 8524 8525 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 8526 uint32_t f; 8527 outs() << "\t mmst_reg "; 8528 for (f = 0; f < 10; f++) 8529 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 8530 outs() << "\n"; 8531 outs() << "\t mmst_rsrv "; 8532 for (f = 0; f < 6; f++) 8533 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 8534 outs() << "\n"; 8535 } 8536 8537 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 8538 uint32_t f; 8539 outs() << "\t xmm_reg "; 8540 for (f = 0; f < 16; f++) 8541 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 8542 outs() << "\n"; 8543 } 8544 8545 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 8546 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 8547 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 8548 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 8549 outs() << " denorm " << fpu.fpu_fcw.denorm; 8550 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 8551 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 8552 outs() << " undfl " << fpu.fpu_fcw.undfl; 8553 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 8554 outs() << "\t\t pc "; 8555 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 8556 outs() << "FP_PREC_24B "; 8557 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 8558 outs() << "FP_PREC_53B "; 8559 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 8560 outs() << "FP_PREC_64B "; 8561 else 8562 outs() << fpu.fpu_fcw.pc << " "; 8563 outs() << "rc "; 8564 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 8565 outs() << "FP_RND_NEAR "; 8566 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 8567 outs() << "FP_RND_DOWN "; 8568 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 8569 outs() << "FP_RND_UP "; 8570 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 8571 outs() << "FP_CHOP "; 8572 outs() << "\n"; 8573 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 8574 outs() << " denorm " << fpu.fpu_fsw.denorm; 8575 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 8576 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 8577 outs() << " undfl " << fpu.fpu_fsw.undfl; 8578 outs() << " precis " << fpu.fpu_fsw.precis; 8579 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 8580 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 8581 outs() << " c0 " << fpu.fpu_fsw.c0; 8582 outs() << " c1 " << fpu.fpu_fsw.c1; 8583 outs() << " c2 " << fpu.fpu_fsw.c2; 8584 outs() << " tos " << fpu.fpu_fsw.tos; 8585 outs() << " c3 " << fpu.fpu_fsw.c3; 8586 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 8587 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 8588 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 8589 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 8590 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 8591 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 8592 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 8593 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 8594 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 8595 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 8596 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 8597 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 8598 outs() << "\n"; 8599 outs() << "\t fpu_stmm0:\n"; 8600 Print_mmst_reg(fpu.fpu_stmm0); 8601 outs() << "\t fpu_stmm1:\n"; 8602 Print_mmst_reg(fpu.fpu_stmm1); 8603 outs() << "\t fpu_stmm2:\n"; 8604 Print_mmst_reg(fpu.fpu_stmm2); 8605 outs() << "\t fpu_stmm3:\n"; 8606 Print_mmst_reg(fpu.fpu_stmm3); 8607 outs() << "\t fpu_stmm4:\n"; 8608 Print_mmst_reg(fpu.fpu_stmm4); 8609 outs() << "\t fpu_stmm5:\n"; 8610 Print_mmst_reg(fpu.fpu_stmm5); 8611 outs() << "\t fpu_stmm6:\n"; 8612 Print_mmst_reg(fpu.fpu_stmm6); 8613 outs() << "\t fpu_stmm7:\n"; 8614 Print_mmst_reg(fpu.fpu_stmm7); 8615 outs() << "\t fpu_xmm0:\n"; 8616 Print_xmm_reg(fpu.fpu_xmm0); 8617 outs() << "\t fpu_xmm1:\n"; 8618 Print_xmm_reg(fpu.fpu_xmm1); 8619 outs() << "\t fpu_xmm2:\n"; 8620 Print_xmm_reg(fpu.fpu_xmm2); 8621 outs() << "\t fpu_xmm3:\n"; 8622 Print_xmm_reg(fpu.fpu_xmm3); 8623 outs() << "\t fpu_xmm4:\n"; 8624 Print_xmm_reg(fpu.fpu_xmm4); 8625 outs() << "\t fpu_xmm5:\n"; 8626 Print_xmm_reg(fpu.fpu_xmm5); 8627 outs() << "\t fpu_xmm6:\n"; 8628 Print_xmm_reg(fpu.fpu_xmm6); 8629 outs() << "\t fpu_xmm7:\n"; 8630 Print_xmm_reg(fpu.fpu_xmm7); 8631 outs() << "\t fpu_xmm8:\n"; 8632 Print_xmm_reg(fpu.fpu_xmm8); 8633 outs() << "\t fpu_xmm9:\n"; 8634 Print_xmm_reg(fpu.fpu_xmm9); 8635 outs() << "\t fpu_xmm10:\n"; 8636 Print_xmm_reg(fpu.fpu_xmm10); 8637 outs() << "\t fpu_xmm11:\n"; 8638 Print_xmm_reg(fpu.fpu_xmm11); 8639 outs() << "\t fpu_xmm12:\n"; 8640 Print_xmm_reg(fpu.fpu_xmm12); 8641 outs() << "\t fpu_xmm13:\n"; 8642 Print_xmm_reg(fpu.fpu_xmm13); 8643 outs() << "\t fpu_xmm14:\n"; 8644 Print_xmm_reg(fpu.fpu_xmm14); 8645 outs() << "\t fpu_xmm15:\n"; 8646 Print_xmm_reg(fpu.fpu_xmm15); 8647 outs() << "\t fpu_rsrv4:\n"; 8648 for (uint32_t f = 0; f < 6; f++) { 8649 outs() << "\t "; 8650 for (uint32_t g = 0; g < 16; g++) 8651 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 8652 outs() << "\n"; 8653 } 8654 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 8655 outs() << "\n"; 8656 } 8657 8658 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 8659 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 8660 outs() << " err " << format("0x%08" PRIx32, exc64.err); 8661 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 8662 } 8663 8664 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 8665 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 8666 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 8667 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 8668 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 8669 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 8670 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 8671 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 8672 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 8673 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 8674 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 8675 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 8676 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 8677 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 8678 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 8679 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 8680 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 8681 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 8682 } 8683 8684 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 8685 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 8686 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 8687 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 8688 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 8689 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 8690 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 8691 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 8692 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 8693 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 8694 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 8695 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 8696 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 8697 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 8698 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 8699 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 8700 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 8701 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 8702 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 8703 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 8704 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 8705 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 8706 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 8707 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 8708 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 8709 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 8710 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 8711 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 8712 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 8713 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 8714 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 8715 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 8716 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 8717 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 8718 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 8719 } 8720 8721 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 8722 bool isLittleEndian, uint32_t cputype) { 8723 if (t.cmd == MachO::LC_THREAD) 8724 outs() << " cmd LC_THREAD\n"; 8725 else if (t.cmd == MachO::LC_UNIXTHREAD) 8726 outs() << " cmd LC_UNIXTHREAD\n"; 8727 else 8728 outs() << " cmd " << t.cmd << " (unknown)\n"; 8729 outs() << " cmdsize " << t.cmdsize; 8730 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 8731 outs() << " Incorrect size\n"; 8732 else 8733 outs() << "\n"; 8734 8735 const char *begin = Ptr + sizeof(struct MachO::thread_command); 8736 const char *end = Ptr + t.cmdsize; 8737 uint32_t flavor, count, left; 8738 if (cputype == MachO::CPU_TYPE_I386) { 8739 while (begin < end) { 8740 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 8741 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 8742 begin += sizeof(uint32_t); 8743 } else { 8744 flavor = 0; 8745 begin = end; 8746 } 8747 if (isLittleEndian != sys::IsLittleEndianHost) 8748 sys::swapByteOrder(flavor); 8749 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 8750 memcpy((char *)&count, begin, sizeof(uint32_t)); 8751 begin += sizeof(uint32_t); 8752 } else { 8753 count = 0; 8754 begin = end; 8755 } 8756 if (isLittleEndian != sys::IsLittleEndianHost) 8757 sys::swapByteOrder(count); 8758 if (flavor == MachO::x86_THREAD_STATE32) { 8759 outs() << " flavor i386_THREAD_STATE\n"; 8760 if (count == MachO::x86_THREAD_STATE32_COUNT) 8761 outs() << " count i386_THREAD_STATE_COUNT\n"; 8762 else 8763 outs() << " count " << count 8764 << " (not x86_THREAD_STATE32_COUNT)\n"; 8765 MachO::x86_thread_state32_t cpu32; 8766 left = end - begin; 8767 if (left >= sizeof(MachO::x86_thread_state32_t)) { 8768 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 8769 begin += sizeof(MachO::x86_thread_state32_t); 8770 } else { 8771 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 8772 memcpy(&cpu32, begin, left); 8773 begin += left; 8774 } 8775 if (isLittleEndian != sys::IsLittleEndianHost) 8776 swapStruct(cpu32); 8777 Print_x86_thread_state32_t(cpu32); 8778 } else if (flavor == MachO::x86_THREAD_STATE) { 8779 outs() << " flavor x86_THREAD_STATE\n"; 8780 if (count == MachO::x86_THREAD_STATE_COUNT) 8781 outs() << " count x86_THREAD_STATE_COUNT\n"; 8782 else 8783 outs() << " count " << count 8784 << " (not x86_THREAD_STATE_COUNT)\n"; 8785 struct MachO::x86_thread_state_t ts; 8786 left = end - begin; 8787 if (left >= sizeof(MachO::x86_thread_state_t)) { 8788 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 8789 begin += sizeof(MachO::x86_thread_state_t); 8790 } else { 8791 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 8792 memcpy(&ts, begin, left); 8793 begin += left; 8794 } 8795 if (isLittleEndian != sys::IsLittleEndianHost) 8796 swapStruct(ts); 8797 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 8798 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 8799 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 8800 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 8801 else 8802 outs() << "tsh.count " << ts.tsh.count 8803 << " (not x86_THREAD_STATE32_COUNT\n"; 8804 Print_x86_thread_state32_t(ts.uts.ts32); 8805 } else { 8806 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 8807 << ts.tsh.count << "\n"; 8808 } 8809 } else { 8810 outs() << " flavor " << flavor << " (unknown)\n"; 8811 outs() << " count " << count << "\n"; 8812 outs() << " state (unknown)\n"; 8813 begin += count * sizeof(uint32_t); 8814 } 8815 } 8816 } else if (cputype == MachO::CPU_TYPE_X86_64) { 8817 while (begin < end) { 8818 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 8819 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 8820 begin += sizeof(uint32_t); 8821 } else { 8822 flavor = 0; 8823 begin = end; 8824 } 8825 if (isLittleEndian != sys::IsLittleEndianHost) 8826 sys::swapByteOrder(flavor); 8827 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 8828 memcpy((char *)&count, begin, sizeof(uint32_t)); 8829 begin += sizeof(uint32_t); 8830 } else { 8831 count = 0; 8832 begin = end; 8833 } 8834 if (isLittleEndian != sys::IsLittleEndianHost) 8835 sys::swapByteOrder(count); 8836 if (flavor == MachO::x86_THREAD_STATE64) { 8837 outs() << " flavor x86_THREAD_STATE64\n"; 8838 if (count == MachO::x86_THREAD_STATE64_COUNT) 8839 outs() << " count x86_THREAD_STATE64_COUNT\n"; 8840 else 8841 outs() << " count " << count 8842 << " (not x86_THREAD_STATE64_COUNT)\n"; 8843 MachO::x86_thread_state64_t cpu64; 8844 left = end - begin; 8845 if (left >= sizeof(MachO::x86_thread_state64_t)) { 8846 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 8847 begin += sizeof(MachO::x86_thread_state64_t); 8848 } else { 8849 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 8850 memcpy(&cpu64, begin, left); 8851 begin += left; 8852 } 8853 if (isLittleEndian != sys::IsLittleEndianHost) 8854 swapStruct(cpu64); 8855 Print_x86_thread_state64_t(cpu64); 8856 } else if (flavor == MachO::x86_THREAD_STATE) { 8857 outs() << " flavor x86_THREAD_STATE\n"; 8858 if (count == MachO::x86_THREAD_STATE_COUNT) 8859 outs() << " count x86_THREAD_STATE_COUNT\n"; 8860 else 8861 outs() << " count " << count 8862 << " (not x86_THREAD_STATE_COUNT)\n"; 8863 struct MachO::x86_thread_state_t ts; 8864 left = end - begin; 8865 if (left >= sizeof(MachO::x86_thread_state_t)) { 8866 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 8867 begin += sizeof(MachO::x86_thread_state_t); 8868 } else { 8869 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 8870 memcpy(&ts, begin, left); 8871 begin += left; 8872 } 8873 if (isLittleEndian != sys::IsLittleEndianHost) 8874 swapStruct(ts); 8875 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 8876 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 8877 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 8878 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 8879 else 8880 outs() << "tsh.count " << ts.tsh.count 8881 << " (not x86_THREAD_STATE64_COUNT\n"; 8882 Print_x86_thread_state64_t(ts.uts.ts64); 8883 } else { 8884 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 8885 << ts.tsh.count << "\n"; 8886 } 8887 } else if (flavor == MachO::x86_FLOAT_STATE) { 8888 outs() << " flavor x86_FLOAT_STATE\n"; 8889 if (count == MachO::x86_FLOAT_STATE_COUNT) 8890 outs() << " count x86_FLOAT_STATE_COUNT\n"; 8891 else 8892 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 8893 struct MachO::x86_float_state_t fs; 8894 left = end - begin; 8895 if (left >= sizeof(MachO::x86_float_state_t)) { 8896 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 8897 begin += sizeof(MachO::x86_float_state_t); 8898 } else { 8899 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 8900 memcpy(&fs, begin, left); 8901 begin += left; 8902 } 8903 if (isLittleEndian != sys::IsLittleEndianHost) 8904 swapStruct(fs); 8905 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 8906 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 8907 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 8908 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 8909 else 8910 outs() << "fsh.count " << fs.fsh.count 8911 << " (not x86_FLOAT_STATE64_COUNT\n"; 8912 Print_x86_float_state_t(fs.ufs.fs64); 8913 } else { 8914 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 8915 << fs.fsh.count << "\n"; 8916 } 8917 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 8918 outs() << " flavor x86_EXCEPTION_STATE\n"; 8919 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 8920 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 8921 else 8922 outs() << " count " << count 8923 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 8924 struct MachO::x86_exception_state_t es; 8925 left = end - begin; 8926 if (left >= sizeof(MachO::x86_exception_state_t)) { 8927 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 8928 begin += sizeof(MachO::x86_exception_state_t); 8929 } else { 8930 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 8931 memcpy(&es, begin, left); 8932 begin += left; 8933 } 8934 if (isLittleEndian != sys::IsLittleEndianHost) 8935 swapStruct(es); 8936 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 8937 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 8938 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 8939 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 8940 else 8941 outs() << "\t esh.count " << es.esh.count 8942 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 8943 Print_x86_exception_state_t(es.ues.es64); 8944 } else { 8945 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 8946 << es.esh.count << "\n"; 8947 } 8948 } else { 8949 outs() << " flavor " << flavor << " (unknown)\n"; 8950 outs() << " count " << count << "\n"; 8951 outs() << " state (unknown)\n"; 8952 begin += count * sizeof(uint32_t); 8953 } 8954 } 8955 } else if (cputype == MachO::CPU_TYPE_ARM) { 8956 while (begin < end) { 8957 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 8958 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 8959 begin += sizeof(uint32_t); 8960 } else { 8961 flavor = 0; 8962 begin = end; 8963 } 8964 if (isLittleEndian != sys::IsLittleEndianHost) 8965 sys::swapByteOrder(flavor); 8966 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 8967 memcpy((char *)&count, begin, sizeof(uint32_t)); 8968 begin += sizeof(uint32_t); 8969 } else { 8970 count = 0; 8971 begin = end; 8972 } 8973 if (isLittleEndian != sys::IsLittleEndianHost) 8974 sys::swapByteOrder(count); 8975 if (flavor == MachO::ARM_THREAD_STATE) { 8976 outs() << " flavor ARM_THREAD_STATE\n"; 8977 if (count == MachO::ARM_THREAD_STATE_COUNT) 8978 outs() << " count ARM_THREAD_STATE_COUNT\n"; 8979 else 8980 outs() << " count " << count 8981 << " (not ARM_THREAD_STATE_COUNT)\n"; 8982 MachO::arm_thread_state32_t cpu32; 8983 left = end - begin; 8984 if (left >= sizeof(MachO::arm_thread_state32_t)) { 8985 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 8986 begin += sizeof(MachO::arm_thread_state32_t); 8987 } else { 8988 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 8989 memcpy(&cpu32, begin, left); 8990 begin += left; 8991 } 8992 if (isLittleEndian != sys::IsLittleEndianHost) 8993 swapStruct(cpu32); 8994 Print_arm_thread_state32_t(cpu32); 8995 } else { 8996 outs() << " flavor " << flavor << " (unknown)\n"; 8997 outs() << " count " << count << "\n"; 8998 outs() << " state (unknown)\n"; 8999 begin += count * sizeof(uint32_t); 9000 } 9001 } 9002 } else if (cputype == MachO::CPU_TYPE_ARM64) { 9003 while (begin < end) { 9004 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9005 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9006 begin += sizeof(uint32_t); 9007 } else { 9008 flavor = 0; 9009 begin = end; 9010 } 9011 if (isLittleEndian != sys::IsLittleEndianHost) 9012 sys::swapByteOrder(flavor); 9013 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9014 memcpy((char *)&count, begin, sizeof(uint32_t)); 9015 begin += sizeof(uint32_t); 9016 } else { 9017 count = 0; 9018 begin = end; 9019 } 9020 if (isLittleEndian != sys::IsLittleEndianHost) 9021 sys::swapByteOrder(count); 9022 if (flavor == MachO::ARM_THREAD_STATE64) { 9023 outs() << " flavor ARM_THREAD_STATE64\n"; 9024 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9025 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9026 else 9027 outs() << " count " << count 9028 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9029 MachO::arm_thread_state64_t cpu64; 9030 left = end - begin; 9031 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9032 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9033 begin += sizeof(MachO::arm_thread_state64_t); 9034 } else { 9035 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9036 memcpy(&cpu64, begin, left); 9037 begin += left; 9038 } 9039 if (isLittleEndian != sys::IsLittleEndianHost) 9040 swapStruct(cpu64); 9041 Print_arm_thread_state64_t(cpu64); 9042 } else { 9043 outs() << " flavor " << flavor << " (unknown)\n"; 9044 outs() << " count " << count << "\n"; 9045 outs() << " state (unknown)\n"; 9046 begin += count * sizeof(uint32_t); 9047 } 9048 } 9049 } else { 9050 while (begin < end) { 9051 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9052 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9053 begin += sizeof(uint32_t); 9054 } else { 9055 flavor = 0; 9056 begin = end; 9057 } 9058 if (isLittleEndian != sys::IsLittleEndianHost) 9059 sys::swapByteOrder(flavor); 9060 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9061 memcpy((char *)&count, begin, sizeof(uint32_t)); 9062 begin += sizeof(uint32_t); 9063 } else { 9064 count = 0; 9065 begin = end; 9066 } 9067 if (isLittleEndian != sys::IsLittleEndianHost) 9068 sys::swapByteOrder(count); 9069 outs() << " flavor " << flavor << "\n"; 9070 outs() << " count " << count << "\n"; 9071 outs() << " state (Unknown cputype/cpusubtype)\n"; 9072 begin += count * sizeof(uint32_t); 9073 } 9074 } 9075 } 9076 9077 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 9078 if (dl.cmd == MachO::LC_ID_DYLIB) 9079 outs() << " cmd LC_ID_DYLIB\n"; 9080 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 9081 outs() << " cmd LC_LOAD_DYLIB\n"; 9082 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 9083 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 9084 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 9085 outs() << " cmd LC_REEXPORT_DYLIB\n"; 9086 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 9087 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 9088 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 9089 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 9090 else 9091 outs() << " cmd " << dl.cmd << " (unknown)\n"; 9092 outs() << " cmdsize " << dl.cmdsize; 9093 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 9094 outs() << " Incorrect size\n"; 9095 else 9096 outs() << "\n"; 9097 if (dl.dylib.name < dl.cmdsize) { 9098 const char *P = (const char *)(Ptr) + dl.dylib.name; 9099 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 9100 } else { 9101 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 9102 } 9103 outs() << " time stamp " << dl.dylib.timestamp << " "; 9104 time_t t = dl.dylib.timestamp; 9105 outs() << ctime(&t); 9106 outs() << " current version "; 9107 if (dl.dylib.current_version == 0xffffffff) 9108 outs() << "n/a\n"; 9109 else 9110 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 9111 << ((dl.dylib.current_version >> 8) & 0xff) << "." 9112 << (dl.dylib.current_version & 0xff) << "\n"; 9113 outs() << "compatibility version "; 9114 if (dl.dylib.compatibility_version == 0xffffffff) 9115 outs() << "n/a\n"; 9116 else 9117 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 9118 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 9119 << (dl.dylib.compatibility_version & 0xff) << "\n"; 9120 } 9121 9122 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 9123 uint32_t object_size) { 9124 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 9125 outs() << " cmd LC_CODE_SIGNATURE\n"; 9126 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 9127 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 9128 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 9129 outs() << " cmd LC_FUNCTION_STARTS\n"; 9130 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 9131 outs() << " cmd LC_DATA_IN_CODE\n"; 9132 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 9133 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 9134 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 9135 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 9136 else 9137 outs() << " cmd " << ld.cmd << " (?)\n"; 9138 outs() << " cmdsize " << ld.cmdsize; 9139 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 9140 outs() << " Incorrect size\n"; 9141 else 9142 outs() << "\n"; 9143 outs() << " dataoff " << ld.dataoff; 9144 if (ld.dataoff > object_size) 9145 outs() << " (past end of file)\n"; 9146 else 9147 outs() << "\n"; 9148 outs() << " datasize " << ld.datasize; 9149 uint64_t big_size = ld.dataoff; 9150 big_size += ld.datasize; 9151 if (big_size > object_size) 9152 outs() << " (past end of file)\n"; 9153 else 9154 outs() << "\n"; 9155 } 9156 9157 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 9158 uint32_t cputype, bool verbose) { 9159 StringRef Buf = Obj->getData(); 9160 unsigned Index = 0; 9161 for (const auto &Command : Obj->load_commands()) { 9162 outs() << "Load command " << Index++ << "\n"; 9163 if (Command.C.cmd == MachO::LC_SEGMENT) { 9164 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 9165 const char *sg_segname = SLC.segname; 9166 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 9167 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 9168 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 9169 verbose); 9170 for (unsigned j = 0; j < SLC.nsects; j++) { 9171 MachO::section S = Obj->getSection(Command, j); 9172 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 9173 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 9174 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 9175 } 9176 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9177 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 9178 const char *sg_segname = SLC_64.segname; 9179 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 9180 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 9181 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 9182 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 9183 for (unsigned j = 0; j < SLC_64.nsects; j++) { 9184 MachO::section_64 S_64 = Obj->getSection64(Command, j); 9185 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 9186 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 9187 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 9188 sg_segname, filetype, Buf.size(), verbose); 9189 } 9190 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 9191 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9192 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 9193 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 9194 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 9195 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9196 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 9197 Obj->is64Bit()); 9198 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 9199 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 9200 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 9201 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 9202 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 9203 Command.C.cmd == MachO::LC_ID_DYLINKER || 9204 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 9205 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 9206 PrintDyldLoadCommand(Dyld, Command.Ptr); 9207 } else if (Command.C.cmd == MachO::LC_UUID) { 9208 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 9209 PrintUuidLoadCommand(Uuid); 9210 } else if (Command.C.cmd == MachO::LC_RPATH) { 9211 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 9212 PrintRpathLoadCommand(Rpath, Command.Ptr); 9213 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 9214 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 9215 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 9216 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 9217 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 9218 PrintVersionMinLoadCommand(Vd); 9219 } else if (Command.C.cmd == MachO::LC_NOTE) { 9220 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 9221 PrintNoteLoadCommand(Nt); 9222 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 9223 MachO::build_version_command Bv = 9224 Obj->getBuildVersionLoadCommand(Command); 9225 PrintBuildVersionLoadCommand(Obj, Bv); 9226 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 9227 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 9228 PrintSourceVersionCommand(Sd); 9229 } else if (Command.C.cmd == MachO::LC_MAIN) { 9230 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 9231 PrintEntryPointCommand(Ep); 9232 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 9233 MachO::encryption_info_command Ei = 9234 Obj->getEncryptionInfoCommand(Command); 9235 PrintEncryptionInfoCommand(Ei, Buf.size()); 9236 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 9237 MachO::encryption_info_command_64 Ei = 9238 Obj->getEncryptionInfoCommand64(Command); 9239 PrintEncryptionInfoCommand64(Ei, Buf.size()); 9240 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 9241 MachO::linker_option_command Lo = 9242 Obj->getLinkerOptionLoadCommand(Command); 9243 PrintLinkerOptionCommand(Lo, Command.Ptr); 9244 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 9245 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 9246 PrintSubFrameworkCommand(Sf, Command.Ptr); 9247 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 9248 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 9249 PrintSubUmbrellaCommand(Sf, Command.Ptr); 9250 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 9251 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 9252 PrintSubLibraryCommand(Sl, Command.Ptr); 9253 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 9254 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 9255 PrintSubClientCommand(Sc, Command.Ptr); 9256 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 9257 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 9258 PrintRoutinesCommand(Rc); 9259 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 9260 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 9261 PrintRoutinesCommand64(Rc); 9262 } else if (Command.C.cmd == MachO::LC_THREAD || 9263 Command.C.cmd == MachO::LC_UNIXTHREAD) { 9264 MachO::thread_command Tc = Obj->getThreadCommand(Command); 9265 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 9266 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 9267 Command.C.cmd == MachO::LC_ID_DYLIB || 9268 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 9269 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 9270 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 9271 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 9272 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 9273 PrintDylibCommand(Dl, Command.Ptr); 9274 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 9275 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 9276 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 9277 Command.C.cmd == MachO::LC_DATA_IN_CODE || 9278 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 9279 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 9280 MachO::linkedit_data_command Ld = 9281 Obj->getLinkeditDataLoadCommand(Command); 9282 PrintLinkEditDataCommand(Ld, Buf.size()); 9283 } else { 9284 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 9285 << ")\n"; 9286 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 9287 // TODO: get and print the raw bytes of the load command. 9288 } 9289 // TODO: print all the other kinds of load commands. 9290 } 9291 } 9292 9293 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 9294 if (Obj->is64Bit()) { 9295 MachO::mach_header_64 H_64; 9296 H_64 = Obj->getHeader64(); 9297 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 9298 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 9299 } else { 9300 MachO::mach_header H; 9301 H = Obj->getHeader(); 9302 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 9303 H.sizeofcmds, H.flags, verbose); 9304 } 9305 } 9306 9307 void llvm::printMachOFileHeader(const object::ObjectFile *Obj) { 9308 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9309 PrintMachHeader(file, !NonVerbose); 9310 } 9311 9312 void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) { 9313 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 9314 uint32_t filetype = 0; 9315 uint32_t cputype = 0; 9316 if (file->is64Bit()) { 9317 MachO::mach_header_64 H_64; 9318 H_64 = file->getHeader64(); 9319 filetype = H_64.filetype; 9320 cputype = H_64.cputype; 9321 } else { 9322 MachO::mach_header H; 9323 H = file->getHeader(); 9324 filetype = H.filetype; 9325 cputype = H.cputype; 9326 } 9327 PrintLoadCommands(file, filetype, cputype, !NonVerbose); 9328 } 9329 9330 //===----------------------------------------------------------------------===// 9331 // export trie dumping 9332 //===----------------------------------------------------------------------===// 9333 9334 void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) { 9335 for (const llvm::object::ExportEntry &Entry : Obj->exports()) { 9336 uint64_t Flags = Entry.flags(); 9337 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 9338 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 9339 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9340 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 9341 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 9342 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 9343 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 9344 if (ReExport) 9345 outs() << "[re-export] "; 9346 else 9347 outs() << format("0x%08llX ", 9348 Entry.address()); // FIXME:add in base address 9349 outs() << Entry.name(); 9350 if (WeakDef || ThreadLocal || Resolver || Abs) { 9351 bool NeedsComma = false; 9352 outs() << " ["; 9353 if (WeakDef) { 9354 outs() << "weak_def"; 9355 NeedsComma = true; 9356 } 9357 if (ThreadLocal) { 9358 if (NeedsComma) 9359 outs() << ", "; 9360 outs() << "per-thread"; 9361 NeedsComma = true; 9362 } 9363 if (Abs) { 9364 if (NeedsComma) 9365 outs() << ", "; 9366 outs() << "absolute"; 9367 NeedsComma = true; 9368 } 9369 if (Resolver) { 9370 if (NeedsComma) 9371 outs() << ", "; 9372 outs() << format("resolver=0x%08llX", Entry.other()); 9373 NeedsComma = true; 9374 } 9375 outs() << "]"; 9376 } 9377 if (ReExport) { 9378 StringRef DylibName = "unknown"; 9379 int Ordinal = Entry.other() - 1; 9380 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 9381 if (Entry.otherName().empty()) 9382 outs() << " (from " << DylibName << ")"; 9383 else 9384 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 9385 } 9386 outs() << "\n"; 9387 } 9388 } 9389 9390 //===----------------------------------------------------------------------===// 9391 // rebase table dumping 9392 //===----------------------------------------------------------------------===// 9393 9394 namespace { 9395 class SegInfo { 9396 public: 9397 SegInfo(const object::MachOObjectFile *Obj); 9398 9399 StringRef segmentName(uint32_t SegIndex); 9400 StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset); 9401 uint64_t address(uint32_t SegIndex, uint64_t SegOffset); 9402 bool isValidSegIndexAndOffset(uint32_t SegIndex, uint64_t SegOffset); 9403 9404 private: 9405 struct SectionInfo { 9406 uint64_t Address; 9407 uint64_t Size; 9408 StringRef SectionName; 9409 StringRef SegmentName; 9410 uint64_t OffsetInSegment; 9411 uint64_t SegmentStartAddress; 9412 uint32_t SegmentIndex; 9413 }; 9414 const SectionInfo &findSection(uint32_t SegIndex, uint64_t SegOffset); 9415 SmallVector<SectionInfo, 32> Sections; 9416 }; 9417 } 9418 9419 SegInfo::SegInfo(const object::MachOObjectFile *Obj) { 9420 // Build table of sections so segIndex/offset pairs can be translated. 9421 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0; 9422 StringRef CurSegName; 9423 uint64_t CurSegAddress; 9424 for (const SectionRef &Section : Obj->sections()) { 9425 SectionInfo Info; 9426 error(Section.getName(Info.SectionName)); 9427 Info.Address = Section.getAddress(); 9428 Info.Size = Section.getSize(); 9429 Info.SegmentName = 9430 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl()); 9431 if (!Info.SegmentName.equals(CurSegName)) { 9432 ++CurSegIndex; 9433 CurSegName = Info.SegmentName; 9434 CurSegAddress = Info.Address; 9435 } 9436 Info.SegmentIndex = CurSegIndex - 1; 9437 Info.OffsetInSegment = Info.Address - CurSegAddress; 9438 Info.SegmentStartAddress = CurSegAddress; 9439 Sections.push_back(Info); 9440 } 9441 } 9442 9443 StringRef SegInfo::segmentName(uint32_t SegIndex) { 9444 for (const SectionInfo &SI : Sections) { 9445 if (SI.SegmentIndex == SegIndex) 9446 return SI.SegmentName; 9447 } 9448 llvm_unreachable("invalid segIndex"); 9449 } 9450 9451 bool SegInfo::isValidSegIndexAndOffset(uint32_t SegIndex, 9452 uint64_t OffsetInSeg) { 9453 for (const SectionInfo &SI : Sections) { 9454 if (SI.SegmentIndex != SegIndex) 9455 continue; 9456 if (SI.OffsetInSegment > OffsetInSeg) 9457 continue; 9458 if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size)) 9459 continue; 9460 return true; 9461 } 9462 return false; 9463 } 9464 9465 const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex, 9466 uint64_t OffsetInSeg) { 9467 for (const SectionInfo &SI : Sections) { 9468 if (SI.SegmentIndex != SegIndex) 9469 continue; 9470 if (SI.OffsetInSegment > OffsetInSeg) 9471 continue; 9472 if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size)) 9473 continue; 9474 return SI; 9475 } 9476 llvm_unreachable("segIndex and offset not in any section"); 9477 } 9478 9479 StringRef SegInfo::sectionName(uint32_t SegIndex, uint64_t OffsetInSeg) { 9480 return findSection(SegIndex, OffsetInSeg).SectionName; 9481 } 9482 9483 uint64_t SegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) { 9484 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg); 9485 return SI.SegmentStartAddress + OffsetInSeg; 9486 } 9487 9488 void llvm::printMachORebaseTable(const object::MachOObjectFile *Obj) { 9489 // Build table of sections so names can used in final output. 9490 SegInfo sectionTable(Obj); 9491 9492 outs() << "segment section address type\n"; 9493 for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) { 9494 uint32_t SegIndex = Entry.segmentIndex(); 9495 uint64_t OffsetInSeg = Entry.segmentOffset(); 9496 StringRef SegmentName = sectionTable.segmentName(SegIndex); 9497 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 9498 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 9499 9500 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 9501 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 9502 SegmentName.str().c_str(), SectionName.str().c_str(), 9503 Address, Entry.typeName().str().c_str()); 9504 } 9505 } 9506 9507 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 9508 StringRef DylibName; 9509 switch (Ordinal) { 9510 case MachO::BIND_SPECIAL_DYLIB_SELF: 9511 return "this-image"; 9512 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 9513 return "main-executable"; 9514 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 9515 return "flat-namespace"; 9516 default: 9517 if (Ordinal > 0) { 9518 std::error_code EC = 9519 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 9520 if (EC) 9521 return "<<bad library ordinal>>"; 9522 return DylibName; 9523 } 9524 } 9525 return "<<unknown special ordinal>>"; 9526 } 9527 9528 //===----------------------------------------------------------------------===// 9529 // bind table dumping 9530 //===----------------------------------------------------------------------===// 9531 9532 void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) { 9533 // Build table of sections so names can used in final output. 9534 SegInfo sectionTable(Obj); 9535 9536 outs() << "segment section address type " 9537 "addend dylib symbol\n"; 9538 Error Err = Error::success(); 9539 for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 9540 uint32_t SegIndex = Entry.segmentIndex(); 9541 uint64_t OffsetInSeg = Entry.segmentOffset(); 9542 StringRef SegmentName = sectionTable.segmentName(SegIndex); 9543 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 9544 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 9545 9546 // Table lines look like: 9547 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 9548 StringRef Attr; 9549 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 9550 Attr = " (weak_import)"; 9551 outs() << left_justify(SegmentName, 8) << " " 9552 << left_justify(SectionName, 18) << " " 9553 << format_hex(Address, 10, true) << " " 9554 << left_justify(Entry.typeName(), 8) << " " 9555 << format_decimal(Entry.addend(), 8) << " " 9556 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9557 << Entry.symbolName() << Attr << "\n"; 9558 } 9559 if (Err) 9560 report_error(Obj->getFileName(), std::move(Err)); 9561 } 9562 9563 //===----------------------------------------------------------------------===// 9564 // lazy bind table dumping 9565 //===----------------------------------------------------------------------===// 9566 9567 void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) { 9568 // Build table of sections so names can used in final output. 9569 SegInfo sectionTable(Obj); 9570 9571 outs() << "segment section address " 9572 "dylib symbol\n"; 9573 Error Err = Error::success(); 9574 for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 9575 uint32_t SegIndex = Entry.segmentIndex(); 9576 uint64_t OffsetInSeg = Entry.segmentOffset(); 9577 StringRef SegmentName = sectionTable.segmentName(SegIndex); 9578 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 9579 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 9580 9581 // Table lines look like: 9582 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 9583 outs() << left_justify(SegmentName, 8) << " " 9584 << left_justify(SectionName, 18) << " " 9585 << format_hex(Address, 10, true) << " " 9586 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 9587 << Entry.symbolName() << "\n"; 9588 } 9589 if (Err) 9590 report_error(Obj->getFileName(), std::move(Err)); 9591 } 9592 9593 //===----------------------------------------------------------------------===// 9594 // weak bind table dumping 9595 //===----------------------------------------------------------------------===// 9596 9597 void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) { 9598 // Build table of sections so names can used in final output. 9599 SegInfo sectionTable(Obj); 9600 9601 outs() << "segment section address " 9602 "type addend symbol\n"; 9603 Error Err = Error::success(); 9604 for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 9605 // Strong symbols don't have a location to update. 9606 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 9607 outs() << " strong " 9608 << Entry.symbolName() << "\n"; 9609 continue; 9610 } 9611 uint32_t SegIndex = Entry.segmentIndex(); 9612 uint64_t OffsetInSeg = Entry.segmentOffset(); 9613 StringRef SegmentName = sectionTable.segmentName(SegIndex); 9614 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 9615 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 9616 9617 // Table lines look like: 9618 // __DATA __data 0x00001000 pointer 0 _foo 9619 outs() << left_justify(SegmentName, 8) << " " 9620 << left_justify(SectionName, 18) << " " 9621 << format_hex(Address, 10, true) << " " 9622 << left_justify(Entry.typeName(), 8) << " " 9623 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 9624 << "\n"; 9625 } 9626 if (Err) 9627 report_error(Obj->getFileName(), std::move(Err)); 9628 } 9629 9630 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 9631 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 9632 // information for that address. If the address is found its binding symbol 9633 // name is returned. If not nullptr is returned. 9634 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 9635 struct DisassembleInfo *info) { 9636 if (info->bindtable == nullptr) { 9637 info->bindtable = llvm::make_unique<SymbolAddressMap>(); 9638 SegInfo sectionTable(info->O); 9639 Error Err = Error::success(); 9640 for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 9641 uint32_t SegIndex = Entry.segmentIndex(); 9642 uint64_t OffsetInSeg = Entry.segmentOffset(); 9643 if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg)) { 9644 if (Err) 9645 report_error(info->O->getFileName(), std::move(Err)); 9646 return nullptr; 9647 } 9648 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 9649 StringRef name = Entry.symbolName(); 9650 if (!name.empty()) 9651 (*info->bindtable)[Address] = name; 9652 } 9653 if (Err) 9654 report_error(info->O->getFileName(), std::move(Err)); 9655 } 9656 auto name = info->bindtable->lookup(ReferenceValue); 9657 return !name.empty() ? name.data() : nullptr; 9658 } 9659