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