1 //===-- MachODump.cpp - Object file dumping utility for llvm --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the MachO-specific dumper for llvm-objdump. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MachODump.h" 14 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/BinaryFormat/MachO.h" 21 #include "llvm/Config/config.h" 22 #include "llvm/DebugInfo/DIContext.h" 23 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 24 #include "llvm/Demangle/Demangle.h" 25 #include "llvm/MC/MCAsmInfo.h" 26 #include "llvm/MC/MCContext.h" 27 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 28 #include "llvm/MC/MCInst.h" 29 #include "llvm/MC/MCInstPrinter.h" 30 #include "llvm/MC/MCInstrDesc.h" 31 #include "llvm/MC/MCInstrInfo.h" 32 #include "llvm/MC/MCRegisterInfo.h" 33 #include "llvm/MC/MCSubtargetInfo.h" 34 #include "llvm/MC/MCTargetOptions.h" 35 #include "llvm/Object/MachO.h" 36 #include "llvm/Object/MachOUniversal.h" 37 #include "llvm/Support/Casting.h" 38 #include "llvm/Support/CommandLine.h" 39 #include "llvm/Support/Debug.h" 40 #include "llvm/Support/Endian.h" 41 #include "llvm/Support/Format.h" 42 #include "llvm/Support/FormattedStream.h" 43 #include "llvm/Support/GraphWriter.h" 44 #include "llvm/Support/LEB128.h" 45 #include "llvm/Support/MemoryBuffer.h" 46 #include "llvm/Support/TargetRegistry.h" 47 #include "llvm/Support/TargetSelect.h" 48 #include "llvm/Support/ToolOutputFile.h" 49 #include "llvm/Support/WithColor.h" 50 #include "llvm/Support/raw_ostream.h" 51 #include <algorithm> 52 #include <cstring> 53 #include <system_error> 54 55 #ifdef HAVE_LIBXAR 56 extern "C" { 57 #include <xar/xar.h> 58 } 59 #endif 60 61 using namespace llvm; 62 using namespace llvm::object; 63 using namespace llvm::objdump; 64 65 cl::OptionCategory objdump::MachOCat("llvm-objdump MachO Specific Options"); 66 67 cl::opt<bool> objdump::FirstPrivateHeader( 68 "private-header", 69 cl::desc("Display only the first format specific file header"), 70 cl::cat(MachOCat)); 71 72 cl::opt<bool> objdump::ExportsTrie("exports-trie", 73 cl::desc("Display mach-o exported symbols"), 74 cl::cat(MachOCat)); 75 76 cl::opt<bool> objdump::Rebase("rebase", 77 cl::desc("Display mach-o rebasing info"), 78 cl::cat(MachOCat)); 79 80 cl::opt<bool> objdump::Bind("bind", cl::desc("Display mach-o binding info"), 81 cl::cat(MachOCat)); 82 83 cl::opt<bool> objdump::LazyBind("lazy-bind", 84 cl::desc("Display mach-o lazy binding info"), 85 cl::cat(MachOCat)); 86 87 cl::opt<bool> objdump::WeakBind("weak-bind", 88 cl::desc("Display mach-o weak binding info"), 89 cl::cat(MachOCat)); 90 91 static cl::opt<bool> 92 UseDbg("g", cl::Grouping, 93 cl::desc("Print line information from debug info if available"), 94 cl::cat(MachOCat)); 95 96 static cl::opt<std::string> DSYMFile("dsym", 97 cl::desc("Use .dSYM file for debug info"), 98 cl::cat(MachOCat)); 99 100 static cl::opt<bool> FullLeadingAddr("full-leading-addr", 101 cl::desc("Print full leading address"), 102 cl::cat(MachOCat)); 103 104 static cl::opt<bool> NoLeadingHeaders("no-leading-headers", 105 cl::desc("Print no leading headers"), 106 cl::cat(MachOCat)); 107 108 cl::opt<bool> objdump::UniversalHeaders( 109 "universal-headers", 110 cl::desc("Print Mach-O universal headers (requires -macho)"), 111 cl::cat(MachOCat)); 112 113 static cl::opt<bool> ArchiveMemberOffsets( 114 "archive-member-offsets", 115 cl::desc("Print the offset to each archive member for Mach-O archives " 116 "(requires -macho and -archive-headers)"), 117 cl::cat(MachOCat)); 118 119 cl::opt<bool> objdump::IndirectSymbols( 120 "indirect-symbols", 121 cl::desc( 122 "Print indirect symbol table for Mach-O objects (requires -macho)"), 123 cl::cat(MachOCat)); 124 125 cl::opt<bool> objdump::DataInCode( 126 "data-in-code", 127 cl::desc( 128 "Print the data in code table for Mach-O objects (requires -macho)"), 129 cl::cat(MachOCat)); 130 131 cl::opt<bool> 132 objdump::LinkOptHints("link-opt-hints", 133 cl::desc("Print the linker optimization hints for " 134 "Mach-O objects (requires -macho)"), 135 cl::cat(MachOCat)); 136 137 cl::opt<bool> 138 objdump::InfoPlist("info-plist", 139 cl::desc("Print the info plist section as strings for " 140 "Mach-O objects (requires -macho)"), 141 cl::cat(MachOCat)); 142 143 cl::opt<bool> 144 objdump::DylibsUsed("dylibs-used", 145 cl::desc("Print the shared libraries used for linked " 146 "Mach-O files (requires -macho)"), 147 cl::cat(MachOCat)); 148 149 cl::opt<bool> objdump::DylibId("dylib-id", 150 cl::desc("Print the shared library's id for the " 151 "dylib Mach-O file (requires -macho)"), 152 cl::cat(MachOCat)); 153 154 static cl::opt<bool> 155 NonVerbose("non-verbose", 156 cl::desc("Print the info for Mach-O objects in non-verbose or " 157 "numeric form (requires -macho)"), 158 cl::cat(MachOCat)); 159 160 cl::opt<bool> 161 objdump::ObjcMetaData("objc-meta-data", 162 cl::desc("Print the Objective-C runtime meta data " 163 "for Mach-O files (requires -macho)"), 164 cl::cat(MachOCat)); 165 166 static cl::opt<std::string> DisSymName( 167 "dis-symname", 168 cl::desc("disassemble just this symbol's instructions (requires -macho)"), 169 cl::cat(MachOCat)); 170 171 static cl::opt<bool> NoSymbolicOperands( 172 "no-symbolic-operands", 173 cl::desc("do not symbolic operands when disassembling (requires -macho)"), 174 cl::cat(MachOCat)); 175 176 static cl::list<std::string> 177 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 178 cl::ZeroOrMore, cl::cat(MachOCat)); 179 180 static bool ArchAll = false; 181 182 static std::string ThumbTripleName; 183 184 static const Target *GetTarget(const MachOObjectFile *MachOObj, 185 const char **McpuDefault, 186 const Target **ThumbTarget) { 187 // Figure out the target triple. 188 Triple TT(TripleName); 189 if (TripleName.empty()) { 190 TT = MachOObj->getArchTriple(McpuDefault); 191 TripleName = TT.str(); 192 } 193 194 if (TT.getArch() == Triple::arm) { 195 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs 196 // that support ARM are also capable of Thumb mode. 197 Triple ThumbTriple = TT; 198 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str(); 199 ThumbTriple.setArchName(ThumbName); 200 ThumbTripleName = ThumbTriple.str(); 201 } 202 203 // Get the target specific parser. 204 std::string Error; 205 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 206 if (TheTarget && ThumbTripleName.empty()) 207 return TheTarget; 208 209 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 210 if (*ThumbTarget) 211 return TheTarget; 212 213 WithColor::error(errs(), "llvm-objdump") << "unable to get target for '"; 214 if (!TheTarget) 215 errs() << TripleName; 216 else 217 errs() << ThumbTripleName; 218 errs() << "', see --version and --triple.\n"; 219 return nullptr; 220 } 221 222 namespace { 223 struct SymbolSorter { 224 bool operator()(const SymbolRef &A, const SymbolRef &B) { 225 Expected<SymbolRef::Type> ATypeOrErr = A.getType(); 226 if (!ATypeOrErr) 227 reportError(ATypeOrErr.takeError(), A.getObject()->getFileName()); 228 SymbolRef::Type AType = *ATypeOrErr; 229 Expected<SymbolRef::Type> BTypeOrErr = B.getType(); 230 if (!BTypeOrErr) 231 reportError(BTypeOrErr.takeError(), B.getObject()->getFileName()); 232 SymbolRef::Type BType = *BTypeOrErr; 233 uint64_t AAddr = 234 (AType != SymbolRef::ST_Function) ? 0 : cantFail(A.getValue()); 235 uint64_t BAddr = 236 (BType != SymbolRef::ST_Function) ? 0 : cantFail(B.getValue()); 237 return AAddr < BAddr; 238 } 239 }; 240 } // namespace 241 242 // Types for the storted data in code table that is built before disassembly 243 // and the predicate function to sort them. 244 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 245 typedef std::vector<DiceTableEntry> DiceTable; 246 typedef DiceTable::iterator dice_table_iterator; 247 248 #ifdef HAVE_LIBXAR 249 namespace { 250 struct ScopedXarFile { 251 xar_t xar; 252 ScopedXarFile(const char *filename, int32_t flags) 253 : xar(xar_open(filename, flags)) {} 254 ~ScopedXarFile() { 255 if (xar) 256 xar_close(xar); 257 } 258 ScopedXarFile(const ScopedXarFile &) = delete; 259 ScopedXarFile &operator=(const ScopedXarFile &) = delete; 260 operator xar_t() { return xar; } 261 }; 262 263 struct ScopedXarIter { 264 xar_iter_t iter; 265 ScopedXarIter() : iter(xar_iter_new()) {} 266 ~ScopedXarIter() { 267 if (iter) 268 xar_iter_free(iter); 269 } 270 ScopedXarIter(const ScopedXarIter &) = delete; 271 ScopedXarIter &operator=(const ScopedXarIter &) = delete; 272 operator xar_iter_t() { return iter; } 273 }; 274 } // namespace 275 #endif // defined(HAVE_LIBXAR) 276 277 // This is used to search for a data in code table entry for the PC being 278 // disassembled. The j parameter has the PC in j.first. A single data in code 279 // table entry can cover many bytes for each of its Kind's. So if the offset, 280 // aka the i.first value, of the data in code table entry plus its Length 281 // covers the PC being searched for this will return true. If not it will 282 // return false. 283 static bool compareDiceTableEntries(const DiceTableEntry &i, 284 const DiceTableEntry &j) { 285 uint16_t Length; 286 i.second.getLength(Length); 287 288 return j.first >= i.first && j.first < i.first + Length; 289 } 290 291 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 292 unsigned short Kind) { 293 uint32_t Value, Size = 1; 294 295 switch (Kind) { 296 default: 297 case MachO::DICE_KIND_DATA: 298 if (Length >= 4) { 299 if (!NoShowRawInsn) 300 dumpBytes(makeArrayRef(bytes, 4), outs()); 301 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 302 outs() << "\t.long " << Value; 303 Size = 4; 304 } else if (Length >= 2) { 305 if (!NoShowRawInsn) 306 dumpBytes(makeArrayRef(bytes, 2), outs()); 307 Value = bytes[1] << 8 | bytes[0]; 308 outs() << "\t.short " << Value; 309 Size = 2; 310 } else { 311 if (!NoShowRawInsn) 312 dumpBytes(makeArrayRef(bytes, 2), outs()); 313 Value = bytes[0]; 314 outs() << "\t.byte " << Value; 315 Size = 1; 316 } 317 if (Kind == MachO::DICE_KIND_DATA) 318 outs() << "\t@ KIND_DATA\n"; 319 else 320 outs() << "\t@ data in code kind = " << Kind << "\n"; 321 break; 322 case MachO::DICE_KIND_JUMP_TABLE8: 323 if (!NoShowRawInsn) 324 dumpBytes(makeArrayRef(bytes, 1), outs()); 325 Value = bytes[0]; 326 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 327 Size = 1; 328 break; 329 case MachO::DICE_KIND_JUMP_TABLE16: 330 if (!NoShowRawInsn) 331 dumpBytes(makeArrayRef(bytes, 2), outs()); 332 Value = bytes[1] << 8 | bytes[0]; 333 outs() << "\t.short " << format("%5u", Value & 0xffff) 334 << "\t@ KIND_JUMP_TABLE16\n"; 335 Size = 2; 336 break; 337 case MachO::DICE_KIND_JUMP_TABLE32: 338 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 339 if (!NoShowRawInsn) 340 dumpBytes(makeArrayRef(bytes, 4), outs()); 341 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 342 outs() << "\t.long " << Value; 343 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 344 outs() << "\t@ KIND_JUMP_TABLE32\n"; 345 else 346 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 347 Size = 4; 348 break; 349 } 350 return Size; 351 } 352 353 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 354 std::vector<SectionRef> &Sections, 355 std::vector<SymbolRef> &Symbols, 356 SmallVectorImpl<uint64_t> &FoundFns, 357 uint64_t &BaseSegmentAddress) { 358 const StringRef FileName = MachOObj->getFileName(); 359 for (const SymbolRef &Symbol : MachOObj->symbols()) { 360 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 361 if (!SymName.startswith("ltmp")) 362 Symbols.push_back(Symbol); 363 } 364 365 for (const SectionRef &Section : MachOObj->sections()) 366 Sections.push_back(Section); 367 368 bool BaseSegmentAddressSet = false; 369 for (const auto &Command : MachOObj->load_commands()) { 370 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 371 // We found a function starts segment, parse the addresses for later 372 // consumption. 373 MachO::linkedit_data_command LLC = 374 MachOObj->getLinkeditDataLoadCommand(Command); 375 376 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 377 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 378 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 379 StringRef SegName = SLC.segname; 380 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 381 BaseSegmentAddressSet = true; 382 BaseSegmentAddress = SLC.vmaddr; 383 } 384 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 385 MachO::segment_command_64 SLC = MachOObj->getSegment64LoadCommand(Command); 386 StringRef SegName = SLC.segname; 387 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 388 BaseSegmentAddressSet = true; 389 BaseSegmentAddress = SLC.vmaddr; 390 } 391 } 392 } 393 } 394 395 static bool DumpAndSkipDataInCode(uint64_t PC, const uint8_t *bytes, 396 DiceTable &Dices, uint64_t &InstSize) { 397 // Check the data in code table here to see if this is data not an 398 // instruction to be disassembled. 399 DiceTable Dice; 400 Dice.push_back(std::make_pair(PC, DiceRef())); 401 dice_table_iterator DTI = 402 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 403 compareDiceTableEntries); 404 if (DTI != Dices.end()) { 405 uint16_t Length; 406 DTI->second.getLength(Length); 407 uint16_t Kind; 408 DTI->second.getKind(Kind); 409 InstSize = DumpDataInCode(bytes, Length, Kind); 410 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 411 (PC == (DTI->first + Length - 1)) && (Length & 1)) 412 InstSize++; 413 return true; 414 } 415 return false; 416 } 417 418 static void printRelocationTargetName(const MachOObjectFile *O, 419 const MachO::any_relocation_info &RE, 420 raw_string_ostream &Fmt) { 421 // Target of a scattered relocation is an address. In the interest of 422 // generating pretty output, scan through the symbol table looking for a 423 // symbol that aligns with that address. If we find one, print it. 424 // Otherwise, we just print the hex address of the target. 425 const StringRef FileName = O->getFileName(); 426 if (O->isRelocationScattered(RE)) { 427 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 428 429 for (const SymbolRef &Symbol : O->symbols()) { 430 uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName); 431 if (Addr != Val) 432 continue; 433 Fmt << unwrapOrError(Symbol.getName(), FileName); 434 return; 435 } 436 437 // If we couldn't find a symbol that this relocation refers to, try 438 // to find a section beginning instead. 439 for (const SectionRef &Section : ToolSectionFilter(*O)) { 440 uint64_t Addr = Section.getAddress(); 441 if (Addr != Val) 442 continue; 443 StringRef NameOrErr = unwrapOrError(Section.getName(), O->getFileName()); 444 Fmt << NameOrErr; 445 return; 446 } 447 448 Fmt << format("0x%x", Val); 449 return; 450 } 451 452 StringRef S; 453 bool isExtern = O->getPlainRelocationExternal(RE); 454 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 455 456 if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND) { 457 Fmt << format("0x%0" PRIx64, Val); 458 return; 459 } 460 461 if (isExtern) { 462 symbol_iterator SI = O->symbol_begin(); 463 advance(SI, Val); 464 S = unwrapOrError(SI->getName(), FileName); 465 } else { 466 section_iterator SI = O->section_begin(); 467 // Adjust for the fact that sections are 1-indexed. 468 if (Val == 0) { 469 Fmt << "0 (?,?)"; 470 return; 471 } 472 uint32_t I = Val - 1; 473 while (I != 0 && SI != O->section_end()) { 474 --I; 475 advance(SI, 1); 476 } 477 if (SI == O->section_end()) { 478 Fmt << Val << " (?,?)"; 479 } else { 480 if (Expected<StringRef> NameOrErr = SI->getName()) 481 S = *NameOrErr; 482 else 483 consumeError(NameOrErr.takeError()); 484 } 485 } 486 487 Fmt << S; 488 } 489 490 Error objdump::getMachORelocationValueString(const MachOObjectFile *Obj, 491 const RelocationRef &RelRef, 492 SmallVectorImpl<char> &Result) { 493 DataRefImpl Rel = RelRef.getRawDataRefImpl(); 494 MachO::any_relocation_info RE = Obj->getRelocation(Rel); 495 496 unsigned Arch = Obj->getArch(); 497 498 std::string FmtBuf; 499 raw_string_ostream Fmt(FmtBuf); 500 unsigned Type = Obj->getAnyRelocationType(RE); 501 bool IsPCRel = Obj->getAnyRelocationPCRel(RE); 502 503 // Determine any addends that should be displayed with the relocation. 504 // These require decoding the relocation type, which is triple-specific. 505 506 // X86_64 has entirely custom relocation types. 507 if (Arch == Triple::x86_64) { 508 switch (Type) { 509 case MachO::X86_64_RELOC_GOT_LOAD: 510 case MachO::X86_64_RELOC_GOT: { 511 printRelocationTargetName(Obj, RE, Fmt); 512 Fmt << "@GOT"; 513 if (IsPCRel) 514 Fmt << "PCREL"; 515 break; 516 } 517 case MachO::X86_64_RELOC_SUBTRACTOR: { 518 DataRefImpl RelNext = Rel; 519 Obj->moveRelocationNext(RelNext); 520 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 521 522 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 523 // X86_64_RELOC_UNSIGNED. 524 // NOTE: Scattered relocations don't exist on x86_64. 525 unsigned RType = Obj->getAnyRelocationType(RENext); 526 if (RType != MachO::X86_64_RELOC_UNSIGNED) 527 reportError(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after " 528 "X86_64_RELOC_SUBTRACTOR."); 529 530 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 531 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 532 printRelocationTargetName(Obj, RENext, Fmt); 533 Fmt << "-"; 534 printRelocationTargetName(Obj, RE, Fmt); 535 break; 536 } 537 case MachO::X86_64_RELOC_TLV: 538 printRelocationTargetName(Obj, RE, Fmt); 539 Fmt << "@TLV"; 540 if (IsPCRel) 541 Fmt << "P"; 542 break; 543 case MachO::X86_64_RELOC_SIGNED_1: 544 printRelocationTargetName(Obj, RE, Fmt); 545 Fmt << "-1"; 546 break; 547 case MachO::X86_64_RELOC_SIGNED_2: 548 printRelocationTargetName(Obj, RE, Fmt); 549 Fmt << "-2"; 550 break; 551 case MachO::X86_64_RELOC_SIGNED_4: 552 printRelocationTargetName(Obj, RE, Fmt); 553 Fmt << "-4"; 554 break; 555 default: 556 printRelocationTargetName(Obj, RE, Fmt); 557 break; 558 } 559 // X86 and ARM share some relocation types in common. 560 } else if (Arch == Triple::x86 || Arch == Triple::arm || 561 Arch == Triple::ppc) { 562 // Generic relocation types... 563 switch (Type) { 564 case MachO::GENERIC_RELOC_PAIR: // prints no info 565 return Error::success(); 566 case MachO::GENERIC_RELOC_SECTDIFF: { 567 DataRefImpl RelNext = Rel; 568 Obj->moveRelocationNext(RelNext); 569 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 570 571 // X86 sect diff's must be followed by a relocation of type 572 // GENERIC_RELOC_PAIR. 573 unsigned RType = Obj->getAnyRelocationType(RENext); 574 575 if (RType != MachO::GENERIC_RELOC_PAIR) 576 reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 577 "GENERIC_RELOC_SECTDIFF."); 578 579 printRelocationTargetName(Obj, RE, Fmt); 580 Fmt << "-"; 581 printRelocationTargetName(Obj, RENext, Fmt); 582 break; 583 } 584 } 585 586 if (Arch == Triple::x86 || Arch == Triple::ppc) { 587 switch (Type) { 588 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 589 DataRefImpl RelNext = Rel; 590 Obj->moveRelocationNext(RelNext); 591 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 592 593 // X86 sect diff's must be followed by a relocation of type 594 // GENERIC_RELOC_PAIR. 595 unsigned RType = Obj->getAnyRelocationType(RENext); 596 if (RType != MachO::GENERIC_RELOC_PAIR) 597 reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 598 "GENERIC_RELOC_LOCAL_SECTDIFF."); 599 600 printRelocationTargetName(Obj, RE, Fmt); 601 Fmt << "-"; 602 printRelocationTargetName(Obj, RENext, Fmt); 603 break; 604 } 605 case MachO::GENERIC_RELOC_TLV: { 606 printRelocationTargetName(Obj, RE, Fmt); 607 Fmt << "@TLV"; 608 if (IsPCRel) 609 Fmt << "P"; 610 break; 611 } 612 default: 613 printRelocationTargetName(Obj, RE, Fmt); 614 } 615 } else { // ARM-specific relocations 616 switch (Type) { 617 case MachO::ARM_RELOC_HALF: 618 case MachO::ARM_RELOC_HALF_SECTDIFF: { 619 // Half relocations steal a bit from the length field to encode 620 // whether this is an upper16 or a lower16 relocation. 621 bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1; 622 623 if (isUpper) 624 Fmt << ":upper16:("; 625 else 626 Fmt << ":lower16:("; 627 printRelocationTargetName(Obj, RE, Fmt); 628 629 DataRefImpl RelNext = Rel; 630 Obj->moveRelocationNext(RelNext); 631 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 632 633 // ARM half relocs must be followed by a relocation of type 634 // ARM_RELOC_PAIR. 635 unsigned RType = Obj->getAnyRelocationType(RENext); 636 if (RType != MachO::ARM_RELOC_PAIR) 637 reportError(Obj->getFileName(), "Expected ARM_RELOC_PAIR after " 638 "ARM_RELOC_HALF"); 639 640 // NOTE: The half of the target virtual address is stashed in the 641 // address field of the secondary relocation, but we can't reverse 642 // engineer the constant offset from it without decoding the movw/movt 643 // instruction to find the other half in its immediate field. 644 645 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 646 // symbol/section pointer of the follow-on relocation. 647 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 648 Fmt << "-"; 649 printRelocationTargetName(Obj, RENext, Fmt); 650 } 651 652 Fmt << ")"; 653 break; 654 } 655 default: { 656 printRelocationTargetName(Obj, RE, Fmt); 657 } 658 } 659 } 660 } else 661 printRelocationTargetName(Obj, RE, Fmt); 662 663 Fmt.flush(); 664 Result.append(FmtBuf.begin(), FmtBuf.end()); 665 return Error::success(); 666 } 667 668 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 669 uint32_t n, uint32_t count, 670 uint32_t stride, uint64_t addr) { 671 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 672 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 673 if (n > nindirectsyms) 674 outs() << " (entries start past the end of the indirect symbol " 675 "table) (reserved1 field greater than the table size)"; 676 else if (n + count > nindirectsyms) 677 outs() << " (entries extends past the end of the indirect symbol " 678 "table)"; 679 outs() << "\n"; 680 uint32_t cputype = O->getHeader().cputype; 681 if (cputype & MachO::CPU_ARCH_ABI64) 682 outs() << "address index"; 683 else 684 outs() << "address index"; 685 if (verbose) 686 outs() << " name\n"; 687 else 688 outs() << "\n"; 689 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 690 if (cputype & MachO::CPU_ARCH_ABI64) 691 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 692 else 693 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 694 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 695 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 696 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 697 outs() << "LOCAL\n"; 698 continue; 699 } 700 if (indirect_symbol == 701 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 702 outs() << "LOCAL ABSOLUTE\n"; 703 continue; 704 } 705 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 706 outs() << "ABSOLUTE\n"; 707 continue; 708 } 709 outs() << format("%5u ", indirect_symbol); 710 if (verbose) { 711 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 712 if (indirect_symbol < Symtab.nsyms) { 713 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 714 SymbolRef Symbol = *Sym; 715 outs() << unwrapOrError(Symbol.getName(), O->getFileName()); 716 } else { 717 outs() << "?"; 718 } 719 } 720 outs() << "\n"; 721 } 722 } 723 724 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 725 for (const auto &Load : O->load_commands()) { 726 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 727 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 728 for (unsigned J = 0; J < Seg.nsects; ++J) { 729 MachO::section_64 Sec = O->getSection64(Load, J); 730 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 731 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 732 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 733 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 734 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 735 section_type == MachO::S_SYMBOL_STUBS) { 736 uint32_t stride; 737 if (section_type == MachO::S_SYMBOL_STUBS) 738 stride = Sec.reserved2; 739 else 740 stride = 8; 741 if (stride == 0) { 742 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 743 << Sec.sectname << ") " 744 << "(size of stubs in reserved2 field is zero)\n"; 745 continue; 746 } 747 uint32_t count = Sec.size / stride; 748 outs() << "Indirect symbols for (" << Sec.segname << "," 749 << Sec.sectname << ") " << count << " entries"; 750 uint32_t n = Sec.reserved1; 751 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 752 } 753 } 754 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 755 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 756 for (unsigned J = 0; J < Seg.nsects; ++J) { 757 MachO::section Sec = O->getSection(Load, J); 758 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 759 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 760 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 761 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 762 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 763 section_type == MachO::S_SYMBOL_STUBS) { 764 uint32_t stride; 765 if (section_type == MachO::S_SYMBOL_STUBS) 766 stride = Sec.reserved2; 767 else 768 stride = 4; 769 if (stride == 0) { 770 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 771 << Sec.sectname << ") " 772 << "(size of stubs in reserved2 field is zero)\n"; 773 continue; 774 } 775 uint32_t count = Sec.size / stride; 776 outs() << "Indirect symbols for (" << Sec.segname << "," 777 << Sec.sectname << ") " << count << " entries"; 778 uint32_t n = Sec.reserved1; 779 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 780 } 781 } 782 } 783 } 784 } 785 786 static void PrintRType(const uint64_t cputype, const unsigned r_type) { 787 static char const *generic_r_types[] = { 788 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ", 789 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", 790 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 791 }; 792 static char const *x86_64_r_types[] = { 793 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", 794 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ", 795 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 796 }; 797 static char const *arm_r_types[] = { 798 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", 799 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ", 800 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 801 }; 802 static char const *arm64_r_types[] = { 803 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", 804 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", 805 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 806 }; 807 808 if (r_type > 0xf){ 809 outs() << format("%-7u", r_type) << " "; 810 return; 811 } 812 switch (cputype) { 813 case MachO::CPU_TYPE_I386: 814 outs() << generic_r_types[r_type]; 815 break; 816 case MachO::CPU_TYPE_X86_64: 817 outs() << x86_64_r_types[r_type]; 818 break; 819 case MachO::CPU_TYPE_ARM: 820 outs() << arm_r_types[r_type]; 821 break; 822 case MachO::CPU_TYPE_ARM64: 823 case MachO::CPU_TYPE_ARM64_32: 824 outs() << arm64_r_types[r_type]; 825 break; 826 default: 827 outs() << format("%-7u ", r_type); 828 } 829 } 830 831 static void PrintRLength(const uint64_t cputype, const unsigned r_type, 832 const unsigned r_length, const bool previous_arm_half){ 833 if (cputype == MachO::CPU_TYPE_ARM && 834 (r_type == MachO::ARM_RELOC_HALF || 835 r_type == MachO::ARM_RELOC_HALF_SECTDIFF || previous_arm_half == true)) { 836 if ((r_length & 0x1) == 0) 837 outs() << "lo/"; 838 else 839 outs() << "hi/"; 840 if ((r_length & 0x1) == 0) 841 outs() << "arm "; 842 else 843 outs() << "thm "; 844 } else { 845 switch (r_length) { 846 case 0: 847 outs() << "byte "; 848 break; 849 case 1: 850 outs() << "word "; 851 break; 852 case 2: 853 outs() << "long "; 854 break; 855 case 3: 856 if (cputype == MachO::CPU_TYPE_X86_64) 857 outs() << "quad "; 858 else 859 outs() << format("?(%2d) ", r_length); 860 break; 861 default: 862 outs() << format("?(%2d) ", r_length); 863 } 864 } 865 } 866 867 static void PrintRelocationEntries(const MachOObjectFile *O, 868 const relocation_iterator Begin, 869 const relocation_iterator End, 870 const uint64_t cputype, 871 const bool verbose) { 872 const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 873 bool previous_arm_half = false; 874 bool previous_sectdiff = false; 875 uint32_t sectdiff_r_type = 0; 876 877 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { 878 const DataRefImpl Rel = Reloc->getRawDataRefImpl(); 879 const MachO::any_relocation_info RE = O->getRelocation(Rel); 880 const unsigned r_type = O->getAnyRelocationType(RE); 881 const bool r_scattered = O->isRelocationScattered(RE); 882 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); 883 const unsigned r_length = O->getAnyRelocationLength(RE); 884 const unsigned r_address = O->getAnyRelocationAddress(RE); 885 const bool r_extern = (r_scattered ? false : 886 O->getPlainRelocationExternal(RE)); 887 const uint32_t r_value = (r_scattered ? 888 O->getScatteredRelocationValue(RE) : 0); 889 const unsigned r_symbolnum = (r_scattered ? 0 : 890 O->getPlainRelocationSymbolNum(RE)); 891 892 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { 893 if (verbose) { 894 // scattered: address 895 if ((cputype == MachO::CPU_TYPE_I386 && 896 r_type == MachO::GENERIC_RELOC_PAIR) || 897 (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)) 898 outs() << " "; 899 else 900 outs() << format("%08x ", (unsigned int)r_address); 901 902 // scattered: pcrel 903 if (r_pcrel) 904 outs() << "True "; 905 else 906 outs() << "False "; 907 908 // scattered: length 909 PrintRLength(cputype, r_type, r_length, previous_arm_half); 910 911 // scattered: extern & type 912 outs() << "n/a "; 913 PrintRType(cputype, r_type); 914 915 // scattered: scattered & value 916 outs() << format("True 0x%08x", (unsigned int)r_value); 917 if (previous_sectdiff == false) { 918 if ((cputype == MachO::CPU_TYPE_ARM && 919 r_type == MachO::ARM_RELOC_PAIR)) 920 outs() << format(" half = 0x%04x ", (unsigned int)r_address); 921 } else if (cputype == MachO::CPU_TYPE_ARM && 922 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF) 923 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); 924 if ((cputype == MachO::CPU_TYPE_I386 && 925 (r_type == MachO::GENERIC_RELOC_SECTDIFF || 926 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || 927 (cputype == MachO::CPU_TYPE_ARM && 928 (sectdiff_r_type == MachO::ARM_RELOC_SECTDIFF || 929 sectdiff_r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 930 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF))) { 931 previous_sectdiff = true; 932 sectdiff_r_type = r_type; 933 } else { 934 previous_sectdiff = false; 935 sectdiff_r_type = 0; 936 } 937 if (cputype == MachO::CPU_TYPE_ARM && 938 (r_type == MachO::ARM_RELOC_HALF || 939 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 940 previous_arm_half = true; 941 else 942 previous_arm_half = false; 943 outs() << "\n"; 944 } 945 else { 946 // scattered: address pcrel length extern type scattered value 947 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n", 948 (unsigned int)r_address, r_pcrel, r_length, r_type, 949 (unsigned int)r_value); 950 } 951 } 952 else { 953 if (verbose) { 954 // plain: address 955 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 956 outs() << " "; 957 else 958 outs() << format("%08x ", (unsigned int)r_address); 959 960 // plain: pcrel 961 if (r_pcrel) 962 outs() << "True "; 963 else 964 outs() << "False "; 965 966 // plain: length 967 PrintRLength(cputype, r_type, r_length, previous_arm_half); 968 969 if (r_extern) { 970 // plain: extern & type & scattered 971 outs() << "True "; 972 PrintRType(cputype, r_type); 973 outs() << "False "; 974 975 // plain: symbolnum/value 976 if (r_symbolnum > Symtab.nsyms) 977 outs() << format("?(%d)\n", r_symbolnum); 978 else { 979 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); 980 Expected<StringRef> SymNameNext = Symbol.getName(); 981 const char *name = NULL; 982 if (SymNameNext) 983 name = SymNameNext->data(); 984 if (name == NULL) 985 outs() << format("?(%d)\n", r_symbolnum); 986 else 987 outs() << name << "\n"; 988 } 989 } 990 else { 991 // plain: extern & type & scattered 992 outs() << "False "; 993 PrintRType(cputype, r_type); 994 outs() << "False "; 995 996 // plain: symbolnum/value 997 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 998 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); 999 else if ((cputype == MachO::CPU_TYPE_ARM64 || 1000 cputype == MachO::CPU_TYPE_ARM64_32) && 1001 r_type == MachO::ARM64_RELOC_ADDEND) 1002 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); 1003 else { 1004 outs() << format("%d ", r_symbolnum); 1005 if (r_symbolnum == MachO::R_ABS) 1006 outs() << "R_ABS\n"; 1007 else { 1008 // in this case, r_symbolnum is actually a 1-based section number 1009 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; 1010 if (r_symbolnum > 0 && r_symbolnum <= nsects) { 1011 object::DataRefImpl DRI; 1012 DRI.d.a = r_symbolnum-1; 1013 StringRef SegName = O->getSectionFinalSegmentName(DRI); 1014 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1015 outs() << "(" << SegName << "," << *NameOrErr << ")\n"; 1016 else 1017 outs() << "(?,?)\n"; 1018 } 1019 else { 1020 outs() << "(?,?)\n"; 1021 } 1022 } 1023 } 1024 } 1025 if (cputype == MachO::CPU_TYPE_ARM && 1026 (r_type == MachO::ARM_RELOC_HALF || 1027 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 1028 previous_arm_half = true; 1029 else 1030 previous_arm_half = false; 1031 } 1032 else { 1033 // plain: address pcrel length extern type scattered symbolnum/section 1034 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n", 1035 (unsigned int)r_address, r_pcrel, r_length, r_extern, 1036 r_type, r_symbolnum); 1037 } 1038 } 1039 } 1040 } 1041 1042 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { 1043 const uint64_t cputype = O->getHeader().cputype; 1044 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 1045 if (Dysymtab.nextrel != 0) { 1046 outs() << "External relocation information " << Dysymtab.nextrel 1047 << " entries"; 1048 outs() << "\naddress pcrel length extern type scattered " 1049 "symbolnum/value\n"; 1050 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, 1051 verbose); 1052 } 1053 if (Dysymtab.nlocrel != 0) { 1054 outs() << format("Local relocation information %u entries", 1055 Dysymtab.nlocrel); 1056 outs() << "\naddress pcrel length extern type scattered " 1057 "symbolnum/value\n"; 1058 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, 1059 verbose); 1060 } 1061 for (const auto &Load : O->load_commands()) { 1062 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 1063 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 1064 for (unsigned J = 0; J < Seg.nsects; ++J) { 1065 const MachO::section_64 Sec = O->getSection64(Load, J); 1066 if (Sec.nreloc != 0) { 1067 DataRefImpl DRI; 1068 DRI.d.a = J; 1069 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1070 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1071 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1072 << format(") %u entries", Sec.nreloc); 1073 else 1074 outs() << "Relocation information (" << SegName << ",?) " 1075 << format("%u entries", Sec.nreloc); 1076 outs() << "\naddress pcrel length extern type scattered " 1077 "symbolnum/value\n"; 1078 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1079 O->section_rel_end(DRI), cputype, verbose); 1080 } 1081 } 1082 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1083 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 1084 for (unsigned J = 0; J < Seg.nsects; ++J) { 1085 const MachO::section Sec = O->getSection(Load, J); 1086 if (Sec.nreloc != 0) { 1087 DataRefImpl DRI; 1088 DRI.d.a = J; 1089 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1090 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1091 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1092 << format(") %u entries", Sec.nreloc); 1093 else 1094 outs() << "Relocation information (" << SegName << ",?) " 1095 << format("%u entries", Sec.nreloc); 1096 outs() << "\naddress pcrel length extern type scattered " 1097 "symbolnum/value\n"; 1098 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1099 O->section_rel_end(DRI), cputype, verbose); 1100 } 1101 } 1102 } 1103 } 1104 } 1105 1106 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 1107 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 1108 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 1109 outs() << "Data in code table (" << nentries << " entries)\n"; 1110 outs() << "offset length kind\n"; 1111 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 1112 ++DI) { 1113 uint32_t Offset; 1114 DI->getOffset(Offset); 1115 outs() << format("0x%08" PRIx32, Offset) << " "; 1116 uint16_t Length; 1117 DI->getLength(Length); 1118 outs() << format("%6u", Length) << " "; 1119 uint16_t Kind; 1120 DI->getKind(Kind); 1121 if (verbose) { 1122 switch (Kind) { 1123 case MachO::DICE_KIND_DATA: 1124 outs() << "DATA"; 1125 break; 1126 case MachO::DICE_KIND_JUMP_TABLE8: 1127 outs() << "JUMP_TABLE8"; 1128 break; 1129 case MachO::DICE_KIND_JUMP_TABLE16: 1130 outs() << "JUMP_TABLE16"; 1131 break; 1132 case MachO::DICE_KIND_JUMP_TABLE32: 1133 outs() << "JUMP_TABLE32"; 1134 break; 1135 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 1136 outs() << "ABS_JUMP_TABLE32"; 1137 break; 1138 default: 1139 outs() << format("0x%04" PRIx32, Kind); 1140 break; 1141 } 1142 } else 1143 outs() << format("0x%04" PRIx32, Kind); 1144 outs() << "\n"; 1145 } 1146 } 1147 1148 static void PrintLinkOptHints(MachOObjectFile *O) { 1149 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 1150 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 1151 uint32_t nloh = LohLC.datasize; 1152 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 1153 for (uint32_t i = 0; i < nloh;) { 1154 unsigned n; 1155 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 1156 i += n; 1157 outs() << " identifier " << identifier << " "; 1158 if (i >= nloh) 1159 return; 1160 switch (identifier) { 1161 case 1: 1162 outs() << "AdrpAdrp\n"; 1163 break; 1164 case 2: 1165 outs() << "AdrpLdr\n"; 1166 break; 1167 case 3: 1168 outs() << "AdrpAddLdr\n"; 1169 break; 1170 case 4: 1171 outs() << "AdrpLdrGotLdr\n"; 1172 break; 1173 case 5: 1174 outs() << "AdrpAddStr\n"; 1175 break; 1176 case 6: 1177 outs() << "AdrpLdrGotStr\n"; 1178 break; 1179 case 7: 1180 outs() << "AdrpAdd\n"; 1181 break; 1182 case 8: 1183 outs() << "AdrpLdrGot\n"; 1184 break; 1185 default: 1186 outs() << "Unknown identifier value\n"; 1187 break; 1188 } 1189 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 1190 i += n; 1191 outs() << " narguments " << narguments << "\n"; 1192 if (i >= nloh) 1193 return; 1194 1195 for (uint32_t j = 0; j < narguments; j++) { 1196 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 1197 i += n; 1198 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 1199 if (i >= nloh) 1200 return; 1201 } 1202 } 1203 } 1204 1205 static void PrintDylibs(MachOObjectFile *O, bool JustId) { 1206 unsigned Index = 0; 1207 for (const auto &Load : O->load_commands()) { 1208 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 1209 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 1210 Load.C.cmd == MachO::LC_LOAD_DYLIB || 1211 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 1212 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 1213 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 1214 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 1215 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 1216 if (dl.dylib.name < dl.cmdsize) { 1217 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 1218 if (JustId) 1219 outs() << p << "\n"; 1220 else { 1221 outs() << "\t" << p; 1222 outs() << " (compatibility version " 1223 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 1224 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 1225 << (dl.dylib.compatibility_version & 0xff) << ","; 1226 outs() << " current version " 1227 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 1228 << ((dl.dylib.current_version >> 8) & 0xff) << "." 1229 << (dl.dylib.current_version & 0xff); 1230 if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 1231 outs() << ", weak"; 1232 if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 1233 outs() << ", reexport"; 1234 if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 1235 outs() << ", upward"; 1236 if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 1237 outs() << ", lazy"; 1238 outs() << ")\n"; 1239 } 1240 } else { 1241 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 1242 if (Load.C.cmd == MachO::LC_ID_DYLIB) 1243 outs() << "LC_ID_DYLIB "; 1244 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 1245 outs() << "LC_LOAD_DYLIB "; 1246 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 1247 outs() << "LC_LOAD_WEAK_DYLIB "; 1248 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 1249 outs() << "LC_LAZY_LOAD_DYLIB "; 1250 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 1251 outs() << "LC_REEXPORT_DYLIB "; 1252 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 1253 outs() << "LC_LOAD_UPWARD_DYLIB "; 1254 else 1255 outs() << "LC_??? "; 1256 outs() << "command " << Index++ << "\n"; 1257 } 1258 } 1259 } 1260 } 1261 1262 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 1263 1264 static void CreateSymbolAddressMap(MachOObjectFile *O, 1265 SymbolAddressMap *AddrMap) { 1266 // Create a map of symbol addresses to symbol names. 1267 const StringRef FileName = O->getFileName(); 1268 for (const SymbolRef &Symbol : O->symbols()) { 1269 SymbolRef::Type ST = unwrapOrError(Symbol.getType(), FileName); 1270 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 1271 ST == SymbolRef::ST_Other) { 1272 uint64_t Address = cantFail(Symbol.getValue()); 1273 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 1274 if (!SymName.startswith(".objc")) 1275 (*AddrMap)[Address] = SymName; 1276 } 1277 } 1278 } 1279 1280 // GuessSymbolName is passed the address of what might be a symbol and a 1281 // pointer to the SymbolAddressMap. It returns the name of a symbol 1282 // with that address or nullptr if no symbol is found with that address. 1283 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 1284 const char *SymbolName = nullptr; 1285 // A DenseMap can't lookup up some values. 1286 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 1287 StringRef name = AddrMap->lookup(value); 1288 if (!name.empty()) 1289 SymbolName = name.data(); 1290 } 1291 return SymbolName; 1292 } 1293 1294 static void DumpCstringChar(const char c) { 1295 char p[2]; 1296 p[0] = c; 1297 p[1] = '\0'; 1298 outs().write_escaped(p); 1299 } 1300 1301 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 1302 uint32_t sect_size, uint64_t sect_addr, 1303 bool print_addresses) { 1304 for (uint32_t i = 0; i < sect_size; i++) { 1305 if (print_addresses) { 1306 if (O->is64Bit()) 1307 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1308 else 1309 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1310 } 1311 for (; i < sect_size && sect[i] != '\0'; i++) 1312 DumpCstringChar(sect[i]); 1313 if (i < sect_size && sect[i] == '\0') 1314 outs() << "\n"; 1315 } 1316 } 1317 1318 static void DumpLiteral4(uint32_t l, float f) { 1319 outs() << format("0x%08" PRIx32, l); 1320 if ((l & 0x7f800000) != 0x7f800000) 1321 outs() << format(" (%.16e)\n", f); 1322 else { 1323 if (l == 0x7f800000) 1324 outs() << " (+Infinity)\n"; 1325 else if (l == 0xff800000) 1326 outs() << " (-Infinity)\n"; 1327 else if ((l & 0x00400000) == 0x00400000) 1328 outs() << " (non-signaling Not-a-Number)\n"; 1329 else 1330 outs() << " (signaling Not-a-Number)\n"; 1331 } 1332 } 1333 1334 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 1335 uint32_t sect_size, uint64_t sect_addr, 1336 bool print_addresses) { 1337 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 1338 if (print_addresses) { 1339 if (O->is64Bit()) 1340 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1341 else 1342 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1343 } 1344 float f; 1345 memcpy(&f, sect + i, sizeof(float)); 1346 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1347 sys::swapByteOrder(f); 1348 uint32_t l; 1349 memcpy(&l, sect + i, sizeof(uint32_t)); 1350 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1351 sys::swapByteOrder(l); 1352 DumpLiteral4(l, f); 1353 } 1354 } 1355 1356 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 1357 double d) { 1358 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 1359 uint32_t Hi, Lo; 1360 Hi = (O->isLittleEndian()) ? l1 : l0; 1361 Lo = (O->isLittleEndian()) ? l0 : l1; 1362 1363 // Hi is the high word, so this is equivalent to if(isfinite(d)) 1364 if ((Hi & 0x7ff00000) != 0x7ff00000) 1365 outs() << format(" (%.16e)\n", d); 1366 else { 1367 if (Hi == 0x7ff00000 && Lo == 0) 1368 outs() << " (+Infinity)\n"; 1369 else if (Hi == 0xfff00000 && Lo == 0) 1370 outs() << " (-Infinity)\n"; 1371 else if ((Hi & 0x00080000) == 0x00080000) 1372 outs() << " (non-signaling Not-a-Number)\n"; 1373 else 1374 outs() << " (signaling Not-a-Number)\n"; 1375 } 1376 } 1377 1378 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 1379 uint32_t sect_size, uint64_t sect_addr, 1380 bool print_addresses) { 1381 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 1382 if (print_addresses) { 1383 if (O->is64Bit()) 1384 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1385 else 1386 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1387 } 1388 double d; 1389 memcpy(&d, sect + i, sizeof(double)); 1390 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1391 sys::swapByteOrder(d); 1392 uint32_t l0, l1; 1393 memcpy(&l0, sect + i, sizeof(uint32_t)); 1394 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1395 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1396 sys::swapByteOrder(l0); 1397 sys::swapByteOrder(l1); 1398 } 1399 DumpLiteral8(O, l0, l1, d); 1400 } 1401 } 1402 1403 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 1404 outs() << format("0x%08" PRIx32, l0) << " "; 1405 outs() << format("0x%08" PRIx32, l1) << " "; 1406 outs() << format("0x%08" PRIx32, l2) << " "; 1407 outs() << format("0x%08" PRIx32, l3) << "\n"; 1408 } 1409 1410 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 1411 uint32_t sect_size, uint64_t sect_addr, 1412 bool print_addresses) { 1413 for (uint32_t i = 0; i < sect_size; i += 16) { 1414 if (print_addresses) { 1415 if (O->is64Bit()) 1416 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1417 else 1418 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1419 } 1420 uint32_t l0, l1, l2, l3; 1421 memcpy(&l0, sect + i, sizeof(uint32_t)); 1422 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1423 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 1424 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1425 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1426 sys::swapByteOrder(l0); 1427 sys::swapByteOrder(l1); 1428 sys::swapByteOrder(l2); 1429 sys::swapByteOrder(l3); 1430 } 1431 DumpLiteral16(l0, l1, l2, l3); 1432 } 1433 } 1434 1435 static void DumpLiteralPointerSection(MachOObjectFile *O, 1436 const SectionRef &Section, 1437 const char *sect, uint32_t sect_size, 1438 uint64_t sect_addr, 1439 bool print_addresses) { 1440 // Collect the literal sections in this Mach-O file. 1441 std::vector<SectionRef> LiteralSections; 1442 for (const SectionRef &Section : O->sections()) { 1443 DataRefImpl Ref = Section.getRawDataRefImpl(); 1444 uint32_t section_type; 1445 if (O->is64Bit()) { 1446 const MachO::section_64 Sec = O->getSection64(Ref); 1447 section_type = Sec.flags & MachO::SECTION_TYPE; 1448 } else { 1449 const MachO::section Sec = O->getSection(Ref); 1450 section_type = Sec.flags & MachO::SECTION_TYPE; 1451 } 1452 if (section_type == MachO::S_CSTRING_LITERALS || 1453 section_type == MachO::S_4BYTE_LITERALS || 1454 section_type == MachO::S_8BYTE_LITERALS || 1455 section_type == MachO::S_16BYTE_LITERALS) 1456 LiteralSections.push_back(Section); 1457 } 1458 1459 // Set the size of the literal pointer. 1460 uint32_t lp_size = O->is64Bit() ? 8 : 4; 1461 1462 // Collect the external relocation symbols for the literal pointers. 1463 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1464 for (const RelocationRef &Reloc : Section.relocations()) { 1465 DataRefImpl Rel; 1466 MachO::any_relocation_info RE; 1467 bool isExtern = false; 1468 Rel = Reloc.getRawDataRefImpl(); 1469 RE = O->getRelocation(Rel); 1470 isExtern = O->getPlainRelocationExternal(RE); 1471 if (isExtern) { 1472 uint64_t RelocOffset = Reloc.getOffset(); 1473 symbol_iterator RelocSym = Reloc.getSymbol(); 1474 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1475 } 1476 } 1477 array_pod_sort(Relocs.begin(), Relocs.end()); 1478 1479 // Dump each literal pointer. 1480 for (uint32_t i = 0; i < sect_size; i += lp_size) { 1481 if (print_addresses) { 1482 if (O->is64Bit()) 1483 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1484 else 1485 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1486 } 1487 uint64_t lp; 1488 if (O->is64Bit()) { 1489 memcpy(&lp, sect + i, sizeof(uint64_t)); 1490 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1491 sys::swapByteOrder(lp); 1492 } else { 1493 uint32_t li; 1494 memcpy(&li, sect + i, sizeof(uint32_t)); 1495 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1496 sys::swapByteOrder(li); 1497 lp = li; 1498 } 1499 1500 // First look for an external relocation entry for this literal pointer. 1501 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1502 return P.first == i; 1503 }); 1504 if (Reloc != Relocs.end()) { 1505 symbol_iterator RelocSym = Reloc->second; 1506 StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName()); 1507 outs() << "external relocation entry for symbol:" << SymName << "\n"; 1508 continue; 1509 } 1510 1511 // For local references see what the section the literal pointer points to. 1512 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 1513 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 1514 }); 1515 if (Sect == LiteralSections.end()) { 1516 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 1517 continue; 1518 } 1519 1520 uint64_t SectAddress = Sect->getAddress(); 1521 uint64_t SectSize = Sect->getSize(); 1522 1523 StringRef SectName; 1524 Expected<StringRef> SectNameOrErr = Sect->getName(); 1525 if (SectNameOrErr) 1526 SectName = *SectNameOrErr; 1527 else 1528 consumeError(SectNameOrErr.takeError()); 1529 1530 DataRefImpl Ref = Sect->getRawDataRefImpl(); 1531 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 1532 outs() << SegmentName << ":" << SectName << ":"; 1533 1534 uint32_t section_type; 1535 if (O->is64Bit()) { 1536 const MachO::section_64 Sec = O->getSection64(Ref); 1537 section_type = Sec.flags & MachO::SECTION_TYPE; 1538 } else { 1539 const MachO::section Sec = O->getSection(Ref); 1540 section_type = Sec.flags & MachO::SECTION_TYPE; 1541 } 1542 1543 StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName()); 1544 1545 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 1546 1547 switch (section_type) { 1548 case MachO::S_CSTRING_LITERALS: 1549 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 1550 i++) { 1551 DumpCstringChar(Contents[i]); 1552 } 1553 outs() << "\n"; 1554 break; 1555 case MachO::S_4BYTE_LITERALS: 1556 float f; 1557 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 1558 uint32_t l; 1559 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 1560 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1561 sys::swapByteOrder(f); 1562 sys::swapByteOrder(l); 1563 } 1564 DumpLiteral4(l, f); 1565 break; 1566 case MachO::S_8BYTE_LITERALS: { 1567 double d; 1568 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 1569 uint32_t l0, l1; 1570 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1571 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1572 sizeof(uint32_t)); 1573 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1574 sys::swapByteOrder(f); 1575 sys::swapByteOrder(l0); 1576 sys::swapByteOrder(l1); 1577 } 1578 DumpLiteral8(O, l0, l1, d); 1579 break; 1580 } 1581 case MachO::S_16BYTE_LITERALS: { 1582 uint32_t l0, l1, l2, l3; 1583 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1584 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1585 sizeof(uint32_t)); 1586 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 1587 sizeof(uint32_t)); 1588 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 1589 sizeof(uint32_t)); 1590 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1591 sys::swapByteOrder(l0); 1592 sys::swapByteOrder(l1); 1593 sys::swapByteOrder(l2); 1594 sys::swapByteOrder(l3); 1595 } 1596 DumpLiteral16(l0, l1, l2, l3); 1597 break; 1598 } 1599 } 1600 } 1601 } 1602 1603 static void DumpInitTermPointerSection(MachOObjectFile *O, 1604 const SectionRef &Section, 1605 const char *sect, 1606 uint32_t sect_size, uint64_t sect_addr, 1607 SymbolAddressMap *AddrMap, 1608 bool verbose) { 1609 uint32_t stride; 1610 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 1611 1612 // Collect the external relocation symbols for the pointers. 1613 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1614 for (const RelocationRef &Reloc : Section.relocations()) { 1615 DataRefImpl Rel; 1616 MachO::any_relocation_info RE; 1617 bool isExtern = false; 1618 Rel = Reloc.getRawDataRefImpl(); 1619 RE = O->getRelocation(Rel); 1620 isExtern = O->getPlainRelocationExternal(RE); 1621 if (isExtern) { 1622 uint64_t RelocOffset = Reloc.getOffset(); 1623 symbol_iterator RelocSym = Reloc.getSymbol(); 1624 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1625 } 1626 } 1627 array_pod_sort(Relocs.begin(), Relocs.end()); 1628 1629 for (uint32_t i = 0; i < sect_size; i += stride) { 1630 const char *SymbolName = nullptr; 1631 uint64_t p; 1632 if (O->is64Bit()) { 1633 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 1634 uint64_t pointer_value; 1635 memcpy(&pointer_value, sect + i, stride); 1636 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1637 sys::swapByteOrder(pointer_value); 1638 outs() << format("0x%016" PRIx64, pointer_value); 1639 p = pointer_value; 1640 } else { 1641 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 1642 uint32_t pointer_value; 1643 memcpy(&pointer_value, sect + i, stride); 1644 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1645 sys::swapByteOrder(pointer_value); 1646 outs() << format("0x%08" PRIx32, pointer_value); 1647 p = pointer_value; 1648 } 1649 if (verbose) { 1650 // First look for an external relocation entry for this pointer. 1651 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1652 return P.first == i; 1653 }); 1654 if (Reloc != Relocs.end()) { 1655 symbol_iterator RelocSym = Reloc->second; 1656 outs() << " " << unwrapOrError(RelocSym->getName(), O->getFileName()); 1657 } else { 1658 SymbolName = GuessSymbolName(p, AddrMap); 1659 if (SymbolName) 1660 outs() << " " << SymbolName; 1661 } 1662 } 1663 outs() << "\n"; 1664 } 1665 } 1666 1667 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 1668 uint32_t size, uint64_t addr) { 1669 uint32_t cputype = O->getHeader().cputype; 1670 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 1671 uint32_t j; 1672 for (uint32_t i = 0; i < size; i += j, addr += j) { 1673 if (O->is64Bit()) 1674 outs() << format("%016" PRIx64, addr) << "\t"; 1675 else 1676 outs() << format("%08" PRIx64, addr) << "\t"; 1677 for (j = 0; j < 16 && i + j < size; j++) { 1678 uint8_t byte_word = *(sect + i + j); 1679 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1680 } 1681 outs() << "\n"; 1682 } 1683 } else { 1684 uint32_t j; 1685 for (uint32_t i = 0; i < size; i += j, addr += j) { 1686 if (O->is64Bit()) 1687 outs() << format("%016" PRIx64, addr) << "\t"; 1688 else 1689 outs() << format("%08" PRIx64, addr) << "\t"; 1690 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 1691 j += sizeof(int32_t)) { 1692 if (i + j + sizeof(int32_t) <= size) { 1693 uint32_t long_word; 1694 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1695 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1696 sys::swapByteOrder(long_word); 1697 outs() << format("%08" PRIx32, long_word) << " "; 1698 } else { 1699 for (uint32_t k = 0; i + j + k < size; k++) { 1700 uint8_t byte_word = *(sect + i + j + k); 1701 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1702 } 1703 } 1704 } 1705 outs() << "\n"; 1706 } 1707 } 1708 } 1709 1710 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1711 StringRef DisSegName, StringRef DisSectName); 1712 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1713 uint32_t size, uint32_t addr); 1714 #ifdef HAVE_LIBXAR 1715 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 1716 uint32_t size, bool verbose, 1717 bool PrintXarHeader, bool PrintXarFileHeaders, 1718 std::string XarMemberName); 1719 #endif // defined(HAVE_LIBXAR) 1720 1721 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1722 bool verbose) { 1723 SymbolAddressMap AddrMap; 1724 if (verbose) 1725 CreateSymbolAddressMap(O, &AddrMap); 1726 1727 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1728 StringRef DumpSection = FilterSections[i]; 1729 std::pair<StringRef, StringRef> DumpSegSectName; 1730 DumpSegSectName = DumpSection.split(','); 1731 StringRef DumpSegName, DumpSectName; 1732 if (!DumpSegSectName.second.empty()) { 1733 DumpSegName = DumpSegSectName.first; 1734 DumpSectName = DumpSegSectName.second; 1735 } else { 1736 DumpSegName = ""; 1737 DumpSectName = DumpSegSectName.first; 1738 } 1739 for (const SectionRef &Section : O->sections()) { 1740 StringRef SectName; 1741 Expected<StringRef> SecNameOrErr = Section.getName(); 1742 if (SecNameOrErr) 1743 SectName = *SecNameOrErr; 1744 else 1745 consumeError(SecNameOrErr.takeError()); 1746 1747 if (!DumpSection.empty()) 1748 FoundSectionSet.insert(DumpSection); 1749 1750 DataRefImpl Ref = Section.getRawDataRefImpl(); 1751 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1752 if ((DumpSegName.empty() || SegName == DumpSegName) && 1753 (SectName == DumpSectName)) { 1754 1755 uint32_t section_flags; 1756 if (O->is64Bit()) { 1757 const MachO::section_64 Sec = O->getSection64(Ref); 1758 section_flags = Sec.flags; 1759 1760 } else { 1761 const MachO::section Sec = O->getSection(Ref); 1762 section_flags = Sec.flags; 1763 } 1764 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1765 1766 StringRef BytesStr = 1767 unwrapOrError(Section.getContents(), O->getFileName()); 1768 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1769 uint32_t sect_size = BytesStr.size(); 1770 uint64_t sect_addr = Section.getAddress(); 1771 1772 if (!NoLeadingHeaders) 1773 outs() << "Contents of (" << SegName << "," << SectName 1774 << ") section\n"; 1775 1776 if (verbose) { 1777 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1778 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1779 DisassembleMachO(Filename, O, SegName, SectName); 1780 continue; 1781 } 1782 if (SegName == "__TEXT" && SectName == "__info_plist") { 1783 outs() << sect; 1784 continue; 1785 } 1786 if (SegName == "__OBJC" && SectName == "__protocol") { 1787 DumpProtocolSection(O, sect, sect_size, sect_addr); 1788 continue; 1789 } 1790 #ifdef HAVE_LIBXAR 1791 if (SegName == "__LLVM" && SectName == "__bundle") { 1792 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands, 1793 ArchiveHeaders, ""); 1794 continue; 1795 } 1796 #endif // defined(HAVE_LIBXAR) 1797 switch (section_type) { 1798 case MachO::S_REGULAR: 1799 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1800 break; 1801 case MachO::S_ZEROFILL: 1802 outs() << "zerofill section and has no contents in the file\n"; 1803 break; 1804 case MachO::S_CSTRING_LITERALS: 1805 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1806 break; 1807 case MachO::S_4BYTE_LITERALS: 1808 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1809 break; 1810 case MachO::S_8BYTE_LITERALS: 1811 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1812 break; 1813 case MachO::S_16BYTE_LITERALS: 1814 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1815 break; 1816 case MachO::S_LITERAL_POINTERS: 1817 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1818 !NoLeadingAddr); 1819 break; 1820 case MachO::S_MOD_INIT_FUNC_POINTERS: 1821 case MachO::S_MOD_TERM_FUNC_POINTERS: 1822 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr, 1823 &AddrMap, verbose); 1824 break; 1825 default: 1826 outs() << "Unknown section type (" 1827 << format("0x%08" PRIx32, section_type) << ")\n"; 1828 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1829 break; 1830 } 1831 } else { 1832 if (section_type == MachO::S_ZEROFILL) 1833 outs() << "zerofill section and has no contents in the file\n"; 1834 else 1835 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1836 } 1837 } 1838 } 1839 } 1840 } 1841 1842 static void DumpInfoPlistSectionContents(StringRef Filename, 1843 MachOObjectFile *O) { 1844 for (const SectionRef &Section : O->sections()) { 1845 StringRef SectName; 1846 Expected<StringRef> SecNameOrErr = Section.getName(); 1847 if (SecNameOrErr) 1848 SectName = *SecNameOrErr; 1849 else 1850 consumeError(SecNameOrErr.takeError()); 1851 1852 DataRefImpl Ref = Section.getRawDataRefImpl(); 1853 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1854 if (SegName == "__TEXT" && SectName == "__info_plist") { 1855 if (!NoLeadingHeaders) 1856 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1857 StringRef BytesStr = 1858 unwrapOrError(Section.getContents(), O->getFileName()); 1859 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1860 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 1861 return; 1862 } 1863 } 1864 } 1865 1866 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1867 // and if it is and there is a list of architecture flags is specified then 1868 // check to make sure this Mach-O file is one of those architectures or all 1869 // architectures were specified. If not then an error is generated and this 1870 // routine returns false. Else it returns true. 1871 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1872 auto *MachO = dyn_cast<MachOObjectFile>(O); 1873 1874 if (!MachO || ArchAll || ArchFlags.empty()) 1875 return true; 1876 1877 MachO::mach_header H; 1878 MachO::mach_header_64 H_64; 1879 Triple T; 1880 const char *McpuDefault, *ArchFlag; 1881 if (MachO->is64Bit()) { 1882 H_64 = MachO->MachOObjectFile::getHeader64(); 1883 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 1884 &McpuDefault, &ArchFlag); 1885 } else { 1886 H = MachO->MachOObjectFile::getHeader(); 1887 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 1888 &McpuDefault, &ArchFlag); 1889 } 1890 const std::string ArchFlagName(ArchFlag); 1891 if (none_of(ArchFlags, [&](const std::string &Name) { 1892 return Name == ArchFlagName; 1893 })) { 1894 WithColor::error(errs(), "llvm-objdump") 1895 << Filename << ": no architecture specified.\n"; 1896 return false; 1897 } 1898 return true; 1899 } 1900 1901 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 1902 1903 // ProcessMachO() is passed a single opened Mach-O file, which may be an 1904 // archive member and or in a slice of a universal file. It prints the 1905 // the file name and header info and then processes it according to the 1906 // command line options. 1907 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 1908 StringRef ArchiveMemberName = StringRef(), 1909 StringRef ArchitectureName = StringRef()) { 1910 // If we are doing some processing here on the Mach-O file print the header 1911 // info. And don't print it otherwise like in the case of printing the 1912 // UniversalHeaders or ArchiveHeaders. 1913 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || 1914 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || 1915 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData || 1916 (!FilterSections.empty())) { 1917 if (!NoLeadingHeaders) { 1918 outs() << Name; 1919 if (!ArchiveMemberName.empty()) 1920 outs() << '(' << ArchiveMemberName << ')'; 1921 if (!ArchitectureName.empty()) 1922 outs() << " (architecture " << ArchitectureName << ")"; 1923 outs() << ":\n"; 1924 } 1925 } 1926 // To use the report_error() form with an ArchiveName and FileName set 1927 // these up based on what is passed for Name and ArchiveMemberName. 1928 StringRef ArchiveName; 1929 StringRef FileName; 1930 if (!ArchiveMemberName.empty()) { 1931 ArchiveName = Name; 1932 FileName = ArchiveMemberName; 1933 } else { 1934 ArchiveName = StringRef(); 1935 FileName = Name; 1936 } 1937 1938 // If we need the symbol table to do the operation then check it here to 1939 // produce a good error message as to where the Mach-O file comes from in 1940 // the error message. 1941 if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo) 1942 if (Error Err = MachOOF->checkSymbolTable()) 1943 reportError(std::move(Err), FileName, ArchiveName, ArchitectureName); 1944 1945 if (DisassembleAll) { 1946 for (const SectionRef &Section : MachOOF->sections()) { 1947 StringRef SectName; 1948 if (Expected<StringRef> NameOrErr = Section.getName()) 1949 SectName = *NameOrErr; 1950 else 1951 consumeError(NameOrErr.takeError()); 1952 1953 if (SectName.equals("__text")) { 1954 DataRefImpl Ref = Section.getRawDataRefImpl(); 1955 StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref); 1956 DisassembleMachO(FileName, MachOOF, SegName, SectName); 1957 } 1958 } 1959 } 1960 else if (Disassemble) { 1961 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE && 1962 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64) 1963 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text"); 1964 else 1965 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 1966 } 1967 if (IndirectSymbols) 1968 PrintIndirectSymbols(MachOOF, !NonVerbose); 1969 if (DataInCode) 1970 PrintDataInCodeTable(MachOOF, !NonVerbose); 1971 if (LinkOptHints) 1972 PrintLinkOptHints(MachOOF); 1973 if (Relocations) 1974 PrintRelocations(MachOOF, !NonVerbose); 1975 if (SectionHeaders) 1976 printSectionHeaders(MachOOF); 1977 if (SectionContents) 1978 printSectionContents(MachOOF); 1979 if (!FilterSections.empty()) 1980 DumpSectionContents(FileName, MachOOF, !NonVerbose); 1981 if (InfoPlist) 1982 DumpInfoPlistSectionContents(FileName, MachOOF); 1983 if (DylibsUsed) 1984 PrintDylibs(MachOOF, false); 1985 if (DylibId) 1986 PrintDylibs(MachOOF, true); 1987 if (SymbolTable) 1988 printSymbolTable(MachOOF, ArchiveName, ArchitectureName); 1989 if (UnwindInfo) 1990 printMachOUnwindInfo(MachOOF); 1991 if (PrivateHeaders) { 1992 printMachOFileHeader(MachOOF); 1993 printMachOLoadCommands(MachOOF); 1994 } 1995 if (FirstPrivateHeader) 1996 printMachOFileHeader(MachOOF); 1997 if (ObjcMetaData) 1998 printObjcMetaData(MachOOF, !NonVerbose); 1999 if (ExportsTrie) 2000 printExportsTrie(MachOOF); 2001 if (Rebase) 2002 printRebaseTable(MachOOF); 2003 if (Bind) 2004 printBindTable(MachOOF); 2005 if (LazyBind) 2006 printLazyBindTable(MachOOF); 2007 if (WeakBind) 2008 printWeakBindTable(MachOOF); 2009 2010 if (DwarfDumpType != DIDT_Null) { 2011 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF); 2012 // Dump the complete DWARF structure. 2013 DIDumpOptions DumpOpts; 2014 DumpOpts.DumpType = DwarfDumpType; 2015 DICtx->dump(outs(), DumpOpts); 2016 } 2017 } 2018 2019 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 2020 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 2021 outs() << " cputype (" << cputype << ")\n"; 2022 outs() << " cpusubtype (" << cpusubtype << ")\n"; 2023 } 2024 2025 // printCPUType() helps print_fat_headers by printing the cputype and 2026 // pusubtype (symbolically for the one's it knows about). 2027 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 2028 switch (cputype) { 2029 case MachO::CPU_TYPE_I386: 2030 switch (cpusubtype) { 2031 case MachO::CPU_SUBTYPE_I386_ALL: 2032 outs() << " cputype CPU_TYPE_I386\n"; 2033 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 2034 break; 2035 default: 2036 printUnknownCPUType(cputype, cpusubtype); 2037 break; 2038 } 2039 break; 2040 case MachO::CPU_TYPE_X86_64: 2041 switch (cpusubtype) { 2042 case MachO::CPU_SUBTYPE_X86_64_ALL: 2043 outs() << " cputype CPU_TYPE_X86_64\n"; 2044 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 2045 break; 2046 case MachO::CPU_SUBTYPE_X86_64_H: 2047 outs() << " cputype CPU_TYPE_X86_64\n"; 2048 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 2049 break; 2050 default: 2051 printUnknownCPUType(cputype, cpusubtype); 2052 break; 2053 } 2054 break; 2055 case MachO::CPU_TYPE_ARM: 2056 switch (cpusubtype) { 2057 case MachO::CPU_SUBTYPE_ARM_ALL: 2058 outs() << " cputype CPU_TYPE_ARM\n"; 2059 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 2060 break; 2061 case MachO::CPU_SUBTYPE_ARM_V4T: 2062 outs() << " cputype CPU_TYPE_ARM\n"; 2063 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 2064 break; 2065 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2066 outs() << " cputype CPU_TYPE_ARM\n"; 2067 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 2068 break; 2069 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2070 outs() << " cputype CPU_TYPE_ARM\n"; 2071 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 2072 break; 2073 case MachO::CPU_SUBTYPE_ARM_V6: 2074 outs() << " cputype CPU_TYPE_ARM\n"; 2075 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 2076 break; 2077 case MachO::CPU_SUBTYPE_ARM_V6M: 2078 outs() << " cputype CPU_TYPE_ARM\n"; 2079 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 2080 break; 2081 case MachO::CPU_SUBTYPE_ARM_V7: 2082 outs() << " cputype CPU_TYPE_ARM\n"; 2083 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 2084 break; 2085 case MachO::CPU_SUBTYPE_ARM_V7EM: 2086 outs() << " cputype CPU_TYPE_ARM\n"; 2087 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 2088 break; 2089 case MachO::CPU_SUBTYPE_ARM_V7K: 2090 outs() << " cputype CPU_TYPE_ARM\n"; 2091 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 2092 break; 2093 case MachO::CPU_SUBTYPE_ARM_V7M: 2094 outs() << " cputype CPU_TYPE_ARM\n"; 2095 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 2096 break; 2097 case MachO::CPU_SUBTYPE_ARM_V7S: 2098 outs() << " cputype CPU_TYPE_ARM\n"; 2099 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 2100 break; 2101 default: 2102 printUnknownCPUType(cputype, cpusubtype); 2103 break; 2104 } 2105 break; 2106 case MachO::CPU_TYPE_ARM64: 2107 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2108 case MachO::CPU_SUBTYPE_ARM64_ALL: 2109 outs() << " cputype CPU_TYPE_ARM64\n"; 2110 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 2111 break; 2112 case MachO::CPU_SUBTYPE_ARM64_V8: 2113 outs() << " cputype CPU_TYPE_ARM64\n"; 2114 outs() << " cpusubtype CPU_SUBTYPE_ARM64_V8\n"; 2115 break; 2116 case MachO::CPU_SUBTYPE_ARM64E: 2117 outs() << " cputype CPU_TYPE_ARM64\n"; 2118 outs() << " cpusubtype CPU_SUBTYPE_ARM64E\n"; 2119 break; 2120 default: 2121 printUnknownCPUType(cputype, cpusubtype); 2122 break; 2123 } 2124 break; 2125 case MachO::CPU_TYPE_ARM64_32: 2126 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2127 case MachO::CPU_SUBTYPE_ARM64_32_V8: 2128 outs() << " cputype CPU_TYPE_ARM64_32\n"; 2129 outs() << " cpusubtype CPU_SUBTYPE_ARM64_32_V8\n"; 2130 break; 2131 default: 2132 printUnknownCPUType(cputype, cpusubtype); 2133 break; 2134 } 2135 break; 2136 default: 2137 printUnknownCPUType(cputype, cpusubtype); 2138 break; 2139 } 2140 } 2141 2142 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 2143 bool verbose) { 2144 outs() << "Fat headers\n"; 2145 if (verbose) { 2146 if (UB->getMagic() == MachO::FAT_MAGIC) 2147 outs() << "fat_magic FAT_MAGIC\n"; 2148 else // UB->getMagic() == MachO::FAT_MAGIC_64 2149 outs() << "fat_magic FAT_MAGIC_64\n"; 2150 } else 2151 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 2152 2153 uint32_t nfat_arch = UB->getNumberOfObjects(); 2154 StringRef Buf = UB->getData(); 2155 uint64_t size = Buf.size(); 2156 uint64_t big_size = sizeof(struct MachO::fat_header) + 2157 nfat_arch * sizeof(struct MachO::fat_arch); 2158 outs() << "nfat_arch " << UB->getNumberOfObjects(); 2159 if (nfat_arch == 0) 2160 outs() << " (malformed, contains zero architecture types)\n"; 2161 else if (big_size > size) 2162 outs() << " (malformed, architectures past end of file)\n"; 2163 else 2164 outs() << "\n"; 2165 2166 for (uint32_t i = 0; i < nfat_arch; ++i) { 2167 MachOUniversalBinary::ObjectForArch OFA(UB, i); 2168 uint32_t cputype = OFA.getCPUType(); 2169 uint32_t cpusubtype = OFA.getCPUSubType(); 2170 outs() << "architecture "; 2171 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 2172 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 2173 uint32_t other_cputype = other_OFA.getCPUType(); 2174 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 2175 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 2176 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 2177 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 2178 outs() << "(illegal duplicate architecture) "; 2179 break; 2180 } 2181 } 2182 if (verbose) { 2183 outs() << OFA.getArchFlagName() << "\n"; 2184 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2185 } else { 2186 outs() << i << "\n"; 2187 outs() << " cputype " << cputype << "\n"; 2188 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 2189 << "\n"; 2190 } 2191 if (verbose && 2192 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 2193 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 2194 else 2195 outs() << " capabilities " 2196 << format("0x%" PRIx32, 2197 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 2198 outs() << " offset " << OFA.getOffset(); 2199 if (OFA.getOffset() > size) 2200 outs() << " (past end of file)"; 2201 if (OFA.getOffset() % (1ull << OFA.getAlign()) != 0) 2202 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 2203 outs() << "\n"; 2204 outs() << " size " << OFA.getSize(); 2205 big_size = OFA.getOffset() + OFA.getSize(); 2206 if (big_size > size) 2207 outs() << " (past end of file)"; 2208 outs() << "\n"; 2209 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 2210 << ")\n"; 2211 } 2212 } 2213 2214 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 2215 size_t ChildIndex, bool verbose, 2216 bool print_offset, 2217 StringRef ArchitectureName = StringRef()) { 2218 if (print_offset) 2219 outs() << C.getChildOffset() << "\t"; 2220 sys::fs::perms Mode = 2221 unwrapOrError(C.getAccessMode(), getFileNameForError(C, ChildIndex), 2222 Filename, ArchitectureName); 2223 if (verbose) { 2224 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 2225 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 2226 outs() << "-"; 2227 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 2228 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 2229 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 2230 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 2231 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 2232 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 2233 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 2234 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 2235 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 2236 } else { 2237 outs() << format("0%o ", Mode); 2238 } 2239 2240 outs() << format("%3d/%-3d %5" PRId64 " ", 2241 unwrapOrError(C.getUID(), getFileNameForError(C, ChildIndex), 2242 Filename, ArchitectureName), 2243 unwrapOrError(C.getGID(), getFileNameForError(C, ChildIndex), 2244 Filename, ArchitectureName), 2245 unwrapOrError(C.getRawSize(), 2246 getFileNameForError(C, ChildIndex), Filename, 2247 ArchitectureName)); 2248 2249 StringRef RawLastModified = C.getRawLastModified(); 2250 if (verbose) { 2251 unsigned Seconds; 2252 if (RawLastModified.getAsInteger(10, Seconds)) 2253 outs() << "(date: \"" << RawLastModified 2254 << "\" contains non-decimal chars) "; 2255 else { 2256 // Since cime(3) returns a 26 character string of the form: 2257 // "Sun Sep 16 01:03:52 1973\n\0" 2258 // just print 24 characters. 2259 time_t t = Seconds; 2260 outs() << format("%.24s ", ctime(&t)); 2261 } 2262 } else { 2263 outs() << RawLastModified << " "; 2264 } 2265 2266 if (verbose) { 2267 Expected<StringRef> NameOrErr = C.getName(); 2268 if (!NameOrErr) { 2269 consumeError(NameOrErr.takeError()); 2270 outs() << unwrapOrError(C.getRawName(), 2271 getFileNameForError(C, ChildIndex), Filename, 2272 ArchitectureName) 2273 << "\n"; 2274 } else { 2275 StringRef Name = NameOrErr.get(); 2276 outs() << Name << "\n"; 2277 } 2278 } else { 2279 outs() << unwrapOrError(C.getRawName(), getFileNameForError(C, ChildIndex), 2280 Filename, ArchitectureName) 2281 << "\n"; 2282 } 2283 } 2284 2285 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 2286 bool print_offset, 2287 StringRef ArchitectureName = StringRef()) { 2288 Error Err = Error::success(); 2289 size_t I = 0; 2290 for (const auto &C : A->children(Err, false)) 2291 printArchiveChild(Filename, C, I++, verbose, print_offset, 2292 ArchitectureName); 2293 2294 if (Err) 2295 reportError(std::move(Err), Filename, "", ArchitectureName); 2296 } 2297 2298 static bool ValidateArchFlags() { 2299 // Check for -arch all and verifiy the -arch flags are valid. 2300 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2301 if (ArchFlags[i] == "all") { 2302 ArchAll = true; 2303 } else { 2304 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 2305 WithColor::error(errs(), "llvm-objdump") 2306 << "unknown architecture named '" + ArchFlags[i] + 2307 "'for the -arch option\n"; 2308 return false; 2309 } 2310 } 2311 } 2312 return true; 2313 } 2314 2315 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 2316 // -arch flags selecting just those slices as specified by them and also parses 2317 // archive files. Then for each individual Mach-O file ProcessMachO() is 2318 // called to process the file based on the command line options. 2319 void objdump::parseInputMachO(StringRef Filename) { 2320 if (!ValidateArchFlags()) 2321 return; 2322 2323 // Attempt to open the binary. 2324 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 2325 if (!BinaryOrErr) { 2326 if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 2327 reportError(std::move(E), Filename); 2328 else 2329 outs() << Filename << ": is not an object file\n"; 2330 return; 2331 } 2332 Binary &Bin = *BinaryOrErr.get().getBinary(); 2333 2334 if (Archive *A = dyn_cast<Archive>(&Bin)) { 2335 outs() << "Archive : " << Filename << "\n"; 2336 if (ArchiveHeaders) 2337 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets); 2338 2339 Error Err = Error::success(); 2340 unsigned I = -1; 2341 for (auto &C : A->children(Err)) { 2342 ++I; 2343 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2344 if (!ChildOrErr) { 2345 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2346 reportError(std::move(E), getFileNameForError(C, I), Filename); 2347 continue; 2348 } 2349 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2350 if (!checkMachOAndArchFlags(O, Filename)) 2351 return; 2352 ProcessMachO(Filename, O, O->getFileName()); 2353 } 2354 } 2355 if (Err) 2356 reportError(std::move(Err), Filename); 2357 return; 2358 } 2359 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 2360 parseInputMachO(UB); 2361 return; 2362 } 2363 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2364 if (!checkMachOAndArchFlags(O, Filename)) 2365 return; 2366 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) 2367 ProcessMachO(Filename, MachOOF); 2368 else 2369 WithColor::error(errs(), "llvm-objdump") 2370 << Filename << "': " 2371 << "object is not a Mach-O file type.\n"; 2372 return; 2373 } 2374 llvm_unreachable("Input object can't be invalid at this point"); 2375 } 2376 2377 void objdump::parseInputMachO(MachOUniversalBinary *UB) { 2378 if (!ValidateArchFlags()) 2379 return; 2380 2381 auto Filename = UB->getFileName(); 2382 2383 if (UniversalHeaders) 2384 printMachOUniversalHeaders(UB, !NonVerbose); 2385 2386 // If we have a list of architecture flags specified dump only those. 2387 if (!ArchAll && !ArchFlags.empty()) { 2388 // Look for a slice in the universal binary that matches each ArchFlag. 2389 bool ArchFound; 2390 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2391 ArchFound = false; 2392 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2393 E = UB->end_objects(); 2394 I != E; ++I) { 2395 if (ArchFlags[i] == I->getArchFlagName()) { 2396 ArchFound = true; 2397 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2398 I->getAsObjectFile(); 2399 std::string ArchitectureName = ""; 2400 if (ArchFlags.size() > 1) 2401 ArchitectureName = I->getArchFlagName(); 2402 if (ObjOrErr) { 2403 ObjectFile &O = *ObjOrErr.get(); 2404 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2405 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2406 } else if (Error E = isNotObjectErrorInvalidFileType( 2407 ObjOrErr.takeError())) { 2408 reportError(std::move(E), "", Filename, ArchitectureName); 2409 continue; 2410 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2411 I->getAsArchive()) { 2412 std::unique_ptr<Archive> &A = *AOrErr; 2413 outs() << "Archive : " << Filename; 2414 if (!ArchitectureName.empty()) 2415 outs() << " (architecture " << ArchitectureName << ")"; 2416 outs() << "\n"; 2417 if (ArchiveHeaders) 2418 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2419 ArchiveMemberOffsets, ArchitectureName); 2420 Error Err = Error::success(); 2421 unsigned I = -1; 2422 for (auto &C : A->children(Err)) { 2423 ++I; 2424 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2425 if (!ChildOrErr) { 2426 if (Error E = 2427 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2428 reportError(std::move(E), getFileNameForError(C, I), Filename, 2429 ArchitectureName); 2430 continue; 2431 } 2432 if (MachOObjectFile *O = 2433 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2434 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2435 } 2436 if (Err) 2437 reportError(std::move(Err), Filename); 2438 } else { 2439 consumeError(AOrErr.takeError()); 2440 reportError(Filename, 2441 "Mach-O universal file for architecture " + 2442 StringRef(I->getArchFlagName()) + 2443 " is not a Mach-O file or an archive file"); 2444 } 2445 } 2446 } 2447 if (!ArchFound) { 2448 WithColor::error(errs(), "llvm-objdump") 2449 << "file: " + Filename + " does not contain " 2450 << "architecture: " + ArchFlags[i] + "\n"; 2451 return; 2452 } 2453 } 2454 return; 2455 } 2456 // No architecture flags were specified so if this contains a slice that 2457 // matches the host architecture dump only that. 2458 if (!ArchAll) { 2459 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2460 E = UB->end_objects(); 2461 I != E; ++I) { 2462 if (MachOObjectFile::getHostArch().getArchName() == 2463 I->getArchFlagName()) { 2464 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2465 std::string ArchiveName; 2466 ArchiveName.clear(); 2467 if (ObjOrErr) { 2468 ObjectFile &O = *ObjOrErr.get(); 2469 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2470 ProcessMachO(Filename, MachOOF); 2471 } else if (Error E = 2472 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2473 reportError(std::move(E), Filename); 2474 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2475 I->getAsArchive()) { 2476 std::unique_ptr<Archive> &A = *AOrErr; 2477 outs() << "Archive : " << Filename << "\n"; 2478 if (ArchiveHeaders) 2479 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2480 ArchiveMemberOffsets); 2481 Error Err = Error::success(); 2482 unsigned I = -1; 2483 for (auto &C : A->children(Err)) { 2484 ++I; 2485 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2486 if (!ChildOrErr) { 2487 if (Error E = 2488 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2489 reportError(std::move(E), getFileNameForError(C, I), Filename); 2490 continue; 2491 } 2492 if (MachOObjectFile *O = 2493 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2494 ProcessMachO(Filename, O, O->getFileName()); 2495 } 2496 if (Err) 2497 reportError(std::move(Err), Filename); 2498 } else { 2499 consumeError(AOrErr.takeError()); 2500 reportError(Filename, "Mach-O universal file for architecture " + 2501 StringRef(I->getArchFlagName()) + 2502 " is not a Mach-O file or an archive file"); 2503 } 2504 return; 2505 } 2506 } 2507 } 2508 // Either all architectures have been specified or none have been specified 2509 // and this does not contain the host architecture so dump all the slices. 2510 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2511 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2512 E = UB->end_objects(); 2513 I != E; ++I) { 2514 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2515 std::string ArchitectureName = ""; 2516 if (moreThanOneArch) 2517 ArchitectureName = I->getArchFlagName(); 2518 if (ObjOrErr) { 2519 ObjectFile &Obj = *ObjOrErr.get(); 2520 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2521 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2522 } else if (Error E = 2523 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2524 reportError(std::move(E), Filename, "", ArchitectureName); 2525 } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { 2526 std::unique_ptr<Archive> &A = *AOrErr; 2527 outs() << "Archive : " << Filename; 2528 if (!ArchitectureName.empty()) 2529 outs() << " (architecture " << ArchitectureName << ")"; 2530 outs() << "\n"; 2531 if (ArchiveHeaders) 2532 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2533 ArchiveMemberOffsets, ArchitectureName); 2534 Error Err = Error::success(); 2535 unsigned I = -1; 2536 for (auto &C : A->children(Err)) { 2537 ++I; 2538 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2539 if (!ChildOrErr) { 2540 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2541 reportError(std::move(E), getFileNameForError(C, I), Filename, 2542 ArchitectureName); 2543 continue; 2544 } 2545 if (MachOObjectFile *O = 2546 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2547 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2548 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2549 ArchitectureName); 2550 } 2551 } 2552 if (Err) 2553 reportError(std::move(Err), Filename); 2554 } else { 2555 consumeError(AOrErr.takeError()); 2556 reportError(Filename, "Mach-O universal file for architecture " + 2557 StringRef(I->getArchFlagName()) + 2558 " is not a Mach-O file or an archive file"); 2559 } 2560 } 2561 } 2562 2563 namespace { 2564 // The block of info used by the Symbolizer call backs. 2565 struct DisassembleInfo { 2566 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, 2567 std::vector<SectionRef> *Sections, bool verbose) 2568 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {} 2569 bool verbose; 2570 MachOObjectFile *O; 2571 SectionRef S; 2572 SymbolAddressMap *AddrMap; 2573 std::vector<SectionRef> *Sections; 2574 const char *class_name = nullptr; 2575 const char *selector_name = nullptr; 2576 std::unique_ptr<char[]> method = nullptr; 2577 char *demangled_name = nullptr; 2578 uint64_t adrp_addr = 0; 2579 uint32_t adrp_inst = 0; 2580 std::unique_ptr<SymbolAddressMap> bindtable; 2581 uint32_t depth = 0; 2582 }; 2583 } // namespace 2584 2585 // SymbolizerGetOpInfo() is the operand information call back function. 2586 // This is called to get the symbolic information for operand(s) of an 2587 // instruction when it is being done. This routine does this from 2588 // the relocation information, symbol table, etc. That block of information 2589 // is a pointer to the struct DisassembleInfo that was passed when the 2590 // disassembler context was created and passed to back to here when 2591 // called back by the disassembler for instruction operands that could have 2592 // relocation information. The address of the instruction containing operand is 2593 // at the Pc parameter. The immediate value the operand has is passed in 2594 // op_info->Value and is at Offset past the start of the instruction and has a 2595 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2596 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2597 // names and addends of the symbolic expression to add for the operand. The 2598 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2599 // information is returned then this function returns 1 else it returns 0. 2600 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2601 uint64_t Size, int TagType, void *TagBuf) { 2602 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2603 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2604 uint64_t value = op_info->Value; 2605 2606 // Make sure all fields returned are zero if we don't set them. 2607 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2608 op_info->Value = value; 2609 2610 // If the TagType is not the value 1 which it code knows about or if no 2611 // verbose symbolic information is wanted then just return 0, indicating no 2612 // information is being returned. 2613 if (TagType != 1 || !info->verbose) 2614 return 0; 2615 2616 unsigned int Arch = info->O->getArch(); 2617 if (Arch == Triple::x86) { 2618 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2619 return 0; 2620 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2621 // TODO: 2622 // Search the external relocation entries of a fully linked image 2623 // (if any) for an entry that matches this segment offset. 2624 // uint32_t seg_offset = (Pc + Offset); 2625 return 0; 2626 } 2627 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2628 // for an entry for this section offset. 2629 uint32_t sect_addr = info->S.getAddress(); 2630 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2631 bool reloc_found = false; 2632 DataRefImpl Rel; 2633 MachO::any_relocation_info RE; 2634 bool isExtern = false; 2635 SymbolRef Symbol; 2636 bool r_scattered = false; 2637 uint32_t r_value, pair_r_value, r_type; 2638 for (const RelocationRef &Reloc : info->S.relocations()) { 2639 uint64_t RelocOffset = Reloc.getOffset(); 2640 if (RelocOffset == sect_offset) { 2641 Rel = Reloc.getRawDataRefImpl(); 2642 RE = info->O->getRelocation(Rel); 2643 r_type = info->O->getAnyRelocationType(RE); 2644 r_scattered = info->O->isRelocationScattered(RE); 2645 if (r_scattered) { 2646 r_value = info->O->getScatteredRelocationValue(RE); 2647 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2648 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2649 DataRefImpl RelNext = Rel; 2650 info->O->moveRelocationNext(RelNext); 2651 MachO::any_relocation_info RENext; 2652 RENext = info->O->getRelocation(RelNext); 2653 if (info->O->isRelocationScattered(RENext)) 2654 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2655 else 2656 return 0; 2657 } 2658 } else { 2659 isExtern = info->O->getPlainRelocationExternal(RE); 2660 if (isExtern) { 2661 symbol_iterator RelocSym = Reloc.getSymbol(); 2662 Symbol = *RelocSym; 2663 } 2664 } 2665 reloc_found = true; 2666 break; 2667 } 2668 } 2669 if (reloc_found && isExtern) { 2670 op_info->AddSymbol.Present = 1; 2671 op_info->AddSymbol.Name = 2672 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2673 // For i386 extern relocation entries the value in the instruction is 2674 // the offset from the symbol, and value is already set in op_info->Value. 2675 return 1; 2676 } 2677 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2678 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2679 const char *add = GuessSymbolName(r_value, info->AddrMap); 2680 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2681 uint32_t offset = value - (r_value - pair_r_value); 2682 op_info->AddSymbol.Present = 1; 2683 if (add != nullptr) 2684 op_info->AddSymbol.Name = add; 2685 else 2686 op_info->AddSymbol.Value = r_value; 2687 op_info->SubtractSymbol.Present = 1; 2688 if (sub != nullptr) 2689 op_info->SubtractSymbol.Name = sub; 2690 else 2691 op_info->SubtractSymbol.Value = pair_r_value; 2692 op_info->Value = offset; 2693 return 1; 2694 } 2695 return 0; 2696 } 2697 if (Arch == Triple::x86_64) { 2698 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2699 return 0; 2700 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2701 // relocation entries of a linked image (if any) for an entry that matches 2702 // this segment offset. 2703 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2704 uint64_t seg_offset = Pc + Offset; 2705 bool reloc_found = false; 2706 DataRefImpl Rel; 2707 MachO::any_relocation_info RE; 2708 bool isExtern = false; 2709 SymbolRef Symbol; 2710 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2711 uint64_t RelocOffset = Reloc.getOffset(); 2712 if (RelocOffset == seg_offset) { 2713 Rel = Reloc.getRawDataRefImpl(); 2714 RE = info->O->getRelocation(Rel); 2715 // external relocation entries should always be external. 2716 isExtern = info->O->getPlainRelocationExternal(RE); 2717 if (isExtern) { 2718 symbol_iterator RelocSym = Reloc.getSymbol(); 2719 Symbol = *RelocSym; 2720 } 2721 reloc_found = true; 2722 break; 2723 } 2724 } 2725 if (reloc_found && isExtern) { 2726 // The Value passed in will be adjusted by the Pc if the instruction 2727 // adds the Pc. But for x86_64 external relocation entries the Value 2728 // is the offset from the external symbol. 2729 if (info->O->getAnyRelocationPCRel(RE)) 2730 op_info->Value -= Pc + Offset + Size; 2731 const char *name = 2732 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2733 op_info->AddSymbol.Present = 1; 2734 op_info->AddSymbol.Name = name; 2735 return 1; 2736 } 2737 return 0; 2738 } 2739 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2740 // for an entry for this section offset. 2741 uint64_t sect_addr = info->S.getAddress(); 2742 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2743 bool reloc_found = false; 2744 DataRefImpl Rel; 2745 MachO::any_relocation_info RE; 2746 bool isExtern = false; 2747 SymbolRef Symbol; 2748 for (const RelocationRef &Reloc : info->S.relocations()) { 2749 uint64_t RelocOffset = Reloc.getOffset(); 2750 if (RelocOffset == sect_offset) { 2751 Rel = Reloc.getRawDataRefImpl(); 2752 RE = info->O->getRelocation(Rel); 2753 // NOTE: Scattered relocations don't exist on x86_64. 2754 isExtern = info->O->getPlainRelocationExternal(RE); 2755 if (isExtern) { 2756 symbol_iterator RelocSym = Reloc.getSymbol(); 2757 Symbol = *RelocSym; 2758 } 2759 reloc_found = true; 2760 break; 2761 } 2762 } 2763 if (reloc_found && isExtern) { 2764 // The Value passed in will be adjusted by the Pc if the instruction 2765 // adds the Pc. But for x86_64 external relocation entries the Value 2766 // is the offset from the external symbol. 2767 if (info->O->getAnyRelocationPCRel(RE)) 2768 op_info->Value -= Pc + Offset + Size; 2769 const char *name = 2770 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2771 unsigned Type = info->O->getAnyRelocationType(RE); 2772 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2773 DataRefImpl RelNext = Rel; 2774 info->O->moveRelocationNext(RelNext); 2775 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2776 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2777 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2778 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2779 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2780 op_info->SubtractSymbol.Present = 1; 2781 op_info->SubtractSymbol.Name = name; 2782 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2783 Symbol = *RelocSymNext; 2784 name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2785 } 2786 } 2787 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 2788 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 2789 op_info->AddSymbol.Present = 1; 2790 op_info->AddSymbol.Name = name; 2791 return 1; 2792 } 2793 return 0; 2794 } 2795 if (Arch == Triple::arm) { 2796 if (Offset != 0 || (Size != 4 && Size != 2)) 2797 return 0; 2798 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2799 // TODO: 2800 // Search the external relocation entries of a fully linked image 2801 // (if any) for an entry that matches this segment offset. 2802 // uint32_t seg_offset = (Pc + Offset); 2803 return 0; 2804 } 2805 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2806 // for an entry for this section offset. 2807 uint32_t sect_addr = info->S.getAddress(); 2808 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2809 DataRefImpl Rel; 2810 MachO::any_relocation_info RE; 2811 bool isExtern = false; 2812 SymbolRef Symbol; 2813 bool r_scattered = false; 2814 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 2815 auto Reloc = 2816 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2817 uint64_t RelocOffset = Reloc.getOffset(); 2818 return RelocOffset == sect_offset; 2819 }); 2820 2821 if (Reloc == info->S.relocations().end()) 2822 return 0; 2823 2824 Rel = Reloc->getRawDataRefImpl(); 2825 RE = info->O->getRelocation(Rel); 2826 r_length = info->O->getAnyRelocationLength(RE); 2827 r_scattered = info->O->isRelocationScattered(RE); 2828 if (r_scattered) { 2829 r_value = info->O->getScatteredRelocationValue(RE); 2830 r_type = info->O->getScatteredRelocationType(RE); 2831 } else { 2832 r_type = info->O->getAnyRelocationType(RE); 2833 isExtern = info->O->getPlainRelocationExternal(RE); 2834 if (isExtern) { 2835 symbol_iterator RelocSym = Reloc->getSymbol(); 2836 Symbol = *RelocSym; 2837 } 2838 } 2839 if (r_type == MachO::ARM_RELOC_HALF || 2840 r_type == MachO::ARM_RELOC_SECTDIFF || 2841 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 2842 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2843 DataRefImpl RelNext = Rel; 2844 info->O->moveRelocationNext(RelNext); 2845 MachO::any_relocation_info RENext; 2846 RENext = info->O->getRelocation(RelNext); 2847 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 2848 if (info->O->isRelocationScattered(RENext)) 2849 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2850 } 2851 2852 if (isExtern) { 2853 const char *name = 2854 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2855 op_info->AddSymbol.Present = 1; 2856 op_info->AddSymbol.Name = name; 2857 switch (r_type) { 2858 case MachO::ARM_RELOC_HALF: 2859 if ((r_length & 0x1) == 1) { 2860 op_info->Value = value << 16 | other_half; 2861 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2862 } else { 2863 op_info->Value = other_half << 16 | value; 2864 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2865 } 2866 break; 2867 default: 2868 break; 2869 } 2870 return 1; 2871 } 2872 // If we have a branch that is not an external relocation entry then 2873 // return 0 so the code in tryAddingSymbolicOperand() can use the 2874 // SymbolLookUp call back with the branch target address to look up the 2875 // symbol and possibility add an annotation for a symbol stub. 2876 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 2877 r_type == MachO::ARM_THUMB_RELOC_BR22)) 2878 return 0; 2879 2880 uint32_t offset = 0; 2881 if (r_type == MachO::ARM_RELOC_HALF || 2882 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2883 if ((r_length & 0x1) == 1) 2884 value = value << 16 | other_half; 2885 else 2886 value = other_half << 16 | value; 2887 } 2888 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 2889 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 2890 offset = value - r_value; 2891 value = r_value; 2892 } 2893 2894 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2895 if ((r_length & 0x1) == 1) 2896 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2897 else 2898 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2899 const char *add = GuessSymbolName(r_value, info->AddrMap); 2900 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2901 int32_t offset = value - (r_value - pair_r_value); 2902 op_info->AddSymbol.Present = 1; 2903 if (add != nullptr) 2904 op_info->AddSymbol.Name = add; 2905 else 2906 op_info->AddSymbol.Value = r_value; 2907 op_info->SubtractSymbol.Present = 1; 2908 if (sub != nullptr) 2909 op_info->SubtractSymbol.Name = sub; 2910 else 2911 op_info->SubtractSymbol.Value = pair_r_value; 2912 op_info->Value = offset; 2913 return 1; 2914 } 2915 2916 op_info->AddSymbol.Present = 1; 2917 op_info->Value = offset; 2918 if (r_type == MachO::ARM_RELOC_HALF) { 2919 if ((r_length & 0x1) == 1) 2920 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2921 else 2922 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2923 } 2924 const char *add = GuessSymbolName(value, info->AddrMap); 2925 if (add != nullptr) { 2926 op_info->AddSymbol.Name = add; 2927 return 1; 2928 } 2929 op_info->AddSymbol.Value = value; 2930 return 1; 2931 } 2932 if (Arch == Triple::aarch64) { 2933 if (Offset != 0 || Size != 4) 2934 return 0; 2935 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2936 // TODO: 2937 // Search the external relocation entries of a fully linked image 2938 // (if any) for an entry that matches this segment offset. 2939 // uint64_t seg_offset = (Pc + Offset); 2940 return 0; 2941 } 2942 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2943 // for an entry for this section offset. 2944 uint64_t sect_addr = info->S.getAddress(); 2945 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2946 auto Reloc = 2947 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2948 uint64_t RelocOffset = Reloc.getOffset(); 2949 return RelocOffset == sect_offset; 2950 }); 2951 2952 if (Reloc == info->S.relocations().end()) 2953 return 0; 2954 2955 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2956 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 2957 uint32_t r_type = info->O->getAnyRelocationType(RE); 2958 if (r_type == MachO::ARM64_RELOC_ADDEND) { 2959 DataRefImpl RelNext = Rel; 2960 info->O->moveRelocationNext(RelNext); 2961 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2962 if (value == 0) { 2963 value = info->O->getPlainRelocationSymbolNum(RENext); 2964 op_info->Value = value; 2965 } 2966 } 2967 // NOTE: Scattered relocations don't exist on arm64. 2968 if (!info->O->getPlainRelocationExternal(RE)) 2969 return 0; 2970 const char *name = 2971 unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName()) 2972 .data(); 2973 op_info->AddSymbol.Present = 1; 2974 op_info->AddSymbol.Name = name; 2975 2976 switch (r_type) { 2977 case MachO::ARM64_RELOC_PAGE21: 2978 /* @page */ 2979 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 2980 break; 2981 case MachO::ARM64_RELOC_PAGEOFF12: 2982 /* @pageoff */ 2983 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 2984 break; 2985 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 2986 /* @gotpage */ 2987 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 2988 break; 2989 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 2990 /* @gotpageoff */ 2991 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 2992 break; 2993 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 2994 /* @tvlppage is not implemented in llvm-mc */ 2995 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 2996 break; 2997 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 2998 /* @tvlppageoff is not implemented in llvm-mc */ 2999 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 3000 break; 3001 default: 3002 case MachO::ARM64_RELOC_BRANCH26: 3003 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 3004 break; 3005 } 3006 return 1; 3007 } 3008 return 0; 3009 } 3010 3011 // GuessCstringPointer is passed the address of what might be a pointer to a 3012 // literal string in a cstring section. If that address is in a cstring section 3013 // it returns a pointer to that string. Else it returns nullptr. 3014 static const char *GuessCstringPointer(uint64_t ReferenceValue, 3015 struct DisassembleInfo *info) { 3016 for (const auto &Load : info->O->load_commands()) { 3017 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3018 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3019 for (unsigned J = 0; J < Seg.nsects; ++J) { 3020 MachO::section_64 Sec = info->O->getSection64(Load, J); 3021 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3022 if (section_type == MachO::S_CSTRING_LITERALS && 3023 ReferenceValue >= Sec.addr && 3024 ReferenceValue < Sec.addr + Sec.size) { 3025 uint64_t sect_offset = ReferenceValue - Sec.addr; 3026 uint64_t object_offset = Sec.offset + sect_offset; 3027 StringRef MachOContents = info->O->getData(); 3028 uint64_t object_size = MachOContents.size(); 3029 const char *object_addr = (const char *)MachOContents.data(); 3030 if (object_offset < object_size) { 3031 const char *name = object_addr + object_offset; 3032 return name; 3033 } else { 3034 return nullptr; 3035 } 3036 } 3037 } 3038 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3039 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3040 for (unsigned J = 0; J < Seg.nsects; ++J) { 3041 MachO::section Sec = info->O->getSection(Load, J); 3042 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3043 if (section_type == MachO::S_CSTRING_LITERALS && 3044 ReferenceValue >= Sec.addr && 3045 ReferenceValue < Sec.addr + Sec.size) { 3046 uint64_t sect_offset = ReferenceValue - Sec.addr; 3047 uint64_t object_offset = Sec.offset + sect_offset; 3048 StringRef MachOContents = info->O->getData(); 3049 uint64_t object_size = MachOContents.size(); 3050 const char *object_addr = (const char *)MachOContents.data(); 3051 if (object_offset < object_size) { 3052 const char *name = object_addr + object_offset; 3053 return name; 3054 } else { 3055 return nullptr; 3056 } 3057 } 3058 } 3059 } 3060 } 3061 return nullptr; 3062 } 3063 3064 // GuessIndirectSymbol returns the name of the indirect symbol for the 3065 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 3066 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 3067 // symbol name being referenced by the stub or pointer. 3068 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 3069 struct DisassembleInfo *info) { 3070 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 3071 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 3072 for (const auto &Load : info->O->load_commands()) { 3073 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3074 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3075 for (unsigned J = 0; J < Seg.nsects; ++J) { 3076 MachO::section_64 Sec = info->O->getSection64(Load, J); 3077 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3078 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3079 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3080 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3081 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3082 section_type == MachO::S_SYMBOL_STUBS) && 3083 ReferenceValue >= Sec.addr && 3084 ReferenceValue < Sec.addr + Sec.size) { 3085 uint32_t stride; 3086 if (section_type == MachO::S_SYMBOL_STUBS) 3087 stride = Sec.reserved2; 3088 else 3089 stride = 8; 3090 if (stride == 0) 3091 return nullptr; 3092 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3093 if (index < Dysymtab.nindirectsyms) { 3094 uint32_t indirect_symbol = 3095 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3096 if (indirect_symbol < Symtab.nsyms) { 3097 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3098 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3099 .data(); 3100 } 3101 } 3102 } 3103 } 3104 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3105 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3106 for (unsigned J = 0; J < Seg.nsects; ++J) { 3107 MachO::section Sec = info->O->getSection(Load, J); 3108 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3109 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3110 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3111 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3112 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3113 section_type == MachO::S_SYMBOL_STUBS) && 3114 ReferenceValue >= Sec.addr && 3115 ReferenceValue < Sec.addr + Sec.size) { 3116 uint32_t stride; 3117 if (section_type == MachO::S_SYMBOL_STUBS) 3118 stride = Sec.reserved2; 3119 else 3120 stride = 4; 3121 if (stride == 0) 3122 return nullptr; 3123 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3124 if (index < Dysymtab.nindirectsyms) { 3125 uint32_t indirect_symbol = 3126 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3127 if (indirect_symbol < Symtab.nsyms) { 3128 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3129 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3130 .data(); 3131 } 3132 } 3133 } 3134 } 3135 } 3136 } 3137 return nullptr; 3138 } 3139 3140 // method_reference() is called passing it the ReferenceName that might be 3141 // a reference it to an Objective-C method call. If so then it allocates and 3142 // assembles a method call string with the values last seen and saved in 3143 // the DisassembleInfo's class_name and selector_name fields. This is saved 3144 // into the method field of the info and any previous string is free'ed. 3145 // Then the class_name field in the info is set to nullptr. The method call 3146 // string is set into ReferenceName and ReferenceType is set to 3147 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 3148 // then both ReferenceType and ReferenceName are left unchanged. 3149 static void method_reference(struct DisassembleInfo *info, 3150 uint64_t *ReferenceType, 3151 const char **ReferenceName) { 3152 unsigned int Arch = info->O->getArch(); 3153 if (*ReferenceName != nullptr) { 3154 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 3155 if (info->selector_name != nullptr) { 3156 if (info->class_name != nullptr) { 3157 info->method = std::make_unique<char[]>( 3158 5 + strlen(info->class_name) + strlen(info->selector_name)); 3159 char *method = info->method.get(); 3160 if (method != nullptr) { 3161 strcpy(method, "+["); 3162 strcat(method, info->class_name); 3163 strcat(method, " "); 3164 strcat(method, info->selector_name); 3165 strcat(method, "]"); 3166 *ReferenceName = method; 3167 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3168 } 3169 } else { 3170 info->method = 3171 std::make_unique<char[]>(9 + strlen(info->selector_name)); 3172 char *method = info->method.get(); 3173 if (method != nullptr) { 3174 if (Arch == Triple::x86_64) 3175 strcpy(method, "-[%rdi "); 3176 else if (Arch == Triple::aarch64) 3177 strcpy(method, "-[x0 "); 3178 else 3179 strcpy(method, "-[r? "); 3180 strcat(method, info->selector_name); 3181 strcat(method, "]"); 3182 *ReferenceName = method; 3183 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3184 } 3185 } 3186 info->class_name = nullptr; 3187 } 3188 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 3189 if (info->selector_name != nullptr) { 3190 info->method = 3191 std::make_unique<char[]>(17 + strlen(info->selector_name)); 3192 char *method = info->method.get(); 3193 if (method != nullptr) { 3194 if (Arch == Triple::x86_64) 3195 strcpy(method, "-[[%rdi super] "); 3196 else if (Arch == Triple::aarch64) 3197 strcpy(method, "-[[x0 super] "); 3198 else 3199 strcpy(method, "-[[r? super] "); 3200 strcat(method, info->selector_name); 3201 strcat(method, "]"); 3202 *ReferenceName = method; 3203 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3204 } 3205 info->class_name = nullptr; 3206 } 3207 } 3208 } 3209 } 3210 3211 // GuessPointerPointer() is passed the address of what might be a pointer to 3212 // a reference to an Objective-C class, selector, message ref or cfstring. 3213 // If so the value of the pointer is returned and one of the booleans are set 3214 // to true. If not zero is returned and all the booleans are set to false. 3215 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 3216 struct DisassembleInfo *info, 3217 bool &classref, bool &selref, bool &msgref, 3218 bool &cfstring) { 3219 classref = false; 3220 selref = false; 3221 msgref = false; 3222 cfstring = false; 3223 for (const auto &Load : info->O->load_commands()) { 3224 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3225 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3226 for (unsigned J = 0; J < Seg.nsects; ++J) { 3227 MachO::section_64 Sec = info->O->getSection64(Load, J); 3228 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 3229 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3230 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 3231 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 3232 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 3233 ReferenceValue >= Sec.addr && 3234 ReferenceValue < Sec.addr + Sec.size) { 3235 uint64_t sect_offset = ReferenceValue - Sec.addr; 3236 uint64_t object_offset = Sec.offset + sect_offset; 3237 StringRef MachOContents = info->O->getData(); 3238 uint64_t object_size = MachOContents.size(); 3239 const char *object_addr = (const char *)MachOContents.data(); 3240 if (object_offset < object_size) { 3241 uint64_t pointer_value; 3242 memcpy(&pointer_value, object_addr + object_offset, 3243 sizeof(uint64_t)); 3244 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3245 sys::swapByteOrder(pointer_value); 3246 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 3247 selref = true; 3248 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3249 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 3250 classref = true; 3251 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 3252 ReferenceValue + 8 < Sec.addr + Sec.size) { 3253 msgref = true; 3254 memcpy(&pointer_value, object_addr + object_offset + 8, 3255 sizeof(uint64_t)); 3256 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3257 sys::swapByteOrder(pointer_value); 3258 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 3259 cfstring = true; 3260 return pointer_value; 3261 } else { 3262 return 0; 3263 } 3264 } 3265 } 3266 } 3267 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 3268 } 3269 return 0; 3270 } 3271 3272 // get_pointer_64 returns a pointer to the bytes in the object file at the 3273 // Address from a section in the Mach-O file. And indirectly returns the 3274 // offset into the section, number of bytes left in the section past the offset 3275 // and which section is was being referenced. If the Address is not in a 3276 // section nullptr is returned. 3277 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 3278 uint32_t &left, SectionRef &S, 3279 DisassembleInfo *info, 3280 bool objc_only = false) { 3281 offset = 0; 3282 left = 0; 3283 S = SectionRef(); 3284 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 3285 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 3286 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 3287 if (SectSize == 0) 3288 continue; 3289 if (objc_only) { 3290 StringRef SectName; 3291 Expected<StringRef> SecNameOrErr = 3292 ((*(info->Sections))[SectIdx]).getName(); 3293 if (SecNameOrErr) 3294 SectName = *SecNameOrErr; 3295 else 3296 consumeError(SecNameOrErr.takeError()); 3297 3298 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 3299 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 3300 if (SegName != "__OBJC" && SectName != "__cstring") 3301 continue; 3302 } 3303 if (Address >= SectAddress && Address < SectAddress + SectSize) { 3304 S = (*(info->Sections))[SectIdx]; 3305 offset = Address - SectAddress; 3306 left = SectSize - offset; 3307 StringRef SectContents = unwrapOrError( 3308 ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName()); 3309 return SectContents.data() + offset; 3310 } 3311 } 3312 return nullptr; 3313 } 3314 3315 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 3316 uint32_t &left, SectionRef &S, 3317 DisassembleInfo *info, 3318 bool objc_only = false) { 3319 return get_pointer_64(Address, offset, left, S, info, objc_only); 3320 } 3321 3322 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 3323 // the symbol indirectly through n_value. Based on the relocation information 3324 // for the specified section offset in the specified section reference. 3325 // If no relocation information is found and a non-zero ReferenceValue for the 3326 // symbol is passed, look up that address in the info's AddrMap. 3327 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 3328 DisassembleInfo *info, uint64_t &n_value, 3329 uint64_t ReferenceValue = 0) { 3330 n_value = 0; 3331 if (!info->verbose) 3332 return nullptr; 3333 3334 // See if there is an external relocation entry at the sect_offset. 3335 bool reloc_found = false; 3336 DataRefImpl Rel; 3337 MachO::any_relocation_info RE; 3338 bool isExtern = false; 3339 SymbolRef Symbol; 3340 for (const RelocationRef &Reloc : S.relocations()) { 3341 uint64_t RelocOffset = Reloc.getOffset(); 3342 if (RelocOffset == sect_offset) { 3343 Rel = Reloc.getRawDataRefImpl(); 3344 RE = info->O->getRelocation(Rel); 3345 if (info->O->isRelocationScattered(RE)) 3346 continue; 3347 isExtern = info->O->getPlainRelocationExternal(RE); 3348 if (isExtern) { 3349 symbol_iterator RelocSym = Reloc.getSymbol(); 3350 Symbol = *RelocSym; 3351 } 3352 reloc_found = true; 3353 break; 3354 } 3355 } 3356 // If there is an external relocation entry for a symbol in this section 3357 // at this section_offset then use that symbol's value for the n_value 3358 // and return its name. 3359 const char *SymbolName = nullptr; 3360 if (reloc_found && isExtern) { 3361 n_value = cantFail(Symbol.getValue()); 3362 StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName()); 3363 if (!Name.empty()) { 3364 SymbolName = Name.data(); 3365 return SymbolName; 3366 } 3367 } 3368 3369 // TODO: For fully linked images, look through the external relocation 3370 // entries off the dynamic symtab command. For these the r_offset is from the 3371 // start of the first writeable segment in the Mach-O file. So the offset 3372 // to this section from that segment is passed to this routine by the caller, 3373 // as the database_offset. Which is the difference of the section's starting 3374 // address and the first writable segment. 3375 // 3376 // NOTE: need add passing the database_offset to this routine. 3377 3378 // We did not find an external relocation entry so look up the ReferenceValue 3379 // as an address of a symbol and if found return that symbol's name. 3380 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 3381 3382 return SymbolName; 3383 } 3384 3385 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 3386 DisassembleInfo *info, 3387 uint32_t ReferenceValue) { 3388 uint64_t n_value64; 3389 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 3390 } 3391 3392 namespace { 3393 3394 // These are structs in the Objective-C meta data and read to produce the 3395 // comments for disassembly. While these are part of the ABI they are no 3396 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 3397 // . 3398 3399 // The cfstring object in a 64-bit Mach-O file. 3400 struct cfstring64_t { 3401 uint64_t isa; // class64_t * (64-bit pointer) 3402 uint64_t flags; // flag bits 3403 uint64_t characters; // char * (64-bit pointer) 3404 uint64_t length; // number of non-NULL characters in above 3405 }; 3406 3407 // The class object in a 64-bit Mach-O file. 3408 struct class64_t { 3409 uint64_t isa; // class64_t * (64-bit pointer) 3410 uint64_t superclass; // class64_t * (64-bit pointer) 3411 uint64_t cache; // Cache (64-bit pointer) 3412 uint64_t vtable; // IMP * (64-bit pointer) 3413 uint64_t data; // class_ro64_t * (64-bit pointer) 3414 }; 3415 3416 struct class32_t { 3417 uint32_t isa; /* class32_t * (32-bit pointer) */ 3418 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3419 uint32_t cache; /* Cache (32-bit pointer) */ 3420 uint32_t vtable; /* IMP * (32-bit pointer) */ 3421 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3422 }; 3423 3424 struct class_ro64_t { 3425 uint32_t flags; 3426 uint32_t instanceStart; 3427 uint32_t instanceSize; 3428 uint32_t reserved; 3429 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3430 uint64_t name; // const char * (64-bit pointer) 3431 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3432 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3433 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3434 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3435 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3436 }; 3437 3438 struct class_ro32_t { 3439 uint32_t flags; 3440 uint32_t instanceStart; 3441 uint32_t instanceSize; 3442 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3443 uint32_t name; /* const char * (32-bit pointer) */ 3444 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3445 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3446 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3447 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3448 uint32_t baseProperties; /* const struct objc_property_list * 3449 (32-bit pointer) */ 3450 }; 3451 3452 /* Values for class_ro{64,32}_t->flags */ 3453 #define RO_META (1 << 0) 3454 #define RO_ROOT (1 << 1) 3455 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3456 3457 struct method_list64_t { 3458 uint32_t entsize; 3459 uint32_t count; 3460 /* struct method64_t first; These structures follow inline */ 3461 }; 3462 3463 struct method_list32_t { 3464 uint32_t entsize; 3465 uint32_t count; 3466 /* struct method32_t first; These structures follow inline */ 3467 }; 3468 3469 struct method64_t { 3470 uint64_t name; /* SEL (64-bit pointer) */ 3471 uint64_t types; /* const char * (64-bit pointer) */ 3472 uint64_t imp; /* IMP (64-bit pointer) */ 3473 }; 3474 3475 struct method32_t { 3476 uint32_t name; /* SEL (32-bit pointer) */ 3477 uint32_t types; /* const char * (32-bit pointer) */ 3478 uint32_t imp; /* IMP (32-bit pointer) */ 3479 }; 3480 3481 struct protocol_list64_t { 3482 uint64_t count; /* uintptr_t (a 64-bit value) */ 3483 /* struct protocol64_t * list[0]; These pointers follow inline */ 3484 }; 3485 3486 struct protocol_list32_t { 3487 uint32_t count; /* uintptr_t (a 32-bit value) */ 3488 /* struct protocol32_t * list[0]; These pointers follow inline */ 3489 }; 3490 3491 struct protocol64_t { 3492 uint64_t isa; /* id * (64-bit pointer) */ 3493 uint64_t name; /* const char * (64-bit pointer) */ 3494 uint64_t protocols; /* struct protocol_list64_t * 3495 (64-bit pointer) */ 3496 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3497 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3498 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3499 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3500 uint64_t instanceProperties; /* struct objc_property_list * 3501 (64-bit pointer) */ 3502 }; 3503 3504 struct protocol32_t { 3505 uint32_t isa; /* id * (32-bit pointer) */ 3506 uint32_t name; /* const char * (32-bit pointer) */ 3507 uint32_t protocols; /* struct protocol_list_t * 3508 (32-bit pointer) */ 3509 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3510 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3511 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3512 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3513 uint32_t instanceProperties; /* struct objc_property_list * 3514 (32-bit pointer) */ 3515 }; 3516 3517 struct ivar_list64_t { 3518 uint32_t entsize; 3519 uint32_t count; 3520 /* struct ivar64_t first; These structures follow inline */ 3521 }; 3522 3523 struct ivar_list32_t { 3524 uint32_t entsize; 3525 uint32_t count; 3526 /* struct ivar32_t first; These structures follow inline */ 3527 }; 3528 3529 struct ivar64_t { 3530 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3531 uint64_t name; /* const char * (64-bit pointer) */ 3532 uint64_t type; /* const char * (64-bit pointer) */ 3533 uint32_t alignment; 3534 uint32_t size; 3535 }; 3536 3537 struct ivar32_t { 3538 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3539 uint32_t name; /* const char * (32-bit pointer) */ 3540 uint32_t type; /* const char * (32-bit pointer) */ 3541 uint32_t alignment; 3542 uint32_t size; 3543 }; 3544 3545 struct objc_property_list64 { 3546 uint32_t entsize; 3547 uint32_t count; 3548 /* struct objc_property64 first; These structures follow inline */ 3549 }; 3550 3551 struct objc_property_list32 { 3552 uint32_t entsize; 3553 uint32_t count; 3554 /* struct objc_property32 first; These structures follow inline */ 3555 }; 3556 3557 struct objc_property64 { 3558 uint64_t name; /* const char * (64-bit pointer) */ 3559 uint64_t attributes; /* const char * (64-bit pointer) */ 3560 }; 3561 3562 struct objc_property32 { 3563 uint32_t name; /* const char * (32-bit pointer) */ 3564 uint32_t attributes; /* const char * (32-bit pointer) */ 3565 }; 3566 3567 struct category64_t { 3568 uint64_t name; /* const char * (64-bit pointer) */ 3569 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3570 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3571 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3572 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3573 uint64_t instanceProperties; /* struct objc_property_list * 3574 (64-bit pointer) */ 3575 }; 3576 3577 struct category32_t { 3578 uint32_t name; /* const char * (32-bit pointer) */ 3579 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3580 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3581 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3582 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3583 uint32_t instanceProperties; /* struct objc_property_list * 3584 (32-bit pointer) */ 3585 }; 3586 3587 struct objc_image_info64 { 3588 uint32_t version; 3589 uint32_t flags; 3590 }; 3591 struct objc_image_info32 { 3592 uint32_t version; 3593 uint32_t flags; 3594 }; 3595 struct imageInfo_t { 3596 uint32_t version; 3597 uint32_t flags; 3598 }; 3599 /* masks for objc_image_info.flags */ 3600 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3601 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3602 #define OBJC_IMAGE_IS_SIMULATED (1 << 5) 3603 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6) 3604 3605 struct message_ref64 { 3606 uint64_t imp; /* IMP (64-bit pointer) */ 3607 uint64_t sel; /* SEL (64-bit pointer) */ 3608 }; 3609 3610 struct message_ref32 { 3611 uint32_t imp; /* IMP (32-bit pointer) */ 3612 uint32_t sel; /* SEL (32-bit pointer) */ 3613 }; 3614 3615 // Objective-C 1 (32-bit only) meta data structs. 3616 3617 struct objc_module_t { 3618 uint32_t version; 3619 uint32_t size; 3620 uint32_t name; /* char * (32-bit pointer) */ 3621 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3622 }; 3623 3624 struct objc_symtab_t { 3625 uint32_t sel_ref_cnt; 3626 uint32_t refs; /* SEL * (32-bit pointer) */ 3627 uint16_t cls_def_cnt; 3628 uint16_t cat_def_cnt; 3629 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3630 }; 3631 3632 struct objc_class_t { 3633 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3634 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3635 uint32_t name; /* const char * (32-bit pointer) */ 3636 int32_t version; 3637 int32_t info; 3638 int32_t instance_size; 3639 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3640 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3641 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3642 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3643 }; 3644 3645 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3646 // class is not a metaclass 3647 #define CLS_CLASS 0x1 3648 // class is a metaclass 3649 #define CLS_META 0x2 3650 3651 struct objc_category_t { 3652 uint32_t category_name; /* char * (32-bit pointer) */ 3653 uint32_t class_name; /* char * (32-bit pointer) */ 3654 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3655 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3656 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3657 }; 3658 3659 struct objc_ivar_t { 3660 uint32_t ivar_name; /* char * (32-bit pointer) */ 3661 uint32_t ivar_type; /* char * (32-bit pointer) */ 3662 int32_t ivar_offset; 3663 }; 3664 3665 struct objc_ivar_list_t { 3666 int32_t ivar_count; 3667 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3668 }; 3669 3670 struct objc_method_list_t { 3671 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3672 int32_t method_count; 3673 // struct objc_method_t method_list[1]; /* variable length structure */ 3674 }; 3675 3676 struct objc_method_t { 3677 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3678 uint32_t method_types; /* char * (32-bit pointer) */ 3679 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3680 (32-bit pointer) */ 3681 }; 3682 3683 struct objc_protocol_list_t { 3684 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3685 int32_t count; 3686 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3687 // (32-bit pointer) */ 3688 }; 3689 3690 struct objc_protocol_t { 3691 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3692 uint32_t protocol_name; /* char * (32-bit pointer) */ 3693 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3694 uint32_t instance_methods; /* struct objc_method_description_list * 3695 (32-bit pointer) */ 3696 uint32_t class_methods; /* struct objc_method_description_list * 3697 (32-bit pointer) */ 3698 }; 3699 3700 struct objc_method_description_list_t { 3701 int32_t count; 3702 // struct objc_method_description_t list[1]; 3703 }; 3704 3705 struct objc_method_description_t { 3706 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3707 uint32_t types; /* char * (32-bit pointer) */ 3708 }; 3709 3710 inline void swapStruct(struct cfstring64_t &cfs) { 3711 sys::swapByteOrder(cfs.isa); 3712 sys::swapByteOrder(cfs.flags); 3713 sys::swapByteOrder(cfs.characters); 3714 sys::swapByteOrder(cfs.length); 3715 } 3716 3717 inline void swapStruct(struct class64_t &c) { 3718 sys::swapByteOrder(c.isa); 3719 sys::swapByteOrder(c.superclass); 3720 sys::swapByteOrder(c.cache); 3721 sys::swapByteOrder(c.vtable); 3722 sys::swapByteOrder(c.data); 3723 } 3724 3725 inline void swapStruct(struct class32_t &c) { 3726 sys::swapByteOrder(c.isa); 3727 sys::swapByteOrder(c.superclass); 3728 sys::swapByteOrder(c.cache); 3729 sys::swapByteOrder(c.vtable); 3730 sys::swapByteOrder(c.data); 3731 } 3732 3733 inline void swapStruct(struct class_ro64_t &cro) { 3734 sys::swapByteOrder(cro.flags); 3735 sys::swapByteOrder(cro.instanceStart); 3736 sys::swapByteOrder(cro.instanceSize); 3737 sys::swapByteOrder(cro.reserved); 3738 sys::swapByteOrder(cro.ivarLayout); 3739 sys::swapByteOrder(cro.name); 3740 sys::swapByteOrder(cro.baseMethods); 3741 sys::swapByteOrder(cro.baseProtocols); 3742 sys::swapByteOrder(cro.ivars); 3743 sys::swapByteOrder(cro.weakIvarLayout); 3744 sys::swapByteOrder(cro.baseProperties); 3745 } 3746 3747 inline void swapStruct(struct class_ro32_t &cro) { 3748 sys::swapByteOrder(cro.flags); 3749 sys::swapByteOrder(cro.instanceStart); 3750 sys::swapByteOrder(cro.instanceSize); 3751 sys::swapByteOrder(cro.ivarLayout); 3752 sys::swapByteOrder(cro.name); 3753 sys::swapByteOrder(cro.baseMethods); 3754 sys::swapByteOrder(cro.baseProtocols); 3755 sys::swapByteOrder(cro.ivars); 3756 sys::swapByteOrder(cro.weakIvarLayout); 3757 sys::swapByteOrder(cro.baseProperties); 3758 } 3759 3760 inline void swapStruct(struct method_list64_t &ml) { 3761 sys::swapByteOrder(ml.entsize); 3762 sys::swapByteOrder(ml.count); 3763 } 3764 3765 inline void swapStruct(struct method_list32_t &ml) { 3766 sys::swapByteOrder(ml.entsize); 3767 sys::swapByteOrder(ml.count); 3768 } 3769 3770 inline void swapStruct(struct method64_t &m) { 3771 sys::swapByteOrder(m.name); 3772 sys::swapByteOrder(m.types); 3773 sys::swapByteOrder(m.imp); 3774 } 3775 3776 inline void swapStruct(struct method32_t &m) { 3777 sys::swapByteOrder(m.name); 3778 sys::swapByteOrder(m.types); 3779 sys::swapByteOrder(m.imp); 3780 } 3781 3782 inline void swapStruct(struct protocol_list64_t &pl) { 3783 sys::swapByteOrder(pl.count); 3784 } 3785 3786 inline void swapStruct(struct protocol_list32_t &pl) { 3787 sys::swapByteOrder(pl.count); 3788 } 3789 3790 inline void swapStruct(struct protocol64_t &p) { 3791 sys::swapByteOrder(p.isa); 3792 sys::swapByteOrder(p.name); 3793 sys::swapByteOrder(p.protocols); 3794 sys::swapByteOrder(p.instanceMethods); 3795 sys::swapByteOrder(p.classMethods); 3796 sys::swapByteOrder(p.optionalInstanceMethods); 3797 sys::swapByteOrder(p.optionalClassMethods); 3798 sys::swapByteOrder(p.instanceProperties); 3799 } 3800 3801 inline void swapStruct(struct protocol32_t &p) { 3802 sys::swapByteOrder(p.isa); 3803 sys::swapByteOrder(p.name); 3804 sys::swapByteOrder(p.protocols); 3805 sys::swapByteOrder(p.instanceMethods); 3806 sys::swapByteOrder(p.classMethods); 3807 sys::swapByteOrder(p.optionalInstanceMethods); 3808 sys::swapByteOrder(p.optionalClassMethods); 3809 sys::swapByteOrder(p.instanceProperties); 3810 } 3811 3812 inline void swapStruct(struct ivar_list64_t &il) { 3813 sys::swapByteOrder(il.entsize); 3814 sys::swapByteOrder(il.count); 3815 } 3816 3817 inline void swapStruct(struct ivar_list32_t &il) { 3818 sys::swapByteOrder(il.entsize); 3819 sys::swapByteOrder(il.count); 3820 } 3821 3822 inline void swapStruct(struct ivar64_t &i) { 3823 sys::swapByteOrder(i.offset); 3824 sys::swapByteOrder(i.name); 3825 sys::swapByteOrder(i.type); 3826 sys::swapByteOrder(i.alignment); 3827 sys::swapByteOrder(i.size); 3828 } 3829 3830 inline void swapStruct(struct ivar32_t &i) { 3831 sys::swapByteOrder(i.offset); 3832 sys::swapByteOrder(i.name); 3833 sys::swapByteOrder(i.type); 3834 sys::swapByteOrder(i.alignment); 3835 sys::swapByteOrder(i.size); 3836 } 3837 3838 inline void swapStruct(struct objc_property_list64 &pl) { 3839 sys::swapByteOrder(pl.entsize); 3840 sys::swapByteOrder(pl.count); 3841 } 3842 3843 inline void swapStruct(struct objc_property_list32 &pl) { 3844 sys::swapByteOrder(pl.entsize); 3845 sys::swapByteOrder(pl.count); 3846 } 3847 3848 inline void swapStruct(struct objc_property64 &op) { 3849 sys::swapByteOrder(op.name); 3850 sys::swapByteOrder(op.attributes); 3851 } 3852 3853 inline void swapStruct(struct objc_property32 &op) { 3854 sys::swapByteOrder(op.name); 3855 sys::swapByteOrder(op.attributes); 3856 } 3857 3858 inline void swapStruct(struct category64_t &c) { 3859 sys::swapByteOrder(c.name); 3860 sys::swapByteOrder(c.cls); 3861 sys::swapByteOrder(c.instanceMethods); 3862 sys::swapByteOrder(c.classMethods); 3863 sys::swapByteOrder(c.protocols); 3864 sys::swapByteOrder(c.instanceProperties); 3865 } 3866 3867 inline void swapStruct(struct category32_t &c) { 3868 sys::swapByteOrder(c.name); 3869 sys::swapByteOrder(c.cls); 3870 sys::swapByteOrder(c.instanceMethods); 3871 sys::swapByteOrder(c.classMethods); 3872 sys::swapByteOrder(c.protocols); 3873 sys::swapByteOrder(c.instanceProperties); 3874 } 3875 3876 inline void swapStruct(struct objc_image_info64 &o) { 3877 sys::swapByteOrder(o.version); 3878 sys::swapByteOrder(o.flags); 3879 } 3880 3881 inline void swapStruct(struct objc_image_info32 &o) { 3882 sys::swapByteOrder(o.version); 3883 sys::swapByteOrder(o.flags); 3884 } 3885 3886 inline void swapStruct(struct imageInfo_t &o) { 3887 sys::swapByteOrder(o.version); 3888 sys::swapByteOrder(o.flags); 3889 } 3890 3891 inline void swapStruct(struct message_ref64 &mr) { 3892 sys::swapByteOrder(mr.imp); 3893 sys::swapByteOrder(mr.sel); 3894 } 3895 3896 inline void swapStruct(struct message_ref32 &mr) { 3897 sys::swapByteOrder(mr.imp); 3898 sys::swapByteOrder(mr.sel); 3899 } 3900 3901 inline void swapStruct(struct objc_module_t &module) { 3902 sys::swapByteOrder(module.version); 3903 sys::swapByteOrder(module.size); 3904 sys::swapByteOrder(module.name); 3905 sys::swapByteOrder(module.symtab); 3906 } 3907 3908 inline void swapStruct(struct objc_symtab_t &symtab) { 3909 sys::swapByteOrder(symtab.sel_ref_cnt); 3910 sys::swapByteOrder(symtab.refs); 3911 sys::swapByteOrder(symtab.cls_def_cnt); 3912 sys::swapByteOrder(symtab.cat_def_cnt); 3913 } 3914 3915 inline void swapStruct(struct objc_class_t &objc_class) { 3916 sys::swapByteOrder(objc_class.isa); 3917 sys::swapByteOrder(objc_class.super_class); 3918 sys::swapByteOrder(objc_class.name); 3919 sys::swapByteOrder(objc_class.version); 3920 sys::swapByteOrder(objc_class.info); 3921 sys::swapByteOrder(objc_class.instance_size); 3922 sys::swapByteOrder(objc_class.ivars); 3923 sys::swapByteOrder(objc_class.methodLists); 3924 sys::swapByteOrder(objc_class.cache); 3925 sys::swapByteOrder(objc_class.protocols); 3926 } 3927 3928 inline void swapStruct(struct objc_category_t &objc_category) { 3929 sys::swapByteOrder(objc_category.category_name); 3930 sys::swapByteOrder(objc_category.class_name); 3931 sys::swapByteOrder(objc_category.instance_methods); 3932 sys::swapByteOrder(objc_category.class_methods); 3933 sys::swapByteOrder(objc_category.protocols); 3934 } 3935 3936 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 3937 sys::swapByteOrder(objc_ivar_list.ivar_count); 3938 } 3939 3940 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 3941 sys::swapByteOrder(objc_ivar.ivar_name); 3942 sys::swapByteOrder(objc_ivar.ivar_type); 3943 sys::swapByteOrder(objc_ivar.ivar_offset); 3944 } 3945 3946 inline void swapStruct(struct objc_method_list_t &method_list) { 3947 sys::swapByteOrder(method_list.obsolete); 3948 sys::swapByteOrder(method_list.method_count); 3949 } 3950 3951 inline void swapStruct(struct objc_method_t &method) { 3952 sys::swapByteOrder(method.method_name); 3953 sys::swapByteOrder(method.method_types); 3954 sys::swapByteOrder(method.method_imp); 3955 } 3956 3957 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 3958 sys::swapByteOrder(protocol_list.next); 3959 sys::swapByteOrder(protocol_list.count); 3960 } 3961 3962 inline void swapStruct(struct objc_protocol_t &protocol) { 3963 sys::swapByteOrder(protocol.isa); 3964 sys::swapByteOrder(protocol.protocol_name); 3965 sys::swapByteOrder(protocol.protocol_list); 3966 sys::swapByteOrder(protocol.instance_methods); 3967 sys::swapByteOrder(protocol.class_methods); 3968 } 3969 3970 inline void swapStruct(struct objc_method_description_list_t &mdl) { 3971 sys::swapByteOrder(mdl.count); 3972 } 3973 3974 inline void swapStruct(struct objc_method_description_t &md) { 3975 sys::swapByteOrder(md.name); 3976 sys::swapByteOrder(md.types); 3977 } 3978 3979 } // namespace 3980 3981 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 3982 struct DisassembleInfo *info); 3983 3984 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 3985 // to an Objective-C class and returns the class name. It is also passed the 3986 // address of the pointer, so when the pointer is zero as it can be in an .o 3987 // file, that is used to look for an external relocation entry with a symbol 3988 // name. 3989 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 3990 uint64_t ReferenceValue, 3991 struct DisassembleInfo *info) { 3992 const char *r; 3993 uint32_t offset, left; 3994 SectionRef S; 3995 3996 // The pointer_value can be 0 in an object file and have a relocation 3997 // entry for the class symbol at the ReferenceValue (the address of the 3998 // pointer). 3999 if (pointer_value == 0) { 4000 r = get_pointer_64(ReferenceValue, offset, left, S, info); 4001 if (r == nullptr || left < sizeof(uint64_t)) 4002 return nullptr; 4003 uint64_t n_value; 4004 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 4005 if (symbol_name == nullptr) 4006 return nullptr; 4007 const char *class_name = strrchr(symbol_name, '$'); 4008 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 4009 return class_name + 2; 4010 else 4011 return nullptr; 4012 } 4013 4014 // The case were the pointer_value is non-zero and points to a class defined 4015 // in this Mach-O file. 4016 r = get_pointer_64(pointer_value, offset, left, S, info); 4017 if (r == nullptr || left < sizeof(struct class64_t)) 4018 return nullptr; 4019 struct class64_t c; 4020 memcpy(&c, r, sizeof(struct class64_t)); 4021 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4022 swapStruct(c); 4023 if (c.data == 0) 4024 return nullptr; 4025 r = get_pointer_64(c.data, offset, left, S, info); 4026 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4027 return nullptr; 4028 struct class_ro64_t cro; 4029 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4030 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4031 swapStruct(cro); 4032 if (cro.name == 0) 4033 return nullptr; 4034 const char *name = get_pointer_64(cro.name, offset, left, S, info); 4035 return name; 4036 } 4037 4038 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 4039 // pointer to a cfstring and returns its name or nullptr. 4040 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 4041 struct DisassembleInfo *info) { 4042 const char *r, *name; 4043 uint32_t offset, left; 4044 SectionRef S; 4045 struct cfstring64_t cfs; 4046 uint64_t cfs_characters; 4047 4048 r = get_pointer_64(ReferenceValue, offset, left, S, info); 4049 if (r == nullptr || left < sizeof(struct cfstring64_t)) 4050 return nullptr; 4051 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 4052 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4053 swapStruct(cfs); 4054 if (cfs.characters == 0) { 4055 uint64_t n_value; 4056 const char *symbol_name = get_symbol_64( 4057 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 4058 if (symbol_name == nullptr) 4059 return nullptr; 4060 cfs_characters = n_value; 4061 } else 4062 cfs_characters = cfs.characters; 4063 name = get_pointer_64(cfs_characters, offset, left, S, info); 4064 4065 return name; 4066 } 4067 4068 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 4069 // of a pointer to an Objective-C selector reference when the pointer value is 4070 // zero as in a .o file and is likely to have a external relocation entry with 4071 // who's symbol's n_value is the real pointer to the selector name. If that is 4072 // the case the real pointer to the selector name is returned else 0 is 4073 // returned 4074 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 4075 struct DisassembleInfo *info) { 4076 uint32_t offset, left; 4077 SectionRef S; 4078 4079 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 4080 if (r == nullptr || left < sizeof(uint64_t)) 4081 return 0; 4082 uint64_t n_value; 4083 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 4084 if (symbol_name == nullptr) 4085 return 0; 4086 return n_value; 4087 } 4088 4089 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 4090 const char *sectname) { 4091 for (const SectionRef &Section : O->sections()) { 4092 StringRef SectName; 4093 Expected<StringRef> SecNameOrErr = Section.getName(); 4094 if (SecNameOrErr) 4095 SectName = *SecNameOrErr; 4096 else 4097 consumeError(SecNameOrErr.takeError()); 4098 4099 DataRefImpl Ref = Section.getRawDataRefImpl(); 4100 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4101 if (SegName == segname && SectName == sectname) 4102 return Section; 4103 } 4104 return SectionRef(); 4105 } 4106 4107 static void 4108 walk_pointer_list_64(const char *listname, const SectionRef S, 4109 MachOObjectFile *O, struct DisassembleInfo *info, 4110 void (*func)(uint64_t, struct DisassembleInfo *info)) { 4111 if (S == SectionRef()) 4112 return; 4113 4114 StringRef SectName; 4115 Expected<StringRef> SecNameOrErr = S.getName(); 4116 if (SecNameOrErr) 4117 SectName = *SecNameOrErr; 4118 else 4119 consumeError(SecNameOrErr.takeError()); 4120 4121 DataRefImpl Ref = S.getRawDataRefImpl(); 4122 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4123 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4124 4125 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4126 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4127 4128 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 4129 uint32_t left = S.getSize() - i; 4130 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 4131 uint64_t p = 0; 4132 memcpy(&p, Contents + i, size); 4133 if (i + sizeof(uint64_t) > S.getSize()) 4134 outs() << listname << " list pointer extends past end of (" << SegName 4135 << "," << SectName << ") section\n"; 4136 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 4137 4138 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4139 sys::swapByteOrder(p); 4140 4141 uint64_t n_value = 0; 4142 const char *name = get_symbol_64(i, S, info, n_value, p); 4143 if (name == nullptr) 4144 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 4145 4146 if (n_value != 0) { 4147 outs() << format("0x%" PRIx64, n_value); 4148 if (p != 0) 4149 outs() << " + " << format("0x%" PRIx64, p); 4150 } else 4151 outs() << format("0x%" PRIx64, p); 4152 if (name != nullptr) 4153 outs() << " " << name; 4154 outs() << "\n"; 4155 4156 p += n_value; 4157 if (func) 4158 func(p, info); 4159 } 4160 } 4161 4162 static void 4163 walk_pointer_list_32(const char *listname, const SectionRef S, 4164 MachOObjectFile *O, struct DisassembleInfo *info, 4165 void (*func)(uint32_t, struct DisassembleInfo *info)) { 4166 if (S == SectionRef()) 4167 return; 4168 4169 StringRef SectName = unwrapOrError(S.getName(), O->getFileName()); 4170 DataRefImpl Ref = S.getRawDataRefImpl(); 4171 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4172 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4173 4174 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4175 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4176 4177 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 4178 uint32_t left = S.getSize() - i; 4179 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 4180 uint32_t p = 0; 4181 memcpy(&p, Contents + i, size); 4182 if (i + sizeof(uint32_t) > S.getSize()) 4183 outs() << listname << " list pointer extends past end of (" << SegName 4184 << "," << SectName << ") section\n"; 4185 uint32_t Address = S.getAddress() + i; 4186 outs() << format("%08" PRIx32, Address) << " "; 4187 4188 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4189 sys::swapByteOrder(p); 4190 outs() << format("0x%" PRIx32, p); 4191 4192 const char *name = get_symbol_32(i, S, info, p); 4193 if (name != nullptr) 4194 outs() << " " << name; 4195 outs() << "\n"; 4196 4197 if (func) 4198 func(p, info); 4199 } 4200 } 4201 4202 static void print_layout_map(const char *layout_map, uint32_t left) { 4203 if (layout_map == nullptr) 4204 return; 4205 outs() << " layout map: "; 4206 do { 4207 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 4208 left--; 4209 layout_map++; 4210 } while (*layout_map != '\0' && left != 0); 4211 outs() << "\n"; 4212 } 4213 4214 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 4215 uint32_t offset, left; 4216 SectionRef S; 4217 const char *layout_map; 4218 4219 if (p == 0) 4220 return; 4221 layout_map = get_pointer_64(p, offset, left, S, info); 4222 print_layout_map(layout_map, left); 4223 } 4224 4225 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 4226 uint32_t offset, left; 4227 SectionRef S; 4228 const char *layout_map; 4229 4230 if (p == 0) 4231 return; 4232 layout_map = get_pointer_32(p, offset, left, S, info); 4233 print_layout_map(layout_map, left); 4234 } 4235 4236 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 4237 const char *indent) { 4238 struct method_list64_t ml; 4239 struct method64_t m; 4240 const char *r; 4241 uint32_t offset, xoffset, left, i; 4242 SectionRef S, xS; 4243 const char *name, *sym_name; 4244 uint64_t n_value; 4245 4246 r = get_pointer_64(p, offset, left, S, info); 4247 if (r == nullptr) 4248 return; 4249 memset(&ml, '\0', sizeof(struct method_list64_t)); 4250 if (left < sizeof(struct method_list64_t)) { 4251 memcpy(&ml, r, left); 4252 outs() << " (method_list_t entends past the end of the section)\n"; 4253 } else 4254 memcpy(&ml, r, sizeof(struct method_list64_t)); 4255 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4256 swapStruct(ml); 4257 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4258 outs() << indent << "\t\t count " << ml.count << "\n"; 4259 4260 p += sizeof(struct method_list64_t); 4261 offset += sizeof(struct method_list64_t); 4262 for (i = 0; i < ml.count; i++) { 4263 r = get_pointer_64(p, offset, left, S, info); 4264 if (r == nullptr) 4265 return; 4266 memset(&m, '\0', sizeof(struct method64_t)); 4267 if (left < sizeof(struct method64_t)) { 4268 memcpy(&m, r, left); 4269 outs() << indent << " (method_t extends past the end of the section)\n"; 4270 } else 4271 memcpy(&m, r, sizeof(struct method64_t)); 4272 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4273 swapStruct(m); 4274 4275 outs() << indent << "\t\t name "; 4276 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 4277 info, n_value, m.name); 4278 if (n_value != 0) { 4279 if (info->verbose && sym_name != nullptr) 4280 outs() << sym_name; 4281 else 4282 outs() << format("0x%" PRIx64, n_value); 4283 if (m.name != 0) 4284 outs() << " + " << format("0x%" PRIx64, m.name); 4285 } else 4286 outs() << format("0x%" PRIx64, m.name); 4287 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 4288 if (name != nullptr) 4289 outs() << format(" %.*s", left, name); 4290 outs() << "\n"; 4291 4292 outs() << indent << "\t\t types "; 4293 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 4294 info, n_value, m.types); 4295 if (n_value != 0) { 4296 if (info->verbose && sym_name != nullptr) 4297 outs() << sym_name; 4298 else 4299 outs() << format("0x%" PRIx64, n_value); 4300 if (m.types != 0) 4301 outs() << " + " << format("0x%" PRIx64, m.types); 4302 } else 4303 outs() << format("0x%" PRIx64, m.types); 4304 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 4305 if (name != nullptr) 4306 outs() << format(" %.*s", left, name); 4307 outs() << "\n"; 4308 4309 outs() << indent << "\t\t imp "; 4310 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 4311 n_value, m.imp); 4312 if (info->verbose && name == nullptr) { 4313 if (n_value != 0) { 4314 outs() << format("0x%" PRIx64, n_value) << " "; 4315 if (m.imp != 0) 4316 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 4317 } else 4318 outs() << format("0x%" PRIx64, m.imp) << " "; 4319 } 4320 if (name != nullptr) 4321 outs() << name; 4322 outs() << "\n"; 4323 4324 p += sizeof(struct method64_t); 4325 offset += sizeof(struct method64_t); 4326 } 4327 } 4328 4329 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 4330 const char *indent) { 4331 struct method_list32_t ml; 4332 struct method32_t m; 4333 const char *r, *name; 4334 uint32_t offset, xoffset, left, i; 4335 SectionRef S, xS; 4336 4337 r = get_pointer_32(p, offset, left, S, info); 4338 if (r == nullptr) 4339 return; 4340 memset(&ml, '\0', sizeof(struct method_list32_t)); 4341 if (left < sizeof(struct method_list32_t)) { 4342 memcpy(&ml, r, left); 4343 outs() << " (method_list_t entends past the end of the section)\n"; 4344 } else 4345 memcpy(&ml, r, sizeof(struct method_list32_t)); 4346 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4347 swapStruct(ml); 4348 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4349 outs() << indent << "\t\t count " << ml.count << "\n"; 4350 4351 p += sizeof(struct method_list32_t); 4352 offset += sizeof(struct method_list32_t); 4353 for (i = 0; i < ml.count; i++) { 4354 r = get_pointer_32(p, offset, left, S, info); 4355 if (r == nullptr) 4356 return; 4357 memset(&m, '\0', sizeof(struct method32_t)); 4358 if (left < sizeof(struct method32_t)) { 4359 memcpy(&ml, r, left); 4360 outs() << indent << " (method_t entends past the end of the section)\n"; 4361 } else 4362 memcpy(&m, r, sizeof(struct method32_t)); 4363 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4364 swapStruct(m); 4365 4366 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 4367 name = get_pointer_32(m.name, xoffset, left, xS, info); 4368 if (name != nullptr) 4369 outs() << format(" %.*s", left, name); 4370 outs() << "\n"; 4371 4372 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 4373 name = get_pointer_32(m.types, xoffset, left, xS, info); 4374 if (name != nullptr) 4375 outs() << format(" %.*s", left, name); 4376 outs() << "\n"; 4377 4378 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4379 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 4380 m.imp); 4381 if (name != nullptr) 4382 outs() << " " << name; 4383 outs() << "\n"; 4384 4385 p += sizeof(struct method32_t); 4386 offset += sizeof(struct method32_t); 4387 } 4388 } 4389 4390 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 4391 uint32_t offset, left, xleft; 4392 SectionRef S; 4393 struct objc_method_list_t method_list; 4394 struct objc_method_t method; 4395 const char *r, *methods, *name, *SymbolName; 4396 int32_t i; 4397 4398 r = get_pointer_32(p, offset, left, S, info, true); 4399 if (r == nullptr) 4400 return true; 4401 4402 outs() << "\n"; 4403 if (left > sizeof(struct objc_method_list_t)) { 4404 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 4405 } else { 4406 outs() << "\t\t objc_method_list extends past end of the section\n"; 4407 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 4408 memcpy(&method_list, r, left); 4409 } 4410 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4411 swapStruct(method_list); 4412 4413 outs() << "\t\t obsolete " 4414 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4415 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4416 4417 methods = r + sizeof(struct objc_method_list_t); 4418 for (i = 0; i < method_list.method_count; i++) { 4419 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4420 outs() << "\t\t remaining method's extend past the of the section\n"; 4421 break; 4422 } 4423 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4424 sizeof(struct objc_method_t)); 4425 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4426 swapStruct(method); 4427 4428 outs() << "\t\t method_name " 4429 << format("0x%08" PRIx32, method.method_name); 4430 if (info->verbose) { 4431 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4432 if (name != nullptr) 4433 outs() << format(" %.*s", xleft, name); 4434 else 4435 outs() << " (not in an __OBJC section)"; 4436 } 4437 outs() << "\n"; 4438 4439 outs() << "\t\t method_types " 4440 << format("0x%08" PRIx32, method.method_types); 4441 if (info->verbose) { 4442 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4443 if (name != nullptr) 4444 outs() << format(" %.*s", xleft, name); 4445 else 4446 outs() << " (not in an __OBJC section)"; 4447 } 4448 outs() << "\n"; 4449 4450 outs() << "\t\t method_imp " 4451 << format("0x%08" PRIx32, method.method_imp) << " "; 4452 if (info->verbose) { 4453 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4454 if (SymbolName != nullptr) 4455 outs() << SymbolName; 4456 } 4457 outs() << "\n"; 4458 } 4459 return false; 4460 } 4461 4462 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4463 struct protocol_list64_t pl; 4464 uint64_t q, n_value; 4465 struct protocol64_t pc; 4466 const char *r; 4467 uint32_t offset, xoffset, left, i; 4468 SectionRef S, xS; 4469 const char *name, *sym_name; 4470 4471 r = get_pointer_64(p, offset, left, S, info); 4472 if (r == nullptr) 4473 return; 4474 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4475 if (left < sizeof(struct protocol_list64_t)) { 4476 memcpy(&pl, r, left); 4477 outs() << " (protocol_list_t entends past the end of the section)\n"; 4478 } else 4479 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4480 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4481 swapStruct(pl); 4482 outs() << " count " << pl.count << "\n"; 4483 4484 p += sizeof(struct protocol_list64_t); 4485 offset += sizeof(struct protocol_list64_t); 4486 for (i = 0; i < pl.count; i++) { 4487 r = get_pointer_64(p, offset, left, S, info); 4488 if (r == nullptr) 4489 return; 4490 q = 0; 4491 if (left < sizeof(uint64_t)) { 4492 memcpy(&q, r, left); 4493 outs() << " (protocol_t * entends past the end of the section)\n"; 4494 } else 4495 memcpy(&q, r, sizeof(uint64_t)); 4496 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4497 sys::swapByteOrder(q); 4498 4499 outs() << "\t\t list[" << i << "] "; 4500 sym_name = get_symbol_64(offset, S, info, n_value, q); 4501 if (n_value != 0) { 4502 if (info->verbose && sym_name != nullptr) 4503 outs() << sym_name; 4504 else 4505 outs() << format("0x%" PRIx64, n_value); 4506 if (q != 0) 4507 outs() << " + " << format("0x%" PRIx64, q); 4508 } else 4509 outs() << format("0x%" PRIx64, q); 4510 outs() << " (struct protocol_t *)\n"; 4511 4512 r = get_pointer_64(q + n_value, offset, left, S, info); 4513 if (r == nullptr) 4514 return; 4515 memset(&pc, '\0', sizeof(struct protocol64_t)); 4516 if (left < sizeof(struct protocol64_t)) { 4517 memcpy(&pc, r, left); 4518 outs() << " (protocol_t entends past the end of the section)\n"; 4519 } else 4520 memcpy(&pc, r, sizeof(struct protocol64_t)); 4521 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4522 swapStruct(pc); 4523 4524 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4525 4526 outs() << "\t\t\t name "; 4527 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4528 info, n_value, pc.name); 4529 if (n_value != 0) { 4530 if (info->verbose && sym_name != nullptr) 4531 outs() << sym_name; 4532 else 4533 outs() << format("0x%" PRIx64, n_value); 4534 if (pc.name != 0) 4535 outs() << " + " << format("0x%" PRIx64, pc.name); 4536 } else 4537 outs() << format("0x%" PRIx64, pc.name); 4538 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4539 if (name != nullptr) 4540 outs() << format(" %.*s", left, name); 4541 outs() << "\n"; 4542 4543 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4544 4545 outs() << "\t\t instanceMethods "; 4546 sym_name = 4547 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4548 S, info, n_value, pc.instanceMethods); 4549 if (n_value != 0) { 4550 if (info->verbose && sym_name != nullptr) 4551 outs() << sym_name; 4552 else 4553 outs() << format("0x%" PRIx64, n_value); 4554 if (pc.instanceMethods != 0) 4555 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4556 } else 4557 outs() << format("0x%" PRIx64, pc.instanceMethods); 4558 outs() << " (struct method_list_t *)\n"; 4559 if (pc.instanceMethods + n_value != 0) 4560 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4561 4562 outs() << "\t\t classMethods "; 4563 sym_name = 4564 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4565 info, n_value, pc.classMethods); 4566 if (n_value != 0) { 4567 if (info->verbose && sym_name != nullptr) 4568 outs() << sym_name; 4569 else 4570 outs() << format("0x%" PRIx64, n_value); 4571 if (pc.classMethods != 0) 4572 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4573 } else 4574 outs() << format("0x%" PRIx64, pc.classMethods); 4575 outs() << " (struct method_list_t *)\n"; 4576 if (pc.classMethods + n_value != 0) 4577 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4578 4579 outs() << "\t optionalInstanceMethods " 4580 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4581 outs() << "\t optionalClassMethods " 4582 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4583 outs() << "\t instanceProperties " 4584 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4585 4586 p += sizeof(uint64_t); 4587 offset += sizeof(uint64_t); 4588 } 4589 } 4590 4591 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4592 struct protocol_list32_t pl; 4593 uint32_t q; 4594 struct protocol32_t pc; 4595 const char *r; 4596 uint32_t offset, xoffset, left, i; 4597 SectionRef S, xS; 4598 const char *name; 4599 4600 r = get_pointer_32(p, offset, left, S, info); 4601 if (r == nullptr) 4602 return; 4603 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4604 if (left < sizeof(struct protocol_list32_t)) { 4605 memcpy(&pl, r, left); 4606 outs() << " (protocol_list_t entends past the end of the section)\n"; 4607 } else 4608 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4609 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4610 swapStruct(pl); 4611 outs() << " count " << pl.count << "\n"; 4612 4613 p += sizeof(struct protocol_list32_t); 4614 offset += sizeof(struct protocol_list32_t); 4615 for (i = 0; i < pl.count; i++) { 4616 r = get_pointer_32(p, offset, left, S, info); 4617 if (r == nullptr) 4618 return; 4619 q = 0; 4620 if (left < sizeof(uint32_t)) { 4621 memcpy(&q, r, left); 4622 outs() << " (protocol_t * entends past the end of the section)\n"; 4623 } else 4624 memcpy(&q, r, sizeof(uint32_t)); 4625 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4626 sys::swapByteOrder(q); 4627 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4628 << " (struct protocol_t *)\n"; 4629 r = get_pointer_32(q, offset, left, S, info); 4630 if (r == nullptr) 4631 return; 4632 memset(&pc, '\0', sizeof(struct protocol32_t)); 4633 if (left < sizeof(struct protocol32_t)) { 4634 memcpy(&pc, r, left); 4635 outs() << " (protocol_t entends past the end of the section)\n"; 4636 } else 4637 memcpy(&pc, r, sizeof(struct protocol32_t)); 4638 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4639 swapStruct(pc); 4640 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4641 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4642 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4643 if (name != nullptr) 4644 outs() << format(" %.*s", left, name); 4645 outs() << "\n"; 4646 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4647 outs() << "\t\t instanceMethods " 4648 << format("0x%" PRIx32, pc.instanceMethods) 4649 << " (struct method_list_t *)\n"; 4650 if (pc.instanceMethods != 0) 4651 print_method_list32_t(pc.instanceMethods, info, "\t"); 4652 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4653 << " (struct method_list_t *)\n"; 4654 if (pc.classMethods != 0) 4655 print_method_list32_t(pc.classMethods, info, "\t"); 4656 outs() << "\t optionalInstanceMethods " 4657 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4658 outs() << "\t optionalClassMethods " 4659 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4660 outs() << "\t instanceProperties " 4661 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4662 p += sizeof(uint32_t); 4663 offset += sizeof(uint32_t); 4664 } 4665 } 4666 4667 static void print_indent(uint32_t indent) { 4668 for (uint32_t i = 0; i < indent;) { 4669 if (indent - i >= 8) { 4670 outs() << "\t"; 4671 i += 8; 4672 } else { 4673 for (uint32_t j = i; j < indent; j++) 4674 outs() << " "; 4675 return; 4676 } 4677 } 4678 } 4679 4680 static bool print_method_description_list(uint32_t p, uint32_t indent, 4681 struct DisassembleInfo *info) { 4682 uint32_t offset, left, xleft; 4683 SectionRef S; 4684 struct objc_method_description_list_t mdl; 4685 struct objc_method_description_t md; 4686 const char *r, *list, *name; 4687 int32_t i; 4688 4689 r = get_pointer_32(p, offset, left, S, info, true); 4690 if (r == nullptr) 4691 return true; 4692 4693 outs() << "\n"; 4694 if (left > sizeof(struct objc_method_description_list_t)) { 4695 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 4696 } else { 4697 print_indent(indent); 4698 outs() << " objc_method_description_list extends past end of the section\n"; 4699 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 4700 memcpy(&mdl, r, left); 4701 } 4702 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4703 swapStruct(mdl); 4704 4705 print_indent(indent); 4706 outs() << " count " << mdl.count << "\n"; 4707 4708 list = r + sizeof(struct objc_method_description_list_t); 4709 for (i = 0; i < mdl.count; i++) { 4710 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 4711 print_indent(indent); 4712 outs() << " remaining list entries extend past the of the section\n"; 4713 break; 4714 } 4715 print_indent(indent); 4716 outs() << " list[" << i << "]\n"; 4717 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 4718 sizeof(struct objc_method_description_t)); 4719 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4720 swapStruct(md); 4721 4722 print_indent(indent); 4723 outs() << " name " << format("0x%08" PRIx32, md.name); 4724 if (info->verbose) { 4725 name = get_pointer_32(md.name, offset, xleft, S, info, true); 4726 if (name != nullptr) 4727 outs() << format(" %.*s", xleft, name); 4728 else 4729 outs() << " (not in an __OBJC section)"; 4730 } 4731 outs() << "\n"; 4732 4733 print_indent(indent); 4734 outs() << " types " << format("0x%08" PRIx32, md.types); 4735 if (info->verbose) { 4736 name = get_pointer_32(md.types, offset, xleft, S, info, true); 4737 if (name != nullptr) 4738 outs() << format(" %.*s", xleft, name); 4739 else 4740 outs() << " (not in an __OBJC section)"; 4741 } 4742 outs() << "\n"; 4743 } 4744 return false; 4745 } 4746 4747 static bool print_protocol_list(uint32_t p, uint32_t indent, 4748 struct DisassembleInfo *info); 4749 4750 static bool print_protocol(uint32_t p, uint32_t indent, 4751 struct DisassembleInfo *info) { 4752 uint32_t offset, left; 4753 SectionRef S; 4754 struct objc_protocol_t protocol; 4755 const char *r, *name; 4756 4757 r = get_pointer_32(p, offset, left, S, info, true); 4758 if (r == nullptr) 4759 return true; 4760 4761 outs() << "\n"; 4762 if (left >= sizeof(struct objc_protocol_t)) { 4763 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 4764 } else { 4765 print_indent(indent); 4766 outs() << " Protocol extends past end of the section\n"; 4767 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 4768 memcpy(&protocol, r, left); 4769 } 4770 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4771 swapStruct(protocol); 4772 4773 print_indent(indent); 4774 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 4775 << "\n"; 4776 4777 print_indent(indent); 4778 outs() << " protocol_name " 4779 << format("0x%08" PRIx32, protocol.protocol_name); 4780 if (info->verbose) { 4781 name = get_pointer_32(protocol.protocol_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 print_indent(indent); 4790 outs() << " protocol_list " 4791 << format("0x%08" PRIx32, protocol.protocol_list); 4792 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 4793 outs() << " (not in an __OBJC section)\n"; 4794 4795 print_indent(indent); 4796 outs() << " instance_methods " 4797 << format("0x%08" PRIx32, protocol.instance_methods); 4798 if (print_method_description_list(protocol.instance_methods, indent, info)) 4799 outs() << " (not in an __OBJC section)\n"; 4800 4801 print_indent(indent); 4802 outs() << " class_methods " 4803 << format("0x%08" PRIx32, protocol.class_methods); 4804 if (print_method_description_list(protocol.class_methods, indent, info)) 4805 outs() << " (not in an __OBJC section)\n"; 4806 4807 return false; 4808 } 4809 4810 static bool print_protocol_list(uint32_t p, uint32_t indent, 4811 struct DisassembleInfo *info) { 4812 uint32_t offset, left, l; 4813 SectionRef S; 4814 struct objc_protocol_list_t protocol_list; 4815 const char *r, *list; 4816 int32_t i; 4817 4818 r = get_pointer_32(p, offset, left, S, info, true); 4819 if (r == nullptr) 4820 return true; 4821 4822 outs() << "\n"; 4823 if (left > sizeof(struct objc_protocol_list_t)) { 4824 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 4825 } else { 4826 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 4827 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 4828 memcpy(&protocol_list, r, left); 4829 } 4830 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4831 swapStruct(protocol_list); 4832 4833 print_indent(indent); 4834 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 4835 << "\n"; 4836 print_indent(indent); 4837 outs() << " count " << protocol_list.count << "\n"; 4838 4839 list = r + sizeof(struct objc_protocol_list_t); 4840 for (i = 0; i < protocol_list.count; i++) { 4841 if ((i + 1) * sizeof(uint32_t) > left) { 4842 outs() << "\t\t remaining list entries extend past the of the section\n"; 4843 break; 4844 } 4845 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 4846 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4847 sys::swapByteOrder(l); 4848 4849 print_indent(indent); 4850 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 4851 if (print_protocol(l, indent, info)) 4852 outs() << "(not in an __OBJC section)\n"; 4853 } 4854 return false; 4855 } 4856 4857 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 4858 struct ivar_list64_t il; 4859 struct ivar64_t i; 4860 const char *r; 4861 uint32_t offset, xoffset, left, j; 4862 SectionRef S, xS; 4863 const char *name, *sym_name, *ivar_offset_p; 4864 uint64_t ivar_offset, n_value; 4865 4866 r = get_pointer_64(p, offset, left, S, info); 4867 if (r == nullptr) 4868 return; 4869 memset(&il, '\0', sizeof(struct ivar_list64_t)); 4870 if (left < sizeof(struct ivar_list64_t)) { 4871 memcpy(&il, r, left); 4872 outs() << " (ivar_list_t entends past the end of the section)\n"; 4873 } else 4874 memcpy(&il, r, sizeof(struct ivar_list64_t)); 4875 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4876 swapStruct(il); 4877 outs() << " entsize " << il.entsize << "\n"; 4878 outs() << " count " << il.count << "\n"; 4879 4880 p += sizeof(struct ivar_list64_t); 4881 offset += sizeof(struct ivar_list64_t); 4882 for (j = 0; j < il.count; j++) { 4883 r = get_pointer_64(p, offset, left, S, info); 4884 if (r == nullptr) 4885 return; 4886 memset(&i, '\0', sizeof(struct ivar64_t)); 4887 if (left < sizeof(struct ivar64_t)) { 4888 memcpy(&i, r, left); 4889 outs() << " (ivar_t entends past the end of the section)\n"; 4890 } else 4891 memcpy(&i, r, sizeof(struct ivar64_t)); 4892 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4893 swapStruct(i); 4894 4895 outs() << "\t\t\t offset "; 4896 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 4897 info, n_value, i.offset); 4898 if (n_value != 0) { 4899 if (info->verbose && sym_name != nullptr) 4900 outs() << sym_name; 4901 else 4902 outs() << format("0x%" PRIx64, n_value); 4903 if (i.offset != 0) 4904 outs() << " + " << format("0x%" PRIx64, i.offset); 4905 } else 4906 outs() << format("0x%" PRIx64, i.offset); 4907 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 4908 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4909 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4910 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4911 sys::swapByteOrder(ivar_offset); 4912 outs() << " " << ivar_offset << "\n"; 4913 } else 4914 outs() << "\n"; 4915 4916 outs() << "\t\t\t name "; 4917 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 4918 n_value, i.name); 4919 if (n_value != 0) { 4920 if (info->verbose && sym_name != nullptr) 4921 outs() << sym_name; 4922 else 4923 outs() << format("0x%" PRIx64, n_value); 4924 if (i.name != 0) 4925 outs() << " + " << format("0x%" PRIx64, i.name); 4926 } else 4927 outs() << format("0x%" PRIx64, i.name); 4928 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 4929 if (name != nullptr) 4930 outs() << format(" %.*s", left, name); 4931 outs() << "\n"; 4932 4933 outs() << "\t\t\t type "; 4934 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 4935 n_value, i.name); 4936 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 4937 if (n_value != 0) { 4938 if (info->verbose && sym_name != nullptr) 4939 outs() << sym_name; 4940 else 4941 outs() << format("0x%" PRIx64, n_value); 4942 if (i.type != 0) 4943 outs() << " + " << format("0x%" PRIx64, i.type); 4944 } else 4945 outs() << format("0x%" PRIx64, i.type); 4946 if (name != nullptr) 4947 outs() << format(" %.*s", left, name); 4948 outs() << "\n"; 4949 4950 outs() << "\t\t\talignment " << i.alignment << "\n"; 4951 outs() << "\t\t\t size " << i.size << "\n"; 4952 4953 p += sizeof(struct ivar64_t); 4954 offset += sizeof(struct ivar64_t); 4955 } 4956 } 4957 4958 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 4959 struct ivar_list32_t il; 4960 struct ivar32_t i; 4961 const char *r; 4962 uint32_t offset, xoffset, left, j; 4963 SectionRef S, xS; 4964 const char *name, *ivar_offset_p; 4965 uint32_t ivar_offset; 4966 4967 r = get_pointer_32(p, offset, left, S, info); 4968 if (r == nullptr) 4969 return; 4970 memset(&il, '\0', sizeof(struct ivar_list32_t)); 4971 if (left < sizeof(struct ivar_list32_t)) { 4972 memcpy(&il, r, left); 4973 outs() << " (ivar_list_t entends past the end of the section)\n"; 4974 } else 4975 memcpy(&il, r, sizeof(struct ivar_list32_t)); 4976 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4977 swapStruct(il); 4978 outs() << " entsize " << il.entsize << "\n"; 4979 outs() << " count " << il.count << "\n"; 4980 4981 p += sizeof(struct ivar_list32_t); 4982 offset += sizeof(struct ivar_list32_t); 4983 for (j = 0; j < il.count; j++) { 4984 r = get_pointer_32(p, offset, left, S, info); 4985 if (r == nullptr) 4986 return; 4987 memset(&i, '\0', sizeof(struct ivar32_t)); 4988 if (left < sizeof(struct ivar32_t)) { 4989 memcpy(&i, r, left); 4990 outs() << " (ivar_t entends past the end of the section)\n"; 4991 } else 4992 memcpy(&i, r, sizeof(struct ivar32_t)); 4993 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4994 swapStruct(i); 4995 4996 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 4997 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 4998 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4999 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 5000 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5001 sys::swapByteOrder(ivar_offset); 5002 outs() << " " << ivar_offset << "\n"; 5003 } else 5004 outs() << "\n"; 5005 5006 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 5007 name = get_pointer_32(i.name, xoffset, left, xS, info); 5008 if (name != nullptr) 5009 outs() << format(" %.*s", left, name); 5010 outs() << "\n"; 5011 5012 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 5013 name = get_pointer_32(i.type, xoffset, left, xS, info); 5014 if (name != nullptr) 5015 outs() << format(" %.*s", left, name); 5016 outs() << "\n"; 5017 5018 outs() << "\t\t\talignment " << i.alignment << "\n"; 5019 outs() << "\t\t\t size " << i.size << "\n"; 5020 5021 p += sizeof(struct ivar32_t); 5022 offset += sizeof(struct ivar32_t); 5023 } 5024 } 5025 5026 static void print_objc_property_list64(uint64_t p, 5027 struct DisassembleInfo *info) { 5028 struct objc_property_list64 opl; 5029 struct objc_property64 op; 5030 const char *r; 5031 uint32_t offset, xoffset, left, j; 5032 SectionRef S, xS; 5033 const char *name, *sym_name; 5034 uint64_t n_value; 5035 5036 r = get_pointer_64(p, offset, left, S, info); 5037 if (r == nullptr) 5038 return; 5039 memset(&opl, '\0', sizeof(struct objc_property_list64)); 5040 if (left < sizeof(struct objc_property_list64)) { 5041 memcpy(&opl, r, left); 5042 outs() << " (objc_property_list entends past the end of the section)\n"; 5043 } else 5044 memcpy(&opl, r, sizeof(struct objc_property_list64)); 5045 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5046 swapStruct(opl); 5047 outs() << " entsize " << opl.entsize << "\n"; 5048 outs() << " count " << opl.count << "\n"; 5049 5050 p += sizeof(struct objc_property_list64); 5051 offset += sizeof(struct objc_property_list64); 5052 for (j = 0; j < opl.count; j++) { 5053 r = get_pointer_64(p, offset, left, S, info); 5054 if (r == nullptr) 5055 return; 5056 memset(&op, '\0', sizeof(struct objc_property64)); 5057 if (left < sizeof(struct objc_property64)) { 5058 memcpy(&op, r, left); 5059 outs() << " (objc_property entends past the end of the section)\n"; 5060 } else 5061 memcpy(&op, r, sizeof(struct objc_property64)); 5062 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5063 swapStruct(op); 5064 5065 outs() << "\t\t\t name "; 5066 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 5067 info, n_value, op.name); 5068 if (n_value != 0) { 5069 if (info->verbose && sym_name != nullptr) 5070 outs() << sym_name; 5071 else 5072 outs() << format("0x%" PRIx64, n_value); 5073 if (op.name != 0) 5074 outs() << " + " << format("0x%" PRIx64, op.name); 5075 } else 5076 outs() << format("0x%" PRIx64, op.name); 5077 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 5078 if (name != nullptr) 5079 outs() << format(" %.*s", left, name); 5080 outs() << "\n"; 5081 5082 outs() << "\t\t\tattributes "; 5083 sym_name = 5084 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 5085 info, n_value, op.attributes); 5086 if (n_value != 0) { 5087 if (info->verbose && sym_name != nullptr) 5088 outs() << sym_name; 5089 else 5090 outs() << format("0x%" PRIx64, n_value); 5091 if (op.attributes != 0) 5092 outs() << " + " << format("0x%" PRIx64, op.attributes); 5093 } else 5094 outs() << format("0x%" PRIx64, op.attributes); 5095 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 5096 if (name != nullptr) 5097 outs() << format(" %.*s", left, name); 5098 outs() << "\n"; 5099 5100 p += sizeof(struct objc_property64); 5101 offset += sizeof(struct objc_property64); 5102 } 5103 } 5104 5105 static void print_objc_property_list32(uint32_t p, 5106 struct DisassembleInfo *info) { 5107 struct objc_property_list32 opl; 5108 struct objc_property32 op; 5109 const char *r; 5110 uint32_t offset, xoffset, left, j; 5111 SectionRef S, xS; 5112 const char *name; 5113 5114 r = get_pointer_32(p, offset, left, S, info); 5115 if (r == nullptr) 5116 return; 5117 memset(&opl, '\0', sizeof(struct objc_property_list32)); 5118 if (left < sizeof(struct objc_property_list32)) { 5119 memcpy(&opl, r, left); 5120 outs() << " (objc_property_list entends past the end of the section)\n"; 5121 } else 5122 memcpy(&opl, r, sizeof(struct objc_property_list32)); 5123 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5124 swapStruct(opl); 5125 outs() << " entsize " << opl.entsize << "\n"; 5126 outs() << " count " << opl.count << "\n"; 5127 5128 p += sizeof(struct objc_property_list32); 5129 offset += sizeof(struct objc_property_list32); 5130 for (j = 0; j < opl.count; j++) { 5131 r = get_pointer_32(p, offset, left, S, info); 5132 if (r == nullptr) 5133 return; 5134 memset(&op, '\0', sizeof(struct objc_property32)); 5135 if (left < sizeof(struct objc_property32)) { 5136 memcpy(&op, r, left); 5137 outs() << " (objc_property entends past the end of the section)\n"; 5138 } else 5139 memcpy(&op, r, sizeof(struct objc_property32)); 5140 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5141 swapStruct(op); 5142 5143 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 5144 name = get_pointer_32(op.name, xoffset, left, xS, info); 5145 if (name != nullptr) 5146 outs() << format(" %.*s", left, name); 5147 outs() << "\n"; 5148 5149 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 5150 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 5151 if (name != nullptr) 5152 outs() << format(" %.*s", left, name); 5153 outs() << "\n"; 5154 5155 p += sizeof(struct objc_property32); 5156 offset += sizeof(struct objc_property32); 5157 } 5158 } 5159 5160 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 5161 bool &is_meta_class) { 5162 struct class_ro64_t cro; 5163 const char *r; 5164 uint32_t offset, xoffset, left; 5165 SectionRef S, xS; 5166 const char *name, *sym_name; 5167 uint64_t n_value; 5168 5169 r = get_pointer_64(p, offset, left, S, info); 5170 if (r == nullptr || left < sizeof(struct class_ro64_t)) 5171 return false; 5172 memcpy(&cro, r, sizeof(struct class_ro64_t)); 5173 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5174 swapStruct(cro); 5175 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5176 if (cro.flags & RO_META) 5177 outs() << " RO_META"; 5178 if (cro.flags & RO_ROOT) 5179 outs() << " RO_ROOT"; 5180 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5181 outs() << " RO_HAS_CXX_STRUCTORS"; 5182 outs() << "\n"; 5183 outs() << " instanceStart " << cro.instanceStart << "\n"; 5184 outs() << " instanceSize " << cro.instanceSize << "\n"; 5185 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 5186 << "\n"; 5187 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 5188 << "\n"; 5189 print_layout_map64(cro.ivarLayout, info); 5190 5191 outs() << " name "; 5192 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 5193 info, n_value, cro.name); 5194 if (n_value != 0) { 5195 if (info->verbose && sym_name != nullptr) 5196 outs() << sym_name; 5197 else 5198 outs() << format("0x%" PRIx64, n_value); 5199 if (cro.name != 0) 5200 outs() << " + " << format("0x%" PRIx64, cro.name); 5201 } else 5202 outs() << format("0x%" PRIx64, cro.name); 5203 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 5204 if (name != nullptr) 5205 outs() << format(" %.*s", left, name); 5206 outs() << "\n"; 5207 5208 outs() << " baseMethods "; 5209 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 5210 S, info, n_value, cro.baseMethods); 5211 if (n_value != 0) { 5212 if (info->verbose && sym_name != nullptr) 5213 outs() << sym_name; 5214 else 5215 outs() << format("0x%" PRIx64, n_value); 5216 if (cro.baseMethods != 0) 5217 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 5218 } else 5219 outs() << format("0x%" PRIx64, cro.baseMethods); 5220 outs() << " (struct method_list_t *)\n"; 5221 if (cro.baseMethods + n_value != 0) 5222 print_method_list64_t(cro.baseMethods + n_value, info, ""); 5223 5224 outs() << " baseProtocols "; 5225 sym_name = 5226 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 5227 info, n_value, cro.baseProtocols); 5228 if (n_value != 0) { 5229 if (info->verbose && sym_name != nullptr) 5230 outs() << sym_name; 5231 else 5232 outs() << format("0x%" PRIx64, n_value); 5233 if (cro.baseProtocols != 0) 5234 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 5235 } else 5236 outs() << format("0x%" PRIx64, cro.baseProtocols); 5237 outs() << "\n"; 5238 if (cro.baseProtocols + n_value != 0) 5239 print_protocol_list64_t(cro.baseProtocols + n_value, info); 5240 5241 outs() << " ivars "; 5242 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 5243 info, n_value, cro.ivars); 5244 if (n_value != 0) { 5245 if (info->verbose && sym_name != nullptr) 5246 outs() << sym_name; 5247 else 5248 outs() << format("0x%" PRIx64, n_value); 5249 if (cro.ivars != 0) 5250 outs() << " + " << format("0x%" PRIx64, cro.ivars); 5251 } else 5252 outs() << format("0x%" PRIx64, cro.ivars); 5253 outs() << "\n"; 5254 if (cro.ivars + n_value != 0) 5255 print_ivar_list64_t(cro.ivars + n_value, info); 5256 5257 outs() << " weakIvarLayout "; 5258 sym_name = 5259 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 5260 info, n_value, cro.weakIvarLayout); 5261 if (n_value != 0) { 5262 if (info->verbose && sym_name != nullptr) 5263 outs() << sym_name; 5264 else 5265 outs() << format("0x%" PRIx64, n_value); 5266 if (cro.weakIvarLayout != 0) 5267 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 5268 } else 5269 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 5270 outs() << "\n"; 5271 print_layout_map64(cro.weakIvarLayout + n_value, info); 5272 5273 outs() << " baseProperties "; 5274 sym_name = 5275 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 5276 info, n_value, cro.baseProperties); 5277 if (n_value != 0) { 5278 if (info->verbose && sym_name != nullptr) 5279 outs() << sym_name; 5280 else 5281 outs() << format("0x%" PRIx64, n_value); 5282 if (cro.baseProperties != 0) 5283 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 5284 } else 5285 outs() << format("0x%" PRIx64, cro.baseProperties); 5286 outs() << "\n"; 5287 if (cro.baseProperties + n_value != 0) 5288 print_objc_property_list64(cro.baseProperties + n_value, info); 5289 5290 is_meta_class = (cro.flags & RO_META) != 0; 5291 return true; 5292 } 5293 5294 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 5295 bool &is_meta_class) { 5296 struct class_ro32_t cro; 5297 const char *r; 5298 uint32_t offset, xoffset, left; 5299 SectionRef S, xS; 5300 const char *name; 5301 5302 r = get_pointer_32(p, offset, left, S, info); 5303 if (r == nullptr) 5304 return false; 5305 memset(&cro, '\0', sizeof(struct class_ro32_t)); 5306 if (left < sizeof(struct class_ro32_t)) { 5307 memcpy(&cro, r, left); 5308 outs() << " (class_ro_t entends past the end of the section)\n"; 5309 } else 5310 memcpy(&cro, r, sizeof(struct class_ro32_t)); 5311 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5312 swapStruct(cro); 5313 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5314 if (cro.flags & RO_META) 5315 outs() << " RO_META"; 5316 if (cro.flags & RO_ROOT) 5317 outs() << " RO_ROOT"; 5318 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5319 outs() << " RO_HAS_CXX_STRUCTORS"; 5320 outs() << "\n"; 5321 outs() << " instanceStart " << cro.instanceStart << "\n"; 5322 outs() << " instanceSize " << cro.instanceSize << "\n"; 5323 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 5324 << "\n"; 5325 print_layout_map32(cro.ivarLayout, info); 5326 5327 outs() << " name " << format("0x%" PRIx32, cro.name); 5328 name = get_pointer_32(cro.name, xoffset, left, xS, info); 5329 if (name != nullptr) 5330 outs() << format(" %.*s", left, name); 5331 outs() << "\n"; 5332 5333 outs() << " baseMethods " 5334 << format("0x%" PRIx32, cro.baseMethods) 5335 << " (struct method_list_t *)\n"; 5336 if (cro.baseMethods != 0) 5337 print_method_list32_t(cro.baseMethods, info, ""); 5338 5339 outs() << " baseProtocols " 5340 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 5341 if (cro.baseProtocols != 0) 5342 print_protocol_list32_t(cro.baseProtocols, info); 5343 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 5344 << "\n"; 5345 if (cro.ivars != 0) 5346 print_ivar_list32_t(cro.ivars, info); 5347 outs() << " weakIvarLayout " 5348 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 5349 print_layout_map32(cro.weakIvarLayout, info); 5350 outs() << " baseProperties " 5351 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 5352 if (cro.baseProperties != 0) 5353 print_objc_property_list32(cro.baseProperties, info); 5354 is_meta_class = (cro.flags & RO_META) != 0; 5355 return true; 5356 } 5357 5358 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 5359 struct class64_t c; 5360 const char *r; 5361 uint32_t offset, left; 5362 SectionRef S; 5363 const char *name; 5364 uint64_t isa_n_value, n_value; 5365 5366 r = get_pointer_64(p, offset, left, S, info); 5367 if (r == nullptr || left < sizeof(struct class64_t)) 5368 return; 5369 memcpy(&c, r, sizeof(struct class64_t)); 5370 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5371 swapStruct(c); 5372 5373 outs() << " isa " << format("0x%" PRIx64, c.isa); 5374 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 5375 isa_n_value, c.isa); 5376 if (name != nullptr) 5377 outs() << " " << name; 5378 outs() << "\n"; 5379 5380 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 5381 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 5382 n_value, c.superclass); 5383 if (name != nullptr) 5384 outs() << " " << name; 5385 else { 5386 name = get_dyld_bind_info_symbolname(S.getAddress() + 5387 offset + offsetof(struct class64_t, superclass), info); 5388 if (name != nullptr) 5389 outs() << " " << name; 5390 } 5391 outs() << "\n"; 5392 5393 outs() << " cache " << format("0x%" PRIx64, c.cache); 5394 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 5395 n_value, c.cache); 5396 if (name != nullptr) 5397 outs() << " " << name; 5398 outs() << "\n"; 5399 5400 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 5401 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 5402 n_value, c.vtable); 5403 if (name != nullptr) 5404 outs() << " " << name; 5405 outs() << "\n"; 5406 5407 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 5408 n_value, c.data); 5409 outs() << " data "; 5410 if (n_value != 0) { 5411 if (info->verbose && name != nullptr) 5412 outs() << name; 5413 else 5414 outs() << format("0x%" PRIx64, n_value); 5415 if (c.data != 0) 5416 outs() << " + " << format("0x%" PRIx64, c.data); 5417 } else 5418 outs() << format("0x%" PRIx64, c.data); 5419 outs() << " (struct class_ro_t *)"; 5420 5421 // This is a Swift class if some of the low bits of the pointer are set. 5422 if ((c.data + n_value) & 0x7) 5423 outs() << " Swift class"; 5424 outs() << "\n"; 5425 bool is_meta_class; 5426 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5427 return; 5428 5429 if (!is_meta_class && 5430 c.isa + isa_n_value != p && 5431 c.isa + isa_n_value != 0 && 5432 info->depth < 100) { 5433 info->depth++; 5434 outs() << "Meta Class\n"; 5435 print_class64_t(c.isa + isa_n_value, info); 5436 } 5437 } 5438 5439 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5440 struct class32_t c; 5441 const char *r; 5442 uint32_t offset, left; 5443 SectionRef S; 5444 const char *name; 5445 5446 r = get_pointer_32(p, offset, left, S, info); 5447 if (r == nullptr) 5448 return; 5449 memset(&c, '\0', sizeof(struct class32_t)); 5450 if (left < sizeof(struct class32_t)) { 5451 memcpy(&c, r, left); 5452 outs() << " (class_t entends past the end of the section)\n"; 5453 } else 5454 memcpy(&c, r, sizeof(struct class32_t)); 5455 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5456 swapStruct(c); 5457 5458 outs() << " isa " << format("0x%" PRIx32, c.isa); 5459 name = 5460 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5461 if (name != nullptr) 5462 outs() << " " << name; 5463 outs() << "\n"; 5464 5465 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5466 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5467 c.superclass); 5468 if (name != nullptr) 5469 outs() << " " << name; 5470 outs() << "\n"; 5471 5472 outs() << " cache " << format("0x%" PRIx32, c.cache); 5473 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5474 c.cache); 5475 if (name != nullptr) 5476 outs() << " " << name; 5477 outs() << "\n"; 5478 5479 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5480 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5481 c.vtable); 5482 if (name != nullptr) 5483 outs() << " " << name; 5484 outs() << "\n"; 5485 5486 name = 5487 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5488 outs() << " data " << format("0x%" PRIx32, c.data) 5489 << " (struct class_ro_t *)"; 5490 5491 // This is a Swift class if some of the low bits of the pointer are set. 5492 if (c.data & 0x3) 5493 outs() << " Swift class"; 5494 outs() << "\n"; 5495 bool is_meta_class; 5496 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5497 return; 5498 5499 if (!is_meta_class) { 5500 outs() << "Meta Class\n"; 5501 print_class32_t(c.isa, info); 5502 } 5503 } 5504 5505 static void print_objc_class_t(struct objc_class_t *objc_class, 5506 struct DisassembleInfo *info) { 5507 uint32_t offset, left, xleft; 5508 const char *name, *p, *ivar_list; 5509 SectionRef S; 5510 int32_t i; 5511 struct objc_ivar_list_t objc_ivar_list; 5512 struct objc_ivar_t ivar; 5513 5514 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5515 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5516 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5517 if (name != nullptr) 5518 outs() << format(" %.*s", left, name); 5519 else 5520 outs() << " (not in an __OBJC section)"; 5521 } 5522 outs() << "\n"; 5523 5524 outs() << "\t super_class " 5525 << format("0x%08" PRIx32, objc_class->super_class); 5526 if (info->verbose) { 5527 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5528 if (name != nullptr) 5529 outs() << format(" %.*s", left, name); 5530 else 5531 outs() << " (not in an __OBJC section)"; 5532 } 5533 outs() << "\n"; 5534 5535 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5536 if (info->verbose) { 5537 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5538 if (name != nullptr) 5539 outs() << format(" %.*s", left, name); 5540 else 5541 outs() << " (not in an __OBJC section)"; 5542 } 5543 outs() << "\n"; 5544 5545 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5546 << "\n"; 5547 5548 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5549 if (info->verbose) { 5550 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5551 outs() << " CLS_CLASS"; 5552 else if (CLS_GETINFO(objc_class, CLS_META)) 5553 outs() << " CLS_META"; 5554 } 5555 outs() << "\n"; 5556 5557 outs() << "\t instance_size " 5558 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5559 5560 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5561 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5562 if (p != nullptr) { 5563 if (left > sizeof(struct objc_ivar_list_t)) { 5564 outs() << "\n"; 5565 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5566 } else { 5567 outs() << " (entends past the end of the section)\n"; 5568 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5569 memcpy(&objc_ivar_list, p, left); 5570 } 5571 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5572 swapStruct(objc_ivar_list); 5573 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5574 ivar_list = p + sizeof(struct objc_ivar_list_t); 5575 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5576 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5577 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5578 break; 5579 } 5580 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5581 sizeof(struct objc_ivar_t)); 5582 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5583 swapStruct(ivar); 5584 5585 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5586 if (info->verbose) { 5587 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5588 if (name != nullptr) 5589 outs() << format(" %.*s", xleft, name); 5590 else 5591 outs() << " (not in an __OBJC section)"; 5592 } 5593 outs() << "\n"; 5594 5595 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5596 if (info->verbose) { 5597 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5598 if (name != nullptr) 5599 outs() << format(" %.*s", xleft, name); 5600 else 5601 outs() << " (not in an __OBJC section)"; 5602 } 5603 outs() << "\n"; 5604 5605 outs() << "\t\t ivar_offset " 5606 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5607 } 5608 } else { 5609 outs() << " (not in an __OBJC section)\n"; 5610 } 5611 5612 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5613 if (print_method_list(objc_class->methodLists, info)) 5614 outs() << " (not in an __OBJC section)\n"; 5615 5616 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5617 << "\n"; 5618 5619 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5620 if (print_protocol_list(objc_class->protocols, 16, info)) 5621 outs() << " (not in an __OBJC section)\n"; 5622 } 5623 5624 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5625 struct DisassembleInfo *info) { 5626 uint32_t offset, left; 5627 const char *name; 5628 SectionRef S; 5629 5630 outs() << "\t category name " 5631 << format("0x%08" PRIx32, objc_category->category_name); 5632 if (info->verbose) { 5633 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5634 true); 5635 if (name != nullptr) 5636 outs() << format(" %.*s", left, name); 5637 else 5638 outs() << " (not in an __OBJC section)"; 5639 } 5640 outs() << "\n"; 5641 5642 outs() << "\t\t class name " 5643 << format("0x%08" PRIx32, objc_category->class_name); 5644 if (info->verbose) { 5645 name = 5646 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5647 if (name != nullptr) 5648 outs() << format(" %.*s", left, name); 5649 else 5650 outs() << " (not in an __OBJC section)"; 5651 } 5652 outs() << "\n"; 5653 5654 outs() << "\t instance methods " 5655 << format("0x%08" PRIx32, objc_category->instance_methods); 5656 if (print_method_list(objc_category->instance_methods, info)) 5657 outs() << " (not in an __OBJC section)\n"; 5658 5659 outs() << "\t class methods " 5660 << format("0x%08" PRIx32, objc_category->class_methods); 5661 if (print_method_list(objc_category->class_methods, info)) 5662 outs() << " (not in an __OBJC section)\n"; 5663 } 5664 5665 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5666 struct category64_t c; 5667 const char *r; 5668 uint32_t offset, xoffset, left; 5669 SectionRef S, xS; 5670 const char *name, *sym_name; 5671 uint64_t n_value; 5672 5673 r = get_pointer_64(p, offset, left, S, info); 5674 if (r == nullptr) 5675 return; 5676 memset(&c, '\0', sizeof(struct category64_t)); 5677 if (left < sizeof(struct category64_t)) { 5678 memcpy(&c, r, left); 5679 outs() << " (category_t entends past the end of the section)\n"; 5680 } else 5681 memcpy(&c, r, sizeof(struct category64_t)); 5682 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5683 swapStruct(c); 5684 5685 outs() << " name "; 5686 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 5687 info, n_value, c.name); 5688 if (n_value != 0) { 5689 if (info->verbose && sym_name != nullptr) 5690 outs() << sym_name; 5691 else 5692 outs() << format("0x%" PRIx64, n_value); 5693 if (c.name != 0) 5694 outs() << " + " << format("0x%" PRIx64, c.name); 5695 } else 5696 outs() << format("0x%" PRIx64, c.name); 5697 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 5698 if (name != nullptr) 5699 outs() << format(" %.*s", left, name); 5700 outs() << "\n"; 5701 5702 outs() << " cls "; 5703 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 5704 n_value, c.cls); 5705 if (n_value != 0) { 5706 if (info->verbose && sym_name != nullptr) 5707 outs() << sym_name; 5708 else 5709 outs() << format("0x%" PRIx64, n_value); 5710 if (c.cls != 0) 5711 outs() << " + " << format("0x%" PRIx64, c.cls); 5712 } else 5713 outs() << format("0x%" PRIx64, c.cls); 5714 outs() << "\n"; 5715 if (c.cls + n_value != 0) 5716 print_class64_t(c.cls + n_value, info); 5717 5718 outs() << " instanceMethods "; 5719 sym_name = 5720 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 5721 info, n_value, c.instanceMethods); 5722 if (n_value != 0) { 5723 if (info->verbose && sym_name != nullptr) 5724 outs() << sym_name; 5725 else 5726 outs() << format("0x%" PRIx64, n_value); 5727 if (c.instanceMethods != 0) 5728 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 5729 } else 5730 outs() << format("0x%" PRIx64, c.instanceMethods); 5731 outs() << "\n"; 5732 if (c.instanceMethods + n_value != 0) 5733 print_method_list64_t(c.instanceMethods + n_value, info, ""); 5734 5735 outs() << " classMethods "; 5736 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 5737 S, info, n_value, c.classMethods); 5738 if (n_value != 0) { 5739 if (info->verbose && sym_name != nullptr) 5740 outs() << sym_name; 5741 else 5742 outs() << format("0x%" PRIx64, n_value); 5743 if (c.classMethods != 0) 5744 outs() << " + " << format("0x%" PRIx64, c.classMethods); 5745 } else 5746 outs() << format("0x%" PRIx64, c.classMethods); 5747 outs() << "\n"; 5748 if (c.classMethods + n_value != 0) 5749 print_method_list64_t(c.classMethods + n_value, info, ""); 5750 5751 outs() << " protocols "; 5752 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 5753 info, n_value, c.protocols); 5754 if (n_value != 0) { 5755 if (info->verbose && sym_name != nullptr) 5756 outs() << sym_name; 5757 else 5758 outs() << format("0x%" PRIx64, n_value); 5759 if (c.protocols != 0) 5760 outs() << " + " << format("0x%" PRIx64, c.protocols); 5761 } else 5762 outs() << format("0x%" PRIx64, c.protocols); 5763 outs() << "\n"; 5764 if (c.protocols + n_value != 0) 5765 print_protocol_list64_t(c.protocols + n_value, info); 5766 5767 outs() << "instanceProperties "; 5768 sym_name = 5769 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 5770 S, info, n_value, c.instanceProperties); 5771 if (n_value != 0) { 5772 if (info->verbose && sym_name != nullptr) 5773 outs() << sym_name; 5774 else 5775 outs() << format("0x%" PRIx64, n_value); 5776 if (c.instanceProperties != 0) 5777 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 5778 } else 5779 outs() << format("0x%" PRIx64, c.instanceProperties); 5780 outs() << "\n"; 5781 if (c.instanceProperties + n_value != 0) 5782 print_objc_property_list64(c.instanceProperties + n_value, info); 5783 } 5784 5785 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 5786 struct category32_t c; 5787 const char *r; 5788 uint32_t offset, left; 5789 SectionRef S, xS; 5790 const char *name; 5791 5792 r = get_pointer_32(p, offset, left, S, info); 5793 if (r == nullptr) 5794 return; 5795 memset(&c, '\0', sizeof(struct category32_t)); 5796 if (left < sizeof(struct category32_t)) { 5797 memcpy(&c, r, left); 5798 outs() << " (category_t entends past the end of the section)\n"; 5799 } else 5800 memcpy(&c, r, sizeof(struct category32_t)); 5801 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5802 swapStruct(c); 5803 5804 outs() << " name " << format("0x%" PRIx32, c.name); 5805 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 5806 c.name); 5807 if (name) 5808 outs() << " " << name; 5809 outs() << "\n"; 5810 5811 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 5812 if (c.cls != 0) 5813 print_class32_t(c.cls, info); 5814 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 5815 << "\n"; 5816 if (c.instanceMethods != 0) 5817 print_method_list32_t(c.instanceMethods, info, ""); 5818 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 5819 << "\n"; 5820 if (c.classMethods != 0) 5821 print_method_list32_t(c.classMethods, info, ""); 5822 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 5823 if (c.protocols != 0) 5824 print_protocol_list32_t(c.protocols, info); 5825 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 5826 << "\n"; 5827 if (c.instanceProperties != 0) 5828 print_objc_property_list32(c.instanceProperties, info); 5829 } 5830 5831 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 5832 uint32_t i, left, offset, xoffset; 5833 uint64_t p, n_value; 5834 struct message_ref64 mr; 5835 const char *name, *sym_name; 5836 const char *r; 5837 SectionRef xS; 5838 5839 if (S == SectionRef()) 5840 return; 5841 5842 StringRef SectName; 5843 Expected<StringRef> SecNameOrErr = S.getName(); 5844 if (SecNameOrErr) 5845 SectName = *SecNameOrErr; 5846 else 5847 consumeError(SecNameOrErr.takeError()); 5848 5849 DataRefImpl Ref = S.getRawDataRefImpl(); 5850 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5851 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5852 offset = 0; 5853 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5854 p = S.getAddress() + i; 5855 r = get_pointer_64(p, offset, left, S, info); 5856 if (r == nullptr) 5857 return; 5858 memset(&mr, '\0', sizeof(struct message_ref64)); 5859 if (left < sizeof(struct message_ref64)) { 5860 memcpy(&mr, r, left); 5861 outs() << " (message_ref entends past the end of the section)\n"; 5862 } else 5863 memcpy(&mr, r, sizeof(struct message_ref64)); 5864 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5865 swapStruct(mr); 5866 5867 outs() << " imp "; 5868 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 5869 n_value, mr.imp); 5870 if (n_value != 0) { 5871 outs() << format("0x%" PRIx64, n_value) << " "; 5872 if (mr.imp != 0) 5873 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 5874 } else 5875 outs() << format("0x%" PRIx64, mr.imp) << " "; 5876 if (name != nullptr) 5877 outs() << " " << name; 5878 outs() << "\n"; 5879 5880 outs() << " sel "; 5881 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 5882 info, n_value, mr.sel); 5883 if (n_value != 0) { 5884 if (info->verbose && sym_name != nullptr) 5885 outs() << sym_name; 5886 else 5887 outs() << format("0x%" PRIx64, n_value); 5888 if (mr.sel != 0) 5889 outs() << " + " << format("0x%" PRIx64, mr.sel); 5890 } else 5891 outs() << format("0x%" PRIx64, mr.sel); 5892 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 5893 if (name != nullptr) 5894 outs() << format(" %.*s", left, name); 5895 outs() << "\n"; 5896 5897 offset += sizeof(struct message_ref64); 5898 } 5899 } 5900 5901 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 5902 uint32_t i, left, offset, xoffset, p; 5903 struct message_ref32 mr; 5904 const char *name, *r; 5905 SectionRef xS; 5906 5907 if (S == SectionRef()) 5908 return; 5909 5910 StringRef SectName; 5911 Expected<StringRef> SecNameOrErr = S.getName(); 5912 if (SecNameOrErr) 5913 SectName = *SecNameOrErr; 5914 else 5915 consumeError(SecNameOrErr.takeError()); 5916 5917 DataRefImpl Ref = S.getRawDataRefImpl(); 5918 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5919 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5920 offset = 0; 5921 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5922 p = S.getAddress() + i; 5923 r = get_pointer_32(p, offset, left, S, info); 5924 if (r == nullptr) 5925 return; 5926 memset(&mr, '\0', sizeof(struct message_ref32)); 5927 if (left < sizeof(struct message_ref32)) { 5928 memcpy(&mr, r, left); 5929 outs() << " (message_ref entends past the end of the section)\n"; 5930 } else 5931 memcpy(&mr, r, sizeof(struct message_ref32)); 5932 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5933 swapStruct(mr); 5934 5935 outs() << " imp " << format("0x%" PRIx32, mr.imp); 5936 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 5937 mr.imp); 5938 if (name != nullptr) 5939 outs() << " " << name; 5940 outs() << "\n"; 5941 5942 outs() << " sel " << format("0x%" PRIx32, mr.sel); 5943 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 5944 if (name != nullptr) 5945 outs() << " " << name; 5946 outs() << "\n"; 5947 5948 offset += sizeof(struct message_ref32); 5949 } 5950 } 5951 5952 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 5953 uint32_t left, offset, swift_version; 5954 uint64_t p; 5955 struct objc_image_info64 o; 5956 const char *r; 5957 5958 if (S == SectionRef()) 5959 return; 5960 5961 StringRef SectName; 5962 Expected<StringRef> SecNameOrErr = S.getName(); 5963 if (SecNameOrErr) 5964 SectName = *SecNameOrErr; 5965 else 5966 consumeError(SecNameOrErr.takeError()); 5967 5968 DataRefImpl Ref = S.getRawDataRefImpl(); 5969 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5970 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5971 p = S.getAddress(); 5972 r = get_pointer_64(p, offset, left, S, info); 5973 if (r == nullptr) 5974 return; 5975 memset(&o, '\0', sizeof(struct objc_image_info64)); 5976 if (left < sizeof(struct objc_image_info64)) { 5977 memcpy(&o, r, left); 5978 outs() << " (objc_image_info entends past the end of the section)\n"; 5979 } else 5980 memcpy(&o, r, sizeof(struct objc_image_info64)); 5981 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5982 swapStruct(o); 5983 outs() << " version " << o.version << "\n"; 5984 outs() << " flags " << format("0x%" PRIx32, o.flags); 5985 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5986 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5987 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5988 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5989 if (o.flags & OBJC_IMAGE_IS_SIMULATED) 5990 outs() << " OBJC_IMAGE_IS_SIMULATED"; 5991 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES) 5992 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES"; 5993 swift_version = (o.flags >> 8) & 0xff; 5994 if (swift_version != 0) { 5995 if (swift_version == 1) 5996 outs() << " Swift 1.0"; 5997 else if (swift_version == 2) 5998 outs() << " Swift 1.1"; 5999 else if(swift_version == 3) 6000 outs() << " Swift 2.0"; 6001 else if(swift_version == 4) 6002 outs() << " Swift 3.0"; 6003 else if(swift_version == 5) 6004 outs() << " Swift 4.0"; 6005 else if(swift_version == 6) 6006 outs() << " Swift 4.1/Swift 4.2"; 6007 else if(swift_version == 7) 6008 outs() << " Swift 5 or later"; 6009 else 6010 outs() << " unknown future Swift version (" << swift_version << ")"; 6011 } 6012 outs() << "\n"; 6013 } 6014 6015 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 6016 uint32_t left, offset, swift_version, p; 6017 struct objc_image_info32 o; 6018 const char *r; 6019 6020 if (S == SectionRef()) 6021 return; 6022 6023 StringRef SectName; 6024 Expected<StringRef> SecNameOrErr = S.getName(); 6025 if (SecNameOrErr) 6026 SectName = *SecNameOrErr; 6027 else 6028 consumeError(SecNameOrErr.takeError()); 6029 6030 DataRefImpl Ref = S.getRawDataRefImpl(); 6031 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6032 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6033 p = S.getAddress(); 6034 r = get_pointer_32(p, offset, left, S, info); 6035 if (r == nullptr) 6036 return; 6037 memset(&o, '\0', sizeof(struct objc_image_info32)); 6038 if (left < sizeof(struct objc_image_info32)) { 6039 memcpy(&o, r, left); 6040 outs() << " (objc_image_info entends past the end of the section)\n"; 6041 } else 6042 memcpy(&o, r, sizeof(struct objc_image_info32)); 6043 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6044 swapStruct(o); 6045 outs() << " version " << o.version << "\n"; 6046 outs() << " flags " << format("0x%" PRIx32, o.flags); 6047 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 6048 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 6049 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 6050 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 6051 swift_version = (o.flags >> 8) & 0xff; 6052 if (swift_version != 0) { 6053 if (swift_version == 1) 6054 outs() << " Swift 1.0"; 6055 else if (swift_version == 2) 6056 outs() << " Swift 1.1"; 6057 else if(swift_version == 3) 6058 outs() << " Swift 2.0"; 6059 else if(swift_version == 4) 6060 outs() << " Swift 3.0"; 6061 else if(swift_version == 5) 6062 outs() << " Swift 4.0"; 6063 else if(swift_version == 6) 6064 outs() << " Swift 4.1/Swift 4.2"; 6065 else if(swift_version == 7) 6066 outs() << " Swift 5 or later"; 6067 else 6068 outs() << " unknown future Swift version (" << swift_version << ")"; 6069 } 6070 outs() << "\n"; 6071 } 6072 6073 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 6074 uint32_t left, offset, p; 6075 struct imageInfo_t o; 6076 const char *r; 6077 6078 StringRef SectName; 6079 Expected<StringRef> SecNameOrErr = S.getName(); 6080 if (SecNameOrErr) 6081 SectName = *SecNameOrErr; 6082 else 6083 consumeError(SecNameOrErr.takeError()); 6084 6085 DataRefImpl Ref = S.getRawDataRefImpl(); 6086 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6087 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6088 p = S.getAddress(); 6089 r = get_pointer_32(p, offset, left, S, info); 6090 if (r == nullptr) 6091 return; 6092 memset(&o, '\0', sizeof(struct imageInfo_t)); 6093 if (left < sizeof(struct imageInfo_t)) { 6094 memcpy(&o, r, left); 6095 outs() << " (imageInfo entends past the end of the section)\n"; 6096 } else 6097 memcpy(&o, r, sizeof(struct imageInfo_t)); 6098 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6099 swapStruct(o); 6100 outs() << " version " << o.version << "\n"; 6101 outs() << " flags " << format("0x%" PRIx32, o.flags); 6102 if (o.flags & 0x1) 6103 outs() << " F&C"; 6104 if (o.flags & 0x2) 6105 outs() << " GC"; 6106 if (o.flags & 0x4) 6107 outs() << " GC-only"; 6108 else 6109 outs() << " RR"; 6110 outs() << "\n"; 6111 } 6112 6113 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 6114 SymbolAddressMap AddrMap; 6115 if (verbose) 6116 CreateSymbolAddressMap(O, &AddrMap); 6117 6118 std::vector<SectionRef> Sections; 6119 for (const SectionRef &Section : O->sections()) 6120 Sections.push_back(Section); 6121 6122 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6123 6124 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6125 if (CL == SectionRef()) 6126 CL = get_section(O, "__DATA", "__objc_classlist"); 6127 if (CL == SectionRef()) 6128 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6129 if (CL == SectionRef()) 6130 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6131 info.S = CL; 6132 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 6133 6134 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6135 if (CR == SectionRef()) 6136 CR = get_section(O, "__DATA", "__objc_classrefs"); 6137 if (CR == SectionRef()) 6138 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6139 if (CR == SectionRef()) 6140 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6141 info.S = CR; 6142 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 6143 6144 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6145 if (SR == SectionRef()) 6146 SR = get_section(O, "__DATA", "__objc_superrefs"); 6147 if (SR == SectionRef()) 6148 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6149 if (SR == SectionRef()) 6150 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6151 info.S = SR; 6152 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 6153 6154 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6155 if (CA == SectionRef()) 6156 CA = get_section(O, "__DATA", "__objc_catlist"); 6157 if (CA == SectionRef()) 6158 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6159 if (CA == SectionRef()) 6160 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6161 info.S = CA; 6162 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 6163 6164 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6165 if (PL == SectionRef()) 6166 PL = get_section(O, "__DATA", "__objc_protolist"); 6167 if (PL == SectionRef()) 6168 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6169 if (PL == SectionRef()) 6170 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6171 info.S = PL; 6172 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 6173 6174 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6175 if (MR == SectionRef()) 6176 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6177 if (MR == SectionRef()) 6178 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6179 if (MR == SectionRef()) 6180 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6181 info.S = MR; 6182 print_message_refs64(MR, &info); 6183 6184 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6185 if (II == SectionRef()) 6186 II = get_section(O, "__DATA", "__objc_imageinfo"); 6187 if (II == SectionRef()) 6188 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6189 if (II == SectionRef()) 6190 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6191 info.S = II; 6192 print_image_info64(II, &info); 6193 } 6194 6195 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6196 SymbolAddressMap AddrMap; 6197 if (verbose) 6198 CreateSymbolAddressMap(O, &AddrMap); 6199 6200 std::vector<SectionRef> Sections; 6201 for (const SectionRef &Section : O->sections()) 6202 Sections.push_back(Section); 6203 6204 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6205 6206 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6207 if (CL == SectionRef()) 6208 CL = get_section(O, "__DATA", "__objc_classlist"); 6209 if (CL == SectionRef()) 6210 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6211 if (CL == SectionRef()) 6212 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6213 info.S = CL; 6214 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 6215 6216 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6217 if (CR == SectionRef()) 6218 CR = get_section(O, "__DATA", "__objc_classrefs"); 6219 if (CR == SectionRef()) 6220 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6221 if (CR == SectionRef()) 6222 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6223 info.S = CR; 6224 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 6225 6226 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6227 if (SR == SectionRef()) 6228 SR = get_section(O, "__DATA", "__objc_superrefs"); 6229 if (SR == SectionRef()) 6230 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6231 if (SR == SectionRef()) 6232 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6233 info.S = SR; 6234 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 6235 6236 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6237 if (CA == SectionRef()) 6238 CA = get_section(O, "__DATA", "__objc_catlist"); 6239 if (CA == SectionRef()) 6240 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6241 if (CA == SectionRef()) 6242 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6243 info.S = CA; 6244 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 6245 6246 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6247 if (PL == SectionRef()) 6248 PL = get_section(O, "__DATA", "__objc_protolist"); 6249 if (PL == SectionRef()) 6250 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6251 if (PL == SectionRef()) 6252 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6253 info.S = PL; 6254 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 6255 6256 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6257 if (MR == SectionRef()) 6258 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6259 if (MR == SectionRef()) 6260 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6261 if (MR == SectionRef()) 6262 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6263 info.S = MR; 6264 print_message_refs32(MR, &info); 6265 6266 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6267 if (II == SectionRef()) 6268 II = get_section(O, "__DATA", "__objc_imageinfo"); 6269 if (II == SectionRef()) 6270 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6271 if (II == SectionRef()) 6272 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6273 info.S = II; 6274 print_image_info32(II, &info); 6275 } 6276 6277 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6278 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 6279 const char *r, *name, *defs; 6280 struct objc_module_t module; 6281 SectionRef S, xS; 6282 struct objc_symtab_t symtab; 6283 struct objc_class_t objc_class; 6284 struct objc_category_t objc_category; 6285 6286 outs() << "Objective-C segment\n"; 6287 S = get_section(O, "__OBJC", "__module_info"); 6288 if (S == SectionRef()) 6289 return false; 6290 6291 SymbolAddressMap AddrMap; 6292 if (verbose) 6293 CreateSymbolAddressMap(O, &AddrMap); 6294 6295 std::vector<SectionRef> Sections; 6296 for (const SectionRef &Section : O->sections()) 6297 Sections.push_back(Section); 6298 6299 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6300 6301 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 6302 p = S.getAddress() + i; 6303 r = get_pointer_32(p, offset, left, S, &info, true); 6304 if (r == nullptr) 6305 return true; 6306 memset(&module, '\0', sizeof(struct objc_module_t)); 6307 if (left < sizeof(struct objc_module_t)) { 6308 memcpy(&module, r, left); 6309 outs() << " (module extends past end of __module_info section)\n"; 6310 } else 6311 memcpy(&module, r, sizeof(struct objc_module_t)); 6312 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6313 swapStruct(module); 6314 6315 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 6316 outs() << " version " << module.version << "\n"; 6317 outs() << " size " << module.size << "\n"; 6318 outs() << " name "; 6319 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 6320 if (name != nullptr) 6321 outs() << format("%.*s", left, name); 6322 else 6323 outs() << format("0x%08" PRIx32, module.name) 6324 << "(not in an __OBJC section)"; 6325 outs() << "\n"; 6326 6327 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 6328 if (module.symtab == 0 || r == nullptr) { 6329 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 6330 << " (not in an __OBJC section)\n"; 6331 continue; 6332 } 6333 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 6334 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 6335 defs_left = 0; 6336 defs = nullptr; 6337 if (left < sizeof(struct objc_symtab_t)) { 6338 memcpy(&symtab, r, left); 6339 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 6340 } else { 6341 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 6342 if (left > sizeof(struct objc_symtab_t)) { 6343 defs_left = left - sizeof(struct objc_symtab_t); 6344 defs = r + sizeof(struct objc_symtab_t); 6345 } 6346 } 6347 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6348 swapStruct(symtab); 6349 6350 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 6351 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 6352 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 6353 if (r == nullptr) 6354 outs() << " (not in an __OBJC section)"; 6355 outs() << "\n"; 6356 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 6357 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 6358 if (symtab.cls_def_cnt > 0) 6359 outs() << "\tClass Definitions\n"; 6360 for (j = 0; j < symtab.cls_def_cnt; j++) { 6361 if ((j + 1) * sizeof(uint32_t) > defs_left) { 6362 outs() << "\t(remaining class defs entries entends past the end of the " 6363 << "section)\n"; 6364 break; 6365 } 6366 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 6367 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6368 sys::swapByteOrder(def); 6369 6370 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6371 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 6372 if (r != nullptr) { 6373 if (left > sizeof(struct objc_class_t)) { 6374 outs() << "\n"; 6375 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6376 } else { 6377 outs() << " (entends past the end of the section)\n"; 6378 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6379 memcpy(&objc_class, r, left); 6380 } 6381 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6382 swapStruct(objc_class); 6383 print_objc_class_t(&objc_class, &info); 6384 } else { 6385 outs() << "(not in an __OBJC section)\n"; 6386 } 6387 6388 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 6389 outs() << "\tMeta Class"; 6390 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 6391 if (r != nullptr) { 6392 if (left > sizeof(struct objc_class_t)) { 6393 outs() << "\n"; 6394 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6395 } else { 6396 outs() << " (entends past the end of the section)\n"; 6397 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6398 memcpy(&objc_class, r, left); 6399 } 6400 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6401 swapStruct(objc_class); 6402 print_objc_class_t(&objc_class, &info); 6403 } else { 6404 outs() << "(not in an __OBJC section)\n"; 6405 } 6406 } 6407 } 6408 if (symtab.cat_def_cnt > 0) 6409 outs() << "\tCategory Definitions\n"; 6410 for (j = 0; j < symtab.cat_def_cnt; j++) { 6411 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 6412 outs() << "\t(remaining category defs entries entends past the end of " 6413 << "the section)\n"; 6414 break; 6415 } 6416 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6417 sizeof(uint32_t)); 6418 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6419 sys::swapByteOrder(def); 6420 6421 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6422 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6423 << format("0x%08" PRIx32, def); 6424 if (r != nullptr) { 6425 if (left > sizeof(struct objc_category_t)) { 6426 outs() << "\n"; 6427 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6428 } else { 6429 outs() << " (entends past the end of the section)\n"; 6430 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6431 memcpy(&objc_category, r, left); 6432 } 6433 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6434 swapStruct(objc_category); 6435 print_objc_objc_category_t(&objc_category, &info); 6436 } else { 6437 outs() << "(not in an __OBJC section)\n"; 6438 } 6439 } 6440 } 6441 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6442 if (II != SectionRef()) 6443 print_image_info(II, &info); 6444 6445 return true; 6446 } 6447 6448 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6449 uint32_t size, uint32_t addr) { 6450 SymbolAddressMap AddrMap; 6451 CreateSymbolAddressMap(O, &AddrMap); 6452 6453 std::vector<SectionRef> Sections; 6454 for (const SectionRef &Section : O->sections()) 6455 Sections.push_back(Section); 6456 6457 struct DisassembleInfo info(O, &AddrMap, &Sections, true); 6458 6459 const char *p; 6460 struct objc_protocol_t protocol; 6461 uint32_t left, paddr; 6462 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6463 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6464 left = size - (p - sect); 6465 if (left < sizeof(struct objc_protocol_t)) { 6466 outs() << "Protocol extends past end of __protocol section\n"; 6467 memcpy(&protocol, p, left); 6468 } else 6469 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6470 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6471 swapStruct(protocol); 6472 paddr = addr + (p - sect); 6473 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6474 if (print_protocol(paddr, 0, &info)) 6475 outs() << "(not in an __OBJC section)\n"; 6476 } 6477 } 6478 6479 #ifdef HAVE_LIBXAR 6480 static inline void swapStruct(struct xar_header &xar) { 6481 sys::swapByteOrder(xar.magic); 6482 sys::swapByteOrder(xar.size); 6483 sys::swapByteOrder(xar.version); 6484 sys::swapByteOrder(xar.toc_length_compressed); 6485 sys::swapByteOrder(xar.toc_length_uncompressed); 6486 sys::swapByteOrder(xar.cksum_alg); 6487 } 6488 6489 static void PrintModeVerbose(uint32_t mode) { 6490 switch(mode & S_IFMT){ 6491 case S_IFDIR: 6492 outs() << "d"; 6493 break; 6494 case S_IFCHR: 6495 outs() << "c"; 6496 break; 6497 case S_IFBLK: 6498 outs() << "b"; 6499 break; 6500 case S_IFREG: 6501 outs() << "-"; 6502 break; 6503 case S_IFLNK: 6504 outs() << "l"; 6505 break; 6506 case S_IFSOCK: 6507 outs() << "s"; 6508 break; 6509 default: 6510 outs() << "?"; 6511 break; 6512 } 6513 6514 /* owner permissions */ 6515 if(mode & S_IREAD) 6516 outs() << "r"; 6517 else 6518 outs() << "-"; 6519 if(mode & S_IWRITE) 6520 outs() << "w"; 6521 else 6522 outs() << "-"; 6523 if(mode & S_ISUID) 6524 outs() << "s"; 6525 else if(mode & S_IEXEC) 6526 outs() << "x"; 6527 else 6528 outs() << "-"; 6529 6530 /* group permissions */ 6531 if(mode & (S_IREAD >> 3)) 6532 outs() << "r"; 6533 else 6534 outs() << "-"; 6535 if(mode & (S_IWRITE >> 3)) 6536 outs() << "w"; 6537 else 6538 outs() << "-"; 6539 if(mode & S_ISGID) 6540 outs() << "s"; 6541 else if(mode & (S_IEXEC >> 3)) 6542 outs() << "x"; 6543 else 6544 outs() << "-"; 6545 6546 /* other permissions */ 6547 if(mode & (S_IREAD >> 6)) 6548 outs() << "r"; 6549 else 6550 outs() << "-"; 6551 if(mode & (S_IWRITE >> 6)) 6552 outs() << "w"; 6553 else 6554 outs() << "-"; 6555 if(mode & S_ISVTX) 6556 outs() << "t"; 6557 else if(mode & (S_IEXEC >> 6)) 6558 outs() << "x"; 6559 else 6560 outs() << "-"; 6561 } 6562 6563 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { 6564 xar_file_t xf; 6565 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; 6566 char *endp; 6567 uint32_t mode_value; 6568 6569 ScopedXarIter xi; 6570 if (!xi) { 6571 WithColor::error(errs(), "llvm-objdump") 6572 << "can't obtain an xar iterator for xar archive " << XarFilename 6573 << "\n"; 6574 return; 6575 } 6576 6577 // Go through the xar's files. 6578 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { 6579 ScopedXarIter xp; 6580 if(!xp){ 6581 WithColor::error(errs(), "llvm-objdump") 6582 << "can't obtain an xar iterator for xar archive " << XarFilename 6583 << "\n"; 6584 return; 6585 } 6586 type = nullptr; 6587 mode = nullptr; 6588 user = nullptr; 6589 group = nullptr; 6590 size = nullptr; 6591 mtime = nullptr; 6592 name = nullptr; 6593 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6594 const char *val = nullptr; 6595 xar_prop_get(xf, key, &val); 6596 #if 0 // Useful for debugging. 6597 outs() << "key: " << key << " value: " << val << "\n"; 6598 #endif 6599 if(strcmp(key, "type") == 0) 6600 type = val; 6601 if(strcmp(key, "mode") == 0) 6602 mode = val; 6603 if(strcmp(key, "user") == 0) 6604 user = val; 6605 if(strcmp(key, "group") == 0) 6606 group = val; 6607 if(strcmp(key, "data/size") == 0) 6608 size = val; 6609 if(strcmp(key, "mtime") == 0) 6610 mtime = val; 6611 if(strcmp(key, "name") == 0) 6612 name = val; 6613 } 6614 if(mode != nullptr){ 6615 mode_value = strtoul(mode, &endp, 8); 6616 if(*endp != '\0') 6617 outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; 6618 if(strcmp(type, "file") == 0) 6619 mode_value |= S_IFREG; 6620 PrintModeVerbose(mode_value); 6621 outs() << " "; 6622 } 6623 if(user != nullptr) 6624 outs() << format("%10s/", user); 6625 if(group != nullptr) 6626 outs() << format("%-10s ", group); 6627 if(size != nullptr) 6628 outs() << format("%7s ", size); 6629 if(mtime != nullptr){ 6630 for(m = mtime; *m != 'T' && *m != '\0'; m++) 6631 outs() << *m; 6632 if(*m == 'T') 6633 m++; 6634 outs() << " "; 6635 for( ; *m != 'Z' && *m != '\0'; m++) 6636 outs() << *m; 6637 outs() << " "; 6638 } 6639 if(name != nullptr) 6640 outs() << name; 6641 outs() << "\n"; 6642 } 6643 } 6644 6645 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 6646 uint32_t size, bool verbose, 6647 bool PrintXarHeader, bool PrintXarFileHeaders, 6648 std::string XarMemberName) { 6649 if(size < sizeof(struct xar_header)) { 6650 outs() << "size of (__LLVM,__bundle) section too small (smaller than size " 6651 "of struct xar_header)\n"; 6652 return; 6653 } 6654 struct xar_header XarHeader; 6655 memcpy(&XarHeader, sect, sizeof(struct xar_header)); 6656 if (sys::IsLittleEndianHost) 6657 swapStruct(XarHeader); 6658 if (PrintXarHeader) { 6659 if (!XarMemberName.empty()) 6660 outs() << "In xar member " << XarMemberName << ": "; 6661 else 6662 outs() << "For (__LLVM,__bundle) section: "; 6663 outs() << "xar header\n"; 6664 if (XarHeader.magic == XAR_HEADER_MAGIC) 6665 outs() << " magic XAR_HEADER_MAGIC\n"; 6666 else 6667 outs() << " magic " 6668 << format_hex(XarHeader.magic, 10, true) 6669 << " (not XAR_HEADER_MAGIC)\n"; 6670 outs() << " size " << XarHeader.size << "\n"; 6671 outs() << " version " << XarHeader.version << "\n"; 6672 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed 6673 << "\n"; 6674 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed 6675 << "\n"; 6676 outs() << " cksum_alg "; 6677 switch (XarHeader.cksum_alg) { 6678 case XAR_CKSUM_NONE: 6679 outs() << "XAR_CKSUM_NONE\n"; 6680 break; 6681 case XAR_CKSUM_SHA1: 6682 outs() << "XAR_CKSUM_SHA1\n"; 6683 break; 6684 case XAR_CKSUM_MD5: 6685 outs() << "XAR_CKSUM_MD5\n"; 6686 break; 6687 #ifdef XAR_CKSUM_SHA256 6688 case XAR_CKSUM_SHA256: 6689 outs() << "XAR_CKSUM_SHA256\n"; 6690 break; 6691 #endif 6692 #ifdef XAR_CKSUM_SHA512 6693 case XAR_CKSUM_SHA512: 6694 outs() << "XAR_CKSUM_SHA512\n"; 6695 break; 6696 #endif 6697 default: 6698 outs() << XarHeader.cksum_alg << "\n"; 6699 } 6700 } 6701 6702 SmallString<128> XarFilename; 6703 int FD; 6704 std::error_code XarEC = 6705 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); 6706 if (XarEC) { 6707 WithColor::error(errs(), "llvm-objdump") << XarEC.message() << "\n"; 6708 return; 6709 } 6710 ToolOutputFile XarFile(XarFilename, FD); 6711 raw_fd_ostream &XarOut = XarFile.os(); 6712 StringRef XarContents(sect, size); 6713 XarOut << XarContents; 6714 XarOut.close(); 6715 if (XarOut.has_error()) 6716 return; 6717 6718 ScopedXarFile xar(XarFilename.c_str(), READ); 6719 if (!xar) { 6720 WithColor::error(errs(), "llvm-objdump") 6721 << "can't create temporary xar archive " << XarFilename << "\n"; 6722 return; 6723 } 6724 6725 SmallString<128> TocFilename; 6726 std::error_code TocEC = 6727 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); 6728 if (TocEC) { 6729 WithColor::error(errs(), "llvm-objdump") << TocEC.message() << "\n"; 6730 return; 6731 } 6732 xar_serialize(xar, TocFilename.c_str()); 6733 6734 if (PrintXarFileHeaders) { 6735 if (!XarMemberName.empty()) 6736 outs() << "In xar member " << XarMemberName << ": "; 6737 else 6738 outs() << "For (__LLVM,__bundle) section: "; 6739 outs() << "xar archive files:\n"; 6740 PrintXarFilesSummary(XarFilename.c_str(), xar); 6741 } 6742 6743 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 6744 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); 6745 if (std::error_code EC = FileOrErr.getError()) { 6746 WithColor::error(errs(), "llvm-objdump") << EC.message() << "\n"; 6747 return; 6748 } 6749 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 6750 6751 if (!XarMemberName.empty()) 6752 outs() << "In xar member " << XarMemberName << ": "; 6753 else 6754 outs() << "For (__LLVM,__bundle) section: "; 6755 outs() << "xar table of contents:\n"; 6756 outs() << Buffer->getBuffer() << "\n"; 6757 6758 // TODO: Go through the xar's files. 6759 ScopedXarIter xi; 6760 if(!xi){ 6761 WithColor::error(errs(), "llvm-objdump") 6762 << "can't obtain an xar iterator for xar archive " 6763 << XarFilename.c_str() << "\n"; 6764 return; 6765 } 6766 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ 6767 const char *key; 6768 const char *member_name, *member_type, *member_size_string; 6769 size_t member_size; 6770 6771 ScopedXarIter xp; 6772 if(!xp){ 6773 WithColor::error(errs(), "llvm-objdump") 6774 << "can't obtain an xar iterator for xar archive " 6775 << XarFilename.c_str() << "\n"; 6776 return; 6777 } 6778 member_name = NULL; 6779 member_type = NULL; 6780 member_size_string = NULL; 6781 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6782 const char *val = nullptr; 6783 xar_prop_get(xf, key, &val); 6784 #if 0 // Useful for debugging. 6785 outs() << "key: " << key << " value: " << val << "\n"; 6786 #endif 6787 if (strcmp(key, "name") == 0) 6788 member_name = val; 6789 if (strcmp(key, "type") == 0) 6790 member_type = val; 6791 if (strcmp(key, "data/size") == 0) 6792 member_size_string = val; 6793 } 6794 /* 6795 * If we find a file with a name, date/size and type properties 6796 * and with the type being "file" see if that is a xar file. 6797 */ 6798 if (member_name != NULL && member_type != NULL && 6799 strcmp(member_type, "file") == 0 && 6800 member_size_string != NULL){ 6801 // Extract the file into a buffer. 6802 char *endptr; 6803 member_size = strtoul(member_size_string, &endptr, 10); 6804 if (*endptr == '\0' && member_size != 0) { 6805 char *buffer; 6806 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { 6807 #if 0 // Useful for debugging. 6808 outs() << "xar member: " << member_name << " extracted\n"; 6809 #endif 6810 // Set the XarMemberName we want to see printed in the header. 6811 std::string OldXarMemberName; 6812 // If XarMemberName is already set this is nested. So 6813 // save the old name and create the nested name. 6814 if (!XarMemberName.empty()) { 6815 OldXarMemberName = XarMemberName; 6816 XarMemberName = 6817 (Twine("[") + XarMemberName + "]" + member_name).str(); 6818 } else { 6819 OldXarMemberName = ""; 6820 XarMemberName = member_name; 6821 } 6822 // See if this is could be a xar file (nested). 6823 if (member_size >= sizeof(struct xar_header)) { 6824 #if 0 // Useful for debugging. 6825 outs() << "could be a xar file: " << member_name << "\n"; 6826 #endif 6827 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); 6828 if (sys::IsLittleEndianHost) 6829 swapStruct(XarHeader); 6830 if (XarHeader.magic == XAR_HEADER_MAGIC) 6831 DumpBitcodeSection(O, buffer, member_size, verbose, 6832 PrintXarHeader, PrintXarFileHeaders, 6833 XarMemberName); 6834 } 6835 XarMemberName = OldXarMemberName; 6836 delete buffer; 6837 } 6838 } 6839 } 6840 } 6841 } 6842 #endif // defined(HAVE_LIBXAR) 6843 6844 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6845 if (O->is64Bit()) 6846 printObjc2_64bit_MetaData(O, verbose); 6847 else { 6848 MachO::mach_header H; 6849 H = O->getHeader(); 6850 if (H.cputype == MachO::CPU_TYPE_ARM) 6851 printObjc2_32bit_MetaData(O, verbose); 6852 else { 6853 // This is the 32-bit non-arm cputype case. Which is normally 6854 // the first Objective-C ABI. But it may be the case of a 6855 // binary for the iOS simulator which is the second Objective-C 6856 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6857 // and return false. 6858 if (!printObjc1_32bit_MetaData(O, verbose)) 6859 printObjc2_32bit_MetaData(O, verbose); 6860 } 6861 } 6862 } 6863 6864 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6865 // for the address passed in as ReferenceValue for printing as a comment with 6866 // the instruction and also returns the corresponding type of that item 6867 // indirectly through ReferenceType. 6868 // 6869 // If ReferenceValue is an address of literal cstring then a pointer to the 6870 // cstring is returned and ReferenceType is set to 6871 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6872 // 6873 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6874 // Class ref that name is returned and the ReferenceType is set accordingly. 6875 // 6876 // Lastly, literals which are Symbol address in a literal pool are looked for 6877 // and if found the symbol name is returned and ReferenceType is set to 6878 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6879 // 6880 // If there is no item in the Mach-O file for the address passed in as 6881 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6882 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6883 uint64_t ReferencePC, 6884 uint64_t *ReferenceType, 6885 struct DisassembleInfo *info) { 6886 // First see if there is an external relocation entry at the ReferencePC. 6887 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6888 uint64_t sect_addr = info->S.getAddress(); 6889 uint64_t sect_offset = ReferencePC - sect_addr; 6890 bool reloc_found = false; 6891 DataRefImpl Rel; 6892 MachO::any_relocation_info RE; 6893 bool isExtern = false; 6894 SymbolRef Symbol; 6895 for (const RelocationRef &Reloc : info->S.relocations()) { 6896 uint64_t RelocOffset = Reloc.getOffset(); 6897 if (RelocOffset == sect_offset) { 6898 Rel = Reloc.getRawDataRefImpl(); 6899 RE = info->O->getRelocation(Rel); 6900 if (info->O->isRelocationScattered(RE)) 6901 continue; 6902 isExtern = info->O->getPlainRelocationExternal(RE); 6903 if (isExtern) { 6904 symbol_iterator RelocSym = Reloc.getSymbol(); 6905 Symbol = *RelocSym; 6906 } 6907 reloc_found = true; 6908 break; 6909 } 6910 } 6911 // If there is an external relocation entry for a symbol in a section 6912 // then used that symbol's value for the value of the reference. 6913 if (reloc_found && isExtern) { 6914 if (info->O->getAnyRelocationPCRel(RE)) { 6915 unsigned Type = info->O->getAnyRelocationType(RE); 6916 if (Type == MachO::X86_64_RELOC_SIGNED) { 6917 ReferenceValue = cantFail(Symbol.getValue()); 6918 } 6919 } 6920 } 6921 } 6922 6923 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6924 // Message refs and Class refs. 6925 bool classref, selref, msgref, cfstring; 6926 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6927 selref, msgref, cfstring); 6928 if (classref && pointer_value == 0) { 6929 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6930 // And the pointer_value in that section is typically zero as it will be 6931 // set by dyld as part of the "bind information". 6932 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6933 if (name != nullptr) { 6934 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6935 const char *class_name = strrchr(name, '$'); 6936 if (class_name != nullptr && class_name[1] == '_' && 6937 class_name[2] != '\0') { 6938 info->class_name = class_name + 2; 6939 return name; 6940 } 6941 } 6942 } 6943 6944 if (classref) { 6945 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6946 const char *name = 6947 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6948 if (name != nullptr) 6949 info->class_name = name; 6950 else 6951 name = "bad class ref"; 6952 return name; 6953 } 6954 6955 if (cfstring) { 6956 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6957 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6958 return name; 6959 } 6960 6961 if (selref && pointer_value == 0) 6962 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6963 6964 if (pointer_value != 0) 6965 ReferenceValue = pointer_value; 6966 6967 const char *name = GuessCstringPointer(ReferenceValue, info); 6968 if (name) { 6969 if (pointer_value != 0 && selref) { 6970 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6971 info->selector_name = name; 6972 } else if (pointer_value != 0 && msgref) { 6973 info->class_name = nullptr; 6974 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6975 info->selector_name = name; 6976 } else 6977 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6978 return name; 6979 } 6980 6981 // Lastly look for an indirect symbol with this ReferenceValue which is in 6982 // a literal pool. If found return that symbol name. 6983 name = GuessIndirectSymbol(ReferenceValue, info); 6984 if (name) { 6985 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6986 return name; 6987 } 6988 6989 return nullptr; 6990 } 6991 6992 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6993 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6994 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6995 // is created and returns the symbol name that matches the ReferenceValue or 6996 // nullptr if none. The ReferenceType is passed in for the IN type of 6997 // reference the instruction is making from the values in defined in the header 6998 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6999 // Out type and the ReferenceName will also be set which is added as a comment 7000 // to the disassembled instruction. 7001 // 7002 // If the symbol name is a C++ mangled name then the demangled name is 7003 // returned through ReferenceName and ReferenceType is set to 7004 // LLVMDisassembler_ReferenceType_DeMangled_Name . 7005 // 7006 // When this is called to get a symbol name for a branch target then the 7007 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 7008 // SymbolValue will be looked for in the indirect symbol table to determine if 7009 // it is an address for a symbol stub. If so then the symbol name for that 7010 // stub is returned indirectly through ReferenceName and then ReferenceType is 7011 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 7012 // 7013 // When this is called with an value loaded via a PC relative load then 7014 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 7015 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 7016 // or an Objective-C meta data reference. If so the output ReferenceType is 7017 // set to correspond to that as well as setting the ReferenceName. 7018 static const char *SymbolizerSymbolLookUp(void *DisInfo, 7019 uint64_t ReferenceValue, 7020 uint64_t *ReferenceType, 7021 uint64_t ReferencePC, 7022 const char **ReferenceName) { 7023 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 7024 // If no verbose symbolic information is wanted then just return nullptr. 7025 if (!info->verbose) { 7026 *ReferenceName = nullptr; 7027 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7028 return nullptr; 7029 } 7030 7031 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 7032 7033 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 7034 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 7035 if (*ReferenceName != nullptr) { 7036 method_reference(info, ReferenceType, ReferenceName); 7037 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 7038 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 7039 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 7040 if (info->demangled_name != nullptr) 7041 free(info->demangled_name); 7042 int status; 7043 info->demangled_name = 7044 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 7045 if (info->demangled_name != nullptr) { 7046 *ReferenceName = info->demangled_name; 7047 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 7048 } else 7049 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7050 } else 7051 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7052 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 7053 *ReferenceName = 7054 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7055 if (*ReferenceName) 7056 method_reference(info, ReferenceType, ReferenceName); 7057 else 7058 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7059 // If this is arm64 and the reference is an adrp instruction save the 7060 // instruction, passed in ReferenceValue and the address of the instruction 7061 // for use later if we see and add immediate instruction. 7062 } else if (info->O->getArch() == Triple::aarch64 && 7063 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 7064 info->adrp_inst = ReferenceValue; 7065 info->adrp_addr = ReferencePC; 7066 SymbolName = nullptr; 7067 *ReferenceName = nullptr; 7068 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7069 // If this is arm64 and reference is an add immediate instruction and we 7070 // have 7071 // seen an adrp instruction just before it and the adrp's Xd register 7072 // matches 7073 // this add's Xn register reconstruct the value being referenced and look to 7074 // see if it is a literal pointer. Note the add immediate instruction is 7075 // passed in ReferenceValue. 7076 } else if (info->O->getArch() == Triple::aarch64 && 7077 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 7078 ReferencePC - 4 == info->adrp_addr && 7079 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7080 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7081 uint32_t addxri_inst; 7082 uint64_t adrp_imm, addxri_imm; 7083 7084 adrp_imm = 7085 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7086 if (info->adrp_inst & 0x0200000) 7087 adrp_imm |= 0xfffffffffc000000LL; 7088 7089 addxri_inst = ReferenceValue; 7090 addxri_imm = (addxri_inst >> 10) & 0xfff; 7091 if (((addxri_inst >> 22) & 0x3) == 1) 7092 addxri_imm <<= 12; 7093 7094 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7095 (adrp_imm << 12) + addxri_imm; 7096 7097 *ReferenceName = 7098 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7099 if (*ReferenceName == nullptr) 7100 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7101 // If this is arm64 and the reference is a load register instruction and we 7102 // have seen an adrp instruction just before it and the adrp's Xd register 7103 // matches this add's Xn register reconstruct the value being referenced and 7104 // look to see if it is a literal pointer. Note the load register 7105 // instruction is passed in ReferenceValue. 7106 } else if (info->O->getArch() == Triple::aarch64 && 7107 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 7108 ReferencePC - 4 == info->adrp_addr && 7109 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7110 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7111 uint32_t ldrxui_inst; 7112 uint64_t adrp_imm, ldrxui_imm; 7113 7114 adrp_imm = 7115 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7116 if (info->adrp_inst & 0x0200000) 7117 adrp_imm |= 0xfffffffffc000000LL; 7118 7119 ldrxui_inst = ReferenceValue; 7120 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 7121 7122 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7123 (adrp_imm << 12) + (ldrxui_imm << 3); 7124 7125 *ReferenceName = 7126 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7127 if (*ReferenceName == nullptr) 7128 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7129 } 7130 // If this arm64 and is an load register (PC-relative) instruction the 7131 // ReferenceValue is the PC plus the immediate value. 7132 else if (info->O->getArch() == Triple::aarch64 && 7133 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 7134 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 7135 *ReferenceName = 7136 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7137 if (*ReferenceName == nullptr) 7138 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7139 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 7140 if (info->demangled_name != nullptr) 7141 free(info->demangled_name); 7142 int status; 7143 info->demangled_name = 7144 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 7145 if (info->demangled_name != nullptr) { 7146 *ReferenceName = info->demangled_name; 7147 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 7148 } 7149 } 7150 else { 7151 *ReferenceName = nullptr; 7152 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7153 } 7154 7155 return SymbolName; 7156 } 7157 7158 /// Emits the comments that are stored in the CommentStream. 7159 /// Each comment in the CommentStream must end with a newline. 7160 static void emitComments(raw_svector_ostream &CommentStream, 7161 SmallString<128> &CommentsToEmit, 7162 formatted_raw_ostream &FormattedOS, 7163 const MCAsmInfo &MAI) { 7164 // Flush the stream before taking its content. 7165 StringRef Comments = CommentsToEmit.str(); 7166 // Get the default information for printing a comment. 7167 StringRef CommentBegin = MAI.getCommentString(); 7168 unsigned CommentColumn = MAI.getCommentColumn(); 7169 bool IsFirst = true; 7170 while (!Comments.empty()) { 7171 if (!IsFirst) 7172 FormattedOS << '\n'; 7173 // Emit a line of comments. 7174 FormattedOS.PadToColumn(CommentColumn); 7175 size_t Position = Comments.find('\n'); 7176 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 7177 // Move after the newline character. 7178 Comments = Comments.substr(Position + 1); 7179 IsFirst = false; 7180 } 7181 FormattedOS.flush(); 7182 7183 // Tell the comment stream that the vector changed underneath it. 7184 CommentsToEmit.clear(); 7185 } 7186 7187 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 7188 StringRef DisSegName, StringRef DisSectName) { 7189 const char *McpuDefault = nullptr; 7190 const Target *ThumbTarget = nullptr; 7191 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 7192 if (!TheTarget) { 7193 // GetTarget prints out stuff. 7194 return; 7195 } 7196 std::string MachOMCPU; 7197 if (MCPU.empty() && McpuDefault) 7198 MachOMCPU = McpuDefault; 7199 else 7200 MachOMCPU = MCPU; 7201 7202 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 7203 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 7204 if (ThumbTarget) 7205 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 7206 7207 // Package up features to be passed to target/subtarget 7208 std::string FeaturesStr; 7209 if (!MAttrs.empty()) { 7210 SubtargetFeatures Features; 7211 for (unsigned i = 0; i != MAttrs.size(); ++i) 7212 Features.AddFeature(MAttrs[i]); 7213 FeaturesStr = Features.getString(); 7214 } 7215 7216 MCTargetOptions MCOptions; 7217 // Set up disassembler. 7218 std::unique_ptr<const MCRegisterInfo> MRI( 7219 TheTarget->createMCRegInfo(TripleName)); 7220 std::unique_ptr<const MCAsmInfo> AsmInfo( 7221 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 7222 std::unique_ptr<const MCSubtargetInfo> STI( 7223 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 7224 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 7225 std::unique_ptr<MCDisassembler> DisAsm( 7226 TheTarget->createMCDisassembler(*STI, Ctx)); 7227 std::unique_ptr<MCSymbolizer> Symbolizer; 7228 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false); 7229 std::unique_ptr<MCRelocationInfo> RelInfo( 7230 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 7231 if (RelInfo) { 7232 Symbolizer.reset(TheTarget->createMCSymbolizer( 7233 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7234 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 7235 DisAsm->setSymbolizer(std::move(Symbolizer)); 7236 } 7237 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 7238 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 7239 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 7240 // Set the display preference for hex vs. decimal immediates. 7241 IP->setPrintImmHex(PrintImmHex); 7242 // Comment stream and backing vector. 7243 SmallString<128> CommentsToEmit; 7244 raw_svector_ostream CommentStream(CommentsToEmit); 7245 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 7246 // if it is done then arm64 comments for string literals don't get printed 7247 // and some constant get printed instead and not setting it causes intel 7248 // (32-bit and 64-bit) comments printed with different spacing before the 7249 // comment causing different diffs with the 'C' disassembler library API. 7250 // IP->setCommentStream(CommentStream); 7251 7252 if (!AsmInfo || !STI || !DisAsm || !IP) { 7253 WithColor::error(errs(), "llvm-objdump") 7254 << "couldn't initialize disassembler for target " << TripleName << '\n'; 7255 return; 7256 } 7257 7258 // Set up separate thumb disassembler if needed. 7259 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 7260 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 7261 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 7262 std::unique_ptr<MCDisassembler> ThumbDisAsm; 7263 std::unique_ptr<MCInstPrinter> ThumbIP; 7264 std::unique_ptr<MCContext> ThumbCtx; 7265 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 7266 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false); 7267 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 7268 if (ThumbTarget) { 7269 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 7270 ThumbAsmInfo.reset( 7271 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions)); 7272 ThumbSTI.reset( 7273 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 7274 FeaturesStr)); 7275 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 7276 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 7277 MCContext *PtrThumbCtx = ThumbCtx.get(); 7278 ThumbRelInfo.reset( 7279 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 7280 if (ThumbRelInfo) { 7281 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 7282 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7283 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 7284 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 7285 } 7286 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 7287 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 7288 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 7289 *ThumbInstrInfo, *ThumbMRI)); 7290 // Set the display preference for hex vs. decimal immediates. 7291 ThumbIP->setPrintImmHex(PrintImmHex); 7292 } 7293 7294 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) { 7295 WithColor::error(errs(), "llvm-objdump") 7296 << "couldn't initialize disassembler for target " << ThumbTripleName 7297 << '\n'; 7298 return; 7299 } 7300 7301 MachO::mach_header Header = MachOOF->getHeader(); 7302 7303 // FIXME: Using the -cfg command line option, this code used to be able to 7304 // annotate relocations with the referenced symbol's name, and if this was 7305 // inside a __[cf]string section, the data it points to. This is now replaced 7306 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 7307 std::vector<SectionRef> Sections; 7308 std::vector<SymbolRef> Symbols; 7309 SmallVector<uint64_t, 8> FoundFns; 7310 uint64_t BaseSegmentAddress = 0; 7311 7312 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 7313 BaseSegmentAddress); 7314 7315 // Sort the symbols by address, just in case they didn't come in that way. 7316 llvm::sort(Symbols, SymbolSorter()); 7317 7318 // Build a data in code table that is sorted on by the address of each entry. 7319 uint64_t BaseAddress = 0; 7320 if (Header.filetype == MachO::MH_OBJECT) 7321 BaseAddress = Sections[0].getAddress(); 7322 else 7323 BaseAddress = BaseSegmentAddress; 7324 DiceTable Dices; 7325 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 7326 DI != DE; ++DI) { 7327 uint32_t Offset; 7328 DI->getOffset(Offset); 7329 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 7330 } 7331 array_pod_sort(Dices.begin(), Dices.end()); 7332 7333 // Try to find debug info and set up the DIContext for it. 7334 std::unique_ptr<DIContext> diContext; 7335 std::unique_ptr<Binary> DSYMBinary; 7336 std::unique_ptr<MemoryBuffer> DSYMBuf; 7337 if (UseDbg) { 7338 ObjectFile *DbgObj = MachOOF; 7339 7340 // A separate DSym file path was specified, parse it as a macho file, 7341 // get the sections and supply it to the section name parsing machinery. 7342 if (!DSYMFile.empty()) { 7343 std::string DSYMPath(DSYMFile); 7344 7345 // If DSYMPath is a .dSYM directory, append the Mach-O file. 7346 if (llvm::sys::fs::is_directory(DSYMPath) && 7347 llvm::sys::path::extension(DSYMPath) == ".dSYM") { 7348 SmallString<128> ShortName(llvm::sys::path::filename(DSYMPath)); 7349 llvm::sys::path::replace_extension(ShortName, ""); 7350 SmallString<1024> FullPath(DSYMPath); 7351 llvm::sys::path::append(FullPath, "Contents", "Resources", "DWARF", 7352 ShortName); 7353 DSYMPath = std::string(FullPath.str()); 7354 } 7355 7356 // Load the file. 7357 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 7358 MemoryBuffer::getFileOrSTDIN(DSYMPath); 7359 if (std::error_code EC = BufOrErr.getError()) { 7360 reportError(errorCodeToError(EC), DSYMPath); 7361 return; 7362 } 7363 7364 // We need to keep the file alive, because we're replacing DbgObj with it. 7365 DSYMBuf = std::move(BufOrErr.get()); 7366 7367 Expected<std::unique_ptr<Binary>> BinaryOrErr = 7368 createBinary(DSYMBuf.get()->getMemBufferRef()); 7369 if (!BinaryOrErr) { 7370 reportError(BinaryOrErr.takeError(), DSYMPath); 7371 return; 7372 } 7373 7374 // We need to keep the Binary alive with the buffer 7375 DSYMBinary = std::move(BinaryOrErr.get()); 7376 if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) { 7377 // this is a Mach-O object file, use it 7378 if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) { 7379 DbgObj = MachDSYM; 7380 } 7381 else { 7382 WithColor::error(errs(), "llvm-objdump") 7383 << DSYMPath << " is not a Mach-O file type.\n"; 7384 return; 7385 } 7386 } 7387 else if (auto UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())){ 7388 // this is a Universal Binary, find a Mach-O for this architecture 7389 uint32_t CPUType, CPUSubType; 7390 const char *ArchFlag; 7391 if (MachOOF->is64Bit()) { 7392 const MachO::mach_header_64 H_64 = MachOOF->getHeader64(); 7393 CPUType = H_64.cputype; 7394 CPUSubType = H_64.cpusubtype; 7395 } else { 7396 const MachO::mach_header H = MachOOF->getHeader(); 7397 CPUType = H.cputype; 7398 CPUSubType = H.cpusubtype; 7399 } 7400 Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr, 7401 &ArchFlag); 7402 Expected<std::unique_ptr<MachOObjectFile>> MachDSYM = 7403 UB->getMachOObjectForArch(ArchFlag); 7404 if (!MachDSYM) { 7405 reportError(MachDSYM.takeError(), DSYMPath); 7406 return; 7407 } 7408 7409 // We need to keep the Binary alive with the buffer 7410 DbgObj = &*MachDSYM.get(); 7411 DSYMBinary = std::move(*MachDSYM); 7412 } 7413 else { 7414 WithColor::error(errs(), "llvm-objdump") 7415 << DSYMPath << " is not a Mach-O or Universal file type.\n"; 7416 return; 7417 } 7418 } 7419 7420 // Setup the DIContext 7421 diContext = DWARFContext::create(*DbgObj); 7422 } 7423 7424 if (FilterSections.empty()) 7425 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 7426 7427 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 7428 Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName(); 7429 if (!SecNameOrErr) { 7430 consumeError(SecNameOrErr.takeError()); 7431 continue; 7432 } 7433 if (*SecNameOrErr != DisSectName) 7434 continue; 7435 7436 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 7437 7438 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 7439 if (SegmentName != DisSegName) 7440 continue; 7441 7442 StringRef BytesStr = 7443 unwrapOrError(Sections[SectIdx].getContents(), Filename); 7444 ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr); 7445 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7446 7447 bool symbolTableWorked = false; 7448 7449 // Create a map of symbol addresses to symbol names for use by 7450 // the SymbolizerSymbolLookUp() routine. 7451 SymbolAddressMap AddrMap; 7452 bool DisSymNameFound = false; 7453 for (const SymbolRef &Symbol : MachOOF->symbols()) { 7454 SymbolRef::Type ST = 7455 unwrapOrError(Symbol.getType(), MachOOF->getFileName()); 7456 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 7457 ST == SymbolRef::ST_Other) { 7458 uint64_t Address = cantFail(Symbol.getValue()); 7459 StringRef SymName = 7460 unwrapOrError(Symbol.getName(), MachOOF->getFileName()); 7461 AddrMap[Address] = SymName; 7462 if (!DisSymName.empty() && DisSymName == SymName) 7463 DisSymNameFound = true; 7464 } 7465 } 7466 if (!DisSymName.empty() && !DisSymNameFound) { 7467 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 7468 return; 7469 } 7470 // Set up the block of info used by the Symbolizer call backs. 7471 SymbolizerInfo.verbose = !NoSymbolicOperands; 7472 SymbolizerInfo.O = MachOOF; 7473 SymbolizerInfo.S = Sections[SectIdx]; 7474 SymbolizerInfo.AddrMap = &AddrMap; 7475 SymbolizerInfo.Sections = &Sections; 7476 // Same for the ThumbSymbolizer 7477 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands; 7478 ThumbSymbolizerInfo.O = MachOOF; 7479 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7480 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7481 ThumbSymbolizerInfo.Sections = &Sections; 7482 7483 unsigned int Arch = MachOOF->getArch(); 7484 7485 // Skip all symbols if this is a stubs file. 7486 if (Bytes.empty()) 7487 return; 7488 7489 // If the section has symbols but no symbol at the start of the section 7490 // these are used to make sure the bytes before the first symbol are 7491 // disassembled. 7492 bool FirstSymbol = true; 7493 bool FirstSymbolAtSectionStart = true; 7494 7495 // Disassemble symbol by symbol. 7496 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7497 StringRef SymName = 7498 unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName()); 7499 SymbolRef::Type ST = 7500 unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName()); 7501 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7502 continue; 7503 7504 // Make sure the symbol is defined in this section. 7505 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7506 if (!containsSym) { 7507 if (!DisSymName.empty() && DisSymName == SymName) { 7508 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7509 return; 7510 } 7511 continue; 7512 } 7513 // The __mh_execute_header is special and we need to deal with that fact 7514 // this symbol is before the start of the (__TEXT,__text) section and at the 7515 // address of the start of the __TEXT segment. This is because this symbol 7516 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7517 // start of the section in a standard MH_EXECUTE filetype. 7518 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7519 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7520 return; 7521 } 7522 // When this code is trying to disassemble a symbol at a time and in the 7523 // case there is only the __mh_execute_header symbol left as in a stripped 7524 // executable, we need to deal with this by ignoring this symbol so the 7525 // whole section is disassembled and this symbol is then not displayed. 7526 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7527 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7528 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7529 continue; 7530 7531 // If we are only disassembling one symbol see if this is that symbol. 7532 if (!DisSymName.empty() && DisSymName != SymName) 7533 continue; 7534 7535 // Start at the address of the symbol relative to the section's address. 7536 uint64_t SectSize = Sections[SectIdx].getSize(); 7537 uint64_t Start = cantFail(Symbols[SymIdx].getValue()); 7538 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7539 Start -= SectionAddress; 7540 7541 if (Start > SectSize) { 7542 outs() << "section data ends, " << SymName 7543 << " lies outside valid range\n"; 7544 return; 7545 } 7546 7547 // Stop disassembling either at the beginning of the next symbol or at 7548 // the end of the section. 7549 bool containsNextSym = false; 7550 uint64_t NextSym = 0; 7551 uint64_t NextSymIdx = SymIdx + 1; 7552 while (Symbols.size() > NextSymIdx) { 7553 SymbolRef::Type NextSymType = unwrapOrError( 7554 Symbols[NextSymIdx].getType(), MachOOF->getFileName()); 7555 if (NextSymType == SymbolRef::ST_Function) { 7556 containsNextSym = 7557 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7558 NextSym = cantFail(Symbols[NextSymIdx].getValue()); 7559 NextSym -= SectionAddress; 7560 break; 7561 } 7562 ++NextSymIdx; 7563 } 7564 7565 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7566 uint64_t Size; 7567 7568 symbolTableWorked = true; 7569 7570 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7571 uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb)); 7572 bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb; 7573 7574 // We only need the dedicated Thumb target if there's a real choice 7575 // (i.e. we're not targeting M-class) and the function is Thumb. 7576 bool UseThumbTarget = IsThumb && ThumbTarget; 7577 7578 // If we are not specifying a symbol to start disassembly with and this 7579 // is the first symbol in the section but not at the start of the section 7580 // then move the disassembly index to the start of the section and 7581 // don't print the symbol name just yet. This is so the bytes before the 7582 // first symbol are disassembled. 7583 uint64_t SymbolStart = Start; 7584 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7585 FirstSymbolAtSectionStart = false; 7586 Start = 0; 7587 } 7588 else 7589 outs() << SymName << ":\n"; 7590 7591 DILineInfo lastLine; 7592 for (uint64_t Index = Start; Index < End; Index += Size) { 7593 MCInst Inst; 7594 7595 // If this is the first symbol in the section and it was not at the 7596 // start of the section, see if we are at its Index now and if so print 7597 // the symbol name. 7598 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7599 outs() << SymName << ":\n"; 7600 7601 uint64_t PC = SectAddress + Index; 7602 if (!NoLeadingAddr) { 7603 if (FullLeadingAddr) { 7604 if (MachOOF->is64Bit()) 7605 outs() << format("%016" PRIx64, PC); 7606 else 7607 outs() << format("%08" PRIx64, PC); 7608 } else { 7609 outs() << format("%8" PRIx64 ":", PC); 7610 } 7611 } 7612 if (!NoShowRawInsn || Arch == Triple::arm) 7613 outs() << "\t"; 7614 7615 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size)) 7616 continue; 7617 7618 SmallVector<char, 64> AnnotationsBytes; 7619 raw_svector_ostream Annotations(AnnotationsBytes); 7620 7621 bool gotInst; 7622 if (UseThumbTarget) 7623 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7624 PC, Annotations); 7625 else 7626 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7627 Annotations); 7628 if (gotInst) { 7629 if (!NoShowRawInsn || Arch == Triple::arm) { 7630 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); 7631 } 7632 formatted_raw_ostream FormattedOS(outs()); 7633 StringRef AnnotationsStr = Annotations.str(); 7634 if (UseThumbTarget) 7635 ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI, 7636 FormattedOS); 7637 else 7638 IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS); 7639 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7640 7641 // Print debug info. 7642 if (diContext) { 7643 DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx}); 7644 // Print valid line info if it changed. 7645 if (dli != lastLine && dli.Line != 0) 7646 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7647 << dli.Column; 7648 lastLine = dli; 7649 } 7650 outs() << "\n"; 7651 } else { 7652 if (MachOOF->getArchTriple().isX86()) { 7653 outs() << format("\t.byte 0x%02x #bad opcode\n", 7654 *(Bytes.data() + Index) & 0xff); 7655 Size = 1; // skip exactly one illegible byte and move on. 7656 } else if (Arch == Triple::aarch64 || 7657 (Arch == Triple::arm && !IsThumb)) { 7658 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7659 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7660 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7661 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7662 outs() << format("\t.long\t0x%08x\n", opcode); 7663 Size = 4; 7664 } else if (Arch == Triple::arm) { 7665 assert(IsThumb && "ARM mode should have been dealt with above"); 7666 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7667 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7668 outs() << format("\t.short\t0x%04x\n", opcode); 7669 Size = 2; 7670 } else{ 7671 WithColor::warning(errs(), "llvm-objdump") 7672 << "invalid instruction encoding\n"; 7673 if (Size == 0) 7674 Size = 1; // skip illegible bytes 7675 } 7676 } 7677 } 7678 // Now that we are done disassembled the first symbol set the bool that 7679 // were doing this to false. 7680 FirstSymbol = false; 7681 } 7682 if (!symbolTableWorked) { 7683 // Reading the symbol table didn't work, disassemble the whole section. 7684 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7685 uint64_t SectSize = Sections[SectIdx].getSize(); 7686 uint64_t InstSize; 7687 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7688 MCInst Inst; 7689 7690 uint64_t PC = SectAddress + Index; 7691 7692 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize)) 7693 continue; 7694 7695 SmallVector<char, 64> AnnotationsBytes; 7696 raw_svector_ostream Annotations(AnnotationsBytes); 7697 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7698 Annotations)) { 7699 if (!NoLeadingAddr) { 7700 if (FullLeadingAddr) { 7701 if (MachOOF->is64Bit()) 7702 outs() << format("%016" PRIx64, PC); 7703 else 7704 outs() << format("%08" PRIx64, PC); 7705 } else { 7706 outs() << format("%8" PRIx64 ":", PC); 7707 } 7708 } 7709 if (!NoShowRawInsn || Arch == Triple::arm) { 7710 outs() << "\t"; 7711 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); 7712 } 7713 StringRef AnnotationsStr = Annotations.str(); 7714 IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs()); 7715 outs() << "\n"; 7716 } else { 7717 if (MachOOF->getArchTriple().isX86()) { 7718 outs() << format("\t.byte 0x%02x #bad opcode\n", 7719 *(Bytes.data() + Index) & 0xff); 7720 InstSize = 1; // skip exactly one illegible byte and move on. 7721 } else { 7722 WithColor::warning(errs(), "llvm-objdump") 7723 << "invalid instruction encoding\n"; 7724 if (InstSize == 0) 7725 InstSize = 1; // skip illegible bytes 7726 } 7727 } 7728 } 7729 } 7730 // The TripleName's need to be reset if we are called again for a different 7731 // architecture. 7732 TripleName = ""; 7733 ThumbTripleName = ""; 7734 7735 if (SymbolizerInfo.demangled_name != nullptr) 7736 free(SymbolizerInfo.demangled_name); 7737 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7738 free(ThumbSymbolizerInfo.demangled_name); 7739 } 7740 } 7741 7742 //===----------------------------------------------------------------------===// 7743 // __compact_unwind section dumping 7744 //===----------------------------------------------------------------------===// 7745 7746 namespace { 7747 7748 template <typename T> 7749 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7750 using llvm::support::little; 7751 using llvm::support::unaligned; 7752 7753 if (Offset + sizeof(T) > Contents.size()) { 7754 outs() << "warning: attempt to read past end of buffer\n"; 7755 return T(); 7756 } 7757 7758 uint64_t Val = 7759 support::endian::read<T, little, unaligned>(Contents.data() + Offset); 7760 return Val; 7761 } 7762 7763 template <typename T> 7764 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7765 T Val = read<T>(Contents, Offset); 7766 Offset += sizeof(T); 7767 return Val; 7768 } 7769 7770 struct CompactUnwindEntry { 7771 uint32_t OffsetInSection; 7772 7773 uint64_t FunctionAddr; 7774 uint32_t Length; 7775 uint32_t CompactEncoding; 7776 uint64_t PersonalityAddr; 7777 uint64_t LSDAAddr; 7778 7779 RelocationRef FunctionReloc; 7780 RelocationRef PersonalityReloc; 7781 RelocationRef LSDAReloc; 7782 7783 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7784 : OffsetInSection(Offset) { 7785 if (Is64) 7786 read<uint64_t>(Contents, Offset); 7787 else 7788 read<uint32_t>(Contents, Offset); 7789 } 7790 7791 private: 7792 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7793 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7794 Length = readNext<uint32_t>(Contents, Offset); 7795 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7796 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7797 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7798 } 7799 }; 7800 } 7801 7802 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7803 /// and data being relocated, determine the best base Name and Addend to use for 7804 /// display purposes. 7805 /// 7806 /// 1. An Extern relocation will directly reference a symbol (and the data is 7807 /// then already an addend), so use that. 7808 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7809 // a symbol before it in the same section, and use the offset from there. 7810 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7811 /// referenced section. 7812 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7813 std::map<uint64_t, SymbolRef> &Symbols, 7814 const RelocationRef &Reloc, uint64_t Addr, 7815 StringRef &Name, uint64_t &Addend) { 7816 if (Reloc.getSymbol() != Obj->symbol_end()) { 7817 Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName()); 7818 Addend = Addr; 7819 return; 7820 } 7821 7822 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7823 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7824 7825 uint64_t SectionAddr = RelocSection.getAddress(); 7826 7827 auto Sym = Symbols.upper_bound(Addr); 7828 if (Sym == Symbols.begin()) { 7829 // The first symbol in the object is after this reference, the best we can 7830 // do is section-relative notation. 7831 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7832 Name = *NameOrErr; 7833 else 7834 consumeError(NameOrErr.takeError()); 7835 7836 Addend = Addr - SectionAddr; 7837 return; 7838 } 7839 7840 // Go back one so that SymbolAddress <= Addr. 7841 --Sym; 7842 7843 section_iterator SymSection = 7844 unwrapOrError(Sym->second.getSection(), Obj->getFileName()); 7845 if (RelocSection == *SymSection) { 7846 // There's a valid symbol in the same section before this reference. 7847 Name = unwrapOrError(Sym->second.getName(), Obj->getFileName()); 7848 Addend = Addr - Sym->first; 7849 return; 7850 } 7851 7852 // There is a symbol before this reference, but it's in a different 7853 // section. Probably not helpful to mention it, so use the section name. 7854 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7855 Name = *NameOrErr; 7856 else 7857 consumeError(NameOrErr.takeError()); 7858 7859 Addend = Addr - SectionAddr; 7860 } 7861 7862 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7863 std::map<uint64_t, SymbolRef> &Symbols, 7864 const RelocationRef &Reloc, uint64_t Addr) { 7865 StringRef Name; 7866 uint64_t Addend; 7867 7868 if (!Reloc.getObject()) 7869 return; 7870 7871 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7872 7873 outs() << Name; 7874 if (Addend) 7875 outs() << " + " << format("0x%" PRIx64, Addend); 7876 } 7877 7878 static void 7879 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7880 std::map<uint64_t, SymbolRef> &Symbols, 7881 const SectionRef &CompactUnwind) { 7882 7883 if (!Obj->isLittleEndian()) { 7884 outs() << "Skipping big-endian __compact_unwind section\n"; 7885 return; 7886 } 7887 7888 bool Is64 = Obj->is64Bit(); 7889 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7890 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7891 7892 StringRef Contents = 7893 unwrapOrError(CompactUnwind.getContents(), Obj->getFileName()); 7894 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7895 7896 // First populate the initial raw offsets, encodings and so on from the entry. 7897 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7898 CompactUnwindEntry Entry(Contents, Offset, Is64); 7899 CompactUnwinds.push_back(Entry); 7900 } 7901 7902 // Next we need to look at the relocations to find out what objects are 7903 // actually being referred to. 7904 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7905 uint64_t RelocAddress = Reloc.getOffset(); 7906 7907 uint32_t EntryIdx = RelocAddress / EntrySize; 7908 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7909 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7910 7911 if (OffsetInEntry == 0) 7912 Entry.FunctionReloc = Reloc; 7913 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7914 Entry.PersonalityReloc = Reloc; 7915 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7916 Entry.LSDAReloc = Reloc; 7917 else { 7918 outs() << "Invalid relocation in __compact_unwind section\n"; 7919 return; 7920 } 7921 } 7922 7923 // Finally, we're ready to print the data we've gathered. 7924 outs() << "Contents of __compact_unwind section:\n"; 7925 for (auto &Entry : CompactUnwinds) { 7926 outs() << " Entry at offset " 7927 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7928 7929 // 1. Start of the region this entry applies to. 7930 outs() << " start: " << format("0x%" PRIx64, 7931 Entry.FunctionAddr) << ' '; 7932 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7933 outs() << '\n'; 7934 7935 // 2. Length of the region this entry applies to. 7936 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7937 << '\n'; 7938 // 3. The 32-bit compact encoding. 7939 outs() << " compact encoding: " 7940 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7941 7942 // 4. The personality function, if present. 7943 if (Entry.PersonalityReloc.getObject()) { 7944 outs() << " personality function: " 7945 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7946 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7947 Entry.PersonalityAddr); 7948 outs() << '\n'; 7949 } 7950 7951 // 5. This entry's language-specific data area. 7952 if (Entry.LSDAReloc.getObject()) { 7953 outs() << " LSDA: " << format("0x%" PRIx64, 7954 Entry.LSDAAddr) << ' '; 7955 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7956 outs() << '\n'; 7957 } 7958 } 7959 } 7960 7961 //===----------------------------------------------------------------------===// 7962 // __unwind_info section dumping 7963 //===----------------------------------------------------------------------===// 7964 7965 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 7966 ptrdiff_t Pos = 0; 7967 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7968 (void)Kind; 7969 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7970 7971 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7972 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7973 7974 Pos = EntriesStart; 7975 for (unsigned i = 0; i < NumEntries; ++i) { 7976 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 7977 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7978 7979 outs() << " [" << i << "]: " 7980 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7981 << ", " 7982 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7983 } 7984 } 7985 7986 static void printCompressedSecondLevelUnwindPage( 7987 StringRef PageData, uint32_t FunctionBase, 7988 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7989 ptrdiff_t Pos = 0; 7990 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7991 (void)Kind; 7992 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 7993 7994 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7995 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7996 7997 uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos); 7998 readNext<uint16_t>(PageData, Pos); 7999 StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos); 8000 8001 Pos = EntriesStart; 8002 for (unsigned i = 0; i < NumEntries; ++i) { 8003 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 8004 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 8005 uint32_t EncodingIdx = Entry >> 24; 8006 8007 uint32_t Encoding; 8008 if (EncodingIdx < CommonEncodings.size()) 8009 Encoding = CommonEncodings[EncodingIdx]; 8010 else 8011 Encoding = read<uint32_t>(PageEncodings, 8012 sizeof(uint32_t) * 8013 (EncodingIdx - CommonEncodings.size())); 8014 8015 outs() << " [" << i << "]: " 8016 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8017 << ", " 8018 << "encoding[" << EncodingIdx 8019 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 8020 } 8021 } 8022 8023 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 8024 std::map<uint64_t, SymbolRef> &Symbols, 8025 const SectionRef &UnwindInfo) { 8026 8027 if (!Obj->isLittleEndian()) { 8028 outs() << "Skipping big-endian __unwind_info section\n"; 8029 return; 8030 } 8031 8032 outs() << "Contents of __unwind_info section:\n"; 8033 8034 StringRef Contents = 8035 unwrapOrError(UnwindInfo.getContents(), Obj->getFileName()); 8036 ptrdiff_t Pos = 0; 8037 8038 //===---------------------------------- 8039 // Section header 8040 //===---------------------------------- 8041 8042 uint32_t Version = readNext<uint32_t>(Contents, Pos); 8043 outs() << " Version: " 8044 << format("0x%" PRIx32, Version) << '\n'; 8045 if (Version != 1) { 8046 outs() << " Skipping section with unknown version\n"; 8047 return; 8048 } 8049 8050 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 8051 outs() << " Common encodings array section offset: " 8052 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 8053 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 8054 outs() << " Number of common encodings in array: " 8055 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 8056 8057 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 8058 outs() << " Personality function array section offset: " 8059 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 8060 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 8061 outs() << " Number of personality functions in array: " 8062 << format("0x%" PRIx32, NumPersonalities) << '\n'; 8063 8064 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 8065 outs() << " Index array section offset: " 8066 << format("0x%" PRIx32, IndicesStart) << '\n'; 8067 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 8068 outs() << " Number of indices in array: " 8069 << format("0x%" PRIx32, NumIndices) << '\n'; 8070 8071 //===---------------------------------- 8072 // A shared list of common encodings 8073 //===---------------------------------- 8074 8075 // These occupy indices in the range [0, N] whenever an encoding is referenced 8076 // from a compressed 2nd level index table. In practice the linker only 8077 // creates ~128 of these, so that indices are available to embed encodings in 8078 // the 2nd level index. 8079 8080 SmallVector<uint32_t, 64> CommonEncodings; 8081 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 8082 Pos = CommonEncodingsStart; 8083 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 8084 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 8085 CommonEncodings.push_back(Encoding); 8086 8087 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 8088 << '\n'; 8089 } 8090 8091 //===---------------------------------- 8092 // Personality functions used in this executable 8093 //===---------------------------------- 8094 8095 // There should be only a handful of these (one per source language, 8096 // roughly). Particularly since they only get 2 bits in the compact encoding. 8097 8098 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 8099 Pos = PersonalitiesStart; 8100 for (unsigned i = 0; i < NumPersonalities; ++i) { 8101 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 8102 outs() << " personality[" << i + 1 8103 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 8104 } 8105 8106 //===---------------------------------- 8107 // The level 1 index entries 8108 //===---------------------------------- 8109 8110 // These specify an approximate place to start searching for the more detailed 8111 // information, sorted by PC. 8112 8113 struct IndexEntry { 8114 uint32_t FunctionOffset; 8115 uint32_t SecondLevelPageStart; 8116 uint32_t LSDAStart; 8117 }; 8118 8119 SmallVector<IndexEntry, 4> IndexEntries; 8120 8121 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 8122 Pos = IndicesStart; 8123 for (unsigned i = 0; i < NumIndices; ++i) { 8124 IndexEntry Entry; 8125 8126 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 8127 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 8128 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 8129 IndexEntries.push_back(Entry); 8130 8131 outs() << " [" << i << "]: " 8132 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 8133 << ", " 8134 << "2nd level page offset=" 8135 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 8136 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 8137 } 8138 8139 //===---------------------------------- 8140 // Next come the LSDA tables 8141 //===---------------------------------- 8142 8143 // The LSDA layout is rather implicit: it's a contiguous array of entries from 8144 // the first top-level index's LSDAOffset to the last (sentinel). 8145 8146 outs() << " LSDA descriptors:\n"; 8147 Pos = IndexEntries[0].LSDAStart; 8148 const uint32_t LSDASize = 2 * sizeof(uint32_t); 8149 int NumLSDAs = 8150 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 8151 8152 for (int i = 0; i < NumLSDAs; ++i) { 8153 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 8154 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 8155 outs() << " [" << i << "]: " 8156 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8157 << ", " 8158 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 8159 } 8160 8161 //===---------------------------------- 8162 // Finally, the 2nd level indices 8163 //===---------------------------------- 8164 8165 // Generally these are 4K in size, and have 2 possible forms: 8166 // + Regular stores up to 511 entries with disparate encodings 8167 // + Compressed stores up to 1021 entries if few enough compact encoding 8168 // values are used. 8169 outs() << " Second level indices:\n"; 8170 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 8171 // The final sentinel top-level index has no associated 2nd level page 8172 if (IndexEntries[i].SecondLevelPageStart == 0) 8173 break; 8174 8175 outs() << " Second level index[" << i << "]: " 8176 << "offset in section=" 8177 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 8178 << ", " 8179 << "base function offset=" 8180 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 8181 8182 Pos = IndexEntries[i].SecondLevelPageStart; 8183 if (Pos + sizeof(uint32_t) > Contents.size()) { 8184 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 8185 continue; 8186 } 8187 8188 uint32_t Kind = 8189 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 8190 if (Kind == 2) 8191 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 8192 else if (Kind == 3) 8193 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 8194 IndexEntries[i].FunctionOffset, 8195 CommonEncodings); 8196 else 8197 outs() << " Skipping 2nd level page with unknown kind " << Kind 8198 << '\n'; 8199 } 8200 } 8201 8202 void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) { 8203 std::map<uint64_t, SymbolRef> Symbols; 8204 for (const SymbolRef &SymRef : Obj->symbols()) { 8205 // Discard any undefined or absolute symbols. They're not going to take part 8206 // in the convenience lookup for unwind info and just take up resources. 8207 auto SectOrErr = SymRef.getSection(); 8208 if (!SectOrErr) { 8209 // TODO: Actually report errors helpfully. 8210 consumeError(SectOrErr.takeError()); 8211 continue; 8212 } 8213 section_iterator Section = *SectOrErr; 8214 if (Section == Obj->section_end()) 8215 continue; 8216 8217 uint64_t Addr = cantFail(SymRef.getValue()); 8218 Symbols.insert(std::make_pair(Addr, SymRef)); 8219 } 8220 8221 for (const SectionRef &Section : Obj->sections()) { 8222 StringRef SectName; 8223 if (Expected<StringRef> NameOrErr = Section.getName()) 8224 SectName = *NameOrErr; 8225 else 8226 consumeError(NameOrErr.takeError()); 8227 8228 if (SectName == "__compact_unwind") 8229 printMachOCompactUnwindSection(Obj, Symbols, Section); 8230 else if (SectName == "__unwind_info") 8231 printMachOUnwindInfoSection(Obj, Symbols, Section); 8232 } 8233 } 8234 8235 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 8236 uint32_t cpusubtype, uint32_t filetype, 8237 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 8238 bool verbose) { 8239 outs() << "Mach header\n"; 8240 outs() << " magic cputype cpusubtype caps filetype ncmds " 8241 "sizeofcmds flags\n"; 8242 if (verbose) { 8243 if (magic == MachO::MH_MAGIC) 8244 outs() << " MH_MAGIC"; 8245 else if (magic == MachO::MH_MAGIC_64) 8246 outs() << "MH_MAGIC_64"; 8247 else 8248 outs() << format(" 0x%08" PRIx32, magic); 8249 switch (cputype) { 8250 case MachO::CPU_TYPE_I386: 8251 outs() << " I386"; 8252 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8253 case MachO::CPU_SUBTYPE_I386_ALL: 8254 outs() << " ALL"; 8255 break; 8256 default: 8257 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8258 break; 8259 } 8260 break; 8261 case MachO::CPU_TYPE_X86_64: 8262 outs() << " X86_64"; 8263 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8264 case MachO::CPU_SUBTYPE_X86_64_ALL: 8265 outs() << " ALL"; 8266 break; 8267 case MachO::CPU_SUBTYPE_X86_64_H: 8268 outs() << " Haswell"; 8269 break; 8270 default: 8271 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8272 break; 8273 } 8274 break; 8275 case MachO::CPU_TYPE_ARM: 8276 outs() << " ARM"; 8277 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8278 case MachO::CPU_SUBTYPE_ARM_ALL: 8279 outs() << " ALL"; 8280 break; 8281 case MachO::CPU_SUBTYPE_ARM_V4T: 8282 outs() << " V4T"; 8283 break; 8284 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 8285 outs() << " V5TEJ"; 8286 break; 8287 case MachO::CPU_SUBTYPE_ARM_XSCALE: 8288 outs() << " XSCALE"; 8289 break; 8290 case MachO::CPU_SUBTYPE_ARM_V6: 8291 outs() << " V6"; 8292 break; 8293 case MachO::CPU_SUBTYPE_ARM_V6M: 8294 outs() << " V6M"; 8295 break; 8296 case MachO::CPU_SUBTYPE_ARM_V7: 8297 outs() << " V7"; 8298 break; 8299 case MachO::CPU_SUBTYPE_ARM_V7EM: 8300 outs() << " V7EM"; 8301 break; 8302 case MachO::CPU_SUBTYPE_ARM_V7K: 8303 outs() << " V7K"; 8304 break; 8305 case MachO::CPU_SUBTYPE_ARM_V7M: 8306 outs() << " V7M"; 8307 break; 8308 case MachO::CPU_SUBTYPE_ARM_V7S: 8309 outs() << " V7S"; 8310 break; 8311 default: 8312 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8313 break; 8314 } 8315 break; 8316 case MachO::CPU_TYPE_ARM64: 8317 outs() << " ARM64"; 8318 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8319 case MachO::CPU_SUBTYPE_ARM64_ALL: 8320 outs() << " ALL"; 8321 break; 8322 case MachO::CPU_SUBTYPE_ARM64_V8: 8323 outs() << " V8"; 8324 break; 8325 case MachO::CPU_SUBTYPE_ARM64E: 8326 outs() << " E"; 8327 break; 8328 default: 8329 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8330 break; 8331 } 8332 break; 8333 case MachO::CPU_TYPE_ARM64_32: 8334 outs() << " ARM64_32"; 8335 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8336 case MachO::CPU_SUBTYPE_ARM64_32_V8: 8337 outs() << " V8"; 8338 break; 8339 default: 8340 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8341 break; 8342 } 8343 break; 8344 case MachO::CPU_TYPE_POWERPC: 8345 outs() << " PPC"; 8346 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8347 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8348 outs() << " ALL"; 8349 break; 8350 default: 8351 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8352 break; 8353 } 8354 break; 8355 case MachO::CPU_TYPE_POWERPC64: 8356 outs() << " PPC64"; 8357 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8358 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8359 outs() << " ALL"; 8360 break; 8361 default: 8362 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8363 break; 8364 } 8365 break; 8366 default: 8367 outs() << format(" %7d", cputype); 8368 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8369 break; 8370 } 8371 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 8372 outs() << " LIB64"; 8373 } else { 8374 outs() << format(" 0x%02" PRIx32, 8375 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8376 } 8377 switch (filetype) { 8378 case MachO::MH_OBJECT: 8379 outs() << " OBJECT"; 8380 break; 8381 case MachO::MH_EXECUTE: 8382 outs() << " EXECUTE"; 8383 break; 8384 case MachO::MH_FVMLIB: 8385 outs() << " FVMLIB"; 8386 break; 8387 case MachO::MH_CORE: 8388 outs() << " CORE"; 8389 break; 8390 case MachO::MH_PRELOAD: 8391 outs() << " PRELOAD"; 8392 break; 8393 case MachO::MH_DYLIB: 8394 outs() << " DYLIB"; 8395 break; 8396 case MachO::MH_DYLIB_STUB: 8397 outs() << " DYLIB_STUB"; 8398 break; 8399 case MachO::MH_DYLINKER: 8400 outs() << " DYLINKER"; 8401 break; 8402 case MachO::MH_BUNDLE: 8403 outs() << " BUNDLE"; 8404 break; 8405 case MachO::MH_DSYM: 8406 outs() << " DSYM"; 8407 break; 8408 case MachO::MH_KEXT_BUNDLE: 8409 outs() << " KEXTBUNDLE"; 8410 break; 8411 default: 8412 outs() << format(" %10u", filetype); 8413 break; 8414 } 8415 outs() << format(" %5u", ncmds); 8416 outs() << format(" %10u", sizeofcmds); 8417 uint32_t f = flags; 8418 if (f & MachO::MH_NOUNDEFS) { 8419 outs() << " NOUNDEFS"; 8420 f &= ~MachO::MH_NOUNDEFS; 8421 } 8422 if (f & MachO::MH_INCRLINK) { 8423 outs() << " INCRLINK"; 8424 f &= ~MachO::MH_INCRLINK; 8425 } 8426 if (f & MachO::MH_DYLDLINK) { 8427 outs() << " DYLDLINK"; 8428 f &= ~MachO::MH_DYLDLINK; 8429 } 8430 if (f & MachO::MH_BINDATLOAD) { 8431 outs() << " BINDATLOAD"; 8432 f &= ~MachO::MH_BINDATLOAD; 8433 } 8434 if (f & MachO::MH_PREBOUND) { 8435 outs() << " PREBOUND"; 8436 f &= ~MachO::MH_PREBOUND; 8437 } 8438 if (f & MachO::MH_SPLIT_SEGS) { 8439 outs() << " SPLIT_SEGS"; 8440 f &= ~MachO::MH_SPLIT_SEGS; 8441 } 8442 if (f & MachO::MH_LAZY_INIT) { 8443 outs() << " LAZY_INIT"; 8444 f &= ~MachO::MH_LAZY_INIT; 8445 } 8446 if (f & MachO::MH_TWOLEVEL) { 8447 outs() << " TWOLEVEL"; 8448 f &= ~MachO::MH_TWOLEVEL; 8449 } 8450 if (f & MachO::MH_FORCE_FLAT) { 8451 outs() << " FORCE_FLAT"; 8452 f &= ~MachO::MH_FORCE_FLAT; 8453 } 8454 if (f & MachO::MH_NOMULTIDEFS) { 8455 outs() << " NOMULTIDEFS"; 8456 f &= ~MachO::MH_NOMULTIDEFS; 8457 } 8458 if (f & MachO::MH_NOFIXPREBINDING) { 8459 outs() << " NOFIXPREBINDING"; 8460 f &= ~MachO::MH_NOFIXPREBINDING; 8461 } 8462 if (f & MachO::MH_PREBINDABLE) { 8463 outs() << " PREBINDABLE"; 8464 f &= ~MachO::MH_PREBINDABLE; 8465 } 8466 if (f & MachO::MH_ALLMODSBOUND) { 8467 outs() << " ALLMODSBOUND"; 8468 f &= ~MachO::MH_ALLMODSBOUND; 8469 } 8470 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8471 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8472 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8473 } 8474 if (f & MachO::MH_CANONICAL) { 8475 outs() << " CANONICAL"; 8476 f &= ~MachO::MH_CANONICAL; 8477 } 8478 if (f & MachO::MH_WEAK_DEFINES) { 8479 outs() << " WEAK_DEFINES"; 8480 f &= ~MachO::MH_WEAK_DEFINES; 8481 } 8482 if (f & MachO::MH_BINDS_TO_WEAK) { 8483 outs() << " BINDS_TO_WEAK"; 8484 f &= ~MachO::MH_BINDS_TO_WEAK; 8485 } 8486 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8487 outs() << " ALLOW_STACK_EXECUTION"; 8488 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8489 } 8490 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8491 outs() << " DEAD_STRIPPABLE_DYLIB"; 8492 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8493 } 8494 if (f & MachO::MH_PIE) { 8495 outs() << " PIE"; 8496 f &= ~MachO::MH_PIE; 8497 } 8498 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8499 outs() << " NO_REEXPORTED_DYLIBS"; 8500 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8501 } 8502 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8503 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8504 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8505 } 8506 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8507 outs() << " MH_NO_HEAP_EXECUTION"; 8508 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8509 } 8510 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8511 outs() << " APP_EXTENSION_SAFE"; 8512 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8513 } 8514 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8515 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8516 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8517 } 8518 if (f != 0 || flags == 0) 8519 outs() << format(" 0x%08" PRIx32, f); 8520 } else { 8521 outs() << format(" 0x%08" PRIx32, magic); 8522 outs() << format(" %7d", cputype); 8523 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8524 outs() << format(" 0x%02" PRIx32, 8525 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8526 outs() << format(" %10u", filetype); 8527 outs() << format(" %5u", ncmds); 8528 outs() << format(" %10u", sizeofcmds); 8529 outs() << format(" 0x%08" PRIx32, flags); 8530 } 8531 outs() << "\n"; 8532 } 8533 8534 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8535 StringRef SegName, uint64_t vmaddr, 8536 uint64_t vmsize, uint64_t fileoff, 8537 uint64_t filesize, uint32_t maxprot, 8538 uint32_t initprot, uint32_t nsects, 8539 uint32_t flags, uint32_t object_size, 8540 bool verbose) { 8541 uint64_t expected_cmdsize; 8542 if (cmd == MachO::LC_SEGMENT) { 8543 outs() << " cmd LC_SEGMENT\n"; 8544 expected_cmdsize = nsects; 8545 expected_cmdsize *= sizeof(struct MachO::section); 8546 expected_cmdsize += sizeof(struct MachO::segment_command); 8547 } else { 8548 outs() << " cmd LC_SEGMENT_64\n"; 8549 expected_cmdsize = nsects; 8550 expected_cmdsize *= sizeof(struct MachO::section_64); 8551 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8552 } 8553 outs() << " cmdsize " << cmdsize; 8554 if (cmdsize != expected_cmdsize) 8555 outs() << " Inconsistent size\n"; 8556 else 8557 outs() << "\n"; 8558 outs() << " segname " << SegName << "\n"; 8559 if (cmd == MachO::LC_SEGMENT_64) { 8560 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8561 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8562 } else { 8563 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8564 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8565 } 8566 outs() << " fileoff " << fileoff; 8567 if (fileoff > object_size) 8568 outs() << " (past end of file)\n"; 8569 else 8570 outs() << "\n"; 8571 outs() << " filesize " << filesize; 8572 if (fileoff + filesize > object_size) 8573 outs() << " (past end of file)\n"; 8574 else 8575 outs() << "\n"; 8576 if (verbose) { 8577 if ((maxprot & 8578 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8579 MachO::VM_PROT_EXECUTE)) != 0) 8580 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8581 else { 8582 outs() << " maxprot "; 8583 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8584 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8585 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8586 } 8587 if ((initprot & 8588 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8589 MachO::VM_PROT_EXECUTE)) != 0) 8590 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8591 else { 8592 outs() << " initprot "; 8593 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8594 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8595 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8596 } 8597 } else { 8598 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8599 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8600 } 8601 outs() << " nsects " << nsects << "\n"; 8602 if (verbose) { 8603 outs() << " flags"; 8604 if (flags == 0) 8605 outs() << " (none)\n"; 8606 else { 8607 if (flags & MachO::SG_HIGHVM) { 8608 outs() << " HIGHVM"; 8609 flags &= ~MachO::SG_HIGHVM; 8610 } 8611 if (flags & MachO::SG_FVMLIB) { 8612 outs() << " FVMLIB"; 8613 flags &= ~MachO::SG_FVMLIB; 8614 } 8615 if (flags & MachO::SG_NORELOC) { 8616 outs() << " NORELOC"; 8617 flags &= ~MachO::SG_NORELOC; 8618 } 8619 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8620 outs() << " PROTECTED_VERSION_1"; 8621 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8622 } 8623 if (flags) 8624 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8625 else 8626 outs() << "\n"; 8627 } 8628 } else { 8629 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8630 } 8631 } 8632 8633 static void PrintSection(const char *sectname, const char *segname, 8634 uint64_t addr, uint64_t size, uint32_t offset, 8635 uint32_t align, uint32_t reloff, uint32_t nreloc, 8636 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8637 uint32_t cmd, const char *sg_segname, 8638 uint32_t filetype, uint32_t object_size, 8639 bool verbose) { 8640 outs() << "Section\n"; 8641 outs() << " sectname " << format("%.16s\n", sectname); 8642 outs() << " segname " << format("%.16s", segname); 8643 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8644 outs() << " (does not match segment)\n"; 8645 else 8646 outs() << "\n"; 8647 if (cmd == MachO::LC_SEGMENT_64) { 8648 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8649 outs() << " size " << format("0x%016" PRIx64, size); 8650 } else { 8651 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8652 outs() << " size " << format("0x%08" PRIx64, size); 8653 } 8654 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8655 outs() << " (past end of file)\n"; 8656 else 8657 outs() << "\n"; 8658 outs() << " offset " << offset; 8659 if (offset > object_size) 8660 outs() << " (past end of file)\n"; 8661 else 8662 outs() << "\n"; 8663 uint32_t align_shifted = 1 << align; 8664 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8665 outs() << " reloff " << reloff; 8666 if (reloff > object_size) 8667 outs() << " (past end of file)\n"; 8668 else 8669 outs() << "\n"; 8670 outs() << " nreloc " << nreloc; 8671 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8672 outs() << " (past end of file)\n"; 8673 else 8674 outs() << "\n"; 8675 uint32_t section_type = flags & MachO::SECTION_TYPE; 8676 if (verbose) { 8677 outs() << " type"; 8678 if (section_type == MachO::S_REGULAR) 8679 outs() << " S_REGULAR\n"; 8680 else if (section_type == MachO::S_ZEROFILL) 8681 outs() << " S_ZEROFILL\n"; 8682 else if (section_type == MachO::S_CSTRING_LITERALS) 8683 outs() << " S_CSTRING_LITERALS\n"; 8684 else if (section_type == MachO::S_4BYTE_LITERALS) 8685 outs() << " S_4BYTE_LITERALS\n"; 8686 else if (section_type == MachO::S_8BYTE_LITERALS) 8687 outs() << " S_8BYTE_LITERALS\n"; 8688 else if (section_type == MachO::S_16BYTE_LITERALS) 8689 outs() << " S_16BYTE_LITERALS\n"; 8690 else if (section_type == MachO::S_LITERAL_POINTERS) 8691 outs() << " S_LITERAL_POINTERS\n"; 8692 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8693 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8694 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8695 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8696 else if (section_type == MachO::S_SYMBOL_STUBS) 8697 outs() << " S_SYMBOL_STUBS\n"; 8698 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8699 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8700 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8701 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8702 else if (section_type == MachO::S_COALESCED) 8703 outs() << " S_COALESCED\n"; 8704 else if (section_type == MachO::S_INTERPOSING) 8705 outs() << " S_INTERPOSING\n"; 8706 else if (section_type == MachO::S_DTRACE_DOF) 8707 outs() << " S_DTRACE_DOF\n"; 8708 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8709 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8710 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8711 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8712 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8713 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8714 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8715 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8716 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8717 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8718 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8719 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8720 else 8721 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8722 outs() << "attributes"; 8723 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8724 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8725 outs() << " PURE_INSTRUCTIONS"; 8726 if (section_attributes & MachO::S_ATTR_NO_TOC) 8727 outs() << " NO_TOC"; 8728 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8729 outs() << " STRIP_STATIC_SYMS"; 8730 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8731 outs() << " NO_DEAD_STRIP"; 8732 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8733 outs() << " LIVE_SUPPORT"; 8734 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8735 outs() << " SELF_MODIFYING_CODE"; 8736 if (section_attributes & MachO::S_ATTR_DEBUG) 8737 outs() << " DEBUG"; 8738 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8739 outs() << " SOME_INSTRUCTIONS"; 8740 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8741 outs() << " EXT_RELOC"; 8742 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8743 outs() << " LOC_RELOC"; 8744 if (section_attributes == 0) 8745 outs() << " (none)"; 8746 outs() << "\n"; 8747 } else 8748 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8749 outs() << " reserved1 " << reserved1; 8750 if (section_type == MachO::S_SYMBOL_STUBS || 8751 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8752 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8753 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8754 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8755 outs() << " (index into indirect symbol table)\n"; 8756 else 8757 outs() << "\n"; 8758 outs() << " reserved2 " << reserved2; 8759 if (section_type == MachO::S_SYMBOL_STUBS) 8760 outs() << " (size of stubs)\n"; 8761 else 8762 outs() << "\n"; 8763 } 8764 8765 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8766 uint32_t object_size) { 8767 outs() << " cmd LC_SYMTAB\n"; 8768 outs() << " cmdsize " << st.cmdsize; 8769 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8770 outs() << " Incorrect size\n"; 8771 else 8772 outs() << "\n"; 8773 outs() << " symoff " << st.symoff; 8774 if (st.symoff > object_size) 8775 outs() << " (past end of file)\n"; 8776 else 8777 outs() << "\n"; 8778 outs() << " nsyms " << st.nsyms; 8779 uint64_t big_size; 8780 if (Is64Bit) { 8781 big_size = st.nsyms; 8782 big_size *= sizeof(struct MachO::nlist_64); 8783 big_size += st.symoff; 8784 if (big_size > object_size) 8785 outs() << " (past end of file)\n"; 8786 else 8787 outs() << "\n"; 8788 } else { 8789 big_size = st.nsyms; 8790 big_size *= sizeof(struct MachO::nlist); 8791 big_size += st.symoff; 8792 if (big_size > object_size) 8793 outs() << " (past end of file)\n"; 8794 else 8795 outs() << "\n"; 8796 } 8797 outs() << " stroff " << st.stroff; 8798 if (st.stroff > object_size) 8799 outs() << " (past end of file)\n"; 8800 else 8801 outs() << "\n"; 8802 outs() << " strsize " << st.strsize; 8803 big_size = st.stroff; 8804 big_size += st.strsize; 8805 if (big_size > object_size) 8806 outs() << " (past end of file)\n"; 8807 else 8808 outs() << "\n"; 8809 } 8810 8811 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8812 uint32_t nsyms, uint32_t object_size, 8813 bool Is64Bit) { 8814 outs() << " cmd LC_DYSYMTAB\n"; 8815 outs() << " cmdsize " << dyst.cmdsize; 8816 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8817 outs() << " Incorrect size\n"; 8818 else 8819 outs() << "\n"; 8820 outs() << " ilocalsym " << dyst.ilocalsym; 8821 if (dyst.ilocalsym > nsyms) 8822 outs() << " (greater than the number of symbols)\n"; 8823 else 8824 outs() << "\n"; 8825 outs() << " nlocalsym " << dyst.nlocalsym; 8826 uint64_t big_size; 8827 big_size = dyst.ilocalsym; 8828 big_size += dyst.nlocalsym; 8829 if (big_size > nsyms) 8830 outs() << " (past the end of the symbol table)\n"; 8831 else 8832 outs() << "\n"; 8833 outs() << " iextdefsym " << dyst.iextdefsym; 8834 if (dyst.iextdefsym > nsyms) 8835 outs() << " (greater than the number of symbols)\n"; 8836 else 8837 outs() << "\n"; 8838 outs() << " nextdefsym " << dyst.nextdefsym; 8839 big_size = dyst.iextdefsym; 8840 big_size += dyst.nextdefsym; 8841 if (big_size > nsyms) 8842 outs() << " (past the end of the symbol table)\n"; 8843 else 8844 outs() << "\n"; 8845 outs() << " iundefsym " << dyst.iundefsym; 8846 if (dyst.iundefsym > nsyms) 8847 outs() << " (greater than the number of symbols)\n"; 8848 else 8849 outs() << "\n"; 8850 outs() << " nundefsym " << dyst.nundefsym; 8851 big_size = dyst.iundefsym; 8852 big_size += dyst.nundefsym; 8853 if (big_size > nsyms) 8854 outs() << " (past the end of the symbol table)\n"; 8855 else 8856 outs() << "\n"; 8857 outs() << " tocoff " << dyst.tocoff; 8858 if (dyst.tocoff > object_size) 8859 outs() << " (past end of file)\n"; 8860 else 8861 outs() << "\n"; 8862 outs() << " ntoc " << dyst.ntoc; 8863 big_size = dyst.ntoc; 8864 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8865 big_size += dyst.tocoff; 8866 if (big_size > object_size) 8867 outs() << " (past end of file)\n"; 8868 else 8869 outs() << "\n"; 8870 outs() << " modtaboff " << dyst.modtaboff; 8871 if (dyst.modtaboff > object_size) 8872 outs() << " (past end of file)\n"; 8873 else 8874 outs() << "\n"; 8875 outs() << " nmodtab " << dyst.nmodtab; 8876 uint64_t modtabend; 8877 if (Is64Bit) { 8878 modtabend = dyst.nmodtab; 8879 modtabend *= sizeof(struct MachO::dylib_module_64); 8880 modtabend += dyst.modtaboff; 8881 } else { 8882 modtabend = dyst.nmodtab; 8883 modtabend *= sizeof(struct MachO::dylib_module); 8884 modtabend += dyst.modtaboff; 8885 } 8886 if (modtabend > object_size) 8887 outs() << " (past end of file)\n"; 8888 else 8889 outs() << "\n"; 8890 outs() << " extrefsymoff " << dyst.extrefsymoff; 8891 if (dyst.extrefsymoff > object_size) 8892 outs() << " (past end of file)\n"; 8893 else 8894 outs() << "\n"; 8895 outs() << " nextrefsyms " << dyst.nextrefsyms; 8896 big_size = dyst.nextrefsyms; 8897 big_size *= sizeof(struct MachO::dylib_reference); 8898 big_size += dyst.extrefsymoff; 8899 if (big_size > object_size) 8900 outs() << " (past end of file)\n"; 8901 else 8902 outs() << "\n"; 8903 outs() << " indirectsymoff " << dyst.indirectsymoff; 8904 if (dyst.indirectsymoff > object_size) 8905 outs() << " (past end of file)\n"; 8906 else 8907 outs() << "\n"; 8908 outs() << " nindirectsyms " << dyst.nindirectsyms; 8909 big_size = dyst.nindirectsyms; 8910 big_size *= sizeof(uint32_t); 8911 big_size += dyst.indirectsymoff; 8912 if (big_size > object_size) 8913 outs() << " (past end of file)\n"; 8914 else 8915 outs() << "\n"; 8916 outs() << " extreloff " << dyst.extreloff; 8917 if (dyst.extreloff > object_size) 8918 outs() << " (past end of file)\n"; 8919 else 8920 outs() << "\n"; 8921 outs() << " nextrel " << dyst.nextrel; 8922 big_size = dyst.nextrel; 8923 big_size *= sizeof(struct MachO::relocation_info); 8924 big_size += dyst.extreloff; 8925 if (big_size > object_size) 8926 outs() << " (past end of file)\n"; 8927 else 8928 outs() << "\n"; 8929 outs() << " locreloff " << dyst.locreloff; 8930 if (dyst.locreloff > object_size) 8931 outs() << " (past end of file)\n"; 8932 else 8933 outs() << "\n"; 8934 outs() << " nlocrel " << dyst.nlocrel; 8935 big_size = dyst.nlocrel; 8936 big_size *= sizeof(struct MachO::relocation_info); 8937 big_size += dyst.locreloff; 8938 if (big_size > object_size) 8939 outs() << " (past end of file)\n"; 8940 else 8941 outs() << "\n"; 8942 } 8943 8944 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8945 uint32_t object_size) { 8946 if (dc.cmd == MachO::LC_DYLD_INFO) 8947 outs() << " cmd LC_DYLD_INFO\n"; 8948 else 8949 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8950 outs() << " cmdsize " << dc.cmdsize; 8951 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8952 outs() << " Incorrect size\n"; 8953 else 8954 outs() << "\n"; 8955 outs() << " rebase_off " << dc.rebase_off; 8956 if (dc.rebase_off > object_size) 8957 outs() << " (past end of file)\n"; 8958 else 8959 outs() << "\n"; 8960 outs() << " rebase_size " << dc.rebase_size; 8961 uint64_t big_size; 8962 big_size = dc.rebase_off; 8963 big_size += dc.rebase_size; 8964 if (big_size > object_size) 8965 outs() << " (past end of file)\n"; 8966 else 8967 outs() << "\n"; 8968 outs() << " bind_off " << dc.bind_off; 8969 if (dc.bind_off > object_size) 8970 outs() << " (past end of file)\n"; 8971 else 8972 outs() << "\n"; 8973 outs() << " bind_size " << dc.bind_size; 8974 big_size = dc.bind_off; 8975 big_size += dc.bind_size; 8976 if (big_size > object_size) 8977 outs() << " (past end of file)\n"; 8978 else 8979 outs() << "\n"; 8980 outs() << " weak_bind_off " << dc.weak_bind_off; 8981 if (dc.weak_bind_off > object_size) 8982 outs() << " (past end of file)\n"; 8983 else 8984 outs() << "\n"; 8985 outs() << " weak_bind_size " << dc.weak_bind_size; 8986 big_size = dc.weak_bind_off; 8987 big_size += dc.weak_bind_size; 8988 if (big_size > object_size) 8989 outs() << " (past end of file)\n"; 8990 else 8991 outs() << "\n"; 8992 outs() << " lazy_bind_off " << dc.lazy_bind_off; 8993 if (dc.lazy_bind_off > object_size) 8994 outs() << " (past end of file)\n"; 8995 else 8996 outs() << "\n"; 8997 outs() << " lazy_bind_size " << dc.lazy_bind_size; 8998 big_size = dc.lazy_bind_off; 8999 big_size += dc.lazy_bind_size; 9000 if (big_size > object_size) 9001 outs() << " (past end of file)\n"; 9002 else 9003 outs() << "\n"; 9004 outs() << " export_off " << dc.export_off; 9005 if (dc.export_off > object_size) 9006 outs() << " (past end of file)\n"; 9007 else 9008 outs() << "\n"; 9009 outs() << " export_size " << dc.export_size; 9010 big_size = dc.export_off; 9011 big_size += dc.export_size; 9012 if (big_size > object_size) 9013 outs() << " (past end of file)\n"; 9014 else 9015 outs() << "\n"; 9016 } 9017 9018 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 9019 const char *Ptr) { 9020 if (dyld.cmd == MachO::LC_ID_DYLINKER) 9021 outs() << " cmd LC_ID_DYLINKER\n"; 9022 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 9023 outs() << " cmd LC_LOAD_DYLINKER\n"; 9024 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 9025 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 9026 else 9027 outs() << " cmd ?(" << dyld.cmd << ")\n"; 9028 outs() << " cmdsize " << dyld.cmdsize; 9029 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 9030 outs() << " Incorrect size\n"; 9031 else 9032 outs() << "\n"; 9033 if (dyld.name >= dyld.cmdsize) 9034 outs() << " name ?(bad offset " << dyld.name << ")\n"; 9035 else { 9036 const char *P = (const char *)(Ptr) + dyld.name; 9037 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 9038 } 9039 } 9040 9041 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 9042 outs() << " cmd LC_UUID\n"; 9043 outs() << " cmdsize " << uuid.cmdsize; 9044 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 9045 outs() << " Incorrect size\n"; 9046 else 9047 outs() << "\n"; 9048 outs() << " uuid "; 9049 for (int i = 0; i < 16; ++i) { 9050 outs() << format("%02" PRIX32, uuid.uuid[i]); 9051 if (i == 3 || i == 5 || i == 7 || i == 9) 9052 outs() << "-"; 9053 } 9054 outs() << "\n"; 9055 } 9056 9057 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 9058 outs() << " cmd LC_RPATH\n"; 9059 outs() << " cmdsize " << rpath.cmdsize; 9060 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 9061 outs() << " Incorrect size\n"; 9062 else 9063 outs() << "\n"; 9064 if (rpath.path >= rpath.cmdsize) 9065 outs() << " path ?(bad offset " << rpath.path << ")\n"; 9066 else { 9067 const char *P = (const char *)(Ptr) + rpath.path; 9068 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 9069 } 9070 } 9071 9072 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 9073 StringRef LoadCmdName; 9074 switch (vd.cmd) { 9075 case MachO::LC_VERSION_MIN_MACOSX: 9076 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 9077 break; 9078 case MachO::LC_VERSION_MIN_IPHONEOS: 9079 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 9080 break; 9081 case MachO::LC_VERSION_MIN_TVOS: 9082 LoadCmdName = "LC_VERSION_MIN_TVOS"; 9083 break; 9084 case MachO::LC_VERSION_MIN_WATCHOS: 9085 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 9086 break; 9087 default: 9088 llvm_unreachable("Unknown version min load command"); 9089 } 9090 9091 outs() << " cmd " << LoadCmdName << '\n'; 9092 outs() << " cmdsize " << vd.cmdsize; 9093 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 9094 outs() << " Incorrect size\n"; 9095 else 9096 outs() << "\n"; 9097 outs() << " version " 9098 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 9099 << MachOObjectFile::getVersionMinMinor(vd, false); 9100 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 9101 if (Update != 0) 9102 outs() << "." << Update; 9103 outs() << "\n"; 9104 if (vd.sdk == 0) 9105 outs() << " sdk n/a"; 9106 else { 9107 outs() << " sdk " 9108 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 9109 << MachOObjectFile::getVersionMinMinor(vd, true); 9110 } 9111 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 9112 if (Update != 0) 9113 outs() << "." << Update; 9114 outs() << "\n"; 9115 } 9116 9117 static void PrintNoteLoadCommand(MachO::note_command Nt) { 9118 outs() << " cmd LC_NOTE\n"; 9119 outs() << " cmdsize " << Nt.cmdsize; 9120 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 9121 outs() << " Incorrect size\n"; 9122 else 9123 outs() << "\n"; 9124 const char *d = Nt.data_owner; 9125 outs() << "data_owner " << format("%.16s\n", d); 9126 outs() << " offset " << Nt.offset << "\n"; 9127 outs() << " size " << Nt.size << "\n"; 9128 } 9129 9130 static void PrintBuildToolVersion(MachO::build_tool_version bv) { 9131 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; 9132 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 9133 << "\n"; 9134 } 9135 9136 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 9137 MachO::build_version_command bd) { 9138 outs() << " cmd LC_BUILD_VERSION\n"; 9139 outs() << " cmdsize " << bd.cmdsize; 9140 if (bd.cmdsize != 9141 sizeof(struct MachO::build_version_command) + 9142 bd.ntools * sizeof(struct MachO::build_tool_version)) 9143 outs() << " Incorrect size\n"; 9144 else 9145 outs() << "\n"; 9146 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) 9147 << "\n"; 9148 if (bd.sdk) 9149 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 9150 << "\n"; 9151 else 9152 outs() << " sdk n/a\n"; 9153 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 9154 << "\n"; 9155 outs() << " ntools " << bd.ntools << "\n"; 9156 for (unsigned i = 0; i < bd.ntools; ++i) { 9157 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 9158 PrintBuildToolVersion(bv); 9159 } 9160 } 9161 9162 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 9163 outs() << " cmd LC_SOURCE_VERSION\n"; 9164 outs() << " cmdsize " << sd.cmdsize; 9165 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 9166 outs() << " Incorrect size\n"; 9167 else 9168 outs() << "\n"; 9169 uint64_t a = (sd.version >> 40) & 0xffffff; 9170 uint64_t b = (sd.version >> 30) & 0x3ff; 9171 uint64_t c = (sd.version >> 20) & 0x3ff; 9172 uint64_t d = (sd.version >> 10) & 0x3ff; 9173 uint64_t e = sd.version & 0x3ff; 9174 outs() << " version " << a << "." << b; 9175 if (e != 0) 9176 outs() << "." << c << "." << d << "." << e; 9177 else if (d != 0) 9178 outs() << "." << c << "." << d; 9179 else if (c != 0) 9180 outs() << "." << c; 9181 outs() << "\n"; 9182 } 9183 9184 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 9185 outs() << " cmd LC_MAIN\n"; 9186 outs() << " cmdsize " << ep.cmdsize; 9187 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 9188 outs() << " Incorrect size\n"; 9189 else 9190 outs() << "\n"; 9191 outs() << " entryoff " << ep.entryoff << "\n"; 9192 outs() << " stacksize " << ep.stacksize << "\n"; 9193 } 9194 9195 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 9196 uint32_t object_size) { 9197 outs() << " cmd LC_ENCRYPTION_INFO\n"; 9198 outs() << " cmdsize " << ec.cmdsize; 9199 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 9200 outs() << " Incorrect size\n"; 9201 else 9202 outs() << "\n"; 9203 outs() << " cryptoff " << ec.cryptoff; 9204 if (ec.cryptoff > object_size) 9205 outs() << " (past end of file)\n"; 9206 else 9207 outs() << "\n"; 9208 outs() << " cryptsize " << ec.cryptsize; 9209 if (ec.cryptsize > object_size) 9210 outs() << " (past end of file)\n"; 9211 else 9212 outs() << "\n"; 9213 outs() << " cryptid " << ec.cryptid << "\n"; 9214 } 9215 9216 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 9217 uint32_t object_size) { 9218 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 9219 outs() << " cmdsize " << ec.cmdsize; 9220 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 9221 outs() << " Incorrect size\n"; 9222 else 9223 outs() << "\n"; 9224 outs() << " cryptoff " << ec.cryptoff; 9225 if (ec.cryptoff > object_size) 9226 outs() << " (past end of file)\n"; 9227 else 9228 outs() << "\n"; 9229 outs() << " cryptsize " << ec.cryptsize; 9230 if (ec.cryptsize > object_size) 9231 outs() << " (past end of file)\n"; 9232 else 9233 outs() << "\n"; 9234 outs() << " cryptid " << ec.cryptid << "\n"; 9235 outs() << " pad " << ec.pad << "\n"; 9236 } 9237 9238 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 9239 const char *Ptr) { 9240 outs() << " cmd LC_LINKER_OPTION\n"; 9241 outs() << " cmdsize " << lo.cmdsize; 9242 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 9243 outs() << " Incorrect size\n"; 9244 else 9245 outs() << "\n"; 9246 outs() << " count " << lo.count << "\n"; 9247 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 9248 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 9249 uint32_t i = 0; 9250 while (left > 0) { 9251 while (*string == '\0' && left > 0) { 9252 string++; 9253 left--; 9254 } 9255 if (left > 0) { 9256 i++; 9257 outs() << " string #" << i << " " << format("%.*s\n", left, string); 9258 uint32_t NullPos = StringRef(string, left).find('\0'); 9259 uint32_t len = std::min(NullPos, left) + 1; 9260 string += len; 9261 left -= len; 9262 } 9263 } 9264 if (lo.count != i) 9265 outs() << " count " << lo.count << " does not match number of strings " 9266 << i << "\n"; 9267 } 9268 9269 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 9270 const char *Ptr) { 9271 outs() << " cmd LC_SUB_FRAMEWORK\n"; 9272 outs() << " cmdsize " << sub.cmdsize; 9273 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 9274 outs() << " Incorrect size\n"; 9275 else 9276 outs() << "\n"; 9277 if (sub.umbrella < sub.cmdsize) { 9278 const char *P = Ptr + sub.umbrella; 9279 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 9280 } else { 9281 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 9282 } 9283 } 9284 9285 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 9286 const char *Ptr) { 9287 outs() << " cmd LC_SUB_UMBRELLA\n"; 9288 outs() << " cmdsize " << sub.cmdsize; 9289 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 9290 outs() << " Incorrect size\n"; 9291 else 9292 outs() << "\n"; 9293 if (sub.sub_umbrella < sub.cmdsize) { 9294 const char *P = Ptr + sub.sub_umbrella; 9295 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 9296 } else { 9297 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 9298 } 9299 } 9300 9301 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 9302 const char *Ptr) { 9303 outs() << " cmd LC_SUB_LIBRARY\n"; 9304 outs() << " cmdsize " << sub.cmdsize; 9305 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 9306 outs() << " Incorrect size\n"; 9307 else 9308 outs() << "\n"; 9309 if (sub.sub_library < sub.cmdsize) { 9310 const char *P = Ptr + sub.sub_library; 9311 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 9312 } else { 9313 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 9314 } 9315 } 9316 9317 static void PrintSubClientCommand(MachO::sub_client_command sub, 9318 const char *Ptr) { 9319 outs() << " cmd LC_SUB_CLIENT\n"; 9320 outs() << " cmdsize " << sub.cmdsize; 9321 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 9322 outs() << " Incorrect size\n"; 9323 else 9324 outs() << "\n"; 9325 if (sub.client < sub.cmdsize) { 9326 const char *P = Ptr + sub.client; 9327 outs() << " client " << P << " (offset " << sub.client << ")\n"; 9328 } else { 9329 outs() << " client ?(bad offset " << sub.client << ")\n"; 9330 } 9331 } 9332 9333 static void PrintRoutinesCommand(MachO::routines_command r) { 9334 outs() << " cmd LC_ROUTINES\n"; 9335 outs() << " cmdsize " << r.cmdsize; 9336 if (r.cmdsize != sizeof(struct MachO::routines_command)) 9337 outs() << " Incorrect size\n"; 9338 else 9339 outs() << "\n"; 9340 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 9341 outs() << " init_module " << r.init_module << "\n"; 9342 outs() << " reserved1 " << r.reserved1 << "\n"; 9343 outs() << " reserved2 " << r.reserved2 << "\n"; 9344 outs() << " reserved3 " << r.reserved3 << "\n"; 9345 outs() << " reserved4 " << r.reserved4 << "\n"; 9346 outs() << " reserved5 " << r.reserved5 << "\n"; 9347 outs() << " reserved6 " << r.reserved6 << "\n"; 9348 } 9349 9350 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 9351 outs() << " cmd LC_ROUTINES_64\n"; 9352 outs() << " cmdsize " << r.cmdsize; 9353 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 9354 outs() << " Incorrect size\n"; 9355 else 9356 outs() << "\n"; 9357 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 9358 outs() << " init_module " << r.init_module << "\n"; 9359 outs() << " reserved1 " << r.reserved1 << "\n"; 9360 outs() << " reserved2 " << r.reserved2 << "\n"; 9361 outs() << " reserved3 " << r.reserved3 << "\n"; 9362 outs() << " reserved4 " << r.reserved4 << "\n"; 9363 outs() << " reserved5 " << r.reserved5 << "\n"; 9364 outs() << " reserved6 " << r.reserved6 << "\n"; 9365 } 9366 9367 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 9368 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 9369 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 9370 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 9371 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 9372 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 9373 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 9374 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 9375 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 9376 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 9377 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 9378 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 9379 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 9380 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 9381 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 9382 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 9383 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 9384 } 9385 9386 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 9387 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 9388 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 9389 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 9390 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 9391 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 9392 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 9393 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 9394 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 9395 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 9396 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 9397 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 9398 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 9399 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 9400 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 9401 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 9402 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 9403 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 9404 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 9405 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 9406 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 9407 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 9408 } 9409 9410 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 9411 uint32_t f; 9412 outs() << "\t mmst_reg "; 9413 for (f = 0; f < 10; f++) 9414 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 9415 outs() << "\n"; 9416 outs() << "\t mmst_rsrv "; 9417 for (f = 0; f < 6; f++) 9418 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 9419 outs() << "\n"; 9420 } 9421 9422 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 9423 uint32_t f; 9424 outs() << "\t xmm_reg "; 9425 for (f = 0; f < 16; f++) 9426 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 9427 outs() << "\n"; 9428 } 9429 9430 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 9431 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 9432 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 9433 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 9434 outs() << " denorm " << fpu.fpu_fcw.denorm; 9435 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 9436 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 9437 outs() << " undfl " << fpu.fpu_fcw.undfl; 9438 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 9439 outs() << "\t\t pc "; 9440 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 9441 outs() << "FP_PREC_24B "; 9442 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 9443 outs() << "FP_PREC_53B "; 9444 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 9445 outs() << "FP_PREC_64B "; 9446 else 9447 outs() << fpu.fpu_fcw.pc << " "; 9448 outs() << "rc "; 9449 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 9450 outs() << "FP_RND_NEAR "; 9451 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 9452 outs() << "FP_RND_DOWN "; 9453 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 9454 outs() << "FP_RND_UP "; 9455 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 9456 outs() << "FP_CHOP "; 9457 outs() << "\n"; 9458 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 9459 outs() << " denorm " << fpu.fpu_fsw.denorm; 9460 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 9461 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 9462 outs() << " undfl " << fpu.fpu_fsw.undfl; 9463 outs() << " precis " << fpu.fpu_fsw.precis; 9464 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 9465 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9466 outs() << " c0 " << fpu.fpu_fsw.c0; 9467 outs() << " c1 " << fpu.fpu_fsw.c1; 9468 outs() << " c2 " << fpu.fpu_fsw.c2; 9469 outs() << " tos " << fpu.fpu_fsw.tos; 9470 outs() << " c3 " << fpu.fpu_fsw.c3; 9471 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9472 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9473 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9474 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9475 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9476 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9477 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9478 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9479 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9480 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9481 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9482 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9483 outs() << "\n"; 9484 outs() << "\t fpu_stmm0:\n"; 9485 Print_mmst_reg(fpu.fpu_stmm0); 9486 outs() << "\t fpu_stmm1:\n"; 9487 Print_mmst_reg(fpu.fpu_stmm1); 9488 outs() << "\t fpu_stmm2:\n"; 9489 Print_mmst_reg(fpu.fpu_stmm2); 9490 outs() << "\t fpu_stmm3:\n"; 9491 Print_mmst_reg(fpu.fpu_stmm3); 9492 outs() << "\t fpu_stmm4:\n"; 9493 Print_mmst_reg(fpu.fpu_stmm4); 9494 outs() << "\t fpu_stmm5:\n"; 9495 Print_mmst_reg(fpu.fpu_stmm5); 9496 outs() << "\t fpu_stmm6:\n"; 9497 Print_mmst_reg(fpu.fpu_stmm6); 9498 outs() << "\t fpu_stmm7:\n"; 9499 Print_mmst_reg(fpu.fpu_stmm7); 9500 outs() << "\t fpu_xmm0:\n"; 9501 Print_xmm_reg(fpu.fpu_xmm0); 9502 outs() << "\t fpu_xmm1:\n"; 9503 Print_xmm_reg(fpu.fpu_xmm1); 9504 outs() << "\t fpu_xmm2:\n"; 9505 Print_xmm_reg(fpu.fpu_xmm2); 9506 outs() << "\t fpu_xmm3:\n"; 9507 Print_xmm_reg(fpu.fpu_xmm3); 9508 outs() << "\t fpu_xmm4:\n"; 9509 Print_xmm_reg(fpu.fpu_xmm4); 9510 outs() << "\t fpu_xmm5:\n"; 9511 Print_xmm_reg(fpu.fpu_xmm5); 9512 outs() << "\t fpu_xmm6:\n"; 9513 Print_xmm_reg(fpu.fpu_xmm6); 9514 outs() << "\t fpu_xmm7:\n"; 9515 Print_xmm_reg(fpu.fpu_xmm7); 9516 outs() << "\t fpu_xmm8:\n"; 9517 Print_xmm_reg(fpu.fpu_xmm8); 9518 outs() << "\t fpu_xmm9:\n"; 9519 Print_xmm_reg(fpu.fpu_xmm9); 9520 outs() << "\t fpu_xmm10:\n"; 9521 Print_xmm_reg(fpu.fpu_xmm10); 9522 outs() << "\t fpu_xmm11:\n"; 9523 Print_xmm_reg(fpu.fpu_xmm11); 9524 outs() << "\t fpu_xmm12:\n"; 9525 Print_xmm_reg(fpu.fpu_xmm12); 9526 outs() << "\t fpu_xmm13:\n"; 9527 Print_xmm_reg(fpu.fpu_xmm13); 9528 outs() << "\t fpu_xmm14:\n"; 9529 Print_xmm_reg(fpu.fpu_xmm14); 9530 outs() << "\t fpu_xmm15:\n"; 9531 Print_xmm_reg(fpu.fpu_xmm15); 9532 outs() << "\t fpu_rsrv4:\n"; 9533 for (uint32_t f = 0; f < 6; f++) { 9534 outs() << "\t "; 9535 for (uint32_t g = 0; g < 16; g++) 9536 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9537 outs() << "\n"; 9538 } 9539 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9540 outs() << "\n"; 9541 } 9542 9543 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9544 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9545 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9546 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9547 } 9548 9549 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9550 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9551 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9552 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9553 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9554 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9555 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9556 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9557 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9558 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9559 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9560 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9561 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9562 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9563 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9564 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9565 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9566 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9567 } 9568 9569 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9570 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9571 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9572 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9573 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9574 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9575 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9576 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9577 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9578 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9579 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9580 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9581 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9582 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9583 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9584 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9585 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9586 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9587 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9588 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9589 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9590 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9591 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9592 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9593 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9594 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9595 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9596 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9597 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9598 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9599 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9600 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9601 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9602 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9603 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9604 } 9605 9606 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9607 bool isLittleEndian, uint32_t cputype) { 9608 if (t.cmd == MachO::LC_THREAD) 9609 outs() << " cmd LC_THREAD\n"; 9610 else if (t.cmd == MachO::LC_UNIXTHREAD) 9611 outs() << " cmd LC_UNIXTHREAD\n"; 9612 else 9613 outs() << " cmd " << t.cmd << " (unknown)\n"; 9614 outs() << " cmdsize " << t.cmdsize; 9615 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9616 outs() << " Incorrect size\n"; 9617 else 9618 outs() << "\n"; 9619 9620 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9621 const char *end = Ptr + t.cmdsize; 9622 uint32_t flavor, count, left; 9623 if (cputype == MachO::CPU_TYPE_I386) { 9624 while (begin < end) { 9625 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9626 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9627 begin += sizeof(uint32_t); 9628 } else { 9629 flavor = 0; 9630 begin = end; 9631 } 9632 if (isLittleEndian != sys::IsLittleEndianHost) 9633 sys::swapByteOrder(flavor); 9634 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9635 memcpy((char *)&count, begin, sizeof(uint32_t)); 9636 begin += sizeof(uint32_t); 9637 } else { 9638 count = 0; 9639 begin = end; 9640 } 9641 if (isLittleEndian != sys::IsLittleEndianHost) 9642 sys::swapByteOrder(count); 9643 if (flavor == MachO::x86_THREAD_STATE32) { 9644 outs() << " flavor i386_THREAD_STATE\n"; 9645 if (count == MachO::x86_THREAD_STATE32_COUNT) 9646 outs() << " count i386_THREAD_STATE_COUNT\n"; 9647 else 9648 outs() << " count " << count 9649 << " (not x86_THREAD_STATE32_COUNT)\n"; 9650 MachO::x86_thread_state32_t cpu32; 9651 left = end - begin; 9652 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9653 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9654 begin += sizeof(MachO::x86_thread_state32_t); 9655 } else { 9656 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9657 memcpy(&cpu32, begin, left); 9658 begin += left; 9659 } 9660 if (isLittleEndian != sys::IsLittleEndianHost) 9661 swapStruct(cpu32); 9662 Print_x86_thread_state32_t(cpu32); 9663 } else if (flavor == MachO::x86_THREAD_STATE) { 9664 outs() << " flavor x86_THREAD_STATE\n"; 9665 if (count == MachO::x86_THREAD_STATE_COUNT) 9666 outs() << " count x86_THREAD_STATE_COUNT\n"; 9667 else 9668 outs() << " count " << count 9669 << " (not x86_THREAD_STATE_COUNT)\n"; 9670 struct MachO::x86_thread_state_t ts; 9671 left = end - begin; 9672 if (left >= sizeof(MachO::x86_thread_state_t)) { 9673 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9674 begin += sizeof(MachO::x86_thread_state_t); 9675 } else { 9676 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9677 memcpy(&ts, begin, left); 9678 begin += left; 9679 } 9680 if (isLittleEndian != sys::IsLittleEndianHost) 9681 swapStruct(ts); 9682 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9683 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9684 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9685 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9686 else 9687 outs() << "tsh.count " << ts.tsh.count 9688 << " (not x86_THREAD_STATE32_COUNT\n"; 9689 Print_x86_thread_state32_t(ts.uts.ts32); 9690 } else { 9691 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9692 << ts.tsh.count << "\n"; 9693 } 9694 } else { 9695 outs() << " flavor " << flavor << " (unknown)\n"; 9696 outs() << " count " << count << "\n"; 9697 outs() << " state (unknown)\n"; 9698 begin += count * sizeof(uint32_t); 9699 } 9700 } 9701 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9702 while (begin < end) { 9703 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9704 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9705 begin += sizeof(uint32_t); 9706 } else { 9707 flavor = 0; 9708 begin = end; 9709 } 9710 if (isLittleEndian != sys::IsLittleEndianHost) 9711 sys::swapByteOrder(flavor); 9712 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9713 memcpy((char *)&count, begin, sizeof(uint32_t)); 9714 begin += sizeof(uint32_t); 9715 } else { 9716 count = 0; 9717 begin = end; 9718 } 9719 if (isLittleEndian != sys::IsLittleEndianHost) 9720 sys::swapByteOrder(count); 9721 if (flavor == MachO::x86_THREAD_STATE64) { 9722 outs() << " flavor x86_THREAD_STATE64\n"; 9723 if (count == MachO::x86_THREAD_STATE64_COUNT) 9724 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9725 else 9726 outs() << " count " << count 9727 << " (not x86_THREAD_STATE64_COUNT)\n"; 9728 MachO::x86_thread_state64_t cpu64; 9729 left = end - begin; 9730 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9731 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9732 begin += sizeof(MachO::x86_thread_state64_t); 9733 } else { 9734 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9735 memcpy(&cpu64, begin, left); 9736 begin += left; 9737 } 9738 if (isLittleEndian != sys::IsLittleEndianHost) 9739 swapStruct(cpu64); 9740 Print_x86_thread_state64_t(cpu64); 9741 } else if (flavor == MachO::x86_THREAD_STATE) { 9742 outs() << " flavor x86_THREAD_STATE\n"; 9743 if (count == MachO::x86_THREAD_STATE_COUNT) 9744 outs() << " count x86_THREAD_STATE_COUNT\n"; 9745 else 9746 outs() << " count " << count 9747 << " (not x86_THREAD_STATE_COUNT)\n"; 9748 struct MachO::x86_thread_state_t ts; 9749 left = end - begin; 9750 if (left >= sizeof(MachO::x86_thread_state_t)) { 9751 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9752 begin += sizeof(MachO::x86_thread_state_t); 9753 } else { 9754 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9755 memcpy(&ts, begin, left); 9756 begin += left; 9757 } 9758 if (isLittleEndian != sys::IsLittleEndianHost) 9759 swapStruct(ts); 9760 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9761 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9762 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9763 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9764 else 9765 outs() << "tsh.count " << ts.tsh.count 9766 << " (not x86_THREAD_STATE64_COUNT\n"; 9767 Print_x86_thread_state64_t(ts.uts.ts64); 9768 } else { 9769 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9770 << ts.tsh.count << "\n"; 9771 } 9772 } else if (flavor == MachO::x86_FLOAT_STATE) { 9773 outs() << " flavor x86_FLOAT_STATE\n"; 9774 if (count == MachO::x86_FLOAT_STATE_COUNT) 9775 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9776 else 9777 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9778 struct MachO::x86_float_state_t fs; 9779 left = end - begin; 9780 if (left >= sizeof(MachO::x86_float_state_t)) { 9781 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9782 begin += sizeof(MachO::x86_float_state_t); 9783 } else { 9784 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9785 memcpy(&fs, begin, left); 9786 begin += left; 9787 } 9788 if (isLittleEndian != sys::IsLittleEndianHost) 9789 swapStruct(fs); 9790 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9791 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9792 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9793 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9794 else 9795 outs() << "fsh.count " << fs.fsh.count 9796 << " (not x86_FLOAT_STATE64_COUNT\n"; 9797 Print_x86_float_state_t(fs.ufs.fs64); 9798 } else { 9799 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9800 << fs.fsh.count << "\n"; 9801 } 9802 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9803 outs() << " flavor x86_EXCEPTION_STATE\n"; 9804 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9805 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9806 else 9807 outs() << " count " << count 9808 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9809 struct MachO::x86_exception_state_t es; 9810 left = end - begin; 9811 if (left >= sizeof(MachO::x86_exception_state_t)) { 9812 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9813 begin += sizeof(MachO::x86_exception_state_t); 9814 } else { 9815 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9816 memcpy(&es, begin, left); 9817 begin += left; 9818 } 9819 if (isLittleEndian != sys::IsLittleEndianHost) 9820 swapStruct(es); 9821 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9822 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9823 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9824 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9825 else 9826 outs() << "\t esh.count " << es.esh.count 9827 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9828 Print_x86_exception_state_t(es.ues.es64); 9829 } else { 9830 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9831 << es.esh.count << "\n"; 9832 } 9833 } else if (flavor == MachO::x86_EXCEPTION_STATE64) { 9834 outs() << " flavor x86_EXCEPTION_STATE64\n"; 9835 if (count == MachO::x86_EXCEPTION_STATE64_COUNT) 9836 outs() << " count x86_EXCEPTION_STATE64_COUNT\n"; 9837 else 9838 outs() << " count " << count 9839 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; 9840 struct MachO::x86_exception_state64_t es64; 9841 left = end - begin; 9842 if (left >= sizeof(MachO::x86_exception_state64_t)) { 9843 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); 9844 begin += sizeof(MachO::x86_exception_state64_t); 9845 } else { 9846 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); 9847 memcpy(&es64, begin, left); 9848 begin += left; 9849 } 9850 if (isLittleEndian != sys::IsLittleEndianHost) 9851 swapStruct(es64); 9852 Print_x86_exception_state_t(es64); 9853 } else { 9854 outs() << " flavor " << flavor << " (unknown)\n"; 9855 outs() << " count " << count << "\n"; 9856 outs() << " state (unknown)\n"; 9857 begin += count * sizeof(uint32_t); 9858 } 9859 } 9860 } else if (cputype == MachO::CPU_TYPE_ARM) { 9861 while (begin < end) { 9862 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9863 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9864 begin += sizeof(uint32_t); 9865 } else { 9866 flavor = 0; 9867 begin = end; 9868 } 9869 if (isLittleEndian != sys::IsLittleEndianHost) 9870 sys::swapByteOrder(flavor); 9871 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9872 memcpy((char *)&count, begin, sizeof(uint32_t)); 9873 begin += sizeof(uint32_t); 9874 } else { 9875 count = 0; 9876 begin = end; 9877 } 9878 if (isLittleEndian != sys::IsLittleEndianHost) 9879 sys::swapByteOrder(count); 9880 if (flavor == MachO::ARM_THREAD_STATE) { 9881 outs() << " flavor ARM_THREAD_STATE\n"; 9882 if (count == MachO::ARM_THREAD_STATE_COUNT) 9883 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9884 else 9885 outs() << " count " << count 9886 << " (not ARM_THREAD_STATE_COUNT)\n"; 9887 MachO::arm_thread_state32_t cpu32; 9888 left = end - begin; 9889 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9890 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9891 begin += sizeof(MachO::arm_thread_state32_t); 9892 } else { 9893 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9894 memcpy(&cpu32, begin, left); 9895 begin += left; 9896 } 9897 if (isLittleEndian != sys::IsLittleEndianHost) 9898 swapStruct(cpu32); 9899 Print_arm_thread_state32_t(cpu32); 9900 } else { 9901 outs() << " flavor " << flavor << " (unknown)\n"; 9902 outs() << " count " << count << "\n"; 9903 outs() << " state (unknown)\n"; 9904 begin += count * sizeof(uint32_t); 9905 } 9906 } 9907 } else if (cputype == MachO::CPU_TYPE_ARM64 || 9908 cputype == MachO::CPU_TYPE_ARM64_32) { 9909 while (begin < end) { 9910 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9911 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9912 begin += sizeof(uint32_t); 9913 } else { 9914 flavor = 0; 9915 begin = end; 9916 } 9917 if (isLittleEndian != sys::IsLittleEndianHost) 9918 sys::swapByteOrder(flavor); 9919 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9920 memcpy((char *)&count, begin, sizeof(uint32_t)); 9921 begin += sizeof(uint32_t); 9922 } else { 9923 count = 0; 9924 begin = end; 9925 } 9926 if (isLittleEndian != sys::IsLittleEndianHost) 9927 sys::swapByteOrder(count); 9928 if (flavor == MachO::ARM_THREAD_STATE64) { 9929 outs() << " flavor ARM_THREAD_STATE64\n"; 9930 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9931 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9932 else 9933 outs() << " count " << count 9934 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9935 MachO::arm_thread_state64_t cpu64; 9936 left = end - begin; 9937 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9938 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9939 begin += sizeof(MachO::arm_thread_state64_t); 9940 } else { 9941 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9942 memcpy(&cpu64, begin, left); 9943 begin += left; 9944 } 9945 if (isLittleEndian != sys::IsLittleEndianHost) 9946 swapStruct(cpu64); 9947 Print_arm_thread_state64_t(cpu64); 9948 } else { 9949 outs() << " flavor " << flavor << " (unknown)\n"; 9950 outs() << " count " << count << "\n"; 9951 outs() << " state (unknown)\n"; 9952 begin += count * sizeof(uint32_t); 9953 } 9954 } 9955 } else { 9956 while (begin < end) { 9957 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9958 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9959 begin += sizeof(uint32_t); 9960 } else { 9961 flavor = 0; 9962 begin = end; 9963 } 9964 if (isLittleEndian != sys::IsLittleEndianHost) 9965 sys::swapByteOrder(flavor); 9966 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9967 memcpy((char *)&count, begin, sizeof(uint32_t)); 9968 begin += sizeof(uint32_t); 9969 } else { 9970 count = 0; 9971 begin = end; 9972 } 9973 if (isLittleEndian != sys::IsLittleEndianHost) 9974 sys::swapByteOrder(count); 9975 outs() << " flavor " << flavor << "\n"; 9976 outs() << " count " << count << "\n"; 9977 outs() << " state (Unknown cputype/cpusubtype)\n"; 9978 begin += count * sizeof(uint32_t); 9979 } 9980 } 9981 } 9982 9983 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 9984 if (dl.cmd == MachO::LC_ID_DYLIB) 9985 outs() << " cmd LC_ID_DYLIB\n"; 9986 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 9987 outs() << " cmd LC_LOAD_DYLIB\n"; 9988 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 9989 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 9990 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 9991 outs() << " cmd LC_REEXPORT_DYLIB\n"; 9992 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 9993 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 9994 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 9995 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 9996 else 9997 outs() << " cmd " << dl.cmd << " (unknown)\n"; 9998 outs() << " cmdsize " << dl.cmdsize; 9999 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 10000 outs() << " Incorrect size\n"; 10001 else 10002 outs() << "\n"; 10003 if (dl.dylib.name < dl.cmdsize) { 10004 const char *P = (const char *)(Ptr) + dl.dylib.name; 10005 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 10006 } else { 10007 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 10008 } 10009 outs() << " time stamp " << dl.dylib.timestamp << " "; 10010 time_t t = dl.dylib.timestamp; 10011 outs() << ctime(&t); 10012 outs() << " current version "; 10013 if (dl.dylib.current_version == 0xffffffff) 10014 outs() << "n/a\n"; 10015 else 10016 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 10017 << ((dl.dylib.current_version >> 8) & 0xff) << "." 10018 << (dl.dylib.current_version & 0xff) << "\n"; 10019 outs() << "compatibility version "; 10020 if (dl.dylib.compatibility_version == 0xffffffff) 10021 outs() << "n/a\n"; 10022 else 10023 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 10024 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 10025 << (dl.dylib.compatibility_version & 0xff) << "\n"; 10026 } 10027 10028 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 10029 uint32_t object_size) { 10030 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 10031 outs() << " cmd LC_CODE_SIGNATURE\n"; 10032 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 10033 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 10034 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 10035 outs() << " cmd LC_FUNCTION_STARTS\n"; 10036 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 10037 outs() << " cmd LC_DATA_IN_CODE\n"; 10038 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 10039 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 10040 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 10041 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 10042 else 10043 outs() << " cmd " << ld.cmd << " (?)\n"; 10044 outs() << " cmdsize " << ld.cmdsize; 10045 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 10046 outs() << " Incorrect size\n"; 10047 else 10048 outs() << "\n"; 10049 outs() << " dataoff " << ld.dataoff; 10050 if (ld.dataoff > object_size) 10051 outs() << " (past end of file)\n"; 10052 else 10053 outs() << "\n"; 10054 outs() << " datasize " << ld.datasize; 10055 uint64_t big_size = ld.dataoff; 10056 big_size += ld.datasize; 10057 if (big_size > object_size) 10058 outs() << " (past end of file)\n"; 10059 else 10060 outs() << "\n"; 10061 } 10062 10063 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 10064 uint32_t cputype, bool verbose) { 10065 StringRef Buf = Obj->getData(); 10066 unsigned Index = 0; 10067 for (const auto &Command : Obj->load_commands()) { 10068 outs() << "Load command " << Index++ << "\n"; 10069 if (Command.C.cmd == MachO::LC_SEGMENT) { 10070 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 10071 const char *sg_segname = SLC.segname; 10072 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 10073 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 10074 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 10075 verbose); 10076 for (unsigned j = 0; j < SLC.nsects; j++) { 10077 MachO::section S = Obj->getSection(Command, j); 10078 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 10079 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 10080 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 10081 } 10082 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10083 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 10084 const char *sg_segname = SLC_64.segname; 10085 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 10086 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 10087 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 10088 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 10089 for (unsigned j = 0; j < SLC_64.nsects; j++) { 10090 MachO::section_64 S_64 = Obj->getSection64(Command, j); 10091 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 10092 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 10093 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 10094 sg_segname, filetype, Buf.size(), verbose); 10095 } 10096 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 10097 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10098 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 10099 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 10100 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 10101 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10102 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 10103 Obj->is64Bit()); 10104 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 10105 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 10106 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 10107 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 10108 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 10109 Command.C.cmd == MachO::LC_ID_DYLINKER || 10110 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 10111 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 10112 PrintDyldLoadCommand(Dyld, Command.Ptr); 10113 } else if (Command.C.cmd == MachO::LC_UUID) { 10114 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 10115 PrintUuidLoadCommand(Uuid); 10116 } else if (Command.C.cmd == MachO::LC_RPATH) { 10117 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 10118 PrintRpathLoadCommand(Rpath, Command.Ptr); 10119 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 10120 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 10121 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 10122 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 10123 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 10124 PrintVersionMinLoadCommand(Vd); 10125 } else if (Command.C.cmd == MachO::LC_NOTE) { 10126 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 10127 PrintNoteLoadCommand(Nt); 10128 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 10129 MachO::build_version_command Bv = 10130 Obj->getBuildVersionLoadCommand(Command); 10131 PrintBuildVersionLoadCommand(Obj, Bv); 10132 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 10133 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 10134 PrintSourceVersionCommand(Sd); 10135 } else if (Command.C.cmd == MachO::LC_MAIN) { 10136 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 10137 PrintEntryPointCommand(Ep); 10138 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 10139 MachO::encryption_info_command Ei = 10140 Obj->getEncryptionInfoCommand(Command); 10141 PrintEncryptionInfoCommand(Ei, Buf.size()); 10142 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 10143 MachO::encryption_info_command_64 Ei = 10144 Obj->getEncryptionInfoCommand64(Command); 10145 PrintEncryptionInfoCommand64(Ei, Buf.size()); 10146 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 10147 MachO::linker_option_command Lo = 10148 Obj->getLinkerOptionLoadCommand(Command); 10149 PrintLinkerOptionCommand(Lo, Command.Ptr); 10150 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 10151 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 10152 PrintSubFrameworkCommand(Sf, Command.Ptr); 10153 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 10154 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 10155 PrintSubUmbrellaCommand(Sf, Command.Ptr); 10156 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 10157 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 10158 PrintSubLibraryCommand(Sl, Command.Ptr); 10159 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 10160 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 10161 PrintSubClientCommand(Sc, Command.Ptr); 10162 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 10163 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 10164 PrintRoutinesCommand(Rc); 10165 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 10166 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 10167 PrintRoutinesCommand64(Rc); 10168 } else if (Command.C.cmd == MachO::LC_THREAD || 10169 Command.C.cmd == MachO::LC_UNIXTHREAD) { 10170 MachO::thread_command Tc = Obj->getThreadCommand(Command); 10171 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 10172 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 10173 Command.C.cmd == MachO::LC_ID_DYLIB || 10174 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 10175 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 10176 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 10177 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 10178 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 10179 PrintDylibCommand(Dl, Command.Ptr); 10180 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 10181 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 10182 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 10183 Command.C.cmd == MachO::LC_DATA_IN_CODE || 10184 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 10185 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 10186 MachO::linkedit_data_command Ld = 10187 Obj->getLinkeditDataLoadCommand(Command); 10188 PrintLinkEditDataCommand(Ld, Buf.size()); 10189 } else { 10190 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 10191 << ")\n"; 10192 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 10193 // TODO: get and print the raw bytes of the load command. 10194 } 10195 // TODO: print all the other kinds of load commands. 10196 } 10197 } 10198 10199 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 10200 if (Obj->is64Bit()) { 10201 MachO::mach_header_64 H_64; 10202 H_64 = Obj->getHeader64(); 10203 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 10204 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 10205 } else { 10206 MachO::mach_header H; 10207 H = Obj->getHeader(); 10208 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 10209 H.sizeofcmds, H.flags, verbose); 10210 } 10211 } 10212 10213 void objdump::printMachOFileHeader(const object::ObjectFile *Obj) { 10214 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 10215 PrintMachHeader(file, !NonVerbose); 10216 } 10217 10218 void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) { 10219 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 10220 uint32_t filetype = 0; 10221 uint32_t cputype = 0; 10222 if (file->is64Bit()) { 10223 MachO::mach_header_64 H_64; 10224 H_64 = file->getHeader64(); 10225 filetype = H_64.filetype; 10226 cputype = H_64.cputype; 10227 } else { 10228 MachO::mach_header H; 10229 H = file->getHeader(); 10230 filetype = H.filetype; 10231 cputype = H.cputype; 10232 } 10233 PrintLoadCommands(file, filetype, cputype, !NonVerbose); 10234 } 10235 10236 //===----------------------------------------------------------------------===// 10237 // export trie dumping 10238 //===----------------------------------------------------------------------===// 10239 10240 static void printMachOExportsTrie(const object::MachOObjectFile *Obj) { 10241 uint64_t BaseSegmentAddress = 0; 10242 for (const auto &Command : Obj->load_commands()) { 10243 if (Command.C.cmd == MachO::LC_SEGMENT) { 10244 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 10245 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10246 BaseSegmentAddress = Seg.vmaddr; 10247 break; 10248 } 10249 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10250 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 10251 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10252 BaseSegmentAddress = Seg.vmaddr; 10253 break; 10254 } 10255 } 10256 } 10257 Error Err = Error::success(); 10258 for (const object::ExportEntry &Entry : Obj->exports(Err)) { 10259 uint64_t Flags = Entry.flags(); 10260 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 10261 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 10262 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10263 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 10264 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10265 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 10266 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 10267 if (ReExport) 10268 outs() << "[re-export] "; 10269 else 10270 outs() << format("0x%08llX ", 10271 Entry.address() + BaseSegmentAddress); 10272 outs() << Entry.name(); 10273 if (WeakDef || ThreadLocal || Resolver || Abs) { 10274 bool NeedsComma = false; 10275 outs() << " ["; 10276 if (WeakDef) { 10277 outs() << "weak_def"; 10278 NeedsComma = true; 10279 } 10280 if (ThreadLocal) { 10281 if (NeedsComma) 10282 outs() << ", "; 10283 outs() << "per-thread"; 10284 NeedsComma = true; 10285 } 10286 if (Abs) { 10287 if (NeedsComma) 10288 outs() << ", "; 10289 outs() << "absolute"; 10290 NeedsComma = true; 10291 } 10292 if (Resolver) { 10293 if (NeedsComma) 10294 outs() << ", "; 10295 outs() << format("resolver=0x%08llX", Entry.other()); 10296 NeedsComma = true; 10297 } 10298 outs() << "]"; 10299 } 10300 if (ReExport) { 10301 StringRef DylibName = "unknown"; 10302 int Ordinal = Entry.other() - 1; 10303 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 10304 if (Entry.otherName().empty()) 10305 outs() << " (from " << DylibName << ")"; 10306 else 10307 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 10308 } 10309 outs() << "\n"; 10310 } 10311 if (Err) 10312 reportError(std::move(Err), Obj->getFileName()); 10313 } 10314 10315 //===----------------------------------------------------------------------===// 10316 // rebase table dumping 10317 //===----------------------------------------------------------------------===// 10318 10319 static void printMachORebaseTable(object::MachOObjectFile *Obj) { 10320 outs() << "segment section address type\n"; 10321 Error Err = Error::success(); 10322 for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 10323 StringRef SegmentName = Entry.segmentName(); 10324 StringRef SectionName = Entry.sectionName(); 10325 uint64_t Address = Entry.address(); 10326 10327 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 10328 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 10329 SegmentName.str().c_str(), SectionName.str().c_str(), 10330 Address, Entry.typeName().str().c_str()); 10331 } 10332 if (Err) 10333 reportError(std::move(Err), Obj->getFileName()); 10334 } 10335 10336 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 10337 StringRef DylibName; 10338 switch (Ordinal) { 10339 case MachO::BIND_SPECIAL_DYLIB_SELF: 10340 return "this-image"; 10341 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 10342 return "main-executable"; 10343 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 10344 return "flat-namespace"; 10345 default: 10346 if (Ordinal > 0) { 10347 std::error_code EC = 10348 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 10349 if (EC) 10350 return "<<bad library ordinal>>"; 10351 return DylibName; 10352 } 10353 } 10354 return "<<unknown special ordinal>>"; 10355 } 10356 10357 //===----------------------------------------------------------------------===// 10358 // bind table dumping 10359 //===----------------------------------------------------------------------===// 10360 10361 static void printMachOBindTable(object::MachOObjectFile *Obj) { 10362 // Build table of sections so names can used in final output. 10363 outs() << "segment section address type " 10364 "addend dylib symbol\n"; 10365 Error Err = Error::success(); 10366 for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 10367 StringRef SegmentName = Entry.segmentName(); 10368 StringRef SectionName = Entry.sectionName(); 10369 uint64_t Address = Entry.address(); 10370 10371 // Table lines look like: 10372 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 10373 StringRef Attr; 10374 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 10375 Attr = " (weak_import)"; 10376 outs() << left_justify(SegmentName, 8) << " " 10377 << left_justify(SectionName, 18) << " " 10378 << format_hex(Address, 10, true) << " " 10379 << left_justify(Entry.typeName(), 8) << " " 10380 << format_decimal(Entry.addend(), 8) << " " 10381 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10382 << Entry.symbolName() << Attr << "\n"; 10383 } 10384 if (Err) 10385 reportError(std::move(Err), Obj->getFileName()); 10386 } 10387 10388 //===----------------------------------------------------------------------===// 10389 // lazy bind table dumping 10390 //===----------------------------------------------------------------------===// 10391 10392 static void printMachOLazyBindTable(object::MachOObjectFile *Obj) { 10393 outs() << "segment section address " 10394 "dylib symbol\n"; 10395 Error Err = Error::success(); 10396 for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 10397 StringRef SegmentName = Entry.segmentName(); 10398 StringRef SectionName = Entry.sectionName(); 10399 uint64_t Address = Entry.address(); 10400 10401 // Table lines look like: 10402 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 10403 outs() << left_justify(SegmentName, 8) << " " 10404 << left_justify(SectionName, 18) << " " 10405 << format_hex(Address, 10, true) << " " 10406 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10407 << Entry.symbolName() << "\n"; 10408 } 10409 if (Err) 10410 reportError(std::move(Err), Obj->getFileName()); 10411 } 10412 10413 //===----------------------------------------------------------------------===// 10414 // weak bind table dumping 10415 //===----------------------------------------------------------------------===// 10416 10417 static void printMachOWeakBindTable(object::MachOObjectFile *Obj) { 10418 outs() << "segment section address " 10419 "type addend symbol\n"; 10420 Error Err = Error::success(); 10421 for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 10422 // Strong symbols don't have a location to update. 10423 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 10424 outs() << " strong " 10425 << Entry.symbolName() << "\n"; 10426 continue; 10427 } 10428 StringRef SegmentName = Entry.segmentName(); 10429 StringRef SectionName = Entry.sectionName(); 10430 uint64_t Address = Entry.address(); 10431 10432 // Table lines look like: 10433 // __DATA __data 0x00001000 pointer 0 _foo 10434 outs() << left_justify(SegmentName, 8) << " " 10435 << left_justify(SectionName, 18) << " " 10436 << format_hex(Address, 10, true) << " " 10437 << left_justify(Entry.typeName(), 8) << " " 10438 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 10439 << "\n"; 10440 } 10441 if (Err) 10442 reportError(std::move(Err), Obj->getFileName()); 10443 } 10444 10445 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 10446 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 10447 // information for that address. If the address is found its binding symbol 10448 // name is returned. If not nullptr is returned. 10449 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 10450 struct DisassembleInfo *info) { 10451 if (info->bindtable == nullptr) { 10452 info->bindtable = std::make_unique<SymbolAddressMap>(); 10453 Error Err = Error::success(); 10454 for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 10455 uint64_t Address = Entry.address(); 10456 StringRef name = Entry.symbolName(); 10457 if (!name.empty()) 10458 (*info->bindtable)[Address] = name; 10459 } 10460 if (Err) 10461 reportError(std::move(Err), info->O->getFileName()); 10462 } 10463 auto name = info->bindtable->lookup(ReferenceValue); 10464 return !name.empty() ? name.data() : nullptr; 10465 } 10466 10467 void objdump::printLazyBindTable(ObjectFile *o) { 10468 outs() << "Lazy bind table:\n"; 10469 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10470 printMachOLazyBindTable(MachO); 10471 else 10472 WithColor::error() 10473 << "This operation is only currently supported " 10474 "for Mach-O executable files.\n"; 10475 } 10476 10477 void objdump::printWeakBindTable(ObjectFile *o) { 10478 outs() << "Weak bind table:\n"; 10479 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10480 printMachOWeakBindTable(MachO); 10481 else 10482 WithColor::error() 10483 << "This operation is only currently supported " 10484 "for Mach-O executable files.\n"; 10485 } 10486 10487 void objdump::printExportsTrie(const ObjectFile *o) { 10488 outs() << "Exports trie:\n"; 10489 if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10490 printMachOExportsTrie(MachO); 10491 else 10492 WithColor::error() 10493 << "This operation is only currently supported " 10494 "for Mach-O executable files.\n"; 10495 } 10496 10497 void objdump::printRebaseTable(ObjectFile *o) { 10498 outs() << "Rebase table:\n"; 10499 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10500 printMachORebaseTable(MachO); 10501 else 10502 WithColor::error() 10503 << "This operation is only currently supported " 10504 "for Mach-O executable files.\n"; 10505 } 10506 10507 void objdump::printBindTable(ObjectFile *o) { 10508 outs() << "Bind table:\n"; 10509 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10510 printMachOBindTable(MachO); 10511 else 10512 WithColor::error() 10513 << "This operation is only currently supported " 10514 "for Mach-O executable files.\n"; 10515 } 10516