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::FunctionStarts("function-starts", 133 cl::desc("Print the function starts table for " 134 "Mach-O objects (requires --macho)"), 135 cl::cat(MachOCat)); 136 137 cl::opt<bool> 138 objdump::LinkOptHints("link-opt-hints", 139 cl::desc("Print the linker optimization hints for " 140 "Mach-O objects (requires --macho)"), 141 cl::cat(MachOCat)); 142 143 cl::opt<bool> 144 objdump::InfoPlist("info-plist", 145 cl::desc("Print the info plist section as strings for " 146 "Mach-O objects (requires --macho)"), 147 cl::cat(MachOCat)); 148 149 cl::opt<bool> 150 objdump::DylibsUsed("dylibs-used", 151 cl::desc("Print the shared libraries used for linked " 152 "Mach-O files (requires --macho)"), 153 cl::cat(MachOCat)); 154 155 cl::opt<bool> objdump::DylibId("dylib-id", 156 cl::desc("Print the shared library's id for the " 157 "dylib Mach-O file (requires --macho)"), 158 cl::cat(MachOCat)); 159 160 static cl::opt<bool> 161 NonVerbose("non-verbose", 162 cl::desc("Print the info for Mach-O objects in non-verbose or " 163 "numeric form (requires --macho)"), 164 cl::cat(MachOCat)); 165 166 cl::opt<bool> 167 objdump::ObjcMetaData("objc-meta-data", 168 cl::desc("Print the Objective-C runtime meta data " 169 "for Mach-O files (requires --macho)"), 170 cl::cat(MachOCat)); 171 172 static cl::opt<std::string> DisSymName( 173 "dis-symname", 174 cl::desc("disassemble just this symbol's instructions (requires --macho)"), 175 cl::cat(MachOCat)); 176 177 static cl::opt<bool> NoSymbolicOperands( 178 "no-symbolic-operands", 179 cl::desc("do not symbolic operands when disassembling (requires --macho)"), 180 cl::cat(MachOCat)); 181 182 static cl::list<std::string> 183 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 184 cl::ZeroOrMore, cl::cat(MachOCat)); 185 186 static bool ArchAll = false; 187 188 static std::string ThumbTripleName; 189 190 static const Target *GetTarget(const MachOObjectFile *MachOObj, 191 const char **McpuDefault, 192 const Target **ThumbTarget) { 193 // Figure out the target triple. 194 Triple TT(TripleName); 195 if (TripleName.empty()) { 196 TT = MachOObj->getArchTriple(McpuDefault); 197 TripleName = TT.str(); 198 } 199 200 if (TT.getArch() == Triple::arm) { 201 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs 202 // that support ARM are also capable of Thumb mode. 203 Triple ThumbTriple = TT; 204 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str(); 205 ThumbTriple.setArchName(ThumbName); 206 ThumbTripleName = ThumbTriple.str(); 207 } 208 209 // Get the target specific parser. 210 std::string Error; 211 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 212 if (TheTarget && ThumbTripleName.empty()) 213 return TheTarget; 214 215 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 216 if (*ThumbTarget) 217 return TheTarget; 218 219 WithColor::error(errs(), "llvm-objdump") << "unable to get target for '"; 220 if (!TheTarget) 221 errs() << TripleName; 222 else 223 errs() << ThumbTripleName; 224 errs() << "', see --version and --triple.\n"; 225 return nullptr; 226 } 227 228 namespace { 229 struct SymbolSorter { 230 bool operator()(const SymbolRef &A, const SymbolRef &B) { 231 Expected<SymbolRef::Type> ATypeOrErr = A.getType(); 232 if (!ATypeOrErr) 233 reportError(ATypeOrErr.takeError(), A.getObject()->getFileName()); 234 SymbolRef::Type AType = *ATypeOrErr; 235 Expected<SymbolRef::Type> BTypeOrErr = B.getType(); 236 if (!BTypeOrErr) 237 reportError(BTypeOrErr.takeError(), B.getObject()->getFileName()); 238 SymbolRef::Type BType = *BTypeOrErr; 239 uint64_t AAddr = 240 (AType != SymbolRef::ST_Function) ? 0 : cantFail(A.getValue()); 241 uint64_t BAddr = 242 (BType != SymbolRef::ST_Function) ? 0 : cantFail(B.getValue()); 243 return AAddr < BAddr; 244 } 245 }; 246 } // namespace 247 248 // Types for the storted data in code table that is built before disassembly 249 // and the predicate function to sort them. 250 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 251 typedef std::vector<DiceTableEntry> DiceTable; 252 typedef DiceTable::iterator dice_table_iterator; 253 254 #ifdef HAVE_LIBXAR 255 namespace { 256 struct ScopedXarFile { 257 xar_t xar; 258 ScopedXarFile(const char *filename, int32_t flags) 259 : xar(xar_open(filename, flags)) {} 260 ~ScopedXarFile() { 261 if (xar) 262 xar_close(xar); 263 } 264 ScopedXarFile(const ScopedXarFile &) = delete; 265 ScopedXarFile &operator=(const ScopedXarFile &) = delete; 266 operator xar_t() { return xar; } 267 }; 268 269 struct ScopedXarIter { 270 xar_iter_t iter; 271 ScopedXarIter() : iter(xar_iter_new()) {} 272 ~ScopedXarIter() { 273 if (iter) 274 xar_iter_free(iter); 275 } 276 ScopedXarIter(const ScopedXarIter &) = delete; 277 ScopedXarIter &operator=(const ScopedXarIter &) = delete; 278 operator xar_iter_t() { return iter; } 279 }; 280 } // namespace 281 #endif // defined(HAVE_LIBXAR) 282 283 // This is used to search for a data in code table entry for the PC being 284 // disassembled. The j parameter has the PC in j.first. A single data in code 285 // table entry can cover many bytes for each of its Kind's. So if the offset, 286 // aka the i.first value, of the data in code table entry plus its Length 287 // covers the PC being searched for this will return true. If not it will 288 // return false. 289 static bool compareDiceTableEntries(const DiceTableEntry &i, 290 const DiceTableEntry &j) { 291 uint16_t Length; 292 i.second.getLength(Length); 293 294 return j.first >= i.first && j.first < i.first + Length; 295 } 296 297 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 298 unsigned short Kind) { 299 uint32_t Value, Size = 1; 300 301 switch (Kind) { 302 default: 303 case MachO::DICE_KIND_DATA: 304 if (Length >= 4) { 305 if (!NoShowRawInsn) 306 dumpBytes(makeArrayRef(bytes, 4), outs()); 307 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 308 outs() << "\t.long " << Value; 309 Size = 4; 310 } else if (Length >= 2) { 311 if (!NoShowRawInsn) 312 dumpBytes(makeArrayRef(bytes, 2), outs()); 313 Value = bytes[1] << 8 | bytes[0]; 314 outs() << "\t.short " << Value; 315 Size = 2; 316 } else { 317 if (!NoShowRawInsn) 318 dumpBytes(makeArrayRef(bytes, 2), outs()); 319 Value = bytes[0]; 320 outs() << "\t.byte " << Value; 321 Size = 1; 322 } 323 if (Kind == MachO::DICE_KIND_DATA) 324 outs() << "\t@ KIND_DATA\n"; 325 else 326 outs() << "\t@ data in code kind = " << Kind << "\n"; 327 break; 328 case MachO::DICE_KIND_JUMP_TABLE8: 329 if (!NoShowRawInsn) 330 dumpBytes(makeArrayRef(bytes, 1), outs()); 331 Value = bytes[0]; 332 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 333 Size = 1; 334 break; 335 case MachO::DICE_KIND_JUMP_TABLE16: 336 if (!NoShowRawInsn) 337 dumpBytes(makeArrayRef(bytes, 2), outs()); 338 Value = bytes[1] << 8 | bytes[0]; 339 outs() << "\t.short " << format("%5u", Value & 0xffff) 340 << "\t@ KIND_JUMP_TABLE16\n"; 341 Size = 2; 342 break; 343 case MachO::DICE_KIND_JUMP_TABLE32: 344 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 345 if (!NoShowRawInsn) 346 dumpBytes(makeArrayRef(bytes, 4), outs()); 347 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 348 outs() << "\t.long " << Value; 349 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 350 outs() << "\t@ KIND_JUMP_TABLE32\n"; 351 else 352 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 353 Size = 4; 354 break; 355 } 356 return Size; 357 } 358 359 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 360 std::vector<SectionRef> &Sections, 361 std::vector<SymbolRef> &Symbols, 362 SmallVectorImpl<uint64_t> &FoundFns, 363 uint64_t &BaseSegmentAddress) { 364 const StringRef FileName = MachOObj->getFileName(); 365 for (const SymbolRef &Symbol : MachOObj->symbols()) { 366 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 367 if (!SymName.startswith("ltmp")) 368 Symbols.push_back(Symbol); 369 } 370 371 append_range(Sections, MachOObj->sections()); 372 373 bool BaseSegmentAddressSet = false; 374 for (const auto &Command : MachOObj->load_commands()) { 375 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 376 // We found a function starts segment, parse the addresses for later 377 // consumption. 378 MachO::linkedit_data_command LLC = 379 MachOObj->getLinkeditDataLoadCommand(Command); 380 381 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 382 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 383 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 384 StringRef SegName = SLC.segname; 385 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 386 BaseSegmentAddressSet = true; 387 BaseSegmentAddress = SLC.vmaddr; 388 } 389 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 390 MachO::segment_command_64 SLC = MachOObj->getSegment64LoadCommand(Command); 391 StringRef SegName = SLC.segname; 392 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 393 BaseSegmentAddressSet = true; 394 BaseSegmentAddress = SLC.vmaddr; 395 } 396 } 397 } 398 } 399 400 static bool DumpAndSkipDataInCode(uint64_t PC, const uint8_t *bytes, 401 DiceTable &Dices, uint64_t &InstSize) { 402 // Check the data in code table here to see if this is data not an 403 // instruction to be disassembled. 404 DiceTable Dice; 405 Dice.push_back(std::make_pair(PC, DiceRef())); 406 dice_table_iterator DTI = 407 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 408 compareDiceTableEntries); 409 if (DTI != Dices.end()) { 410 uint16_t Length; 411 DTI->second.getLength(Length); 412 uint16_t Kind; 413 DTI->second.getKind(Kind); 414 InstSize = DumpDataInCode(bytes, Length, Kind); 415 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 416 (PC == (DTI->first + Length - 1)) && (Length & 1)) 417 InstSize++; 418 return true; 419 } 420 return false; 421 } 422 423 static void printRelocationTargetName(const MachOObjectFile *O, 424 const MachO::any_relocation_info &RE, 425 raw_string_ostream &Fmt) { 426 // Target of a scattered relocation is an address. In the interest of 427 // generating pretty output, scan through the symbol table looking for a 428 // symbol that aligns with that address. If we find one, print it. 429 // Otherwise, we just print the hex address of the target. 430 const StringRef FileName = O->getFileName(); 431 if (O->isRelocationScattered(RE)) { 432 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 433 434 for (const SymbolRef &Symbol : O->symbols()) { 435 uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName); 436 if (Addr != Val) 437 continue; 438 Fmt << unwrapOrError(Symbol.getName(), FileName); 439 return; 440 } 441 442 // If we couldn't find a symbol that this relocation refers to, try 443 // to find a section beginning instead. 444 for (const SectionRef &Section : ToolSectionFilter(*O)) { 445 uint64_t Addr = Section.getAddress(); 446 if (Addr != Val) 447 continue; 448 StringRef NameOrErr = unwrapOrError(Section.getName(), O->getFileName()); 449 Fmt << NameOrErr; 450 return; 451 } 452 453 Fmt << format("0x%x", Val); 454 return; 455 } 456 457 StringRef S; 458 bool isExtern = O->getPlainRelocationExternal(RE); 459 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 460 461 if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND && 462 (O->getArch() == Triple::aarch64 || O->getArch() == Triple::aarch64_be)) { 463 Fmt << format("0x%0" PRIx64, Val); 464 return; 465 } 466 467 if (isExtern) { 468 symbol_iterator SI = O->symbol_begin(); 469 advance(SI, Val); 470 S = unwrapOrError(SI->getName(), FileName); 471 } else { 472 section_iterator SI = O->section_begin(); 473 // Adjust for the fact that sections are 1-indexed. 474 if (Val == 0) { 475 Fmt << "0 (?,?)"; 476 return; 477 } 478 uint32_t I = Val - 1; 479 while (I != 0 && SI != O->section_end()) { 480 --I; 481 advance(SI, 1); 482 } 483 if (SI == O->section_end()) { 484 Fmt << Val << " (?,?)"; 485 } else { 486 if (Expected<StringRef> NameOrErr = SI->getName()) 487 S = *NameOrErr; 488 else 489 consumeError(NameOrErr.takeError()); 490 } 491 } 492 493 Fmt << S; 494 } 495 496 Error objdump::getMachORelocationValueString(const MachOObjectFile *Obj, 497 const RelocationRef &RelRef, 498 SmallVectorImpl<char> &Result) { 499 DataRefImpl Rel = RelRef.getRawDataRefImpl(); 500 MachO::any_relocation_info RE = Obj->getRelocation(Rel); 501 502 unsigned Arch = Obj->getArch(); 503 504 std::string FmtBuf; 505 raw_string_ostream Fmt(FmtBuf); 506 unsigned Type = Obj->getAnyRelocationType(RE); 507 bool IsPCRel = Obj->getAnyRelocationPCRel(RE); 508 509 // Determine any addends that should be displayed with the relocation. 510 // These require decoding the relocation type, which is triple-specific. 511 512 // X86_64 has entirely custom relocation types. 513 if (Arch == Triple::x86_64) { 514 switch (Type) { 515 case MachO::X86_64_RELOC_GOT_LOAD: 516 case MachO::X86_64_RELOC_GOT: { 517 printRelocationTargetName(Obj, RE, Fmt); 518 Fmt << "@GOT"; 519 if (IsPCRel) 520 Fmt << "PCREL"; 521 break; 522 } 523 case MachO::X86_64_RELOC_SUBTRACTOR: { 524 DataRefImpl RelNext = Rel; 525 Obj->moveRelocationNext(RelNext); 526 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 527 528 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 529 // X86_64_RELOC_UNSIGNED. 530 // NOTE: Scattered relocations don't exist on x86_64. 531 unsigned RType = Obj->getAnyRelocationType(RENext); 532 if (RType != MachO::X86_64_RELOC_UNSIGNED) 533 reportError(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after " 534 "X86_64_RELOC_SUBTRACTOR."); 535 536 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 537 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 538 printRelocationTargetName(Obj, RENext, Fmt); 539 Fmt << "-"; 540 printRelocationTargetName(Obj, RE, Fmt); 541 break; 542 } 543 case MachO::X86_64_RELOC_TLV: 544 printRelocationTargetName(Obj, RE, Fmt); 545 Fmt << "@TLV"; 546 if (IsPCRel) 547 Fmt << "P"; 548 break; 549 case MachO::X86_64_RELOC_SIGNED_1: 550 printRelocationTargetName(Obj, RE, Fmt); 551 Fmt << "-1"; 552 break; 553 case MachO::X86_64_RELOC_SIGNED_2: 554 printRelocationTargetName(Obj, RE, Fmt); 555 Fmt << "-2"; 556 break; 557 case MachO::X86_64_RELOC_SIGNED_4: 558 printRelocationTargetName(Obj, RE, Fmt); 559 Fmt << "-4"; 560 break; 561 default: 562 printRelocationTargetName(Obj, RE, Fmt); 563 break; 564 } 565 // X86 and ARM share some relocation types in common. 566 } else if (Arch == Triple::x86 || Arch == Triple::arm || 567 Arch == Triple::ppc) { 568 // Generic relocation types... 569 switch (Type) { 570 case MachO::GENERIC_RELOC_PAIR: // prints no info 571 return Error::success(); 572 case MachO::GENERIC_RELOC_SECTDIFF: { 573 DataRefImpl RelNext = Rel; 574 Obj->moveRelocationNext(RelNext); 575 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 576 577 // X86 sect diff's must be followed by a relocation of type 578 // GENERIC_RELOC_PAIR. 579 unsigned RType = Obj->getAnyRelocationType(RENext); 580 581 if (RType != MachO::GENERIC_RELOC_PAIR) 582 reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 583 "GENERIC_RELOC_SECTDIFF."); 584 585 printRelocationTargetName(Obj, RE, Fmt); 586 Fmt << "-"; 587 printRelocationTargetName(Obj, RENext, Fmt); 588 break; 589 } 590 } 591 592 if (Arch == Triple::x86 || Arch == Triple::ppc) { 593 switch (Type) { 594 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 595 DataRefImpl RelNext = Rel; 596 Obj->moveRelocationNext(RelNext); 597 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 598 599 // X86 sect diff's must be followed by a relocation of type 600 // GENERIC_RELOC_PAIR. 601 unsigned RType = Obj->getAnyRelocationType(RENext); 602 if (RType != MachO::GENERIC_RELOC_PAIR) 603 reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 604 "GENERIC_RELOC_LOCAL_SECTDIFF."); 605 606 printRelocationTargetName(Obj, RE, Fmt); 607 Fmt << "-"; 608 printRelocationTargetName(Obj, RENext, Fmt); 609 break; 610 } 611 case MachO::GENERIC_RELOC_TLV: { 612 printRelocationTargetName(Obj, RE, Fmt); 613 Fmt << "@TLV"; 614 if (IsPCRel) 615 Fmt << "P"; 616 break; 617 } 618 default: 619 printRelocationTargetName(Obj, RE, Fmt); 620 } 621 } else { // ARM-specific relocations 622 switch (Type) { 623 case MachO::ARM_RELOC_HALF: 624 case MachO::ARM_RELOC_HALF_SECTDIFF: { 625 // Half relocations steal a bit from the length field to encode 626 // whether this is an upper16 or a lower16 relocation. 627 bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1; 628 629 if (isUpper) 630 Fmt << ":upper16:("; 631 else 632 Fmt << ":lower16:("; 633 printRelocationTargetName(Obj, RE, Fmt); 634 635 DataRefImpl RelNext = Rel; 636 Obj->moveRelocationNext(RelNext); 637 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 638 639 // ARM half relocs must be followed by a relocation of type 640 // ARM_RELOC_PAIR. 641 unsigned RType = Obj->getAnyRelocationType(RENext); 642 if (RType != MachO::ARM_RELOC_PAIR) 643 reportError(Obj->getFileName(), "Expected ARM_RELOC_PAIR after " 644 "ARM_RELOC_HALF"); 645 646 // NOTE: The half of the target virtual address is stashed in the 647 // address field of the secondary relocation, but we can't reverse 648 // engineer the constant offset from it without decoding the movw/movt 649 // instruction to find the other half in its immediate field. 650 651 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 652 // symbol/section pointer of the follow-on relocation. 653 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 654 Fmt << "-"; 655 printRelocationTargetName(Obj, RENext, Fmt); 656 } 657 658 Fmt << ")"; 659 break; 660 } 661 default: { 662 printRelocationTargetName(Obj, RE, Fmt); 663 } 664 } 665 } 666 } else 667 printRelocationTargetName(Obj, RE, Fmt); 668 669 Fmt.flush(); 670 Result.append(FmtBuf.begin(), FmtBuf.end()); 671 return Error::success(); 672 } 673 674 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 675 uint32_t n, uint32_t count, 676 uint32_t stride, uint64_t addr) { 677 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 678 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 679 if (n > nindirectsyms) 680 outs() << " (entries start past the end of the indirect symbol " 681 "table) (reserved1 field greater than the table size)"; 682 else if (n + count > nindirectsyms) 683 outs() << " (entries extends past the end of the indirect symbol " 684 "table)"; 685 outs() << "\n"; 686 uint32_t cputype = O->getHeader().cputype; 687 if (cputype & MachO::CPU_ARCH_ABI64) 688 outs() << "address index"; 689 else 690 outs() << "address index"; 691 if (verbose) 692 outs() << " name\n"; 693 else 694 outs() << "\n"; 695 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 696 if (cputype & MachO::CPU_ARCH_ABI64) 697 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 698 else 699 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 700 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 701 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 702 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 703 outs() << "LOCAL\n"; 704 continue; 705 } 706 if (indirect_symbol == 707 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 708 outs() << "LOCAL ABSOLUTE\n"; 709 continue; 710 } 711 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 712 outs() << "ABSOLUTE\n"; 713 continue; 714 } 715 outs() << format("%5u ", indirect_symbol); 716 if (verbose) { 717 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 718 if (indirect_symbol < Symtab.nsyms) { 719 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 720 SymbolRef Symbol = *Sym; 721 outs() << unwrapOrError(Symbol.getName(), O->getFileName()); 722 } else { 723 outs() << "?"; 724 } 725 } 726 outs() << "\n"; 727 } 728 } 729 730 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 731 for (const auto &Load : O->load_commands()) { 732 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 733 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 734 for (unsigned J = 0; J < Seg.nsects; ++J) { 735 MachO::section_64 Sec = O->getSection64(Load, J); 736 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 737 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 738 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 739 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 740 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 741 section_type == MachO::S_SYMBOL_STUBS) { 742 uint32_t stride; 743 if (section_type == MachO::S_SYMBOL_STUBS) 744 stride = Sec.reserved2; 745 else 746 stride = 8; 747 if (stride == 0) { 748 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 749 << Sec.sectname << ") " 750 << "(size of stubs in reserved2 field is zero)\n"; 751 continue; 752 } 753 uint32_t count = Sec.size / stride; 754 outs() << "Indirect symbols for (" << Sec.segname << "," 755 << Sec.sectname << ") " << count << " entries"; 756 uint32_t n = Sec.reserved1; 757 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 758 } 759 } 760 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 761 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 762 for (unsigned J = 0; J < Seg.nsects; ++J) { 763 MachO::section Sec = O->getSection(Load, J); 764 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 765 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 766 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 767 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 768 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 769 section_type == MachO::S_SYMBOL_STUBS) { 770 uint32_t stride; 771 if (section_type == MachO::S_SYMBOL_STUBS) 772 stride = Sec.reserved2; 773 else 774 stride = 4; 775 if (stride == 0) { 776 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 777 << Sec.sectname << ") " 778 << "(size of stubs in reserved2 field is zero)\n"; 779 continue; 780 } 781 uint32_t count = Sec.size / stride; 782 outs() << "Indirect symbols for (" << Sec.segname << "," 783 << Sec.sectname << ") " << count << " entries"; 784 uint32_t n = Sec.reserved1; 785 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 786 } 787 } 788 } 789 } 790 } 791 792 static void PrintRType(const uint64_t cputype, const unsigned r_type) { 793 static char const *generic_r_types[] = { 794 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ", 795 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", 796 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 797 }; 798 static char const *x86_64_r_types[] = { 799 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", 800 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ", 801 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 802 }; 803 static char const *arm_r_types[] = { 804 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", 805 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ", 806 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 807 }; 808 static char const *arm64_r_types[] = { 809 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", 810 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", 811 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 812 }; 813 814 if (r_type > 0xf){ 815 outs() << format("%-7u", r_type) << " "; 816 return; 817 } 818 switch (cputype) { 819 case MachO::CPU_TYPE_I386: 820 outs() << generic_r_types[r_type]; 821 break; 822 case MachO::CPU_TYPE_X86_64: 823 outs() << x86_64_r_types[r_type]; 824 break; 825 case MachO::CPU_TYPE_ARM: 826 outs() << arm_r_types[r_type]; 827 break; 828 case MachO::CPU_TYPE_ARM64: 829 case MachO::CPU_TYPE_ARM64_32: 830 outs() << arm64_r_types[r_type]; 831 break; 832 default: 833 outs() << format("%-7u ", r_type); 834 } 835 } 836 837 static void PrintRLength(const uint64_t cputype, const unsigned r_type, 838 const unsigned r_length, const bool previous_arm_half){ 839 if (cputype == MachO::CPU_TYPE_ARM && 840 (r_type == MachO::ARM_RELOC_HALF || 841 r_type == MachO::ARM_RELOC_HALF_SECTDIFF || previous_arm_half == true)) { 842 if ((r_length & 0x1) == 0) 843 outs() << "lo/"; 844 else 845 outs() << "hi/"; 846 if ((r_length & 0x1) == 0) 847 outs() << "arm "; 848 else 849 outs() << "thm "; 850 } else { 851 switch (r_length) { 852 case 0: 853 outs() << "byte "; 854 break; 855 case 1: 856 outs() << "word "; 857 break; 858 case 2: 859 outs() << "long "; 860 break; 861 case 3: 862 if (cputype == MachO::CPU_TYPE_X86_64) 863 outs() << "quad "; 864 else 865 outs() << format("?(%2d) ", r_length); 866 break; 867 default: 868 outs() << format("?(%2d) ", r_length); 869 } 870 } 871 } 872 873 static void PrintRelocationEntries(const MachOObjectFile *O, 874 const relocation_iterator Begin, 875 const relocation_iterator End, 876 const uint64_t cputype, 877 const bool verbose) { 878 const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 879 bool previous_arm_half = false; 880 bool previous_sectdiff = false; 881 uint32_t sectdiff_r_type = 0; 882 883 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { 884 const DataRefImpl Rel = Reloc->getRawDataRefImpl(); 885 const MachO::any_relocation_info RE = O->getRelocation(Rel); 886 const unsigned r_type = O->getAnyRelocationType(RE); 887 const bool r_scattered = O->isRelocationScattered(RE); 888 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); 889 const unsigned r_length = O->getAnyRelocationLength(RE); 890 const unsigned r_address = O->getAnyRelocationAddress(RE); 891 const bool r_extern = (r_scattered ? false : 892 O->getPlainRelocationExternal(RE)); 893 const uint32_t r_value = (r_scattered ? 894 O->getScatteredRelocationValue(RE) : 0); 895 const unsigned r_symbolnum = (r_scattered ? 0 : 896 O->getPlainRelocationSymbolNum(RE)); 897 898 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { 899 if (verbose) { 900 // scattered: address 901 if ((cputype == MachO::CPU_TYPE_I386 && 902 r_type == MachO::GENERIC_RELOC_PAIR) || 903 (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)) 904 outs() << " "; 905 else 906 outs() << format("%08x ", (unsigned int)r_address); 907 908 // scattered: pcrel 909 if (r_pcrel) 910 outs() << "True "; 911 else 912 outs() << "False "; 913 914 // scattered: length 915 PrintRLength(cputype, r_type, r_length, previous_arm_half); 916 917 // scattered: extern & type 918 outs() << "n/a "; 919 PrintRType(cputype, r_type); 920 921 // scattered: scattered & value 922 outs() << format("True 0x%08x", (unsigned int)r_value); 923 if (previous_sectdiff == false) { 924 if ((cputype == MachO::CPU_TYPE_ARM && 925 r_type == MachO::ARM_RELOC_PAIR)) 926 outs() << format(" half = 0x%04x ", (unsigned int)r_address); 927 } else if (cputype == MachO::CPU_TYPE_ARM && 928 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF) 929 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); 930 if ((cputype == MachO::CPU_TYPE_I386 && 931 (r_type == MachO::GENERIC_RELOC_SECTDIFF || 932 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || 933 (cputype == MachO::CPU_TYPE_ARM && 934 (sectdiff_r_type == MachO::ARM_RELOC_SECTDIFF || 935 sectdiff_r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 936 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF))) { 937 previous_sectdiff = true; 938 sectdiff_r_type = r_type; 939 } else { 940 previous_sectdiff = false; 941 sectdiff_r_type = 0; 942 } 943 if (cputype == MachO::CPU_TYPE_ARM && 944 (r_type == MachO::ARM_RELOC_HALF || 945 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 946 previous_arm_half = true; 947 else 948 previous_arm_half = false; 949 outs() << "\n"; 950 } 951 else { 952 // scattered: address pcrel length extern type scattered value 953 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n", 954 (unsigned int)r_address, r_pcrel, r_length, r_type, 955 (unsigned int)r_value); 956 } 957 } 958 else { 959 if (verbose) { 960 // plain: address 961 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 962 outs() << " "; 963 else 964 outs() << format("%08x ", (unsigned int)r_address); 965 966 // plain: pcrel 967 if (r_pcrel) 968 outs() << "True "; 969 else 970 outs() << "False "; 971 972 // plain: length 973 PrintRLength(cputype, r_type, r_length, previous_arm_half); 974 975 if (r_extern) { 976 // plain: extern & type & scattered 977 outs() << "True "; 978 PrintRType(cputype, r_type); 979 outs() << "False "; 980 981 // plain: symbolnum/value 982 if (r_symbolnum > Symtab.nsyms) 983 outs() << format("?(%d)\n", r_symbolnum); 984 else { 985 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); 986 Expected<StringRef> SymNameNext = Symbol.getName(); 987 const char *name = NULL; 988 if (SymNameNext) 989 name = SymNameNext->data(); 990 if (name == NULL) 991 outs() << format("?(%d)\n", r_symbolnum); 992 else 993 outs() << name << "\n"; 994 } 995 } 996 else { 997 // plain: extern & type & scattered 998 outs() << "False "; 999 PrintRType(cputype, r_type); 1000 outs() << "False "; 1001 1002 // plain: symbolnum/value 1003 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 1004 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); 1005 else if ((cputype == MachO::CPU_TYPE_ARM64 || 1006 cputype == MachO::CPU_TYPE_ARM64_32) && 1007 r_type == MachO::ARM64_RELOC_ADDEND) 1008 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); 1009 else { 1010 outs() << format("%d ", r_symbolnum); 1011 if (r_symbolnum == MachO::R_ABS) 1012 outs() << "R_ABS\n"; 1013 else { 1014 // in this case, r_symbolnum is actually a 1-based section number 1015 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; 1016 if (r_symbolnum > 0 && r_symbolnum <= nsects) { 1017 object::DataRefImpl DRI; 1018 DRI.d.a = r_symbolnum-1; 1019 StringRef SegName = O->getSectionFinalSegmentName(DRI); 1020 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1021 outs() << "(" << SegName << "," << *NameOrErr << ")\n"; 1022 else 1023 outs() << "(?,?)\n"; 1024 } 1025 else { 1026 outs() << "(?,?)\n"; 1027 } 1028 } 1029 } 1030 } 1031 if (cputype == MachO::CPU_TYPE_ARM && 1032 (r_type == MachO::ARM_RELOC_HALF || 1033 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 1034 previous_arm_half = true; 1035 else 1036 previous_arm_half = false; 1037 } 1038 else { 1039 // plain: address pcrel length extern type scattered symbolnum/section 1040 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n", 1041 (unsigned int)r_address, r_pcrel, r_length, r_extern, 1042 r_type, r_symbolnum); 1043 } 1044 } 1045 } 1046 } 1047 1048 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { 1049 const uint64_t cputype = O->getHeader().cputype; 1050 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 1051 if (Dysymtab.nextrel != 0) { 1052 outs() << "External relocation information " << Dysymtab.nextrel 1053 << " entries"; 1054 outs() << "\naddress pcrel length extern type scattered " 1055 "symbolnum/value\n"; 1056 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, 1057 verbose); 1058 } 1059 if (Dysymtab.nlocrel != 0) { 1060 outs() << format("Local relocation information %u entries", 1061 Dysymtab.nlocrel); 1062 outs() << "\naddress pcrel length extern type scattered " 1063 "symbolnum/value\n"; 1064 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, 1065 verbose); 1066 } 1067 for (const auto &Load : O->load_commands()) { 1068 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 1069 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 1070 for (unsigned J = 0; J < Seg.nsects; ++J) { 1071 const MachO::section_64 Sec = O->getSection64(Load, J); 1072 if (Sec.nreloc != 0) { 1073 DataRefImpl DRI; 1074 DRI.d.a = J; 1075 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1076 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1077 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1078 << format(") %u entries", Sec.nreloc); 1079 else 1080 outs() << "Relocation information (" << SegName << ",?) " 1081 << format("%u entries", Sec.nreloc); 1082 outs() << "\naddress pcrel length extern type scattered " 1083 "symbolnum/value\n"; 1084 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1085 O->section_rel_end(DRI), cputype, verbose); 1086 } 1087 } 1088 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1089 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 1090 for (unsigned J = 0; J < Seg.nsects; ++J) { 1091 const MachO::section Sec = O->getSection(Load, J); 1092 if (Sec.nreloc != 0) { 1093 DataRefImpl DRI; 1094 DRI.d.a = J; 1095 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1096 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1097 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1098 << format(") %u entries", Sec.nreloc); 1099 else 1100 outs() << "Relocation information (" << SegName << ",?) " 1101 << format("%u entries", Sec.nreloc); 1102 outs() << "\naddress pcrel length extern type scattered " 1103 "symbolnum/value\n"; 1104 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1105 O->section_rel_end(DRI), cputype, verbose); 1106 } 1107 } 1108 } 1109 } 1110 } 1111 1112 static void PrintFunctionStarts(MachOObjectFile *O) { 1113 uint64_t BaseSegmentAddress = 0; 1114 for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) { 1115 if (Command.C.cmd == MachO::LC_SEGMENT) { 1116 MachO::segment_command SLC = O->getSegmentLoadCommand(Command); 1117 if (StringRef(SLC.segname) == "__TEXT") { 1118 BaseSegmentAddress = SLC.vmaddr; 1119 break; 1120 } 1121 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 1122 MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command); 1123 if (StringRef(SLC.segname) == "__TEXT") { 1124 BaseSegmentAddress = SLC.vmaddr; 1125 break; 1126 } 1127 } 1128 } 1129 1130 SmallVector<uint64_t, 8> FunctionStarts; 1131 for (const MachOObjectFile::LoadCommandInfo &LC : O->load_commands()) { 1132 if (LC.C.cmd == MachO::LC_FUNCTION_STARTS) { 1133 MachO::linkedit_data_command FunctionStartsLC = 1134 O->getLinkeditDataLoadCommand(LC); 1135 O->ReadULEB128s(FunctionStartsLC.dataoff, FunctionStarts); 1136 break; 1137 } 1138 } 1139 1140 for (uint64_t S : FunctionStarts) { 1141 uint64_t Addr = BaseSegmentAddress + S; 1142 if (O->is64Bit()) 1143 outs() << format("%016" PRIx64, Addr) << "\n"; 1144 else 1145 outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr)) << "\n"; 1146 } 1147 } 1148 1149 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 1150 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 1151 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 1152 outs() << "Data in code table (" << nentries << " entries)\n"; 1153 outs() << "offset length kind\n"; 1154 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 1155 ++DI) { 1156 uint32_t Offset; 1157 DI->getOffset(Offset); 1158 outs() << format("0x%08" PRIx32, Offset) << " "; 1159 uint16_t Length; 1160 DI->getLength(Length); 1161 outs() << format("%6u", Length) << " "; 1162 uint16_t Kind; 1163 DI->getKind(Kind); 1164 if (verbose) { 1165 switch (Kind) { 1166 case MachO::DICE_KIND_DATA: 1167 outs() << "DATA"; 1168 break; 1169 case MachO::DICE_KIND_JUMP_TABLE8: 1170 outs() << "JUMP_TABLE8"; 1171 break; 1172 case MachO::DICE_KIND_JUMP_TABLE16: 1173 outs() << "JUMP_TABLE16"; 1174 break; 1175 case MachO::DICE_KIND_JUMP_TABLE32: 1176 outs() << "JUMP_TABLE32"; 1177 break; 1178 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 1179 outs() << "ABS_JUMP_TABLE32"; 1180 break; 1181 default: 1182 outs() << format("0x%04" PRIx32, Kind); 1183 break; 1184 } 1185 } else 1186 outs() << format("0x%04" PRIx32, Kind); 1187 outs() << "\n"; 1188 } 1189 } 1190 1191 static void PrintLinkOptHints(MachOObjectFile *O) { 1192 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 1193 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 1194 uint32_t nloh = LohLC.datasize; 1195 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 1196 for (uint32_t i = 0; i < nloh;) { 1197 unsigned n; 1198 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 1199 i += n; 1200 outs() << " identifier " << identifier << " "; 1201 if (i >= nloh) 1202 return; 1203 switch (identifier) { 1204 case 1: 1205 outs() << "AdrpAdrp\n"; 1206 break; 1207 case 2: 1208 outs() << "AdrpLdr\n"; 1209 break; 1210 case 3: 1211 outs() << "AdrpAddLdr\n"; 1212 break; 1213 case 4: 1214 outs() << "AdrpLdrGotLdr\n"; 1215 break; 1216 case 5: 1217 outs() << "AdrpAddStr\n"; 1218 break; 1219 case 6: 1220 outs() << "AdrpLdrGotStr\n"; 1221 break; 1222 case 7: 1223 outs() << "AdrpAdd\n"; 1224 break; 1225 case 8: 1226 outs() << "AdrpLdrGot\n"; 1227 break; 1228 default: 1229 outs() << "Unknown identifier value\n"; 1230 break; 1231 } 1232 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 1233 i += n; 1234 outs() << " narguments " << narguments << "\n"; 1235 if (i >= nloh) 1236 return; 1237 1238 for (uint32_t j = 0; j < narguments; j++) { 1239 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 1240 i += n; 1241 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 1242 if (i >= nloh) 1243 return; 1244 } 1245 } 1246 } 1247 1248 static void PrintDylibs(MachOObjectFile *O, bool JustId) { 1249 unsigned Index = 0; 1250 for (const auto &Load : O->load_commands()) { 1251 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 1252 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 1253 Load.C.cmd == MachO::LC_LOAD_DYLIB || 1254 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 1255 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 1256 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 1257 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 1258 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 1259 if (dl.dylib.name < dl.cmdsize) { 1260 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 1261 if (JustId) 1262 outs() << p << "\n"; 1263 else { 1264 outs() << "\t" << p; 1265 outs() << " (compatibility version " 1266 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 1267 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 1268 << (dl.dylib.compatibility_version & 0xff) << ","; 1269 outs() << " current version " 1270 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 1271 << ((dl.dylib.current_version >> 8) & 0xff) << "." 1272 << (dl.dylib.current_version & 0xff); 1273 if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 1274 outs() << ", weak"; 1275 if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 1276 outs() << ", reexport"; 1277 if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 1278 outs() << ", upward"; 1279 if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 1280 outs() << ", lazy"; 1281 outs() << ")\n"; 1282 } 1283 } else { 1284 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 1285 if (Load.C.cmd == MachO::LC_ID_DYLIB) 1286 outs() << "LC_ID_DYLIB "; 1287 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 1288 outs() << "LC_LOAD_DYLIB "; 1289 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 1290 outs() << "LC_LOAD_WEAK_DYLIB "; 1291 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 1292 outs() << "LC_LAZY_LOAD_DYLIB "; 1293 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 1294 outs() << "LC_REEXPORT_DYLIB "; 1295 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 1296 outs() << "LC_LOAD_UPWARD_DYLIB "; 1297 else 1298 outs() << "LC_??? "; 1299 outs() << "command " << Index++ << "\n"; 1300 } 1301 } 1302 } 1303 } 1304 1305 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 1306 1307 static void CreateSymbolAddressMap(MachOObjectFile *O, 1308 SymbolAddressMap *AddrMap) { 1309 // Create a map of symbol addresses to symbol names. 1310 const StringRef FileName = O->getFileName(); 1311 for (const SymbolRef &Symbol : O->symbols()) { 1312 SymbolRef::Type ST = unwrapOrError(Symbol.getType(), FileName); 1313 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 1314 ST == SymbolRef::ST_Other) { 1315 uint64_t Address = cantFail(Symbol.getValue()); 1316 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 1317 if (!SymName.startswith(".objc")) 1318 (*AddrMap)[Address] = SymName; 1319 } 1320 } 1321 } 1322 1323 // GuessSymbolName is passed the address of what might be a symbol and a 1324 // pointer to the SymbolAddressMap. It returns the name of a symbol 1325 // with that address or nullptr if no symbol is found with that address. 1326 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 1327 const char *SymbolName = nullptr; 1328 // A DenseMap can't lookup up some values. 1329 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 1330 StringRef name = AddrMap->lookup(value); 1331 if (!name.empty()) 1332 SymbolName = name.data(); 1333 } 1334 return SymbolName; 1335 } 1336 1337 static void DumpCstringChar(const char c) { 1338 char p[2]; 1339 p[0] = c; 1340 p[1] = '\0'; 1341 outs().write_escaped(p); 1342 } 1343 1344 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 1345 uint32_t sect_size, uint64_t sect_addr, 1346 bool print_addresses) { 1347 for (uint32_t i = 0; i < sect_size; i++) { 1348 if (print_addresses) { 1349 if (O->is64Bit()) 1350 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1351 else 1352 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1353 } 1354 for (; i < sect_size && sect[i] != '\0'; i++) 1355 DumpCstringChar(sect[i]); 1356 if (i < sect_size && sect[i] == '\0') 1357 outs() << "\n"; 1358 } 1359 } 1360 1361 static void DumpLiteral4(uint32_t l, float f) { 1362 outs() << format("0x%08" PRIx32, l); 1363 if ((l & 0x7f800000) != 0x7f800000) 1364 outs() << format(" (%.16e)\n", f); 1365 else { 1366 if (l == 0x7f800000) 1367 outs() << " (+Infinity)\n"; 1368 else if (l == 0xff800000) 1369 outs() << " (-Infinity)\n"; 1370 else if ((l & 0x00400000) == 0x00400000) 1371 outs() << " (non-signaling Not-a-Number)\n"; 1372 else 1373 outs() << " (signaling Not-a-Number)\n"; 1374 } 1375 } 1376 1377 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 1378 uint32_t sect_size, uint64_t sect_addr, 1379 bool print_addresses) { 1380 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 1381 if (print_addresses) { 1382 if (O->is64Bit()) 1383 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1384 else 1385 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1386 } 1387 float f; 1388 memcpy(&f, sect + i, sizeof(float)); 1389 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1390 sys::swapByteOrder(f); 1391 uint32_t l; 1392 memcpy(&l, sect + i, sizeof(uint32_t)); 1393 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1394 sys::swapByteOrder(l); 1395 DumpLiteral4(l, f); 1396 } 1397 } 1398 1399 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 1400 double d) { 1401 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 1402 uint32_t Hi, Lo; 1403 Hi = (O->isLittleEndian()) ? l1 : l0; 1404 Lo = (O->isLittleEndian()) ? l0 : l1; 1405 1406 // Hi is the high word, so this is equivalent to if(isfinite(d)) 1407 if ((Hi & 0x7ff00000) != 0x7ff00000) 1408 outs() << format(" (%.16e)\n", d); 1409 else { 1410 if (Hi == 0x7ff00000 && Lo == 0) 1411 outs() << " (+Infinity)\n"; 1412 else if (Hi == 0xfff00000 && Lo == 0) 1413 outs() << " (-Infinity)\n"; 1414 else if ((Hi & 0x00080000) == 0x00080000) 1415 outs() << " (non-signaling Not-a-Number)\n"; 1416 else 1417 outs() << " (signaling Not-a-Number)\n"; 1418 } 1419 } 1420 1421 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 1422 uint32_t sect_size, uint64_t sect_addr, 1423 bool print_addresses) { 1424 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 1425 if (print_addresses) { 1426 if (O->is64Bit()) 1427 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1428 else 1429 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1430 } 1431 double d; 1432 memcpy(&d, sect + i, sizeof(double)); 1433 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1434 sys::swapByteOrder(d); 1435 uint32_t l0, l1; 1436 memcpy(&l0, sect + i, sizeof(uint32_t)); 1437 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1438 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1439 sys::swapByteOrder(l0); 1440 sys::swapByteOrder(l1); 1441 } 1442 DumpLiteral8(O, l0, l1, d); 1443 } 1444 } 1445 1446 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 1447 outs() << format("0x%08" PRIx32, l0) << " "; 1448 outs() << format("0x%08" PRIx32, l1) << " "; 1449 outs() << format("0x%08" PRIx32, l2) << " "; 1450 outs() << format("0x%08" PRIx32, l3) << "\n"; 1451 } 1452 1453 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 1454 uint32_t sect_size, uint64_t sect_addr, 1455 bool print_addresses) { 1456 for (uint32_t i = 0; i < sect_size; i += 16) { 1457 if (print_addresses) { 1458 if (O->is64Bit()) 1459 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1460 else 1461 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1462 } 1463 uint32_t l0, l1, l2, l3; 1464 memcpy(&l0, sect + i, sizeof(uint32_t)); 1465 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1466 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 1467 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1468 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1469 sys::swapByteOrder(l0); 1470 sys::swapByteOrder(l1); 1471 sys::swapByteOrder(l2); 1472 sys::swapByteOrder(l3); 1473 } 1474 DumpLiteral16(l0, l1, l2, l3); 1475 } 1476 } 1477 1478 static void DumpLiteralPointerSection(MachOObjectFile *O, 1479 const SectionRef &Section, 1480 const char *sect, uint32_t sect_size, 1481 uint64_t sect_addr, 1482 bool print_addresses) { 1483 // Collect the literal sections in this Mach-O file. 1484 std::vector<SectionRef> LiteralSections; 1485 for (const SectionRef &Section : O->sections()) { 1486 DataRefImpl Ref = Section.getRawDataRefImpl(); 1487 uint32_t section_type; 1488 if (O->is64Bit()) { 1489 const MachO::section_64 Sec = O->getSection64(Ref); 1490 section_type = Sec.flags & MachO::SECTION_TYPE; 1491 } else { 1492 const MachO::section Sec = O->getSection(Ref); 1493 section_type = Sec.flags & MachO::SECTION_TYPE; 1494 } 1495 if (section_type == MachO::S_CSTRING_LITERALS || 1496 section_type == MachO::S_4BYTE_LITERALS || 1497 section_type == MachO::S_8BYTE_LITERALS || 1498 section_type == MachO::S_16BYTE_LITERALS) 1499 LiteralSections.push_back(Section); 1500 } 1501 1502 // Set the size of the literal pointer. 1503 uint32_t lp_size = O->is64Bit() ? 8 : 4; 1504 1505 // Collect the external relocation symbols for the literal pointers. 1506 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1507 for (const RelocationRef &Reloc : Section.relocations()) { 1508 DataRefImpl Rel; 1509 MachO::any_relocation_info RE; 1510 bool isExtern = false; 1511 Rel = Reloc.getRawDataRefImpl(); 1512 RE = O->getRelocation(Rel); 1513 isExtern = O->getPlainRelocationExternal(RE); 1514 if (isExtern) { 1515 uint64_t RelocOffset = Reloc.getOffset(); 1516 symbol_iterator RelocSym = Reloc.getSymbol(); 1517 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1518 } 1519 } 1520 array_pod_sort(Relocs.begin(), Relocs.end()); 1521 1522 // Dump each literal pointer. 1523 for (uint32_t i = 0; i < sect_size; i += lp_size) { 1524 if (print_addresses) { 1525 if (O->is64Bit()) 1526 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1527 else 1528 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1529 } 1530 uint64_t lp; 1531 if (O->is64Bit()) { 1532 memcpy(&lp, sect + i, sizeof(uint64_t)); 1533 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1534 sys::swapByteOrder(lp); 1535 } else { 1536 uint32_t li; 1537 memcpy(&li, sect + i, sizeof(uint32_t)); 1538 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1539 sys::swapByteOrder(li); 1540 lp = li; 1541 } 1542 1543 // First look for an external relocation entry for this literal pointer. 1544 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1545 return P.first == i; 1546 }); 1547 if (Reloc != Relocs.end()) { 1548 symbol_iterator RelocSym = Reloc->second; 1549 StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName()); 1550 outs() << "external relocation entry for symbol:" << SymName << "\n"; 1551 continue; 1552 } 1553 1554 // For local references see what the section the literal pointer points to. 1555 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 1556 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 1557 }); 1558 if (Sect == LiteralSections.end()) { 1559 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 1560 continue; 1561 } 1562 1563 uint64_t SectAddress = Sect->getAddress(); 1564 uint64_t SectSize = Sect->getSize(); 1565 1566 StringRef SectName; 1567 Expected<StringRef> SectNameOrErr = Sect->getName(); 1568 if (SectNameOrErr) 1569 SectName = *SectNameOrErr; 1570 else 1571 consumeError(SectNameOrErr.takeError()); 1572 1573 DataRefImpl Ref = Sect->getRawDataRefImpl(); 1574 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 1575 outs() << SegmentName << ":" << SectName << ":"; 1576 1577 uint32_t section_type; 1578 if (O->is64Bit()) { 1579 const MachO::section_64 Sec = O->getSection64(Ref); 1580 section_type = Sec.flags & MachO::SECTION_TYPE; 1581 } else { 1582 const MachO::section Sec = O->getSection(Ref); 1583 section_type = Sec.flags & MachO::SECTION_TYPE; 1584 } 1585 1586 StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName()); 1587 1588 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 1589 1590 switch (section_type) { 1591 case MachO::S_CSTRING_LITERALS: 1592 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 1593 i++) { 1594 DumpCstringChar(Contents[i]); 1595 } 1596 outs() << "\n"; 1597 break; 1598 case MachO::S_4BYTE_LITERALS: 1599 float f; 1600 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 1601 uint32_t l; 1602 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 1603 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1604 sys::swapByteOrder(f); 1605 sys::swapByteOrder(l); 1606 } 1607 DumpLiteral4(l, f); 1608 break; 1609 case MachO::S_8BYTE_LITERALS: { 1610 double d; 1611 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 1612 uint32_t l0, l1; 1613 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1614 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1615 sizeof(uint32_t)); 1616 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1617 sys::swapByteOrder(f); 1618 sys::swapByteOrder(l0); 1619 sys::swapByteOrder(l1); 1620 } 1621 DumpLiteral8(O, l0, l1, d); 1622 break; 1623 } 1624 case MachO::S_16BYTE_LITERALS: { 1625 uint32_t l0, l1, l2, l3; 1626 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1627 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1628 sizeof(uint32_t)); 1629 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 1630 sizeof(uint32_t)); 1631 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 1632 sizeof(uint32_t)); 1633 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1634 sys::swapByteOrder(l0); 1635 sys::swapByteOrder(l1); 1636 sys::swapByteOrder(l2); 1637 sys::swapByteOrder(l3); 1638 } 1639 DumpLiteral16(l0, l1, l2, l3); 1640 break; 1641 } 1642 } 1643 } 1644 } 1645 1646 static void DumpInitTermPointerSection(MachOObjectFile *O, 1647 const SectionRef &Section, 1648 const char *sect, 1649 uint32_t sect_size, uint64_t sect_addr, 1650 SymbolAddressMap *AddrMap, 1651 bool verbose) { 1652 uint32_t stride; 1653 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 1654 1655 // Collect the external relocation symbols for the pointers. 1656 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1657 for (const RelocationRef &Reloc : Section.relocations()) { 1658 DataRefImpl Rel; 1659 MachO::any_relocation_info RE; 1660 bool isExtern = false; 1661 Rel = Reloc.getRawDataRefImpl(); 1662 RE = O->getRelocation(Rel); 1663 isExtern = O->getPlainRelocationExternal(RE); 1664 if (isExtern) { 1665 uint64_t RelocOffset = Reloc.getOffset(); 1666 symbol_iterator RelocSym = Reloc.getSymbol(); 1667 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1668 } 1669 } 1670 array_pod_sort(Relocs.begin(), Relocs.end()); 1671 1672 for (uint32_t i = 0; i < sect_size; i += stride) { 1673 const char *SymbolName = nullptr; 1674 uint64_t p; 1675 if (O->is64Bit()) { 1676 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 1677 uint64_t pointer_value; 1678 memcpy(&pointer_value, sect + i, stride); 1679 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1680 sys::swapByteOrder(pointer_value); 1681 outs() << format("0x%016" PRIx64, pointer_value); 1682 p = pointer_value; 1683 } else { 1684 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 1685 uint32_t pointer_value; 1686 memcpy(&pointer_value, sect + i, stride); 1687 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1688 sys::swapByteOrder(pointer_value); 1689 outs() << format("0x%08" PRIx32, pointer_value); 1690 p = pointer_value; 1691 } 1692 if (verbose) { 1693 // First look for an external relocation entry for this pointer. 1694 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1695 return P.first == i; 1696 }); 1697 if (Reloc != Relocs.end()) { 1698 symbol_iterator RelocSym = Reloc->second; 1699 outs() << " " << unwrapOrError(RelocSym->getName(), O->getFileName()); 1700 } else { 1701 SymbolName = GuessSymbolName(p, AddrMap); 1702 if (SymbolName) 1703 outs() << " " << SymbolName; 1704 } 1705 } 1706 outs() << "\n"; 1707 } 1708 } 1709 1710 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 1711 uint32_t size, uint64_t addr) { 1712 uint32_t cputype = O->getHeader().cputype; 1713 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 1714 uint32_t j; 1715 for (uint32_t i = 0; i < size; i += j, addr += j) { 1716 if (O->is64Bit()) 1717 outs() << format("%016" PRIx64, addr) << "\t"; 1718 else 1719 outs() << format("%08" PRIx64, addr) << "\t"; 1720 for (j = 0; j < 16 && i + j < size; j++) { 1721 uint8_t byte_word = *(sect + i + j); 1722 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1723 } 1724 outs() << "\n"; 1725 } 1726 } else { 1727 uint32_t j; 1728 for (uint32_t i = 0; i < size; i += j, addr += j) { 1729 if (O->is64Bit()) 1730 outs() << format("%016" PRIx64, addr) << "\t"; 1731 else 1732 outs() << format("%08" PRIx64, addr) << "\t"; 1733 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 1734 j += sizeof(int32_t)) { 1735 if (i + j + sizeof(int32_t) <= size) { 1736 uint32_t long_word; 1737 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1738 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1739 sys::swapByteOrder(long_word); 1740 outs() << format("%08" PRIx32, long_word) << " "; 1741 } else { 1742 for (uint32_t k = 0; i + j + k < size; k++) { 1743 uint8_t byte_word = *(sect + i + j + k); 1744 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1745 } 1746 } 1747 } 1748 outs() << "\n"; 1749 } 1750 } 1751 } 1752 1753 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1754 StringRef DisSegName, StringRef DisSectName); 1755 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1756 uint32_t size, uint32_t addr); 1757 #ifdef HAVE_LIBXAR 1758 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 1759 uint32_t size, bool verbose, 1760 bool PrintXarHeader, bool PrintXarFileHeaders, 1761 std::string XarMemberName); 1762 #endif // defined(HAVE_LIBXAR) 1763 1764 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1765 bool verbose) { 1766 SymbolAddressMap AddrMap; 1767 if (verbose) 1768 CreateSymbolAddressMap(O, &AddrMap); 1769 1770 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1771 StringRef DumpSection = FilterSections[i]; 1772 std::pair<StringRef, StringRef> DumpSegSectName; 1773 DumpSegSectName = DumpSection.split(','); 1774 StringRef DumpSegName, DumpSectName; 1775 if (!DumpSegSectName.second.empty()) { 1776 DumpSegName = DumpSegSectName.first; 1777 DumpSectName = DumpSegSectName.second; 1778 } else { 1779 DumpSegName = ""; 1780 DumpSectName = DumpSegSectName.first; 1781 } 1782 for (const SectionRef &Section : O->sections()) { 1783 StringRef SectName; 1784 Expected<StringRef> SecNameOrErr = Section.getName(); 1785 if (SecNameOrErr) 1786 SectName = *SecNameOrErr; 1787 else 1788 consumeError(SecNameOrErr.takeError()); 1789 1790 if (!DumpSection.empty()) 1791 FoundSectionSet.insert(DumpSection); 1792 1793 DataRefImpl Ref = Section.getRawDataRefImpl(); 1794 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1795 if ((DumpSegName.empty() || SegName == DumpSegName) && 1796 (SectName == DumpSectName)) { 1797 1798 uint32_t section_flags; 1799 if (O->is64Bit()) { 1800 const MachO::section_64 Sec = O->getSection64(Ref); 1801 section_flags = Sec.flags; 1802 1803 } else { 1804 const MachO::section Sec = O->getSection(Ref); 1805 section_flags = Sec.flags; 1806 } 1807 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1808 1809 StringRef BytesStr = 1810 unwrapOrError(Section.getContents(), O->getFileName()); 1811 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1812 uint32_t sect_size = BytesStr.size(); 1813 uint64_t sect_addr = Section.getAddress(); 1814 1815 if (!NoLeadingHeaders) 1816 outs() << "Contents of (" << SegName << "," << SectName 1817 << ") section\n"; 1818 1819 if (verbose) { 1820 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1821 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1822 DisassembleMachO(Filename, O, SegName, SectName); 1823 continue; 1824 } 1825 if (SegName == "__TEXT" && SectName == "__info_plist") { 1826 outs() << sect; 1827 continue; 1828 } 1829 if (SegName == "__OBJC" && SectName == "__protocol") { 1830 DumpProtocolSection(O, sect, sect_size, sect_addr); 1831 continue; 1832 } 1833 #ifdef HAVE_LIBXAR 1834 if (SegName == "__LLVM" && SectName == "__bundle") { 1835 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands, 1836 ArchiveHeaders, ""); 1837 continue; 1838 } 1839 #endif // defined(HAVE_LIBXAR) 1840 switch (section_type) { 1841 case MachO::S_REGULAR: 1842 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1843 break; 1844 case MachO::S_ZEROFILL: 1845 outs() << "zerofill section and has no contents in the file\n"; 1846 break; 1847 case MachO::S_CSTRING_LITERALS: 1848 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1849 break; 1850 case MachO::S_4BYTE_LITERALS: 1851 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1852 break; 1853 case MachO::S_8BYTE_LITERALS: 1854 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1855 break; 1856 case MachO::S_16BYTE_LITERALS: 1857 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1858 break; 1859 case MachO::S_LITERAL_POINTERS: 1860 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1861 !NoLeadingAddr); 1862 break; 1863 case MachO::S_MOD_INIT_FUNC_POINTERS: 1864 case MachO::S_MOD_TERM_FUNC_POINTERS: 1865 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr, 1866 &AddrMap, verbose); 1867 break; 1868 default: 1869 outs() << "Unknown section type (" 1870 << format("0x%08" PRIx32, section_type) << ")\n"; 1871 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1872 break; 1873 } 1874 } else { 1875 if (section_type == MachO::S_ZEROFILL) 1876 outs() << "zerofill section and has no contents in the file\n"; 1877 else 1878 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1879 } 1880 } 1881 } 1882 } 1883 } 1884 1885 static void DumpInfoPlistSectionContents(StringRef Filename, 1886 MachOObjectFile *O) { 1887 for (const SectionRef &Section : O->sections()) { 1888 StringRef SectName; 1889 Expected<StringRef> SecNameOrErr = Section.getName(); 1890 if (SecNameOrErr) 1891 SectName = *SecNameOrErr; 1892 else 1893 consumeError(SecNameOrErr.takeError()); 1894 1895 DataRefImpl Ref = Section.getRawDataRefImpl(); 1896 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1897 if (SegName == "__TEXT" && SectName == "__info_plist") { 1898 if (!NoLeadingHeaders) 1899 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1900 StringRef BytesStr = 1901 unwrapOrError(Section.getContents(), O->getFileName()); 1902 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1903 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 1904 return; 1905 } 1906 } 1907 } 1908 1909 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1910 // and if it is and there is a list of architecture flags is specified then 1911 // check to make sure this Mach-O file is one of those architectures or all 1912 // architectures were specified. If not then an error is generated and this 1913 // routine returns false. Else it returns true. 1914 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1915 auto *MachO = dyn_cast<MachOObjectFile>(O); 1916 1917 if (!MachO || ArchAll || ArchFlags.empty()) 1918 return true; 1919 1920 MachO::mach_header H; 1921 MachO::mach_header_64 H_64; 1922 Triple T; 1923 const char *McpuDefault, *ArchFlag; 1924 if (MachO->is64Bit()) { 1925 H_64 = MachO->MachOObjectFile::getHeader64(); 1926 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 1927 &McpuDefault, &ArchFlag); 1928 } else { 1929 H = MachO->MachOObjectFile::getHeader(); 1930 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 1931 &McpuDefault, &ArchFlag); 1932 } 1933 const std::string ArchFlagName(ArchFlag); 1934 if (!llvm::is_contained(ArchFlags, ArchFlagName)) { 1935 WithColor::error(errs(), "llvm-objdump") 1936 << Filename << ": no architecture specified.\n"; 1937 return false; 1938 } 1939 return true; 1940 } 1941 1942 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 1943 1944 // ProcessMachO() is passed a single opened Mach-O file, which may be an 1945 // archive member and or in a slice of a universal file. It prints the 1946 // the file name and header info and then processes it according to the 1947 // command line options. 1948 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 1949 StringRef ArchiveMemberName = StringRef(), 1950 StringRef ArchitectureName = StringRef()) { 1951 // If we are doing some processing here on the Mach-O file print the header 1952 // info. And don't print it otherwise like in the case of printing the 1953 // UniversalHeaders or ArchiveHeaders. 1954 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || 1955 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || 1956 DataInCode || FunctionStarts || LinkOptHints || DylibsUsed || DylibId || 1957 ObjcMetaData || (!FilterSections.empty())) { 1958 if (!NoLeadingHeaders) { 1959 outs() << Name; 1960 if (!ArchiveMemberName.empty()) 1961 outs() << '(' << ArchiveMemberName << ')'; 1962 if (!ArchitectureName.empty()) 1963 outs() << " (architecture " << ArchitectureName << ")"; 1964 outs() << ":\n"; 1965 } 1966 } 1967 // To use the report_error() form with an ArchiveName and FileName set 1968 // these up based on what is passed for Name and ArchiveMemberName. 1969 StringRef ArchiveName; 1970 StringRef FileName; 1971 if (!ArchiveMemberName.empty()) { 1972 ArchiveName = Name; 1973 FileName = ArchiveMemberName; 1974 } else { 1975 ArchiveName = StringRef(); 1976 FileName = Name; 1977 } 1978 1979 // If we need the symbol table to do the operation then check it here to 1980 // produce a good error message as to where the Mach-O file comes from in 1981 // the error message. 1982 if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo) 1983 if (Error Err = MachOOF->checkSymbolTable()) 1984 reportError(std::move(Err), FileName, ArchiveName, ArchitectureName); 1985 1986 if (DisassembleAll) { 1987 for (const SectionRef &Section : MachOOF->sections()) { 1988 StringRef SectName; 1989 if (Expected<StringRef> NameOrErr = Section.getName()) 1990 SectName = *NameOrErr; 1991 else 1992 consumeError(NameOrErr.takeError()); 1993 1994 if (SectName.equals("__text")) { 1995 DataRefImpl Ref = Section.getRawDataRefImpl(); 1996 StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref); 1997 DisassembleMachO(FileName, MachOOF, SegName, SectName); 1998 } 1999 } 2000 } 2001 else if (Disassemble) { 2002 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE && 2003 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64) 2004 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text"); 2005 else 2006 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 2007 } 2008 if (IndirectSymbols) 2009 PrintIndirectSymbols(MachOOF, !NonVerbose); 2010 if (DataInCode) 2011 PrintDataInCodeTable(MachOOF, !NonVerbose); 2012 if (FunctionStarts) 2013 PrintFunctionStarts(MachOOF); 2014 if (LinkOptHints) 2015 PrintLinkOptHints(MachOOF); 2016 if (Relocations) 2017 PrintRelocations(MachOOF, !NonVerbose); 2018 if (SectionHeaders) 2019 printSectionHeaders(MachOOF); 2020 if (SectionContents) 2021 printSectionContents(MachOOF); 2022 if (!FilterSections.empty()) 2023 DumpSectionContents(FileName, MachOOF, !NonVerbose); 2024 if (InfoPlist) 2025 DumpInfoPlistSectionContents(FileName, MachOOF); 2026 if (DylibsUsed) 2027 PrintDylibs(MachOOF, false); 2028 if (DylibId) 2029 PrintDylibs(MachOOF, true); 2030 if (SymbolTable) 2031 printSymbolTable(MachOOF, ArchiveName, ArchitectureName); 2032 if (UnwindInfo) 2033 printMachOUnwindInfo(MachOOF); 2034 if (PrivateHeaders) { 2035 printMachOFileHeader(MachOOF); 2036 printMachOLoadCommands(MachOOF); 2037 } 2038 if (FirstPrivateHeader) 2039 printMachOFileHeader(MachOOF); 2040 if (ObjcMetaData) 2041 printObjcMetaData(MachOOF, !NonVerbose); 2042 if (ExportsTrie) 2043 printExportsTrie(MachOOF); 2044 if (Rebase) 2045 printRebaseTable(MachOOF); 2046 if (Bind) 2047 printBindTable(MachOOF); 2048 if (LazyBind) 2049 printLazyBindTable(MachOOF); 2050 if (WeakBind) 2051 printWeakBindTable(MachOOF); 2052 2053 if (DwarfDumpType != DIDT_Null) { 2054 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF); 2055 // Dump the complete DWARF structure. 2056 DIDumpOptions DumpOpts; 2057 DumpOpts.DumpType = DwarfDumpType; 2058 DICtx->dump(outs(), DumpOpts); 2059 } 2060 } 2061 2062 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 2063 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 2064 outs() << " cputype (" << cputype << ")\n"; 2065 outs() << " cpusubtype (" << cpusubtype << ")\n"; 2066 } 2067 2068 // printCPUType() helps print_fat_headers by printing the cputype and 2069 // pusubtype (symbolically for the one's it knows about). 2070 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 2071 switch (cputype) { 2072 case MachO::CPU_TYPE_I386: 2073 switch (cpusubtype) { 2074 case MachO::CPU_SUBTYPE_I386_ALL: 2075 outs() << " cputype CPU_TYPE_I386\n"; 2076 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 2077 break; 2078 default: 2079 printUnknownCPUType(cputype, cpusubtype); 2080 break; 2081 } 2082 break; 2083 case MachO::CPU_TYPE_X86_64: 2084 switch (cpusubtype) { 2085 case MachO::CPU_SUBTYPE_X86_64_ALL: 2086 outs() << " cputype CPU_TYPE_X86_64\n"; 2087 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 2088 break; 2089 case MachO::CPU_SUBTYPE_X86_64_H: 2090 outs() << " cputype CPU_TYPE_X86_64\n"; 2091 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 2092 break; 2093 default: 2094 printUnknownCPUType(cputype, cpusubtype); 2095 break; 2096 } 2097 break; 2098 case MachO::CPU_TYPE_ARM: 2099 switch (cpusubtype) { 2100 case MachO::CPU_SUBTYPE_ARM_ALL: 2101 outs() << " cputype CPU_TYPE_ARM\n"; 2102 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 2103 break; 2104 case MachO::CPU_SUBTYPE_ARM_V4T: 2105 outs() << " cputype CPU_TYPE_ARM\n"; 2106 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 2107 break; 2108 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2109 outs() << " cputype CPU_TYPE_ARM\n"; 2110 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 2111 break; 2112 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2113 outs() << " cputype CPU_TYPE_ARM\n"; 2114 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 2115 break; 2116 case MachO::CPU_SUBTYPE_ARM_V6: 2117 outs() << " cputype CPU_TYPE_ARM\n"; 2118 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 2119 break; 2120 case MachO::CPU_SUBTYPE_ARM_V6M: 2121 outs() << " cputype CPU_TYPE_ARM\n"; 2122 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 2123 break; 2124 case MachO::CPU_SUBTYPE_ARM_V7: 2125 outs() << " cputype CPU_TYPE_ARM\n"; 2126 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 2127 break; 2128 case MachO::CPU_SUBTYPE_ARM_V7EM: 2129 outs() << " cputype CPU_TYPE_ARM\n"; 2130 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 2131 break; 2132 case MachO::CPU_SUBTYPE_ARM_V7K: 2133 outs() << " cputype CPU_TYPE_ARM\n"; 2134 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 2135 break; 2136 case MachO::CPU_SUBTYPE_ARM_V7M: 2137 outs() << " cputype CPU_TYPE_ARM\n"; 2138 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 2139 break; 2140 case MachO::CPU_SUBTYPE_ARM_V7S: 2141 outs() << " cputype CPU_TYPE_ARM\n"; 2142 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 2143 break; 2144 default: 2145 printUnknownCPUType(cputype, cpusubtype); 2146 break; 2147 } 2148 break; 2149 case MachO::CPU_TYPE_ARM64: 2150 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2151 case MachO::CPU_SUBTYPE_ARM64_ALL: 2152 outs() << " cputype CPU_TYPE_ARM64\n"; 2153 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 2154 break; 2155 case MachO::CPU_SUBTYPE_ARM64_V8: 2156 outs() << " cputype CPU_TYPE_ARM64\n"; 2157 outs() << " cpusubtype CPU_SUBTYPE_ARM64_V8\n"; 2158 break; 2159 case MachO::CPU_SUBTYPE_ARM64E: 2160 outs() << " cputype CPU_TYPE_ARM64\n"; 2161 outs() << " cpusubtype CPU_SUBTYPE_ARM64E\n"; 2162 break; 2163 default: 2164 printUnknownCPUType(cputype, cpusubtype); 2165 break; 2166 } 2167 break; 2168 case MachO::CPU_TYPE_ARM64_32: 2169 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2170 case MachO::CPU_SUBTYPE_ARM64_32_V8: 2171 outs() << " cputype CPU_TYPE_ARM64_32\n"; 2172 outs() << " cpusubtype CPU_SUBTYPE_ARM64_32_V8\n"; 2173 break; 2174 default: 2175 printUnknownCPUType(cputype, cpusubtype); 2176 break; 2177 } 2178 break; 2179 default: 2180 printUnknownCPUType(cputype, cpusubtype); 2181 break; 2182 } 2183 } 2184 2185 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 2186 bool verbose) { 2187 outs() << "Fat headers\n"; 2188 if (verbose) { 2189 if (UB->getMagic() == MachO::FAT_MAGIC) 2190 outs() << "fat_magic FAT_MAGIC\n"; 2191 else // UB->getMagic() == MachO::FAT_MAGIC_64 2192 outs() << "fat_magic FAT_MAGIC_64\n"; 2193 } else 2194 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 2195 2196 uint32_t nfat_arch = UB->getNumberOfObjects(); 2197 StringRef Buf = UB->getData(); 2198 uint64_t size = Buf.size(); 2199 uint64_t big_size = sizeof(struct MachO::fat_header) + 2200 nfat_arch * sizeof(struct MachO::fat_arch); 2201 outs() << "nfat_arch " << UB->getNumberOfObjects(); 2202 if (nfat_arch == 0) 2203 outs() << " (malformed, contains zero architecture types)\n"; 2204 else if (big_size > size) 2205 outs() << " (malformed, architectures past end of file)\n"; 2206 else 2207 outs() << "\n"; 2208 2209 for (uint32_t i = 0; i < nfat_arch; ++i) { 2210 MachOUniversalBinary::ObjectForArch OFA(UB, i); 2211 uint32_t cputype = OFA.getCPUType(); 2212 uint32_t cpusubtype = OFA.getCPUSubType(); 2213 outs() << "architecture "; 2214 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 2215 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 2216 uint32_t other_cputype = other_OFA.getCPUType(); 2217 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 2218 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 2219 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 2220 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 2221 outs() << "(illegal duplicate architecture) "; 2222 break; 2223 } 2224 } 2225 if (verbose) { 2226 outs() << OFA.getArchFlagName() << "\n"; 2227 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2228 } else { 2229 outs() << i << "\n"; 2230 outs() << " cputype " << cputype << "\n"; 2231 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 2232 << "\n"; 2233 } 2234 if (verbose && 2235 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 2236 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 2237 else 2238 outs() << " capabilities " 2239 << format("0x%" PRIx32, 2240 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 2241 outs() << " offset " << OFA.getOffset(); 2242 if (OFA.getOffset() > size) 2243 outs() << " (past end of file)"; 2244 if (OFA.getOffset() % (1ull << OFA.getAlign()) != 0) 2245 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 2246 outs() << "\n"; 2247 outs() << " size " << OFA.getSize(); 2248 big_size = OFA.getOffset() + OFA.getSize(); 2249 if (big_size > size) 2250 outs() << " (past end of file)"; 2251 outs() << "\n"; 2252 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 2253 << ")\n"; 2254 } 2255 } 2256 2257 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 2258 size_t ChildIndex, bool verbose, 2259 bool print_offset, 2260 StringRef ArchitectureName = StringRef()) { 2261 if (print_offset) 2262 outs() << C.getChildOffset() << "\t"; 2263 sys::fs::perms Mode = 2264 unwrapOrError(C.getAccessMode(), getFileNameForError(C, ChildIndex), 2265 Filename, ArchitectureName); 2266 if (verbose) { 2267 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 2268 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 2269 outs() << "-"; 2270 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 2271 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 2272 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 2273 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 2274 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 2275 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 2276 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 2277 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 2278 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 2279 } else { 2280 outs() << format("0%o ", Mode); 2281 } 2282 2283 outs() << format("%3d/%-3d %5" PRId64 " ", 2284 unwrapOrError(C.getUID(), getFileNameForError(C, ChildIndex), 2285 Filename, ArchitectureName), 2286 unwrapOrError(C.getGID(), getFileNameForError(C, ChildIndex), 2287 Filename, ArchitectureName), 2288 unwrapOrError(C.getRawSize(), 2289 getFileNameForError(C, ChildIndex), Filename, 2290 ArchitectureName)); 2291 2292 StringRef RawLastModified = C.getRawLastModified(); 2293 if (verbose) { 2294 unsigned Seconds; 2295 if (RawLastModified.getAsInteger(10, Seconds)) 2296 outs() << "(date: \"" << RawLastModified 2297 << "\" contains non-decimal chars) "; 2298 else { 2299 // Since cime(3) returns a 26 character string of the form: 2300 // "Sun Sep 16 01:03:52 1973\n\0" 2301 // just print 24 characters. 2302 time_t t = Seconds; 2303 outs() << format("%.24s ", ctime(&t)); 2304 } 2305 } else { 2306 outs() << RawLastModified << " "; 2307 } 2308 2309 if (verbose) { 2310 Expected<StringRef> NameOrErr = C.getName(); 2311 if (!NameOrErr) { 2312 consumeError(NameOrErr.takeError()); 2313 outs() << unwrapOrError(C.getRawName(), 2314 getFileNameForError(C, ChildIndex), Filename, 2315 ArchitectureName) 2316 << "\n"; 2317 } else { 2318 StringRef Name = NameOrErr.get(); 2319 outs() << Name << "\n"; 2320 } 2321 } else { 2322 outs() << unwrapOrError(C.getRawName(), getFileNameForError(C, ChildIndex), 2323 Filename, ArchitectureName) 2324 << "\n"; 2325 } 2326 } 2327 2328 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 2329 bool print_offset, 2330 StringRef ArchitectureName = StringRef()) { 2331 Error Err = Error::success(); 2332 size_t I = 0; 2333 for (const auto &C : A->children(Err, false)) 2334 printArchiveChild(Filename, C, I++, verbose, print_offset, 2335 ArchitectureName); 2336 2337 if (Err) 2338 reportError(std::move(Err), Filename, "", ArchitectureName); 2339 } 2340 2341 static bool ValidateArchFlags() { 2342 // Check for -arch all and verifiy the -arch flags are valid. 2343 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2344 if (ArchFlags[i] == "all") { 2345 ArchAll = true; 2346 } else { 2347 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 2348 WithColor::error(errs(), "llvm-objdump") 2349 << "unknown architecture named '" + ArchFlags[i] + 2350 "'for the -arch option\n"; 2351 return false; 2352 } 2353 } 2354 } 2355 return true; 2356 } 2357 2358 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 2359 // -arch flags selecting just those slices as specified by them and also parses 2360 // archive files. Then for each individual Mach-O file ProcessMachO() is 2361 // called to process the file based on the command line options. 2362 void objdump::parseInputMachO(StringRef Filename) { 2363 if (!ValidateArchFlags()) 2364 return; 2365 2366 // Attempt to open the binary. 2367 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 2368 if (!BinaryOrErr) { 2369 if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 2370 reportError(std::move(E), Filename); 2371 else 2372 outs() << Filename << ": is not an object file\n"; 2373 return; 2374 } 2375 Binary &Bin = *BinaryOrErr.get().getBinary(); 2376 2377 if (Archive *A = dyn_cast<Archive>(&Bin)) { 2378 outs() << "Archive : " << Filename << "\n"; 2379 if (ArchiveHeaders) 2380 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets); 2381 2382 Error Err = Error::success(); 2383 unsigned I = -1; 2384 for (auto &C : A->children(Err)) { 2385 ++I; 2386 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2387 if (!ChildOrErr) { 2388 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2389 reportError(std::move(E), getFileNameForError(C, I), Filename); 2390 continue; 2391 } 2392 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2393 if (!checkMachOAndArchFlags(O, Filename)) 2394 return; 2395 ProcessMachO(Filename, O, O->getFileName()); 2396 } 2397 } 2398 if (Err) 2399 reportError(std::move(Err), Filename); 2400 return; 2401 } 2402 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 2403 parseInputMachO(UB); 2404 return; 2405 } 2406 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2407 if (!checkMachOAndArchFlags(O, Filename)) 2408 return; 2409 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) 2410 ProcessMachO(Filename, MachOOF); 2411 else 2412 WithColor::error(errs(), "llvm-objdump") 2413 << Filename << "': " 2414 << "object is not a Mach-O file type.\n"; 2415 return; 2416 } 2417 llvm_unreachable("Input object can't be invalid at this point"); 2418 } 2419 2420 void objdump::parseInputMachO(MachOUniversalBinary *UB) { 2421 if (!ValidateArchFlags()) 2422 return; 2423 2424 auto Filename = UB->getFileName(); 2425 2426 if (UniversalHeaders) 2427 printMachOUniversalHeaders(UB, !NonVerbose); 2428 2429 // If we have a list of architecture flags specified dump only those. 2430 if (!ArchAll && !ArchFlags.empty()) { 2431 // Look for a slice in the universal binary that matches each ArchFlag. 2432 bool ArchFound; 2433 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2434 ArchFound = false; 2435 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2436 E = UB->end_objects(); 2437 I != E; ++I) { 2438 if (ArchFlags[i] == I->getArchFlagName()) { 2439 ArchFound = true; 2440 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2441 I->getAsObjectFile(); 2442 std::string ArchitectureName; 2443 if (ArchFlags.size() > 1) 2444 ArchitectureName = I->getArchFlagName(); 2445 if (ObjOrErr) { 2446 ObjectFile &O = *ObjOrErr.get(); 2447 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2448 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2449 } else if (Error E = isNotObjectErrorInvalidFileType( 2450 ObjOrErr.takeError())) { 2451 reportError(std::move(E), "", Filename, ArchitectureName); 2452 continue; 2453 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2454 I->getAsArchive()) { 2455 std::unique_ptr<Archive> &A = *AOrErr; 2456 outs() << "Archive : " << Filename; 2457 if (!ArchitectureName.empty()) 2458 outs() << " (architecture " << ArchitectureName << ")"; 2459 outs() << "\n"; 2460 if (ArchiveHeaders) 2461 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2462 ArchiveMemberOffsets, ArchitectureName); 2463 Error Err = Error::success(); 2464 unsigned I = -1; 2465 for (auto &C : A->children(Err)) { 2466 ++I; 2467 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2468 if (!ChildOrErr) { 2469 if (Error E = 2470 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2471 reportError(std::move(E), getFileNameForError(C, I), Filename, 2472 ArchitectureName); 2473 continue; 2474 } 2475 if (MachOObjectFile *O = 2476 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2477 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2478 } 2479 if (Err) 2480 reportError(std::move(Err), Filename); 2481 } else { 2482 consumeError(AOrErr.takeError()); 2483 reportError(Filename, 2484 "Mach-O universal file for architecture " + 2485 StringRef(I->getArchFlagName()) + 2486 " is not a Mach-O file or an archive file"); 2487 } 2488 } 2489 } 2490 if (!ArchFound) { 2491 WithColor::error(errs(), "llvm-objdump") 2492 << "file: " + Filename + " does not contain " 2493 << "architecture: " + ArchFlags[i] + "\n"; 2494 return; 2495 } 2496 } 2497 return; 2498 } 2499 // No architecture flags were specified so if this contains a slice that 2500 // matches the host architecture dump only that. 2501 if (!ArchAll) { 2502 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2503 E = UB->end_objects(); 2504 I != E; ++I) { 2505 if (MachOObjectFile::getHostArch().getArchName() == 2506 I->getArchFlagName()) { 2507 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2508 std::string ArchiveName; 2509 ArchiveName.clear(); 2510 if (ObjOrErr) { 2511 ObjectFile &O = *ObjOrErr.get(); 2512 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2513 ProcessMachO(Filename, MachOOF); 2514 } else if (Error E = 2515 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2516 reportError(std::move(E), Filename); 2517 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2518 I->getAsArchive()) { 2519 std::unique_ptr<Archive> &A = *AOrErr; 2520 outs() << "Archive : " << Filename << "\n"; 2521 if (ArchiveHeaders) 2522 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2523 ArchiveMemberOffsets); 2524 Error Err = Error::success(); 2525 unsigned I = -1; 2526 for (auto &C : A->children(Err)) { 2527 ++I; 2528 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2529 if (!ChildOrErr) { 2530 if (Error E = 2531 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2532 reportError(std::move(E), getFileNameForError(C, I), Filename); 2533 continue; 2534 } 2535 if (MachOObjectFile *O = 2536 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2537 ProcessMachO(Filename, O, O->getFileName()); 2538 } 2539 if (Err) 2540 reportError(std::move(Err), Filename); 2541 } else { 2542 consumeError(AOrErr.takeError()); 2543 reportError(Filename, "Mach-O universal file for architecture " + 2544 StringRef(I->getArchFlagName()) + 2545 " is not a Mach-O file or an archive file"); 2546 } 2547 return; 2548 } 2549 } 2550 } 2551 // Either all architectures have been specified or none have been specified 2552 // and this does not contain the host architecture so dump all the slices. 2553 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2554 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2555 E = UB->end_objects(); 2556 I != E; ++I) { 2557 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2558 std::string ArchitectureName; 2559 if (moreThanOneArch) 2560 ArchitectureName = I->getArchFlagName(); 2561 if (ObjOrErr) { 2562 ObjectFile &Obj = *ObjOrErr.get(); 2563 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2564 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2565 } else if (Error E = 2566 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2567 reportError(std::move(E), Filename, "", ArchitectureName); 2568 } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { 2569 std::unique_ptr<Archive> &A = *AOrErr; 2570 outs() << "Archive : " << Filename; 2571 if (!ArchitectureName.empty()) 2572 outs() << " (architecture " << ArchitectureName << ")"; 2573 outs() << "\n"; 2574 if (ArchiveHeaders) 2575 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2576 ArchiveMemberOffsets, ArchitectureName); 2577 Error Err = Error::success(); 2578 unsigned I = -1; 2579 for (auto &C : A->children(Err)) { 2580 ++I; 2581 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2582 if (!ChildOrErr) { 2583 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2584 reportError(std::move(E), getFileNameForError(C, I), Filename, 2585 ArchitectureName); 2586 continue; 2587 } 2588 if (MachOObjectFile *O = 2589 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2590 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2591 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2592 ArchitectureName); 2593 } 2594 } 2595 if (Err) 2596 reportError(std::move(Err), Filename); 2597 } else { 2598 consumeError(AOrErr.takeError()); 2599 reportError(Filename, "Mach-O universal file for architecture " + 2600 StringRef(I->getArchFlagName()) + 2601 " is not a Mach-O file or an archive file"); 2602 } 2603 } 2604 } 2605 2606 namespace { 2607 // The block of info used by the Symbolizer call backs. 2608 struct DisassembleInfo { 2609 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, 2610 std::vector<SectionRef> *Sections, bool verbose) 2611 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {} 2612 bool verbose; 2613 MachOObjectFile *O; 2614 SectionRef S; 2615 SymbolAddressMap *AddrMap; 2616 std::vector<SectionRef> *Sections; 2617 const char *class_name = nullptr; 2618 const char *selector_name = nullptr; 2619 std::unique_ptr<char[]> method = nullptr; 2620 char *demangled_name = nullptr; 2621 uint64_t adrp_addr = 0; 2622 uint32_t adrp_inst = 0; 2623 std::unique_ptr<SymbolAddressMap> bindtable; 2624 uint32_t depth = 0; 2625 }; 2626 } // namespace 2627 2628 // SymbolizerGetOpInfo() is the operand information call back function. 2629 // This is called to get the symbolic information for operand(s) of an 2630 // instruction when it is being done. This routine does this from 2631 // the relocation information, symbol table, etc. That block of information 2632 // is a pointer to the struct DisassembleInfo that was passed when the 2633 // disassembler context was created and passed to back to here when 2634 // called back by the disassembler for instruction operands that could have 2635 // relocation information. The address of the instruction containing operand is 2636 // at the Pc parameter. The immediate value the operand has is passed in 2637 // op_info->Value and is at Offset past the start of the instruction and has a 2638 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2639 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2640 // names and addends of the symbolic expression to add for the operand. The 2641 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2642 // information is returned then this function returns 1 else it returns 0. 2643 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2644 uint64_t Size, int TagType, void *TagBuf) { 2645 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2646 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2647 uint64_t value = op_info->Value; 2648 2649 // Make sure all fields returned are zero if we don't set them. 2650 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2651 op_info->Value = value; 2652 2653 // If the TagType is not the value 1 which it code knows about or if no 2654 // verbose symbolic information is wanted then just return 0, indicating no 2655 // information is being returned. 2656 if (TagType != 1 || !info->verbose) 2657 return 0; 2658 2659 unsigned int Arch = info->O->getArch(); 2660 if (Arch == Triple::x86) { 2661 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2662 return 0; 2663 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2664 // TODO: 2665 // Search the external relocation entries of a fully linked image 2666 // (if any) for an entry that matches this segment offset. 2667 // uint32_t seg_offset = (Pc + Offset); 2668 return 0; 2669 } 2670 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2671 // for an entry for this section offset. 2672 uint32_t sect_addr = info->S.getAddress(); 2673 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2674 bool reloc_found = false; 2675 DataRefImpl Rel; 2676 MachO::any_relocation_info RE; 2677 bool isExtern = false; 2678 SymbolRef Symbol; 2679 bool r_scattered = false; 2680 uint32_t r_value, pair_r_value, r_type; 2681 for (const RelocationRef &Reloc : info->S.relocations()) { 2682 uint64_t RelocOffset = Reloc.getOffset(); 2683 if (RelocOffset == sect_offset) { 2684 Rel = Reloc.getRawDataRefImpl(); 2685 RE = info->O->getRelocation(Rel); 2686 r_type = info->O->getAnyRelocationType(RE); 2687 r_scattered = info->O->isRelocationScattered(RE); 2688 if (r_scattered) { 2689 r_value = info->O->getScatteredRelocationValue(RE); 2690 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2691 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2692 DataRefImpl RelNext = Rel; 2693 info->O->moveRelocationNext(RelNext); 2694 MachO::any_relocation_info RENext; 2695 RENext = info->O->getRelocation(RelNext); 2696 if (info->O->isRelocationScattered(RENext)) 2697 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2698 else 2699 return 0; 2700 } 2701 } else { 2702 isExtern = info->O->getPlainRelocationExternal(RE); 2703 if (isExtern) { 2704 symbol_iterator RelocSym = Reloc.getSymbol(); 2705 Symbol = *RelocSym; 2706 } 2707 } 2708 reloc_found = true; 2709 break; 2710 } 2711 } 2712 if (reloc_found && isExtern) { 2713 op_info->AddSymbol.Present = 1; 2714 op_info->AddSymbol.Name = 2715 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2716 // For i386 extern relocation entries the value in the instruction is 2717 // the offset from the symbol, and value is already set in op_info->Value. 2718 return 1; 2719 } 2720 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2721 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2722 const char *add = GuessSymbolName(r_value, info->AddrMap); 2723 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2724 uint32_t offset = value - (r_value - pair_r_value); 2725 op_info->AddSymbol.Present = 1; 2726 if (add != nullptr) 2727 op_info->AddSymbol.Name = add; 2728 else 2729 op_info->AddSymbol.Value = r_value; 2730 op_info->SubtractSymbol.Present = 1; 2731 if (sub != nullptr) 2732 op_info->SubtractSymbol.Name = sub; 2733 else 2734 op_info->SubtractSymbol.Value = pair_r_value; 2735 op_info->Value = offset; 2736 return 1; 2737 } 2738 return 0; 2739 } 2740 if (Arch == Triple::x86_64) { 2741 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2742 return 0; 2743 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2744 // relocation entries of a linked image (if any) for an entry that matches 2745 // this segment offset. 2746 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2747 uint64_t seg_offset = Pc + Offset; 2748 bool reloc_found = false; 2749 DataRefImpl Rel; 2750 MachO::any_relocation_info RE; 2751 bool isExtern = false; 2752 SymbolRef Symbol; 2753 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2754 uint64_t RelocOffset = Reloc.getOffset(); 2755 if (RelocOffset == seg_offset) { 2756 Rel = Reloc.getRawDataRefImpl(); 2757 RE = info->O->getRelocation(Rel); 2758 // external relocation entries should always be external. 2759 isExtern = info->O->getPlainRelocationExternal(RE); 2760 if (isExtern) { 2761 symbol_iterator RelocSym = Reloc.getSymbol(); 2762 Symbol = *RelocSym; 2763 } 2764 reloc_found = true; 2765 break; 2766 } 2767 } 2768 if (reloc_found && isExtern) { 2769 // The Value passed in will be adjusted by the Pc if the instruction 2770 // adds the Pc. But for x86_64 external relocation entries the Value 2771 // is the offset from the external symbol. 2772 if (info->O->getAnyRelocationPCRel(RE)) 2773 op_info->Value -= Pc + Offset + Size; 2774 const char *name = 2775 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2776 op_info->AddSymbol.Present = 1; 2777 op_info->AddSymbol.Name = name; 2778 return 1; 2779 } 2780 return 0; 2781 } 2782 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2783 // for an entry for this section offset. 2784 uint64_t sect_addr = info->S.getAddress(); 2785 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2786 bool reloc_found = false; 2787 DataRefImpl Rel; 2788 MachO::any_relocation_info RE; 2789 bool isExtern = false; 2790 SymbolRef Symbol; 2791 for (const RelocationRef &Reloc : info->S.relocations()) { 2792 uint64_t RelocOffset = Reloc.getOffset(); 2793 if (RelocOffset == sect_offset) { 2794 Rel = Reloc.getRawDataRefImpl(); 2795 RE = info->O->getRelocation(Rel); 2796 // NOTE: Scattered relocations don't exist on x86_64. 2797 isExtern = info->O->getPlainRelocationExternal(RE); 2798 if (isExtern) { 2799 symbol_iterator RelocSym = Reloc.getSymbol(); 2800 Symbol = *RelocSym; 2801 } 2802 reloc_found = true; 2803 break; 2804 } 2805 } 2806 if (reloc_found && isExtern) { 2807 // The Value passed in will be adjusted by the Pc if the instruction 2808 // adds the Pc. But for x86_64 external relocation entries the Value 2809 // is the offset from the external symbol. 2810 if (info->O->getAnyRelocationPCRel(RE)) 2811 op_info->Value -= Pc + Offset + Size; 2812 const char *name = 2813 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2814 unsigned Type = info->O->getAnyRelocationType(RE); 2815 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2816 DataRefImpl RelNext = Rel; 2817 info->O->moveRelocationNext(RelNext); 2818 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2819 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2820 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2821 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2822 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2823 op_info->SubtractSymbol.Present = 1; 2824 op_info->SubtractSymbol.Name = name; 2825 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2826 Symbol = *RelocSymNext; 2827 name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2828 } 2829 } 2830 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 2831 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 2832 op_info->AddSymbol.Present = 1; 2833 op_info->AddSymbol.Name = name; 2834 return 1; 2835 } 2836 return 0; 2837 } 2838 if (Arch == Triple::arm) { 2839 if (Offset != 0 || (Size != 4 && Size != 2)) 2840 return 0; 2841 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2842 // TODO: 2843 // Search the external relocation entries of a fully linked image 2844 // (if any) for an entry that matches this segment offset. 2845 // uint32_t seg_offset = (Pc + Offset); 2846 return 0; 2847 } 2848 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2849 // for an entry for this section offset. 2850 uint32_t sect_addr = info->S.getAddress(); 2851 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2852 DataRefImpl Rel; 2853 MachO::any_relocation_info RE; 2854 bool isExtern = false; 2855 SymbolRef Symbol; 2856 bool r_scattered = false; 2857 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 2858 auto Reloc = 2859 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2860 uint64_t RelocOffset = Reloc.getOffset(); 2861 return RelocOffset == sect_offset; 2862 }); 2863 2864 if (Reloc == info->S.relocations().end()) 2865 return 0; 2866 2867 Rel = Reloc->getRawDataRefImpl(); 2868 RE = info->O->getRelocation(Rel); 2869 r_length = info->O->getAnyRelocationLength(RE); 2870 r_scattered = info->O->isRelocationScattered(RE); 2871 if (r_scattered) { 2872 r_value = info->O->getScatteredRelocationValue(RE); 2873 r_type = info->O->getScatteredRelocationType(RE); 2874 } else { 2875 r_type = info->O->getAnyRelocationType(RE); 2876 isExtern = info->O->getPlainRelocationExternal(RE); 2877 if (isExtern) { 2878 symbol_iterator RelocSym = Reloc->getSymbol(); 2879 Symbol = *RelocSym; 2880 } 2881 } 2882 if (r_type == MachO::ARM_RELOC_HALF || 2883 r_type == MachO::ARM_RELOC_SECTDIFF || 2884 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 2885 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2886 DataRefImpl RelNext = Rel; 2887 info->O->moveRelocationNext(RelNext); 2888 MachO::any_relocation_info RENext; 2889 RENext = info->O->getRelocation(RelNext); 2890 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 2891 if (info->O->isRelocationScattered(RENext)) 2892 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2893 } 2894 2895 if (isExtern) { 2896 const char *name = 2897 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2898 op_info->AddSymbol.Present = 1; 2899 op_info->AddSymbol.Name = name; 2900 switch (r_type) { 2901 case MachO::ARM_RELOC_HALF: 2902 if ((r_length & 0x1) == 1) { 2903 op_info->Value = value << 16 | other_half; 2904 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2905 } else { 2906 op_info->Value = other_half << 16 | value; 2907 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2908 } 2909 break; 2910 default: 2911 break; 2912 } 2913 return 1; 2914 } 2915 // If we have a branch that is not an external relocation entry then 2916 // return 0 so the code in tryAddingSymbolicOperand() can use the 2917 // SymbolLookUp call back with the branch target address to look up the 2918 // symbol and possibility add an annotation for a symbol stub. 2919 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 2920 r_type == MachO::ARM_THUMB_RELOC_BR22)) 2921 return 0; 2922 2923 uint32_t offset = 0; 2924 if (r_type == MachO::ARM_RELOC_HALF || 2925 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2926 if ((r_length & 0x1) == 1) 2927 value = value << 16 | other_half; 2928 else 2929 value = other_half << 16 | value; 2930 } 2931 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 2932 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 2933 offset = value - r_value; 2934 value = r_value; 2935 } 2936 2937 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2938 if ((r_length & 0x1) == 1) 2939 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2940 else 2941 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2942 const char *add = GuessSymbolName(r_value, info->AddrMap); 2943 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2944 int32_t offset = value - (r_value - pair_r_value); 2945 op_info->AddSymbol.Present = 1; 2946 if (add != nullptr) 2947 op_info->AddSymbol.Name = add; 2948 else 2949 op_info->AddSymbol.Value = r_value; 2950 op_info->SubtractSymbol.Present = 1; 2951 if (sub != nullptr) 2952 op_info->SubtractSymbol.Name = sub; 2953 else 2954 op_info->SubtractSymbol.Value = pair_r_value; 2955 op_info->Value = offset; 2956 return 1; 2957 } 2958 2959 op_info->AddSymbol.Present = 1; 2960 op_info->Value = offset; 2961 if (r_type == MachO::ARM_RELOC_HALF) { 2962 if ((r_length & 0x1) == 1) 2963 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2964 else 2965 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2966 } 2967 const char *add = GuessSymbolName(value, info->AddrMap); 2968 if (add != nullptr) { 2969 op_info->AddSymbol.Name = add; 2970 return 1; 2971 } 2972 op_info->AddSymbol.Value = value; 2973 return 1; 2974 } 2975 if (Arch == Triple::aarch64) { 2976 if (Offset != 0 || Size != 4) 2977 return 0; 2978 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2979 // TODO: 2980 // Search the external relocation entries of a fully linked image 2981 // (if any) for an entry that matches this segment offset. 2982 // uint64_t seg_offset = (Pc + Offset); 2983 return 0; 2984 } 2985 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2986 // for an entry for this section offset. 2987 uint64_t sect_addr = info->S.getAddress(); 2988 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2989 auto Reloc = 2990 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2991 uint64_t RelocOffset = Reloc.getOffset(); 2992 return RelocOffset == sect_offset; 2993 }); 2994 2995 if (Reloc == info->S.relocations().end()) 2996 return 0; 2997 2998 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2999 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 3000 uint32_t r_type = info->O->getAnyRelocationType(RE); 3001 if (r_type == MachO::ARM64_RELOC_ADDEND) { 3002 DataRefImpl RelNext = Rel; 3003 info->O->moveRelocationNext(RelNext); 3004 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 3005 if (value == 0) { 3006 value = info->O->getPlainRelocationSymbolNum(RENext); 3007 op_info->Value = value; 3008 } 3009 } 3010 // NOTE: Scattered relocations don't exist on arm64. 3011 if (!info->O->getPlainRelocationExternal(RE)) 3012 return 0; 3013 const char *name = 3014 unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName()) 3015 .data(); 3016 op_info->AddSymbol.Present = 1; 3017 op_info->AddSymbol.Name = name; 3018 3019 switch (r_type) { 3020 case MachO::ARM64_RELOC_PAGE21: 3021 /* @page */ 3022 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 3023 break; 3024 case MachO::ARM64_RELOC_PAGEOFF12: 3025 /* @pageoff */ 3026 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 3027 break; 3028 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 3029 /* @gotpage */ 3030 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 3031 break; 3032 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 3033 /* @gotpageoff */ 3034 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 3035 break; 3036 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 3037 /* @tvlppage is not implemented in llvm-mc */ 3038 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 3039 break; 3040 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 3041 /* @tvlppageoff is not implemented in llvm-mc */ 3042 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 3043 break; 3044 default: 3045 case MachO::ARM64_RELOC_BRANCH26: 3046 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 3047 break; 3048 } 3049 return 1; 3050 } 3051 return 0; 3052 } 3053 3054 // GuessCstringPointer is passed the address of what might be a pointer to a 3055 // literal string in a cstring section. If that address is in a cstring section 3056 // it returns a pointer to that string. Else it returns nullptr. 3057 static const char *GuessCstringPointer(uint64_t ReferenceValue, 3058 struct DisassembleInfo *info) { 3059 for (const auto &Load : info->O->load_commands()) { 3060 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3061 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3062 for (unsigned J = 0; J < Seg.nsects; ++J) { 3063 MachO::section_64 Sec = info->O->getSection64(Load, J); 3064 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3065 if (section_type == MachO::S_CSTRING_LITERALS && 3066 ReferenceValue >= Sec.addr && 3067 ReferenceValue < Sec.addr + Sec.size) { 3068 uint64_t sect_offset = ReferenceValue - Sec.addr; 3069 uint64_t object_offset = Sec.offset + sect_offset; 3070 StringRef MachOContents = info->O->getData(); 3071 uint64_t object_size = MachOContents.size(); 3072 const char *object_addr = (const char *)MachOContents.data(); 3073 if (object_offset < object_size) { 3074 const char *name = object_addr + object_offset; 3075 return name; 3076 } else { 3077 return nullptr; 3078 } 3079 } 3080 } 3081 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3082 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3083 for (unsigned J = 0; J < Seg.nsects; ++J) { 3084 MachO::section Sec = info->O->getSection(Load, J); 3085 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3086 if (section_type == MachO::S_CSTRING_LITERALS && 3087 ReferenceValue >= Sec.addr && 3088 ReferenceValue < Sec.addr + Sec.size) { 3089 uint64_t sect_offset = ReferenceValue - Sec.addr; 3090 uint64_t object_offset = Sec.offset + sect_offset; 3091 StringRef MachOContents = info->O->getData(); 3092 uint64_t object_size = MachOContents.size(); 3093 const char *object_addr = (const char *)MachOContents.data(); 3094 if (object_offset < object_size) { 3095 const char *name = object_addr + object_offset; 3096 return name; 3097 } else { 3098 return nullptr; 3099 } 3100 } 3101 } 3102 } 3103 } 3104 return nullptr; 3105 } 3106 3107 // GuessIndirectSymbol returns the name of the indirect symbol for the 3108 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 3109 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 3110 // symbol name being referenced by the stub or pointer. 3111 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 3112 struct DisassembleInfo *info) { 3113 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 3114 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 3115 for (const auto &Load : info->O->load_commands()) { 3116 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3117 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3118 for (unsigned J = 0; J < Seg.nsects; ++J) { 3119 MachO::section_64 Sec = info->O->getSection64(Load, J); 3120 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3121 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3122 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3123 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3124 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3125 section_type == MachO::S_SYMBOL_STUBS) && 3126 ReferenceValue >= Sec.addr && 3127 ReferenceValue < Sec.addr + Sec.size) { 3128 uint32_t stride; 3129 if (section_type == MachO::S_SYMBOL_STUBS) 3130 stride = Sec.reserved2; 3131 else 3132 stride = 8; 3133 if (stride == 0) 3134 return nullptr; 3135 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3136 if (index < Dysymtab.nindirectsyms) { 3137 uint32_t indirect_symbol = 3138 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3139 if (indirect_symbol < Symtab.nsyms) { 3140 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3141 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3142 .data(); 3143 } 3144 } 3145 } 3146 } 3147 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3148 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3149 for (unsigned J = 0; J < Seg.nsects; ++J) { 3150 MachO::section Sec = info->O->getSection(Load, J); 3151 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3152 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3153 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3154 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3155 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3156 section_type == MachO::S_SYMBOL_STUBS) && 3157 ReferenceValue >= Sec.addr && 3158 ReferenceValue < Sec.addr + Sec.size) { 3159 uint32_t stride; 3160 if (section_type == MachO::S_SYMBOL_STUBS) 3161 stride = Sec.reserved2; 3162 else 3163 stride = 4; 3164 if (stride == 0) 3165 return nullptr; 3166 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3167 if (index < Dysymtab.nindirectsyms) { 3168 uint32_t indirect_symbol = 3169 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3170 if (indirect_symbol < Symtab.nsyms) { 3171 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3172 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3173 .data(); 3174 } 3175 } 3176 } 3177 } 3178 } 3179 } 3180 return nullptr; 3181 } 3182 3183 // method_reference() is called passing it the ReferenceName that might be 3184 // a reference it to an Objective-C method call. If so then it allocates and 3185 // assembles a method call string with the values last seen and saved in 3186 // the DisassembleInfo's class_name and selector_name fields. This is saved 3187 // into the method field of the info and any previous string is free'ed. 3188 // Then the class_name field in the info is set to nullptr. The method call 3189 // string is set into ReferenceName and ReferenceType is set to 3190 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 3191 // then both ReferenceType and ReferenceName are left unchanged. 3192 static void method_reference(struct DisassembleInfo *info, 3193 uint64_t *ReferenceType, 3194 const char **ReferenceName) { 3195 unsigned int Arch = info->O->getArch(); 3196 if (*ReferenceName != nullptr) { 3197 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 3198 if (info->selector_name != nullptr) { 3199 if (info->class_name != nullptr) { 3200 info->method = std::make_unique<char[]>( 3201 5 + strlen(info->class_name) + strlen(info->selector_name)); 3202 char *method = info->method.get(); 3203 if (method != nullptr) { 3204 strcpy(method, "+["); 3205 strcat(method, info->class_name); 3206 strcat(method, " "); 3207 strcat(method, info->selector_name); 3208 strcat(method, "]"); 3209 *ReferenceName = method; 3210 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3211 } 3212 } else { 3213 info->method = 3214 std::make_unique<char[]>(9 + strlen(info->selector_name)); 3215 char *method = info->method.get(); 3216 if (method != nullptr) { 3217 if (Arch == Triple::x86_64) 3218 strcpy(method, "-[%rdi "); 3219 else if (Arch == Triple::aarch64) 3220 strcpy(method, "-[x0 "); 3221 else 3222 strcpy(method, "-[r? "); 3223 strcat(method, info->selector_name); 3224 strcat(method, "]"); 3225 *ReferenceName = method; 3226 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3227 } 3228 } 3229 info->class_name = nullptr; 3230 } 3231 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 3232 if (info->selector_name != nullptr) { 3233 info->method = 3234 std::make_unique<char[]>(17 + strlen(info->selector_name)); 3235 char *method = info->method.get(); 3236 if (method != nullptr) { 3237 if (Arch == Triple::x86_64) 3238 strcpy(method, "-[[%rdi super] "); 3239 else if (Arch == Triple::aarch64) 3240 strcpy(method, "-[[x0 super] "); 3241 else 3242 strcpy(method, "-[[r? super] "); 3243 strcat(method, info->selector_name); 3244 strcat(method, "]"); 3245 *ReferenceName = method; 3246 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3247 } 3248 info->class_name = nullptr; 3249 } 3250 } 3251 } 3252 } 3253 3254 // GuessPointerPointer() is passed the address of what might be a pointer to 3255 // a reference to an Objective-C class, selector, message ref or cfstring. 3256 // If so the value of the pointer is returned and one of the booleans are set 3257 // to true. If not zero is returned and all the booleans are set to false. 3258 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 3259 struct DisassembleInfo *info, 3260 bool &classref, bool &selref, bool &msgref, 3261 bool &cfstring) { 3262 classref = false; 3263 selref = false; 3264 msgref = false; 3265 cfstring = false; 3266 for (const auto &Load : info->O->load_commands()) { 3267 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3268 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3269 for (unsigned J = 0; J < Seg.nsects; ++J) { 3270 MachO::section_64 Sec = info->O->getSection64(Load, J); 3271 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 3272 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3273 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 3274 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 3275 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 3276 ReferenceValue >= Sec.addr && 3277 ReferenceValue < Sec.addr + Sec.size) { 3278 uint64_t sect_offset = ReferenceValue - Sec.addr; 3279 uint64_t object_offset = Sec.offset + sect_offset; 3280 StringRef MachOContents = info->O->getData(); 3281 uint64_t object_size = MachOContents.size(); 3282 const char *object_addr = (const char *)MachOContents.data(); 3283 if (object_offset < object_size) { 3284 uint64_t pointer_value; 3285 memcpy(&pointer_value, object_addr + object_offset, 3286 sizeof(uint64_t)); 3287 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3288 sys::swapByteOrder(pointer_value); 3289 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 3290 selref = true; 3291 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3292 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 3293 classref = true; 3294 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 3295 ReferenceValue + 8 < Sec.addr + Sec.size) { 3296 msgref = true; 3297 memcpy(&pointer_value, object_addr + object_offset + 8, 3298 sizeof(uint64_t)); 3299 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3300 sys::swapByteOrder(pointer_value); 3301 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 3302 cfstring = true; 3303 return pointer_value; 3304 } else { 3305 return 0; 3306 } 3307 } 3308 } 3309 } 3310 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 3311 } 3312 return 0; 3313 } 3314 3315 // get_pointer_64 returns a pointer to the bytes in the object file at the 3316 // Address from a section in the Mach-O file. And indirectly returns the 3317 // offset into the section, number of bytes left in the section past the offset 3318 // and which section is was being referenced. If the Address is not in a 3319 // section nullptr is returned. 3320 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 3321 uint32_t &left, SectionRef &S, 3322 DisassembleInfo *info, 3323 bool objc_only = false) { 3324 offset = 0; 3325 left = 0; 3326 S = SectionRef(); 3327 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 3328 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 3329 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 3330 if (SectSize == 0) 3331 continue; 3332 if (objc_only) { 3333 StringRef SectName; 3334 Expected<StringRef> SecNameOrErr = 3335 ((*(info->Sections))[SectIdx]).getName(); 3336 if (SecNameOrErr) 3337 SectName = *SecNameOrErr; 3338 else 3339 consumeError(SecNameOrErr.takeError()); 3340 3341 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 3342 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 3343 if (SegName != "__OBJC" && SectName != "__cstring") 3344 continue; 3345 } 3346 if (Address >= SectAddress && Address < SectAddress + SectSize) { 3347 S = (*(info->Sections))[SectIdx]; 3348 offset = Address - SectAddress; 3349 left = SectSize - offset; 3350 StringRef SectContents = unwrapOrError( 3351 ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName()); 3352 return SectContents.data() + offset; 3353 } 3354 } 3355 return nullptr; 3356 } 3357 3358 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 3359 uint32_t &left, SectionRef &S, 3360 DisassembleInfo *info, 3361 bool objc_only = false) { 3362 return get_pointer_64(Address, offset, left, S, info, objc_only); 3363 } 3364 3365 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 3366 // the symbol indirectly through n_value. Based on the relocation information 3367 // for the specified section offset in the specified section reference. 3368 // If no relocation information is found and a non-zero ReferenceValue for the 3369 // symbol is passed, look up that address in the info's AddrMap. 3370 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 3371 DisassembleInfo *info, uint64_t &n_value, 3372 uint64_t ReferenceValue = 0) { 3373 n_value = 0; 3374 if (!info->verbose) 3375 return nullptr; 3376 3377 // See if there is an external relocation entry at the sect_offset. 3378 bool reloc_found = false; 3379 DataRefImpl Rel; 3380 MachO::any_relocation_info RE; 3381 bool isExtern = false; 3382 SymbolRef Symbol; 3383 for (const RelocationRef &Reloc : S.relocations()) { 3384 uint64_t RelocOffset = Reloc.getOffset(); 3385 if (RelocOffset == sect_offset) { 3386 Rel = Reloc.getRawDataRefImpl(); 3387 RE = info->O->getRelocation(Rel); 3388 if (info->O->isRelocationScattered(RE)) 3389 continue; 3390 isExtern = info->O->getPlainRelocationExternal(RE); 3391 if (isExtern) { 3392 symbol_iterator RelocSym = Reloc.getSymbol(); 3393 Symbol = *RelocSym; 3394 } 3395 reloc_found = true; 3396 break; 3397 } 3398 } 3399 // If there is an external relocation entry for a symbol in this section 3400 // at this section_offset then use that symbol's value for the n_value 3401 // and return its name. 3402 const char *SymbolName = nullptr; 3403 if (reloc_found && isExtern) { 3404 n_value = cantFail(Symbol.getValue()); 3405 StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName()); 3406 if (!Name.empty()) { 3407 SymbolName = Name.data(); 3408 return SymbolName; 3409 } 3410 } 3411 3412 // TODO: For fully linked images, look through the external relocation 3413 // entries off the dynamic symtab command. For these the r_offset is from the 3414 // start of the first writeable segment in the Mach-O file. So the offset 3415 // to this section from that segment is passed to this routine by the caller, 3416 // as the database_offset. Which is the difference of the section's starting 3417 // address and the first writable segment. 3418 // 3419 // NOTE: need add passing the database_offset to this routine. 3420 3421 // We did not find an external relocation entry so look up the ReferenceValue 3422 // as an address of a symbol and if found return that symbol's name. 3423 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 3424 3425 return SymbolName; 3426 } 3427 3428 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 3429 DisassembleInfo *info, 3430 uint32_t ReferenceValue) { 3431 uint64_t n_value64; 3432 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 3433 } 3434 3435 namespace { 3436 3437 // These are structs in the Objective-C meta data and read to produce the 3438 // comments for disassembly. While these are part of the ABI they are no 3439 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 3440 // . 3441 3442 // The cfstring object in a 64-bit Mach-O file. 3443 struct cfstring64_t { 3444 uint64_t isa; // class64_t * (64-bit pointer) 3445 uint64_t flags; // flag bits 3446 uint64_t characters; // char * (64-bit pointer) 3447 uint64_t length; // number of non-NULL characters in above 3448 }; 3449 3450 // The class object in a 64-bit Mach-O file. 3451 struct class64_t { 3452 uint64_t isa; // class64_t * (64-bit pointer) 3453 uint64_t superclass; // class64_t * (64-bit pointer) 3454 uint64_t cache; // Cache (64-bit pointer) 3455 uint64_t vtable; // IMP * (64-bit pointer) 3456 uint64_t data; // class_ro64_t * (64-bit pointer) 3457 }; 3458 3459 struct class32_t { 3460 uint32_t isa; /* class32_t * (32-bit pointer) */ 3461 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3462 uint32_t cache; /* Cache (32-bit pointer) */ 3463 uint32_t vtable; /* IMP * (32-bit pointer) */ 3464 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3465 }; 3466 3467 struct class_ro64_t { 3468 uint32_t flags; 3469 uint32_t instanceStart; 3470 uint32_t instanceSize; 3471 uint32_t reserved; 3472 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3473 uint64_t name; // const char * (64-bit pointer) 3474 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3475 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3476 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3477 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3478 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3479 }; 3480 3481 struct class_ro32_t { 3482 uint32_t flags; 3483 uint32_t instanceStart; 3484 uint32_t instanceSize; 3485 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3486 uint32_t name; /* const char * (32-bit pointer) */ 3487 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3488 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3489 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3490 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3491 uint32_t baseProperties; /* const struct objc_property_list * 3492 (32-bit pointer) */ 3493 }; 3494 3495 /* Values for class_ro{64,32}_t->flags */ 3496 #define RO_META (1 << 0) 3497 #define RO_ROOT (1 << 1) 3498 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3499 3500 struct method_list64_t { 3501 uint32_t entsize; 3502 uint32_t count; 3503 /* struct method64_t first; These structures follow inline */ 3504 }; 3505 3506 struct method_list32_t { 3507 uint32_t entsize; 3508 uint32_t count; 3509 /* struct method32_t first; These structures follow inline */ 3510 }; 3511 3512 struct method64_t { 3513 uint64_t name; /* SEL (64-bit pointer) */ 3514 uint64_t types; /* const char * (64-bit pointer) */ 3515 uint64_t imp; /* IMP (64-bit pointer) */ 3516 }; 3517 3518 struct method32_t { 3519 uint32_t name; /* SEL (32-bit pointer) */ 3520 uint32_t types; /* const char * (32-bit pointer) */ 3521 uint32_t imp; /* IMP (32-bit pointer) */ 3522 }; 3523 3524 struct protocol_list64_t { 3525 uint64_t count; /* uintptr_t (a 64-bit value) */ 3526 /* struct protocol64_t * list[0]; These pointers follow inline */ 3527 }; 3528 3529 struct protocol_list32_t { 3530 uint32_t count; /* uintptr_t (a 32-bit value) */ 3531 /* struct protocol32_t * list[0]; These pointers follow inline */ 3532 }; 3533 3534 struct protocol64_t { 3535 uint64_t isa; /* id * (64-bit pointer) */ 3536 uint64_t name; /* const char * (64-bit pointer) */ 3537 uint64_t protocols; /* struct protocol_list64_t * 3538 (64-bit pointer) */ 3539 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3540 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3541 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3542 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3543 uint64_t instanceProperties; /* struct objc_property_list * 3544 (64-bit pointer) */ 3545 }; 3546 3547 struct protocol32_t { 3548 uint32_t isa; /* id * (32-bit pointer) */ 3549 uint32_t name; /* const char * (32-bit pointer) */ 3550 uint32_t protocols; /* struct protocol_list_t * 3551 (32-bit pointer) */ 3552 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3553 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3554 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3555 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3556 uint32_t instanceProperties; /* struct objc_property_list * 3557 (32-bit pointer) */ 3558 }; 3559 3560 struct ivar_list64_t { 3561 uint32_t entsize; 3562 uint32_t count; 3563 /* struct ivar64_t first; These structures follow inline */ 3564 }; 3565 3566 struct ivar_list32_t { 3567 uint32_t entsize; 3568 uint32_t count; 3569 /* struct ivar32_t first; These structures follow inline */ 3570 }; 3571 3572 struct ivar64_t { 3573 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3574 uint64_t name; /* const char * (64-bit pointer) */ 3575 uint64_t type; /* const char * (64-bit pointer) */ 3576 uint32_t alignment; 3577 uint32_t size; 3578 }; 3579 3580 struct ivar32_t { 3581 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3582 uint32_t name; /* const char * (32-bit pointer) */ 3583 uint32_t type; /* const char * (32-bit pointer) */ 3584 uint32_t alignment; 3585 uint32_t size; 3586 }; 3587 3588 struct objc_property_list64 { 3589 uint32_t entsize; 3590 uint32_t count; 3591 /* struct objc_property64 first; These structures follow inline */ 3592 }; 3593 3594 struct objc_property_list32 { 3595 uint32_t entsize; 3596 uint32_t count; 3597 /* struct objc_property32 first; These structures follow inline */ 3598 }; 3599 3600 struct objc_property64 { 3601 uint64_t name; /* const char * (64-bit pointer) */ 3602 uint64_t attributes; /* const char * (64-bit pointer) */ 3603 }; 3604 3605 struct objc_property32 { 3606 uint32_t name; /* const char * (32-bit pointer) */ 3607 uint32_t attributes; /* const char * (32-bit pointer) */ 3608 }; 3609 3610 struct category64_t { 3611 uint64_t name; /* const char * (64-bit pointer) */ 3612 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3613 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3614 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3615 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3616 uint64_t instanceProperties; /* struct objc_property_list * 3617 (64-bit pointer) */ 3618 }; 3619 3620 struct category32_t { 3621 uint32_t name; /* const char * (32-bit pointer) */ 3622 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3623 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3624 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3625 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3626 uint32_t instanceProperties; /* struct objc_property_list * 3627 (32-bit pointer) */ 3628 }; 3629 3630 struct objc_image_info64 { 3631 uint32_t version; 3632 uint32_t flags; 3633 }; 3634 struct objc_image_info32 { 3635 uint32_t version; 3636 uint32_t flags; 3637 }; 3638 struct imageInfo_t { 3639 uint32_t version; 3640 uint32_t flags; 3641 }; 3642 /* masks for objc_image_info.flags */ 3643 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3644 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3645 #define OBJC_IMAGE_IS_SIMULATED (1 << 5) 3646 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6) 3647 3648 struct message_ref64 { 3649 uint64_t imp; /* IMP (64-bit pointer) */ 3650 uint64_t sel; /* SEL (64-bit pointer) */ 3651 }; 3652 3653 struct message_ref32 { 3654 uint32_t imp; /* IMP (32-bit pointer) */ 3655 uint32_t sel; /* SEL (32-bit pointer) */ 3656 }; 3657 3658 // Objective-C 1 (32-bit only) meta data structs. 3659 3660 struct objc_module_t { 3661 uint32_t version; 3662 uint32_t size; 3663 uint32_t name; /* char * (32-bit pointer) */ 3664 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3665 }; 3666 3667 struct objc_symtab_t { 3668 uint32_t sel_ref_cnt; 3669 uint32_t refs; /* SEL * (32-bit pointer) */ 3670 uint16_t cls_def_cnt; 3671 uint16_t cat_def_cnt; 3672 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3673 }; 3674 3675 struct objc_class_t { 3676 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3677 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3678 uint32_t name; /* const char * (32-bit pointer) */ 3679 int32_t version; 3680 int32_t info; 3681 int32_t instance_size; 3682 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3683 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3684 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3685 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3686 }; 3687 3688 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3689 // class is not a metaclass 3690 #define CLS_CLASS 0x1 3691 // class is a metaclass 3692 #define CLS_META 0x2 3693 3694 struct objc_category_t { 3695 uint32_t category_name; /* char * (32-bit pointer) */ 3696 uint32_t class_name; /* char * (32-bit pointer) */ 3697 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3698 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3699 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3700 }; 3701 3702 struct objc_ivar_t { 3703 uint32_t ivar_name; /* char * (32-bit pointer) */ 3704 uint32_t ivar_type; /* char * (32-bit pointer) */ 3705 int32_t ivar_offset; 3706 }; 3707 3708 struct objc_ivar_list_t { 3709 int32_t ivar_count; 3710 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3711 }; 3712 3713 struct objc_method_list_t { 3714 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3715 int32_t method_count; 3716 // struct objc_method_t method_list[1]; /* variable length structure */ 3717 }; 3718 3719 struct objc_method_t { 3720 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3721 uint32_t method_types; /* char * (32-bit pointer) */ 3722 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3723 (32-bit pointer) */ 3724 }; 3725 3726 struct objc_protocol_list_t { 3727 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3728 int32_t count; 3729 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3730 // (32-bit pointer) */ 3731 }; 3732 3733 struct objc_protocol_t { 3734 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3735 uint32_t protocol_name; /* char * (32-bit pointer) */ 3736 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3737 uint32_t instance_methods; /* struct objc_method_description_list * 3738 (32-bit pointer) */ 3739 uint32_t class_methods; /* struct objc_method_description_list * 3740 (32-bit pointer) */ 3741 }; 3742 3743 struct objc_method_description_list_t { 3744 int32_t count; 3745 // struct objc_method_description_t list[1]; 3746 }; 3747 3748 struct objc_method_description_t { 3749 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3750 uint32_t types; /* char * (32-bit pointer) */ 3751 }; 3752 3753 inline void swapStruct(struct cfstring64_t &cfs) { 3754 sys::swapByteOrder(cfs.isa); 3755 sys::swapByteOrder(cfs.flags); 3756 sys::swapByteOrder(cfs.characters); 3757 sys::swapByteOrder(cfs.length); 3758 } 3759 3760 inline void swapStruct(struct class64_t &c) { 3761 sys::swapByteOrder(c.isa); 3762 sys::swapByteOrder(c.superclass); 3763 sys::swapByteOrder(c.cache); 3764 sys::swapByteOrder(c.vtable); 3765 sys::swapByteOrder(c.data); 3766 } 3767 3768 inline void swapStruct(struct class32_t &c) { 3769 sys::swapByteOrder(c.isa); 3770 sys::swapByteOrder(c.superclass); 3771 sys::swapByteOrder(c.cache); 3772 sys::swapByteOrder(c.vtable); 3773 sys::swapByteOrder(c.data); 3774 } 3775 3776 inline void swapStruct(struct class_ro64_t &cro) { 3777 sys::swapByteOrder(cro.flags); 3778 sys::swapByteOrder(cro.instanceStart); 3779 sys::swapByteOrder(cro.instanceSize); 3780 sys::swapByteOrder(cro.reserved); 3781 sys::swapByteOrder(cro.ivarLayout); 3782 sys::swapByteOrder(cro.name); 3783 sys::swapByteOrder(cro.baseMethods); 3784 sys::swapByteOrder(cro.baseProtocols); 3785 sys::swapByteOrder(cro.ivars); 3786 sys::swapByteOrder(cro.weakIvarLayout); 3787 sys::swapByteOrder(cro.baseProperties); 3788 } 3789 3790 inline void swapStruct(struct class_ro32_t &cro) { 3791 sys::swapByteOrder(cro.flags); 3792 sys::swapByteOrder(cro.instanceStart); 3793 sys::swapByteOrder(cro.instanceSize); 3794 sys::swapByteOrder(cro.ivarLayout); 3795 sys::swapByteOrder(cro.name); 3796 sys::swapByteOrder(cro.baseMethods); 3797 sys::swapByteOrder(cro.baseProtocols); 3798 sys::swapByteOrder(cro.ivars); 3799 sys::swapByteOrder(cro.weakIvarLayout); 3800 sys::swapByteOrder(cro.baseProperties); 3801 } 3802 3803 inline void swapStruct(struct method_list64_t &ml) { 3804 sys::swapByteOrder(ml.entsize); 3805 sys::swapByteOrder(ml.count); 3806 } 3807 3808 inline void swapStruct(struct method_list32_t &ml) { 3809 sys::swapByteOrder(ml.entsize); 3810 sys::swapByteOrder(ml.count); 3811 } 3812 3813 inline void swapStruct(struct method64_t &m) { 3814 sys::swapByteOrder(m.name); 3815 sys::swapByteOrder(m.types); 3816 sys::swapByteOrder(m.imp); 3817 } 3818 3819 inline void swapStruct(struct method32_t &m) { 3820 sys::swapByteOrder(m.name); 3821 sys::swapByteOrder(m.types); 3822 sys::swapByteOrder(m.imp); 3823 } 3824 3825 inline void swapStruct(struct protocol_list64_t &pl) { 3826 sys::swapByteOrder(pl.count); 3827 } 3828 3829 inline void swapStruct(struct protocol_list32_t &pl) { 3830 sys::swapByteOrder(pl.count); 3831 } 3832 3833 inline void swapStruct(struct protocol64_t &p) { 3834 sys::swapByteOrder(p.isa); 3835 sys::swapByteOrder(p.name); 3836 sys::swapByteOrder(p.protocols); 3837 sys::swapByteOrder(p.instanceMethods); 3838 sys::swapByteOrder(p.classMethods); 3839 sys::swapByteOrder(p.optionalInstanceMethods); 3840 sys::swapByteOrder(p.optionalClassMethods); 3841 sys::swapByteOrder(p.instanceProperties); 3842 } 3843 3844 inline void swapStruct(struct protocol32_t &p) { 3845 sys::swapByteOrder(p.isa); 3846 sys::swapByteOrder(p.name); 3847 sys::swapByteOrder(p.protocols); 3848 sys::swapByteOrder(p.instanceMethods); 3849 sys::swapByteOrder(p.classMethods); 3850 sys::swapByteOrder(p.optionalInstanceMethods); 3851 sys::swapByteOrder(p.optionalClassMethods); 3852 sys::swapByteOrder(p.instanceProperties); 3853 } 3854 3855 inline void swapStruct(struct ivar_list64_t &il) { 3856 sys::swapByteOrder(il.entsize); 3857 sys::swapByteOrder(il.count); 3858 } 3859 3860 inline void swapStruct(struct ivar_list32_t &il) { 3861 sys::swapByteOrder(il.entsize); 3862 sys::swapByteOrder(il.count); 3863 } 3864 3865 inline void swapStruct(struct ivar64_t &i) { 3866 sys::swapByteOrder(i.offset); 3867 sys::swapByteOrder(i.name); 3868 sys::swapByteOrder(i.type); 3869 sys::swapByteOrder(i.alignment); 3870 sys::swapByteOrder(i.size); 3871 } 3872 3873 inline void swapStruct(struct ivar32_t &i) { 3874 sys::swapByteOrder(i.offset); 3875 sys::swapByteOrder(i.name); 3876 sys::swapByteOrder(i.type); 3877 sys::swapByteOrder(i.alignment); 3878 sys::swapByteOrder(i.size); 3879 } 3880 3881 inline void swapStruct(struct objc_property_list64 &pl) { 3882 sys::swapByteOrder(pl.entsize); 3883 sys::swapByteOrder(pl.count); 3884 } 3885 3886 inline void swapStruct(struct objc_property_list32 &pl) { 3887 sys::swapByteOrder(pl.entsize); 3888 sys::swapByteOrder(pl.count); 3889 } 3890 3891 inline void swapStruct(struct objc_property64 &op) { 3892 sys::swapByteOrder(op.name); 3893 sys::swapByteOrder(op.attributes); 3894 } 3895 3896 inline void swapStruct(struct objc_property32 &op) { 3897 sys::swapByteOrder(op.name); 3898 sys::swapByteOrder(op.attributes); 3899 } 3900 3901 inline void swapStruct(struct category64_t &c) { 3902 sys::swapByteOrder(c.name); 3903 sys::swapByteOrder(c.cls); 3904 sys::swapByteOrder(c.instanceMethods); 3905 sys::swapByteOrder(c.classMethods); 3906 sys::swapByteOrder(c.protocols); 3907 sys::swapByteOrder(c.instanceProperties); 3908 } 3909 3910 inline void swapStruct(struct category32_t &c) { 3911 sys::swapByteOrder(c.name); 3912 sys::swapByteOrder(c.cls); 3913 sys::swapByteOrder(c.instanceMethods); 3914 sys::swapByteOrder(c.classMethods); 3915 sys::swapByteOrder(c.protocols); 3916 sys::swapByteOrder(c.instanceProperties); 3917 } 3918 3919 inline void swapStruct(struct objc_image_info64 &o) { 3920 sys::swapByteOrder(o.version); 3921 sys::swapByteOrder(o.flags); 3922 } 3923 3924 inline void swapStruct(struct objc_image_info32 &o) { 3925 sys::swapByteOrder(o.version); 3926 sys::swapByteOrder(o.flags); 3927 } 3928 3929 inline void swapStruct(struct imageInfo_t &o) { 3930 sys::swapByteOrder(o.version); 3931 sys::swapByteOrder(o.flags); 3932 } 3933 3934 inline void swapStruct(struct message_ref64 &mr) { 3935 sys::swapByteOrder(mr.imp); 3936 sys::swapByteOrder(mr.sel); 3937 } 3938 3939 inline void swapStruct(struct message_ref32 &mr) { 3940 sys::swapByteOrder(mr.imp); 3941 sys::swapByteOrder(mr.sel); 3942 } 3943 3944 inline void swapStruct(struct objc_module_t &module) { 3945 sys::swapByteOrder(module.version); 3946 sys::swapByteOrder(module.size); 3947 sys::swapByteOrder(module.name); 3948 sys::swapByteOrder(module.symtab); 3949 } 3950 3951 inline void swapStruct(struct objc_symtab_t &symtab) { 3952 sys::swapByteOrder(symtab.sel_ref_cnt); 3953 sys::swapByteOrder(symtab.refs); 3954 sys::swapByteOrder(symtab.cls_def_cnt); 3955 sys::swapByteOrder(symtab.cat_def_cnt); 3956 } 3957 3958 inline void swapStruct(struct objc_class_t &objc_class) { 3959 sys::swapByteOrder(objc_class.isa); 3960 sys::swapByteOrder(objc_class.super_class); 3961 sys::swapByteOrder(objc_class.name); 3962 sys::swapByteOrder(objc_class.version); 3963 sys::swapByteOrder(objc_class.info); 3964 sys::swapByteOrder(objc_class.instance_size); 3965 sys::swapByteOrder(objc_class.ivars); 3966 sys::swapByteOrder(objc_class.methodLists); 3967 sys::swapByteOrder(objc_class.cache); 3968 sys::swapByteOrder(objc_class.protocols); 3969 } 3970 3971 inline void swapStruct(struct objc_category_t &objc_category) { 3972 sys::swapByteOrder(objc_category.category_name); 3973 sys::swapByteOrder(objc_category.class_name); 3974 sys::swapByteOrder(objc_category.instance_methods); 3975 sys::swapByteOrder(objc_category.class_methods); 3976 sys::swapByteOrder(objc_category.protocols); 3977 } 3978 3979 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 3980 sys::swapByteOrder(objc_ivar_list.ivar_count); 3981 } 3982 3983 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 3984 sys::swapByteOrder(objc_ivar.ivar_name); 3985 sys::swapByteOrder(objc_ivar.ivar_type); 3986 sys::swapByteOrder(objc_ivar.ivar_offset); 3987 } 3988 3989 inline void swapStruct(struct objc_method_list_t &method_list) { 3990 sys::swapByteOrder(method_list.obsolete); 3991 sys::swapByteOrder(method_list.method_count); 3992 } 3993 3994 inline void swapStruct(struct objc_method_t &method) { 3995 sys::swapByteOrder(method.method_name); 3996 sys::swapByteOrder(method.method_types); 3997 sys::swapByteOrder(method.method_imp); 3998 } 3999 4000 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 4001 sys::swapByteOrder(protocol_list.next); 4002 sys::swapByteOrder(protocol_list.count); 4003 } 4004 4005 inline void swapStruct(struct objc_protocol_t &protocol) { 4006 sys::swapByteOrder(protocol.isa); 4007 sys::swapByteOrder(protocol.protocol_name); 4008 sys::swapByteOrder(protocol.protocol_list); 4009 sys::swapByteOrder(protocol.instance_methods); 4010 sys::swapByteOrder(protocol.class_methods); 4011 } 4012 4013 inline void swapStruct(struct objc_method_description_list_t &mdl) { 4014 sys::swapByteOrder(mdl.count); 4015 } 4016 4017 inline void swapStruct(struct objc_method_description_t &md) { 4018 sys::swapByteOrder(md.name); 4019 sys::swapByteOrder(md.types); 4020 } 4021 4022 } // namespace 4023 4024 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 4025 struct DisassembleInfo *info); 4026 4027 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 4028 // to an Objective-C class and returns the class name. It is also passed the 4029 // address of the pointer, so when the pointer is zero as it can be in an .o 4030 // file, that is used to look for an external relocation entry with a symbol 4031 // name. 4032 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 4033 uint64_t ReferenceValue, 4034 struct DisassembleInfo *info) { 4035 const char *r; 4036 uint32_t offset, left; 4037 SectionRef S; 4038 4039 // The pointer_value can be 0 in an object file and have a relocation 4040 // entry for the class symbol at the ReferenceValue (the address of the 4041 // pointer). 4042 if (pointer_value == 0) { 4043 r = get_pointer_64(ReferenceValue, offset, left, S, info); 4044 if (r == nullptr || left < sizeof(uint64_t)) 4045 return nullptr; 4046 uint64_t n_value; 4047 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 4048 if (symbol_name == nullptr) 4049 return nullptr; 4050 const char *class_name = strrchr(symbol_name, '$'); 4051 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 4052 return class_name + 2; 4053 else 4054 return nullptr; 4055 } 4056 4057 // The case were the pointer_value is non-zero and points to a class defined 4058 // in this Mach-O file. 4059 r = get_pointer_64(pointer_value, offset, left, S, info); 4060 if (r == nullptr || left < sizeof(struct class64_t)) 4061 return nullptr; 4062 struct class64_t c; 4063 memcpy(&c, r, sizeof(struct class64_t)); 4064 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4065 swapStruct(c); 4066 if (c.data == 0) 4067 return nullptr; 4068 r = get_pointer_64(c.data, offset, left, S, info); 4069 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4070 return nullptr; 4071 struct class_ro64_t cro; 4072 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4073 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4074 swapStruct(cro); 4075 if (cro.name == 0) 4076 return nullptr; 4077 const char *name = get_pointer_64(cro.name, offset, left, S, info); 4078 return name; 4079 } 4080 4081 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 4082 // pointer to a cfstring and returns its name or nullptr. 4083 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 4084 struct DisassembleInfo *info) { 4085 const char *r, *name; 4086 uint32_t offset, left; 4087 SectionRef S; 4088 struct cfstring64_t cfs; 4089 uint64_t cfs_characters; 4090 4091 r = get_pointer_64(ReferenceValue, offset, left, S, info); 4092 if (r == nullptr || left < sizeof(struct cfstring64_t)) 4093 return nullptr; 4094 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 4095 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4096 swapStruct(cfs); 4097 if (cfs.characters == 0) { 4098 uint64_t n_value; 4099 const char *symbol_name = get_symbol_64( 4100 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 4101 if (symbol_name == nullptr) 4102 return nullptr; 4103 cfs_characters = n_value; 4104 } else 4105 cfs_characters = cfs.characters; 4106 name = get_pointer_64(cfs_characters, offset, left, S, info); 4107 4108 return name; 4109 } 4110 4111 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 4112 // of a pointer to an Objective-C selector reference when the pointer value is 4113 // zero as in a .o file and is likely to have a external relocation entry with 4114 // who's symbol's n_value is the real pointer to the selector name. If that is 4115 // the case the real pointer to the selector name is returned else 0 is 4116 // returned 4117 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 4118 struct DisassembleInfo *info) { 4119 uint32_t offset, left; 4120 SectionRef S; 4121 4122 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 4123 if (r == nullptr || left < sizeof(uint64_t)) 4124 return 0; 4125 uint64_t n_value; 4126 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 4127 if (symbol_name == nullptr) 4128 return 0; 4129 return n_value; 4130 } 4131 4132 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 4133 const char *sectname) { 4134 for (const SectionRef &Section : O->sections()) { 4135 StringRef SectName; 4136 Expected<StringRef> SecNameOrErr = Section.getName(); 4137 if (SecNameOrErr) 4138 SectName = *SecNameOrErr; 4139 else 4140 consumeError(SecNameOrErr.takeError()); 4141 4142 DataRefImpl Ref = Section.getRawDataRefImpl(); 4143 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4144 if (SegName == segname && SectName == sectname) 4145 return Section; 4146 } 4147 return SectionRef(); 4148 } 4149 4150 static void 4151 walk_pointer_list_64(const char *listname, const SectionRef S, 4152 MachOObjectFile *O, struct DisassembleInfo *info, 4153 void (*func)(uint64_t, struct DisassembleInfo *info)) { 4154 if (S == SectionRef()) 4155 return; 4156 4157 StringRef SectName; 4158 Expected<StringRef> SecNameOrErr = S.getName(); 4159 if (SecNameOrErr) 4160 SectName = *SecNameOrErr; 4161 else 4162 consumeError(SecNameOrErr.takeError()); 4163 4164 DataRefImpl Ref = S.getRawDataRefImpl(); 4165 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4166 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4167 4168 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4169 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4170 4171 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 4172 uint32_t left = S.getSize() - i; 4173 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 4174 uint64_t p = 0; 4175 memcpy(&p, Contents + i, size); 4176 if (i + sizeof(uint64_t) > S.getSize()) 4177 outs() << listname << " list pointer extends past end of (" << SegName 4178 << "," << SectName << ") section\n"; 4179 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 4180 4181 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4182 sys::swapByteOrder(p); 4183 4184 uint64_t n_value = 0; 4185 const char *name = get_symbol_64(i, S, info, n_value, p); 4186 if (name == nullptr) 4187 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 4188 4189 if (n_value != 0) { 4190 outs() << format("0x%" PRIx64, n_value); 4191 if (p != 0) 4192 outs() << " + " << format("0x%" PRIx64, p); 4193 } else 4194 outs() << format("0x%" PRIx64, p); 4195 if (name != nullptr) 4196 outs() << " " << name; 4197 outs() << "\n"; 4198 4199 p += n_value; 4200 if (func) 4201 func(p, info); 4202 } 4203 } 4204 4205 static void 4206 walk_pointer_list_32(const char *listname, const SectionRef S, 4207 MachOObjectFile *O, struct DisassembleInfo *info, 4208 void (*func)(uint32_t, struct DisassembleInfo *info)) { 4209 if (S == SectionRef()) 4210 return; 4211 4212 StringRef SectName = unwrapOrError(S.getName(), O->getFileName()); 4213 DataRefImpl Ref = S.getRawDataRefImpl(); 4214 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4215 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4216 4217 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4218 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4219 4220 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 4221 uint32_t left = S.getSize() - i; 4222 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 4223 uint32_t p = 0; 4224 memcpy(&p, Contents + i, size); 4225 if (i + sizeof(uint32_t) > S.getSize()) 4226 outs() << listname << " list pointer extends past end of (" << SegName 4227 << "," << SectName << ") section\n"; 4228 uint32_t Address = S.getAddress() + i; 4229 outs() << format("%08" PRIx32, Address) << " "; 4230 4231 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4232 sys::swapByteOrder(p); 4233 outs() << format("0x%" PRIx32, p); 4234 4235 const char *name = get_symbol_32(i, S, info, p); 4236 if (name != nullptr) 4237 outs() << " " << name; 4238 outs() << "\n"; 4239 4240 if (func) 4241 func(p, info); 4242 } 4243 } 4244 4245 static void print_layout_map(const char *layout_map, uint32_t left) { 4246 if (layout_map == nullptr) 4247 return; 4248 outs() << " layout map: "; 4249 do { 4250 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 4251 left--; 4252 layout_map++; 4253 } while (*layout_map != '\0' && left != 0); 4254 outs() << "\n"; 4255 } 4256 4257 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 4258 uint32_t offset, left; 4259 SectionRef S; 4260 const char *layout_map; 4261 4262 if (p == 0) 4263 return; 4264 layout_map = get_pointer_64(p, offset, left, S, info); 4265 print_layout_map(layout_map, left); 4266 } 4267 4268 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 4269 uint32_t offset, left; 4270 SectionRef S; 4271 const char *layout_map; 4272 4273 if (p == 0) 4274 return; 4275 layout_map = get_pointer_32(p, offset, left, S, info); 4276 print_layout_map(layout_map, left); 4277 } 4278 4279 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 4280 const char *indent) { 4281 struct method_list64_t ml; 4282 struct method64_t m; 4283 const char *r; 4284 uint32_t offset, xoffset, left, i; 4285 SectionRef S, xS; 4286 const char *name, *sym_name; 4287 uint64_t n_value; 4288 4289 r = get_pointer_64(p, offset, left, S, info); 4290 if (r == nullptr) 4291 return; 4292 memset(&ml, '\0', sizeof(struct method_list64_t)); 4293 if (left < sizeof(struct method_list64_t)) { 4294 memcpy(&ml, r, left); 4295 outs() << " (method_list_t entends past the end of the section)\n"; 4296 } else 4297 memcpy(&ml, r, sizeof(struct method_list64_t)); 4298 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4299 swapStruct(ml); 4300 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4301 outs() << indent << "\t\t count " << ml.count << "\n"; 4302 4303 p += sizeof(struct method_list64_t); 4304 offset += sizeof(struct method_list64_t); 4305 for (i = 0; i < ml.count; i++) { 4306 r = get_pointer_64(p, offset, left, S, info); 4307 if (r == nullptr) 4308 return; 4309 memset(&m, '\0', sizeof(struct method64_t)); 4310 if (left < sizeof(struct method64_t)) { 4311 memcpy(&m, r, left); 4312 outs() << indent << " (method_t extends past the end of the section)\n"; 4313 } else 4314 memcpy(&m, r, sizeof(struct method64_t)); 4315 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4316 swapStruct(m); 4317 4318 outs() << indent << "\t\t name "; 4319 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 4320 info, n_value, m.name); 4321 if (n_value != 0) { 4322 if (info->verbose && sym_name != nullptr) 4323 outs() << sym_name; 4324 else 4325 outs() << format("0x%" PRIx64, n_value); 4326 if (m.name != 0) 4327 outs() << " + " << format("0x%" PRIx64, m.name); 4328 } else 4329 outs() << format("0x%" PRIx64, m.name); 4330 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 4331 if (name != nullptr) 4332 outs() << format(" %.*s", left, name); 4333 outs() << "\n"; 4334 4335 outs() << indent << "\t\t types "; 4336 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 4337 info, n_value, m.types); 4338 if (n_value != 0) { 4339 if (info->verbose && sym_name != nullptr) 4340 outs() << sym_name; 4341 else 4342 outs() << format("0x%" PRIx64, n_value); 4343 if (m.types != 0) 4344 outs() << " + " << format("0x%" PRIx64, m.types); 4345 } else 4346 outs() << format("0x%" PRIx64, m.types); 4347 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 4348 if (name != nullptr) 4349 outs() << format(" %.*s", left, name); 4350 outs() << "\n"; 4351 4352 outs() << indent << "\t\t imp "; 4353 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 4354 n_value, m.imp); 4355 if (info->verbose && name == nullptr) { 4356 if (n_value != 0) { 4357 outs() << format("0x%" PRIx64, n_value) << " "; 4358 if (m.imp != 0) 4359 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 4360 } else 4361 outs() << format("0x%" PRIx64, m.imp) << " "; 4362 } 4363 if (name != nullptr) 4364 outs() << name; 4365 outs() << "\n"; 4366 4367 p += sizeof(struct method64_t); 4368 offset += sizeof(struct method64_t); 4369 } 4370 } 4371 4372 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 4373 const char *indent) { 4374 struct method_list32_t ml; 4375 struct method32_t m; 4376 const char *r, *name; 4377 uint32_t offset, xoffset, left, i; 4378 SectionRef S, xS; 4379 4380 r = get_pointer_32(p, offset, left, S, info); 4381 if (r == nullptr) 4382 return; 4383 memset(&ml, '\0', sizeof(struct method_list32_t)); 4384 if (left < sizeof(struct method_list32_t)) { 4385 memcpy(&ml, r, left); 4386 outs() << " (method_list_t entends past the end of the section)\n"; 4387 } else 4388 memcpy(&ml, r, sizeof(struct method_list32_t)); 4389 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4390 swapStruct(ml); 4391 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4392 outs() << indent << "\t\t count " << ml.count << "\n"; 4393 4394 p += sizeof(struct method_list32_t); 4395 offset += sizeof(struct method_list32_t); 4396 for (i = 0; i < ml.count; i++) { 4397 r = get_pointer_32(p, offset, left, S, info); 4398 if (r == nullptr) 4399 return; 4400 memset(&m, '\0', sizeof(struct method32_t)); 4401 if (left < sizeof(struct method32_t)) { 4402 memcpy(&ml, r, left); 4403 outs() << indent << " (method_t entends past the end of the section)\n"; 4404 } else 4405 memcpy(&m, r, sizeof(struct method32_t)); 4406 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4407 swapStruct(m); 4408 4409 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 4410 name = get_pointer_32(m.name, xoffset, left, xS, info); 4411 if (name != nullptr) 4412 outs() << format(" %.*s", left, name); 4413 outs() << "\n"; 4414 4415 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 4416 name = get_pointer_32(m.types, xoffset, left, xS, info); 4417 if (name != nullptr) 4418 outs() << format(" %.*s", left, name); 4419 outs() << "\n"; 4420 4421 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4422 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 4423 m.imp); 4424 if (name != nullptr) 4425 outs() << " " << name; 4426 outs() << "\n"; 4427 4428 p += sizeof(struct method32_t); 4429 offset += sizeof(struct method32_t); 4430 } 4431 } 4432 4433 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 4434 uint32_t offset, left, xleft; 4435 SectionRef S; 4436 struct objc_method_list_t method_list; 4437 struct objc_method_t method; 4438 const char *r, *methods, *name, *SymbolName; 4439 int32_t i; 4440 4441 r = get_pointer_32(p, offset, left, S, info, true); 4442 if (r == nullptr) 4443 return true; 4444 4445 outs() << "\n"; 4446 if (left > sizeof(struct objc_method_list_t)) { 4447 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 4448 } else { 4449 outs() << "\t\t objc_method_list extends past end of the section\n"; 4450 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 4451 memcpy(&method_list, r, left); 4452 } 4453 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4454 swapStruct(method_list); 4455 4456 outs() << "\t\t obsolete " 4457 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4458 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4459 4460 methods = r + sizeof(struct objc_method_list_t); 4461 for (i = 0; i < method_list.method_count; i++) { 4462 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4463 outs() << "\t\t remaining method's extend past the of the section\n"; 4464 break; 4465 } 4466 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4467 sizeof(struct objc_method_t)); 4468 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4469 swapStruct(method); 4470 4471 outs() << "\t\t method_name " 4472 << format("0x%08" PRIx32, method.method_name); 4473 if (info->verbose) { 4474 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4475 if (name != nullptr) 4476 outs() << format(" %.*s", xleft, name); 4477 else 4478 outs() << " (not in an __OBJC section)"; 4479 } 4480 outs() << "\n"; 4481 4482 outs() << "\t\t method_types " 4483 << format("0x%08" PRIx32, method.method_types); 4484 if (info->verbose) { 4485 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4486 if (name != nullptr) 4487 outs() << format(" %.*s", xleft, name); 4488 else 4489 outs() << " (not in an __OBJC section)"; 4490 } 4491 outs() << "\n"; 4492 4493 outs() << "\t\t method_imp " 4494 << format("0x%08" PRIx32, method.method_imp) << " "; 4495 if (info->verbose) { 4496 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4497 if (SymbolName != nullptr) 4498 outs() << SymbolName; 4499 } 4500 outs() << "\n"; 4501 } 4502 return false; 4503 } 4504 4505 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4506 struct protocol_list64_t pl; 4507 uint64_t q, n_value; 4508 struct protocol64_t pc; 4509 const char *r; 4510 uint32_t offset, xoffset, left, i; 4511 SectionRef S, xS; 4512 const char *name, *sym_name; 4513 4514 r = get_pointer_64(p, offset, left, S, info); 4515 if (r == nullptr) 4516 return; 4517 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4518 if (left < sizeof(struct protocol_list64_t)) { 4519 memcpy(&pl, r, left); 4520 outs() << " (protocol_list_t entends past the end of the section)\n"; 4521 } else 4522 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4523 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4524 swapStruct(pl); 4525 outs() << " count " << pl.count << "\n"; 4526 4527 p += sizeof(struct protocol_list64_t); 4528 offset += sizeof(struct protocol_list64_t); 4529 for (i = 0; i < pl.count; i++) { 4530 r = get_pointer_64(p, offset, left, S, info); 4531 if (r == nullptr) 4532 return; 4533 q = 0; 4534 if (left < sizeof(uint64_t)) { 4535 memcpy(&q, r, left); 4536 outs() << " (protocol_t * entends past the end of the section)\n"; 4537 } else 4538 memcpy(&q, r, sizeof(uint64_t)); 4539 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4540 sys::swapByteOrder(q); 4541 4542 outs() << "\t\t list[" << i << "] "; 4543 sym_name = get_symbol_64(offset, S, info, n_value, q); 4544 if (n_value != 0) { 4545 if (info->verbose && sym_name != nullptr) 4546 outs() << sym_name; 4547 else 4548 outs() << format("0x%" PRIx64, n_value); 4549 if (q != 0) 4550 outs() << " + " << format("0x%" PRIx64, q); 4551 } else 4552 outs() << format("0x%" PRIx64, q); 4553 outs() << " (struct protocol_t *)\n"; 4554 4555 r = get_pointer_64(q + n_value, offset, left, S, info); 4556 if (r == nullptr) 4557 return; 4558 memset(&pc, '\0', sizeof(struct protocol64_t)); 4559 if (left < sizeof(struct protocol64_t)) { 4560 memcpy(&pc, r, left); 4561 outs() << " (protocol_t entends past the end of the section)\n"; 4562 } else 4563 memcpy(&pc, r, sizeof(struct protocol64_t)); 4564 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4565 swapStruct(pc); 4566 4567 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4568 4569 outs() << "\t\t\t name "; 4570 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4571 info, n_value, pc.name); 4572 if (n_value != 0) { 4573 if (info->verbose && sym_name != nullptr) 4574 outs() << sym_name; 4575 else 4576 outs() << format("0x%" PRIx64, n_value); 4577 if (pc.name != 0) 4578 outs() << " + " << format("0x%" PRIx64, pc.name); 4579 } else 4580 outs() << format("0x%" PRIx64, pc.name); 4581 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4582 if (name != nullptr) 4583 outs() << format(" %.*s", left, name); 4584 outs() << "\n"; 4585 4586 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4587 4588 outs() << "\t\t instanceMethods "; 4589 sym_name = 4590 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4591 S, info, n_value, pc.instanceMethods); 4592 if (n_value != 0) { 4593 if (info->verbose && sym_name != nullptr) 4594 outs() << sym_name; 4595 else 4596 outs() << format("0x%" PRIx64, n_value); 4597 if (pc.instanceMethods != 0) 4598 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4599 } else 4600 outs() << format("0x%" PRIx64, pc.instanceMethods); 4601 outs() << " (struct method_list_t *)\n"; 4602 if (pc.instanceMethods + n_value != 0) 4603 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4604 4605 outs() << "\t\t classMethods "; 4606 sym_name = 4607 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4608 info, n_value, pc.classMethods); 4609 if (n_value != 0) { 4610 if (info->verbose && sym_name != nullptr) 4611 outs() << sym_name; 4612 else 4613 outs() << format("0x%" PRIx64, n_value); 4614 if (pc.classMethods != 0) 4615 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4616 } else 4617 outs() << format("0x%" PRIx64, pc.classMethods); 4618 outs() << " (struct method_list_t *)\n"; 4619 if (pc.classMethods + n_value != 0) 4620 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4621 4622 outs() << "\t optionalInstanceMethods " 4623 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4624 outs() << "\t optionalClassMethods " 4625 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4626 outs() << "\t instanceProperties " 4627 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4628 4629 p += sizeof(uint64_t); 4630 offset += sizeof(uint64_t); 4631 } 4632 } 4633 4634 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4635 struct protocol_list32_t pl; 4636 uint32_t q; 4637 struct protocol32_t pc; 4638 const char *r; 4639 uint32_t offset, xoffset, left, i; 4640 SectionRef S, xS; 4641 const char *name; 4642 4643 r = get_pointer_32(p, offset, left, S, info); 4644 if (r == nullptr) 4645 return; 4646 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4647 if (left < sizeof(struct protocol_list32_t)) { 4648 memcpy(&pl, r, left); 4649 outs() << " (protocol_list_t entends past the end of the section)\n"; 4650 } else 4651 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4652 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4653 swapStruct(pl); 4654 outs() << " count " << pl.count << "\n"; 4655 4656 p += sizeof(struct protocol_list32_t); 4657 offset += sizeof(struct protocol_list32_t); 4658 for (i = 0; i < pl.count; i++) { 4659 r = get_pointer_32(p, offset, left, S, info); 4660 if (r == nullptr) 4661 return; 4662 q = 0; 4663 if (left < sizeof(uint32_t)) { 4664 memcpy(&q, r, left); 4665 outs() << " (protocol_t * entends past the end of the section)\n"; 4666 } else 4667 memcpy(&q, r, sizeof(uint32_t)); 4668 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4669 sys::swapByteOrder(q); 4670 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4671 << " (struct protocol_t *)\n"; 4672 r = get_pointer_32(q, offset, left, S, info); 4673 if (r == nullptr) 4674 return; 4675 memset(&pc, '\0', sizeof(struct protocol32_t)); 4676 if (left < sizeof(struct protocol32_t)) { 4677 memcpy(&pc, r, left); 4678 outs() << " (protocol_t entends past the end of the section)\n"; 4679 } else 4680 memcpy(&pc, r, sizeof(struct protocol32_t)); 4681 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4682 swapStruct(pc); 4683 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4684 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4685 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4686 if (name != nullptr) 4687 outs() << format(" %.*s", left, name); 4688 outs() << "\n"; 4689 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4690 outs() << "\t\t instanceMethods " 4691 << format("0x%" PRIx32, pc.instanceMethods) 4692 << " (struct method_list_t *)\n"; 4693 if (pc.instanceMethods != 0) 4694 print_method_list32_t(pc.instanceMethods, info, "\t"); 4695 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4696 << " (struct method_list_t *)\n"; 4697 if (pc.classMethods != 0) 4698 print_method_list32_t(pc.classMethods, info, "\t"); 4699 outs() << "\t optionalInstanceMethods " 4700 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4701 outs() << "\t optionalClassMethods " 4702 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4703 outs() << "\t instanceProperties " 4704 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4705 p += sizeof(uint32_t); 4706 offset += sizeof(uint32_t); 4707 } 4708 } 4709 4710 static void print_indent(uint32_t indent) { 4711 for (uint32_t i = 0; i < indent;) { 4712 if (indent - i >= 8) { 4713 outs() << "\t"; 4714 i += 8; 4715 } else { 4716 for (uint32_t j = i; j < indent; j++) 4717 outs() << " "; 4718 return; 4719 } 4720 } 4721 } 4722 4723 static bool print_method_description_list(uint32_t p, uint32_t indent, 4724 struct DisassembleInfo *info) { 4725 uint32_t offset, left, xleft; 4726 SectionRef S; 4727 struct objc_method_description_list_t mdl; 4728 struct objc_method_description_t md; 4729 const char *r, *list, *name; 4730 int32_t i; 4731 4732 r = get_pointer_32(p, offset, left, S, info, true); 4733 if (r == nullptr) 4734 return true; 4735 4736 outs() << "\n"; 4737 if (left > sizeof(struct objc_method_description_list_t)) { 4738 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 4739 } else { 4740 print_indent(indent); 4741 outs() << " objc_method_description_list extends past end of the section\n"; 4742 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 4743 memcpy(&mdl, r, left); 4744 } 4745 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4746 swapStruct(mdl); 4747 4748 print_indent(indent); 4749 outs() << " count " << mdl.count << "\n"; 4750 4751 list = r + sizeof(struct objc_method_description_list_t); 4752 for (i = 0; i < mdl.count; i++) { 4753 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 4754 print_indent(indent); 4755 outs() << " remaining list entries extend past the of the section\n"; 4756 break; 4757 } 4758 print_indent(indent); 4759 outs() << " list[" << i << "]\n"; 4760 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 4761 sizeof(struct objc_method_description_t)); 4762 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4763 swapStruct(md); 4764 4765 print_indent(indent); 4766 outs() << " name " << format("0x%08" PRIx32, md.name); 4767 if (info->verbose) { 4768 name = get_pointer_32(md.name, offset, xleft, S, info, true); 4769 if (name != nullptr) 4770 outs() << format(" %.*s", xleft, name); 4771 else 4772 outs() << " (not in an __OBJC section)"; 4773 } 4774 outs() << "\n"; 4775 4776 print_indent(indent); 4777 outs() << " types " << format("0x%08" PRIx32, md.types); 4778 if (info->verbose) { 4779 name = get_pointer_32(md.types, offset, xleft, S, info, true); 4780 if (name != nullptr) 4781 outs() << format(" %.*s", xleft, name); 4782 else 4783 outs() << " (not in an __OBJC section)"; 4784 } 4785 outs() << "\n"; 4786 } 4787 return false; 4788 } 4789 4790 static bool print_protocol_list(uint32_t p, uint32_t indent, 4791 struct DisassembleInfo *info); 4792 4793 static bool print_protocol(uint32_t p, uint32_t indent, 4794 struct DisassembleInfo *info) { 4795 uint32_t offset, left; 4796 SectionRef S; 4797 struct objc_protocol_t protocol; 4798 const char *r, *name; 4799 4800 r = get_pointer_32(p, offset, left, S, info, true); 4801 if (r == nullptr) 4802 return true; 4803 4804 outs() << "\n"; 4805 if (left >= sizeof(struct objc_protocol_t)) { 4806 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 4807 } else { 4808 print_indent(indent); 4809 outs() << " Protocol extends past end of the section\n"; 4810 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 4811 memcpy(&protocol, r, left); 4812 } 4813 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4814 swapStruct(protocol); 4815 4816 print_indent(indent); 4817 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 4818 << "\n"; 4819 4820 print_indent(indent); 4821 outs() << " protocol_name " 4822 << format("0x%08" PRIx32, protocol.protocol_name); 4823 if (info->verbose) { 4824 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 4825 if (name != nullptr) 4826 outs() << format(" %.*s", left, name); 4827 else 4828 outs() << " (not in an __OBJC section)"; 4829 } 4830 outs() << "\n"; 4831 4832 print_indent(indent); 4833 outs() << " protocol_list " 4834 << format("0x%08" PRIx32, protocol.protocol_list); 4835 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 4836 outs() << " (not in an __OBJC section)\n"; 4837 4838 print_indent(indent); 4839 outs() << " instance_methods " 4840 << format("0x%08" PRIx32, protocol.instance_methods); 4841 if (print_method_description_list(protocol.instance_methods, indent, info)) 4842 outs() << " (not in an __OBJC section)\n"; 4843 4844 print_indent(indent); 4845 outs() << " class_methods " 4846 << format("0x%08" PRIx32, protocol.class_methods); 4847 if (print_method_description_list(protocol.class_methods, indent, info)) 4848 outs() << " (not in an __OBJC section)\n"; 4849 4850 return false; 4851 } 4852 4853 static bool print_protocol_list(uint32_t p, uint32_t indent, 4854 struct DisassembleInfo *info) { 4855 uint32_t offset, left, l; 4856 SectionRef S; 4857 struct objc_protocol_list_t protocol_list; 4858 const char *r, *list; 4859 int32_t i; 4860 4861 r = get_pointer_32(p, offset, left, S, info, true); 4862 if (r == nullptr) 4863 return true; 4864 4865 outs() << "\n"; 4866 if (left > sizeof(struct objc_protocol_list_t)) { 4867 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 4868 } else { 4869 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 4870 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 4871 memcpy(&protocol_list, r, left); 4872 } 4873 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4874 swapStruct(protocol_list); 4875 4876 print_indent(indent); 4877 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 4878 << "\n"; 4879 print_indent(indent); 4880 outs() << " count " << protocol_list.count << "\n"; 4881 4882 list = r + sizeof(struct objc_protocol_list_t); 4883 for (i = 0; i < protocol_list.count; i++) { 4884 if ((i + 1) * sizeof(uint32_t) > left) { 4885 outs() << "\t\t remaining list entries extend past the of the section\n"; 4886 break; 4887 } 4888 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 4889 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4890 sys::swapByteOrder(l); 4891 4892 print_indent(indent); 4893 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 4894 if (print_protocol(l, indent, info)) 4895 outs() << "(not in an __OBJC section)\n"; 4896 } 4897 return false; 4898 } 4899 4900 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 4901 struct ivar_list64_t il; 4902 struct ivar64_t i; 4903 const char *r; 4904 uint32_t offset, xoffset, left, j; 4905 SectionRef S, xS; 4906 const char *name, *sym_name, *ivar_offset_p; 4907 uint64_t ivar_offset, n_value; 4908 4909 r = get_pointer_64(p, offset, left, S, info); 4910 if (r == nullptr) 4911 return; 4912 memset(&il, '\0', sizeof(struct ivar_list64_t)); 4913 if (left < sizeof(struct ivar_list64_t)) { 4914 memcpy(&il, r, left); 4915 outs() << " (ivar_list_t entends past the end of the section)\n"; 4916 } else 4917 memcpy(&il, r, sizeof(struct ivar_list64_t)); 4918 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4919 swapStruct(il); 4920 outs() << " entsize " << il.entsize << "\n"; 4921 outs() << " count " << il.count << "\n"; 4922 4923 p += sizeof(struct ivar_list64_t); 4924 offset += sizeof(struct ivar_list64_t); 4925 for (j = 0; j < il.count; j++) { 4926 r = get_pointer_64(p, offset, left, S, info); 4927 if (r == nullptr) 4928 return; 4929 memset(&i, '\0', sizeof(struct ivar64_t)); 4930 if (left < sizeof(struct ivar64_t)) { 4931 memcpy(&i, r, left); 4932 outs() << " (ivar_t entends past the end of the section)\n"; 4933 } else 4934 memcpy(&i, r, sizeof(struct ivar64_t)); 4935 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4936 swapStruct(i); 4937 4938 outs() << "\t\t\t offset "; 4939 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 4940 info, n_value, i.offset); 4941 if (n_value != 0) { 4942 if (info->verbose && sym_name != nullptr) 4943 outs() << sym_name; 4944 else 4945 outs() << format("0x%" PRIx64, n_value); 4946 if (i.offset != 0) 4947 outs() << " + " << format("0x%" PRIx64, i.offset); 4948 } else 4949 outs() << format("0x%" PRIx64, i.offset); 4950 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 4951 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4952 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4953 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4954 sys::swapByteOrder(ivar_offset); 4955 outs() << " " << ivar_offset << "\n"; 4956 } else 4957 outs() << "\n"; 4958 4959 outs() << "\t\t\t name "; 4960 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 4961 n_value, i.name); 4962 if (n_value != 0) { 4963 if (info->verbose && sym_name != nullptr) 4964 outs() << sym_name; 4965 else 4966 outs() << format("0x%" PRIx64, n_value); 4967 if (i.name != 0) 4968 outs() << " + " << format("0x%" PRIx64, i.name); 4969 } else 4970 outs() << format("0x%" PRIx64, i.name); 4971 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 4972 if (name != nullptr) 4973 outs() << format(" %.*s", left, name); 4974 outs() << "\n"; 4975 4976 outs() << "\t\t\t type "; 4977 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 4978 n_value, i.name); 4979 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 4980 if (n_value != 0) { 4981 if (info->verbose && sym_name != nullptr) 4982 outs() << sym_name; 4983 else 4984 outs() << format("0x%" PRIx64, n_value); 4985 if (i.type != 0) 4986 outs() << " + " << format("0x%" PRIx64, i.type); 4987 } else 4988 outs() << format("0x%" PRIx64, i.type); 4989 if (name != nullptr) 4990 outs() << format(" %.*s", left, name); 4991 outs() << "\n"; 4992 4993 outs() << "\t\t\talignment " << i.alignment << "\n"; 4994 outs() << "\t\t\t size " << i.size << "\n"; 4995 4996 p += sizeof(struct ivar64_t); 4997 offset += sizeof(struct ivar64_t); 4998 } 4999 } 5000 5001 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 5002 struct ivar_list32_t il; 5003 struct ivar32_t i; 5004 const char *r; 5005 uint32_t offset, xoffset, left, j; 5006 SectionRef S, xS; 5007 const char *name, *ivar_offset_p; 5008 uint32_t ivar_offset; 5009 5010 r = get_pointer_32(p, offset, left, S, info); 5011 if (r == nullptr) 5012 return; 5013 memset(&il, '\0', sizeof(struct ivar_list32_t)); 5014 if (left < sizeof(struct ivar_list32_t)) { 5015 memcpy(&il, r, left); 5016 outs() << " (ivar_list_t entends past the end of the section)\n"; 5017 } else 5018 memcpy(&il, r, sizeof(struct ivar_list32_t)); 5019 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5020 swapStruct(il); 5021 outs() << " entsize " << il.entsize << "\n"; 5022 outs() << " count " << il.count << "\n"; 5023 5024 p += sizeof(struct ivar_list32_t); 5025 offset += sizeof(struct ivar_list32_t); 5026 for (j = 0; j < il.count; j++) { 5027 r = get_pointer_32(p, offset, left, S, info); 5028 if (r == nullptr) 5029 return; 5030 memset(&i, '\0', sizeof(struct ivar32_t)); 5031 if (left < sizeof(struct ivar32_t)) { 5032 memcpy(&i, r, left); 5033 outs() << " (ivar_t entends past the end of the section)\n"; 5034 } else 5035 memcpy(&i, r, sizeof(struct ivar32_t)); 5036 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5037 swapStruct(i); 5038 5039 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 5040 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 5041 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 5042 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 5043 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5044 sys::swapByteOrder(ivar_offset); 5045 outs() << " " << ivar_offset << "\n"; 5046 } else 5047 outs() << "\n"; 5048 5049 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 5050 name = get_pointer_32(i.name, xoffset, left, xS, info); 5051 if (name != nullptr) 5052 outs() << format(" %.*s", left, name); 5053 outs() << "\n"; 5054 5055 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 5056 name = get_pointer_32(i.type, xoffset, left, xS, info); 5057 if (name != nullptr) 5058 outs() << format(" %.*s", left, name); 5059 outs() << "\n"; 5060 5061 outs() << "\t\t\talignment " << i.alignment << "\n"; 5062 outs() << "\t\t\t size " << i.size << "\n"; 5063 5064 p += sizeof(struct ivar32_t); 5065 offset += sizeof(struct ivar32_t); 5066 } 5067 } 5068 5069 static void print_objc_property_list64(uint64_t p, 5070 struct DisassembleInfo *info) { 5071 struct objc_property_list64 opl; 5072 struct objc_property64 op; 5073 const char *r; 5074 uint32_t offset, xoffset, left, j; 5075 SectionRef S, xS; 5076 const char *name, *sym_name; 5077 uint64_t n_value; 5078 5079 r = get_pointer_64(p, offset, left, S, info); 5080 if (r == nullptr) 5081 return; 5082 memset(&opl, '\0', sizeof(struct objc_property_list64)); 5083 if (left < sizeof(struct objc_property_list64)) { 5084 memcpy(&opl, r, left); 5085 outs() << " (objc_property_list entends past the end of the section)\n"; 5086 } else 5087 memcpy(&opl, r, sizeof(struct objc_property_list64)); 5088 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5089 swapStruct(opl); 5090 outs() << " entsize " << opl.entsize << "\n"; 5091 outs() << " count " << opl.count << "\n"; 5092 5093 p += sizeof(struct objc_property_list64); 5094 offset += sizeof(struct objc_property_list64); 5095 for (j = 0; j < opl.count; j++) { 5096 r = get_pointer_64(p, offset, left, S, info); 5097 if (r == nullptr) 5098 return; 5099 memset(&op, '\0', sizeof(struct objc_property64)); 5100 if (left < sizeof(struct objc_property64)) { 5101 memcpy(&op, r, left); 5102 outs() << " (objc_property entends past the end of the section)\n"; 5103 } else 5104 memcpy(&op, r, sizeof(struct objc_property64)); 5105 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5106 swapStruct(op); 5107 5108 outs() << "\t\t\t name "; 5109 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 5110 info, n_value, op.name); 5111 if (n_value != 0) { 5112 if (info->verbose && sym_name != nullptr) 5113 outs() << sym_name; 5114 else 5115 outs() << format("0x%" PRIx64, n_value); 5116 if (op.name != 0) 5117 outs() << " + " << format("0x%" PRIx64, op.name); 5118 } else 5119 outs() << format("0x%" PRIx64, op.name); 5120 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 5121 if (name != nullptr) 5122 outs() << format(" %.*s", left, name); 5123 outs() << "\n"; 5124 5125 outs() << "\t\t\tattributes "; 5126 sym_name = 5127 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 5128 info, n_value, op.attributes); 5129 if (n_value != 0) { 5130 if (info->verbose && sym_name != nullptr) 5131 outs() << sym_name; 5132 else 5133 outs() << format("0x%" PRIx64, n_value); 5134 if (op.attributes != 0) 5135 outs() << " + " << format("0x%" PRIx64, op.attributes); 5136 } else 5137 outs() << format("0x%" PRIx64, op.attributes); 5138 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 5139 if (name != nullptr) 5140 outs() << format(" %.*s", left, name); 5141 outs() << "\n"; 5142 5143 p += sizeof(struct objc_property64); 5144 offset += sizeof(struct objc_property64); 5145 } 5146 } 5147 5148 static void print_objc_property_list32(uint32_t p, 5149 struct DisassembleInfo *info) { 5150 struct objc_property_list32 opl; 5151 struct objc_property32 op; 5152 const char *r; 5153 uint32_t offset, xoffset, left, j; 5154 SectionRef S, xS; 5155 const char *name; 5156 5157 r = get_pointer_32(p, offset, left, S, info); 5158 if (r == nullptr) 5159 return; 5160 memset(&opl, '\0', sizeof(struct objc_property_list32)); 5161 if (left < sizeof(struct objc_property_list32)) { 5162 memcpy(&opl, r, left); 5163 outs() << " (objc_property_list entends past the end of the section)\n"; 5164 } else 5165 memcpy(&opl, r, sizeof(struct objc_property_list32)); 5166 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5167 swapStruct(opl); 5168 outs() << " entsize " << opl.entsize << "\n"; 5169 outs() << " count " << opl.count << "\n"; 5170 5171 p += sizeof(struct objc_property_list32); 5172 offset += sizeof(struct objc_property_list32); 5173 for (j = 0; j < opl.count; j++) { 5174 r = get_pointer_32(p, offset, left, S, info); 5175 if (r == nullptr) 5176 return; 5177 memset(&op, '\0', sizeof(struct objc_property32)); 5178 if (left < sizeof(struct objc_property32)) { 5179 memcpy(&op, r, left); 5180 outs() << " (objc_property entends past the end of the section)\n"; 5181 } else 5182 memcpy(&op, r, sizeof(struct objc_property32)); 5183 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5184 swapStruct(op); 5185 5186 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 5187 name = get_pointer_32(op.name, xoffset, left, xS, info); 5188 if (name != nullptr) 5189 outs() << format(" %.*s", left, name); 5190 outs() << "\n"; 5191 5192 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 5193 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 5194 if (name != nullptr) 5195 outs() << format(" %.*s", left, name); 5196 outs() << "\n"; 5197 5198 p += sizeof(struct objc_property32); 5199 offset += sizeof(struct objc_property32); 5200 } 5201 } 5202 5203 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 5204 bool &is_meta_class) { 5205 struct class_ro64_t cro; 5206 const char *r; 5207 uint32_t offset, xoffset, left; 5208 SectionRef S, xS; 5209 const char *name, *sym_name; 5210 uint64_t n_value; 5211 5212 r = get_pointer_64(p, offset, left, S, info); 5213 if (r == nullptr || left < sizeof(struct class_ro64_t)) 5214 return false; 5215 memcpy(&cro, r, sizeof(struct class_ro64_t)); 5216 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5217 swapStruct(cro); 5218 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5219 if (cro.flags & RO_META) 5220 outs() << " RO_META"; 5221 if (cro.flags & RO_ROOT) 5222 outs() << " RO_ROOT"; 5223 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5224 outs() << " RO_HAS_CXX_STRUCTORS"; 5225 outs() << "\n"; 5226 outs() << " instanceStart " << cro.instanceStart << "\n"; 5227 outs() << " instanceSize " << cro.instanceSize << "\n"; 5228 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 5229 << "\n"; 5230 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 5231 << "\n"; 5232 print_layout_map64(cro.ivarLayout, info); 5233 5234 outs() << " name "; 5235 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 5236 info, n_value, cro.name); 5237 if (n_value != 0) { 5238 if (info->verbose && sym_name != nullptr) 5239 outs() << sym_name; 5240 else 5241 outs() << format("0x%" PRIx64, n_value); 5242 if (cro.name != 0) 5243 outs() << " + " << format("0x%" PRIx64, cro.name); 5244 } else 5245 outs() << format("0x%" PRIx64, cro.name); 5246 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 5247 if (name != nullptr) 5248 outs() << format(" %.*s", left, name); 5249 outs() << "\n"; 5250 5251 outs() << " baseMethods "; 5252 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 5253 S, info, n_value, cro.baseMethods); 5254 if (n_value != 0) { 5255 if (info->verbose && sym_name != nullptr) 5256 outs() << sym_name; 5257 else 5258 outs() << format("0x%" PRIx64, n_value); 5259 if (cro.baseMethods != 0) 5260 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 5261 } else 5262 outs() << format("0x%" PRIx64, cro.baseMethods); 5263 outs() << " (struct method_list_t *)\n"; 5264 if (cro.baseMethods + n_value != 0) 5265 print_method_list64_t(cro.baseMethods + n_value, info, ""); 5266 5267 outs() << " baseProtocols "; 5268 sym_name = 5269 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 5270 info, n_value, cro.baseProtocols); 5271 if (n_value != 0) { 5272 if (info->verbose && sym_name != nullptr) 5273 outs() << sym_name; 5274 else 5275 outs() << format("0x%" PRIx64, n_value); 5276 if (cro.baseProtocols != 0) 5277 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 5278 } else 5279 outs() << format("0x%" PRIx64, cro.baseProtocols); 5280 outs() << "\n"; 5281 if (cro.baseProtocols + n_value != 0) 5282 print_protocol_list64_t(cro.baseProtocols + n_value, info); 5283 5284 outs() << " ivars "; 5285 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 5286 info, n_value, cro.ivars); 5287 if (n_value != 0) { 5288 if (info->verbose && sym_name != nullptr) 5289 outs() << sym_name; 5290 else 5291 outs() << format("0x%" PRIx64, n_value); 5292 if (cro.ivars != 0) 5293 outs() << " + " << format("0x%" PRIx64, cro.ivars); 5294 } else 5295 outs() << format("0x%" PRIx64, cro.ivars); 5296 outs() << "\n"; 5297 if (cro.ivars + n_value != 0) 5298 print_ivar_list64_t(cro.ivars + n_value, info); 5299 5300 outs() << " weakIvarLayout "; 5301 sym_name = 5302 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 5303 info, n_value, cro.weakIvarLayout); 5304 if (n_value != 0) { 5305 if (info->verbose && sym_name != nullptr) 5306 outs() << sym_name; 5307 else 5308 outs() << format("0x%" PRIx64, n_value); 5309 if (cro.weakIvarLayout != 0) 5310 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 5311 } else 5312 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 5313 outs() << "\n"; 5314 print_layout_map64(cro.weakIvarLayout + n_value, info); 5315 5316 outs() << " baseProperties "; 5317 sym_name = 5318 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 5319 info, n_value, cro.baseProperties); 5320 if (n_value != 0) { 5321 if (info->verbose && sym_name != nullptr) 5322 outs() << sym_name; 5323 else 5324 outs() << format("0x%" PRIx64, n_value); 5325 if (cro.baseProperties != 0) 5326 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 5327 } else 5328 outs() << format("0x%" PRIx64, cro.baseProperties); 5329 outs() << "\n"; 5330 if (cro.baseProperties + n_value != 0) 5331 print_objc_property_list64(cro.baseProperties + n_value, info); 5332 5333 is_meta_class = (cro.flags & RO_META) != 0; 5334 return true; 5335 } 5336 5337 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 5338 bool &is_meta_class) { 5339 struct class_ro32_t cro; 5340 const char *r; 5341 uint32_t offset, xoffset, left; 5342 SectionRef S, xS; 5343 const char *name; 5344 5345 r = get_pointer_32(p, offset, left, S, info); 5346 if (r == nullptr) 5347 return false; 5348 memset(&cro, '\0', sizeof(struct class_ro32_t)); 5349 if (left < sizeof(struct class_ro32_t)) { 5350 memcpy(&cro, r, left); 5351 outs() << " (class_ro_t entends past the end of the section)\n"; 5352 } else 5353 memcpy(&cro, r, sizeof(struct class_ro32_t)); 5354 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5355 swapStruct(cro); 5356 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5357 if (cro.flags & RO_META) 5358 outs() << " RO_META"; 5359 if (cro.flags & RO_ROOT) 5360 outs() << " RO_ROOT"; 5361 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5362 outs() << " RO_HAS_CXX_STRUCTORS"; 5363 outs() << "\n"; 5364 outs() << " instanceStart " << cro.instanceStart << "\n"; 5365 outs() << " instanceSize " << cro.instanceSize << "\n"; 5366 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 5367 << "\n"; 5368 print_layout_map32(cro.ivarLayout, info); 5369 5370 outs() << " name " << format("0x%" PRIx32, cro.name); 5371 name = get_pointer_32(cro.name, xoffset, left, xS, info); 5372 if (name != nullptr) 5373 outs() << format(" %.*s", left, name); 5374 outs() << "\n"; 5375 5376 outs() << " baseMethods " 5377 << format("0x%" PRIx32, cro.baseMethods) 5378 << " (struct method_list_t *)\n"; 5379 if (cro.baseMethods != 0) 5380 print_method_list32_t(cro.baseMethods, info, ""); 5381 5382 outs() << " baseProtocols " 5383 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 5384 if (cro.baseProtocols != 0) 5385 print_protocol_list32_t(cro.baseProtocols, info); 5386 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 5387 << "\n"; 5388 if (cro.ivars != 0) 5389 print_ivar_list32_t(cro.ivars, info); 5390 outs() << " weakIvarLayout " 5391 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 5392 print_layout_map32(cro.weakIvarLayout, info); 5393 outs() << " baseProperties " 5394 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 5395 if (cro.baseProperties != 0) 5396 print_objc_property_list32(cro.baseProperties, info); 5397 is_meta_class = (cro.flags & RO_META) != 0; 5398 return true; 5399 } 5400 5401 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 5402 struct class64_t c; 5403 const char *r; 5404 uint32_t offset, left; 5405 SectionRef S; 5406 const char *name; 5407 uint64_t isa_n_value, n_value; 5408 5409 r = get_pointer_64(p, offset, left, S, info); 5410 if (r == nullptr || left < sizeof(struct class64_t)) 5411 return; 5412 memcpy(&c, r, sizeof(struct class64_t)); 5413 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5414 swapStruct(c); 5415 5416 outs() << " isa " << format("0x%" PRIx64, c.isa); 5417 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 5418 isa_n_value, c.isa); 5419 if (name != nullptr) 5420 outs() << " " << name; 5421 outs() << "\n"; 5422 5423 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 5424 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 5425 n_value, c.superclass); 5426 if (name != nullptr) 5427 outs() << " " << name; 5428 else { 5429 name = get_dyld_bind_info_symbolname(S.getAddress() + 5430 offset + offsetof(struct class64_t, superclass), info); 5431 if (name != nullptr) 5432 outs() << " " << name; 5433 } 5434 outs() << "\n"; 5435 5436 outs() << " cache " << format("0x%" PRIx64, c.cache); 5437 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 5438 n_value, c.cache); 5439 if (name != nullptr) 5440 outs() << " " << name; 5441 outs() << "\n"; 5442 5443 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 5444 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 5445 n_value, c.vtable); 5446 if (name != nullptr) 5447 outs() << " " << name; 5448 outs() << "\n"; 5449 5450 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 5451 n_value, c.data); 5452 outs() << " data "; 5453 if (n_value != 0) { 5454 if (info->verbose && name != nullptr) 5455 outs() << name; 5456 else 5457 outs() << format("0x%" PRIx64, n_value); 5458 if (c.data != 0) 5459 outs() << " + " << format("0x%" PRIx64, c.data); 5460 } else 5461 outs() << format("0x%" PRIx64, c.data); 5462 outs() << " (struct class_ro_t *)"; 5463 5464 // This is a Swift class if some of the low bits of the pointer are set. 5465 if ((c.data + n_value) & 0x7) 5466 outs() << " Swift class"; 5467 outs() << "\n"; 5468 bool is_meta_class; 5469 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5470 return; 5471 5472 if (!is_meta_class && 5473 c.isa + isa_n_value != p && 5474 c.isa + isa_n_value != 0 && 5475 info->depth < 100) { 5476 info->depth++; 5477 outs() << "Meta Class\n"; 5478 print_class64_t(c.isa + isa_n_value, info); 5479 } 5480 } 5481 5482 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5483 struct class32_t c; 5484 const char *r; 5485 uint32_t offset, left; 5486 SectionRef S; 5487 const char *name; 5488 5489 r = get_pointer_32(p, offset, left, S, info); 5490 if (r == nullptr) 5491 return; 5492 memset(&c, '\0', sizeof(struct class32_t)); 5493 if (left < sizeof(struct class32_t)) { 5494 memcpy(&c, r, left); 5495 outs() << " (class_t entends past the end of the section)\n"; 5496 } else 5497 memcpy(&c, r, sizeof(struct class32_t)); 5498 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5499 swapStruct(c); 5500 5501 outs() << " isa " << format("0x%" PRIx32, c.isa); 5502 name = 5503 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5504 if (name != nullptr) 5505 outs() << " " << name; 5506 outs() << "\n"; 5507 5508 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5509 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5510 c.superclass); 5511 if (name != nullptr) 5512 outs() << " " << name; 5513 outs() << "\n"; 5514 5515 outs() << " cache " << format("0x%" PRIx32, c.cache); 5516 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5517 c.cache); 5518 if (name != nullptr) 5519 outs() << " " << name; 5520 outs() << "\n"; 5521 5522 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5523 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5524 c.vtable); 5525 if (name != nullptr) 5526 outs() << " " << name; 5527 outs() << "\n"; 5528 5529 name = 5530 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5531 outs() << " data " << format("0x%" PRIx32, c.data) 5532 << " (struct class_ro_t *)"; 5533 5534 // This is a Swift class if some of the low bits of the pointer are set. 5535 if (c.data & 0x3) 5536 outs() << " Swift class"; 5537 outs() << "\n"; 5538 bool is_meta_class; 5539 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5540 return; 5541 5542 if (!is_meta_class) { 5543 outs() << "Meta Class\n"; 5544 print_class32_t(c.isa, info); 5545 } 5546 } 5547 5548 static void print_objc_class_t(struct objc_class_t *objc_class, 5549 struct DisassembleInfo *info) { 5550 uint32_t offset, left, xleft; 5551 const char *name, *p, *ivar_list; 5552 SectionRef S; 5553 int32_t i; 5554 struct objc_ivar_list_t objc_ivar_list; 5555 struct objc_ivar_t ivar; 5556 5557 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5558 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5559 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5560 if (name != nullptr) 5561 outs() << format(" %.*s", left, name); 5562 else 5563 outs() << " (not in an __OBJC section)"; 5564 } 5565 outs() << "\n"; 5566 5567 outs() << "\t super_class " 5568 << format("0x%08" PRIx32, objc_class->super_class); 5569 if (info->verbose) { 5570 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5571 if (name != nullptr) 5572 outs() << format(" %.*s", left, name); 5573 else 5574 outs() << " (not in an __OBJC section)"; 5575 } 5576 outs() << "\n"; 5577 5578 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5579 if (info->verbose) { 5580 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5581 if (name != nullptr) 5582 outs() << format(" %.*s", left, name); 5583 else 5584 outs() << " (not in an __OBJC section)"; 5585 } 5586 outs() << "\n"; 5587 5588 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5589 << "\n"; 5590 5591 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5592 if (info->verbose) { 5593 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5594 outs() << " CLS_CLASS"; 5595 else if (CLS_GETINFO(objc_class, CLS_META)) 5596 outs() << " CLS_META"; 5597 } 5598 outs() << "\n"; 5599 5600 outs() << "\t instance_size " 5601 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5602 5603 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5604 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5605 if (p != nullptr) { 5606 if (left > sizeof(struct objc_ivar_list_t)) { 5607 outs() << "\n"; 5608 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5609 } else { 5610 outs() << " (entends past the end of the section)\n"; 5611 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5612 memcpy(&objc_ivar_list, p, left); 5613 } 5614 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5615 swapStruct(objc_ivar_list); 5616 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5617 ivar_list = p + sizeof(struct objc_ivar_list_t); 5618 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5619 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5620 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5621 break; 5622 } 5623 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5624 sizeof(struct objc_ivar_t)); 5625 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5626 swapStruct(ivar); 5627 5628 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5629 if (info->verbose) { 5630 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5631 if (name != nullptr) 5632 outs() << format(" %.*s", xleft, name); 5633 else 5634 outs() << " (not in an __OBJC section)"; 5635 } 5636 outs() << "\n"; 5637 5638 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5639 if (info->verbose) { 5640 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5641 if (name != nullptr) 5642 outs() << format(" %.*s", xleft, name); 5643 else 5644 outs() << " (not in an __OBJC section)"; 5645 } 5646 outs() << "\n"; 5647 5648 outs() << "\t\t ivar_offset " 5649 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5650 } 5651 } else { 5652 outs() << " (not in an __OBJC section)\n"; 5653 } 5654 5655 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5656 if (print_method_list(objc_class->methodLists, info)) 5657 outs() << " (not in an __OBJC section)\n"; 5658 5659 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5660 << "\n"; 5661 5662 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5663 if (print_protocol_list(objc_class->protocols, 16, info)) 5664 outs() << " (not in an __OBJC section)\n"; 5665 } 5666 5667 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5668 struct DisassembleInfo *info) { 5669 uint32_t offset, left; 5670 const char *name; 5671 SectionRef S; 5672 5673 outs() << "\t category name " 5674 << format("0x%08" PRIx32, objc_category->category_name); 5675 if (info->verbose) { 5676 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5677 true); 5678 if (name != nullptr) 5679 outs() << format(" %.*s", left, name); 5680 else 5681 outs() << " (not in an __OBJC section)"; 5682 } 5683 outs() << "\n"; 5684 5685 outs() << "\t\t class name " 5686 << format("0x%08" PRIx32, objc_category->class_name); 5687 if (info->verbose) { 5688 name = 5689 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5690 if (name != nullptr) 5691 outs() << format(" %.*s", left, name); 5692 else 5693 outs() << " (not in an __OBJC section)"; 5694 } 5695 outs() << "\n"; 5696 5697 outs() << "\t instance methods " 5698 << format("0x%08" PRIx32, objc_category->instance_methods); 5699 if (print_method_list(objc_category->instance_methods, info)) 5700 outs() << " (not in an __OBJC section)\n"; 5701 5702 outs() << "\t class methods " 5703 << format("0x%08" PRIx32, objc_category->class_methods); 5704 if (print_method_list(objc_category->class_methods, info)) 5705 outs() << " (not in an __OBJC section)\n"; 5706 } 5707 5708 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5709 struct category64_t c; 5710 const char *r; 5711 uint32_t offset, xoffset, left; 5712 SectionRef S, xS; 5713 const char *name, *sym_name; 5714 uint64_t n_value; 5715 5716 r = get_pointer_64(p, offset, left, S, info); 5717 if (r == nullptr) 5718 return; 5719 memset(&c, '\0', sizeof(struct category64_t)); 5720 if (left < sizeof(struct category64_t)) { 5721 memcpy(&c, r, left); 5722 outs() << " (category_t entends past the end of the section)\n"; 5723 } else 5724 memcpy(&c, r, sizeof(struct category64_t)); 5725 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5726 swapStruct(c); 5727 5728 outs() << " name "; 5729 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 5730 info, n_value, c.name); 5731 if (n_value != 0) { 5732 if (info->verbose && sym_name != nullptr) 5733 outs() << sym_name; 5734 else 5735 outs() << format("0x%" PRIx64, n_value); 5736 if (c.name != 0) 5737 outs() << " + " << format("0x%" PRIx64, c.name); 5738 } else 5739 outs() << format("0x%" PRIx64, c.name); 5740 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 5741 if (name != nullptr) 5742 outs() << format(" %.*s", left, name); 5743 outs() << "\n"; 5744 5745 outs() << " cls "; 5746 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 5747 n_value, c.cls); 5748 if (n_value != 0) { 5749 if (info->verbose && sym_name != nullptr) 5750 outs() << sym_name; 5751 else 5752 outs() << format("0x%" PRIx64, n_value); 5753 if (c.cls != 0) 5754 outs() << " + " << format("0x%" PRIx64, c.cls); 5755 } else 5756 outs() << format("0x%" PRIx64, c.cls); 5757 outs() << "\n"; 5758 if (c.cls + n_value != 0) 5759 print_class64_t(c.cls + n_value, info); 5760 5761 outs() << " instanceMethods "; 5762 sym_name = 5763 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 5764 info, n_value, c.instanceMethods); 5765 if (n_value != 0) { 5766 if (info->verbose && sym_name != nullptr) 5767 outs() << sym_name; 5768 else 5769 outs() << format("0x%" PRIx64, n_value); 5770 if (c.instanceMethods != 0) 5771 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 5772 } else 5773 outs() << format("0x%" PRIx64, c.instanceMethods); 5774 outs() << "\n"; 5775 if (c.instanceMethods + n_value != 0) 5776 print_method_list64_t(c.instanceMethods + n_value, info, ""); 5777 5778 outs() << " classMethods "; 5779 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 5780 S, info, n_value, c.classMethods); 5781 if (n_value != 0) { 5782 if (info->verbose && sym_name != nullptr) 5783 outs() << sym_name; 5784 else 5785 outs() << format("0x%" PRIx64, n_value); 5786 if (c.classMethods != 0) 5787 outs() << " + " << format("0x%" PRIx64, c.classMethods); 5788 } else 5789 outs() << format("0x%" PRIx64, c.classMethods); 5790 outs() << "\n"; 5791 if (c.classMethods + n_value != 0) 5792 print_method_list64_t(c.classMethods + n_value, info, ""); 5793 5794 outs() << " protocols "; 5795 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 5796 info, n_value, c.protocols); 5797 if (n_value != 0) { 5798 if (info->verbose && sym_name != nullptr) 5799 outs() << sym_name; 5800 else 5801 outs() << format("0x%" PRIx64, n_value); 5802 if (c.protocols != 0) 5803 outs() << " + " << format("0x%" PRIx64, c.protocols); 5804 } else 5805 outs() << format("0x%" PRIx64, c.protocols); 5806 outs() << "\n"; 5807 if (c.protocols + n_value != 0) 5808 print_protocol_list64_t(c.protocols + n_value, info); 5809 5810 outs() << "instanceProperties "; 5811 sym_name = 5812 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 5813 S, info, n_value, c.instanceProperties); 5814 if (n_value != 0) { 5815 if (info->verbose && sym_name != nullptr) 5816 outs() << sym_name; 5817 else 5818 outs() << format("0x%" PRIx64, n_value); 5819 if (c.instanceProperties != 0) 5820 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 5821 } else 5822 outs() << format("0x%" PRIx64, c.instanceProperties); 5823 outs() << "\n"; 5824 if (c.instanceProperties + n_value != 0) 5825 print_objc_property_list64(c.instanceProperties + n_value, info); 5826 } 5827 5828 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 5829 struct category32_t c; 5830 const char *r; 5831 uint32_t offset, left; 5832 SectionRef S, xS; 5833 const char *name; 5834 5835 r = get_pointer_32(p, offset, left, S, info); 5836 if (r == nullptr) 5837 return; 5838 memset(&c, '\0', sizeof(struct category32_t)); 5839 if (left < sizeof(struct category32_t)) { 5840 memcpy(&c, r, left); 5841 outs() << " (category_t entends past the end of the section)\n"; 5842 } else 5843 memcpy(&c, r, sizeof(struct category32_t)); 5844 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5845 swapStruct(c); 5846 5847 outs() << " name " << format("0x%" PRIx32, c.name); 5848 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 5849 c.name); 5850 if (name) 5851 outs() << " " << name; 5852 outs() << "\n"; 5853 5854 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 5855 if (c.cls != 0) 5856 print_class32_t(c.cls, info); 5857 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 5858 << "\n"; 5859 if (c.instanceMethods != 0) 5860 print_method_list32_t(c.instanceMethods, info, ""); 5861 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 5862 << "\n"; 5863 if (c.classMethods != 0) 5864 print_method_list32_t(c.classMethods, info, ""); 5865 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 5866 if (c.protocols != 0) 5867 print_protocol_list32_t(c.protocols, info); 5868 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 5869 << "\n"; 5870 if (c.instanceProperties != 0) 5871 print_objc_property_list32(c.instanceProperties, info); 5872 } 5873 5874 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 5875 uint32_t i, left, offset, xoffset; 5876 uint64_t p, n_value; 5877 struct message_ref64 mr; 5878 const char *name, *sym_name; 5879 const char *r; 5880 SectionRef xS; 5881 5882 if (S == SectionRef()) 5883 return; 5884 5885 StringRef SectName; 5886 Expected<StringRef> SecNameOrErr = S.getName(); 5887 if (SecNameOrErr) 5888 SectName = *SecNameOrErr; 5889 else 5890 consumeError(SecNameOrErr.takeError()); 5891 5892 DataRefImpl Ref = S.getRawDataRefImpl(); 5893 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5894 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5895 offset = 0; 5896 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5897 p = S.getAddress() + i; 5898 r = get_pointer_64(p, offset, left, S, info); 5899 if (r == nullptr) 5900 return; 5901 memset(&mr, '\0', sizeof(struct message_ref64)); 5902 if (left < sizeof(struct message_ref64)) { 5903 memcpy(&mr, r, left); 5904 outs() << " (message_ref entends past the end of the section)\n"; 5905 } else 5906 memcpy(&mr, r, sizeof(struct message_ref64)); 5907 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5908 swapStruct(mr); 5909 5910 outs() << " imp "; 5911 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 5912 n_value, mr.imp); 5913 if (n_value != 0) { 5914 outs() << format("0x%" PRIx64, n_value) << " "; 5915 if (mr.imp != 0) 5916 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 5917 } else 5918 outs() << format("0x%" PRIx64, mr.imp) << " "; 5919 if (name != nullptr) 5920 outs() << " " << name; 5921 outs() << "\n"; 5922 5923 outs() << " sel "; 5924 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 5925 info, n_value, mr.sel); 5926 if (n_value != 0) { 5927 if (info->verbose && sym_name != nullptr) 5928 outs() << sym_name; 5929 else 5930 outs() << format("0x%" PRIx64, n_value); 5931 if (mr.sel != 0) 5932 outs() << " + " << format("0x%" PRIx64, mr.sel); 5933 } else 5934 outs() << format("0x%" PRIx64, mr.sel); 5935 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 5936 if (name != nullptr) 5937 outs() << format(" %.*s", left, name); 5938 outs() << "\n"; 5939 5940 offset += sizeof(struct message_ref64); 5941 } 5942 } 5943 5944 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 5945 uint32_t i, left, offset, xoffset, p; 5946 struct message_ref32 mr; 5947 const char *name, *r; 5948 SectionRef xS; 5949 5950 if (S == SectionRef()) 5951 return; 5952 5953 StringRef SectName; 5954 Expected<StringRef> SecNameOrErr = S.getName(); 5955 if (SecNameOrErr) 5956 SectName = *SecNameOrErr; 5957 else 5958 consumeError(SecNameOrErr.takeError()); 5959 5960 DataRefImpl Ref = S.getRawDataRefImpl(); 5961 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5962 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5963 offset = 0; 5964 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5965 p = S.getAddress() + i; 5966 r = get_pointer_32(p, offset, left, S, info); 5967 if (r == nullptr) 5968 return; 5969 memset(&mr, '\0', sizeof(struct message_ref32)); 5970 if (left < sizeof(struct message_ref32)) { 5971 memcpy(&mr, r, left); 5972 outs() << " (message_ref entends past the end of the section)\n"; 5973 } else 5974 memcpy(&mr, r, sizeof(struct message_ref32)); 5975 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5976 swapStruct(mr); 5977 5978 outs() << " imp " << format("0x%" PRIx32, mr.imp); 5979 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 5980 mr.imp); 5981 if (name != nullptr) 5982 outs() << " " << name; 5983 outs() << "\n"; 5984 5985 outs() << " sel " << format("0x%" PRIx32, mr.sel); 5986 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 5987 if (name != nullptr) 5988 outs() << " " << name; 5989 outs() << "\n"; 5990 5991 offset += sizeof(struct message_ref32); 5992 } 5993 } 5994 5995 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 5996 uint32_t left, offset, swift_version; 5997 uint64_t p; 5998 struct objc_image_info64 o; 5999 const char *r; 6000 6001 if (S == SectionRef()) 6002 return; 6003 6004 StringRef SectName; 6005 Expected<StringRef> SecNameOrErr = S.getName(); 6006 if (SecNameOrErr) 6007 SectName = *SecNameOrErr; 6008 else 6009 consumeError(SecNameOrErr.takeError()); 6010 6011 DataRefImpl Ref = S.getRawDataRefImpl(); 6012 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6013 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6014 p = S.getAddress(); 6015 r = get_pointer_64(p, offset, left, S, info); 6016 if (r == nullptr) 6017 return; 6018 memset(&o, '\0', sizeof(struct objc_image_info64)); 6019 if (left < sizeof(struct objc_image_info64)) { 6020 memcpy(&o, r, left); 6021 outs() << " (objc_image_info entends past the end of the section)\n"; 6022 } else 6023 memcpy(&o, r, sizeof(struct objc_image_info64)); 6024 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6025 swapStruct(o); 6026 outs() << " version " << o.version << "\n"; 6027 outs() << " flags " << format("0x%" PRIx32, o.flags); 6028 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 6029 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 6030 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 6031 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 6032 if (o.flags & OBJC_IMAGE_IS_SIMULATED) 6033 outs() << " OBJC_IMAGE_IS_SIMULATED"; 6034 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES) 6035 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES"; 6036 swift_version = (o.flags >> 8) & 0xff; 6037 if (swift_version != 0) { 6038 if (swift_version == 1) 6039 outs() << " Swift 1.0"; 6040 else if (swift_version == 2) 6041 outs() << " Swift 1.1"; 6042 else if(swift_version == 3) 6043 outs() << " Swift 2.0"; 6044 else if(swift_version == 4) 6045 outs() << " Swift 3.0"; 6046 else if(swift_version == 5) 6047 outs() << " Swift 4.0"; 6048 else if(swift_version == 6) 6049 outs() << " Swift 4.1/Swift 4.2"; 6050 else if(swift_version == 7) 6051 outs() << " Swift 5 or later"; 6052 else 6053 outs() << " unknown future Swift version (" << swift_version << ")"; 6054 } 6055 outs() << "\n"; 6056 } 6057 6058 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 6059 uint32_t left, offset, swift_version, p; 6060 struct objc_image_info32 o; 6061 const char *r; 6062 6063 if (S == SectionRef()) 6064 return; 6065 6066 StringRef SectName; 6067 Expected<StringRef> SecNameOrErr = S.getName(); 6068 if (SecNameOrErr) 6069 SectName = *SecNameOrErr; 6070 else 6071 consumeError(SecNameOrErr.takeError()); 6072 6073 DataRefImpl Ref = S.getRawDataRefImpl(); 6074 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6075 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6076 p = S.getAddress(); 6077 r = get_pointer_32(p, offset, left, S, info); 6078 if (r == nullptr) 6079 return; 6080 memset(&o, '\0', sizeof(struct objc_image_info32)); 6081 if (left < sizeof(struct objc_image_info32)) { 6082 memcpy(&o, r, left); 6083 outs() << " (objc_image_info entends past the end of the section)\n"; 6084 } else 6085 memcpy(&o, r, sizeof(struct objc_image_info32)); 6086 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6087 swapStruct(o); 6088 outs() << " version " << o.version << "\n"; 6089 outs() << " flags " << format("0x%" PRIx32, o.flags); 6090 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 6091 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 6092 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 6093 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 6094 swift_version = (o.flags >> 8) & 0xff; 6095 if (swift_version != 0) { 6096 if (swift_version == 1) 6097 outs() << " Swift 1.0"; 6098 else if (swift_version == 2) 6099 outs() << " Swift 1.1"; 6100 else if(swift_version == 3) 6101 outs() << " Swift 2.0"; 6102 else if(swift_version == 4) 6103 outs() << " Swift 3.0"; 6104 else if(swift_version == 5) 6105 outs() << " Swift 4.0"; 6106 else if(swift_version == 6) 6107 outs() << " Swift 4.1/Swift 4.2"; 6108 else if(swift_version == 7) 6109 outs() << " Swift 5 or later"; 6110 else 6111 outs() << " unknown future Swift version (" << swift_version << ")"; 6112 } 6113 outs() << "\n"; 6114 } 6115 6116 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 6117 uint32_t left, offset, p; 6118 struct imageInfo_t o; 6119 const char *r; 6120 6121 StringRef SectName; 6122 Expected<StringRef> SecNameOrErr = S.getName(); 6123 if (SecNameOrErr) 6124 SectName = *SecNameOrErr; 6125 else 6126 consumeError(SecNameOrErr.takeError()); 6127 6128 DataRefImpl Ref = S.getRawDataRefImpl(); 6129 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6130 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6131 p = S.getAddress(); 6132 r = get_pointer_32(p, offset, left, S, info); 6133 if (r == nullptr) 6134 return; 6135 memset(&o, '\0', sizeof(struct imageInfo_t)); 6136 if (left < sizeof(struct imageInfo_t)) { 6137 memcpy(&o, r, left); 6138 outs() << " (imageInfo entends past the end of the section)\n"; 6139 } else 6140 memcpy(&o, r, sizeof(struct imageInfo_t)); 6141 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6142 swapStruct(o); 6143 outs() << " version " << o.version << "\n"; 6144 outs() << " flags " << format("0x%" PRIx32, o.flags); 6145 if (o.flags & 0x1) 6146 outs() << " F&C"; 6147 if (o.flags & 0x2) 6148 outs() << " GC"; 6149 if (o.flags & 0x4) 6150 outs() << " GC-only"; 6151 else 6152 outs() << " RR"; 6153 outs() << "\n"; 6154 } 6155 6156 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 6157 SymbolAddressMap AddrMap; 6158 if (verbose) 6159 CreateSymbolAddressMap(O, &AddrMap); 6160 6161 std::vector<SectionRef> Sections; 6162 append_range(Sections, O->sections()); 6163 6164 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6165 6166 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6167 if (CL == SectionRef()) 6168 CL = get_section(O, "__DATA", "__objc_classlist"); 6169 if (CL == SectionRef()) 6170 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6171 if (CL == SectionRef()) 6172 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6173 info.S = CL; 6174 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 6175 6176 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6177 if (CR == SectionRef()) 6178 CR = get_section(O, "__DATA", "__objc_classrefs"); 6179 if (CR == SectionRef()) 6180 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6181 if (CR == SectionRef()) 6182 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6183 info.S = CR; 6184 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 6185 6186 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6187 if (SR == SectionRef()) 6188 SR = get_section(O, "__DATA", "__objc_superrefs"); 6189 if (SR == SectionRef()) 6190 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6191 if (SR == SectionRef()) 6192 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6193 info.S = SR; 6194 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 6195 6196 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6197 if (CA == SectionRef()) 6198 CA = get_section(O, "__DATA", "__objc_catlist"); 6199 if (CA == SectionRef()) 6200 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6201 if (CA == SectionRef()) 6202 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6203 info.S = CA; 6204 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 6205 6206 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6207 if (PL == SectionRef()) 6208 PL = get_section(O, "__DATA", "__objc_protolist"); 6209 if (PL == SectionRef()) 6210 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6211 if (PL == SectionRef()) 6212 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6213 info.S = PL; 6214 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 6215 6216 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6217 if (MR == SectionRef()) 6218 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6219 if (MR == SectionRef()) 6220 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6221 if (MR == SectionRef()) 6222 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6223 info.S = MR; 6224 print_message_refs64(MR, &info); 6225 6226 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6227 if (II == SectionRef()) 6228 II = get_section(O, "__DATA", "__objc_imageinfo"); 6229 if (II == SectionRef()) 6230 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6231 if (II == SectionRef()) 6232 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6233 info.S = II; 6234 print_image_info64(II, &info); 6235 } 6236 6237 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6238 SymbolAddressMap AddrMap; 6239 if (verbose) 6240 CreateSymbolAddressMap(O, &AddrMap); 6241 6242 std::vector<SectionRef> Sections; 6243 append_range(Sections, O->sections()); 6244 6245 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6246 6247 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6248 if (CL == SectionRef()) 6249 CL = get_section(O, "__DATA", "__objc_classlist"); 6250 if (CL == SectionRef()) 6251 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6252 if (CL == SectionRef()) 6253 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6254 info.S = CL; 6255 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 6256 6257 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6258 if (CR == SectionRef()) 6259 CR = get_section(O, "__DATA", "__objc_classrefs"); 6260 if (CR == SectionRef()) 6261 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6262 if (CR == SectionRef()) 6263 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6264 info.S = CR; 6265 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 6266 6267 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6268 if (SR == SectionRef()) 6269 SR = get_section(O, "__DATA", "__objc_superrefs"); 6270 if (SR == SectionRef()) 6271 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6272 if (SR == SectionRef()) 6273 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6274 info.S = SR; 6275 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 6276 6277 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6278 if (CA == SectionRef()) 6279 CA = get_section(O, "__DATA", "__objc_catlist"); 6280 if (CA == SectionRef()) 6281 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6282 if (CA == SectionRef()) 6283 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6284 info.S = CA; 6285 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 6286 6287 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6288 if (PL == SectionRef()) 6289 PL = get_section(O, "__DATA", "__objc_protolist"); 6290 if (PL == SectionRef()) 6291 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6292 if (PL == SectionRef()) 6293 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6294 info.S = PL; 6295 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 6296 6297 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6298 if (MR == SectionRef()) 6299 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6300 if (MR == SectionRef()) 6301 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6302 if (MR == SectionRef()) 6303 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6304 info.S = MR; 6305 print_message_refs32(MR, &info); 6306 6307 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6308 if (II == SectionRef()) 6309 II = get_section(O, "__DATA", "__objc_imageinfo"); 6310 if (II == SectionRef()) 6311 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6312 if (II == SectionRef()) 6313 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6314 info.S = II; 6315 print_image_info32(II, &info); 6316 } 6317 6318 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6319 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 6320 const char *r, *name, *defs; 6321 struct objc_module_t module; 6322 SectionRef S, xS; 6323 struct objc_symtab_t symtab; 6324 struct objc_class_t objc_class; 6325 struct objc_category_t objc_category; 6326 6327 outs() << "Objective-C segment\n"; 6328 S = get_section(O, "__OBJC", "__module_info"); 6329 if (S == SectionRef()) 6330 return false; 6331 6332 SymbolAddressMap AddrMap; 6333 if (verbose) 6334 CreateSymbolAddressMap(O, &AddrMap); 6335 6336 std::vector<SectionRef> Sections; 6337 append_range(Sections, O->sections()); 6338 6339 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6340 6341 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 6342 p = S.getAddress() + i; 6343 r = get_pointer_32(p, offset, left, S, &info, true); 6344 if (r == nullptr) 6345 return true; 6346 memset(&module, '\0', sizeof(struct objc_module_t)); 6347 if (left < sizeof(struct objc_module_t)) { 6348 memcpy(&module, r, left); 6349 outs() << " (module extends past end of __module_info section)\n"; 6350 } else 6351 memcpy(&module, r, sizeof(struct objc_module_t)); 6352 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6353 swapStruct(module); 6354 6355 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 6356 outs() << " version " << module.version << "\n"; 6357 outs() << " size " << module.size << "\n"; 6358 outs() << " name "; 6359 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 6360 if (name != nullptr) 6361 outs() << format("%.*s", left, name); 6362 else 6363 outs() << format("0x%08" PRIx32, module.name) 6364 << "(not in an __OBJC section)"; 6365 outs() << "\n"; 6366 6367 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 6368 if (module.symtab == 0 || r == nullptr) { 6369 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 6370 << " (not in an __OBJC section)\n"; 6371 continue; 6372 } 6373 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 6374 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 6375 defs_left = 0; 6376 defs = nullptr; 6377 if (left < sizeof(struct objc_symtab_t)) { 6378 memcpy(&symtab, r, left); 6379 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 6380 } else { 6381 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 6382 if (left > sizeof(struct objc_symtab_t)) { 6383 defs_left = left - sizeof(struct objc_symtab_t); 6384 defs = r + sizeof(struct objc_symtab_t); 6385 } 6386 } 6387 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6388 swapStruct(symtab); 6389 6390 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 6391 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 6392 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 6393 if (r == nullptr) 6394 outs() << " (not in an __OBJC section)"; 6395 outs() << "\n"; 6396 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 6397 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 6398 if (symtab.cls_def_cnt > 0) 6399 outs() << "\tClass Definitions\n"; 6400 for (j = 0; j < symtab.cls_def_cnt; j++) { 6401 if ((j + 1) * sizeof(uint32_t) > defs_left) { 6402 outs() << "\t(remaining class defs entries entends past the end of the " 6403 << "section)\n"; 6404 break; 6405 } 6406 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 6407 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6408 sys::swapByteOrder(def); 6409 6410 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6411 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 6412 if (r != nullptr) { 6413 if (left > sizeof(struct objc_class_t)) { 6414 outs() << "\n"; 6415 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6416 } else { 6417 outs() << " (entends past the end of the section)\n"; 6418 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6419 memcpy(&objc_class, r, left); 6420 } 6421 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6422 swapStruct(objc_class); 6423 print_objc_class_t(&objc_class, &info); 6424 } else { 6425 outs() << "(not in an __OBJC section)\n"; 6426 } 6427 6428 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 6429 outs() << "\tMeta Class"; 6430 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 6431 if (r != nullptr) { 6432 if (left > sizeof(struct objc_class_t)) { 6433 outs() << "\n"; 6434 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6435 } else { 6436 outs() << " (entends past the end of the section)\n"; 6437 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6438 memcpy(&objc_class, r, left); 6439 } 6440 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6441 swapStruct(objc_class); 6442 print_objc_class_t(&objc_class, &info); 6443 } else { 6444 outs() << "(not in an __OBJC section)\n"; 6445 } 6446 } 6447 } 6448 if (symtab.cat_def_cnt > 0) 6449 outs() << "\tCategory Definitions\n"; 6450 for (j = 0; j < symtab.cat_def_cnt; j++) { 6451 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 6452 outs() << "\t(remaining category defs entries entends past the end of " 6453 << "the section)\n"; 6454 break; 6455 } 6456 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6457 sizeof(uint32_t)); 6458 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6459 sys::swapByteOrder(def); 6460 6461 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6462 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6463 << format("0x%08" PRIx32, def); 6464 if (r != nullptr) { 6465 if (left > sizeof(struct objc_category_t)) { 6466 outs() << "\n"; 6467 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6468 } else { 6469 outs() << " (entends past the end of the section)\n"; 6470 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6471 memcpy(&objc_category, r, left); 6472 } 6473 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6474 swapStruct(objc_category); 6475 print_objc_objc_category_t(&objc_category, &info); 6476 } else { 6477 outs() << "(not in an __OBJC section)\n"; 6478 } 6479 } 6480 } 6481 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6482 if (II != SectionRef()) 6483 print_image_info(II, &info); 6484 6485 return true; 6486 } 6487 6488 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6489 uint32_t size, uint32_t addr) { 6490 SymbolAddressMap AddrMap; 6491 CreateSymbolAddressMap(O, &AddrMap); 6492 6493 std::vector<SectionRef> Sections; 6494 append_range(Sections, O->sections()); 6495 6496 struct DisassembleInfo info(O, &AddrMap, &Sections, true); 6497 6498 const char *p; 6499 struct objc_protocol_t protocol; 6500 uint32_t left, paddr; 6501 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6502 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6503 left = size - (p - sect); 6504 if (left < sizeof(struct objc_protocol_t)) { 6505 outs() << "Protocol extends past end of __protocol section\n"; 6506 memcpy(&protocol, p, left); 6507 } else 6508 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6509 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6510 swapStruct(protocol); 6511 paddr = addr + (p - sect); 6512 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6513 if (print_protocol(paddr, 0, &info)) 6514 outs() << "(not in an __OBJC section)\n"; 6515 } 6516 } 6517 6518 #ifdef HAVE_LIBXAR 6519 static inline void swapStruct(struct xar_header &xar) { 6520 sys::swapByteOrder(xar.magic); 6521 sys::swapByteOrder(xar.size); 6522 sys::swapByteOrder(xar.version); 6523 sys::swapByteOrder(xar.toc_length_compressed); 6524 sys::swapByteOrder(xar.toc_length_uncompressed); 6525 sys::swapByteOrder(xar.cksum_alg); 6526 } 6527 6528 static void PrintModeVerbose(uint32_t mode) { 6529 switch(mode & S_IFMT){ 6530 case S_IFDIR: 6531 outs() << "d"; 6532 break; 6533 case S_IFCHR: 6534 outs() << "c"; 6535 break; 6536 case S_IFBLK: 6537 outs() << "b"; 6538 break; 6539 case S_IFREG: 6540 outs() << "-"; 6541 break; 6542 case S_IFLNK: 6543 outs() << "l"; 6544 break; 6545 case S_IFSOCK: 6546 outs() << "s"; 6547 break; 6548 default: 6549 outs() << "?"; 6550 break; 6551 } 6552 6553 /* owner permissions */ 6554 if(mode & S_IREAD) 6555 outs() << "r"; 6556 else 6557 outs() << "-"; 6558 if(mode & S_IWRITE) 6559 outs() << "w"; 6560 else 6561 outs() << "-"; 6562 if(mode & S_ISUID) 6563 outs() << "s"; 6564 else if(mode & S_IEXEC) 6565 outs() << "x"; 6566 else 6567 outs() << "-"; 6568 6569 /* group permissions */ 6570 if(mode & (S_IREAD >> 3)) 6571 outs() << "r"; 6572 else 6573 outs() << "-"; 6574 if(mode & (S_IWRITE >> 3)) 6575 outs() << "w"; 6576 else 6577 outs() << "-"; 6578 if(mode & S_ISGID) 6579 outs() << "s"; 6580 else if(mode & (S_IEXEC >> 3)) 6581 outs() << "x"; 6582 else 6583 outs() << "-"; 6584 6585 /* other permissions */ 6586 if(mode & (S_IREAD >> 6)) 6587 outs() << "r"; 6588 else 6589 outs() << "-"; 6590 if(mode & (S_IWRITE >> 6)) 6591 outs() << "w"; 6592 else 6593 outs() << "-"; 6594 if(mode & S_ISVTX) 6595 outs() << "t"; 6596 else if(mode & (S_IEXEC >> 6)) 6597 outs() << "x"; 6598 else 6599 outs() << "-"; 6600 } 6601 6602 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { 6603 xar_file_t xf; 6604 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; 6605 char *endp; 6606 uint32_t mode_value; 6607 6608 ScopedXarIter xi; 6609 if (!xi) { 6610 WithColor::error(errs(), "llvm-objdump") 6611 << "can't obtain an xar iterator for xar archive " << XarFilename 6612 << "\n"; 6613 return; 6614 } 6615 6616 // Go through the xar's files. 6617 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { 6618 ScopedXarIter xp; 6619 if(!xp){ 6620 WithColor::error(errs(), "llvm-objdump") 6621 << "can't obtain an xar iterator for xar archive " << XarFilename 6622 << "\n"; 6623 return; 6624 } 6625 type = nullptr; 6626 mode = nullptr; 6627 user = nullptr; 6628 group = nullptr; 6629 size = nullptr; 6630 mtime = nullptr; 6631 name = nullptr; 6632 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6633 const char *val = nullptr; 6634 xar_prop_get(xf, key, &val); 6635 #if 0 // Useful for debugging. 6636 outs() << "key: " << key << " value: " << val << "\n"; 6637 #endif 6638 if(strcmp(key, "type") == 0) 6639 type = val; 6640 if(strcmp(key, "mode") == 0) 6641 mode = val; 6642 if(strcmp(key, "user") == 0) 6643 user = val; 6644 if(strcmp(key, "group") == 0) 6645 group = val; 6646 if(strcmp(key, "data/size") == 0) 6647 size = val; 6648 if(strcmp(key, "mtime") == 0) 6649 mtime = val; 6650 if(strcmp(key, "name") == 0) 6651 name = val; 6652 } 6653 if(mode != nullptr){ 6654 mode_value = strtoul(mode, &endp, 8); 6655 if(*endp != '\0') 6656 outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; 6657 if(strcmp(type, "file") == 0) 6658 mode_value |= S_IFREG; 6659 PrintModeVerbose(mode_value); 6660 outs() << " "; 6661 } 6662 if(user != nullptr) 6663 outs() << format("%10s/", user); 6664 if(group != nullptr) 6665 outs() << format("%-10s ", group); 6666 if(size != nullptr) 6667 outs() << format("%7s ", size); 6668 if(mtime != nullptr){ 6669 for(m = mtime; *m != 'T' && *m != '\0'; m++) 6670 outs() << *m; 6671 if(*m == 'T') 6672 m++; 6673 outs() << " "; 6674 for( ; *m != 'Z' && *m != '\0'; m++) 6675 outs() << *m; 6676 outs() << " "; 6677 } 6678 if(name != nullptr) 6679 outs() << name; 6680 outs() << "\n"; 6681 } 6682 } 6683 6684 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 6685 uint32_t size, bool verbose, 6686 bool PrintXarHeader, bool PrintXarFileHeaders, 6687 std::string XarMemberName) { 6688 if(size < sizeof(struct xar_header)) { 6689 outs() << "size of (__LLVM,__bundle) section too small (smaller than size " 6690 "of struct xar_header)\n"; 6691 return; 6692 } 6693 struct xar_header XarHeader; 6694 memcpy(&XarHeader, sect, sizeof(struct xar_header)); 6695 if (sys::IsLittleEndianHost) 6696 swapStruct(XarHeader); 6697 if (PrintXarHeader) { 6698 if (!XarMemberName.empty()) 6699 outs() << "In xar member " << XarMemberName << ": "; 6700 else 6701 outs() << "For (__LLVM,__bundle) section: "; 6702 outs() << "xar header\n"; 6703 if (XarHeader.magic == XAR_HEADER_MAGIC) 6704 outs() << " magic XAR_HEADER_MAGIC\n"; 6705 else 6706 outs() << " magic " 6707 << format_hex(XarHeader.magic, 10, true) 6708 << " (not XAR_HEADER_MAGIC)\n"; 6709 outs() << " size " << XarHeader.size << "\n"; 6710 outs() << " version " << XarHeader.version << "\n"; 6711 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed 6712 << "\n"; 6713 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed 6714 << "\n"; 6715 outs() << " cksum_alg "; 6716 switch (XarHeader.cksum_alg) { 6717 case XAR_CKSUM_NONE: 6718 outs() << "XAR_CKSUM_NONE\n"; 6719 break; 6720 case XAR_CKSUM_SHA1: 6721 outs() << "XAR_CKSUM_SHA1\n"; 6722 break; 6723 case XAR_CKSUM_MD5: 6724 outs() << "XAR_CKSUM_MD5\n"; 6725 break; 6726 #ifdef XAR_CKSUM_SHA256 6727 case XAR_CKSUM_SHA256: 6728 outs() << "XAR_CKSUM_SHA256\n"; 6729 break; 6730 #endif 6731 #ifdef XAR_CKSUM_SHA512 6732 case XAR_CKSUM_SHA512: 6733 outs() << "XAR_CKSUM_SHA512\n"; 6734 break; 6735 #endif 6736 default: 6737 outs() << XarHeader.cksum_alg << "\n"; 6738 } 6739 } 6740 6741 SmallString<128> XarFilename; 6742 int FD; 6743 std::error_code XarEC = 6744 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); 6745 if (XarEC) { 6746 WithColor::error(errs(), "llvm-objdump") << XarEC.message() << "\n"; 6747 return; 6748 } 6749 ToolOutputFile XarFile(XarFilename, FD); 6750 raw_fd_ostream &XarOut = XarFile.os(); 6751 StringRef XarContents(sect, size); 6752 XarOut << XarContents; 6753 XarOut.close(); 6754 if (XarOut.has_error()) 6755 return; 6756 6757 ScopedXarFile xar(XarFilename.c_str(), READ); 6758 if (!xar) { 6759 WithColor::error(errs(), "llvm-objdump") 6760 << "can't create temporary xar archive " << XarFilename << "\n"; 6761 return; 6762 } 6763 6764 SmallString<128> TocFilename; 6765 std::error_code TocEC = 6766 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); 6767 if (TocEC) { 6768 WithColor::error(errs(), "llvm-objdump") << TocEC.message() << "\n"; 6769 return; 6770 } 6771 xar_serialize(xar, TocFilename.c_str()); 6772 6773 if (PrintXarFileHeaders) { 6774 if (!XarMemberName.empty()) 6775 outs() << "In xar member " << XarMemberName << ": "; 6776 else 6777 outs() << "For (__LLVM,__bundle) section: "; 6778 outs() << "xar archive files:\n"; 6779 PrintXarFilesSummary(XarFilename.c_str(), xar); 6780 } 6781 6782 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 6783 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); 6784 if (std::error_code EC = FileOrErr.getError()) { 6785 WithColor::error(errs(), "llvm-objdump") << EC.message() << "\n"; 6786 return; 6787 } 6788 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 6789 6790 if (!XarMemberName.empty()) 6791 outs() << "In xar member " << XarMemberName << ": "; 6792 else 6793 outs() << "For (__LLVM,__bundle) section: "; 6794 outs() << "xar table of contents:\n"; 6795 outs() << Buffer->getBuffer() << "\n"; 6796 6797 // TODO: Go through the xar's files. 6798 ScopedXarIter xi; 6799 if(!xi){ 6800 WithColor::error(errs(), "llvm-objdump") 6801 << "can't obtain an xar iterator for xar archive " 6802 << XarFilename.c_str() << "\n"; 6803 return; 6804 } 6805 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ 6806 const char *key; 6807 const char *member_name, *member_type, *member_size_string; 6808 size_t member_size; 6809 6810 ScopedXarIter xp; 6811 if(!xp){ 6812 WithColor::error(errs(), "llvm-objdump") 6813 << "can't obtain an xar iterator for xar archive " 6814 << XarFilename.c_str() << "\n"; 6815 return; 6816 } 6817 member_name = NULL; 6818 member_type = NULL; 6819 member_size_string = NULL; 6820 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6821 const char *val = nullptr; 6822 xar_prop_get(xf, key, &val); 6823 #if 0 // Useful for debugging. 6824 outs() << "key: " << key << " value: " << val << "\n"; 6825 #endif 6826 if (strcmp(key, "name") == 0) 6827 member_name = val; 6828 if (strcmp(key, "type") == 0) 6829 member_type = val; 6830 if (strcmp(key, "data/size") == 0) 6831 member_size_string = val; 6832 } 6833 /* 6834 * If we find a file with a name, date/size and type properties 6835 * and with the type being "file" see if that is a xar file. 6836 */ 6837 if (member_name != NULL && member_type != NULL && 6838 strcmp(member_type, "file") == 0 && 6839 member_size_string != NULL){ 6840 // Extract the file into a buffer. 6841 char *endptr; 6842 member_size = strtoul(member_size_string, &endptr, 10); 6843 if (*endptr == '\0' && member_size != 0) { 6844 char *buffer; 6845 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { 6846 #if 0 // Useful for debugging. 6847 outs() << "xar member: " << member_name << " extracted\n"; 6848 #endif 6849 // Set the XarMemberName we want to see printed in the header. 6850 std::string OldXarMemberName; 6851 // If XarMemberName is already set this is nested. So 6852 // save the old name and create the nested name. 6853 if (!XarMemberName.empty()) { 6854 OldXarMemberName = XarMemberName; 6855 XarMemberName = 6856 (Twine("[") + XarMemberName + "]" + member_name).str(); 6857 } else { 6858 OldXarMemberName = ""; 6859 XarMemberName = member_name; 6860 } 6861 // See if this is could be a xar file (nested). 6862 if (member_size >= sizeof(struct xar_header)) { 6863 #if 0 // Useful for debugging. 6864 outs() << "could be a xar file: " << member_name << "\n"; 6865 #endif 6866 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); 6867 if (sys::IsLittleEndianHost) 6868 swapStruct(XarHeader); 6869 if (XarHeader.magic == XAR_HEADER_MAGIC) 6870 DumpBitcodeSection(O, buffer, member_size, verbose, 6871 PrintXarHeader, PrintXarFileHeaders, 6872 XarMemberName); 6873 } 6874 XarMemberName = OldXarMemberName; 6875 delete buffer; 6876 } 6877 } 6878 } 6879 } 6880 } 6881 #endif // defined(HAVE_LIBXAR) 6882 6883 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6884 if (O->is64Bit()) 6885 printObjc2_64bit_MetaData(O, verbose); 6886 else { 6887 MachO::mach_header H; 6888 H = O->getHeader(); 6889 if (H.cputype == MachO::CPU_TYPE_ARM) 6890 printObjc2_32bit_MetaData(O, verbose); 6891 else { 6892 // This is the 32-bit non-arm cputype case. Which is normally 6893 // the first Objective-C ABI. But it may be the case of a 6894 // binary for the iOS simulator which is the second Objective-C 6895 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6896 // and return false. 6897 if (!printObjc1_32bit_MetaData(O, verbose)) 6898 printObjc2_32bit_MetaData(O, verbose); 6899 } 6900 } 6901 } 6902 6903 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6904 // for the address passed in as ReferenceValue for printing as a comment with 6905 // the instruction and also returns the corresponding type of that item 6906 // indirectly through ReferenceType. 6907 // 6908 // If ReferenceValue is an address of literal cstring then a pointer to the 6909 // cstring is returned and ReferenceType is set to 6910 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6911 // 6912 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6913 // Class ref that name is returned and the ReferenceType is set accordingly. 6914 // 6915 // Lastly, literals which are Symbol address in a literal pool are looked for 6916 // and if found the symbol name is returned and ReferenceType is set to 6917 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6918 // 6919 // If there is no item in the Mach-O file for the address passed in as 6920 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6921 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6922 uint64_t ReferencePC, 6923 uint64_t *ReferenceType, 6924 struct DisassembleInfo *info) { 6925 // First see if there is an external relocation entry at the ReferencePC. 6926 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6927 uint64_t sect_addr = info->S.getAddress(); 6928 uint64_t sect_offset = ReferencePC - sect_addr; 6929 bool reloc_found = false; 6930 DataRefImpl Rel; 6931 MachO::any_relocation_info RE; 6932 bool isExtern = false; 6933 SymbolRef Symbol; 6934 for (const RelocationRef &Reloc : info->S.relocations()) { 6935 uint64_t RelocOffset = Reloc.getOffset(); 6936 if (RelocOffset == sect_offset) { 6937 Rel = Reloc.getRawDataRefImpl(); 6938 RE = info->O->getRelocation(Rel); 6939 if (info->O->isRelocationScattered(RE)) 6940 continue; 6941 isExtern = info->O->getPlainRelocationExternal(RE); 6942 if (isExtern) { 6943 symbol_iterator RelocSym = Reloc.getSymbol(); 6944 Symbol = *RelocSym; 6945 } 6946 reloc_found = true; 6947 break; 6948 } 6949 } 6950 // If there is an external relocation entry for a symbol in a section 6951 // then used that symbol's value for the value of the reference. 6952 if (reloc_found && isExtern) { 6953 if (info->O->getAnyRelocationPCRel(RE)) { 6954 unsigned Type = info->O->getAnyRelocationType(RE); 6955 if (Type == MachO::X86_64_RELOC_SIGNED) { 6956 ReferenceValue = cantFail(Symbol.getValue()); 6957 } 6958 } 6959 } 6960 } 6961 6962 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6963 // Message refs and Class refs. 6964 bool classref, selref, msgref, cfstring; 6965 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6966 selref, msgref, cfstring); 6967 if (classref && pointer_value == 0) { 6968 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6969 // And the pointer_value in that section is typically zero as it will be 6970 // set by dyld as part of the "bind information". 6971 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6972 if (name != nullptr) { 6973 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6974 const char *class_name = strrchr(name, '$'); 6975 if (class_name != nullptr && class_name[1] == '_' && 6976 class_name[2] != '\0') { 6977 info->class_name = class_name + 2; 6978 return name; 6979 } 6980 } 6981 } 6982 6983 if (classref) { 6984 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6985 const char *name = 6986 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6987 if (name != nullptr) 6988 info->class_name = name; 6989 else 6990 name = "bad class ref"; 6991 return name; 6992 } 6993 6994 if (cfstring) { 6995 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6996 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6997 return name; 6998 } 6999 7000 if (selref && pointer_value == 0) 7001 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 7002 7003 if (pointer_value != 0) 7004 ReferenceValue = pointer_value; 7005 7006 const char *name = GuessCstringPointer(ReferenceValue, info); 7007 if (name) { 7008 if (pointer_value != 0 && selref) { 7009 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 7010 info->selector_name = name; 7011 } else if (pointer_value != 0 && msgref) { 7012 info->class_name = nullptr; 7013 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 7014 info->selector_name = name; 7015 } else 7016 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 7017 return name; 7018 } 7019 7020 // Lastly look for an indirect symbol with this ReferenceValue which is in 7021 // a literal pool. If found return that symbol name. 7022 name = GuessIndirectSymbol(ReferenceValue, info); 7023 if (name) { 7024 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 7025 return name; 7026 } 7027 7028 return nullptr; 7029 } 7030 7031 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 7032 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 7033 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 7034 // is created and returns the symbol name that matches the ReferenceValue or 7035 // nullptr if none. The ReferenceType is passed in for the IN type of 7036 // reference the instruction is making from the values in defined in the header 7037 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 7038 // Out type and the ReferenceName will also be set which is added as a comment 7039 // to the disassembled instruction. 7040 // 7041 // If the symbol name is a C++ mangled name then the demangled name is 7042 // returned through ReferenceName and ReferenceType is set to 7043 // LLVMDisassembler_ReferenceType_DeMangled_Name . 7044 // 7045 // When this is called to get a symbol name for a branch target then the 7046 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 7047 // SymbolValue will be looked for in the indirect symbol table to determine if 7048 // it is an address for a symbol stub. If so then the symbol name for that 7049 // stub is returned indirectly through ReferenceName and then ReferenceType is 7050 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 7051 // 7052 // When this is called with an value loaded via a PC relative load then 7053 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 7054 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 7055 // or an Objective-C meta data reference. If so the output ReferenceType is 7056 // set to correspond to that as well as setting the ReferenceName. 7057 static const char *SymbolizerSymbolLookUp(void *DisInfo, 7058 uint64_t ReferenceValue, 7059 uint64_t *ReferenceType, 7060 uint64_t ReferencePC, 7061 const char **ReferenceName) { 7062 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 7063 // If no verbose symbolic information is wanted then just return nullptr. 7064 if (!info->verbose) { 7065 *ReferenceName = nullptr; 7066 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7067 return nullptr; 7068 } 7069 7070 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 7071 7072 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 7073 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 7074 if (*ReferenceName != nullptr) { 7075 method_reference(info, ReferenceType, ReferenceName); 7076 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 7077 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 7078 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 7079 if (info->demangled_name != nullptr) 7080 free(info->demangled_name); 7081 int status; 7082 info->demangled_name = 7083 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 7084 if (info->demangled_name != nullptr) { 7085 *ReferenceName = info->demangled_name; 7086 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 7087 } else 7088 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7089 } else 7090 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7091 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 7092 *ReferenceName = 7093 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7094 if (*ReferenceName) 7095 method_reference(info, ReferenceType, ReferenceName); 7096 else 7097 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7098 // If this is arm64 and the reference is an adrp instruction save the 7099 // instruction, passed in ReferenceValue and the address of the instruction 7100 // for use later if we see and add immediate instruction. 7101 } else if (info->O->getArch() == Triple::aarch64 && 7102 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 7103 info->adrp_inst = ReferenceValue; 7104 info->adrp_addr = ReferencePC; 7105 SymbolName = nullptr; 7106 *ReferenceName = nullptr; 7107 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7108 // If this is arm64 and reference is an add immediate instruction and we 7109 // have 7110 // seen an adrp instruction just before it and the adrp's Xd register 7111 // matches 7112 // this add's Xn register reconstruct the value being referenced and look to 7113 // see if it is a literal pointer. Note the add immediate instruction is 7114 // passed in ReferenceValue. 7115 } else if (info->O->getArch() == Triple::aarch64 && 7116 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 7117 ReferencePC - 4 == info->adrp_addr && 7118 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7119 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7120 uint32_t addxri_inst; 7121 uint64_t adrp_imm, addxri_imm; 7122 7123 adrp_imm = 7124 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7125 if (info->adrp_inst & 0x0200000) 7126 adrp_imm |= 0xfffffffffc000000LL; 7127 7128 addxri_inst = ReferenceValue; 7129 addxri_imm = (addxri_inst >> 10) & 0xfff; 7130 if (((addxri_inst >> 22) & 0x3) == 1) 7131 addxri_imm <<= 12; 7132 7133 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7134 (adrp_imm << 12) + addxri_imm; 7135 7136 *ReferenceName = 7137 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7138 if (*ReferenceName == nullptr) 7139 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7140 // If this is arm64 and the reference is a load register instruction and we 7141 // have seen an adrp instruction just before it and the adrp's Xd register 7142 // matches this add's Xn register reconstruct the value being referenced and 7143 // look to see if it is a literal pointer. Note the load register 7144 // instruction is passed in ReferenceValue. 7145 } else if (info->O->getArch() == Triple::aarch64 && 7146 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 7147 ReferencePC - 4 == info->adrp_addr && 7148 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7149 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7150 uint32_t ldrxui_inst; 7151 uint64_t adrp_imm, ldrxui_imm; 7152 7153 adrp_imm = 7154 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7155 if (info->adrp_inst & 0x0200000) 7156 adrp_imm |= 0xfffffffffc000000LL; 7157 7158 ldrxui_inst = ReferenceValue; 7159 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 7160 7161 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7162 (adrp_imm << 12) + (ldrxui_imm << 3); 7163 7164 *ReferenceName = 7165 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7166 if (*ReferenceName == nullptr) 7167 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7168 } 7169 // If this arm64 and is an load register (PC-relative) instruction the 7170 // ReferenceValue is the PC plus the immediate value. 7171 else if (info->O->getArch() == Triple::aarch64 && 7172 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 7173 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 7174 *ReferenceName = 7175 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7176 if (*ReferenceName == nullptr) 7177 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7178 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 7179 if (info->demangled_name != nullptr) 7180 free(info->demangled_name); 7181 int status; 7182 info->demangled_name = 7183 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 7184 if (info->demangled_name != nullptr) { 7185 *ReferenceName = info->demangled_name; 7186 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 7187 } 7188 } 7189 else { 7190 *ReferenceName = nullptr; 7191 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7192 } 7193 7194 return SymbolName; 7195 } 7196 7197 /// Emits the comments that are stored in the CommentStream. 7198 /// Each comment in the CommentStream must end with a newline. 7199 static void emitComments(raw_svector_ostream &CommentStream, 7200 SmallString<128> &CommentsToEmit, 7201 formatted_raw_ostream &FormattedOS, 7202 const MCAsmInfo &MAI) { 7203 // Flush the stream before taking its content. 7204 StringRef Comments = CommentsToEmit.str(); 7205 // Get the default information for printing a comment. 7206 StringRef CommentBegin = MAI.getCommentString(); 7207 unsigned CommentColumn = MAI.getCommentColumn(); 7208 ListSeparator LS("\n"); 7209 while (!Comments.empty()) { 7210 FormattedOS << LS; 7211 // Emit a line of comments. 7212 FormattedOS.PadToColumn(CommentColumn); 7213 size_t Position = Comments.find('\n'); 7214 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 7215 // Move after the newline character. 7216 Comments = Comments.substr(Position + 1); 7217 } 7218 FormattedOS.flush(); 7219 7220 // Tell the comment stream that the vector changed underneath it. 7221 CommentsToEmit.clear(); 7222 } 7223 7224 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 7225 StringRef DisSegName, StringRef DisSectName) { 7226 const char *McpuDefault = nullptr; 7227 const Target *ThumbTarget = nullptr; 7228 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 7229 if (!TheTarget) { 7230 // GetTarget prints out stuff. 7231 return; 7232 } 7233 std::string MachOMCPU; 7234 if (MCPU.empty() && McpuDefault) 7235 MachOMCPU = McpuDefault; 7236 else 7237 MachOMCPU = MCPU; 7238 7239 #define CHECK_TARGET_INFO_CREATION(NAME) \ 7240 do { \ 7241 if (!NAME) { \ 7242 WithColor::error(errs(), "llvm-objdump") \ 7243 << "couldn't initialize disassembler for target " << TripleName \ 7244 << '\n'; \ 7245 return; \ 7246 } \ 7247 } while (false) 7248 #define CHECK_THUMB_TARGET_INFO_CREATION(NAME) \ 7249 do { \ 7250 if (!NAME) { \ 7251 WithColor::error(errs(), "llvm-objdump") \ 7252 << "couldn't initialize disassembler for target " << ThumbTripleName \ 7253 << '\n'; \ 7254 return; \ 7255 } \ 7256 } while (false) 7257 7258 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 7259 CHECK_TARGET_INFO_CREATION(InstrInfo); 7260 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 7261 if (ThumbTarget) { 7262 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 7263 CHECK_THUMB_TARGET_INFO_CREATION(ThumbInstrInfo); 7264 } 7265 7266 // Package up features to be passed to target/subtarget 7267 std::string FeaturesStr; 7268 if (!MAttrs.empty()) { 7269 SubtargetFeatures Features; 7270 for (unsigned i = 0; i != MAttrs.size(); ++i) 7271 Features.AddFeature(MAttrs[i]); 7272 FeaturesStr = Features.getString(); 7273 } 7274 7275 MCTargetOptions MCOptions; 7276 // Set up disassembler. 7277 std::unique_ptr<const MCRegisterInfo> MRI( 7278 TheTarget->createMCRegInfo(TripleName)); 7279 CHECK_TARGET_INFO_CREATION(MRI); 7280 std::unique_ptr<const MCAsmInfo> AsmInfo( 7281 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 7282 CHECK_TARGET_INFO_CREATION(AsmInfo); 7283 std::unique_ptr<const MCSubtargetInfo> STI( 7284 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 7285 CHECK_TARGET_INFO_CREATION(STI); 7286 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 7287 std::unique_ptr<MCDisassembler> DisAsm( 7288 TheTarget->createMCDisassembler(*STI, Ctx)); 7289 CHECK_TARGET_INFO_CREATION(DisAsm); 7290 std::unique_ptr<MCSymbolizer> Symbolizer; 7291 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false); 7292 std::unique_ptr<MCRelocationInfo> RelInfo( 7293 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 7294 if (RelInfo) { 7295 Symbolizer.reset(TheTarget->createMCSymbolizer( 7296 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7297 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 7298 DisAsm->setSymbolizer(std::move(Symbolizer)); 7299 } 7300 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 7301 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 7302 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 7303 CHECK_TARGET_INFO_CREATION(IP); 7304 // Set the display preference for hex vs. decimal immediates. 7305 IP->setPrintImmHex(PrintImmHex); 7306 // Comment stream and backing vector. 7307 SmallString<128> CommentsToEmit; 7308 raw_svector_ostream CommentStream(CommentsToEmit); 7309 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 7310 // if it is done then arm64 comments for string literals don't get printed 7311 // and some constant get printed instead and not setting it causes intel 7312 // (32-bit and 64-bit) comments printed with different spacing before the 7313 // comment causing different diffs with the 'C' disassembler library API. 7314 // IP->setCommentStream(CommentStream); 7315 7316 // Set up separate thumb disassembler if needed. 7317 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 7318 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 7319 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 7320 std::unique_ptr<MCDisassembler> ThumbDisAsm; 7321 std::unique_ptr<MCInstPrinter> ThumbIP; 7322 std::unique_ptr<MCContext> ThumbCtx; 7323 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 7324 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false); 7325 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 7326 if (ThumbTarget) { 7327 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 7328 CHECK_THUMB_TARGET_INFO_CREATION(ThumbMRI); 7329 ThumbAsmInfo.reset( 7330 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions)); 7331 CHECK_THUMB_TARGET_INFO_CREATION(ThumbAsmInfo); 7332 ThumbSTI.reset( 7333 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 7334 FeaturesStr)); 7335 CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI); 7336 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 7337 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 7338 CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm); 7339 MCContext *PtrThumbCtx = ThumbCtx.get(); 7340 ThumbRelInfo.reset( 7341 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 7342 if (ThumbRelInfo) { 7343 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 7344 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7345 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 7346 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 7347 } 7348 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 7349 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 7350 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 7351 *ThumbInstrInfo, *ThumbMRI)); 7352 CHECK_THUMB_TARGET_INFO_CREATION(ThumbIP); 7353 // Set the display preference for hex vs. decimal immediates. 7354 ThumbIP->setPrintImmHex(PrintImmHex); 7355 } 7356 7357 #undef CHECK_TARGET_INFO_CREATION 7358 #undef CHECK_THUMB_TARGET_INFO_CREATION 7359 7360 MachO::mach_header Header = MachOOF->getHeader(); 7361 7362 // FIXME: Using the -cfg command line option, this code used to be able to 7363 // annotate relocations with the referenced symbol's name, and if this was 7364 // inside a __[cf]string section, the data it points to. This is now replaced 7365 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 7366 std::vector<SectionRef> Sections; 7367 std::vector<SymbolRef> Symbols; 7368 SmallVector<uint64_t, 8> FoundFns; 7369 uint64_t BaseSegmentAddress = 0; 7370 7371 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 7372 BaseSegmentAddress); 7373 7374 // Sort the symbols by address, just in case they didn't come in that way. 7375 llvm::sort(Symbols, SymbolSorter()); 7376 7377 // Build a data in code table that is sorted on by the address of each entry. 7378 uint64_t BaseAddress = 0; 7379 if (Header.filetype == MachO::MH_OBJECT) 7380 BaseAddress = Sections[0].getAddress(); 7381 else 7382 BaseAddress = BaseSegmentAddress; 7383 DiceTable Dices; 7384 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 7385 DI != DE; ++DI) { 7386 uint32_t Offset; 7387 DI->getOffset(Offset); 7388 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 7389 } 7390 array_pod_sort(Dices.begin(), Dices.end()); 7391 7392 // Try to find debug info and set up the DIContext for it. 7393 std::unique_ptr<DIContext> diContext; 7394 std::unique_ptr<Binary> DSYMBinary; 7395 std::unique_ptr<MemoryBuffer> DSYMBuf; 7396 if (UseDbg) { 7397 ObjectFile *DbgObj = MachOOF; 7398 7399 // A separate DSym file path was specified, parse it as a macho file, 7400 // get the sections and supply it to the section name parsing machinery. 7401 if (!DSYMFile.empty()) { 7402 std::string DSYMPath(DSYMFile); 7403 7404 // If DSYMPath is a .dSYM directory, append the Mach-O file. 7405 if (llvm::sys::fs::is_directory(DSYMPath) && 7406 llvm::sys::path::extension(DSYMPath) == ".dSYM") { 7407 SmallString<128> ShortName(llvm::sys::path::filename(DSYMPath)); 7408 llvm::sys::path::replace_extension(ShortName, ""); 7409 SmallString<1024> FullPath(DSYMPath); 7410 llvm::sys::path::append(FullPath, "Contents", "Resources", "DWARF", 7411 ShortName); 7412 DSYMPath = std::string(FullPath.str()); 7413 } 7414 7415 // Load the file. 7416 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 7417 MemoryBuffer::getFileOrSTDIN(DSYMPath); 7418 if (std::error_code EC = BufOrErr.getError()) { 7419 reportError(errorCodeToError(EC), DSYMPath); 7420 return; 7421 } 7422 7423 // We need to keep the file alive, because we're replacing DbgObj with it. 7424 DSYMBuf = std::move(BufOrErr.get()); 7425 7426 Expected<std::unique_ptr<Binary>> BinaryOrErr = 7427 createBinary(DSYMBuf.get()->getMemBufferRef()); 7428 if (!BinaryOrErr) { 7429 reportError(BinaryOrErr.takeError(), DSYMPath); 7430 return; 7431 } 7432 7433 // We need to keep the Binary alive with the buffer 7434 DSYMBinary = std::move(BinaryOrErr.get()); 7435 if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) { 7436 // this is a Mach-O object file, use it 7437 if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) { 7438 DbgObj = MachDSYM; 7439 } 7440 else { 7441 WithColor::error(errs(), "llvm-objdump") 7442 << DSYMPath << " is not a Mach-O file type.\n"; 7443 return; 7444 } 7445 } 7446 else if (auto UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())){ 7447 // this is a Universal Binary, find a Mach-O for this architecture 7448 uint32_t CPUType, CPUSubType; 7449 const char *ArchFlag; 7450 if (MachOOF->is64Bit()) { 7451 const MachO::mach_header_64 H_64 = MachOOF->getHeader64(); 7452 CPUType = H_64.cputype; 7453 CPUSubType = H_64.cpusubtype; 7454 } else { 7455 const MachO::mach_header H = MachOOF->getHeader(); 7456 CPUType = H.cputype; 7457 CPUSubType = H.cpusubtype; 7458 } 7459 Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr, 7460 &ArchFlag); 7461 Expected<std::unique_ptr<MachOObjectFile>> MachDSYM = 7462 UB->getMachOObjectForArch(ArchFlag); 7463 if (!MachDSYM) { 7464 reportError(MachDSYM.takeError(), DSYMPath); 7465 return; 7466 } 7467 7468 // We need to keep the Binary alive with the buffer 7469 DbgObj = &*MachDSYM.get(); 7470 DSYMBinary = std::move(*MachDSYM); 7471 } 7472 else { 7473 WithColor::error(errs(), "llvm-objdump") 7474 << DSYMPath << " is not a Mach-O or Universal file type.\n"; 7475 return; 7476 } 7477 } 7478 7479 // Setup the DIContext 7480 diContext = DWARFContext::create(*DbgObj); 7481 } 7482 7483 if (FilterSections.empty()) 7484 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 7485 7486 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 7487 Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName(); 7488 if (!SecNameOrErr) { 7489 consumeError(SecNameOrErr.takeError()); 7490 continue; 7491 } 7492 if (*SecNameOrErr != DisSectName) 7493 continue; 7494 7495 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 7496 7497 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 7498 if (SegmentName != DisSegName) 7499 continue; 7500 7501 StringRef BytesStr = 7502 unwrapOrError(Sections[SectIdx].getContents(), Filename); 7503 ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr); 7504 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7505 7506 bool symbolTableWorked = false; 7507 7508 // Create a map of symbol addresses to symbol names for use by 7509 // the SymbolizerSymbolLookUp() routine. 7510 SymbolAddressMap AddrMap; 7511 bool DisSymNameFound = false; 7512 for (const SymbolRef &Symbol : MachOOF->symbols()) { 7513 SymbolRef::Type ST = 7514 unwrapOrError(Symbol.getType(), MachOOF->getFileName()); 7515 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 7516 ST == SymbolRef::ST_Other) { 7517 uint64_t Address = cantFail(Symbol.getValue()); 7518 StringRef SymName = 7519 unwrapOrError(Symbol.getName(), MachOOF->getFileName()); 7520 AddrMap[Address] = SymName; 7521 if (!DisSymName.empty() && DisSymName == SymName) 7522 DisSymNameFound = true; 7523 } 7524 } 7525 if (!DisSymName.empty() && !DisSymNameFound) { 7526 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 7527 return; 7528 } 7529 // Set up the block of info used by the Symbolizer call backs. 7530 SymbolizerInfo.verbose = !NoSymbolicOperands; 7531 SymbolizerInfo.O = MachOOF; 7532 SymbolizerInfo.S = Sections[SectIdx]; 7533 SymbolizerInfo.AddrMap = &AddrMap; 7534 SymbolizerInfo.Sections = &Sections; 7535 // Same for the ThumbSymbolizer 7536 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands; 7537 ThumbSymbolizerInfo.O = MachOOF; 7538 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7539 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7540 ThumbSymbolizerInfo.Sections = &Sections; 7541 7542 unsigned int Arch = MachOOF->getArch(); 7543 7544 // Skip all symbols if this is a stubs file. 7545 if (Bytes.empty()) 7546 return; 7547 7548 // If the section has symbols but no symbol at the start of the section 7549 // these are used to make sure the bytes before the first symbol are 7550 // disassembled. 7551 bool FirstSymbol = true; 7552 bool FirstSymbolAtSectionStart = true; 7553 7554 // Disassemble symbol by symbol. 7555 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7556 StringRef SymName = 7557 unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName()); 7558 SymbolRef::Type ST = 7559 unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName()); 7560 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7561 continue; 7562 7563 // Make sure the symbol is defined in this section. 7564 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7565 if (!containsSym) { 7566 if (!DisSymName.empty() && DisSymName == SymName) { 7567 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7568 return; 7569 } 7570 continue; 7571 } 7572 // The __mh_execute_header is special and we need to deal with that fact 7573 // this symbol is before the start of the (__TEXT,__text) section and at the 7574 // address of the start of the __TEXT segment. This is because this symbol 7575 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7576 // start of the section in a standard MH_EXECUTE filetype. 7577 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7578 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7579 return; 7580 } 7581 // When this code is trying to disassemble a symbol at a time and in the 7582 // case there is only the __mh_execute_header symbol left as in a stripped 7583 // executable, we need to deal with this by ignoring this symbol so the 7584 // whole section is disassembled and this symbol is then not displayed. 7585 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7586 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7587 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7588 continue; 7589 7590 // If we are only disassembling one symbol see if this is that symbol. 7591 if (!DisSymName.empty() && DisSymName != SymName) 7592 continue; 7593 7594 // Start at the address of the symbol relative to the section's address. 7595 uint64_t SectSize = Sections[SectIdx].getSize(); 7596 uint64_t Start = cantFail(Symbols[SymIdx].getValue()); 7597 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7598 Start -= SectionAddress; 7599 7600 if (Start > SectSize) { 7601 outs() << "section data ends, " << SymName 7602 << " lies outside valid range\n"; 7603 return; 7604 } 7605 7606 // Stop disassembling either at the beginning of the next symbol or at 7607 // the end of the section. 7608 bool containsNextSym = false; 7609 uint64_t NextSym = 0; 7610 uint64_t NextSymIdx = SymIdx + 1; 7611 while (Symbols.size() > NextSymIdx) { 7612 SymbolRef::Type NextSymType = unwrapOrError( 7613 Symbols[NextSymIdx].getType(), MachOOF->getFileName()); 7614 if (NextSymType == SymbolRef::ST_Function) { 7615 containsNextSym = 7616 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7617 NextSym = cantFail(Symbols[NextSymIdx].getValue()); 7618 NextSym -= SectionAddress; 7619 break; 7620 } 7621 ++NextSymIdx; 7622 } 7623 7624 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7625 uint64_t Size; 7626 7627 symbolTableWorked = true; 7628 7629 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7630 uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb)); 7631 bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb; 7632 7633 // We only need the dedicated Thumb target if there's a real choice 7634 // (i.e. we're not targeting M-class) and the function is Thumb. 7635 bool UseThumbTarget = IsThumb && ThumbTarget; 7636 7637 // If we are not specifying a symbol to start disassembly with and this 7638 // is the first symbol in the section but not at the start of the section 7639 // then move the disassembly index to the start of the section and 7640 // don't print the symbol name just yet. This is so the bytes before the 7641 // first symbol are disassembled. 7642 uint64_t SymbolStart = Start; 7643 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7644 FirstSymbolAtSectionStart = false; 7645 Start = 0; 7646 } 7647 else 7648 outs() << SymName << ":\n"; 7649 7650 DILineInfo lastLine; 7651 for (uint64_t Index = Start; Index < End; Index += Size) { 7652 MCInst Inst; 7653 7654 // If this is the first symbol in the section and it was not at the 7655 // start of the section, see if we are at its Index now and if so print 7656 // the symbol name. 7657 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7658 outs() << SymName << ":\n"; 7659 7660 uint64_t PC = SectAddress + Index; 7661 if (!NoLeadingAddr) { 7662 if (FullLeadingAddr) { 7663 if (MachOOF->is64Bit()) 7664 outs() << format("%016" PRIx64, PC); 7665 else 7666 outs() << format("%08" PRIx64, PC); 7667 } else { 7668 outs() << format("%8" PRIx64 ":", PC); 7669 } 7670 } 7671 if (!NoShowRawInsn || Arch == Triple::arm) 7672 outs() << "\t"; 7673 7674 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size)) 7675 continue; 7676 7677 SmallVector<char, 64> AnnotationsBytes; 7678 raw_svector_ostream Annotations(AnnotationsBytes); 7679 7680 bool gotInst; 7681 if (UseThumbTarget) 7682 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7683 PC, Annotations); 7684 else 7685 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7686 Annotations); 7687 if (gotInst) { 7688 if (!NoShowRawInsn || Arch == Triple::arm) { 7689 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); 7690 } 7691 formatted_raw_ostream FormattedOS(outs()); 7692 StringRef AnnotationsStr = Annotations.str(); 7693 if (UseThumbTarget) 7694 ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI, 7695 FormattedOS); 7696 else 7697 IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS); 7698 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7699 7700 // Print debug info. 7701 if (diContext) { 7702 DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx}); 7703 // Print valid line info if it changed. 7704 if (dli != lastLine && dli.Line != 0) 7705 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7706 << dli.Column; 7707 lastLine = dli; 7708 } 7709 outs() << "\n"; 7710 } else { 7711 if (MachOOF->getArchTriple().isX86()) { 7712 outs() << format("\t.byte 0x%02x #bad opcode\n", 7713 *(Bytes.data() + Index) & 0xff); 7714 Size = 1; // skip exactly one illegible byte and move on. 7715 } else if (Arch == Triple::aarch64 || 7716 (Arch == Triple::arm && !IsThumb)) { 7717 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7718 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7719 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7720 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7721 outs() << format("\t.long\t0x%08x\n", opcode); 7722 Size = 4; 7723 } else if (Arch == Triple::arm) { 7724 assert(IsThumb && "ARM mode should have been dealt with above"); 7725 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7726 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7727 outs() << format("\t.short\t0x%04x\n", opcode); 7728 Size = 2; 7729 } else{ 7730 WithColor::warning(errs(), "llvm-objdump") 7731 << "invalid instruction encoding\n"; 7732 if (Size == 0) 7733 Size = 1; // skip illegible bytes 7734 } 7735 } 7736 } 7737 // Now that we are done disassembled the first symbol set the bool that 7738 // were doing this to false. 7739 FirstSymbol = false; 7740 } 7741 if (!symbolTableWorked) { 7742 // Reading the symbol table didn't work, disassemble the whole section. 7743 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7744 uint64_t SectSize = Sections[SectIdx].getSize(); 7745 uint64_t InstSize; 7746 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7747 MCInst Inst; 7748 7749 uint64_t PC = SectAddress + Index; 7750 7751 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize)) 7752 continue; 7753 7754 SmallVector<char, 64> AnnotationsBytes; 7755 raw_svector_ostream Annotations(AnnotationsBytes); 7756 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7757 Annotations)) { 7758 if (!NoLeadingAddr) { 7759 if (FullLeadingAddr) { 7760 if (MachOOF->is64Bit()) 7761 outs() << format("%016" PRIx64, PC); 7762 else 7763 outs() << format("%08" PRIx64, PC); 7764 } else { 7765 outs() << format("%8" PRIx64 ":", PC); 7766 } 7767 } 7768 if (!NoShowRawInsn || Arch == Triple::arm) { 7769 outs() << "\t"; 7770 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); 7771 } 7772 StringRef AnnotationsStr = Annotations.str(); 7773 IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs()); 7774 outs() << "\n"; 7775 } else { 7776 if (MachOOF->getArchTriple().isX86()) { 7777 outs() << format("\t.byte 0x%02x #bad opcode\n", 7778 *(Bytes.data() + Index) & 0xff); 7779 InstSize = 1; // skip exactly one illegible byte and move on. 7780 } else { 7781 WithColor::warning(errs(), "llvm-objdump") 7782 << "invalid instruction encoding\n"; 7783 if (InstSize == 0) 7784 InstSize = 1; // skip illegible bytes 7785 } 7786 } 7787 } 7788 } 7789 // The TripleName's need to be reset if we are called again for a different 7790 // architecture. 7791 TripleName = ""; 7792 ThumbTripleName = ""; 7793 7794 if (SymbolizerInfo.demangled_name != nullptr) 7795 free(SymbolizerInfo.demangled_name); 7796 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7797 free(ThumbSymbolizerInfo.demangled_name); 7798 } 7799 } 7800 7801 //===----------------------------------------------------------------------===// 7802 // __compact_unwind section dumping 7803 //===----------------------------------------------------------------------===// 7804 7805 namespace { 7806 7807 template <typename T> 7808 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7809 using llvm::support::little; 7810 using llvm::support::unaligned; 7811 7812 if (Offset + sizeof(T) > Contents.size()) { 7813 outs() << "warning: attempt to read past end of buffer\n"; 7814 return T(); 7815 } 7816 7817 uint64_t Val = 7818 support::endian::read<T, little, unaligned>(Contents.data() + Offset); 7819 return Val; 7820 } 7821 7822 template <typename T> 7823 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7824 T Val = read<T>(Contents, Offset); 7825 Offset += sizeof(T); 7826 return Val; 7827 } 7828 7829 struct CompactUnwindEntry { 7830 uint32_t OffsetInSection; 7831 7832 uint64_t FunctionAddr; 7833 uint32_t Length; 7834 uint32_t CompactEncoding; 7835 uint64_t PersonalityAddr; 7836 uint64_t LSDAAddr; 7837 7838 RelocationRef FunctionReloc; 7839 RelocationRef PersonalityReloc; 7840 RelocationRef LSDAReloc; 7841 7842 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7843 : OffsetInSection(Offset) { 7844 if (Is64) 7845 read<uint64_t>(Contents, Offset); 7846 else 7847 read<uint32_t>(Contents, Offset); 7848 } 7849 7850 private: 7851 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7852 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7853 Length = readNext<uint32_t>(Contents, Offset); 7854 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7855 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7856 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7857 } 7858 }; 7859 } 7860 7861 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7862 /// and data being relocated, determine the best base Name and Addend to use for 7863 /// display purposes. 7864 /// 7865 /// 1. An Extern relocation will directly reference a symbol (and the data is 7866 /// then already an addend), so use that. 7867 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7868 // a symbol before it in the same section, and use the offset from there. 7869 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7870 /// referenced section. 7871 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7872 std::map<uint64_t, SymbolRef> &Symbols, 7873 const RelocationRef &Reloc, uint64_t Addr, 7874 StringRef &Name, uint64_t &Addend) { 7875 if (Reloc.getSymbol() != Obj->symbol_end()) { 7876 Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName()); 7877 Addend = Addr; 7878 return; 7879 } 7880 7881 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7882 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7883 7884 uint64_t SectionAddr = RelocSection.getAddress(); 7885 7886 auto Sym = Symbols.upper_bound(Addr); 7887 if (Sym == Symbols.begin()) { 7888 // The first symbol in the object is after this reference, the best we can 7889 // do is section-relative notation. 7890 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7891 Name = *NameOrErr; 7892 else 7893 consumeError(NameOrErr.takeError()); 7894 7895 Addend = Addr - SectionAddr; 7896 return; 7897 } 7898 7899 // Go back one so that SymbolAddress <= Addr. 7900 --Sym; 7901 7902 section_iterator SymSection = 7903 unwrapOrError(Sym->second.getSection(), Obj->getFileName()); 7904 if (RelocSection == *SymSection) { 7905 // There's a valid symbol in the same section before this reference. 7906 Name = unwrapOrError(Sym->second.getName(), Obj->getFileName()); 7907 Addend = Addr - Sym->first; 7908 return; 7909 } 7910 7911 // There is a symbol before this reference, but it's in a different 7912 // section. Probably not helpful to mention it, so use the section name. 7913 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7914 Name = *NameOrErr; 7915 else 7916 consumeError(NameOrErr.takeError()); 7917 7918 Addend = Addr - SectionAddr; 7919 } 7920 7921 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7922 std::map<uint64_t, SymbolRef> &Symbols, 7923 const RelocationRef &Reloc, uint64_t Addr) { 7924 StringRef Name; 7925 uint64_t Addend; 7926 7927 if (!Reloc.getObject()) 7928 return; 7929 7930 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7931 7932 outs() << Name; 7933 if (Addend) 7934 outs() << " + " << format("0x%" PRIx64, Addend); 7935 } 7936 7937 static void 7938 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7939 std::map<uint64_t, SymbolRef> &Symbols, 7940 const SectionRef &CompactUnwind) { 7941 7942 if (!Obj->isLittleEndian()) { 7943 outs() << "Skipping big-endian __compact_unwind section\n"; 7944 return; 7945 } 7946 7947 bool Is64 = Obj->is64Bit(); 7948 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7949 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7950 7951 StringRef Contents = 7952 unwrapOrError(CompactUnwind.getContents(), Obj->getFileName()); 7953 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7954 7955 // First populate the initial raw offsets, encodings and so on from the entry. 7956 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7957 CompactUnwindEntry Entry(Contents, Offset, Is64); 7958 CompactUnwinds.push_back(Entry); 7959 } 7960 7961 // Next we need to look at the relocations to find out what objects are 7962 // actually being referred to. 7963 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7964 uint64_t RelocAddress = Reloc.getOffset(); 7965 7966 uint32_t EntryIdx = RelocAddress / EntrySize; 7967 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7968 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7969 7970 if (OffsetInEntry == 0) 7971 Entry.FunctionReloc = Reloc; 7972 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7973 Entry.PersonalityReloc = Reloc; 7974 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7975 Entry.LSDAReloc = Reloc; 7976 else { 7977 outs() << "Invalid relocation in __compact_unwind section\n"; 7978 return; 7979 } 7980 } 7981 7982 // Finally, we're ready to print the data we've gathered. 7983 outs() << "Contents of __compact_unwind section:\n"; 7984 for (auto &Entry : CompactUnwinds) { 7985 outs() << " Entry at offset " 7986 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7987 7988 // 1. Start of the region this entry applies to. 7989 outs() << " start: " << format("0x%" PRIx64, 7990 Entry.FunctionAddr) << ' '; 7991 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7992 outs() << '\n'; 7993 7994 // 2. Length of the region this entry applies to. 7995 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7996 << '\n'; 7997 // 3. The 32-bit compact encoding. 7998 outs() << " compact encoding: " 7999 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 8000 8001 // 4. The personality function, if present. 8002 if (Entry.PersonalityReloc.getObject()) { 8003 outs() << " personality function: " 8004 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 8005 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 8006 Entry.PersonalityAddr); 8007 outs() << '\n'; 8008 } 8009 8010 // 5. This entry's language-specific data area. 8011 if (Entry.LSDAReloc.getObject()) { 8012 outs() << " LSDA: " << format("0x%" PRIx64, 8013 Entry.LSDAAddr) << ' '; 8014 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 8015 outs() << '\n'; 8016 } 8017 } 8018 } 8019 8020 //===----------------------------------------------------------------------===// 8021 // __unwind_info section dumping 8022 //===----------------------------------------------------------------------===// 8023 8024 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 8025 ptrdiff_t Pos = 0; 8026 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 8027 (void)Kind; 8028 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 8029 8030 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 8031 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 8032 8033 Pos = EntriesStart; 8034 for (unsigned i = 0; i < NumEntries; ++i) { 8035 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 8036 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 8037 8038 outs() << " [" << i << "]: " 8039 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8040 << ", " 8041 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 8042 } 8043 } 8044 8045 static void printCompressedSecondLevelUnwindPage( 8046 StringRef PageData, uint32_t FunctionBase, 8047 const SmallVectorImpl<uint32_t> &CommonEncodings) { 8048 ptrdiff_t Pos = 0; 8049 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 8050 (void)Kind; 8051 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 8052 8053 uint32_t NumCommonEncodings = CommonEncodings.size(); 8054 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 8055 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 8056 8057 uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos); 8058 uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos); 8059 SmallVector<uint32_t, 64> PageEncodings; 8060 if (NumPageEncodings) { 8061 outs() << " Page encodings: (count = " << NumPageEncodings << ")\n"; 8062 Pos = PageEncodingsStart; 8063 for (unsigned i = 0; i < NumPageEncodings; ++i) { 8064 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 8065 PageEncodings.push_back(Encoding); 8066 outs() << " encoding[" << (i + NumCommonEncodings) 8067 << "]: " << format("0x%08" PRIx32, Encoding) << '\n'; 8068 } 8069 } 8070 8071 Pos = EntriesStart; 8072 for (unsigned i = 0; i < NumEntries; ++i) { 8073 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 8074 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 8075 uint32_t EncodingIdx = Entry >> 24; 8076 8077 uint32_t Encoding; 8078 if (EncodingIdx < NumCommonEncodings) 8079 Encoding = CommonEncodings[EncodingIdx]; 8080 else 8081 Encoding = PageEncodings[EncodingIdx - NumCommonEncodings]; 8082 8083 outs() << " [" << i << "]: " 8084 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8085 << ", " 8086 << "encoding[" << EncodingIdx 8087 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 8088 } 8089 } 8090 8091 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 8092 std::map<uint64_t, SymbolRef> &Symbols, 8093 const SectionRef &UnwindInfo) { 8094 8095 if (!Obj->isLittleEndian()) { 8096 outs() << "Skipping big-endian __unwind_info section\n"; 8097 return; 8098 } 8099 8100 outs() << "Contents of __unwind_info section:\n"; 8101 8102 StringRef Contents = 8103 unwrapOrError(UnwindInfo.getContents(), Obj->getFileName()); 8104 ptrdiff_t Pos = 0; 8105 8106 //===---------------------------------- 8107 // Section header 8108 //===---------------------------------- 8109 8110 uint32_t Version = readNext<uint32_t>(Contents, Pos); 8111 outs() << " Version: " 8112 << format("0x%" PRIx32, Version) << '\n'; 8113 if (Version != 1) { 8114 outs() << " Skipping section with unknown version\n"; 8115 return; 8116 } 8117 8118 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 8119 outs() << " Common encodings array section offset: " 8120 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 8121 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 8122 outs() << " Number of common encodings in array: " 8123 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 8124 8125 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 8126 outs() << " Personality function array section offset: " 8127 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 8128 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 8129 outs() << " Number of personality functions in array: " 8130 << format("0x%" PRIx32, NumPersonalities) << '\n'; 8131 8132 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 8133 outs() << " Index array section offset: " 8134 << format("0x%" PRIx32, IndicesStart) << '\n'; 8135 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 8136 outs() << " Number of indices in array: " 8137 << format("0x%" PRIx32, NumIndices) << '\n'; 8138 8139 //===---------------------------------- 8140 // A shared list of common encodings 8141 //===---------------------------------- 8142 8143 // These occupy indices in the range [0, N] whenever an encoding is referenced 8144 // from a compressed 2nd level index table. In practice the linker only 8145 // creates ~128 of these, so that indices are available to embed encodings in 8146 // the 2nd level index. 8147 8148 SmallVector<uint32_t, 64> CommonEncodings; 8149 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 8150 Pos = CommonEncodingsStart; 8151 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 8152 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 8153 CommonEncodings.push_back(Encoding); 8154 8155 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 8156 << '\n'; 8157 } 8158 8159 //===---------------------------------- 8160 // Personality functions used in this executable 8161 //===---------------------------------- 8162 8163 // There should be only a handful of these (one per source language, 8164 // roughly). Particularly since they only get 2 bits in the compact encoding. 8165 8166 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 8167 Pos = PersonalitiesStart; 8168 for (unsigned i = 0; i < NumPersonalities; ++i) { 8169 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 8170 outs() << " personality[" << i + 1 8171 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 8172 } 8173 8174 //===---------------------------------- 8175 // The level 1 index entries 8176 //===---------------------------------- 8177 8178 // These specify an approximate place to start searching for the more detailed 8179 // information, sorted by PC. 8180 8181 struct IndexEntry { 8182 uint32_t FunctionOffset; 8183 uint32_t SecondLevelPageStart; 8184 uint32_t LSDAStart; 8185 }; 8186 8187 SmallVector<IndexEntry, 4> IndexEntries; 8188 8189 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 8190 Pos = IndicesStart; 8191 for (unsigned i = 0; i < NumIndices; ++i) { 8192 IndexEntry Entry; 8193 8194 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 8195 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 8196 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 8197 IndexEntries.push_back(Entry); 8198 8199 outs() << " [" << i << "]: " 8200 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 8201 << ", " 8202 << "2nd level page offset=" 8203 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 8204 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 8205 } 8206 8207 //===---------------------------------- 8208 // Next come the LSDA tables 8209 //===---------------------------------- 8210 8211 // The LSDA layout is rather implicit: it's a contiguous array of entries from 8212 // the first top-level index's LSDAOffset to the last (sentinel). 8213 8214 outs() << " LSDA descriptors:\n"; 8215 Pos = IndexEntries[0].LSDAStart; 8216 const uint32_t LSDASize = 2 * sizeof(uint32_t); 8217 int NumLSDAs = 8218 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 8219 8220 for (int i = 0; i < NumLSDAs; ++i) { 8221 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 8222 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 8223 outs() << " [" << i << "]: " 8224 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8225 << ", " 8226 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 8227 } 8228 8229 //===---------------------------------- 8230 // Finally, the 2nd level indices 8231 //===---------------------------------- 8232 8233 // Generally these are 4K in size, and have 2 possible forms: 8234 // + Regular stores up to 511 entries with disparate encodings 8235 // + Compressed stores up to 1021 entries if few enough compact encoding 8236 // values are used. 8237 outs() << " Second level indices:\n"; 8238 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 8239 // The final sentinel top-level index has no associated 2nd level page 8240 if (IndexEntries[i].SecondLevelPageStart == 0) 8241 break; 8242 8243 outs() << " Second level index[" << i << "]: " 8244 << "offset in section=" 8245 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 8246 << ", " 8247 << "base function offset=" 8248 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 8249 8250 Pos = IndexEntries[i].SecondLevelPageStart; 8251 if (Pos + sizeof(uint32_t) > Contents.size()) { 8252 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 8253 continue; 8254 } 8255 8256 uint32_t Kind = 8257 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 8258 if (Kind == 2) 8259 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 8260 else if (Kind == 3) 8261 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 8262 IndexEntries[i].FunctionOffset, 8263 CommonEncodings); 8264 else 8265 outs() << " Skipping 2nd level page with unknown kind " << Kind 8266 << '\n'; 8267 } 8268 } 8269 8270 void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) { 8271 std::map<uint64_t, SymbolRef> Symbols; 8272 for (const SymbolRef &SymRef : Obj->symbols()) { 8273 // Discard any undefined or absolute symbols. They're not going to take part 8274 // in the convenience lookup for unwind info and just take up resources. 8275 auto SectOrErr = SymRef.getSection(); 8276 if (!SectOrErr) { 8277 // TODO: Actually report errors helpfully. 8278 consumeError(SectOrErr.takeError()); 8279 continue; 8280 } 8281 section_iterator Section = *SectOrErr; 8282 if (Section == Obj->section_end()) 8283 continue; 8284 8285 uint64_t Addr = cantFail(SymRef.getValue()); 8286 Symbols.insert(std::make_pair(Addr, SymRef)); 8287 } 8288 8289 for (const SectionRef &Section : Obj->sections()) { 8290 StringRef SectName; 8291 if (Expected<StringRef> NameOrErr = Section.getName()) 8292 SectName = *NameOrErr; 8293 else 8294 consumeError(NameOrErr.takeError()); 8295 8296 if (SectName == "__compact_unwind") 8297 printMachOCompactUnwindSection(Obj, Symbols, Section); 8298 else if (SectName == "__unwind_info") 8299 printMachOUnwindInfoSection(Obj, Symbols, Section); 8300 } 8301 } 8302 8303 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 8304 uint32_t cpusubtype, uint32_t filetype, 8305 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 8306 bool verbose) { 8307 outs() << "Mach header\n"; 8308 outs() << " magic cputype cpusubtype caps filetype ncmds " 8309 "sizeofcmds flags\n"; 8310 if (verbose) { 8311 if (magic == MachO::MH_MAGIC) 8312 outs() << " MH_MAGIC"; 8313 else if (magic == MachO::MH_MAGIC_64) 8314 outs() << "MH_MAGIC_64"; 8315 else 8316 outs() << format(" 0x%08" PRIx32, magic); 8317 switch (cputype) { 8318 case MachO::CPU_TYPE_I386: 8319 outs() << " I386"; 8320 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8321 case MachO::CPU_SUBTYPE_I386_ALL: 8322 outs() << " ALL"; 8323 break; 8324 default: 8325 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8326 break; 8327 } 8328 break; 8329 case MachO::CPU_TYPE_X86_64: 8330 outs() << " X86_64"; 8331 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8332 case MachO::CPU_SUBTYPE_X86_64_ALL: 8333 outs() << " ALL"; 8334 break; 8335 case MachO::CPU_SUBTYPE_X86_64_H: 8336 outs() << " Haswell"; 8337 break; 8338 default: 8339 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8340 break; 8341 } 8342 break; 8343 case MachO::CPU_TYPE_ARM: 8344 outs() << " ARM"; 8345 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8346 case MachO::CPU_SUBTYPE_ARM_ALL: 8347 outs() << " ALL"; 8348 break; 8349 case MachO::CPU_SUBTYPE_ARM_V4T: 8350 outs() << " V4T"; 8351 break; 8352 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 8353 outs() << " V5TEJ"; 8354 break; 8355 case MachO::CPU_SUBTYPE_ARM_XSCALE: 8356 outs() << " XSCALE"; 8357 break; 8358 case MachO::CPU_SUBTYPE_ARM_V6: 8359 outs() << " V6"; 8360 break; 8361 case MachO::CPU_SUBTYPE_ARM_V6M: 8362 outs() << " V6M"; 8363 break; 8364 case MachO::CPU_SUBTYPE_ARM_V7: 8365 outs() << " V7"; 8366 break; 8367 case MachO::CPU_SUBTYPE_ARM_V7EM: 8368 outs() << " V7EM"; 8369 break; 8370 case MachO::CPU_SUBTYPE_ARM_V7K: 8371 outs() << " V7K"; 8372 break; 8373 case MachO::CPU_SUBTYPE_ARM_V7M: 8374 outs() << " V7M"; 8375 break; 8376 case MachO::CPU_SUBTYPE_ARM_V7S: 8377 outs() << " V7S"; 8378 break; 8379 default: 8380 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8381 break; 8382 } 8383 break; 8384 case MachO::CPU_TYPE_ARM64: 8385 outs() << " ARM64"; 8386 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8387 case MachO::CPU_SUBTYPE_ARM64_ALL: 8388 outs() << " ALL"; 8389 break; 8390 case MachO::CPU_SUBTYPE_ARM64_V8: 8391 outs() << " V8"; 8392 break; 8393 case MachO::CPU_SUBTYPE_ARM64E: 8394 outs() << " E"; 8395 break; 8396 default: 8397 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8398 break; 8399 } 8400 break; 8401 case MachO::CPU_TYPE_ARM64_32: 8402 outs() << " ARM64_32"; 8403 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8404 case MachO::CPU_SUBTYPE_ARM64_32_V8: 8405 outs() << " V8"; 8406 break; 8407 default: 8408 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8409 break; 8410 } 8411 break; 8412 case MachO::CPU_TYPE_POWERPC: 8413 outs() << " PPC"; 8414 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8415 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8416 outs() << " ALL"; 8417 break; 8418 default: 8419 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8420 break; 8421 } 8422 break; 8423 case MachO::CPU_TYPE_POWERPC64: 8424 outs() << " PPC64"; 8425 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8426 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8427 outs() << " ALL"; 8428 break; 8429 default: 8430 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8431 break; 8432 } 8433 break; 8434 default: 8435 outs() << format(" %7d", cputype); 8436 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8437 break; 8438 } 8439 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 8440 outs() << " LIB64"; 8441 } else { 8442 outs() << format(" 0x%02" PRIx32, 8443 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8444 } 8445 switch (filetype) { 8446 case MachO::MH_OBJECT: 8447 outs() << " OBJECT"; 8448 break; 8449 case MachO::MH_EXECUTE: 8450 outs() << " EXECUTE"; 8451 break; 8452 case MachO::MH_FVMLIB: 8453 outs() << " FVMLIB"; 8454 break; 8455 case MachO::MH_CORE: 8456 outs() << " CORE"; 8457 break; 8458 case MachO::MH_PRELOAD: 8459 outs() << " PRELOAD"; 8460 break; 8461 case MachO::MH_DYLIB: 8462 outs() << " DYLIB"; 8463 break; 8464 case MachO::MH_DYLIB_STUB: 8465 outs() << " DYLIB_STUB"; 8466 break; 8467 case MachO::MH_DYLINKER: 8468 outs() << " DYLINKER"; 8469 break; 8470 case MachO::MH_BUNDLE: 8471 outs() << " BUNDLE"; 8472 break; 8473 case MachO::MH_DSYM: 8474 outs() << " DSYM"; 8475 break; 8476 case MachO::MH_KEXT_BUNDLE: 8477 outs() << " KEXTBUNDLE"; 8478 break; 8479 default: 8480 outs() << format(" %10u", filetype); 8481 break; 8482 } 8483 outs() << format(" %5u", ncmds); 8484 outs() << format(" %10u", sizeofcmds); 8485 uint32_t f = flags; 8486 if (f & MachO::MH_NOUNDEFS) { 8487 outs() << " NOUNDEFS"; 8488 f &= ~MachO::MH_NOUNDEFS; 8489 } 8490 if (f & MachO::MH_INCRLINK) { 8491 outs() << " INCRLINK"; 8492 f &= ~MachO::MH_INCRLINK; 8493 } 8494 if (f & MachO::MH_DYLDLINK) { 8495 outs() << " DYLDLINK"; 8496 f &= ~MachO::MH_DYLDLINK; 8497 } 8498 if (f & MachO::MH_BINDATLOAD) { 8499 outs() << " BINDATLOAD"; 8500 f &= ~MachO::MH_BINDATLOAD; 8501 } 8502 if (f & MachO::MH_PREBOUND) { 8503 outs() << " PREBOUND"; 8504 f &= ~MachO::MH_PREBOUND; 8505 } 8506 if (f & MachO::MH_SPLIT_SEGS) { 8507 outs() << " SPLIT_SEGS"; 8508 f &= ~MachO::MH_SPLIT_SEGS; 8509 } 8510 if (f & MachO::MH_LAZY_INIT) { 8511 outs() << " LAZY_INIT"; 8512 f &= ~MachO::MH_LAZY_INIT; 8513 } 8514 if (f & MachO::MH_TWOLEVEL) { 8515 outs() << " TWOLEVEL"; 8516 f &= ~MachO::MH_TWOLEVEL; 8517 } 8518 if (f & MachO::MH_FORCE_FLAT) { 8519 outs() << " FORCE_FLAT"; 8520 f &= ~MachO::MH_FORCE_FLAT; 8521 } 8522 if (f & MachO::MH_NOMULTIDEFS) { 8523 outs() << " NOMULTIDEFS"; 8524 f &= ~MachO::MH_NOMULTIDEFS; 8525 } 8526 if (f & MachO::MH_NOFIXPREBINDING) { 8527 outs() << " NOFIXPREBINDING"; 8528 f &= ~MachO::MH_NOFIXPREBINDING; 8529 } 8530 if (f & MachO::MH_PREBINDABLE) { 8531 outs() << " PREBINDABLE"; 8532 f &= ~MachO::MH_PREBINDABLE; 8533 } 8534 if (f & MachO::MH_ALLMODSBOUND) { 8535 outs() << " ALLMODSBOUND"; 8536 f &= ~MachO::MH_ALLMODSBOUND; 8537 } 8538 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8539 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8540 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8541 } 8542 if (f & MachO::MH_CANONICAL) { 8543 outs() << " CANONICAL"; 8544 f &= ~MachO::MH_CANONICAL; 8545 } 8546 if (f & MachO::MH_WEAK_DEFINES) { 8547 outs() << " WEAK_DEFINES"; 8548 f &= ~MachO::MH_WEAK_DEFINES; 8549 } 8550 if (f & MachO::MH_BINDS_TO_WEAK) { 8551 outs() << " BINDS_TO_WEAK"; 8552 f &= ~MachO::MH_BINDS_TO_WEAK; 8553 } 8554 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8555 outs() << " ALLOW_STACK_EXECUTION"; 8556 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8557 } 8558 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8559 outs() << " DEAD_STRIPPABLE_DYLIB"; 8560 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8561 } 8562 if (f & MachO::MH_PIE) { 8563 outs() << " PIE"; 8564 f &= ~MachO::MH_PIE; 8565 } 8566 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8567 outs() << " NO_REEXPORTED_DYLIBS"; 8568 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8569 } 8570 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8571 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8572 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8573 } 8574 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8575 outs() << " MH_NO_HEAP_EXECUTION"; 8576 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8577 } 8578 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8579 outs() << " APP_EXTENSION_SAFE"; 8580 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8581 } 8582 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8583 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8584 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8585 } 8586 if (f != 0 || flags == 0) 8587 outs() << format(" 0x%08" PRIx32, f); 8588 } else { 8589 outs() << format(" 0x%08" PRIx32, magic); 8590 outs() << format(" %7d", cputype); 8591 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8592 outs() << format(" 0x%02" PRIx32, 8593 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8594 outs() << format(" %10u", filetype); 8595 outs() << format(" %5u", ncmds); 8596 outs() << format(" %10u", sizeofcmds); 8597 outs() << format(" 0x%08" PRIx32, flags); 8598 } 8599 outs() << "\n"; 8600 } 8601 8602 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8603 StringRef SegName, uint64_t vmaddr, 8604 uint64_t vmsize, uint64_t fileoff, 8605 uint64_t filesize, uint32_t maxprot, 8606 uint32_t initprot, uint32_t nsects, 8607 uint32_t flags, uint32_t object_size, 8608 bool verbose) { 8609 uint64_t expected_cmdsize; 8610 if (cmd == MachO::LC_SEGMENT) { 8611 outs() << " cmd LC_SEGMENT\n"; 8612 expected_cmdsize = nsects; 8613 expected_cmdsize *= sizeof(struct MachO::section); 8614 expected_cmdsize += sizeof(struct MachO::segment_command); 8615 } else { 8616 outs() << " cmd LC_SEGMENT_64\n"; 8617 expected_cmdsize = nsects; 8618 expected_cmdsize *= sizeof(struct MachO::section_64); 8619 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8620 } 8621 outs() << " cmdsize " << cmdsize; 8622 if (cmdsize != expected_cmdsize) 8623 outs() << " Inconsistent size\n"; 8624 else 8625 outs() << "\n"; 8626 outs() << " segname " << SegName << "\n"; 8627 if (cmd == MachO::LC_SEGMENT_64) { 8628 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8629 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8630 } else { 8631 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8632 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8633 } 8634 outs() << " fileoff " << fileoff; 8635 if (fileoff > object_size) 8636 outs() << " (past end of file)\n"; 8637 else 8638 outs() << "\n"; 8639 outs() << " filesize " << filesize; 8640 if (fileoff + filesize > object_size) 8641 outs() << " (past end of file)\n"; 8642 else 8643 outs() << "\n"; 8644 if (verbose) { 8645 if ((maxprot & 8646 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8647 MachO::VM_PROT_EXECUTE)) != 0) 8648 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8649 else { 8650 outs() << " maxprot "; 8651 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8652 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8653 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8654 } 8655 if ((initprot & 8656 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8657 MachO::VM_PROT_EXECUTE)) != 0) 8658 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8659 else { 8660 outs() << " initprot "; 8661 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8662 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8663 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8664 } 8665 } else { 8666 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8667 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8668 } 8669 outs() << " nsects " << nsects << "\n"; 8670 if (verbose) { 8671 outs() << " flags"; 8672 if (flags == 0) 8673 outs() << " (none)\n"; 8674 else { 8675 if (flags & MachO::SG_HIGHVM) { 8676 outs() << " HIGHVM"; 8677 flags &= ~MachO::SG_HIGHVM; 8678 } 8679 if (flags & MachO::SG_FVMLIB) { 8680 outs() << " FVMLIB"; 8681 flags &= ~MachO::SG_FVMLIB; 8682 } 8683 if (flags & MachO::SG_NORELOC) { 8684 outs() << " NORELOC"; 8685 flags &= ~MachO::SG_NORELOC; 8686 } 8687 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8688 outs() << " PROTECTED_VERSION_1"; 8689 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8690 } 8691 if (flags) 8692 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8693 else 8694 outs() << "\n"; 8695 } 8696 } else { 8697 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8698 } 8699 } 8700 8701 static void PrintSection(const char *sectname, const char *segname, 8702 uint64_t addr, uint64_t size, uint32_t offset, 8703 uint32_t align, uint32_t reloff, uint32_t nreloc, 8704 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8705 uint32_t cmd, const char *sg_segname, 8706 uint32_t filetype, uint32_t object_size, 8707 bool verbose) { 8708 outs() << "Section\n"; 8709 outs() << " sectname " << format("%.16s\n", sectname); 8710 outs() << " segname " << format("%.16s", segname); 8711 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8712 outs() << " (does not match segment)\n"; 8713 else 8714 outs() << "\n"; 8715 if (cmd == MachO::LC_SEGMENT_64) { 8716 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8717 outs() << " size " << format("0x%016" PRIx64, size); 8718 } else { 8719 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8720 outs() << " size " << format("0x%08" PRIx64, size); 8721 } 8722 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8723 outs() << " (past end of file)\n"; 8724 else 8725 outs() << "\n"; 8726 outs() << " offset " << offset; 8727 if (offset > object_size) 8728 outs() << " (past end of file)\n"; 8729 else 8730 outs() << "\n"; 8731 uint32_t align_shifted = 1 << align; 8732 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8733 outs() << " reloff " << reloff; 8734 if (reloff > object_size) 8735 outs() << " (past end of file)\n"; 8736 else 8737 outs() << "\n"; 8738 outs() << " nreloc " << nreloc; 8739 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8740 outs() << " (past end of file)\n"; 8741 else 8742 outs() << "\n"; 8743 uint32_t section_type = flags & MachO::SECTION_TYPE; 8744 if (verbose) { 8745 outs() << " type"; 8746 if (section_type == MachO::S_REGULAR) 8747 outs() << " S_REGULAR\n"; 8748 else if (section_type == MachO::S_ZEROFILL) 8749 outs() << " S_ZEROFILL\n"; 8750 else if (section_type == MachO::S_CSTRING_LITERALS) 8751 outs() << " S_CSTRING_LITERALS\n"; 8752 else if (section_type == MachO::S_4BYTE_LITERALS) 8753 outs() << " S_4BYTE_LITERALS\n"; 8754 else if (section_type == MachO::S_8BYTE_LITERALS) 8755 outs() << " S_8BYTE_LITERALS\n"; 8756 else if (section_type == MachO::S_16BYTE_LITERALS) 8757 outs() << " S_16BYTE_LITERALS\n"; 8758 else if (section_type == MachO::S_LITERAL_POINTERS) 8759 outs() << " S_LITERAL_POINTERS\n"; 8760 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8761 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8762 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8763 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8764 else if (section_type == MachO::S_SYMBOL_STUBS) 8765 outs() << " S_SYMBOL_STUBS\n"; 8766 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8767 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8768 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8769 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8770 else if (section_type == MachO::S_COALESCED) 8771 outs() << " S_COALESCED\n"; 8772 else if (section_type == MachO::S_INTERPOSING) 8773 outs() << " S_INTERPOSING\n"; 8774 else if (section_type == MachO::S_DTRACE_DOF) 8775 outs() << " S_DTRACE_DOF\n"; 8776 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8777 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8778 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8779 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8780 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8781 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8782 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8783 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8784 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8785 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8786 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8787 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8788 else 8789 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8790 outs() << "attributes"; 8791 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8792 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8793 outs() << " PURE_INSTRUCTIONS"; 8794 if (section_attributes & MachO::S_ATTR_NO_TOC) 8795 outs() << " NO_TOC"; 8796 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8797 outs() << " STRIP_STATIC_SYMS"; 8798 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8799 outs() << " NO_DEAD_STRIP"; 8800 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8801 outs() << " LIVE_SUPPORT"; 8802 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8803 outs() << " SELF_MODIFYING_CODE"; 8804 if (section_attributes & MachO::S_ATTR_DEBUG) 8805 outs() << " DEBUG"; 8806 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8807 outs() << " SOME_INSTRUCTIONS"; 8808 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8809 outs() << " EXT_RELOC"; 8810 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8811 outs() << " LOC_RELOC"; 8812 if (section_attributes == 0) 8813 outs() << " (none)"; 8814 outs() << "\n"; 8815 } else 8816 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8817 outs() << " reserved1 " << reserved1; 8818 if (section_type == MachO::S_SYMBOL_STUBS || 8819 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8820 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8821 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8822 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8823 outs() << " (index into indirect symbol table)\n"; 8824 else 8825 outs() << "\n"; 8826 outs() << " reserved2 " << reserved2; 8827 if (section_type == MachO::S_SYMBOL_STUBS) 8828 outs() << " (size of stubs)\n"; 8829 else 8830 outs() << "\n"; 8831 } 8832 8833 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8834 uint32_t object_size) { 8835 outs() << " cmd LC_SYMTAB\n"; 8836 outs() << " cmdsize " << st.cmdsize; 8837 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8838 outs() << " Incorrect size\n"; 8839 else 8840 outs() << "\n"; 8841 outs() << " symoff " << st.symoff; 8842 if (st.symoff > object_size) 8843 outs() << " (past end of file)\n"; 8844 else 8845 outs() << "\n"; 8846 outs() << " nsyms " << st.nsyms; 8847 uint64_t big_size; 8848 if (Is64Bit) { 8849 big_size = st.nsyms; 8850 big_size *= sizeof(struct MachO::nlist_64); 8851 big_size += st.symoff; 8852 if (big_size > object_size) 8853 outs() << " (past end of file)\n"; 8854 else 8855 outs() << "\n"; 8856 } else { 8857 big_size = st.nsyms; 8858 big_size *= sizeof(struct MachO::nlist); 8859 big_size += st.symoff; 8860 if (big_size > object_size) 8861 outs() << " (past end of file)\n"; 8862 else 8863 outs() << "\n"; 8864 } 8865 outs() << " stroff " << st.stroff; 8866 if (st.stroff > object_size) 8867 outs() << " (past end of file)\n"; 8868 else 8869 outs() << "\n"; 8870 outs() << " strsize " << st.strsize; 8871 big_size = st.stroff; 8872 big_size += st.strsize; 8873 if (big_size > object_size) 8874 outs() << " (past end of file)\n"; 8875 else 8876 outs() << "\n"; 8877 } 8878 8879 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8880 uint32_t nsyms, uint32_t object_size, 8881 bool Is64Bit) { 8882 outs() << " cmd LC_DYSYMTAB\n"; 8883 outs() << " cmdsize " << dyst.cmdsize; 8884 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8885 outs() << " Incorrect size\n"; 8886 else 8887 outs() << "\n"; 8888 outs() << " ilocalsym " << dyst.ilocalsym; 8889 if (dyst.ilocalsym > nsyms) 8890 outs() << " (greater than the number of symbols)\n"; 8891 else 8892 outs() << "\n"; 8893 outs() << " nlocalsym " << dyst.nlocalsym; 8894 uint64_t big_size; 8895 big_size = dyst.ilocalsym; 8896 big_size += dyst.nlocalsym; 8897 if (big_size > nsyms) 8898 outs() << " (past the end of the symbol table)\n"; 8899 else 8900 outs() << "\n"; 8901 outs() << " iextdefsym " << dyst.iextdefsym; 8902 if (dyst.iextdefsym > nsyms) 8903 outs() << " (greater than the number of symbols)\n"; 8904 else 8905 outs() << "\n"; 8906 outs() << " nextdefsym " << dyst.nextdefsym; 8907 big_size = dyst.iextdefsym; 8908 big_size += dyst.nextdefsym; 8909 if (big_size > nsyms) 8910 outs() << " (past the end of the symbol table)\n"; 8911 else 8912 outs() << "\n"; 8913 outs() << " iundefsym " << dyst.iundefsym; 8914 if (dyst.iundefsym > nsyms) 8915 outs() << " (greater than the number of symbols)\n"; 8916 else 8917 outs() << "\n"; 8918 outs() << " nundefsym " << dyst.nundefsym; 8919 big_size = dyst.iundefsym; 8920 big_size += dyst.nundefsym; 8921 if (big_size > nsyms) 8922 outs() << " (past the end of the symbol table)\n"; 8923 else 8924 outs() << "\n"; 8925 outs() << " tocoff " << dyst.tocoff; 8926 if (dyst.tocoff > object_size) 8927 outs() << " (past end of file)\n"; 8928 else 8929 outs() << "\n"; 8930 outs() << " ntoc " << dyst.ntoc; 8931 big_size = dyst.ntoc; 8932 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8933 big_size += dyst.tocoff; 8934 if (big_size > object_size) 8935 outs() << " (past end of file)\n"; 8936 else 8937 outs() << "\n"; 8938 outs() << " modtaboff " << dyst.modtaboff; 8939 if (dyst.modtaboff > object_size) 8940 outs() << " (past end of file)\n"; 8941 else 8942 outs() << "\n"; 8943 outs() << " nmodtab " << dyst.nmodtab; 8944 uint64_t modtabend; 8945 if (Is64Bit) { 8946 modtabend = dyst.nmodtab; 8947 modtabend *= sizeof(struct MachO::dylib_module_64); 8948 modtabend += dyst.modtaboff; 8949 } else { 8950 modtabend = dyst.nmodtab; 8951 modtabend *= sizeof(struct MachO::dylib_module); 8952 modtabend += dyst.modtaboff; 8953 } 8954 if (modtabend > object_size) 8955 outs() << " (past end of file)\n"; 8956 else 8957 outs() << "\n"; 8958 outs() << " extrefsymoff " << dyst.extrefsymoff; 8959 if (dyst.extrefsymoff > object_size) 8960 outs() << " (past end of file)\n"; 8961 else 8962 outs() << "\n"; 8963 outs() << " nextrefsyms " << dyst.nextrefsyms; 8964 big_size = dyst.nextrefsyms; 8965 big_size *= sizeof(struct MachO::dylib_reference); 8966 big_size += dyst.extrefsymoff; 8967 if (big_size > object_size) 8968 outs() << " (past end of file)\n"; 8969 else 8970 outs() << "\n"; 8971 outs() << " indirectsymoff " << dyst.indirectsymoff; 8972 if (dyst.indirectsymoff > object_size) 8973 outs() << " (past end of file)\n"; 8974 else 8975 outs() << "\n"; 8976 outs() << " nindirectsyms " << dyst.nindirectsyms; 8977 big_size = dyst.nindirectsyms; 8978 big_size *= sizeof(uint32_t); 8979 big_size += dyst.indirectsymoff; 8980 if (big_size > object_size) 8981 outs() << " (past end of file)\n"; 8982 else 8983 outs() << "\n"; 8984 outs() << " extreloff " << dyst.extreloff; 8985 if (dyst.extreloff > object_size) 8986 outs() << " (past end of file)\n"; 8987 else 8988 outs() << "\n"; 8989 outs() << " nextrel " << dyst.nextrel; 8990 big_size = dyst.nextrel; 8991 big_size *= sizeof(struct MachO::relocation_info); 8992 big_size += dyst.extreloff; 8993 if (big_size > object_size) 8994 outs() << " (past end of file)\n"; 8995 else 8996 outs() << "\n"; 8997 outs() << " locreloff " << dyst.locreloff; 8998 if (dyst.locreloff > object_size) 8999 outs() << " (past end of file)\n"; 9000 else 9001 outs() << "\n"; 9002 outs() << " nlocrel " << dyst.nlocrel; 9003 big_size = dyst.nlocrel; 9004 big_size *= sizeof(struct MachO::relocation_info); 9005 big_size += dyst.locreloff; 9006 if (big_size > object_size) 9007 outs() << " (past end of file)\n"; 9008 else 9009 outs() << "\n"; 9010 } 9011 9012 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 9013 uint32_t object_size) { 9014 if (dc.cmd == MachO::LC_DYLD_INFO) 9015 outs() << " cmd LC_DYLD_INFO\n"; 9016 else 9017 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 9018 outs() << " cmdsize " << dc.cmdsize; 9019 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 9020 outs() << " Incorrect size\n"; 9021 else 9022 outs() << "\n"; 9023 outs() << " rebase_off " << dc.rebase_off; 9024 if (dc.rebase_off > object_size) 9025 outs() << " (past end of file)\n"; 9026 else 9027 outs() << "\n"; 9028 outs() << " rebase_size " << dc.rebase_size; 9029 uint64_t big_size; 9030 big_size = dc.rebase_off; 9031 big_size += dc.rebase_size; 9032 if (big_size > object_size) 9033 outs() << " (past end of file)\n"; 9034 else 9035 outs() << "\n"; 9036 outs() << " bind_off " << dc.bind_off; 9037 if (dc.bind_off > object_size) 9038 outs() << " (past end of file)\n"; 9039 else 9040 outs() << "\n"; 9041 outs() << " bind_size " << dc.bind_size; 9042 big_size = dc.bind_off; 9043 big_size += dc.bind_size; 9044 if (big_size > object_size) 9045 outs() << " (past end of file)\n"; 9046 else 9047 outs() << "\n"; 9048 outs() << " weak_bind_off " << dc.weak_bind_off; 9049 if (dc.weak_bind_off > object_size) 9050 outs() << " (past end of file)\n"; 9051 else 9052 outs() << "\n"; 9053 outs() << " weak_bind_size " << dc.weak_bind_size; 9054 big_size = dc.weak_bind_off; 9055 big_size += dc.weak_bind_size; 9056 if (big_size > object_size) 9057 outs() << " (past end of file)\n"; 9058 else 9059 outs() << "\n"; 9060 outs() << " lazy_bind_off " << dc.lazy_bind_off; 9061 if (dc.lazy_bind_off > object_size) 9062 outs() << " (past end of file)\n"; 9063 else 9064 outs() << "\n"; 9065 outs() << " lazy_bind_size " << dc.lazy_bind_size; 9066 big_size = dc.lazy_bind_off; 9067 big_size += dc.lazy_bind_size; 9068 if (big_size > object_size) 9069 outs() << " (past end of file)\n"; 9070 else 9071 outs() << "\n"; 9072 outs() << " export_off " << dc.export_off; 9073 if (dc.export_off > object_size) 9074 outs() << " (past end of file)\n"; 9075 else 9076 outs() << "\n"; 9077 outs() << " export_size " << dc.export_size; 9078 big_size = dc.export_off; 9079 big_size += dc.export_size; 9080 if (big_size > object_size) 9081 outs() << " (past end of file)\n"; 9082 else 9083 outs() << "\n"; 9084 } 9085 9086 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 9087 const char *Ptr) { 9088 if (dyld.cmd == MachO::LC_ID_DYLINKER) 9089 outs() << " cmd LC_ID_DYLINKER\n"; 9090 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 9091 outs() << " cmd LC_LOAD_DYLINKER\n"; 9092 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 9093 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 9094 else 9095 outs() << " cmd ?(" << dyld.cmd << ")\n"; 9096 outs() << " cmdsize " << dyld.cmdsize; 9097 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 9098 outs() << " Incorrect size\n"; 9099 else 9100 outs() << "\n"; 9101 if (dyld.name >= dyld.cmdsize) 9102 outs() << " name ?(bad offset " << dyld.name << ")\n"; 9103 else { 9104 const char *P = (const char *)(Ptr) + dyld.name; 9105 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 9106 } 9107 } 9108 9109 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 9110 outs() << " cmd LC_UUID\n"; 9111 outs() << " cmdsize " << uuid.cmdsize; 9112 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 9113 outs() << " Incorrect size\n"; 9114 else 9115 outs() << "\n"; 9116 outs() << " uuid "; 9117 for (int i = 0; i < 16; ++i) { 9118 outs() << format("%02" PRIX32, uuid.uuid[i]); 9119 if (i == 3 || i == 5 || i == 7 || i == 9) 9120 outs() << "-"; 9121 } 9122 outs() << "\n"; 9123 } 9124 9125 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 9126 outs() << " cmd LC_RPATH\n"; 9127 outs() << " cmdsize " << rpath.cmdsize; 9128 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 9129 outs() << " Incorrect size\n"; 9130 else 9131 outs() << "\n"; 9132 if (rpath.path >= rpath.cmdsize) 9133 outs() << " path ?(bad offset " << rpath.path << ")\n"; 9134 else { 9135 const char *P = (const char *)(Ptr) + rpath.path; 9136 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 9137 } 9138 } 9139 9140 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 9141 StringRef LoadCmdName; 9142 switch (vd.cmd) { 9143 case MachO::LC_VERSION_MIN_MACOSX: 9144 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 9145 break; 9146 case MachO::LC_VERSION_MIN_IPHONEOS: 9147 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 9148 break; 9149 case MachO::LC_VERSION_MIN_TVOS: 9150 LoadCmdName = "LC_VERSION_MIN_TVOS"; 9151 break; 9152 case MachO::LC_VERSION_MIN_WATCHOS: 9153 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 9154 break; 9155 default: 9156 llvm_unreachable("Unknown version min load command"); 9157 } 9158 9159 outs() << " cmd " << LoadCmdName << '\n'; 9160 outs() << " cmdsize " << vd.cmdsize; 9161 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 9162 outs() << " Incorrect size\n"; 9163 else 9164 outs() << "\n"; 9165 outs() << " version " 9166 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 9167 << MachOObjectFile::getVersionMinMinor(vd, false); 9168 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 9169 if (Update != 0) 9170 outs() << "." << Update; 9171 outs() << "\n"; 9172 if (vd.sdk == 0) 9173 outs() << " sdk n/a"; 9174 else { 9175 outs() << " sdk " 9176 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 9177 << MachOObjectFile::getVersionMinMinor(vd, true); 9178 } 9179 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 9180 if (Update != 0) 9181 outs() << "." << Update; 9182 outs() << "\n"; 9183 } 9184 9185 static void PrintNoteLoadCommand(MachO::note_command Nt) { 9186 outs() << " cmd LC_NOTE\n"; 9187 outs() << " cmdsize " << Nt.cmdsize; 9188 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 9189 outs() << " Incorrect size\n"; 9190 else 9191 outs() << "\n"; 9192 const char *d = Nt.data_owner; 9193 outs() << "data_owner " << format("%.16s\n", d); 9194 outs() << " offset " << Nt.offset << "\n"; 9195 outs() << " size " << Nt.size << "\n"; 9196 } 9197 9198 static void PrintBuildToolVersion(MachO::build_tool_version bv) { 9199 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; 9200 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 9201 << "\n"; 9202 } 9203 9204 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 9205 MachO::build_version_command bd) { 9206 outs() << " cmd LC_BUILD_VERSION\n"; 9207 outs() << " cmdsize " << bd.cmdsize; 9208 if (bd.cmdsize != 9209 sizeof(struct MachO::build_version_command) + 9210 bd.ntools * sizeof(struct MachO::build_tool_version)) 9211 outs() << " Incorrect size\n"; 9212 else 9213 outs() << "\n"; 9214 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) 9215 << "\n"; 9216 if (bd.sdk) 9217 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 9218 << "\n"; 9219 else 9220 outs() << " sdk n/a\n"; 9221 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 9222 << "\n"; 9223 outs() << " ntools " << bd.ntools << "\n"; 9224 for (unsigned i = 0; i < bd.ntools; ++i) { 9225 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 9226 PrintBuildToolVersion(bv); 9227 } 9228 } 9229 9230 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 9231 outs() << " cmd LC_SOURCE_VERSION\n"; 9232 outs() << " cmdsize " << sd.cmdsize; 9233 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 9234 outs() << " Incorrect size\n"; 9235 else 9236 outs() << "\n"; 9237 uint64_t a = (sd.version >> 40) & 0xffffff; 9238 uint64_t b = (sd.version >> 30) & 0x3ff; 9239 uint64_t c = (sd.version >> 20) & 0x3ff; 9240 uint64_t d = (sd.version >> 10) & 0x3ff; 9241 uint64_t e = sd.version & 0x3ff; 9242 outs() << " version " << a << "." << b; 9243 if (e != 0) 9244 outs() << "." << c << "." << d << "." << e; 9245 else if (d != 0) 9246 outs() << "." << c << "." << d; 9247 else if (c != 0) 9248 outs() << "." << c; 9249 outs() << "\n"; 9250 } 9251 9252 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 9253 outs() << " cmd LC_MAIN\n"; 9254 outs() << " cmdsize " << ep.cmdsize; 9255 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 9256 outs() << " Incorrect size\n"; 9257 else 9258 outs() << "\n"; 9259 outs() << " entryoff " << ep.entryoff << "\n"; 9260 outs() << " stacksize " << ep.stacksize << "\n"; 9261 } 9262 9263 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 9264 uint32_t object_size) { 9265 outs() << " cmd LC_ENCRYPTION_INFO\n"; 9266 outs() << " cmdsize " << ec.cmdsize; 9267 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 9268 outs() << " Incorrect size\n"; 9269 else 9270 outs() << "\n"; 9271 outs() << " cryptoff " << ec.cryptoff; 9272 if (ec.cryptoff > object_size) 9273 outs() << " (past end of file)\n"; 9274 else 9275 outs() << "\n"; 9276 outs() << " cryptsize " << ec.cryptsize; 9277 if (ec.cryptsize > object_size) 9278 outs() << " (past end of file)\n"; 9279 else 9280 outs() << "\n"; 9281 outs() << " cryptid " << ec.cryptid << "\n"; 9282 } 9283 9284 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 9285 uint32_t object_size) { 9286 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 9287 outs() << " cmdsize " << ec.cmdsize; 9288 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 9289 outs() << " Incorrect size\n"; 9290 else 9291 outs() << "\n"; 9292 outs() << " cryptoff " << ec.cryptoff; 9293 if (ec.cryptoff > object_size) 9294 outs() << " (past end of file)\n"; 9295 else 9296 outs() << "\n"; 9297 outs() << " cryptsize " << ec.cryptsize; 9298 if (ec.cryptsize > object_size) 9299 outs() << " (past end of file)\n"; 9300 else 9301 outs() << "\n"; 9302 outs() << " cryptid " << ec.cryptid << "\n"; 9303 outs() << " pad " << ec.pad << "\n"; 9304 } 9305 9306 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 9307 const char *Ptr) { 9308 outs() << " cmd LC_LINKER_OPTION\n"; 9309 outs() << " cmdsize " << lo.cmdsize; 9310 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 9311 outs() << " Incorrect size\n"; 9312 else 9313 outs() << "\n"; 9314 outs() << " count " << lo.count << "\n"; 9315 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 9316 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 9317 uint32_t i = 0; 9318 while (left > 0) { 9319 while (*string == '\0' && left > 0) { 9320 string++; 9321 left--; 9322 } 9323 if (left > 0) { 9324 i++; 9325 outs() << " string #" << i << " " << format("%.*s\n", left, string); 9326 uint32_t NullPos = StringRef(string, left).find('\0'); 9327 uint32_t len = std::min(NullPos, left) + 1; 9328 string += len; 9329 left -= len; 9330 } 9331 } 9332 if (lo.count != i) 9333 outs() << " count " << lo.count << " does not match number of strings " 9334 << i << "\n"; 9335 } 9336 9337 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 9338 const char *Ptr) { 9339 outs() << " cmd LC_SUB_FRAMEWORK\n"; 9340 outs() << " cmdsize " << sub.cmdsize; 9341 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 9342 outs() << " Incorrect size\n"; 9343 else 9344 outs() << "\n"; 9345 if (sub.umbrella < sub.cmdsize) { 9346 const char *P = Ptr + sub.umbrella; 9347 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 9348 } else { 9349 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 9350 } 9351 } 9352 9353 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 9354 const char *Ptr) { 9355 outs() << " cmd LC_SUB_UMBRELLA\n"; 9356 outs() << " cmdsize " << sub.cmdsize; 9357 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 9358 outs() << " Incorrect size\n"; 9359 else 9360 outs() << "\n"; 9361 if (sub.sub_umbrella < sub.cmdsize) { 9362 const char *P = Ptr + sub.sub_umbrella; 9363 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 9364 } else { 9365 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 9366 } 9367 } 9368 9369 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 9370 const char *Ptr) { 9371 outs() << " cmd LC_SUB_LIBRARY\n"; 9372 outs() << " cmdsize " << sub.cmdsize; 9373 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 9374 outs() << " Incorrect size\n"; 9375 else 9376 outs() << "\n"; 9377 if (sub.sub_library < sub.cmdsize) { 9378 const char *P = Ptr + sub.sub_library; 9379 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 9380 } else { 9381 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 9382 } 9383 } 9384 9385 static void PrintSubClientCommand(MachO::sub_client_command sub, 9386 const char *Ptr) { 9387 outs() << " cmd LC_SUB_CLIENT\n"; 9388 outs() << " cmdsize " << sub.cmdsize; 9389 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 9390 outs() << " Incorrect size\n"; 9391 else 9392 outs() << "\n"; 9393 if (sub.client < sub.cmdsize) { 9394 const char *P = Ptr + sub.client; 9395 outs() << " client " << P << " (offset " << sub.client << ")\n"; 9396 } else { 9397 outs() << " client ?(bad offset " << sub.client << ")\n"; 9398 } 9399 } 9400 9401 static void PrintRoutinesCommand(MachO::routines_command r) { 9402 outs() << " cmd LC_ROUTINES\n"; 9403 outs() << " cmdsize " << r.cmdsize; 9404 if (r.cmdsize != sizeof(struct MachO::routines_command)) 9405 outs() << " Incorrect size\n"; 9406 else 9407 outs() << "\n"; 9408 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 9409 outs() << " init_module " << r.init_module << "\n"; 9410 outs() << " reserved1 " << r.reserved1 << "\n"; 9411 outs() << " reserved2 " << r.reserved2 << "\n"; 9412 outs() << " reserved3 " << r.reserved3 << "\n"; 9413 outs() << " reserved4 " << r.reserved4 << "\n"; 9414 outs() << " reserved5 " << r.reserved5 << "\n"; 9415 outs() << " reserved6 " << r.reserved6 << "\n"; 9416 } 9417 9418 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 9419 outs() << " cmd LC_ROUTINES_64\n"; 9420 outs() << " cmdsize " << r.cmdsize; 9421 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 9422 outs() << " Incorrect size\n"; 9423 else 9424 outs() << "\n"; 9425 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 9426 outs() << " init_module " << r.init_module << "\n"; 9427 outs() << " reserved1 " << r.reserved1 << "\n"; 9428 outs() << " reserved2 " << r.reserved2 << "\n"; 9429 outs() << " reserved3 " << r.reserved3 << "\n"; 9430 outs() << " reserved4 " << r.reserved4 << "\n"; 9431 outs() << " reserved5 " << r.reserved5 << "\n"; 9432 outs() << " reserved6 " << r.reserved6 << "\n"; 9433 } 9434 9435 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 9436 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 9437 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 9438 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 9439 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 9440 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 9441 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 9442 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 9443 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 9444 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 9445 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 9446 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 9447 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 9448 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 9449 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 9450 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 9451 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 9452 } 9453 9454 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 9455 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 9456 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 9457 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 9458 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 9459 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 9460 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 9461 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 9462 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 9463 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 9464 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 9465 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 9466 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 9467 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 9468 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 9469 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 9470 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 9471 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 9472 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 9473 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 9474 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 9475 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 9476 } 9477 9478 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 9479 uint32_t f; 9480 outs() << "\t mmst_reg "; 9481 for (f = 0; f < 10; f++) 9482 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 9483 outs() << "\n"; 9484 outs() << "\t mmst_rsrv "; 9485 for (f = 0; f < 6; f++) 9486 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 9487 outs() << "\n"; 9488 } 9489 9490 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 9491 uint32_t f; 9492 outs() << "\t xmm_reg "; 9493 for (f = 0; f < 16; f++) 9494 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 9495 outs() << "\n"; 9496 } 9497 9498 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 9499 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 9500 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 9501 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 9502 outs() << " denorm " << fpu.fpu_fcw.denorm; 9503 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 9504 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 9505 outs() << " undfl " << fpu.fpu_fcw.undfl; 9506 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 9507 outs() << "\t\t pc "; 9508 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 9509 outs() << "FP_PREC_24B "; 9510 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 9511 outs() << "FP_PREC_53B "; 9512 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 9513 outs() << "FP_PREC_64B "; 9514 else 9515 outs() << fpu.fpu_fcw.pc << " "; 9516 outs() << "rc "; 9517 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 9518 outs() << "FP_RND_NEAR "; 9519 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 9520 outs() << "FP_RND_DOWN "; 9521 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 9522 outs() << "FP_RND_UP "; 9523 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 9524 outs() << "FP_CHOP "; 9525 outs() << "\n"; 9526 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 9527 outs() << " denorm " << fpu.fpu_fsw.denorm; 9528 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 9529 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 9530 outs() << " undfl " << fpu.fpu_fsw.undfl; 9531 outs() << " precis " << fpu.fpu_fsw.precis; 9532 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 9533 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9534 outs() << " c0 " << fpu.fpu_fsw.c0; 9535 outs() << " c1 " << fpu.fpu_fsw.c1; 9536 outs() << " c2 " << fpu.fpu_fsw.c2; 9537 outs() << " tos " << fpu.fpu_fsw.tos; 9538 outs() << " c3 " << fpu.fpu_fsw.c3; 9539 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9540 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9541 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9542 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9543 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9544 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9545 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9546 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9547 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9548 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9549 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9550 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9551 outs() << "\n"; 9552 outs() << "\t fpu_stmm0:\n"; 9553 Print_mmst_reg(fpu.fpu_stmm0); 9554 outs() << "\t fpu_stmm1:\n"; 9555 Print_mmst_reg(fpu.fpu_stmm1); 9556 outs() << "\t fpu_stmm2:\n"; 9557 Print_mmst_reg(fpu.fpu_stmm2); 9558 outs() << "\t fpu_stmm3:\n"; 9559 Print_mmst_reg(fpu.fpu_stmm3); 9560 outs() << "\t fpu_stmm4:\n"; 9561 Print_mmst_reg(fpu.fpu_stmm4); 9562 outs() << "\t fpu_stmm5:\n"; 9563 Print_mmst_reg(fpu.fpu_stmm5); 9564 outs() << "\t fpu_stmm6:\n"; 9565 Print_mmst_reg(fpu.fpu_stmm6); 9566 outs() << "\t fpu_stmm7:\n"; 9567 Print_mmst_reg(fpu.fpu_stmm7); 9568 outs() << "\t fpu_xmm0:\n"; 9569 Print_xmm_reg(fpu.fpu_xmm0); 9570 outs() << "\t fpu_xmm1:\n"; 9571 Print_xmm_reg(fpu.fpu_xmm1); 9572 outs() << "\t fpu_xmm2:\n"; 9573 Print_xmm_reg(fpu.fpu_xmm2); 9574 outs() << "\t fpu_xmm3:\n"; 9575 Print_xmm_reg(fpu.fpu_xmm3); 9576 outs() << "\t fpu_xmm4:\n"; 9577 Print_xmm_reg(fpu.fpu_xmm4); 9578 outs() << "\t fpu_xmm5:\n"; 9579 Print_xmm_reg(fpu.fpu_xmm5); 9580 outs() << "\t fpu_xmm6:\n"; 9581 Print_xmm_reg(fpu.fpu_xmm6); 9582 outs() << "\t fpu_xmm7:\n"; 9583 Print_xmm_reg(fpu.fpu_xmm7); 9584 outs() << "\t fpu_xmm8:\n"; 9585 Print_xmm_reg(fpu.fpu_xmm8); 9586 outs() << "\t fpu_xmm9:\n"; 9587 Print_xmm_reg(fpu.fpu_xmm9); 9588 outs() << "\t fpu_xmm10:\n"; 9589 Print_xmm_reg(fpu.fpu_xmm10); 9590 outs() << "\t fpu_xmm11:\n"; 9591 Print_xmm_reg(fpu.fpu_xmm11); 9592 outs() << "\t fpu_xmm12:\n"; 9593 Print_xmm_reg(fpu.fpu_xmm12); 9594 outs() << "\t fpu_xmm13:\n"; 9595 Print_xmm_reg(fpu.fpu_xmm13); 9596 outs() << "\t fpu_xmm14:\n"; 9597 Print_xmm_reg(fpu.fpu_xmm14); 9598 outs() << "\t fpu_xmm15:\n"; 9599 Print_xmm_reg(fpu.fpu_xmm15); 9600 outs() << "\t fpu_rsrv4:\n"; 9601 for (uint32_t f = 0; f < 6; f++) { 9602 outs() << "\t "; 9603 for (uint32_t g = 0; g < 16; g++) 9604 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9605 outs() << "\n"; 9606 } 9607 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9608 outs() << "\n"; 9609 } 9610 9611 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9612 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9613 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9614 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9615 } 9616 9617 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9618 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9619 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9620 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9621 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9622 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9623 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9624 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9625 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9626 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9627 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9628 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9629 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9630 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9631 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9632 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9633 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9634 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9635 } 9636 9637 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9638 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9639 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9640 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9641 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9642 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9643 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9644 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9645 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9646 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9647 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9648 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9649 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9650 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9651 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9652 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9653 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9654 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9655 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9656 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9657 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9658 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9659 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9660 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9661 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9662 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9663 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9664 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9665 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9666 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9667 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9668 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9669 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9670 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9671 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9672 } 9673 9674 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9675 bool isLittleEndian, uint32_t cputype) { 9676 if (t.cmd == MachO::LC_THREAD) 9677 outs() << " cmd LC_THREAD\n"; 9678 else if (t.cmd == MachO::LC_UNIXTHREAD) 9679 outs() << " cmd LC_UNIXTHREAD\n"; 9680 else 9681 outs() << " cmd " << t.cmd << " (unknown)\n"; 9682 outs() << " cmdsize " << t.cmdsize; 9683 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9684 outs() << " Incorrect size\n"; 9685 else 9686 outs() << "\n"; 9687 9688 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9689 const char *end = Ptr + t.cmdsize; 9690 uint32_t flavor, count, left; 9691 if (cputype == MachO::CPU_TYPE_I386) { 9692 while (begin < end) { 9693 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9694 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9695 begin += sizeof(uint32_t); 9696 } else { 9697 flavor = 0; 9698 begin = end; 9699 } 9700 if (isLittleEndian != sys::IsLittleEndianHost) 9701 sys::swapByteOrder(flavor); 9702 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9703 memcpy((char *)&count, begin, sizeof(uint32_t)); 9704 begin += sizeof(uint32_t); 9705 } else { 9706 count = 0; 9707 begin = end; 9708 } 9709 if (isLittleEndian != sys::IsLittleEndianHost) 9710 sys::swapByteOrder(count); 9711 if (flavor == MachO::x86_THREAD_STATE32) { 9712 outs() << " flavor i386_THREAD_STATE\n"; 9713 if (count == MachO::x86_THREAD_STATE32_COUNT) 9714 outs() << " count i386_THREAD_STATE_COUNT\n"; 9715 else 9716 outs() << " count " << count 9717 << " (not x86_THREAD_STATE32_COUNT)\n"; 9718 MachO::x86_thread_state32_t cpu32; 9719 left = end - begin; 9720 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9721 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9722 begin += sizeof(MachO::x86_thread_state32_t); 9723 } else { 9724 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9725 memcpy(&cpu32, begin, left); 9726 begin += left; 9727 } 9728 if (isLittleEndian != sys::IsLittleEndianHost) 9729 swapStruct(cpu32); 9730 Print_x86_thread_state32_t(cpu32); 9731 } else if (flavor == MachO::x86_THREAD_STATE) { 9732 outs() << " flavor x86_THREAD_STATE\n"; 9733 if (count == MachO::x86_THREAD_STATE_COUNT) 9734 outs() << " count x86_THREAD_STATE_COUNT\n"; 9735 else 9736 outs() << " count " << count 9737 << " (not x86_THREAD_STATE_COUNT)\n"; 9738 struct MachO::x86_thread_state_t ts; 9739 left = end - begin; 9740 if (left >= sizeof(MachO::x86_thread_state_t)) { 9741 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9742 begin += sizeof(MachO::x86_thread_state_t); 9743 } else { 9744 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9745 memcpy(&ts, begin, left); 9746 begin += left; 9747 } 9748 if (isLittleEndian != sys::IsLittleEndianHost) 9749 swapStruct(ts); 9750 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9751 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9752 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9753 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9754 else 9755 outs() << "tsh.count " << ts.tsh.count 9756 << " (not x86_THREAD_STATE32_COUNT\n"; 9757 Print_x86_thread_state32_t(ts.uts.ts32); 9758 } else { 9759 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9760 << ts.tsh.count << "\n"; 9761 } 9762 } else { 9763 outs() << " flavor " << flavor << " (unknown)\n"; 9764 outs() << " count " << count << "\n"; 9765 outs() << " state (unknown)\n"; 9766 begin += count * sizeof(uint32_t); 9767 } 9768 } 9769 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9770 while (begin < end) { 9771 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9772 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9773 begin += sizeof(uint32_t); 9774 } else { 9775 flavor = 0; 9776 begin = end; 9777 } 9778 if (isLittleEndian != sys::IsLittleEndianHost) 9779 sys::swapByteOrder(flavor); 9780 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9781 memcpy((char *)&count, begin, sizeof(uint32_t)); 9782 begin += sizeof(uint32_t); 9783 } else { 9784 count = 0; 9785 begin = end; 9786 } 9787 if (isLittleEndian != sys::IsLittleEndianHost) 9788 sys::swapByteOrder(count); 9789 if (flavor == MachO::x86_THREAD_STATE64) { 9790 outs() << " flavor x86_THREAD_STATE64\n"; 9791 if (count == MachO::x86_THREAD_STATE64_COUNT) 9792 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9793 else 9794 outs() << " count " << count 9795 << " (not x86_THREAD_STATE64_COUNT)\n"; 9796 MachO::x86_thread_state64_t cpu64; 9797 left = end - begin; 9798 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9799 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9800 begin += sizeof(MachO::x86_thread_state64_t); 9801 } else { 9802 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9803 memcpy(&cpu64, begin, left); 9804 begin += left; 9805 } 9806 if (isLittleEndian != sys::IsLittleEndianHost) 9807 swapStruct(cpu64); 9808 Print_x86_thread_state64_t(cpu64); 9809 } else if (flavor == MachO::x86_THREAD_STATE) { 9810 outs() << " flavor x86_THREAD_STATE\n"; 9811 if (count == MachO::x86_THREAD_STATE_COUNT) 9812 outs() << " count x86_THREAD_STATE_COUNT\n"; 9813 else 9814 outs() << " count " << count 9815 << " (not x86_THREAD_STATE_COUNT)\n"; 9816 struct MachO::x86_thread_state_t ts; 9817 left = end - begin; 9818 if (left >= sizeof(MachO::x86_thread_state_t)) { 9819 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9820 begin += sizeof(MachO::x86_thread_state_t); 9821 } else { 9822 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9823 memcpy(&ts, begin, left); 9824 begin += left; 9825 } 9826 if (isLittleEndian != sys::IsLittleEndianHost) 9827 swapStruct(ts); 9828 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9829 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9830 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9831 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9832 else 9833 outs() << "tsh.count " << ts.tsh.count 9834 << " (not x86_THREAD_STATE64_COUNT\n"; 9835 Print_x86_thread_state64_t(ts.uts.ts64); 9836 } else { 9837 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9838 << ts.tsh.count << "\n"; 9839 } 9840 } else if (flavor == MachO::x86_FLOAT_STATE) { 9841 outs() << " flavor x86_FLOAT_STATE\n"; 9842 if (count == MachO::x86_FLOAT_STATE_COUNT) 9843 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9844 else 9845 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9846 struct MachO::x86_float_state_t fs; 9847 left = end - begin; 9848 if (left >= sizeof(MachO::x86_float_state_t)) { 9849 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9850 begin += sizeof(MachO::x86_float_state_t); 9851 } else { 9852 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9853 memcpy(&fs, begin, left); 9854 begin += left; 9855 } 9856 if (isLittleEndian != sys::IsLittleEndianHost) 9857 swapStruct(fs); 9858 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9859 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9860 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9861 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9862 else 9863 outs() << "fsh.count " << fs.fsh.count 9864 << " (not x86_FLOAT_STATE64_COUNT\n"; 9865 Print_x86_float_state_t(fs.ufs.fs64); 9866 } else { 9867 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9868 << fs.fsh.count << "\n"; 9869 } 9870 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9871 outs() << " flavor x86_EXCEPTION_STATE\n"; 9872 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9873 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9874 else 9875 outs() << " count " << count 9876 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9877 struct MachO::x86_exception_state_t es; 9878 left = end - begin; 9879 if (left >= sizeof(MachO::x86_exception_state_t)) { 9880 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9881 begin += sizeof(MachO::x86_exception_state_t); 9882 } else { 9883 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9884 memcpy(&es, begin, left); 9885 begin += left; 9886 } 9887 if (isLittleEndian != sys::IsLittleEndianHost) 9888 swapStruct(es); 9889 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9890 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9891 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9892 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9893 else 9894 outs() << "\t esh.count " << es.esh.count 9895 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9896 Print_x86_exception_state_t(es.ues.es64); 9897 } else { 9898 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9899 << es.esh.count << "\n"; 9900 } 9901 } else if (flavor == MachO::x86_EXCEPTION_STATE64) { 9902 outs() << " flavor x86_EXCEPTION_STATE64\n"; 9903 if (count == MachO::x86_EXCEPTION_STATE64_COUNT) 9904 outs() << " count x86_EXCEPTION_STATE64_COUNT\n"; 9905 else 9906 outs() << " count " << count 9907 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; 9908 struct MachO::x86_exception_state64_t es64; 9909 left = end - begin; 9910 if (left >= sizeof(MachO::x86_exception_state64_t)) { 9911 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); 9912 begin += sizeof(MachO::x86_exception_state64_t); 9913 } else { 9914 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); 9915 memcpy(&es64, begin, left); 9916 begin += left; 9917 } 9918 if (isLittleEndian != sys::IsLittleEndianHost) 9919 swapStruct(es64); 9920 Print_x86_exception_state_t(es64); 9921 } else { 9922 outs() << " flavor " << flavor << " (unknown)\n"; 9923 outs() << " count " << count << "\n"; 9924 outs() << " state (unknown)\n"; 9925 begin += count * sizeof(uint32_t); 9926 } 9927 } 9928 } else if (cputype == MachO::CPU_TYPE_ARM) { 9929 while (begin < end) { 9930 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9931 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9932 begin += sizeof(uint32_t); 9933 } else { 9934 flavor = 0; 9935 begin = end; 9936 } 9937 if (isLittleEndian != sys::IsLittleEndianHost) 9938 sys::swapByteOrder(flavor); 9939 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9940 memcpy((char *)&count, begin, sizeof(uint32_t)); 9941 begin += sizeof(uint32_t); 9942 } else { 9943 count = 0; 9944 begin = end; 9945 } 9946 if (isLittleEndian != sys::IsLittleEndianHost) 9947 sys::swapByteOrder(count); 9948 if (flavor == MachO::ARM_THREAD_STATE) { 9949 outs() << " flavor ARM_THREAD_STATE\n"; 9950 if (count == MachO::ARM_THREAD_STATE_COUNT) 9951 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9952 else 9953 outs() << " count " << count 9954 << " (not ARM_THREAD_STATE_COUNT)\n"; 9955 MachO::arm_thread_state32_t cpu32; 9956 left = end - begin; 9957 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9958 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9959 begin += sizeof(MachO::arm_thread_state32_t); 9960 } else { 9961 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9962 memcpy(&cpu32, begin, left); 9963 begin += left; 9964 } 9965 if (isLittleEndian != sys::IsLittleEndianHost) 9966 swapStruct(cpu32); 9967 Print_arm_thread_state32_t(cpu32); 9968 } else { 9969 outs() << " flavor " << flavor << " (unknown)\n"; 9970 outs() << " count " << count << "\n"; 9971 outs() << " state (unknown)\n"; 9972 begin += count * sizeof(uint32_t); 9973 } 9974 } 9975 } else if (cputype == MachO::CPU_TYPE_ARM64 || 9976 cputype == MachO::CPU_TYPE_ARM64_32) { 9977 while (begin < end) { 9978 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9979 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9980 begin += sizeof(uint32_t); 9981 } else { 9982 flavor = 0; 9983 begin = end; 9984 } 9985 if (isLittleEndian != sys::IsLittleEndianHost) 9986 sys::swapByteOrder(flavor); 9987 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9988 memcpy((char *)&count, begin, sizeof(uint32_t)); 9989 begin += sizeof(uint32_t); 9990 } else { 9991 count = 0; 9992 begin = end; 9993 } 9994 if (isLittleEndian != sys::IsLittleEndianHost) 9995 sys::swapByteOrder(count); 9996 if (flavor == MachO::ARM_THREAD_STATE64) { 9997 outs() << " flavor ARM_THREAD_STATE64\n"; 9998 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9999 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 10000 else 10001 outs() << " count " << count 10002 << " (not ARM_THREAD_STATE64_COUNT)\n"; 10003 MachO::arm_thread_state64_t cpu64; 10004 left = end - begin; 10005 if (left >= sizeof(MachO::arm_thread_state64_t)) { 10006 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 10007 begin += sizeof(MachO::arm_thread_state64_t); 10008 } else { 10009 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 10010 memcpy(&cpu64, begin, left); 10011 begin += left; 10012 } 10013 if (isLittleEndian != sys::IsLittleEndianHost) 10014 swapStruct(cpu64); 10015 Print_arm_thread_state64_t(cpu64); 10016 } else { 10017 outs() << " flavor " << flavor << " (unknown)\n"; 10018 outs() << " count " << count << "\n"; 10019 outs() << " state (unknown)\n"; 10020 begin += count * sizeof(uint32_t); 10021 } 10022 } 10023 } else { 10024 while (begin < end) { 10025 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 10026 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 10027 begin += sizeof(uint32_t); 10028 } else { 10029 flavor = 0; 10030 begin = end; 10031 } 10032 if (isLittleEndian != sys::IsLittleEndianHost) 10033 sys::swapByteOrder(flavor); 10034 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 10035 memcpy((char *)&count, begin, sizeof(uint32_t)); 10036 begin += sizeof(uint32_t); 10037 } else { 10038 count = 0; 10039 begin = end; 10040 } 10041 if (isLittleEndian != sys::IsLittleEndianHost) 10042 sys::swapByteOrder(count); 10043 outs() << " flavor " << flavor << "\n"; 10044 outs() << " count " << count << "\n"; 10045 outs() << " state (Unknown cputype/cpusubtype)\n"; 10046 begin += count * sizeof(uint32_t); 10047 } 10048 } 10049 } 10050 10051 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 10052 if (dl.cmd == MachO::LC_ID_DYLIB) 10053 outs() << " cmd LC_ID_DYLIB\n"; 10054 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 10055 outs() << " cmd LC_LOAD_DYLIB\n"; 10056 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 10057 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 10058 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 10059 outs() << " cmd LC_REEXPORT_DYLIB\n"; 10060 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 10061 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 10062 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 10063 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 10064 else 10065 outs() << " cmd " << dl.cmd << " (unknown)\n"; 10066 outs() << " cmdsize " << dl.cmdsize; 10067 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 10068 outs() << " Incorrect size\n"; 10069 else 10070 outs() << "\n"; 10071 if (dl.dylib.name < dl.cmdsize) { 10072 const char *P = (const char *)(Ptr) + dl.dylib.name; 10073 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 10074 } else { 10075 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 10076 } 10077 outs() << " time stamp " << dl.dylib.timestamp << " "; 10078 time_t t = dl.dylib.timestamp; 10079 outs() << ctime(&t); 10080 outs() << " current version "; 10081 if (dl.dylib.current_version == 0xffffffff) 10082 outs() << "n/a\n"; 10083 else 10084 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 10085 << ((dl.dylib.current_version >> 8) & 0xff) << "." 10086 << (dl.dylib.current_version & 0xff) << "\n"; 10087 outs() << "compatibility version "; 10088 if (dl.dylib.compatibility_version == 0xffffffff) 10089 outs() << "n/a\n"; 10090 else 10091 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 10092 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 10093 << (dl.dylib.compatibility_version & 0xff) << "\n"; 10094 } 10095 10096 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 10097 uint32_t object_size) { 10098 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 10099 outs() << " cmd LC_CODE_SIGNATURE\n"; 10100 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 10101 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 10102 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 10103 outs() << " cmd LC_FUNCTION_STARTS\n"; 10104 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 10105 outs() << " cmd LC_DATA_IN_CODE\n"; 10106 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 10107 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 10108 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 10109 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 10110 else 10111 outs() << " cmd " << ld.cmd << " (?)\n"; 10112 outs() << " cmdsize " << ld.cmdsize; 10113 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 10114 outs() << " Incorrect size\n"; 10115 else 10116 outs() << "\n"; 10117 outs() << " dataoff " << ld.dataoff; 10118 if (ld.dataoff > object_size) 10119 outs() << " (past end of file)\n"; 10120 else 10121 outs() << "\n"; 10122 outs() << " datasize " << ld.datasize; 10123 uint64_t big_size = ld.dataoff; 10124 big_size += ld.datasize; 10125 if (big_size > object_size) 10126 outs() << " (past end of file)\n"; 10127 else 10128 outs() << "\n"; 10129 } 10130 10131 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 10132 uint32_t cputype, bool verbose) { 10133 StringRef Buf = Obj->getData(); 10134 unsigned Index = 0; 10135 for (const auto &Command : Obj->load_commands()) { 10136 outs() << "Load command " << Index++ << "\n"; 10137 if (Command.C.cmd == MachO::LC_SEGMENT) { 10138 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 10139 const char *sg_segname = SLC.segname; 10140 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 10141 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 10142 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 10143 verbose); 10144 for (unsigned j = 0; j < SLC.nsects; j++) { 10145 MachO::section S = Obj->getSection(Command, j); 10146 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 10147 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 10148 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 10149 } 10150 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10151 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 10152 const char *sg_segname = SLC_64.segname; 10153 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 10154 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 10155 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 10156 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 10157 for (unsigned j = 0; j < SLC_64.nsects; j++) { 10158 MachO::section_64 S_64 = Obj->getSection64(Command, j); 10159 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 10160 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 10161 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 10162 sg_segname, filetype, Buf.size(), verbose); 10163 } 10164 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 10165 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10166 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 10167 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 10168 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 10169 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10170 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 10171 Obj->is64Bit()); 10172 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 10173 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 10174 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 10175 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 10176 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 10177 Command.C.cmd == MachO::LC_ID_DYLINKER || 10178 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 10179 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 10180 PrintDyldLoadCommand(Dyld, Command.Ptr); 10181 } else if (Command.C.cmd == MachO::LC_UUID) { 10182 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 10183 PrintUuidLoadCommand(Uuid); 10184 } else if (Command.C.cmd == MachO::LC_RPATH) { 10185 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 10186 PrintRpathLoadCommand(Rpath, Command.Ptr); 10187 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 10188 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 10189 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 10190 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 10191 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 10192 PrintVersionMinLoadCommand(Vd); 10193 } else if (Command.C.cmd == MachO::LC_NOTE) { 10194 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 10195 PrintNoteLoadCommand(Nt); 10196 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 10197 MachO::build_version_command Bv = 10198 Obj->getBuildVersionLoadCommand(Command); 10199 PrintBuildVersionLoadCommand(Obj, Bv); 10200 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 10201 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 10202 PrintSourceVersionCommand(Sd); 10203 } else if (Command.C.cmd == MachO::LC_MAIN) { 10204 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 10205 PrintEntryPointCommand(Ep); 10206 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 10207 MachO::encryption_info_command Ei = 10208 Obj->getEncryptionInfoCommand(Command); 10209 PrintEncryptionInfoCommand(Ei, Buf.size()); 10210 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 10211 MachO::encryption_info_command_64 Ei = 10212 Obj->getEncryptionInfoCommand64(Command); 10213 PrintEncryptionInfoCommand64(Ei, Buf.size()); 10214 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 10215 MachO::linker_option_command Lo = 10216 Obj->getLinkerOptionLoadCommand(Command); 10217 PrintLinkerOptionCommand(Lo, Command.Ptr); 10218 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 10219 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 10220 PrintSubFrameworkCommand(Sf, Command.Ptr); 10221 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 10222 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 10223 PrintSubUmbrellaCommand(Sf, Command.Ptr); 10224 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 10225 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 10226 PrintSubLibraryCommand(Sl, Command.Ptr); 10227 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 10228 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 10229 PrintSubClientCommand(Sc, Command.Ptr); 10230 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 10231 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 10232 PrintRoutinesCommand(Rc); 10233 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 10234 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 10235 PrintRoutinesCommand64(Rc); 10236 } else if (Command.C.cmd == MachO::LC_THREAD || 10237 Command.C.cmd == MachO::LC_UNIXTHREAD) { 10238 MachO::thread_command Tc = Obj->getThreadCommand(Command); 10239 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 10240 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 10241 Command.C.cmd == MachO::LC_ID_DYLIB || 10242 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 10243 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 10244 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 10245 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 10246 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 10247 PrintDylibCommand(Dl, Command.Ptr); 10248 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 10249 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 10250 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 10251 Command.C.cmd == MachO::LC_DATA_IN_CODE || 10252 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 10253 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 10254 MachO::linkedit_data_command Ld = 10255 Obj->getLinkeditDataLoadCommand(Command); 10256 PrintLinkEditDataCommand(Ld, Buf.size()); 10257 } else { 10258 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 10259 << ")\n"; 10260 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 10261 // TODO: get and print the raw bytes of the load command. 10262 } 10263 // TODO: print all the other kinds of load commands. 10264 } 10265 } 10266 10267 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 10268 if (Obj->is64Bit()) { 10269 MachO::mach_header_64 H_64; 10270 H_64 = Obj->getHeader64(); 10271 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 10272 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 10273 } else { 10274 MachO::mach_header H; 10275 H = Obj->getHeader(); 10276 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 10277 H.sizeofcmds, H.flags, verbose); 10278 } 10279 } 10280 10281 void objdump::printMachOFileHeader(const object::ObjectFile *Obj) { 10282 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 10283 PrintMachHeader(file, !NonVerbose); 10284 } 10285 10286 void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) { 10287 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 10288 uint32_t filetype = 0; 10289 uint32_t cputype = 0; 10290 if (file->is64Bit()) { 10291 MachO::mach_header_64 H_64; 10292 H_64 = file->getHeader64(); 10293 filetype = H_64.filetype; 10294 cputype = H_64.cputype; 10295 } else { 10296 MachO::mach_header H; 10297 H = file->getHeader(); 10298 filetype = H.filetype; 10299 cputype = H.cputype; 10300 } 10301 PrintLoadCommands(file, filetype, cputype, !NonVerbose); 10302 } 10303 10304 //===----------------------------------------------------------------------===// 10305 // export trie dumping 10306 //===----------------------------------------------------------------------===// 10307 10308 static void printMachOExportsTrie(const object::MachOObjectFile *Obj) { 10309 uint64_t BaseSegmentAddress = 0; 10310 for (const auto &Command : Obj->load_commands()) { 10311 if (Command.C.cmd == MachO::LC_SEGMENT) { 10312 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 10313 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10314 BaseSegmentAddress = Seg.vmaddr; 10315 break; 10316 } 10317 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10318 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 10319 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10320 BaseSegmentAddress = Seg.vmaddr; 10321 break; 10322 } 10323 } 10324 } 10325 Error Err = Error::success(); 10326 for (const object::ExportEntry &Entry : Obj->exports(Err)) { 10327 uint64_t Flags = Entry.flags(); 10328 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 10329 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 10330 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10331 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 10332 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10333 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 10334 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 10335 if (ReExport) 10336 outs() << "[re-export] "; 10337 else 10338 outs() << format("0x%08llX ", 10339 Entry.address() + BaseSegmentAddress); 10340 outs() << Entry.name(); 10341 if (WeakDef || ThreadLocal || Resolver || Abs) { 10342 ListSeparator LS; 10343 outs() << " ["; 10344 if (WeakDef) 10345 outs() << LS << "weak_def"; 10346 if (ThreadLocal) 10347 outs() << LS << "per-thread"; 10348 if (Abs) 10349 outs() << LS << "absolute"; 10350 if (Resolver) 10351 outs() << LS << format("resolver=0x%08llX", Entry.other()); 10352 outs() << "]"; 10353 } 10354 if (ReExport) { 10355 StringRef DylibName = "unknown"; 10356 int Ordinal = Entry.other() - 1; 10357 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 10358 if (Entry.otherName().empty()) 10359 outs() << " (from " << DylibName << ")"; 10360 else 10361 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 10362 } 10363 outs() << "\n"; 10364 } 10365 if (Err) 10366 reportError(std::move(Err), Obj->getFileName()); 10367 } 10368 10369 //===----------------------------------------------------------------------===// 10370 // rebase table dumping 10371 //===----------------------------------------------------------------------===// 10372 10373 static void printMachORebaseTable(object::MachOObjectFile *Obj) { 10374 outs() << "segment section address type\n"; 10375 Error Err = Error::success(); 10376 for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 10377 StringRef SegmentName = Entry.segmentName(); 10378 StringRef SectionName = Entry.sectionName(); 10379 uint64_t Address = Entry.address(); 10380 10381 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 10382 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 10383 SegmentName.str().c_str(), SectionName.str().c_str(), 10384 Address, Entry.typeName().str().c_str()); 10385 } 10386 if (Err) 10387 reportError(std::move(Err), Obj->getFileName()); 10388 } 10389 10390 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 10391 StringRef DylibName; 10392 switch (Ordinal) { 10393 case MachO::BIND_SPECIAL_DYLIB_SELF: 10394 return "this-image"; 10395 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 10396 return "main-executable"; 10397 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 10398 return "flat-namespace"; 10399 default: 10400 if (Ordinal > 0) { 10401 std::error_code EC = 10402 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 10403 if (EC) 10404 return "<<bad library ordinal>>"; 10405 return DylibName; 10406 } 10407 } 10408 return "<<unknown special ordinal>>"; 10409 } 10410 10411 //===----------------------------------------------------------------------===// 10412 // bind table dumping 10413 //===----------------------------------------------------------------------===// 10414 10415 static void printMachOBindTable(object::MachOObjectFile *Obj) { 10416 // Build table of sections so names can used in final output. 10417 outs() << "segment section address type " 10418 "addend dylib symbol\n"; 10419 Error Err = Error::success(); 10420 for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 10421 StringRef SegmentName = Entry.segmentName(); 10422 StringRef SectionName = Entry.sectionName(); 10423 uint64_t Address = Entry.address(); 10424 10425 // Table lines look like: 10426 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 10427 StringRef Attr; 10428 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 10429 Attr = " (weak_import)"; 10430 outs() << left_justify(SegmentName, 8) << " " 10431 << left_justify(SectionName, 18) << " " 10432 << format_hex(Address, 10, true) << " " 10433 << left_justify(Entry.typeName(), 8) << " " 10434 << format_decimal(Entry.addend(), 8) << " " 10435 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10436 << Entry.symbolName() << Attr << "\n"; 10437 } 10438 if (Err) 10439 reportError(std::move(Err), Obj->getFileName()); 10440 } 10441 10442 //===----------------------------------------------------------------------===// 10443 // lazy bind table dumping 10444 //===----------------------------------------------------------------------===// 10445 10446 static void printMachOLazyBindTable(object::MachOObjectFile *Obj) { 10447 outs() << "segment section address " 10448 "dylib symbol\n"; 10449 Error Err = Error::success(); 10450 for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 10451 StringRef SegmentName = Entry.segmentName(); 10452 StringRef SectionName = Entry.sectionName(); 10453 uint64_t Address = Entry.address(); 10454 10455 // Table lines look like: 10456 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 10457 outs() << left_justify(SegmentName, 8) << " " 10458 << left_justify(SectionName, 18) << " " 10459 << format_hex(Address, 10, true) << " " 10460 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10461 << Entry.symbolName() << "\n"; 10462 } 10463 if (Err) 10464 reportError(std::move(Err), Obj->getFileName()); 10465 } 10466 10467 //===----------------------------------------------------------------------===// 10468 // weak bind table dumping 10469 //===----------------------------------------------------------------------===// 10470 10471 static void printMachOWeakBindTable(object::MachOObjectFile *Obj) { 10472 outs() << "segment section address " 10473 "type addend symbol\n"; 10474 Error Err = Error::success(); 10475 for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 10476 // Strong symbols don't have a location to update. 10477 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 10478 outs() << " strong " 10479 << Entry.symbolName() << "\n"; 10480 continue; 10481 } 10482 StringRef SegmentName = Entry.segmentName(); 10483 StringRef SectionName = Entry.sectionName(); 10484 uint64_t Address = Entry.address(); 10485 10486 // Table lines look like: 10487 // __DATA __data 0x00001000 pointer 0 _foo 10488 outs() << left_justify(SegmentName, 8) << " " 10489 << left_justify(SectionName, 18) << " " 10490 << format_hex(Address, 10, true) << " " 10491 << left_justify(Entry.typeName(), 8) << " " 10492 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 10493 << "\n"; 10494 } 10495 if (Err) 10496 reportError(std::move(Err), Obj->getFileName()); 10497 } 10498 10499 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 10500 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 10501 // information for that address. If the address is found its binding symbol 10502 // name is returned. If not nullptr is returned. 10503 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 10504 struct DisassembleInfo *info) { 10505 if (info->bindtable == nullptr) { 10506 info->bindtable = std::make_unique<SymbolAddressMap>(); 10507 Error Err = Error::success(); 10508 for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 10509 uint64_t Address = Entry.address(); 10510 StringRef name = Entry.symbolName(); 10511 if (!name.empty()) 10512 (*info->bindtable)[Address] = name; 10513 } 10514 if (Err) 10515 reportError(std::move(Err), info->O->getFileName()); 10516 } 10517 auto name = info->bindtable->lookup(ReferenceValue); 10518 return !name.empty() ? name.data() : nullptr; 10519 } 10520 10521 void objdump::printLazyBindTable(ObjectFile *o) { 10522 outs() << "Lazy bind table:\n"; 10523 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10524 printMachOLazyBindTable(MachO); 10525 else 10526 WithColor::error() 10527 << "This operation is only currently supported " 10528 "for Mach-O executable files.\n"; 10529 } 10530 10531 void objdump::printWeakBindTable(ObjectFile *o) { 10532 outs() << "Weak bind table:\n"; 10533 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10534 printMachOWeakBindTable(MachO); 10535 else 10536 WithColor::error() 10537 << "This operation is only currently supported " 10538 "for Mach-O executable files.\n"; 10539 } 10540 10541 void objdump::printExportsTrie(const ObjectFile *o) { 10542 outs() << "Exports trie:\n"; 10543 if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10544 printMachOExportsTrie(MachO); 10545 else 10546 WithColor::error() 10547 << "This operation is only currently supported " 10548 "for Mach-O executable files.\n"; 10549 } 10550 10551 void objdump::printRebaseTable(ObjectFile *o) { 10552 outs() << "Rebase table:\n"; 10553 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10554 printMachORebaseTable(MachO); 10555 else 10556 WithColor::error() 10557 << "This operation is only currently supported " 10558 "for Mach-O executable files.\n"; 10559 } 10560 10561 void objdump::printBindTable(ObjectFile *o) { 10562 outs() << "Bind table:\n"; 10563 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10564 printMachOBindTable(MachO); 10565 else 10566 WithColor::error() 10567 << "This operation is only currently supported " 10568 "for Mach-O executable files.\n"; 10569 } 10570