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