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