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 "llvm-objdump.h" 14 #include "llvm-c/Disassembler.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/ADT/Triple.h" 18 #include "llvm/BinaryFormat/MachO.h" 19 #include "llvm/Config/config.h" 20 #include "llvm/DebugInfo/DIContext.h" 21 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 22 #include "llvm/Demangle/Demangle.h" 23 #include "llvm/MC/MCAsmInfo.h" 24 #include "llvm/MC/MCContext.h" 25 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 26 #include "llvm/MC/MCInst.h" 27 #include "llvm/MC/MCInstPrinter.h" 28 #include "llvm/MC/MCInstrDesc.h" 29 #include "llvm/MC/MCInstrInfo.h" 30 #include "llvm/MC/MCRegisterInfo.h" 31 #include "llvm/MC/MCSubtargetInfo.h" 32 #include "llvm/Object/MachO.h" 33 #include "llvm/Object/MachOUniversal.h" 34 #include "llvm/Support/Casting.h" 35 #include "llvm/Support/CommandLine.h" 36 #include "llvm/Support/Debug.h" 37 #include "llvm/Support/Endian.h" 38 #include "llvm/Support/Format.h" 39 #include "llvm/Support/FormattedStream.h" 40 #include "llvm/Support/GraphWriter.h" 41 #include "llvm/Support/LEB128.h" 42 #include "llvm/Support/MemoryBuffer.h" 43 #include "llvm/Support/TargetRegistry.h" 44 #include "llvm/Support/TargetSelect.h" 45 #include "llvm/Support/ToolOutputFile.h" 46 #include "llvm/Support/WithColor.h" 47 #include "llvm/Support/raw_ostream.h" 48 #include <algorithm> 49 #include <cstring> 50 #include <system_error> 51 52 #ifdef HAVE_LIBXAR 53 extern "C" { 54 #include <xar/xar.h> 55 } 56 #endif 57 58 using namespace llvm::object; 59 60 namespace llvm { 61 62 cl::OptionCategory MachOCat("llvm-objdump MachO Specific Options"); 63 64 extern cl::opt<bool> ArchiveHeaders; 65 extern cl::opt<bool> Disassemble; 66 extern cl::opt<bool> DisassembleAll; 67 extern cl::opt<DIDumpType> DwarfDumpType; 68 extern cl::list<std::string> FilterSections; 69 extern cl::list<std::string> MAttrs; 70 extern cl::opt<std::string> MCPU; 71 extern cl::opt<bool> NoShowRawInsn; 72 extern cl::opt<bool> NoLeadingAddr; 73 extern cl::opt<bool> PrintImmHex; 74 extern cl::opt<bool> PrivateHeaders; 75 extern cl::opt<bool> Relocations; 76 extern cl::opt<bool> SectionHeaders; 77 extern cl::opt<bool> SectionContents; 78 extern cl::opt<bool> SymbolTable; 79 extern cl::opt<std::string> TripleName; 80 extern cl::opt<bool> UnwindInfo; 81 82 cl::opt<bool> 83 FirstPrivateHeader("private-header", 84 cl::desc("Display only the first format specific file " 85 "header"), 86 cl::cat(MachOCat)); 87 88 cl::opt<bool> ExportsTrie("exports-trie", 89 cl::desc("Display mach-o exported symbols"), 90 cl::cat(MachOCat)); 91 92 cl::opt<bool> Rebase("rebase", cl::desc("Display mach-o rebasing info"), 93 cl::cat(MachOCat)); 94 95 cl::opt<bool> Bind("bind", cl::desc("Display mach-o binding info"), 96 cl::cat(MachOCat)); 97 98 cl::opt<bool> LazyBind("lazy-bind", 99 cl::desc("Display mach-o lazy binding info"), 100 cl::cat(MachOCat)); 101 102 cl::opt<bool> WeakBind("weak-bind", 103 cl::desc("Display mach-o weak binding info"), 104 cl::cat(MachOCat)); 105 106 static cl::opt<bool> 107 UseDbg("g", cl::Grouping, 108 cl::desc("Print line information from debug info if available"), 109 cl::cat(MachOCat)); 110 111 static cl::opt<std::string> DSYMFile("dsym", 112 cl::desc("Use .dSYM file for debug info"), 113 cl::cat(MachOCat)); 114 115 static cl::opt<bool> FullLeadingAddr("full-leading-addr", 116 cl::desc("Print full leading address"), 117 cl::cat(MachOCat)); 118 119 static cl::opt<bool> NoLeadingHeaders("no-leading-headers", 120 cl::desc("Print no leading headers"), 121 cl::cat(MachOCat)); 122 123 cl::opt<bool> UniversalHeaders("universal-headers", 124 cl::desc("Print Mach-O universal headers " 125 "(requires -macho)"), 126 cl::cat(MachOCat)); 127 128 cl::opt<bool> 129 ArchiveMemberOffsets("archive-member-offsets", 130 cl::desc("Print the offset to each archive member for " 131 "Mach-O archives (requires -macho and " 132 "-archive-headers)"), 133 cl::cat(MachOCat)); 134 135 cl::opt<bool> IndirectSymbols("indirect-symbols", 136 cl::desc("Print indirect symbol table for Mach-O " 137 "objects (requires -macho)"), 138 cl::cat(MachOCat)); 139 140 cl::opt<bool> 141 DataInCode("data-in-code", 142 cl::desc("Print the data in code table for Mach-O objects " 143 "(requires -macho)"), 144 cl::cat(MachOCat)); 145 146 cl::opt<bool> LinkOptHints("link-opt-hints", 147 cl::desc("Print the linker optimization hints for " 148 "Mach-O objects (requires -macho)"), 149 cl::cat(MachOCat)); 150 151 cl::opt<bool> InfoPlist("info-plist", 152 cl::desc("Print the info plist section as strings for " 153 "Mach-O objects (requires -macho)"), 154 cl::cat(MachOCat)); 155 156 cl::opt<bool> DylibsUsed("dylibs-used", 157 cl::desc("Print the shared libraries used for linked " 158 "Mach-O files (requires -macho)"), 159 cl::cat(MachOCat)); 160 161 cl::opt<bool> 162 DylibId("dylib-id", 163 cl::desc("Print the shared library's id for the dylib Mach-O " 164 "file (requires -macho)"), 165 cl::cat(MachOCat)); 166 167 cl::opt<bool> 168 NonVerbose("non-verbose", 169 cl::desc("Print the info for Mach-O objects in " 170 "non-verbose or numeric form (requires -macho)"), 171 cl::cat(MachOCat)); 172 173 cl::opt<bool> 174 ObjcMetaData("objc-meta-data", 175 cl::desc("Print the Objective-C runtime meta data for " 176 "Mach-O files (requires -macho)"), 177 cl::cat(MachOCat)); 178 179 cl::opt<std::string> DisSymName( 180 "dis-symname", 181 cl::desc("disassemble just this symbol's instructions (requires -macho)"), 182 cl::cat(MachOCat)); 183 184 static cl::opt<bool> NoSymbolicOperands( 185 "no-symbolic-operands", 186 cl::desc("do not symbolic operands when disassembling (requires -macho)"), 187 cl::cat(MachOCat)); 188 189 static cl::list<std::string> 190 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 191 cl::ZeroOrMore, cl::cat(MachOCat)); 192 193 bool ArchAll = false; 194 195 static std::string ThumbTripleName; 196 197 static const Target *GetTarget(const MachOObjectFile *MachOObj, 198 const char **McpuDefault, 199 const Target **ThumbTarget) { 200 // Figure out the target triple. 201 Triple TT(TripleName); 202 if (TripleName.empty()) { 203 TT = MachOObj->getArchTriple(McpuDefault); 204 TripleName = TT.str(); 205 } 206 207 if (TT.getArch() == Triple::arm) { 208 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs 209 // that support ARM are also capable of Thumb mode. 210 Triple ThumbTriple = TT; 211 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str(); 212 ThumbTriple.setArchName(ThumbName); 213 ThumbTripleName = ThumbTriple.str(); 214 } 215 216 // Get the target specific parser. 217 std::string Error; 218 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 219 if (TheTarget && ThumbTripleName.empty()) 220 return TheTarget; 221 222 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 223 if (*ThumbTarget) 224 return TheTarget; 225 226 WithColor::error(errs(), "llvm-objdump") << "unable to get target for '"; 227 if (!TheTarget) 228 errs() << TripleName; 229 else 230 errs() << ThumbTripleName; 231 errs() << "', see --version and --triple.\n"; 232 return nullptr; 233 } 234 235 struct SymbolSorter { 236 bool operator()(const SymbolRef &A, const SymbolRef &B) { 237 Expected<SymbolRef::Type> ATypeOrErr = A.getType(); 238 if (!ATypeOrErr) 239 report_error(ATypeOrErr.takeError(), A.getObject()->getFileName()); 240 SymbolRef::Type AType = *ATypeOrErr; 241 Expected<SymbolRef::Type> BTypeOrErr = B.getType(); 242 if (!BTypeOrErr) 243 report_error(BTypeOrErr.takeError(), B.getObject()->getFileName()); 244 SymbolRef::Type BType = *BTypeOrErr; 245 uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue(); 246 uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue(); 247 return AAddr < BAddr; 248 } 249 }; 250 251 // Types for the storted data in code table that is built before disassembly 252 // and the predicate function to sort them. 253 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 254 typedef std::vector<DiceTableEntry> DiceTable; 255 typedef DiceTable::iterator dice_table_iterator; 256 257 #ifdef HAVE_LIBXAR 258 namespace { 259 struct ScopedXarFile { 260 xar_t xar; 261 ScopedXarFile(const char *filename, int32_t flags) 262 : xar(xar_open(filename, flags)) {} 263 ~ScopedXarFile() { 264 if (xar) 265 xar_close(xar); 266 } 267 ScopedXarFile(const ScopedXarFile &) = delete; 268 ScopedXarFile &operator=(const ScopedXarFile &) = delete; 269 operator xar_t() { return xar; } 270 }; 271 272 struct ScopedXarIter { 273 xar_iter_t iter; 274 ScopedXarIter() : iter(xar_iter_new()) {} 275 ~ScopedXarIter() { 276 if (iter) 277 xar_iter_free(iter); 278 } 279 ScopedXarIter(const ScopedXarIter &) = delete; 280 ScopedXarIter &operator=(const ScopedXarIter &) = delete; 281 operator xar_iter_t() { return iter; } 282 }; 283 } // namespace 284 #endif // defined(HAVE_LIBXAR) 285 286 // This is used to search for a data in code table entry for the PC being 287 // disassembled. The j parameter has the PC in j.first. A single data in code 288 // table entry can cover many bytes for each of its Kind's. So if the offset, 289 // aka the i.first value, of the data in code table entry plus its Length 290 // covers the PC being searched for this will return true. If not it will 291 // return false. 292 static bool compareDiceTableEntries(const DiceTableEntry &i, 293 const DiceTableEntry &j) { 294 uint16_t Length; 295 i.second.getLength(Length); 296 297 return j.first >= i.first && j.first < i.first + Length; 298 } 299 300 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 301 unsigned short Kind) { 302 uint32_t Value, Size = 1; 303 304 switch (Kind) { 305 default: 306 case MachO::DICE_KIND_DATA: 307 if (Length >= 4) { 308 if (!NoShowRawInsn) 309 dumpBytes(makeArrayRef(bytes, 4), outs()); 310 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 311 outs() << "\t.long " << Value; 312 Size = 4; 313 } else if (Length >= 2) { 314 if (!NoShowRawInsn) 315 dumpBytes(makeArrayRef(bytes, 2), outs()); 316 Value = bytes[1] << 8 | bytes[0]; 317 outs() << "\t.short " << Value; 318 Size = 2; 319 } else { 320 if (!NoShowRawInsn) 321 dumpBytes(makeArrayRef(bytes, 2), outs()); 322 Value = bytes[0]; 323 outs() << "\t.byte " << Value; 324 Size = 1; 325 } 326 if (Kind == MachO::DICE_KIND_DATA) 327 outs() << "\t@ KIND_DATA\n"; 328 else 329 outs() << "\t@ data in code kind = " << Kind << "\n"; 330 break; 331 case MachO::DICE_KIND_JUMP_TABLE8: 332 if (!NoShowRawInsn) 333 dumpBytes(makeArrayRef(bytes, 1), outs()); 334 Value = bytes[0]; 335 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 336 Size = 1; 337 break; 338 case MachO::DICE_KIND_JUMP_TABLE16: 339 if (!NoShowRawInsn) 340 dumpBytes(makeArrayRef(bytes, 2), outs()); 341 Value = bytes[1] << 8 | bytes[0]; 342 outs() << "\t.short " << format("%5u", Value & 0xffff) 343 << "\t@ KIND_JUMP_TABLE16\n"; 344 Size = 2; 345 break; 346 case MachO::DICE_KIND_JUMP_TABLE32: 347 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 348 if (!NoShowRawInsn) 349 dumpBytes(makeArrayRef(bytes, 4), outs()); 350 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 351 outs() << "\t.long " << Value; 352 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 353 outs() << "\t@ KIND_JUMP_TABLE32\n"; 354 else 355 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 356 Size = 4; 357 break; 358 } 359 return Size; 360 } 361 362 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 363 std::vector<SectionRef> &Sections, 364 std::vector<SymbolRef> &Symbols, 365 SmallVectorImpl<uint64_t> &FoundFns, 366 uint64_t &BaseSegmentAddress) { 367 const StringRef FileName = MachOObj->getFileName(); 368 for (const SymbolRef &Symbol : MachOObj->symbols()) { 369 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 370 if (!SymName.startswith("ltmp")) 371 Symbols.push_back(Symbol); 372 } 373 374 for (const SectionRef &Section : MachOObj->sections()) { 375 StringRef SectName; 376 Section.getName(SectName); 377 Sections.push_back(Section); 378 } 379 380 bool BaseSegmentAddressSet = false; 381 for (const auto &Command : MachOObj->load_commands()) { 382 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 383 // We found a function starts segment, parse the addresses for later 384 // consumption. 385 MachO::linkedit_data_command LLC = 386 MachOObj->getLinkeditDataLoadCommand(Command); 387 388 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 389 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 390 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(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 void printRelocationTargetName(const MachOObjectFile *O, 401 const MachO::any_relocation_info &RE, 402 raw_string_ostream &Fmt) { 403 // Target of a scattered relocation is an address. In the interest of 404 // generating pretty output, scan through the symbol table looking for a 405 // symbol that aligns with that address. If we find one, print it. 406 // Otherwise, we just print the hex address of the target. 407 const StringRef FileName = O->getFileName(); 408 if (O->isRelocationScattered(RE)) { 409 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 410 411 for (const SymbolRef &Symbol : O->symbols()) { 412 uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName); 413 if (Addr != Val) 414 continue; 415 Fmt << unwrapOrError(Symbol.getName(), FileName); 416 return; 417 } 418 419 // If we couldn't find a symbol that this relocation refers to, try 420 // to find a section beginning instead. 421 for (const SectionRef &Section : ToolSectionFilter(*O)) { 422 StringRef Name; 423 uint64_t Addr = Section.getAddress(); 424 if (Addr != Val) 425 continue; 426 if (std::error_code EC = Section.getName(Name)) 427 report_error(errorCodeToError(EC), O->getFileName()); 428 Fmt << Name; 429 return; 430 } 431 432 Fmt << format("0x%x", Val); 433 return; 434 } 435 436 StringRef S; 437 bool isExtern = O->getPlainRelocationExternal(RE); 438 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 439 440 if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND) { 441 Fmt << format("0x%0" PRIx64, Val); 442 return; 443 } 444 445 if (isExtern) { 446 symbol_iterator SI = O->symbol_begin(); 447 advance(SI, Val); 448 S = unwrapOrError(SI->getName(), FileName); 449 } else { 450 section_iterator SI = O->section_begin(); 451 // Adjust for the fact that sections are 1-indexed. 452 if (Val == 0) { 453 Fmt << "0 (?,?)"; 454 return; 455 } 456 uint32_t I = Val - 1; 457 while (I != 0 && SI != O->section_end()) { 458 --I; 459 advance(SI, 1); 460 } 461 if (SI == O->section_end()) 462 Fmt << Val << " (?,?)"; 463 else 464 SI->getName(S); 465 } 466 467 Fmt << S; 468 } 469 470 Error getMachORelocationValueString(const MachOObjectFile *Obj, 471 const RelocationRef &RelRef, 472 SmallVectorImpl<char> &Result) { 473 DataRefImpl Rel = RelRef.getRawDataRefImpl(); 474 MachO::any_relocation_info RE = Obj->getRelocation(Rel); 475 476 unsigned Arch = Obj->getArch(); 477 478 std::string FmtBuf; 479 raw_string_ostream Fmt(FmtBuf); 480 unsigned Type = Obj->getAnyRelocationType(RE); 481 bool IsPCRel = Obj->getAnyRelocationPCRel(RE); 482 483 // Determine any addends that should be displayed with the relocation. 484 // These require decoding the relocation type, which is triple-specific. 485 486 // X86_64 has entirely custom relocation types. 487 if (Arch == Triple::x86_64) { 488 switch (Type) { 489 case MachO::X86_64_RELOC_GOT_LOAD: 490 case MachO::X86_64_RELOC_GOT: { 491 printRelocationTargetName(Obj, RE, Fmt); 492 Fmt << "@GOT"; 493 if (IsPCRel) 494 Fmt << "PCREL"; 495 break; 496 } 497 case MachO::X86_64_RELOC_SUBTRACTOR: { 498 DataRefImpl RelNext = Rel; 499 Obj->moveRelocationNext(RelNext); 500 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 501 502 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 503 // X86_64_RELOC_UNSIGNED. 504 // NOTE: Scattered relocations don't exist on x86_64. 505 unsigned RType = Obj->getAnyRelocationType(RENext); 506 if (RType != MachO::X86_64_RELOC_UNSIGNED) 507 report_error(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after " 508 "X86_64_RELOC_SUBTRACTOR."); 509 510 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 511 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 512 printRelocationTargetName(Obj, RENext, Fmt); 513 Fmt << "-"; 514 printRelocationTargetName(Obj, RE, Fmt); 515 break; 516 } 517 case MachO::X86_64_RELOC_TLV: 518 printRelocationTargetName(Obj, RE, Fmt); 519 Fmt << "@TLV"; 520 if (IsPCRel) 521 Fmt << "P"; 522 break; 523 case MachO::X86_64_RELOC_SIGNED_1: 524 printRelocationTargetName(Obj, RE, Fmt); 525 Fmt << "-1"; 526 break; 527 case MachO::X86_64_RELOC_SIGNED_2: 528 printRelocationTargetName(Obj, RE, Fmt); 529 Fmt << "-2"; 530 break; 531 case MachO::X86_64_RELOC_SIGNED_4: 532 printRelocationTargetName(Obj, RE, Fmt); 533 Fmt << "-4"; 534 break; 535 default: 536 printRelocationTargetName(Obj, RE, Fmt); 537 break; 538 } 539 // X86 and ARM share some relocation types in common. 540 } else if (Arch == Triple::x86 || Arch == Triple::arm || 541 Arch == Triple::ppc) { 542 // Generic relocation types... 543 switch (Type) { 544 case MachO::GENERIC_RELOC_PAIR: // prints no info 545 return Error::success(); 546 case MachO::GENERIC_RELOC_SECTDIFF: { 547 DataRefImpl RelNext = Rel; 548 Obj->moveRelocationNext(RelNext); 549 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 550 551 // X86 sect diff's must be followed by a relocation of type 552 // GENERIC_RELOC_PAIR. 553 unsigned RType = Obj->getAnyRelocationType(RENext); 554 555 if (RType != MachO::GENERIC_RELOC_PAIR) 556 report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 557 "GENERIC_RELOC_SECTDIFF."); 558 559 printRelocationTargetName(Obj, RE, Fmt); 560 Fmt << "-"; 561 printRelocationTargetName(Obj, RENext, Fmt); 562 break; 563 } 564 } 565 566 if (Arch == Triple::x86 || Arch == Triple::ppc) { 567 switch (Type) { 568 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 569 DataRefImpl RelNext = Rel; 570 Obj->moveRelocationNext(RelNext); 571 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 572 573 // X86 sect diff's must be followed by a relocation of type 574 // GENERIC_RELOC_PAIR. 575 unsigned RType = Obj->getAnyRelocationType(RENext); 576 if (RType != MachO::GENERIC_RELOC_PAIR) 577 report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 578 "GENERIC_RELOC_LOCAL_SECTDIFF."); 579 580 printRelocationTargetName(Obj, RE, Fmt); 581 Fmt << "-"; 582 printRelocationTargetName(Obj, RENext, Fmt); 583 break; 584 } 585 case MachO::GENERIC_RELOC_TLV: { 586 printRelocationTargetName(Obj, RE, Fmt); 587 Fmt << "@TLV"; 588 if (IsPCRel) 589 Fmt << "P"; 590 break; 591 } 592 default: 593 printRelocationTargetName(Obj, RE, Fmt); 594 } 595 } else { // ARM-specific relocations 596 switch (Type) { 597 case MachO::ARM_RELOC_HALF: 598 case MachO::ARM_RELOC_HALF_SECTDIFF: { 599 // Half relocations steal a bit from the length field to encode 600 // whether this is an upper16 or a lower16 relocation. 601 bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1; 602 603 if (isUpper) 604 Fmt << ":upper16:("; 605 else 606 Fmt << ":lower16:("; 607 printRelocationTargetName(Obj, RE, Fmt); 608 609 DataRefImpl RelNext = Rel; 610 Obj->moveRelocationNext(RelNext); 611 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 612 613 // ARM half relocs must be followed by a relocation of type 614 // ARM_RELOC_PAIR. 615 unsigned RType = Obj->getAnyRelocationType(RENext); 616 if (RType != MachO::ARM_RELOC_PAIR) 617 report_error(Obj->getFileName(), "Expected ARM_RELOC_PAIR after " 618 "ARM_RELOC_HALF"); 619 620 // NOTE: The half of the target virtual address is stashed in the 621 // address field of the secondary relocation, but we can't reverse 622 // engineer the constant offset from it without decoding the movw/movt 623 // instruction to find the other half in its immediate field. 624 625 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 626 // symbol/section pointer of the follow-on relocation. 627 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 628 Fmt << "-"; 629 printRelocationTargetName(Obj, RENext, Fmt); 630 } 631 632 Fmt << ")"; 633 break; 634 } 635 default: { 636 printRelocationTargetName(Obj, RE, Fmt); 637 } 638 } 639 } 640 } else 641 printRelocationTargetName(Obj, RE, Fmt); 642 643 Fmt.flush(); 644 Result.append(FmtBuf.begin(), FmtBuf.end()); 645 return Error::success(); 646 } 647 648 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 649 uint32_t n, uint32_t count, 650 uint32_t stride, uint64_t addr) { 651 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 652 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 653 if (n > nindirectsyms) 654 outs() << " (entries start past the end of the indirect symbol " 655 "table) (reserved1 field greater than the table size)"; 656 else if (n + count > nindirectsyms) 657 outs() << " (entries extends past the end of the indirect symbol " 658 "table)"; 659 outs() << "\n"; 660 uint32_t cputype = O->getHeader().cputype; 661 if (cputype & MachO::CPU_ARCH_ABI64) 662 outs() << "address index"; 663 else 664 outs() << "address index"; 665 if (verbose) 666 outs() << " name\n"; 667 else 668 outs() << "\n"; 669 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 670 if (cputype & MachO::CPU_ARCH_ABI64) 671 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 672 else 673 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 674 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 675 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 676 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 677 outs() << "LOCAL\n"; 678 continue; 679 } 680 if (indirect_symbol == 681 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 682 outs() << "LOCAL ABSOLUTE\n"; 683 continue; 684 } 685 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 686 outs() << "ABSOLUTE\n"; 687 continue; 688 } 689 outs() << format("%5u ", indirect_symbol); 690 if (verbose) { 691 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 692 if (indirect_symbol < Symtab.nsyms) { 693 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 694 SymbolRef Symbol = *Sym; 695 outs() << unwrapOrError(Symbol.getName(), O->getFileName()); 696 } else { 697 outs() << "?"; 698 } 699 } 700 outs() << "\n"; 701 } 702 } 703 704 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 705 for (const auto &Load : O->load_commands()) { 706 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 707 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 708 for (unsigned J = 0; J < Seg.nsects; ++J) { 709 MachO::section_64 Sec = O->getSection64(Load, J); 710 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 711 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 712 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 713 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 714 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 715 section_type == MachO::S_SYMBOL_STUBS) { 716 uint32_t stride; 717 if (section_type == MachO::S_SYMBOL_STUBS) 718 stride = Sec.reserved2; 719 else 720 stride = 8; 721 if (stride == 0) { 722 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 723 << Sec.sectname << ") " 724 << "(size of stubs in reserved2 field is zero)\n"; 725 continue; 726 } 727 uint32_t count = Sec.size / stride; 728 outs() << "Indirect symbols for (" << Sec.segname << "," 729 << Sec.sectname << ") " << count << " entries"; 730 uint32_t n = Sec.reserved1; 731 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 732 } 733 } 734 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 735 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 736 for (unsigned J = 0; J < Seg.nsects; ++J) { 737 MachO::section Sec = O->getSection(Load, J); 738 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 739 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 740 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 741 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 742 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 743 section_type == MachO::S_SYMBOL_STUBS) { 744 uint32_t stride; 745 if (section_type == MachO::S_SYMBOL_STUBS) 746 stride = Sec.reserved2; 747 else 748 stride = 4; 749 if (stride == 0) { 750 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 751 << Sec.sectname << ") " 752 << "(size of stubs in reserved2 field is zero)\n"; 753 continue; 754 } 755 uint32_t count = Sec.size / stride; 756 outs() << "Indirect symbols for (" << Sec.segname << "," 757 << Sec.sectname << ") " << count << " entries"; 758 uint32_t n = Sec.reserved1; 759 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 760 } 761 } 762 } 763 } 764 } 765 766 static void PrintRType(const uint64_t cputype, const unsigned r_type) { 767 static char const *generic_r_types[] = { 768 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ", 769 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", 770 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 771 }; 772 static char const *x86_64_r_types[] = { 773 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", 774 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ", 775 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 776 }; 777 static char const *arm_r_types[] = { 778 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", 779 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ", 780 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 781 }; 782 static char const *arm64_r_types[] = { 783 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", 784 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", 785 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 786 }; 787 788 if (r_type > 0xf){ 789 outs() << format("%-7u", r_type) << " "; 790 return; 791 } 792 switch (cputype) { 793 case MachO::CPU_TYPE_I386: 794 outs() << generic_r_types[r_type]; 795 break; 796 case MachO::CPU_TYPE_X86_64: 797 outs() << x86_64_r_types[r_type]; 798 break; 799 case MachO::CPU_TYPE_ARM: 800 outs() << arm_r_types[r_type]; 801 break; 802 case MachO::CPU_TYPE_ARM64: 803 case MachO::CPU_TYPE_ARM64_32: 804 outs() << arm64_r_types[r_type]; 805 break; 806 default: 807 outs() << format("%-7u ", r_type); 808 } 809 } 810 811 static void PrintRLength(const uint64_t cputype, const unsigned r_type, 812 const unsigned r_length, const bool previous_arm_half){ 813 if (cputype == MachO::CPU_TYPE_ARM && 814 (r_type == MachO::ARM_RELOC_HALF || 815 r_type == MachO::ARM_RELOC_HALF_SECTDIFF || previous_arm_half == true)) { 816 if ((r_length & 0x1) == 0) 817 outs() << "lo/"; 818 else 819 outs() << "hi/"; 820 if ((r_length & 0x1) == 0) 821 outs() << "arm "; 822 else 823 outs() << "thm "; 824 } else { 825 switch (r_length) { 826 case 0: 827 outs() << "byte "; 828 break; 829 case 1: 830 outs() << "word "; 831 break; 832 case 2: 833 outs() << "long "; 834 break; 835 case 3: 836 if (cputype == MachO::CPU_TYPE_X86_64) 837 outs() << "quad "; 838 else 839 outs() << format("?(%2d) ", r_length); 840 break; 841 default: 842 outs() << format("?(%2d) ", r_length); 843 } 844 } 845 } 846 847 static void PrintRelocationEntries(const MachOObjectFile *O, 848 const relocation_iterator Begin, 849 const relocation_iterator End, 850 const uint64_t cputype, 851 const bool verbose) { 852 const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 853 bool previous_arm_half = false; 854 bool previous_sectdiff = false; 855 uint32_t sectdiff_r_type = 0; 856 857 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { 858 const DataRefImpl Rel = Reloc->getRawDataRefImpl(); 859 const MachO::any_relocation_info RE = O->getRelocation(Rel); 860 const unsigned r_type = O->getAnyRelocationType(RE); 861 const bool r_scattered = O->isRelocationScattered(RE); 862 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); 863 const unsigned r_length = O->getAnyRelocationLength(RE); 864 const unsigned r_address = O->getAnyRelocationAddress(RE); 865 const bool r_extern = (r_scattered ? false : 866 O->getPlainRelocationExternal(RE)); 867 const uint32_t r_value = (r_scattered ? 868 O->getScatteredRelocationValue(RE) : 0); 869 const unsigned r_symbolnum = (r_scattered ? 0 : 870 O->getPlainRelocationSymbolNum(RE)); 871 872 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { 873 if (verbose) { 874 // scattered: address 875 if ((cputype == MachO::CPU_TYPE_I386 && 876 r_type == MachO::GENERIC_RELOC_PAIR) || 877 (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)) 878 outs() << " "; 879 else 880 outs() << format("%08x ", (unsigned int)r_address); 881 882 // scattered: pcrel 883 if (r_pcrel) 884 outs() << "True "; 885 else 886 outs() << "False "; 887 888 // scattered: length 889 PrintRLength(cputype, r_type, r_length, previous_arm_half); 890 891 // scattered: extern & type 892 outs() << "n/a "; 893 PrintRType(cputype, r_type); 894 895 // scattered: scattered & value 896 outs() << format("True 0x%08x", (unsigned int)r_value); 897 if (previous_sectdiff == false) { 898 if ((cputype == MachO::CPU_TYPE_ARM && 899 r_type == MachO::ARM_RELOC_PAIR)) 900 outs() << format(" half = 0x%04x ", (unsigned int)r_address); 901 } else if (cputype == MachO::CPU_TYPE_ARM && 902 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF) 903 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); 904 if ((cputype == MachO::CPU_TYPE_I386 && 905 (r_type == MachO::GENERIC_RELOC_SECTDIFF || 906 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || 907 (cputype == MachO::CPU_TYPE_ARM && 908 (sectdiff_r_type == MachO::ARM_RELOC_SECTDIFF || 909 sectdiff_r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 910 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF))) { 911 previous_sectdiff = true; 912 sectdiff_r_type = r_type; 913 } else { 914 previous_sectdiff = false; 915 sectdiff_r_type = 0; 916 } 917 if (cputype == MachO::CPU_TYPE_ARM && 918 (r_type == MachO::ARM_RELOC_HALF || 919 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 920 previous_arm_half = true; 921 else 922 previous_arm_half = false; 923 outs() << "\n"; 924 } 925 else { 926 // scattered: address pcrel length extern type scattered value 927 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n", 928 (unsigned int)r_address, r_pcrel, r_length, r_type, 929 (unsigned int)r_value); 930 } 931 } 932 else { 933 if (verbose) { 934 // plain: address 935 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 936 outs() << " "; 937 else 938 outs() << format("%08x ", (unsigned int)r_address); 939 940 // plain: pcrel 941 if (r_pcrel) 942 outs() << "True "; 943 else 944 outs() << "False "; 945 946 // plain: length 947 PrintRLength(cputype, r_type, r_length, previous_arm_half); 948 949 if (r_extern) { 950 // plain: extern & type & scattered 951 outs() << "True "; 952 PrintRType(cputype, r_type); 953 outs() << "False "; 954 955 // plain: symbolnum/value 956 if (r_symbolnum > Symtab.nsyms) 957 outs() << format("?(%d)\n", r_symbolnum); 958 else { 959 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); 960 Expected<StringRef> SymNameNext = Symbol.getName(); 961 const char *name = NULL; 962 if (SymNameNext) 963 name = SymNameNext->data(); 964 if (name == NULL) 965 outs() << format("?(%d)\n", r_symbolnum); 966 else 967 outs() << name << "\n"; 968 } 969 } 970 else { 971 // plain: extern & type & scattered 972 outs() << "False "; 973 PrintRType(cputype, r_type); 974 outs() << "False "; 975 976 // plain: symbolnum/value 977 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 978 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); 979 else if ((cputype == MachO::CPU_TYPE_ARM64 || 980 cputype == MachO::CPU_TYPE_ARM64_32) && 981 r_type == MachO::ARM64_RELOC_ADDEND) 982 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); 983 else { 984 outs() << format("%d ", r_symbolnum); 985 if (r_symbolnum == MachO::R_ABS) 986 outs() << "R_ABS\n"; 987 else { 988 // in this case, r_symbolnum is actually a 1-based section number 989 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; 990 if (r_symbolnum > 0 && r_symbolnum <= nsects) { 991 object::DataRefImpl DRI; 992 DRI.d.a = r_symbolnum-1; 993 StringRef SegName = O->getSectionFinalSegmentName(DRI); 994 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 995 outs() << "(" << SegName << "," << *NameOrErr << ")\n"; 996 else 997 outs() << "(?,?)\n"; 998 } 999 else { 1000 outs() << "(?,?)\n"; 1001 } 1002 } 1003 } 1004 } 1005 if (cputype == MachO::CPU_TYPE_ARM && 1006 (r_type == MachO::ARM_RELOC_HALF || 1007 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 1008 previous_arm_half = true; 1009 else 1010 previous_arm_half = false; 1011 } 1012 else { 1013 // plain: address pcrel length extern type scattered symbolnum/section 1014 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n", 1015 (unsigned int)r_address, r_pcrel, r_length, r_extern, 1016 r_type, r_symbolnum); 1017 } 1018 } 1019 } 1020 } 1021 1022 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { 1023 const uint64_t cputype = O->getHeader().cputype; 1024 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 1025 if (Dysymtab.nextrel != 0) { 1026 outs() << "External relocation information " << Dysymtab.nextrel 1027 << " entries"; 1028 outs() << "\naddress pcrel length extern type scattered " 1029 "symbolnum/value\n"; 1030 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, 1031 verbose); 1032 } 1033 if (Dysymtab.nlocrel != 0) { 1034 outs() << format("Local relocation information %u entries", 1035 Dysymtab.nlocrel); 1036 outs() << "\naddress pcrel length extern type scattered " 1037 "symbolnum/value\n"; 1038 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, 1039 verbose); 1040 } 1041 for (const auto &Load : O->load_commands()) { 1042 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 1043 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 1044 for (unsigned J = 0; J < Seg.nsects; ++J) { 1045 const MachO::section_64 Sec = O->getSection64(Load, J); 1046 if (Sec.nreloc != 0) { 1047 DataRefImpl DRI; 1048 DRI.d.a = J; 1049 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1050 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1051 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1052 << format(") %u entries", Sec.nreloc); 1053 else 1054 outs() << "Relocation information (" << SegName << ",?) " 1055 << format("%u entries", Sec.nreloc); 1056 outs() << "\naddress pcrel length extern type scattered " 1057 "symbolnum/value\n"; 1058 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1059 O->section_rel_end(DRI), cputype, verbose); 1060 } 1061 } 1062 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1063 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 1064 for (unsigned J = 0; J < Seg.nsects; ++J) { 1065 const MachO::section Sec = O->getSection(Load, J); 1066 if (Sec.nreloc != 0) { 1067 DataRefImpl DRI; 1068 DRI.d.a = J; 1069 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1070 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1071 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1072 << format(") %u entries", Sec.nreloc); 1073 else 1074 outs() << "Relocation information (" << SegName << ",?) " 1075 << format("%u entries", Sec.nreloc); 1076 outs() << "\naddress pcrel length extern type scattered " 1077 "symbolnum/value\n"; 1078 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1079 O->section_rel_end(DRI), cputype, verbose); 1080 } 1081 } 1082 } 1083 } 1084 } 1085 1086 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 1087 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 1088 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 1089 outs() << "Data in code table (" << nentries << " entries)\n"; 1090 outs() << "offset length kind\n"; 1091 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 1092 ++DI) { 1093 uint32_t Offset; 1094 DI->getOffset(Offset); 1095 outs() << format("0x%08" PRIx32, Offset) << " "; 1096 uint16_t Length; 1097 DI->getLength(Length); 1098 outs() << format("%6u", Length) << " "; 1099 uint16_t Kind; 1100 DI->getKind(Kind); 1101 if (verbose) { 1102 switch (Kind) { 1103 case MachO::DICE_KIND_DATA: 1104 outs() << "DATA"; 1105 break; 1106 case MachO::DICE_KIND_JUMP_TABLE8: 1107 outs() << "JUMP_TABLE8"; 1108 break; 1109 case MachO::DICE_KIND_JUMP_TABLE16: 1110 outs() << "JUMP_TABLE16"; 1111 break; 1112 case MachO::DICE_KIND_JUMP_TABLE32: 1113 outs() << "JUMP_TABLE32"; 1114 break; 1115 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 1116 outs() << "ABS_JUMP_TABLE32"; 1117 break; 1118 default: 1119 outs() << format("0x%04" PRIx32, Kind); 1120 break; 1121 } 1122 } else 1123 outs() << format("0x%04" PRIx32, Kind); 1124 outs() << "\n"; 1125 } 1126 } 1127 1128 static void PrintLinkOptHints(MachOObjectFile *O) { 1129 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 1130 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 1131 uint32_t nloh = LohLC.datasize; 1132 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 1133 for (uint32_t i = 0; i < nloh;) { 1134 unsigned n; 1135 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 1136 i += n; 1137 outs() << " identifier " << identifier << " "; 1138 if (i >= nloh) 1139 return; 1140 switch (identifier) { 1141 case 1: 1142 outs() << "AdrpAdrp\n"; 1143 break; 1144 case 2: 1145 outs() << "AdrpLdr\n"; 1146 break; 1147 case 3: 1148 outs() << "AdrpAddLdr\n"; 1149 break; 1150 case 4: 1151 outs() << "AdrpLdrGotLdr\n"; 1152 break; 1153 case 5: 1154 outs() << "AdrpAddStr\n"; 1155 break; 1156 case 6: 1157 outs() << "AdrpLdrGotStr\n"; 1158 break; 1159 case 7: 1160 outs() << "AdrpAdd\n"; 1161 break; 1162 case 8: 1163 outs() << "AdrpLdrGot\n"; 1164 break; 1165 default: 1166 outs() << "Unknown identifier value\n"; 1167 break; 1168 } 1169 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 1170 i += n; 1171 outs() << " narguments " << narguments << "\n"; 1172 if (i >= nloh) 1173 return; 1174 1175 for (uint32_t j = 0; j < narguments; j++) { 1176 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 1177 i += n; 1178 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 1179 if (i >= nloh) 1180 return; 1181 } 1182 } 1183 } 1184 1185 static void PrintDylibs(MachOObjectFile *O, bool JustId) { 1186 unsigned Index = 0; 1187 for (const auto &Load : O->load_commands()) { 1188 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 1189 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 1190 Load.C.cmd == MachO::LC_LOAD_DYLIB || 1191 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 1192 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 1193 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 1194 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 1195 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 1196 if (dl.dylib.name < dl.cmdsize) { 1197 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 1198 if (JustId) 1199 outs() << p << "\n"; 1200 else { 1201 outs() << "\t" << p; 1202 outs() << " (compatibility version " 1203 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 1204 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 1205 << (dl.dylib.compatibility_version & 0xff) << ","; 1206 outs() << " current version " 1207 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 1208 << ((dl.dylib.current_version >> 8) & 0xff) << "." 1209 << (dl.dylib.current_version & 0xff) << ")\n"; 1210 } 1211 } else { 1212 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 1213 if (Load.C.cmd == MachO::LC_ID_DYLIB) 1214 outs() << "LC_ID_DYLIB "; 1215 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 1216 outs() << "LC_LOAD_DYLIB "; 1217 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 1218 outs() << "LC_LOAD_WEAK_DYLIB "; 1219 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 1220 outs() << "LC_LAZY_LOAD_DYLIB "; 1221 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 1222 outs() << "LC_REEXPORT_DYLIB "; 1223 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 1224 outs() << "LC_LOAD_UPWARD_DYLIB "; 1225 else 1226 outs() << "LC_??? "; 1227 outs() << "command " << Index++ << "\n"; 1228 } 1229 } 1230 } 1231 } 1232 1233 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 1234 1235 static void CreateSymbolAddressMap(MachOObjectFile *O, 1236 SymbolAddressMap *AddrMap) { 1237 // Create a map of symbol addresses to symbol names. 1238 const StringRef FileName = O->getFileName(); 1239 for (const SymbolRef &Symbol : O->symbols()) { 1240 SymbolRef::Type ST = unwrapOrError(Symbol.getType(), FileName); 1241 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 1242 ST == SymbolRef::ST_Other) { 1243 uint64_t Address = Symbol.getValue(); 1244 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 1245 if (!SymName.startswith(".objc")) 1246 (*AddrMap)[Address] = SymName; 1247 } 1248 } 1249 } 1250 1251 // GuessSymbolName is passed the address of what might be a symbol and a 1252 // pointer to the SymbolAddressMap. It returns the name of a symbol 1253 // with that address or nullptr if no symbol is found with that address. 1254 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 1255 const char *SymbolName = nullptr; 1256 // A DenseMap can't lookup up some values. 1257 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 1258 StringRef name = AddrMap->lookup(value); 1259 if (!name.empty()) 1260 SymbolName = name.data(); 1261 } 1262 return SymbolName; 1263 } 1264 1265 static void DumpCstringChar(const char c) { 1266 char p[2]; 1267 p[0] = c; 1268 p[1] = '\0'; 1269 outs().write_escaped(p); 1270 } 1271 1272 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 1273 uint32_t sect_size, uint64_t sect_addr, 1274 bool print_addresses) { 1275 for (uint32_t i = 0; i < sect_size; i++) { 1276 if (print_addresses) { 1277 if (O->is64Bit()) 1278 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1279 else 1280 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1281 } 1282 for (; i < sect_size && sect[i] != '\0'; i++) 1283 DumpCstringChar(sect[i]); 1284 if (i < sect_size && sect[i] == '\0') 1285 outs() << "\n"; 1286 } 1287 } 1288 1289 static void DumpLiteral4(uint32_t l, float f) { 1290 outs() << format("0x%08" PRIx32, l); 1291 if ((l & 0x7f800000) != 0x7f800000) 1292 outs() << format(" (%.16e)\n", f); 1293 else { 1294 if (l == 0x7f800000) 1295 outs() << " (+Infinity)\n"; 1296 else if (l == 0xff800000) 1297 outs() << " (-Infinity)\n"; 1298 else if ((l & 0x00400000) == 0x00400000) 1299 outs() << " (non-signaling Not-a-Number)\n"; 1300 else 1301 outs() << " (signaling Not-a-Number)\n"; 1302 } 1303 } 1304 1305 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 1306 uint32_t sect_size, uint64_t sect_addr, 1307 bool print_addresses) { 1308 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 1309 if (print_addresses) { 1310 if (O->is64Bit()) 1311 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1312 else 1313 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1314 } 1315 float f; 1316 memcpy(&f, sect + i, sizeof(float)); 1317 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1318 sys::swapByteOrder(f); 1319 uint32_t l; 1320 memcpy(&l, sect + i, sizeof(uint32_t)); 1321 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1322 sys::swapByteOrder(l); 1323 DumpLiteral4(l, f); 1324 } 1325 } 1326 1327 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 1328 double d) { 1329 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 1330 uint32_t Hi, Lo; 1331 Hi = (O->isLittleEndian()) ? l1 : l0; 1332 Lo = (O->isLittleEndian()) ? l0 : l1; 1333 1334 // Hi is the high word, so this is equivalent to if(isfinite(d)) 1335 if ((Hi & 0x7ff00000) != 0x7ff00000) 1336 outs() << format(" (%.16e)\n", d); 1337 else { 1338 if (Hi == 0x7ff00000 && Lo == 0) 1339 outs() << " (+Infinity)\n"; 1340 else if (Hi == 0xfff00000 && Lo == 0) 1341 outs() << " (-Infinity)\n"; 1342 else if ((Hi & 0x00080000) == 0x00080000) 1343 outs() << " (non-signaling Not-a-Number)\n"; 1344 else 1345 outs() << " (signaling Not-a-Number)\n"; 1346 } 1347 } 1348 1349 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 1350 uint32_t sect_size, uint64_t sect_addr, 1351 bool print_addresses) { 1352 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 1353 if (print_addresses) { 1354 if (O->is64Bit()) 1355 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1356 else 1357 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1358 } 1359 double d; 1360 memcpy(&d, sect + i, sizeof(double)); 1361 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1362 sys::swapByteOrder(d); 1363 uint32_t l0, l1; 1364 memcpy(&l0, sect + i, sizeof(uint32_t)); 1365 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1366 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1367 sys::swapByteOrder(l0); 1368 sys::swapByteOrder(l1); 1369 } 1370 DumpLiteral8(O, l0, l1, d); 1371 } 1372 } 1373 1374 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 1375 outs() << format("0x%08" PRIx32, l0) << " "; 1376 outs() << format("0x%08" PRIx32, l1) << " "; 1377 outs() << format("0x%08" PRIx32, l2) << " "; 1378 outs() << format("0x%08" PRIx32, l3) << "\n"; 1379 } 1380 1381 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 1382 uint32_t sect_size, uint64_t sect_addr, 1383 bool print_addresses) { 1384 for (uint32_t i = 0; i < sect_size; i += 16) { 1385 if (print_addresses) { 1386 if (O->is64Bit()) 1387 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1388 else 1389 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1390 } 1391 uint32_t l0, l1, l2, l3; 1392 memcpy(&l0, sect + i, sizeof(uint32_t)); 1393 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1394 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 1395 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1396 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1397 sys::swapByteOrder(l0); 1398 sys::swapByteOrder(l1); 1399 sys::swapByteOrder(l2); 1400 sys::swapByteOrder(l3); 1401 } 1402 DumpLiteral16(l0, l1, l2, l3); 1403 } 1404 } 1405 1406 static void DumpLiteralPointerSection(MachOObjectFile *O, 1407 const SectionRef &Section, 1408 const char *sect, uint32_t sect_size, 1409 uint64_t sect_addr, 1410 bool print_addresses) { 1411 // Collect the literal sections in this Mach-O file. 1412 std::vector<SectionRef> LiteralSections; 1413 for (const SectionRef &Section : O->sections()) { 1414 DataRefImpl Ref = Section.getRawDataRefImpl(); 1415 uint32_t section_type; 1416 if (O->is64Bit()) { 1417 const MachO::section_64 Sec = O->getSection64(Ref); 1418 section_type = Sec.flags & MachO::SECTION_TYPE; 1419 } else { 1420 const MachO::section Sec = O->getSection(Ref); 1421 section_type = Sec.flags & MachO::SECTION_TYPE; 1422 } 1423 if (section_type == MachO::S_CSTRING_LITERALS || 1424 section_type == MachO::S_4BYTE_LITERALS || 1425 section_type == MachO::S_8BYTE_LITERALS || 1426 section_type == MachO::S_16BYTE_LITERALS) 1427 LiteralSections.push_back(Section); 1428 } 1429 1430 // Set the size of the literal pointer. 1431 uint32_t lp_size = O->is64Bit() ? 8 : 4; 1432 1433 // Collect the external relocation symbols for the literal pointers. 1434 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1435 for (const RelocationRef &Reloc : Section.relocations()) { 1436 DataRefImpl Rel; 1437 MachO::any_relocation_info RE; 1438 bool isExtern = false; 1439 Rel = Reloc.getRawDataRefImpl(); 1440 RE = O->getRelocation(Rel); 1441 isExtern = O->getPlainRelocationExternal(RE); 1442 if (isExtern) { 1443 uint64_t RelocOffset = Reloc.getOffset(); 1444 symbol_iterator RelocSym = Reloc.getSymbol(); 1445 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1446 } 1447 } 1448 array_pod_sort(Relocs.begin(), Relocs.end()); 1449 1450 // Dump each literal pointer. 1451 for (uint32_t i = 0; i < sect_size; i += lp_size) { 1452 if (print_addresses) { 1453 if (O->is64Bit()) 1454 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1455 else 1456 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1457 } 1458 uint64_t lp; 1459 if (O->is64Bit()) { 1460 memcpy(&lp, sect + i, sizeof(uint64_t)); 1461 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1462 sys::swapByteOrder(lp); 1463 } else { 1464 uint32_t li; 1465 memcpy(&li, sect + i, sizeof(uint32_t)); 1466 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1467 sys::swapByteOrder(li); 1468 lp = li; 1469 } 1470 1471 // First look for an external relocation entry for this literal pointer. 1472 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1473 return P.first == i; 1474 }); 1475 if (Reloc != Relocs.end()) { 1476 symbol_iterator RelocSym = Reloc->second; 1477 StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName()); 1478 outs() << "external relocation entry for symbol:" << SymName << "\n"; 1479 continue; 1480 } 1481 1482 // For local references see what the section the literal pointer points to. 1483 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 1484 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 1485 }); 1486 if (Sect == LiteralSections.end()) { 1487 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 1488 continue; 1489 } 1490 1491 uint64_t SectAddress = Sect->getAddress(); 1492 uint64_t SectSize = Sect->getSize(); 1493 1494 StringRef SectName; 1495 Sect->getName(SectName); 1496 DataRefImpl Ref = Sect->getRawDataRefImpl(); 1497 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 1498 outs() << SegmentName << ":" << SectName << ":"; 1499 1500 uint32_t section_type; 1501 if (O->is64Bit()) { 1502 const MachO::section_64 Sec = O->getSection64(Ref); 1503 section_type = Sec.flags & MachO::SECTION_TYPE; 1504 } else { 1505 const MachO::section Sec = O->getSection(Ref); 1506 section_type = Sec.flags & MachO::SECTION_TYPE; 1507 } 1508 1509 StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName()); 1510 1511 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 1512 1513 switch (section_type) { 1514 case MachO::S_CSTRING_LITERALS: 1515 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 1516 i++) { 1517 DumpCstringChar(Contents[i]); 1518 } 1519 outs() << "\n"; 1520 break; 1521 case MachO::S_4BYTE_LITERALS: 1522 float f; 1523 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 1524 uint32_t l; 1525 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 1526 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1527 sys::swapByteOrder(f); 1528 sys::swapByteOrder(l); 1529 } 1530 DumpLiteral4(l, f); 1531 break; 1532 case MachO::S_8BYTE_LITERALS: { 1533 double d; 1534 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 1535 uint32_t l0, l1; 1536 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1537 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1538 sizeof(uint32_t)); 1539 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1540 sys::swapByteOrder(f); 1541 sys::swapByteOrder(l0); 1542 sys::swapByteOrder(l1); 1543 } 1544 DumpLiteral8(O, l0, l1, d); 1545 break; 1546 } 1547 case MachO::S_16BYTE_LITERALS: { 1548 uint32_t l0, l1, l2, l3; 1549 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1550 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1551 sizeof(uint32_t)); 1552 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 1553 sizeof(uint32_t)); 1554 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 1555 sizeof(uint32_t)); 1556 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1557 sys::swapByteOrder(l0); 1558 sys::swapByteOrder(l1); 1559 sys::swapByteOrder(l2); 1560 sys::swapByteOrder(l3); 1561 } 1562 DumpLiteral16(l0, l1, l2, l3); 1563 break; 1564 } 1565 } 1566 } 1567 } 1568 1569 static void DumpInitTermPointerSection(MachOObjectFile *O, 1570 const SectionRef &Section, 1571 const char *sect, 1572 uint32_t sect_size, uint64_t sect_addr, 1573 SymbolAddressMap *AddrMap, 1574 bool verbose) { 1575 uint32_t stride; 1576 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 1577 1578 // Collect the external relocation symbols for the pointers. 1579 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1580 for (const RelocationRef &Reloc : Section.relocations()) { 1581 DataRefImpl Rel; 1582 MachO::any_relocation_info RE; 1583 bool isExtern = false; 1584 Rel = Reloc.getRawDataRefImpl(); 1585 RE = O->getRelocation(Rel); 1586 isExtern = O->getPlainRelocationExternal(RE); 1587 if (isExtern) { 1588 uint64_t RelocOffset = Reloc.getOffset(); 1589 symbol_iterator RelocSym = Reloc.getSymbol(); 1590 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1591 } 1592 } 1593 array_pod_sort(Relocs.begin(), Relocs.end()); 1594 1595 for (uint32_t i = 0; i < sect_size; i += stride) { 1596 const char *SymbolName = nullptr; 1597 uint64_t p; 1598 if (O->is64Bit()) { 1599 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 1600 uint64_t pointer_value; 1601 memcpy(&pointer_value, sect + i, stride); 1602 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1603 sys::swapByteOrder(pointer_value); 1604 outs() << format("0x%016" PRIx64, pointer_value); 1605 p = pointer_value; 1606 } else { 1607 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 1608 uint32_t pointer_value; 1609 memcpy(&pointer_value, sect + i, stride); 1610 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1611 sys::swapByteOrder(pointer_value); 1612 outs() << format("0x%08" PRIx32, pointer_value); 1613 p = pointer_value; 1614 } 1615 if (verbose) { 1616 // First look for an external relocation entry for this pointer. 1617 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1618 return P.first == i; 1619 }); 1620 if (Reloc != Relocs.end()) { 1621 symbol_iterator RelocSym = Reloc->second; 1622 outs() << " " << unwrapOrError(RelocSym->getName(), O->getFileName()); 1623 } else { 1624 SymbolName = GuessSymbolName(p, AddrMap); 1625 if (SymbolName) 1626 outs() << " " << SymbolName; 1627 } 1628 } 1629 outs() << "\n"; 1630 } 1631 } 1632 1633 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 1634 uint32_t size, uint64_t addr) { 1635 uint32_t cputype = O->getHeader().cputype; 1636 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 1637 uint32_t j; 1638 for (uint32_t i = 0; i < size; i += j, addr += j) { 1639 if (O->is64Bit()) 1640 outs() << format("%016" PRIx64, addr) << "\t"; 1641 else 1642 outs() << format("%08" PRIx64, addr) << "\t"; 1643 for (j = 0; j < 16 && i + j < size; j++) { 1644 uint8_t byte_word = *(sect + i + j); 1645 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1646 } 1647 outs() << "\n"; 1648 } 1649 } else { 1650 uint32_t j; 1651 for (uint32_t i = 0; i < size; i += j, addr += j) { 1652 if (O->is64Bit()) 1653 outs() << format("%016" PRIx64, addr) << "\t"; 1654 else 1655 outs() << format("%08" PRIx64, addr) << "\t"; 1656 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 1657 j += sizeof(int32_t)) { 1658 if (i + j + sizeof(int32_t) <= size) { 1659 uint32_t long_word; 1660 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1661 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1662 sys::swapByteOrder(long_word); 1663 outs() << format("%08" PRIx32, long_word) << " "; 1664 } else { 1665 for (uint32_t k = 0; i + j + k < size; k++) { 1666 uint8_t byte_word = *(sect + i + j + k); 1667 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1668 } 1669 } 1670 } 1671 outs() << "\n"; 1672 } 1673 } 1674 } 1675 1676 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1677 StringRef DisSegName, StringRef DisSectName); 1678 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1679 uint32_t size, uint32_t addr); 1680 #ifdef HAVE_LIBXAR 1681 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 1682 uint32_t size, bool verbose, 1683 bool PrintXarHeader, bool PrintXarFileHeaders, 1684 std::string XarMemberName); 1685 #endif // defined(HAVE_LIBXAR) 1686 1687 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1688 bool verbose) { 1689 SymbolAddressMap AddrMap; 1690 if (verbose) 1691 CreateSymbolAddressMap(O, &AddrMap); 1692 1693 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1694 StringRef DumpSection = FilterSections[i]; 1695 std::pair<StringRef, StringRef> DumpSegSectName; 1696 DumpSegSectName = DumpSection.split(','); 1697 StringRef DumpSegName, DumpSectName; 1698 if (!DumpSegSectName.second.empty()) { 1699 DumpSegName = DumpSegSectName.first; 1700 DumpSectName = DumpSegSectName.second; 1701 } else { 1702 DumpSegName = ""; 1703 DumpSectName = DumpSegSectName.first; 1704 } 1705 for (const SectionRef &Section : O->sections()) { 1706 StringRef SectName; 1707 Section.getName(SectName); 1708 DataRefImpl Ref = Section.getRawDataRefImpl(); 1709 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1710 if ((DumpSegName.empty() || SegName == DumpSegName) && 1711 (SectName == DumpSectName)) { 1712 1713 uint32_t section_flags; 1714 if (O->is64Bit()) { 1715 const MachO::section_64 Sec = O->getSection64(Ref); 1716 section_flags = Sec.flags; 1717 1718 } else { 1719 const MachO::section Sec = O->getSection(Ref); 1720 section_flags = Sec.flags; 1721 } 1722 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1723 1724 StringRef BytesStr = 1725 unwrapOrError(Section.getContents(), O->getFileName()); 1726 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1727 uint32_t sect_size = BytesStr.size(); 1728 uint64_t sect_addr = Section.getAddress(); 1729 1730 outs() << "Contents of (" << SegName << "," << SectName 1731 << ") section\n"; 1732 1733 if (verbose) { 1734 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1735 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1736 DisassembleMachO(Filename, O, SegName, SectName); 1737 continue; 1738 } 1739 if (SegName == "__TEXT" && SectName == "__info_plist") { 1740 outs() << sect; 1741 continue; 1742 } 1743 if (SegName == "__OBJC" && SectName == "__protocol") { 1744 DumpProtocolSection(O, sect, sect_size, sect_addr); 1745 continue; 1746 } 1747 #ifdef HAVE_LIBXAR 1748 if (SegName == "__LLVM" && SectName == "__bundle") { 1749 DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands, 1750 ArchiveHeaders, ""); 1751 continue; 1752 } 1753 #endif // defined(HAVE_LIBXAR) 1754 switch (section_type) { 1755 case MachO::S_REGULAR: 1756 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1757 break; 1758 case MachO::S_ZEROFILL: 1759 outs() << "zerofill section and has no contents in the file\n"; 1760 break; 1761 case MachO::S_CSTRING_LITERALS: 1762 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1763 break; 1764 case MachO::S_4BYTE_LITERALS: 1765 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1766 break; 1767 case MachO::S_8BYTE_LITERALS: 1768 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1769 break; 1770 case MachO::S_16BYTE_LITERALS: 1771 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1772 break; 1773 case MachO::S_LITERAL_POINTERS: 1774 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1775 !NoLeadingAddr); 1776 break; 1777 case MachO::S_MOD_INIT_FUNC_POINTERS: 1778 case MachO::S_MOD_TERM_FUNC_POINTERS: 1779 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr, 1780 &AddrMap, verbose); 1781 break; 1782 default: 1783 outs() << "Unknown section type (" 1784 << format("0x%08" PRIx32, section_type) << ")\n"; 1785 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1786 break; 1787 } 1788 } else { 1789 if (section_type == MachO::S_ZEROFILL) 1790 outs() << "zerofill section and has no contents in the file\n"; 1791 else 1792 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1793 } 1794 } 1795 } 1796 } 1797 } 1798 1799 static void DumpInfoPlistSectionContents(StringRef Filename, 1800 MachOObjectFile *O) { 1801 for (const SectionRef &Section : O->sections()) { 1802 StringRef SectName; 1803 Section.getName(SectName); 1804 DataRefImpl Ref = Section.getRawDataRefImpl(); 1805 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1806 if (SegName == "__TEXT" && SectName == "__info_plist") { 1807 if (!NoLeadingHeaders) 1808 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1809 StringRef BytesStr = 1810 unwrapOrError(Section.getContents(), O->getFileName()); 1811 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1812 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 1813 return; 1814 } 1815 } 1816 } 1817 1818 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1819 // and if it is and there is a list of architecture flags is specified then 1820 // check to make sure this Mach-O file is one of those architectures or all 1821 // architectures were specified. If not then an error is generated and this 1822 // routine returns false. Else it returns true. 1823 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1824 auto *MachO = dyn_cast<MachOObjectFile>(O); 1825 1826 if (!MachO || ArchAll || ArchFlags.empty()) 1827 return true; 1828 1829 MachO::mach_header H; 1830 MachO::mach_header_64 H_64; 1831 Triple T; 1832 const char *McpuDefault, *ArchFlag; 1833 if (MachO->is64Bit()) { 1834 H_64 = MachO->MachOObjectFile::getHeader64(); 1835 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 1836 &McpuDefault, &ArchFlag); 1837 } else { 1838 H = MachO->MachOObjectFile::getHeader(); 1839 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 1840 &McpuDefault, &ArchFlag); 1841 } 1842 const std::string ArchFlagName(ArchFlag); 1843 if (none_of(ArchFlags, [&](const std::string &Name) { 1844 return Name == ArchFlagName; 1845 })) { 1846 WithColor::error(errs(), "llvm-objdump") 1847 << Filename << ": no architecture specified.\n"; 1848 return false; 1849 } 1850 return true; 1851 } 1852 1853 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 1854 1855 // ProcessMachO() is passed a single opened Mach-O file, which may be an 1856 // archive member and or in a slice of a universal file. It prints the 1857 // the file name and header info and then processes it according to the 1858 // command line options. 1859 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 1860 StringRef ArchiveMemberName = StringRef(), 1861 StringRef ArchitectureName = StringRef()) { 1862 // If we are doing some processing here on the Mach-O file print the header 1863 // info. And don't print it otherwise like in the case of printing the 1864 // UniversalHeaders or ArchiveHeaders. 1865 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || 1866 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || 1867 DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData || 1868 (!FilterSections.empty())) { 1869 if (!NoLeadingHeaders) { 1870 outs() << Name; 1871 if (!ArchiveMemberName.empty()) 1872 outs() << '(' << ArchiveMemberName << ')'; 1873 if (!ArchitectureName.empty()) 1874 outs() << " (architecture " << ArchitectureName << ")"; 1875 outs() << ":\n"; 1876 } 1877 } 1878 // To use the report_error() form with an ArchiveName and FileName set 1879 // these up based on what is passed for Name and ArchiveMemberName. 1880 StringRef ArchiveName; 1881 StringRef FileName; 1882 if (!ArchiveMemberName.empty()) { 1883 ArchiveName = Name; 1884 FileName = ArchiveMemberName; 1885 } else { 1886 ArchiveName = StringRef(); 1887 FileName = Name; 1888 } 1889 1890 // If we need the symbol table to do the operation then check it here to 1891 // produce a good error message as to where the Mach-O file comes from in 1892 // the error message. 1893 if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo) 1894 if (Error Err = MachOOF->checkSymbolTable()) 1895 report_error(std::move(Err), ArchiveName, FileName, ArchitectureName); 1896 1897 if (DisassembleAll) { 1898 for (const SectionRef &Section : MachOOF->sections()) { 1899 StringRef SectName; 1900 Section.getName(SectName); 1901 if (SectName.equals("__text")) { 1902 DataRefImpl Ref = Section.getRawDataRefImpl(); 1903 StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref); 1904 DisassembleMachO(FileName, MachOOF, SegName, SectName); 1905 } 1906 } 1907 } 1908 else if (Disassemble) { 1909 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE && 1910 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64) 1911 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text"); 1912 else 1913 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 1914 } 1915 if (IndirectSymbols) 1916 PrintIndirectSymbols(MachOOF, !NonVerbose); 1917 if (DataInCode) 1918 PrintDataInCodeTable(MachOOF, !NonVerbose); 1919 if (LinkOptHints) 1920 PrintLinkOptHints(MachOOF); 1921 if (Relocations) 1922 PrintRelocations(MachOOF, !NonVerbose); 1923 if (SectionHeaders) 1924 printSectionHeaders(MachOOF); 1925 if (SectionContents) 1926 printSectionContents(MachOOF); 1927 if (!FilterSections.empty()) 1928 DumpSectionContents(FileName, MachOOF, !NonVerbose); 1929 if (InfoPlist) 1930 DumpInfoPlistSectionContents(FileName, MachOOF); 1931 if (DylibsUsed) 1932 PrintDylibs(MachOOF, false); 1933 if (DylibId) 1934 PrintDylibs(MachOOF, true); 1935 if (SymbolTable) 1936 printSymbolTable(MachOOF, ArchiveName, ArchitectureName); 1937 if (UnwindInfo) 1938 printMachOUnwindInfo(MachOOF); 1939 if (PrivateHeaders) { 1940 printMachOFileHeader(MachOOF); 1941 printMachOLoadCommands(MachOOF); 1942 } 1943 if (FirstPrivateHeader) 1944 printMachOFileHeader(MachOOF); 1945 if (ObjcMetaData) 1946 printObjcMetaData(MachOOF, !NonVerbose); 1947 if (ExportsTrie) 1948 printExportsTrie(MachOOF); 1949 if (Rebase) 1950 printRebaseTable(MachOOF); 1951 if (Bind) 1952 printBindTable(MachOOF); 1953 if (LazyBind) 1954 printLazyBindTable(MachOOF); 1955 if (WeakBind) 1956 printWeakBindTable(MachOOF); 1957 1958 if (DwarfDumpType != DIDT_Null) { 1959 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF); 1960 // Dump the complete DWARF structure. 1961 DIDumpOptions DumpOpts; 1962 DumpOpts.DumpType = DwarfDumpType; 1963 DICtx->dump(outs(), DumpOpts); 1964 } 1965 } 1966 1967 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 1968 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 1969 outs() << " cputype (" << cputype << ")\n"; 1970 outs() << " cpusubtype (" << cpusubtype << ")\n"; 1971 } 1972 1973 // printCPUType() helps print_fat_headers by printing the cputype and 1974 // pusubtype (symbolically for the one's it knows about). 1975 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 1976 switch (cputype) { 1977 case MachO::CPU_TYPE_I386: 1978 switch (cpusubtype) { 1979 case MachO::CPU_SUBTYPE_I386_ALL: 1980 outs() << " cputype CPU_TYPE_I386\n"; 1981 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 1982 break; 1983 default: 1984 printUnknownCPUType(cputype, cpusubtype); 1985 break; 1986 } 1987 break; 1988 case MachO::CPU_TYPE_X86_64: 1989 switch (cpusubtype) { 1990 case MachO::CPU_SUBTYPE_X86_64_ALL: 1991 outs() << " cputype CPU_TYPE_X86_64\n"; 1992 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 1993 break; 1994 case MachO::CPU_SUBTYPE_X86_64_H: 1995 outs() << " cputype CPU_TYPE_X86_64\n"; 1996 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 1997 break; 1998 default: 1999 printUnknownCPUType(cputype, cpusubtype); 2000 break; 2001 } 2002 break; 2003 case MachO::CPU_TYPE_ARM: 2004 switch (cpusubtype) { 2005 case MachO::CPU_SUBTYPE_ARM_ALL: 2006 outs() << " cputype CPU_TYPE_ARM\n"; 2007 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 2008 break; 2009 case MachO::CPU_SUBTYPE_ARM_V4T: 2010 outs() << " cputype CPU_TYPE_ARM\n"; 2011 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 2012 break; 2013 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2014 outs() << " cputype CPU_TYPE_ARM\n"; 2015 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 2016 break; 2017 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2018 outs() << " cputype CPU_TYPE_ARM\n"; 2019 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 2020 break; 2021 case MachO::CPU_SUBTYPE_ARM_V6: 2022 outs() << " cputype CPU_TYPE_ARM\n"; 2023 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 2024 break; 2025 case MachO::CPU_SUBTYPE_ARM_V6M: 2026 outs() << " cputype CPU_TYPE_ARM\n"; 2027 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 2028 break; 2029 case MachO::CPU_SUBTYPE_ARM_V7: 2030 outs() << " cputype CPU_TYPE_ARM\n"; 2031 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 2032 break; 2033 case MachO::CPU_SUBTYPE_ARM_V7EM: 2034 outs() << " cputype CPU_TYPE_ARM\n"; 2035 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 2036 break; 2037 case MachO::CPU_SUBTYPE_ARM_V7K: 2038 outs() << " cputype CPU_TYPE_ARM\n"; 2039 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 2040 break; 2041 case MachO::CPU_SUBTYPE_ARM_V7M: 2042 outs() << " cputype CPU_TYPE_ARM\n"; 2043 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 2044 break; 2045 case MachO::CPU_SUBTYPE_ARM_V7S: 2046 outs() << " cputype CPU_TYPE_ARM\n"; 2047 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 2048 break; 2049 default: 2050 printUnknownCPUType(cputype, cpusubtype); 2051 break; 2052 } 2053 break; 2054 case MachO::CPU_TYPE_ARM64: 2055 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2056 case MachO::CPU_SUBTYPE_ARM64_ALL: 2057 outs() << " cputype CPU_TYPE_ARM64\n"; 2058 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 2059 break; 2060 case MachO::CPU_SUBTYPE_ARM64E: 2061 outs() << " cputype CPU_TYPE_ARM64\n"; 2062 outs() << " cpusubtype CPU_SUBTYPE_ARM64E\n"; 2063 break; 2064 default: 2065 printUnknownCPUType(cputype, cpusubtype); 2066 break; 2067 } 2068 break; 2069 case MachO::CPU_TYPE_ARM64_32: 2070 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2071 case MachO::CPU_SUBTYPE_ARM64_32_V8: 2072 outs() << " cputype CPU_TYPE_ARM64_32\n"; 2073 outs() << " cpusubtype CPU_SUBTYPE_ARM64_32_V8\n"; 2074 break; 2075 default: 2076 printUnknownCPUType(cputype, cpusubtype); 2077 break; 2078 } 2079 break; 2080 default: 2081 printUnknownCPUType(cputype, cpusubtype); 2082 break; 2083 } 2084 } 2085 2086 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 2087 bool verbose) { 2088 outs() << "Fat headers\n"; 2089 if (verbose) { 2090 if (UB->getMagic() == MachO::FAT_MAGIC) 2091 outs() << "fat_magic FAT_MAGIC\n"; 2092 else // UB->getMagic() == MachO::FAT_MAGIC_64 2093 outs() << "fat_magic FAT_MAGIC_64\n"; 2094 } else 2095 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 2096 2097 uint32_t nfat_arch = UB->getNumberOfObjects(); 2098 StringRef Buf = UB->getData(); 2099 uint64_t size = Buf.size(); 2100 uint64_t big_size = sizeof(struct MachO::fat_header) + 2101 nfat_arch * sizeof(struct MachO::fat_arch); 2102 outs() << "nfat_arch " << UB->getNumberOfObjects(); 2103 if (nfat_arch == 0) 2104 outs() << " (malformed, contains zero architecture types)\n"; 2105 else if (big_size > size) 2106 outs() << " (malformed, architectures past end of file)\n"; 2107 else 2108 outs() << "\n"; 2109 2110 for (uint32_t i = 0; i < nfat_arch; ++i) { 2111 MachOUniversalBinary::ObjectForArch OFA(UB, i); 2112 uint32_t cputype = OFA.getCPUType(); 2113 uint32_t cpusubtype = OFA.getCPUSubType(); 2114 outs() << "architecture "; 2115 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 2116 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 2117 uint32_t other_cputype = other_OFA.getCPUType(); 2118 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 2119 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 2120 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 2121 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 2122 outs() << "(illegal duplicate architecture) "; 2123 break; 2124 } 2125 } 2126 if (verbose) { 2127 outs() << OFA.getArchFlagName() << "\n"; 2128 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2129 } else { 2130 outs() << i << "\n"; 2131 outs() << " cputype " << cputype << "\n"; 2132 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 2133 << "\n"; 2134 } 2135 if (verbose && 2136 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 2137 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 2138 else 2139 outs() << " capabilities " 2140 << format("0x%" PRIx32, 2141 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 2142 outs() << " offset " << OFA.getOffset(); 2143 if (OFA.getOffset() > size) 2144 outs() << " (past end of file)"; 2145 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0) 2146 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 2147 outs() << "\n"; 2148 outs() << " size " << OFA.getSize(); 2149 big_size = OFA.getOffset() + OFA.getSize(); 2150 if (big_size > size) 2151 outs() << " (past end of file)"; 2152 outs() << "\n"; 2153 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 2154 << ")\n"; 2155 } 2156 } 2157 2158 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 2159 bool verbose, bool print_offset, 2160 StringRef ArchitectureName = StringRef()) { 2161 if (print_offset) 2162 outs() << C.getChildOffset() << "\t"; 2163 sys::fs::perms Mode = 2164 unwrapOrError(C.getAccessMode(), Filename, C, ArchitectureName); 2165 if (verbose) { 2166 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 2167 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 2168 outs() << "-"; 2169 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 2170 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 2171 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 2172 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 2173 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 2174 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 2175 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 2176 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 2177 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 2178 } else { 2179 outs() << format("0%o ", Mode); 2180 } 2181 2182 outs() << format( 2183 "%3d/%-3d %5" PRId64 " ", 2184 unwrapOrError(C.getUID(), Filename, C, ArchitectureName), 2185 unwrapOrError(C.getGID(), Filename, C, ArchitectureName), 2186 unwrapOrError(C.getRawSize(), Filename, C, ArchitectureName)); 2187 2188 StringRef RawLastModified = C.getRawLastModified(); 2189 if (verbose) { 2190 unsigned Seconds; 2191 if (RawLastModified.getAsInteger(10, Seconds)) 2192 outs() << "(date: \"" << RawLastModified 2193 << "\" contains non-decimal chars) "; 2194 else { 2195 // Since cime(3) returns a 26 character string of the form: 2196 // "Sun Sep 16 01:03:52 1973\n\0" 2197 // just print 24 characters. 2198 time_t t = Seconds; 2199 outs() << format("%.24s ", ctime(&t)); 2200 } 2201 } else { 2202 outs() << RawLastModified << " "; 2203 } 2204 2205 if (verbose) { 2206 Expected<StringRef> NameOrErr = C.getName(); 2207 if (!NameOrErr) { 2208 consumeError(NameOrErr.takeError()); 2209 outs() << unwrapOrError(C.getRawName(), Filename, C, ArchitectureName) 2210 << "\n"; 2211 } else { 2212 StringRef Name = NameOrErr.get(); 2213 outs() << Name << "\n"; 2214 } 2215 } else { 2216 outs() << unwrapOrError(C.getRawName(), Filename, C, ArchitectureName) 2217 << "\n"; 2218 } 2219 } 2220 2221 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 2222 bool print_offset, 2223 StringRef ArchitectureName = StringRef()) { 2224 Error Err = Error::success(); 2225 for (const auto &C : A->children(Err, false)) 2226 printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName); 2227 2228 if (Err) 2229 report_error(std::move(Err), StringRef(), Filename, ArchitectureName); 2230 } 2231 2232 static bool ValidateArchFlags() { 2233 // Check for -arch all and verifiy the -arch flags are valid. 2234 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2235 if (ArchFlags[i] == "all") { 2236 ArchAll = true; 2237 } else { 2238 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 2239 WithColor::error(errs(), "llvm-objdump") 2240 << "unknown architecture named '" + ArchFlags[i] + 2241 "'for the -arch option\n"; 2242 return false; 2243 } 2244 } 2245 } 2246 return true; 2247 } 2248 2249 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 2250 // -arch flags selecting just those slices as specified by them and also parses 2251 // archive files. Then for each individual Mach-O file ProcessMachO() is 2252 // called to process the file based on the command line options. 2253 void parseInputMachO(StringRef Filename) { 2254 if (!ValidateArchFlags()) 2255 return; 2256 2257 // Attempt to open the binary. 2258 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 2259 if (!BinaryOrErr) { 2260 if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 2261 report_error(std::move(E), Filename); 2262 else 2263 outs() << Filename << ": is not an object file\n"; 2264 return; 2265 } 2266 Binary &Bin = *BinaryOrErr.get().getBinary(); 2267 2268 if (Archive *A = dyn_cast<Archive>(&Bin)) { 2269 outs() << "Archive : " << Filename << "\n"; 2270 if (ArchiveHeaders) 2271 printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets); 2272 2273 Error Err = Error::success(); 2274 for (auto &C : A->children(Err)) { 2275 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2276 if (!ChildOrErr) { 2277 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2278 report_error(std::move(E), Filename, C); 2279 continue; 2280 } 2281 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2282 if (!checkMachOAndArchFlags(O, Filename)) 2283 return; 2284 ProcessMachO(Filename, O, O->getFileName()); 2285 } 2286 } 2287 if (Err) 2288 report_error(std::move(Err), Filename); 2289 return; 2290 } 2291 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 2292 parseInputMachO(UB); 2293 return; 2294 } 2295 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2296 if (!checkMachOAndArchFlags(O, Filename)) 2297 return; 2298 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) 2299 ProcessMachO(Filename, MachOOF); 2300 else 2301 WithColor::error(errs(), "llvm-objdump") 2302 << Filename << "': " 2303 << "object is not a Mach-O file type.\n"; 2304 return; 2305 } 2306 llvm_unreachable("Input object can't be invalid at this point"); 2307 } 2308 2309 void parseInputMachO(MachOUniversalBinary *UB) { 2310 if (!ValidateArchFlags()) 2311 return; 2312 2313 auto Filename = UB->getFileName(); 2314 2315 if (UniversalHeaders) 2316 printMachOUniversalHeaders(UB, !NonVerbose); 2317 2318 // If we have a list of architecture flags specified dump only those. 2319 if (!ArchAll && !ArchFlags.empty()) { 2320 // Look for a slice in the universal binary that matches each ArchFlag. 2321 bool ArchFound; 2322 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2323 ArchFound = false; 2324 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2325 E = UB->end_objects(); 2326 I != E; ++I) { 2327 if (ArchFlags[i] == I->getArchFlagName()) { 2328 ArchFound = true; 2329 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2330 I->getAsObjectFile(); 2331 std::string ArchitectureName = ""; 2332 if (ArchFlags.size() > 1) 2333 ArchitectureName = I->getArchFlagName(); 2334 if (ObjOrErr) { 2335 ObjectFile &O = *ObjOrErr.get(); 2336 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2337 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2338 } else if (Error E = isNotObjectErrorInvalidFileType( 2339 ObjOrErr.takeError())) { 2340 report_error(std::move(E), Filename, StringRef(), ArchitectureName); 2341 continue; 2342 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2343 I->getAsArchive()) { 2344 std::unique_ptr<Archive> &A = *AOrErr; 2345 outs() << "Archive : " << Filename; 2346 if (!ArchitectureName.empty()) 2347 outs() << " (architecture " << ArchitectureName << ")"; 2348 outs() << "\n"; 2349 if (ArchiveHeaders) 2350 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2351 ArchiveMemberOffsets, ArchitectureName); 2352 Error Err = Error::success(); 2353 for (auto &C : A->children(Err)) { 2354 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2355 if (!ChildOrErr) { 2356 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2357 report_error(std::move(E), Filename, C, ArchitectureName); 2358 continue; 2359 } 2360 if (MachOObjectFile *O = 2361 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2362 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2363 } 2364 if (Err) 2365 report_error(std::move(Err), Filename); 2366 } else { 2367 consumeError(AOrErr.takeError()); 2368 error("Mach-O universal file: " + Filename + " for " + 2369 "architecture " + StringRef(I->getArchFlagName()) + 2370 " is not a Mach-O file or an archive file"); 2371 } 2372 } 2373 } 2374 if (!ArchFound) { 2375 WithColor::error(errs(), "llvm-objdump") 2376 << "file: " + Filename + " does not contain " 2377 << "architecture: " + ArchFlags[i] + "\n"; 2378 return; 2379 } 2380 } 2381 return; 2382 } 2383 // No architecture flags were specified so if this contains a slice that 2384 // matches the host architecture dump only that. 2385 if (!ArchAll) { 2386 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2387 E = UB->end_objects(); 2388 I != E; ++I) { 2389 if (MachOObjectFile::getHostArch().getArchName() == 2390 I->getArchFlagName()) { 2391 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2392 std::string ArchiveName; 2393 ArchiveName.clear(); 2394 if (ObjOrErr) { 2395 ObjectFile &O = *ObjOrErr.get(); 2396 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2397 ProcessMachO(Filename, MachOOF); 2398 } else if (Error E = 2399 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2400 report_error(std::move(E), Filename); 2401 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2402 I->getAsArchive()) { 2403 std::unique_ptr<Archive> &A = *AOrErr; 2404 outs() << "Archive : " << Filename << "\n"; 2405 if (ArchiveHeaders) 2406 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2407 ArchiveMemberOffsets); 2408 Error Err = Error::success(); 2409 for (auto &C : A->children(Err)) { 2410 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2411 if (!ChildOrErr) { 2412 if (Error E = 2413 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2414 report_error(std::move(E), Filename, C); 2415 continue; 2416 } 2417 if (MachOObjectFile *O = 2418 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2419 ProcessMachO(Filename, O, O->getFileName()); 2420 } 2421 if (Err) 2422 report_error(std::move(Err), Filename); 2423 } else { 2424 consumeError(AOrErr.takeError()); 2425 error("Mach-O universal file: " + Filename + " for architecture " + 2426 StringRef(I->getArchFlagName()) + 2427 " is not a Mach-O file or an archive file"); 2428 } 2429 return; 2430 } 2431 } 2432 } 2433 // Either all architectures have been specified or none have been specified 2434 // and this does not contain the host architecture so dump all the slices. 2435 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2436 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2437 E = UB->end_objects(); 2438 I != E; ++I) { 2439 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2440 std::string ArchitectureName = ""; 2441 if (moreThanOneArch) 2442 ArchitectureName = I->getArchFlagName(); 2443 if (ObjOrErr) { 2444 ObjectFile &Obj = *ObjOrErr.get(); 2445 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2446 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2447 } else if (Error E = 2448 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2449 report_error(std::move(E), StringRef(), Filename, ArchitectureName); 2450 } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { 2451 std::unique_ptr<Archive> &A = *AOrErr; 2452 outs() << "Archive : " << Filename; 2453 if (!ArchitectureName.empty()) 2454 outs() << " (architecture " << ArchitectureName << ")"; 2455 outs() << "\n"; 2456 if (ArchiveHeaders) 2457 printArchiveHeaders(Filename, A.get(), !NonVerbose, 2458 ArchiveMemberOffsets, ArchitectureName); 2459 Error Err = Error::success(); 2460 for (auto &C : A->children(Err)) { 2461 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2462 if (!ChildOrErr) { 2463 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2464 report_error(std::move(E), Filename, C, ArchitectureName); 2465 continue; 2466 } 2467 if (MachOObjectFile *O = 2468 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2469 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2470 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2471 ArchitectureName); 2472 } 2473 } 2474 if (Err) 2475 report_error(std::move(Err), Filename); 2476 } else { 2477 consumeError(AOrErr.takeError()); 2478 error("Mach-O universal file: " + Filename + " for architecture " + 2479 StringRef(I->getArchFlagName()) + 2480 " is not a Mach-O file or an archive file"); 2481 } 2482 } 2483 } 2484 2485 // The block of info used by the Symbolizer call backs. 2486 struct DisassembleInfo { 2487 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, 2488 std::vector<SectionRef> *Sections, bool verbose) 2489 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {} 2490 bool verbose; 2491 MachOObjectFile *O; 2492 SectionRef S; 2493 SymbolAddressMap *AddrMap; 2494 std::vector<SectionRef> *Sections; 2495 const char *class_name = nullptr; 2496 const char *selector_name = nullptr; 2497 std::unique_ptr<char[]> method = nullptr; 2498 char *demangled_name = nullptr; 2499 uint64_t adrp_addr = 0; 2500 uint32_t adrp_inst = 0; 2501 std::unique_ptr<SymbolAddressMap> bindtable; 2502 uint32_t depth = 0; 2503 }; 2504 2505 // SymbolizerGetOpInfo() is the operand information call back function. 2506 // This is called to get the symbolic information for operand(s) of an 2507 // instruction when it is being done. This routine does this from 2508 // the relocation information, symbol table, etc. That block of information 2509 // is a pointer to the struct DisassembleInfo that was passed when the 2510 // disassembler context was created and passed to back to here when 2511 // called back by the disassembler for instruction operands that could have 2512 // relocation information. The address of the instruction containing operand is 2513 // at the Pc parameter. The immediate value the operand has is passed in 2514 // op_info->Value and is at Offset past the start of the instruction and has a 2515 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2516 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2517 // names and addends of the symbolic expression to add for the operand. The 2518 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2519 // information is returned then this function returns 1 else it returns 0. 2520 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2521 uint64_t Size, int TagType, void *TagBuf) { 2522 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2523 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2524 uint64_t value = op_info->Value; 2525 2526 // Make sure all fields returned are zero if we don't set them. 2527 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2528 op_info->Value = value; 2529 2530 // If the TagType is not the value 1 which it code knows about or if no 2531 // verbose symbolic information is wanted then just return 0, indicating no 2532 // information is being returned. 2533 if (TagType != 1 || !info->verbose) 2534 return 0; 2535 2536 unsigned int Arch = info->O->getArch(); 2537 if (Arch == Triple::x86) { 2538 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2539 return 0; 2540 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2541 // TODO: 2542 // Search the external relocation entries of a fully linked image 2543 // (if any) for an entry that matches this segment offset. 2544 // uint32_t seg_offset = (Pc + Offset); 2545 return 0; 2546 } 2547 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2548 // for an entry for this section offset. 2549 uint32_t sect_addr = info->S.getAddress(); 2550 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2551 bool reloc_found = false; 2552 DataRefImpl Rel; 2553 MachO::any_relocation_info RE; 2554 bool isExtern = false; 2555 SymbolRef Symbol; 2556 bool r_scattered = false; 2557 uint32_t r_value, pair_r_value, r_type; 2558 for (const RelocationRef &Reloc : info->S.relocations()) { 2559 uint64_t RelocOffset = Reloc.getOffset(); 2560 if (RelocOffset == sect_offset) { 2561 Rel = Reloc.getRawDataRefImpl(); 2562 RE = info->O->getRelocation(Rel); 2563 r_type = info->O->getAnyRelocationType(RE); 2564 r_scattered = info->O->isRelocationScattered(RE); 2565 if (r_scattered) { 2566 r_value = info->O->getScatteredRelocationValue(RE); 2567 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2568 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2569 DataRefImpl RelNext = Rel; 2570 info->O->moveRelocationNext(RelNext); 2571 MachO::any_relocation_info RENext; 2572 RENext = info->O->getRelocation(RelNext); 2573 if (info->O->isRelocationScattered(RENext)) 2574 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2575 else 2576 return 0; 2577 } 2578 } else { 2579 isExtern = info->O->getPlainRelocationExternal(RE); 2580 if (isExtern) { 2581 symbol_iterator RelocSym = Reloc.getSymbol(); 2582 Symbol = *RelocSym; 2583 } 2584 } 2585 reloc_found = true; 2586 break; 2587 } 2588 } 2589 if (reloc_found && isExtern) { 2590 op_info->AddSymbol.Present = 1; 2591 op_info->AddSymbol.Name = 2592 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2593 // For i386 extern relocation entries the value in the instruction is 2594 // the offset from the symbol, and value is already set in op_info->Value. 2595 return 1; 2596 } 2597 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2598 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2599 const char *add = GuessSymbolName(r_value, info->AddrMap); 2600 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2601 uint32_t offset = value - (r_value - pair_r_value); 2602 op_info->AddSymbol.Present = 1; 2603 if (add != nullptr) 2604 op_info->AddSymbol.Name = add; 2605 else 2606 op_info->AddSymbol.Value = r_value; 2607 op_info->SubtractSymbol.Present = 1; 2608 if (sub != nullptr) 2609 op_info->SubtractSymbol.Name = sub; 2610 else 2611 op_info->SubtractSymbol.Value = pair_r_value; 2612 op_info->Value = offset; 2613 return 1; 2614 } 2615 return 0; 2616 } 2617 if (Arch == Triple::x86_64) { 2618 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2619 return 0; 2620 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2621 // relocation entries of a linked image (if any) for an entry that matches 2622 // this segment offset. 2623 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2624 uint64_t seg_offset = Pc + Offset; 2625 bool reloc_found = false; 2626 DataRefImpl Rel; 2627 MachO::any_relocation_info RE; 2628 bool isExtern = false; 2629 SymbolRef Symbol; 2630 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2631 uint64_t RelocOffset = Reloc.getOffset(); 2632 if (RelocOffset == seg_offset) { 2633 Rel = Reloc.getRawDataRefImpl(); 2634 RE = info->O->getRelocation(Rel); 2635 // external relocation entries should always be external. 2636 isExtern = info->O->getPlainRelocationExternal(RE); 2637 if (isExtern) { 2638 symbol_iterator RelocSym = Reloc.getSymbol(); 2639 Symbol = *RelocSym; 2640 } 2641 reloc_found = true; 2642 break; 2643 } 2644 } 2645 if (reloc_found && isExtern) { 2646 // The Value passed in will be adjusted by the Pc if the instruction 2647 // adds the Pc. But for x86_64 external relocation entries the Value 2648 // is the offset from the external symbol. 2649 if (info->O->getAnyRelocationPCRel(RE)) 2650 op_info->Value -= Pc + Offset + Size; 2651 const char *name = 2652 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2653 op_info->AddSymbol.Present = 1; 2654 op_info->AddSymbol.Name = name; 2655 return 1; 2656 } 2657 return 0; 2658 } 2659 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2660 // for an entry for this section offset. 2661 uint64_t sect_addr = info->S.getAddress(); 2662 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2663 bool reloc_found = false; 2664 DataRefImpl Rel; 2665 MachO::any_relocation_info RE; 2666 bool isExtern = false; 2667 SymbolRef Symbol; 2668 for (const RelocationRef &Reloc : info->S.relocations()) { 2669 uint64_t RelocOffset = Reloc.getOffset(); 2670 if (RelocOffset == sect_offset) { 2671 Rel = Reloc.getRawDataRefImpl(); 2672 RE = info->O->getRelocation(Rel); 2673 // NOTE: Scattered relocations don't exist on x86_64. 2674 isExtern = info->O->getPlainRelocationExternal(RE); 2675 if (isExtern) { 2676 symbol_iterator RelocSym = Reloc.getSymbol(); 2677 Symbol = *RelocSym; 2678 } 2679 reloc_found = true; 2680 break; 2681 } 2682 } 2683 if (reloc_found && isExtern) { 2684 // The Value passed in will be adjusted by the Pc if the instruction 2685 // adds the Pc. But for x86_64 external relocation entries the Value 2686 // is the offset from the external symbol. 2687 if (info->O->getAnyRelocationPCRel(RE)) 2688 op_info->Value -= Pc + Offset + Size; 2689 const char *name = 2690 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2691 unsigned Type = info->O->getAnyRelocationType(RE); 2692 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2693 DataRefImpl RelNext = Rel; 2694 info->O->moveRelocationNext(RelNext); 2695 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2696 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2697 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2698 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2699 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2700 op_info->SubtractSymbol.Present = 1; 2701 op_info->SubtractSymbol.Name = name; 2702 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2703 Symbol = *RelocSymNext; 2704 name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2705 } 2706 } 2707 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 2708 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 2709 op_info->AddSymbol.Present = 1; 2710 op_info->AddSymbol.Name = name; 2711 return 1; 2712 } 2713 return 0; 2714 } 2715 if (Arch == Triple::arm) { 2716 if (Offset != 0 || (Size != 4 && Size != 2)) 2717 return 0; 2718 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2719 // TODO: 2720 // Search the external relocation entries of a fully linked image 2721 // (if any) for an entry that matches this segment offset. 2722 // uint32_t seg_offset = (Pc + Offset); 2723 return 0; 2724 } 2725 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2726 // for an entry for this section offset. 2727 uint32_t sect_addr = info->S.getAddress(); 2728 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2729 DataRefImpl Rel; 2730 MachO::any_relocation_info RE; 2731 bool isExtern = false; 2732 SymbolRef Symbol; 2733 bool r_scattered = false; 2734 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 2735 auto Reloc = 2736 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2737 uint64_t RelocOffset = Reloc.getOffset(); 2738 return RelocOffset == sect_offset; 2739 }); 2740 2741 if (Reloc == info->S.relocations().end()) 2742 return 0; 2743 2744 Rel = Reloc->getRawDataRefImpl(); 2745 RE = info->O->getRelocation(Rel); 2746 r_length = info->O->getAnyRelocationLength(RE); 2747 r_scattered = info->O->isRelocationScattered(RE); 2748 if (r_scattered) { 2749 r_value = info->O->getScatteredRelocationValue(RE); 2750 r_type = info->O->getScatteredRelocationType(RE); 2751 } else { 2752 r_type = info->O->getAnyRelocationType(RE); 2753 isExtern = info->O->getPlainRelocationExternal(RE); 2754 if (isExtern) { 2755 symbol_iterator RelocSym = Reloc->getSymbol(); 2756 Symbol = *RelocSym; 2757 } 2758 } 2759 if (r_type == MachO::ARM_RELOC_HALF || 2760 r_type == MachO::ARM_RELOC_SECTDIFF || 2761 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 2762 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2763 DataRefImpl RelNext = Rel; 2764 info->O->moveRelocationNext(RelNext); 2765 MachO::any_relocation_info RENext; 2766 RENext = info->O->getRelocation(RelNext); 2767 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 2768 if (info->O->isRelocationScattered(RENext)) 2769 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2770 } 2771 2772 if (isExtern) { 2773 const char *name = 2774 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2775 op_info->AddSymbol.Present = 1; 2776 op_info->AddSymbol.Name = name; 2777 switch (r_type) { 2778 case MachO::ARM_RELOC_HALF: 2779 if ((r_length & 0x1) == 1) { 2780 op_info->Value = value << 16 | other_half; 2781 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2782 } else { 2783 op_info->Value = other_half << 16 | value; 2784 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2785 } 2786 break; 2787 default: 2788 break; 2789 } 2790 return 1; 2791 } 2792 // If we have a branch that is not an external relocation entry then 2793 // return 0 so the code in tryAddingSymbolicOperand() can use the 2794 // SymbolLookUp call back with the branch target address to look up the 2795 // symbol and possibility add an annotation for a symbol stub. 2796 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 2797 r_type == MachO::ARM_THUMB_RELOC_BR22)) 2798 return 0; 2799 2800 uint32_t offset = 0; 2801 if (r_type == MachO::ARM_RELOC_HALF || 2802 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2803 if ((r_length & 0x1) == 1) 2804 value = value << 16 | other_half; 2805 else 2806 value = other_half << 16 | value; 2807 } 2808 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 2809 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 2810 offset = value - r_value; 2811 value = r_value; 2812 } 2813 2814 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2815 if ((r_length & 0x1) == 1) 2816 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2817 else 2818 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2819 const char *add = GuessSymbolName(r_value, info->AddrMap); 2820 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2821 int32_t offset = value - (r_value - pair_r_value); 2822 op_info->AddSymbol.Present = 1; 2823 if (add != nullptr) 2824 op_info->AddSymbol.Name = add; 2825 else 2826 op_info->AddSymbol.Value = r_value; 2827 op_info->SubtractSymbol.Present = 1; 2828 if (sub != nullptr) 2829 op_info->SubtractSymbol.Name = sub; 2830 else 2831 op_info->SubtractSymbol.Value = pair_r_value; 2832 op_info->Value = offset; 2833 return 1; 2834 } 2835 2836 op_info->AddSymbol.Present = 1; 2837 op_info->Value = offset; 2838 if (r_type == MachO::ARM_RELOC_HALF) { 2839 if ((r_length & 0x1) == 1) 2840 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2841 else 2842 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2843 } 2844 const char *add = GuessSymbolName(value, info->AddrMap); 2845 if (add != nullptr) { 2846 op_info->AddSymbol.Name = add; 2847 return 1; 2848 } 2849 op_info->AddSymbol.Value = value; 2850 return 1; 2851 } 2852 if (Arch == Triple::aarch64) { 2853 if (Offset != 0 || Size != 4) 2854 return 0; 2855 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2856 // TODO: 2857 // Search the external relocation entries of a fully linked image 2858 // (if any) for an entry that matches this segment offset. 2859 // uint64_t seg_offset = (Pc + Offset); 2860 return 0; 2861 } 2862 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2863 // for an entry for this section offset. 2864 uint64_t sect_addr = info->S.getAddress(); 2865 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2866 auto Reloc = 2867 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2868 uint64_t RelocOffset = Reloc.getOffset(); 2869 return RelocOffset == sect_offset; 2870 }); 2871 2872 if (Reloc == info->S.relocations().end()) 2873 return 0; 2874 2875 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2876 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 2877 uint32_t r_type = info->O->getAnyRelocationType(RE); 2878 if (r_type == MachO::ARM64_RELOC_ADDEND) { 2879 DataRefImpl RelNext = Rel; 2880 info->O->moveRelocationNext(RelNext); 2881 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2882 if (value == 0) { 2883 value = info->O->getPlainRelocationSymbolNum(RENext); 2884 op_info->Value = value; 2885 } 2886 } 2887 // NOTE: Scattered relocations don't exist on arm64. 2888 if (!info->O->getPlainRelocationExternal(RE)) 2889 return 0; 2890 const char *name = 2891 unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName()) 2892 .data(); 2893 op_info->AddSymbol.Present = 1; 2894 op_info->AddSymbol.Name = name; 2895 2896 switch (r_type) { 2897 case MachO::ARM64_RELOC_PAGE21: 2898 /* @page */ 2899 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 2900 break; 2901 case MachO::ARM64_RELOC_PAGEOFF12: 2902 /* @pageoff */ 2903 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 2904 break; 2905 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 2906 /* @gotpage */ 2907 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 2908 break; 2909 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 2910 /* @gotpageoff */ 2911 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 2912 break; 2913 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 2914 /* @tvlppage is not implemented in llvm-mc */ 2915 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 2916 break; 2917 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 2918 /* @tvlppageoff is not implemented in llvm-mc */ 2919 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 2920 break; 2921 default: 2922 case MachO::ARM64_RELOC_BRANCH26: 2923 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 2924 break; 2925 } 2926 return 1; 2927 } 2928 return 0; 2929 } 2930 2931 // GuessCstringPointer is passed the address of what might be a pointer to a 2932 // literal string in a cstring section. If that address is in a cstring section 2933 // it returns a pointer to that string. Else it returns nullptr. 2934 static const char *GuessCstringPointer(uint64_t ReferenceValue, 2935 struct DisassembleInfo *info) { 2936 for (const auto &Load : info->O->load_commands()) { 2937 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2938 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2939 for (unsigned J = 0; J < Seg.nsects; ++J) { 2940 MachO::section_64 Sec = info->O->getSection64(Load, J); 2941 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2942 if (section_type == MachO::S_CSTRING_LITERALS && 2943 ReferenceValue >= Sec.addr && 2944 ReferenceValue < Sec.addr + Sec.size) { 2945 uint64_t sect_offset = ReferenceValue - Sec.addr; 2946 uint64_t object_offset = Sec.offset + sect_offset; 2947 StringRef MachOContents = info->O->getData(); 2948 uint64_t object_size = MachOContents.size(); 2949 const char *object_addr = (const char *)MachOContents.data(); 2950 if (object_offset < object_size) { 2951 const char *name = object_addr + object_offset; 2952 return name; 2953 } else { 2954 return nullptr; 2955 } 2956 } 2957 } 2958 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2959 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2960 for (unsigned J = 0; J < Seg.nsects; ++J) { 2961 MachO::section Sec = info->O->getSection(Load, J); 2962 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2963 if (section_type == MachO::S_CSTRING_LITERALS && 2964 ReferenceValue >= Sec.addr && 2965 ReferenceValue < Sec.addr + Sec.size) { 2966 uint64_t sect_offset = ReferenceValue - Sec.addr; 2967 uint64_t object_offset = Sec.offset + sect_offset; 2968 StringRef MachOContents = info->O->getData(); 2969 uint64_t object_size = MachOContents.size(); 2970 const char *object_addr = (const char *)MachOContents.data(); 2971 if (object_offset < object_size) { 2972 const char *name = object_addr + object_offset; 2973 return name; 2974 } else { 2975 return nullptr; 2976 } 2977 } 2978 } 2979 } 2980 } 2981 return nullptr; 2982 } 2983 2984 // GuessIndirectSymbol returns the name of the indirect symbol for the 2985 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 2986 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 2987 // symbol name being referenced by the stub or pointer. 2988 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 2989 struct DisassembleInfo *info) { 2990 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 2991 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 2992 for (const auto &Load : info->O->load_commands()) { 2993 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2994 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2995 for (unsigned J = 0; J < Seg.nsects; ++J) { 2996 MachO::section_64 Sec = info->O->getSection64(Load, J); 2997 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2998 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2999 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3000 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3001 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3002 section_type == MachO::S_SYMBOL_STUBS) && 3003 ReferenceValue >= Sec.addr && 3004 ReferenceValue < Sec.addr + Sec.size) { 3005 uint32_t stride; 3006 if (section_type == MachO::S_SYMBOL_STUBS) 3007 stride = Sec.reserved2; 3008 else 3009 stride = 8; 3010 if (stride == 0) 3011 return nullptr; 3012 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3013 if (index < Dysymtab.nindirectsyms) { 3014 uint32_t indirect_symbol = 3015 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3016 if (indirect_symbol < Symtab.nsyms) { 3017 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3018 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3019 .data(); 3020 } 3021 } 3022 } 3023 } 3024 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3025 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3026 for (unsigned J = 0; J < Seg.nsects; ++J) { 3027 MachO::section Sec = info->O->getSection(Load, J); 3028 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3029 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3030 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3031 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3032 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3033 section_type == MachO::S_SYMBOL_STUBS) && 3034 ReferenceValue >= Sec.addr && 3035 ReferenceValue < Sec.addr + Sec.size) { 3036 uint32_t stride; 3037 if (section_type == MachO::S_SYMBOL_STUBS) 3038 stride = Sec.reserved2; 3039 else 3040 stride = 4; 3041 if (stride == 0) 3042 return nullptr; 3043 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3044 if (index < Dysymtab.nindirectsyms) { 3045 uint32_t indirect_symbol = 3046 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3047 if (indirect_symbol < Symtab.nsyms) { 3048 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3049 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3050 .data(); 3051 } 3052 } 3053 } 3054 } 3055 } 3056 } 3057 return nullptr; 3058 } 3059 3060 // method_reference() is called passing it the ReferenceName that might be 3061 // a reference it to an Objective-C method call. If so then it allocates and 3062 // assembles a method call string with the values last seen and saved in 3063 // the DisassembleInfo's class_name and selector_name fields. This is saved 3064 // into the method field of the info and any previous string is free'ed. 3065 // Then the class_name field in the info is set to nullptr. The method call 3066 // string is set into ReferenceName and ReferenceType is set to 3067 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 3068 // then both ReferenceType and ReferenceName are left unchanged. 3069 static void method_reference(struct DisassembleInfo *info, 3070 uint64_t *ReferenceType, 3071 const char **ReferenceName) { 3072 unsigned int Arch = info->O->getArch(); 3073 if (*ReferenceName != nullptr) { 3074 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 3075 if (info->selector_name != nullptr) { 3076 if (info->class_name != nullptr) { 3077 info->method = llvm::make_unique<char[]>( 3078 5 + strlen(info->class_name) + strlen(info->selector_name)); 3079 char *method = info->method.get(); 3080 if (method != nullptr) { 3081 strcpy(method, "+["); 3082 strcat(method, info->class_name); 3083 strcat(method, " "); 3084 strcat(method, info->selector_name); 3085 strcat(method, "]"); 3086 *ReferenceName = method; 3087 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3088 } 3089 } else { 3090 info->method = 3091 llvm::make_unique<char[]>(9 + strlen(info->selector_name)); 3092 char *method = info->method.get(); 3093 if (method != nullptr) { 3094 if (Arch == Triple::x86_64) 3095 strcpy(method, "-[%rdi "); 3096 else if (Arch == Triple::aarch64) 3097 strcpy(method, "-[x0 "); 3098 else 3099 strcpy(method, "-[r? "); 3100 strcat(method, info->selector_name); 3101 strcat(method, "]"); 3102 *ReferenceName = method; 3103 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3104 } 3105 } 3106 info->class_name = nullptr; 3107 } 3108 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 3109 if (info->selector_name != nullptr) { 3110 info->method = 3111 llvm::make_unique<char[]>(17 + strlen(info->selector_name)); 3112 char *method = info->method.get(); 3113 if (method != nullptr) { 3114 if (Arch == Triple::x86_64) 3115 strcpy(method, "-[[%rdi super] "); 3116 else if (Arch == Triple::aarch64) 3117 strcpy(method, "-[[x0 super] "); 3118 else 3119 strcpy(method, "-[[r? super] "); 3120 strcat(method, info->selector_name); 3121 strcat(method, "]"); 3122 *ReferenceName = method; 3123 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3124 } 3125 info->class_name = nullptr; 3126 } 3127 } 3128 } 3129 } 3130 3131 // GuessPointerPointer() is passed the address of what might be a pointer to 3132 // a reference to an Objective-C class, selector, message ref or cfstring. 3133 // If so the value of the pointer is returned and one of the booleans are set 3134 // to true. If not zero is returned and all the booleans are set to false. 3135 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 3136 struct DisassembleInfo *info, 3137 bool &classref, bool &selref, bool &msgref, 3138 bool &cfstring) { 3139 classref = false; 3140 selref = false; 3141 msgref = false; 3142 cfstring = false; 3143 for (const auto &Load : info->O->load_commands()) { 3144 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3145 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3146 for (unsigned J = 0; J < Seg.nsects; ++J) { 3147 MachO::section_64 Sec = info->O->getSection64(Load, J); 3148 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 3149 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3150 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 3151 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 3152 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 3153 ReferenceValue >= Sec.addr && 3154 ReferenceValue < Sec.addr + Sec.size) { 3155 uint64_t sect_offset = ReferenceValue - Sec.addr; 3156 uint64_t object_offset = Sec.offset + sect_offset; 3157 StringRef MachOContents = info->O->getData(); 3158 uint64_t object_size = MachOContents.size(); 3159 const char *object_addr = (const char *)MachOContents.data(); 3160 if (object_offset < object_size) { 3161 uint64_t pointer_value; 3162 memcpy(&pointer_value, object_addr + object_offset, 3163 sizeof(uint64_t)); 3164 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3165 sys::swapByteOrder(pointer_value); 3166 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 3167 selref = true; 3168 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3169 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 3170 classref = true; 3171 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 3172 ReferenceValue + 8 < Sec.addr + Sec.size) { 3173 msgref = true; 3174 memcpy(&pointer_value, object_addr + object_offset + 8, 3175 sizeof(uint64_t)); 3176 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3177 sys::swapByteOrder(pointer_value); 3178 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 3179 cfstring = true; 3180 return pointer_value; 3181 } else { 3182 return 0; 3183 } 3184 } 3185 } 3186 } 3187 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 3188 } 3189 return 0; 3190 } 3191 3192 // get_pointer_64 returns a pointer to the bytes in the object file at the 3193 // Address from a section in the Mach-O file. And indirectly returns the 3194 // offset into the section, number of bytes left in the section past the offset 3195 // and which section is was being referenced. If the Address is not in a 3196 // section nullptr is returned. 3197 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 3198 uint32_t &left, SectionRef &S, 3199 DisassembleInfo *info, 3200 bool objc_only = false) { 3201 offset = 0; 3202 left = 0; 3203 S = SectionRef(); 3204 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 3205 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 3206 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 3207 if (SectSize == 0) 3208 continue; 3209 if (objc_only) { 3210 StringRef SectName; 3211 ((*(info->Sections))[SectIdx]).getName(SectName); 3212 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 3213 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 3214 if (SegName != "__OBJC" && SectName != "__cstring") 3215 continue; 3216 } 3217 if (Address >= SectAddress && Address < SectAddress + SectSize) { 3218 S = (*(info->Sections))[SectIdx]; 3219 offset = Address - SectAddress; 3220 left = SectSize - offset; 3221 StringRef SectContents = unwrapOrError( 3222 ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName()); 3223 return SectContents.data() + offset; 3224 } 3225 } 3226 return nullptr; 3227 } 3228 3229 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 3230 uint32_t &left, SectionRef &S, 3231 DisassembleInfo *info, 3232 bool objc_only = false) { 3233 return get_pointer_64(Address, offset, left, S, info, objc_only); 3234 } 3235 3236 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 3237 // the symbol indirectly through n_value. Based on the relocation information 3238 // for the specified section offset in the specified section reference. 3239 // If no relocation information is found and a non-zero ReferenceValue for the 3240 // symbol is passed, look up that address in the info's AddrMap. 3241 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 3242 DisassembleInfo *info, uint64_t &n_value, 3243 uint64_t ReferenceValue = 0) { 3244 n_value = 0; 3245 if (!info->verbose) 3246 return nullptr; 3247 3248 // See if there is an external relocation entry at the sect_offset. 3249 bool reloc_found = false; 3250 DataRefImpl Rel; 3251 MachO::any_relocation_info RE; 3252 bool isExtern = false; 3253 SymbolRef Symbol; 3254 for (const RelocationRef &Reloc : S.relocations()) { 3255 uint64_t RelocOffset = Reloc.getOffset(); 3256 if (RelocOffset == sect_offset) { 3257 Rel = Reloc.getRawDataRefImpl(); 3258 RE = info->O->getRelocation(Rel); 3259 if (info->O->isRelocationScattered(RE)) 3260 continue; 3261 isExtern = info->O->getPlainRelocationExternal(RE); 3262 if (isExtern) { 3263 symbol_iterator RelocSym = Reloc.getSymbol(); 3264 Symbol = *RelocSym; 3265 } 3266 reloc_found = true; 3267 break; 3268 } 3269 } 3270 // If there is an external relocation entry for a symbol in this section 3271 // at this section_offset then use that symbol's value for the n_value 3272 // and return its name. 3273 const char *SymbolName = nullptr; 3274 if (reloc_found && isExtern) { 3275 n_value = Symbol.getValue(); 3276 StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName()); 3277 if (!Name.empty()) { 3278 SymbolName = Name.data(); 3279 return SymbolName; 3280 } 3281 } 3282 3283 // TODO: For fully linked images, look through the external relocation 3284 // entries off the dynamic symtab command. For these the r_offset is from the 3285 // start of the first writeable segment in the Mach-O file. So the offset 3286 // to this section from that segment is passed to this routine by the caller, 3287 // as the database_offset. Which is the difference of the section's starting 3288 // address and the first writable segment. 3289 // 3290 // NOTE: need add passing the database_offset to this routine. 3291 3292 // We did not find an external relocation entry so look up the ReferenceValue 3293 // as an address of a symbol and if found return that symbol's name. 3294 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 3295 3296 return SymbolName; 3297 } 3298 3299 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 3300 DisassembleInfo *info, 3301 uint32_t ReferenceValue) { 3302 uint64_t n_value64; 3303 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 3304 } 3305 3306 // These are structs in the Objective-C meta data and read to produce the 3307 // comments for disassembly. While these are part of the ABI they are no 3308 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 3309 // . 3310 3311 // The cfstring object in a 64-bit Mach-O file. 3312 struct cfstring64_t { 3313 uint64_t isa; // class64_t * (64-bit pointer) 3314 uint64_t flags; // flag bits 3315 uint64_t characters; // char * (64-bit pointer) 3316 uint64_t length; // number of non-NULL characters in above 3317 }; 3318 3319 // The class object in a 64-bit Mach-O file. 3320 struct class64_t { 3321 uint64_t isa; // class64_t * (64-bit pointer) 3322 uint64_t superclass; // class64_t * (64-bit pointer) 3323 uint64_t cache; // Cache (64-bit pointer) 3324 uint64_t vtable; // IMP * (64-bit pointer) 3325 uint64_t data; // class_ro64_t * (64-bit pointer) 3326 }; 3327 3328 struct class32_t { 3329 uint32_t isa; /* class32_t * (32-bit pointer) */ 3330 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3331 uint32_t cache; /* Cache (32-bit pointer) */ 3332 uint32_t vtable; /* IMP * (32-bit pointer) */ 3333 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3334 }; 3335 3336 struct class_ro64_t { 3337 uint32_t flags; 3338 uint32_t instanceStart; 3339 uint32_t instanceSize; 3340 uint32_t reserved; 3341 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3342 uint64_t name; // const char * (64-bit pointer) 3343 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3344 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3345 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3346 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3347 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3348 }; 3349 3350 struct class_ro32_t { 3351 uint32_t flags; 3352 uint32_t instanceStart; 3353 uint32_t instanceSize; 3354 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3355 uint32_t name; /* const char * (32-bit pointer) */ 3356 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3357 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3358 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3359 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3360 uint32_t baseProperties; /* const struct objc_property_list * 3361 (32-bit pointer) */ 3362 }; 3363 3364 /* Values for class_ro{64,32}_t->flags */ 3365 #define RO_META (1 << 0) 3366 #define RO_ROOT (1 << 1) 3367 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3368 3369 struct method_list64_t { 3370 uint32_t entsize; 3371 uint32_t count; 3372 /* struct method64_t first; These structures follow inline */ 3373 }; 3374 3375 struct method_list32_t { 3376 uint32_t entsize; 3377 uint32_t count; 3378 /* struct method32_t first; These structures follow inline */ 3379 }; 3380 3381 struct method64_t { 3382 uint64_t name; /* SEL (64-bit pointer) */ 3383 uint64_t types; /* const char * (64-bit pointer) */ 3384 uint64_t imp; /* IMP (64-bit pointer) */ 3385 }; 3386 3387 struct method32_t { 3388 uint32_t name; /* SEL (32-bit pointer) */ 3389 uint32_t types; /* const char * (32-bit pointer) */ 3390 uint32_t imp; /* IMP (32-bit pointer) */ 3391 }; 3392 3393 struct protocol_list64_t { 3394 uint64_t count; /* uintptr_t (a 64-bit value) */ 3395 /* struct protocol64_t * list[0]; These pointers follow inline */ 3396 }; 3397 3398 struct protocol_list32_t { 3399 uint32_t count; /* uintptr_t (a 32-bit value) */ 3400 /* struct protocol32_t * list[0]; These pointers follow inline */ 3401 }; 3402 3403 struct protocol64_t { 3404 uint64_t isa; /* id * (64-bit pointer) */ 3405 uint64_t name; /* const char * (64-bit pointer) */ 3406 uint64_t protocols; /* struct protocol_list64_t * 3407 (64-bit pointer) */ 3408 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3409 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3410 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3411 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3412 uint64_t instanceProperties; /* struct objc_property_list * 3413 (64-bit pointer) */ 3414 }; 3415 3416 struct protocol32_t { 3417 uint32_t isa; /* id * (32-bit pointer) */ 3418 uint32_t name; /* const char * (32-bit pointer) */ 3419 uint32_t protocols; /* struct protocol_list_t * 3420 (32-bit pointer) */ 3421 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3422 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3423 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3424 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3425 uint32_t instanceProperties; /* struct objc_property_list * 3426 (32-bit pointer) */ 3427 }; 3428 3429 struct ivar_list64_t { 3430 uint32_t entsize; 3431 uint32_t count; 3432 /* struct ivar64_t first; These structures follow inline */ 3433 }; 3434 3435 struct ivar_list32_t { 3436 uint32_t entsize; 3437 uint32_t count; 3438 /* struct ivar32_t first; These structures follow inline */ 3439 }; 3440 3441 struct ivar64_t { 3442 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3443 uint64_t name; /* const char * (64-bit pointer) */ 3444 uint64_t type; /* const char * (64-bit pointer) */ 3445 uint32_t alignment; 3446 uint32_t size; 3447 }; 3448 3449 struct ivar32_t { 3450 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3451 uint32_t name; /* const char * (32-bit pointer) */ 3452 uint32_t type; /* const char * (32-bit pointer) */ 3453 uint32_t alignment; 3454 uint32_t size; 3455 }; 3456 3457 struct objc_property_list64 { 3458 uint32_t entsize; 3459 uint32_t count; 3460 /* struct objc_property64 first; These structures follow inline */ 3461 }; 3462 3463 struct objc_property_list32 { 3464 uint32_t entsize; 3465 uint32_t count; 3466 /* struct objc_property32 first; These structures follow inline */ 3467 }; 3468 3469 struct objc_property64 { 3470 uint64_t name; /* const char * (64-bit pointer) */ 3471 uint64_t attributes; /* const char * (64-bit pointer) */ 3472 }; 3473 3474 struct objc_property32 { 3475 uint32_t name; /* const char * (32-bit pointer) */ 3476 uint32_t attributes; /* const char * (32-bit pointer) */ 3477 }; 3478 3479 struct category64_t { 3480 uint64_t name; /* const char * (64-bit pointer) */ 3481 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3482 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3483 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3484 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3485 uint64_t instanceProperties; /* struct objc_property_list * 3486 (64-bit pointer) */ 3487 }; 3488 3489 struct category32_t { 3490 uint32_t name; /* const char * (32-bit pointer) */ 3491 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3492 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3493 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3494 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3495 uint32_t instanceProperties; /* struct objc_property_list * 3496 (32-bit pointer) */ 3497 }; 3498 3499 struct objc_image_info64 { 3500 uint32_t version; 3501 uint32_t flags; 3502 }; 3503 struct objc_image_info32 { 3504 uint32_t version; 3505 uint32_t flags; 3506 }; 3507 struct imageInfo_t { 3508 uint32_t version; 3509 uint32_t flags; 3510 }; 3511 /* masks for objc_image_info.flags */ 3512 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3513 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3514 #define OBJC_IMAGE_IS_SIMULATED (1 << 5) 3515 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6) 3516 3517 struct message_ref64 { 3518 uint64_t imp; /* IMP (64-bit pointer) */ 3519 uint64_t sel; /* SEL (64-bit pointer) */ 3520 }; 3521 3522 struct message_ref32 { 3523 uint32_t imp; /* IMP (32-bit pointer) */ 3524 uint32_t sel; /* SEL (32-bit pointer) */ 3525 }; 3526 3527 // Objective-C 1 (32-bit only) meta data structs. 3528 3529 struct objc_module_t { 3530 uint32_t version; 3531 uint32_t size; 3532 uint32_t name; /* char * (32-bit pointer) */ 3533 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3534 }; 3535 3536 struct objc_symtab_t { 3537 uint32_t sel_ref_cnt; 3538 uint32_t refs; /* SEL * (32-bit pointer) */ 3539 uint16_t cls_def_cnt; 3540 uint16_t cat_def_cnt; 3541 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3542 }; 3543 3544 struct objc_class_t { 3545 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3546 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3547 uint32_t name; /* const char * (32-bit pointer) */ 3548 int32_t version; 3549 int32_t info; 3550 int32_t instance_size; 3551 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3552 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3553 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3554 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3555 }; 3556 3557 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3558 // class is not a metaclass 3559 #define CLS_CLASS 0x1 3560 // class is a metaclass 3561 #define CLS_META 0x2 3562 3563 struct objc_category_t { 3564 uint32_t category_name; /* char * (32-bit pointer) */ 3565 uint32_t class_name; /* char * (32-bit pointer) */ 3566 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3567 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3568 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3569 }; 3570 3571 struct objc_ivar_t { 3572 uint32_t ivar_name; /* char * (32-bit pointer) */ 3573 uint32_t ivar_type; /* char * (32-bit pointer) */ 3574 int32_t ivar_offset; 3575 }; 3576 3577 struct objc_ivar_list_t { 3578 int32_t ivar_count; 3579 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3580 }; 3581 3582 struct objc_method_list_t { 3583 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3584 int32_t method_count; 3585 // struct objc_method_t method_list[1]; /* variable length structure */ 3586 }; 3587 3588 struct objc_method_t { 3589 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3590 uint32_t method_types; /* char * (32-bit pointer) */ 3591 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3592 (32-bit pointer) */ 3593 }; 3594 3595 struct objc_protocol_list_t { 3596 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3597 int32_t count; 3598 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3599 // (32-bit pointer) */ 3600 }; 3601 3602 struct objc_protocol_t { 3603 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3604 uint32_t protocol_name; /* char * (32-bit pointer) */ 3605 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3606 uint32_t instance_methods; /* struct objc_method_description_list * 3607 (32-bit pointer) */ 3608 uint32_t class_methods; /* struct objc_method_description_list * 3609 (32-bit pointer) */ 3610 }; 3611 3612 struct objc_method_description_list_t { 3613 int32_t count; 3614 // struct objc_method_description_t list[1]; 3615 }; 3616 3617 struct objc_method_description_t { 3618 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3619 uint32_t types; /* char * (32-bit pointer) */ 3620 }; 3621 3622 inline void swapStruct(struct cfstring64_t &cfs) { 3623 sys::swapByteOrder(cfs.isa); 3624 sys::swapByteOrder(cfs.flags); 3625 sys::swapByteOrder(cfs.characters); 3626 sys::swapByteOrder(cfs.length); 3627 } 3628 3629 inline void swapStruct(struct class64_t &c) { 3630 sys::swapByteOrder(c.isa); 3631 sys::swapByteOrder(c.superclass); 3632 sys::swapByteOrder(c.cache); 3633 sys::swapByteOrder(c.vtable); 3634 sys::swapByteOrder(c.data); 3635 } 3636 3637 inline void swapStruct(struct class32_t &c) { 3638 sys::swapByteOrder(c.isa); 3639 sys::swapByteOrder(c.superclass); 3640 sys::swapByteOrder(c.cache); 3641 sys::swapByteOrder(c.vtable); 3642 sys::swapByteOrder(c.data); 3643 } 3644 3645 inline void swapStruct(struct class_ro64_t &cro) { 3646 sys::swapByteOrder(cro.flags); 3647 sys::swapByteOrder(cro.instanceStart); 3648 sys::swapByteOrder(cro.instanceSize); 3649 sys::swapByteOrder(cro.reserved); 3650 sys::swapByteOrder(cro.ivarLayout); 3651 sys::swapByteOrder(cro.name); 3652 sys::swapByteOrder(cro.baseMethods); 3653 sys::swapByteOrder(cro.baseProtocols); 3654 sys::swapByteOrder(cro.ivars); 3655 sys::swapByteOrder(cro.weakIvarLayout); 3656 sys::swapByteOrder(cro.baseProperties); 3657 } 3658 3659 inline void swapStruct(struct class_ro32_t &cro) { 3660 sys::swapByteOrder(cro.flags); 3661 sys::swapByteOrder(cro.instanceStart); 3662 sys::swapByteOrder(cro.instanceSize); 3663 sys::swapByteOrder(cro.ivarLayout); 3664 sys::swapByteOrder(cro.name); 3665 sys::swapByteOrder(cro.baseMethods); 3666 sys::swapByteOrder(cro.baseProtocols); 3667 sys::swapByteOrder(cro.ivars); 3668 sys::swapByteOrder(cro.weakIvarLayout); 3669 sys::swapByteOrder(cro.baseProperties); 3670 } 3671 3672 inline void swapStruct(struct method_list64_t &ml) { 3673 sys::swapByteOrder(ml.entsize); 3674 sys::swapByteOrder(ml.count); 3675 } 3676 3677 inline void swapStruct(struct method_list32_t &ml) { 3678 sys::swapByteOrder(ml.entsize); 3679 sys::swapByteOrder(ml.count); 3680 } 3681 3682 inline void swapStruct(struct method64_t &m) { 3683 sys::swapByteOrder(m.name); 3684 sys::swapByteOrder(m.types); 3685 sys::swapByteOrder(m.imp); 3686 } 3687 3688 inline void swapStruct(struct method32_t &m) { 3689 sys::swapByteOrder(m.name); 3690 sys::swapByteOrder(m.types); 3691 sys::swapByteOrder(m.imp); 3692 } 3693 3694 inline void swapStruct(struct protocol_list64_t &pl) { 3695 sys::swapByteOrder(pl.count); 3696 } 3697 3698 inline void swapStruct(struct protocol_list32_t &pl) { 3699 sys::swapByteOrder(pl.count); 3700 } 3701 3702 inline void swapStruct(struct protocol64_t &p) { 3703 sys::swapByteOrder(p.isa); 3704 sys::swapByteOrder(p.name); 3705 sys::swapByteOrder(p.protocols); 3706 sys::swapByteOrder(p.instanceMethods); 3707 sys::swapByteOrder(p.classMethods); 3708 sys::swapByteOrder(p.optionalInstanceMethods); 3709 sys::swapByteOrder(p.optionalClassMethods); 3710 sys::swapByteOrder(p.instanceProperties); 3711 } 3712 3713 inline void swapStruct(struct protocol32_t &p) { 3714 sys::swapByteOrder(p.isa); 3715 sys::swapByteOrder(p.name); 3716 sys::swapByteOrder(p.protocols); 3717 sys::swapByteOrder(p.instanceMethods); 3718 sys::swapByteOrder(p.classMethods); 3719 sys::swapByteOrder(p.optionalInstanceMethods); 3720 sys::swapByteOrder(p.optionalClassMethods); 3721 sys::swapByteOrder(p.instanceProperties); 3722 } 3723 3724 inline void swapStruct(struct ivar_list64_t &il) { 3725 sys::swapByteOrder(il.entsize); 3726 sys::swapByteOrder(il.count); 3727 } 3728 3729 inline void swapStruct(struct ivar_list32_t &il) { 3730 sys::swapByteOrder(il.entsize); 3731 sys::swapByteOrder(il.count); 3732 } 3733 3734 inline void swapStruct(struct ivar64_t &i) { 3735 sys::swapByteOrder(i.offset); 3736 sys::swapByteOrder(i.name); 3737 sys::swapByteOrder(i.type); 3738 sys::swapByteOrder(i.alignment); 3739 sys::swapByteOrder(i.size); 3740 } 3741 3742 inline void swapStruct(struct ivar32_t &i) { 3743 sys::swapByteOrder(i.offset); 3744 sys::swapByteOrder(i.name); 3745 sys::swapByteOrder(i.type); 3746 sys::swapByteOrder(i.alignment); 3747 sys::swapByteOrder(i.size); 3748 } 3749 3750 inline void swapStruct(struct objc_property_list64 &pl) { 3751 sys::swapByteOrder(pl.entsize); 3752 sys::swapByteOrder(pl.count); 3753 } 3754 3755 inline void swapStruct(struct objc_property_list32 &pl) { 3756 sys::swapByteOrder(pl.entsize); 3757 sys::swapByteOrder(pl.count); 3758 } 3759 3760 inline void swapStruct(struct objc_property64 &op) { 3761 sys::swapByteOrder(op.name); 3762 sys::swapByteOrder(op.attributes); 3763 } 3764 3765 inline void swapStruct(struct objc_property32 &op) { 3766 sys::swapByteOrder(op.name); 3767 sys::swapByteOrder(op.attributes); 3768 } 3769 3770 inline void swapStruct(struct category64_t &c) { 3771 sys::swapByteOrder(c.name); 3772 sys::swapByteOrder(c.cls); 3773 sys::swapByteOrder(c.instanceMethods); 3774 sys::swapByteOrder(c.classMethods); 3775 sys::swapByteOrder(c.protocols); 3776 sys::swapByteOrder(c.instanceProperties); 3777 } 3778 3779 inline void swapStruct(struct category32_t &c) { 3780 sys::swapByteOrder(c.name); 3781 sys::swapByteOrder(c.cls); 3782 sys::swapByteOrder(c.instanceMethods); 3783 sys::swapByteOrder(c.classMethods); 3784 sys::swapByteOrder(c.protocols); 3785 sys::swapByteOrder(c.instanceProperties); 3786 } 3787 3788 inline void swapStruct(struct objc_image_info64 &o) { 3789 sys::swapByteOrder(o.version); 3790 sys::swapByteOrder(o.flags); 3791 } 3792 3793 inline void swapStruct(struct objc_image_info32 &o) { 3794 sys::swapByteOrder(o.version); 3795 sys::swapByteOrder(o.flags); 3796 } 3797 3798 inline void swapStruct(struct imageInfo_t &o) { 3799 sys::swapByteOrder(o.version); 3800 sys::swapByteOrder(o.flags); 3801 } 3802 3803 inline void swapStruct(struct message_ref64 &mr) { 3804 sys::swapByteOrder(mr.imp); 3805 sys::swapByteOrder(mr.sel); 3806 } 3807 3808 inline void swapStruct(struct message_ref32 &mr) { 3809 sys::swapByteOrder(mr.imp); 3810 sys::swapByteOrder(mr.sel); 3811 } 3812 3813 inline void swapStruct(struct objc_module_t &module) { 3814 sys::swapByteOrder(module.version); 3815 sys::swapByteOrder(module.size); 3816 sys::swapByteOrder(module.name); 3817 sys::swapByteOrder(module.symtab); 3818 } 3819 3820 inline void swapStruct(struct objc_symtab_t &symtab) { 3821 sys::swapByteOrder(symtab.sel_ref_cnt); 3822 sys::swapByteOrder(symtab.refs); 3823 sys::swapByteOrder(symtab.cls_def_cnt); 3824 sys::swapByteOrder(symtab.cat_def_cnt); 3825 } 3826 3827 inline void swapStruct(struct objc_class_t &objc_class) { 3828 sys::swapByteOrder(objc_class.isa); 3829 sys::swapByteOrder(objc_class.super_class); 3830 sys::swapByteOrder(objc_class.name); 3831 sys::swapByteOrder(objc_class.version); 3832 sys::swapByteOrder(objc_class.info); 3833 sys::swapByteOrder(objc_class.instance_size); 3834 sys::swapByteOrder(objc_class.ivars); 3835 sys::swapByteOrder(objc_class.methodLists); 3836 sys::swapByteOrder(objc_class.cache); 3837 sys::swapByteOrder(objc_class.protocols); 3838 } 3839 3840 inline void swapStruct(struct objc_category_t &objc_category) { 3841 sys::swapByteOrder(objc_category.category_name); 3842 sys::swapByteOrder(objc_category.class_name); 3843 sys::swapByteOrder(objc_category.instance_methods); 3844 sys::swapByteOrder(objc_category.class_methods); 3845 sys::swapByteOrder(objc_category.protocols); 3846 } 3847 3848 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 3849 sys::swapByteOrder(objc_ivar_list.ivar_count); 3850 } 3851 3852 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 3853 sys::swapByteOrder(objc_ivar.ivar_name); 3854 sys::swapByteOrder(objc_ivar.ivar_type); 3855 sys::swapByteOrder(objc_ivar.ivar_offset); 3856 } 3857 3858 inline void swapStruct(struct objc_method_list_t &method_list) { 3859 sys::swapByteOrder(method_list.obsolete); 3860 sys::swapByteOrder(method_list.method_count); 3861 } 3862 3863 inline void swapStruct(struct objc_method_t &method) { 3864 sys::swapByteOrder(method.method_name); 3865 sys::swapByteOrder(method.method_types); 3866 sys::swapByteOrder(method.method_imp); 3867 } 3868 3869 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 3870 sys::swapByteOrder(protocol_list.next); 3871 sys::swapByteOrder(protocol_list.count); 3872 } 3873 3874 inline void swapStruct(struct objc_protocol_t &protocol) { 3875 sys::swapByteOrder(protocol.isa); 3876 sys::swapByteOrder(protocol.protocol_name); 3877 sys::swapByteOrder(protocol.protocol_list); 3878 sys::swapByteOrder(protocol.instance_methods); 3879 sys::swapByteOrder(protocol.class_methods); 3880 } 3881 3882 inline void swapStruct(struct objc_method_description_list_t &mdl) { 3883 sys::swapByteOrder(mdl.count); 3884 } 3885 3886 inline void swapStruct(struct objc_method_description_t &md) { 3887 sys::swapByteOrder(md.name); 3888 sys::swapByteOrder(md.types); 3889 } 3890 3891 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 3892 struct DisassembleInfo *info); 3893 3894 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 3895 // to an Objective-C class and returns the class name. It is also passed the 3896 // address of the pointer, so when the pointer is zero as it can be in an .o 3897 // file, that is used to look for an external relocation entry with a symbol 3898 // name. 3899 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 3900 uint64_t ReferenceValue, 3901 struct DisassembleInfo *info) { 3902 const char *r; 3903 uint32_t offset, left; 3904 SectionRef S; 3905 3906 // The pointer_value can be 0 in an object file and have a relocation 3907 // entry for the class symbol at the ReferenceValue (the address of the 3908 // pointer). 3909 if (pointer_value == 0) { 3910 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3911 if (r == nullptr || left < sizeof(uint64_t)) 3912 return nullptr; 3913 uint64_t n_value; 3914 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3915 if (symbol_name == nullptr) 3916 return nullptr; 3917 const char *class_name = strrchr(symbol_name, '$'); 3918 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 3919 return class_name + 2; 3920 else 3921 return nullptr; 3922 } 3923 3924 // The case were the pointer_value is non-zero and points to a class defined 3925 // in this Mach-O file. 3926 r = get_pointer_64(pointer_value, offset, left, S, info); 3927 if (r == nullptr || left < sizeof(struct class64_t)) 3928 return nullptr; 3929 struct class64_t c; 3930 memcpy(&c, r, sizeof(struct class64_t)); 3931 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3932 swapStruct(c); 3933 if (c.data == 0) 3934 return nullptr; 3935 r = get_pointer_64(c.data, offset, left, S, info); 3936 if (r == nullptr || left < sizeof(struct class_ro64_t)) 3937 return nullptr; 3938 struct class_ro64_t cro; 3939 memcpy(&cro, r, sizeof(struct class_ro64_t)); 3940 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3941 swapStruct(cro); 3942 if (cro.name == 0) 3943 return nullptr; 3944 const char *name = get_pointer_64(cro.name, offset, left, S, info); 3945 return name; 3946 } 3947 3948 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 3949 // pointer to a cfstring and returns its name or nullptr. 3950 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 3951 struct DisassembleInfo *info) { 3952 const char *r, *name; 3953 uint32_t offset, left; 3954 SectionRef S; 3955 struct cfstring64_t cfs; 3956 uint64_t cfs_characters; 3957 3958 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3959 if (r == nullptr || left < sizeof(struct cfstring64_t)) 3960 return nullptr; 3961 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 3962 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3963 swapStruct(cfs); 3964 if (cfs.characters == 0) { 3965 uint64_t n_value; 3966 const char *symbol_name = get_symbol_64( 3967 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 3968 if (symbol_name == nullptr) 3969 return nullptr; 3970 cfs_characters = n_value; 3971 } else 3972 cfs_characters = cfs.characters; 3973 name = get_pointer_64(cfs_characters, offset, left, S, info); 3974 3975 return name; 3976 } 3977 3978 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 3979 // of a pointer to an Objective-C selector reference when the pointer value is 3980 // zero as in a .o file and is likely to have a external relocation entry with 3981 // who's symbol's n_value is the real pointer to the selector name. If that is 3982 // the case the real pointer to the selector name is returned else 0 is 3983 // returned 3984 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 3985 struct DisassembleInfo *info) { 3986 uint32_t offset, left; 3987 SectionRef S; 3988 3989 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 3990 if (r == nullptr || left < sizeof(uint64_t)) 3991 return 0; 3992 uint64_t n_value; 3993 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3994 if (symbol_name == nullptr) 3995 return 0; 3996 return n_value; 3997 } 3998 3999 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 4000 const char *sectname) { 4001 for (const SectionRef &Section : O->sections()) { 4002 StringRef SectName; 4003 Section.getName(SectName); 4004 DataRefImpl Ref = Section.getRawDataRefImpl(); 4005 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4006 if (SegName == segname && SectName == sectname) 4007 return Section; 4008 } 4009 return SectionRef(); 4010 } 4011 4012 static void 4013 walk_pointer_list_64(const char *listname, const SectionRef S, 4014 MachOObjectFile *O, struct DisassembleInfo *info, 4015 void (*func)(uint64_t, struct DisassembleInfo *info)) { 4016 if (S == SectionRef()) 4017 return; 4018 4019 StringRef SectName; 4020 S.getName(SectName); 4021 DataRefImpl Ref = S.getRawDataRefImpl(); 4022 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4023 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4024 4025 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4026 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4027 4028 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 4029 uint32_t left = S.getSize() - i; 4030 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 4031 uint64_t p = 0; 4032 memcpy(&p, Contents + i, size); 4033 if (i + sizeof(uint64_t) > S.getSize()) 4034 outs() << listname << " list pointer extends past end of (" << SegName 4035 << "," << SectName << ") section\n"; 4036 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 4037 4038 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4039 sys::swapByteOrder(p); 4040 4041 uint64_t n_value = 0; 4042 const char *name = get_symbol_64(i, S, info, n_value, p); 4043 if (name == nullptr) 4044 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 4045 4046 if (n_value != 0) { 4047 outs() << format("0x%" PRIx64, n_value); 4048 if (p != 0) 4049 outs() << " + " << format("0x%" PRIx64, p); 4050 } else 4051 outs() << format("0x%" PRIx64, p); 4052 if (name != nullptr) 4053 outs() << " " << name; 4054 outs() << "\n"; 4055 4056 p += n_value; 4057 if (func) 4058 func(p, info); 4059 } 4060 } 4061 4062 static void 4063 walk_pointer_list_32(const char *listname, const SectionRef S, 4064 MachOObjectFile *O, struct DisassembleInfo *info, 4065 void (*func)(uint32_t, struct DisassembleInfo *info)) { 4066 if (S == SectionRef()) 4067 return; 4068 4069 StringRef SectName; 4070 S.getName(SectName); 4071 DataRefImpl Ref = S.getRawDataRefImpl(); 4072 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4073 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4074 4075 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4076 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4077 4078 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 4079 uint32_t left = S.getSize() - i; 4080 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 4081 uint32_t p = 0; 4082 memcpy(&p, Contents + i, size); 4083 if (i + sizeof(uint32_t) > S.getSize()) 4084 outs() << listname << " list pointer extends past end of (" << SegName 4085 << "," << SectName << ") section\n"; 4086 uint32_t Address = S.getAddress() + i; 4087 outs() << format("%08" PRIx32, Address) << " "; 4088 4089 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4090 sys::swapByteOrder(p); 4091 outs() << format("0x%" PRIx32, p); 4092 4093 const char *name = get_symbol_32(i, S, info, p); 4094 if (name != nullptr) 4095 outs() << " " << name; 4096 outs() << "\n"; 4097 4098 if (func) 4099 func(p, info); 4100 } 4101 } 4102 4103 static void print_layout_map(const char *layout_map, uint32_t left) { 4104 if (layout_map == nullptr) 4105 return; 4106 outs() << " layout map: "; 4107 do { 4108 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 4109 left--; 4110 layout_map++; 4111 } while (*layout_map != '\0' && left != 0); 4112 outs() << "\n"; 4113 } 4114 4115 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 4116 uint32_t offset, left; 4117 SectionRef S; 4118 const char *layout_map; 4119 4120 if (p == 0) 4121 return; 4122 layout_map = get_pointer_64(p, offset, left, S, info); 4123 print_layout_map(layout_map, left); 4124 } 4125 4126 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 4127 uint32_t offset, left; 4128 SectionRef S; 4129 const char *layout_map; 4130 4131 if (p == 0) 4132 return; 4133 layout_map = get_pointer_32(p, offset, left, S, info); 4134 print_layout_map(layout_map, left); 4135 } 4136 4137 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 4138 const char *indent) { 4139 struct method_list64_t ml; 4140 struct method64_t m; 4141 const char *r; 4142 uint32_t offset, xoffset, left, i; 4143 SectionRef S, xS; 4144 const char *name, *sym_name; 4145 uint64_t n_value; 4146 4147 r = get_pointer_64(p, offset, left, S, info); 4148 if (r == nullptr) 4149 return; 4150 memset(&ml, '\0', sizeof(struct method_list64_t)); 4151 if (left < sizeof(struct method_list64_t)) { 4152 memcpy(&ml, r, left); 4153 outs() << " (method_list_t entends past the end of the section)\n"; 4154 } else 4155 memcpy(&ml, r, sizeof(struct method_list64_t)); 4156 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4157 swapStruct(ml); 4158 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4159 outs() << indent << "\t\t count " << ml.count << "\n"; 4160 4161 p += sizeof(struct method_list64_t); 4162 offset += sizeof(struct method_list64_t); 4163 for (i = 0; i < ml.count; i++) { 4164 r = get_pointer_64(p, offset, left, S, info); 4165 if (r == nullptr) 4166 return; 4167 memset(&m, '\0', sizeof(struct method64_t)); 4168 if (left < sizeof(struct method64_t)) { 4169 memcpy(&m, r, left); 4170 outs() << indent << " (method_t extends past the end of the section)\n"; 4171 } else 4172 memcpy(&m, r, sizeof(struct method64_t)); 4173 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4174 swapStruct(m); 4175 4176 outs() << indent << "\t\t name "; 4177 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 4178 info, n_value, m.name); 4179 if (n_value != 0) { 4180 if (info->verbose && sym_name != nullptr) 4181 outs() << sym_name; 4182 else 4183 outs() << format("0x%" PRIx64, n_value); 4184 if (m.name != 0) 4185 outs() << " + " << format("0x%" PRIx64, m.name); 4186 } else 4187 outs() << format("0x%" PRIx64, m.name); 4188 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 4189 if (name != nullptr) 4190 outs() << format(" %.*s", left, name); 4191 outs() << "\n"; 4192 4193 outs() << indent << "\t\t types "; 4194 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 4195 info, n_value, m.types); 4196 if (n_value != 0) { 4197 if (info->verbose && sym_name != nullptr) 4198 outs() << sym_name; 4199 else 4200 outs() << format("0x%" PRIx64, n_value); 4201 if (m.types != 0) 4202 outs() << " + " << format("0x%" PRIx64, m.types); 4203 } else 4204 outs() << format("0x%" PRIx64, m.types); 4205 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 4206 if (name != nullptr) 4207 outs() << format(" %.*s", left, name); 4208 outs() << "\n"; 4209 4210 outs() << indent << "\t\t imp "; 4211 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 4212 n_value, m.imp); 4213 if (info->verbose && name == nullptr) { 4214 if (n_value != 0) { 4215 outs() << format("0x%" PRIx64, n_value) << " "; 4216 if (m.imp != 0) 4217 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 4218 } else 4219 outs() << format("0x%" PRIx64, m.imp) << " "; 4220 } 4221 if (name != nullptr) 4222 outs() << name; 4223 outs() << "\n"; 4224 4225 p += sizeof(struct method64_t); 4226 offset += sizeof(struct method64_t); 4227 } 4228 } 4229 4230 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 4231 const char *indent) { 4232 struct method_list32_t ml; 4233 struct method32_t m; 4234 const char *r, *name; 4235 uint32_t offset, xoffset, left, i; 4236 SectionRef S, xS; 4237 4238 r = get_pointer_32(p, offset, left, S, info); 4239 if (r == nullptr) 4240 return; 4241 memset(&ml, '\0', sizeof(struct method_list32_t)); 4242 if (left < sizeof(struct method_list32_t)) { 4243 memcpy(&ml, r, left); 4244 outs() << " (method_list_t entends past the end of the section)\n"; 4245 } else 4246 memcpy(&ml, r, sizeof(struct method_list32_t)); 4247 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4248 swapStruct(ml); 4249 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4250 outs() << indent << "\t\t count " << ml.count << "\n"; 4251 4252 p += sizeof(struct method_list32_t); 4253 offset += sizeof(struct method_list32_t); 4254 for (i = 0; i < ml.count; i++) { 4255 r = get_pointer_32(p, offset, left, S, info); 4256 if (r == nullptr) 4257 return; 4258 memset(&m, '\0', sizeof(struct method32_t)); 4259 if (left < sizeof(struct method32_t)) { 4260 memcpy(&ml, r, left); 4261 outs() << indent << " (method_t entends past the end of the section)\n"; 4262 } else 4263 memcpy(&m, r, sizeof(struct method32_t)); 4264 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4265 swapStruct(m); 4266 4267 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 4268 name = get_pointer_32(m.name, xoffset, left, xS, info); 4269 if (name != nullptr) 4270 outs() << format(" %.*s", left, name); 4271 outs() << "\n"; 4272 4273 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 4274 name = get_pointer_32(m.types, xoffset, left, xS, info); 4275 if (name != nullptr) 4276 outs() << format(" %.*s", left, name); 4277 outs() << "\n"; 4278 4279 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4280 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 4281 m.imp); 4282 if (name != nullptr) 4283 outs() << " " << name; 4284 outs() << "\n"; 4285 4286 p += sizeof(struct method32_t); 4287 offset += sizeof(struct method32_t); 4288 } 4289 } 4290 4291 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 4292 uint32_t offset, left, xleft; 4293 SectionRef S; 4294 struct objc_method_list_t method_list; 4295 struct objc_method_t method; 4296 const char *r, *methods, *name, *SymbolName; 4297 int32_t i; 4298 4299 r = get_pointer_32(p, offset, left, S, info, true); 4300 if (r == nullptr) 4301 return true; 4302 4303 outs() << "\n"; 4304 if (left > sizeof(struct objc_method_list_t)) { 4305 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 4306 } else { 4307 outs() << "\t\t objc_method_list extends past end of the section\n"; 4308 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 4309 memcpy(&method_list, r, left); 4310 } 4311 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4312 swapStruct(method_list); 4313 4314 outs() << "\t\t obsolete " 4315 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4316 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4317 4318 methods = r + sizeof(struct objc_method_list_t); 4319 for (i = 0; i < method_list.method_count; i++) { 4320 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4321 outs() << "\t\t remaining method's extend past the of the section\n"; 4322 break; 4323 } 4324 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4325 sizeof(struct objc_method_t)); 4326 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4327 swapStruct(method); 4328 4329 outs() << "\t\t method_name " 4330 << format("0x%08" PRIx32, method.method_name); 4331 if (info->verbose) { 4332 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4333 if (name != nullptr) 4334 outs() << format(" %.*s", xleft, name); 4335 else 4336 outs() << " (not in an __OBJC section)"; 4337 } 4338 outs() << "\n"; 4339 4340 outs() << "\t\t method_types " 4341 << format("0x%08" PRIx32, method.method_types); 4342 if (info->verbose) { 4343 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4344 if (name != nullptr) 4345 outs() << format(" %.*s", xleft, name); 4346 else 4347 outs() << " (not in an __OBJC section)"; 4348 } 4349 outs() << "\n"; 4350 4351 outs() << "\t\t method_imp " 4352 << format("0x%08" PRIx32, method.method_imp) << " "; 4353 if (info->verbose) { 4354 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4355 if (SymbolName != nullptr) 4356 outs() << SymbolName; 4357 } 4358 outs() << "\n"; 4359 } 4360 return false; 4361 } 4362 4363 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4364 struct protocol_list64_t pl; 4365 uint64_t q, n_value; 4366 struct protocol64_t pc; 4367 const char *r; 4368 uint32_t offset, xoffset, left, i; 4369 SectionRef S, xS; 4370 const char *name, *sym_name; 4371 4372 r = get_pointer_64(p, offset, left, S, info); 4373 if (r == nullptr) 4374 return; 4375 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4376 if (left < sizeof(struct protocol_list64_t)) { 4377 memcpy(&pl, r, left); 4378 outs() << " (protocol_list_t entends past the end of the section)\n"; 4379 } else 4380 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4381 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4382 swapStruct(pl); 4383 outs() << " count " << pl.count << "\n"; 4384 4385 p += sizeof(struct protocol_list64_t); 4386 offset += sizeof(struct protocol_list64_t); 4387 for (i = 0; i < pl.count; i++) { 4388 r = get_pointer_64(p, offset, left, S, info); 4389 if (r == nullptr) 4390 return; 4391 q = 0; 4392 if (left < sizeof(uint64_t)) { 4393 memcpy(&q, r, left); 4394 outs() << " (protocol_t * entends past the end of the section)\n"; 4395 } else 4396 memcpy(&q, r, sizeof(uint64_t)); 4397 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4398 sys::swapByteOrder(q); 4399 4400 outs() << "\t\t list[" << i << "] "; 4401 sym_name = get_symbol_64(offset, S, info, n_value, q); 4402 if (n_value != 0) { 4403 if (info->verbose && sym_name != nullptr) 4404 outs() << sym_name; 4405 else 4406 outs() << format("0x%" PRIx64, n_value); 4407 if (q != 0) 4408 outs() << " + " << format("0x%" PRIx64, q); 4409 } else 4410 outs() << format("0x%" PRIx64, q); 4411 outs() << " (struct protocol_t *)\n"; 4412 4413 r = get_pointer_64(q + n_value, offset, left, S, info); 4414 if (r == nullptr) 4415 return; 4416 memset(&pc, '\0', sizeof(struct protocol64_t)); 4417 if (left < sizeof(struct protocol64_t)) { 4418 memcpy(&pc, r, left); 4419 outs() << " (protocol_t entends past the end of the section)\n"; 4420 } else 4421 memcpy(&pc, r, sizeof(struct protocol64_t)); 4422 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4423 swapStruct(pc); 4424 4425 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4426 4427 outs() << "\t\t\t name "; 4428 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4429 info, n_value, pc.name); 4430 if (n_value != 0) { 4431 if (info->verbose && sym_name != nullptr) 4432 outs() << sym_name; 4433 else 4434 outs() << format("0x%" PRIx64, n_value); 4435 if (pc.name != 0) 4436 outs() << " + " << format("0x%" PRIx64, pc.name); 4437 } else 4438 outs() << format("0x%" PRIx64, pc.name); 4439 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4440 if (name != nullptr) 4441 outs() << format(" %.*s", left, name); 4442 outs() << "\n"; 4443 4444 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4445 4446 outs() << "\t\t instanceMethods "; 4447 sym_name = 4448 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4449 S, info, n_value, pc.instanceMethods); 4450 if (n_value != 0) { 4451 if (info->verbose && sym_name != nullptr) 4452 outs() << sym_name; 4453 else 4454 outs() << format("0x%" PRIx64, n_value); 4455 if (pc.instanceMethods != 0) 4456 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4457 } else 4458 outs() << format("0x%" PRIx64, pc.instanceMethods); 4459 outs() << " (struct method_list_t *)\n"; 4460 if (pc.instanceMethods + n_value != 0) 4461 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4462 4463 outs() << "\t\t classMethods "; 4464 sym_name = 4465 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4466 info, n_value, pc.classMethods); 4467 if (n_value != 0) { 4468 if (info->verbose && sym_name != nullptr) 4469 outs() << sym_name; 4470 else 4471 outs() << format("0x%" PRIx64, n_value); 4472 if (pc.classMethods != 0) 4473 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4474 } else 4475 outs() << format("0x%" PRIx64, pc.classMethods); 4476 outs() << " (struct method_list_t *)\n"; 4477 if (pc.classMethods + n_value != 0) 4478 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4479 4480 outs() << "\t optionalInstanceMethods " 4481 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4482 outs() << "\t optionalClassMethods " 4483 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4484 outs() << "\t instanceProperties " 4485 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4486 4487 p += sizeof(uint64_t); 4488 offset += sizeof(uint64_t); 4489 } 4490 } 4491 4492 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4493 struct protocol_list32_t pl; 4494 uint32_t q; 4495 struct protocol32_t pc; 4496 const char *r; 4497 uint32_t offset, xoffset, left, i; 4498 SectionRef S, xS; 4499 const char *name; 4500 4501 r = get_pointer_32(p, offset, left, S, info); 4502 if (r == nullptr) 4503 return; 4504 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4505 if (left < sizeof(struct protocol_list32_t)) { 4506 memcpy(&pl, r, left); 4507 outs() << " (protocol_list_t entends past the end of the section)\n"; 4508 } else 4509 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4510 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4511 swapStruct(pl); 4512 outs() << " count " << pl.count << "\n"; 4513 4514 p += sizeof(struct protocol_list32_t); 4515 offset += sizeof(struct protocol_list32_t); 4516 for (i = 0; i < pl.count; i++) { 4517 r = get_pointer_32(p, offset, left, S, info); 4518 if (r == nullptr) 4519 return; 4520 q = 0; 4521 if (left < sizeof(uint32_t)) { 4522 memcpy(&q, r, left); 4523 outs() << " (protocol_t * entends past the end of the section)\n"; 4524 } else 4525 memcpy(&q, r, sizeof(uint32_t)); 4526 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4527 sys::swapByteOrder(q); 4528 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4529 << " (struct protocol_t *)\n"; 4530 r = get_pointer_32(q, offset, left, S, info); 4531 if (r == nullptr) 4532 return; 4533 memset(&pc, '\0', sizeof(struct protocol32_t)); 4534 if (left < sizeof(struct protocol32_t)) { 4535 memcpy(&pc, r, left); 4536 outs() << " (protocol_t entends past the end of the section)\n"; 4537 } else 4538 memcpy(&pc, r, sizeof(struct protocol32_t)); 4539 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4540 swapStruct(pc); 4541 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4542 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4543 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4544 if (name != nullptr) 4545 outs() << format(" %.*s", left, name); 4546 outs() << "\n"; 4547 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4548 outs() << "\t\t instanceMethods " 4549 << format("0x%" PRIx32, pc.instanceMethods) 4550 << " (struct method_list_t *)\n"; 4551 if (pc.instanceMethods != 0) 4552 print_method_list32_t(pc.instanceMethods, info, "\t"); 4553 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4554 << " (struct method_list_t *)\n"; 4555 if (pc.classMethods != 0) 4556 print_method_list32_t(pc.classMethods, info, "\t"); 4557 outs() << "\t optionalInstanceMethods " 4558 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4559 outs() << "\t optionalClassMethods " 4560 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4561 outs() << "\t instanceProperties " 4562 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4563 p += sizeof(uint32_t); 4564 offset += sizeof(uint32_t); 4565 } 4566 } 4567 4568 static void print_indent(uint32_t indent) { 4569 for (uint32_t i = 0; i < indent;) { 4570 if (indent - i >= 8) { 4571 outs() << "\t"; 4572 i += 8; 4573 } else { 4574 for (uint32_t j = i; j < indent; j++) 4575 outs() << " "; 4576 return; 4577 } 4578 } 4579 } 4580 4581 static bool print_method_description_list(uint32_t p, uint32_t indent, 4582 struct DisassembleInfo *info) { 4583 uint32_t offset, left, xleft; 4584 SectionRef S; 4585 struct objc_method_description_list_t mdl; 4586 struct objc_method_description_t md; 4587 const char *r, *list, *name; 4588 int32_t i; 4589 4590 r = get_pointer_32(p, offset, left, S, info, true); 4591 if (r == nullptr) 4592 return true; 4593 4594 outs() << "\n"; 4595 if (left > sizeof(struct objc_method_description_list_t)) { 4596 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 4597 } else { 4598 print_indent(indent); 4599 outs() << " objc_method_description_list extends past end of the section\n"; 4600 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 4601 memcpy(&mdl, r, left); 4602 } 4603 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4604 swapStruct(mdl); 4605 4606 print_indent(indent); 4607 outs() << " count " << mdl.count << "\n"; 4608 4609 list = r + sizeof(struct objc_method_description_list_t); 4610 for (i = 0; i < mdl.count; i++) { 4611 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 4612 print_indent(indent); 4613 outs() << " remaining list entries extend past the of the section\n"; 4614 break; 4615 } 4616 print_indent(indent); 4617 outs() << " list[" << i << "]\n"; 4618 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 4619 sizeof(struct objc_method_description_t)); 4620 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4621 swapStruct(md); 4622 4623 print_indent(indent); 4624 outs() << " name " << format("0x%08" PRIx32, md.name); 4625 if (info->verbose) { 4626 name = get_pointer_32(md.name, offset, xleft, S, info, true); 4627 if (name != nullptr) 4628 outs() << format(" %.*s", xleft, name); 4629 else 4630 outs() << " (not in an __OBJC section)"; 4631 } 4632 outs() << "\n"; 4633 4634 print_indent(indent); 4635 outs() << " types " << format("0x%08" PRIx32, md.types); 4636 if (info->verbose) { 4637 name = get_pointer_32(md.types, offset, xleft, S, info, true); 4638 if (name != nullptr) 4639 outs() << format(" %.*s", xleft, name); 4640 else 4641 outs() << " (not in an __OBJC section)"; 4642 } 4643 outs() << "\n"; 4644 } 4645 return false; 4646 } 4647 4648 static bool print_protocol_list(uint32_t p, uint32_t indent, 4649 struct DisassembleInfo *info); 4650 4651 static bool print_protocol(uint32_t p, uint32_t indent, 4652 struct DisassembleInfo *info) { 4653 uint32_t offset, left; 4654 SectionRef S; 4655 struct objc_protocol_t protocol; 4656 const char *r, *name; 4657 4658 r = get_pointer_32(p, offset, left, S, info, true); 4659 if (r == nullptr) 4660 return true; 4661 4662 outs() << "\n"; 4663 if (left >= sizeof(struct objc_protocol_t)) { 4664 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 4665 } else { 4666 print_indent(indent); 4667 outs() << " Protocol extends past end of the section\n"; 4668 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 4669 memcpy(&protocol, r, left); 4670 } 4671 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4672 swapStruct(protocol); 4673 4674 print_indent(indent); 4675 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 4676 << "\n"; 4677 4678 print_indent(indent); 4679 outs() << " protocol_name " 4680 << format("0x%08" PRIx32, protocol.protocol_name); 4681 if (info->verbose) { 4682 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 4683 if (name != nullptr) 4684 outs() << format(" %.*s", left, name); 4685 else 4686 outs() << " (not in an __OBJC section)"; 4687 } 4688 outs() << "\n"; 4689 4690 print_indent(indent); 4691 outs() << " protocol_list " 4692 << format("0x%08" PRIx32, protocol.protocol_list); 4693 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 4694 outs() << " (not in an __OBJC section)\n"; 4695 4696 print_indent(indent); 4697 outs() << " instance_methods " 4698 << format("0x%08" PRIx32, protocol.instance_methods); 4699 if (print_method_description_list(protocol.instance_methods, indent, info)) 4700 outs() << " (not in an __OBJC section)\n"; 4701 4702 print_indent(indent); 4703 outs() << " class_methods " 4704 << format("0x%08" PRIx32, protocol.class_methods); 4705 if (print_method_description_list(protocol.class_methods, indent, info)) 4706 outs() << " (not in an __OBJC section)\n"; 4707 4708 return false; 4709 } 4710 4711 static bool print_protocol_list(uint32_t p, uint32_t indent, 4712 struct DisassembleInfo *info) { 4713 uint32_t offset, left, l; 4714 SectionRef S; 4715 struct objc_protocol_list_t protocol_list; 4716 const char *r, *list; 4717 int32_t i; 4718 4719 r = get_pointer_32(p, offset, left, S, info, true); 4720 if (r == nullptr) 4721 return true; 4722 4723 outs() << "\n"; 4724 if (left > sizeof(struct objc_protocol_list_t)) { 4725 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 4726 } else { 4727 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 4728 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 4729 memcpy(&protocol_list, r, left); 4730 } 4731 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4732 swapStruct(protocol_list); 4733 4734 print_indent(indent); 4735 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 4736 << "\n"; 4737 print_indent(indent); 4738 outs() << " count " << protocol_list.count << "\n"; 4739 4740 list = r + sizeof(struct objc_protocol_list_t); 4741 for (i = 0; i < protocol_list.count; i++) { 4742 if ((i + 1) * sizeof(uint32_t) > left) { 4743 outs() << "\t\t remaining list entries extend past the of the section\n"; 4744 break; 4745 } 4746 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 4747 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4748 sys::swapByteOrder(l); 4749 4750 print_indent(indent); 4751 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 4752 if (print_protocol(l, indent, info)) 4753 outs() << "(not in an __OBJC section)\n"; 4754 } 4755 return false; 4756 } 4757 4758 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 4759 struct ivar_list64_t il; 4760 struct ivar64_t i; 4761 const char *r; 4762 uint32_t offset, xoffset, left, j; 4763 SectionRef S, xS; 4764 const char *name, *sym_name, *ivar_offset_p; 4765 uint64_t ivar_offset, n_value; 4766 4767 r = get_pointer_64(p, offset, left, S, info); 4768 if (r == nullptr) 4769 return; 4770 memset(&il, '\0', sizeof(struct ivar_list64_t)); 4771 if (left < sizeof(struct ivar_list64_t)) { 4772 memcpy(&il, r, left); 4773 outs() << " (ivar_list_t entends past the end of the section)\n"; 4774 } else 4775 memcpy(&il, r, sizeof(struct ivar_list64_t)); 4776 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4777 swapStruct(il); 4778 outs() << " entsize " << il.entsize << "\n"; 4779 outs() << " count " << il.count << "\n"; 4780 4781 p += sizeof(struct ivar_list64_t); 4782 offset += sizeof(struct ivar_list64_t); 4783 for (j = 0; j < il.count; j++) { 4784 r = get_pointer_64(p, offset, left, S, info); 4785 if (r == nullptr) 4786 return; 4787 memset(&i, '\0', sizeof(struct ivar64_t)); 4788 if (left < sizeof(struct ivar64_t)) { 4789 memcpy(&i, r, left); 4790 outs() << " (ivar_t entends past the end of the section)\n"; 4791 } else 4792 memcpy(&i, r, sizeof(struct ivar64_t)); 4793 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4794 swapStruct(i); 4795 4796 outs() << "\t\t\t offset "; 4797 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 4798 info, n_value, i.offset); 4799 if (n_value != 0) { 4800 if (info->verbose && sym_name != nullptr) 4801 outs() << sym_name; 4802 else 4803 outs() << format("0x%" PRIx64, n_value); 4804 if (i.offset != 0) 4805 outs() << " + " << format("0x%" PRIx64, i.offset); 4806 } else 4807 outs() << format("0x%" PRIx64, i.offset); 4808 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 4809 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4810 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4811 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4812 sys::swapByteOrder(ivar_offset); 4813 outs() << " " << ivar_offset << "\n"; 4814 } else 4815 outs() << "\n"; 4816 4817 outs() << "\t\t\t name "; 4818 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 4819 n_value, i.name); 4820 if (n_value != 0) { 4821 if (info->verbose && sym_name != nullptr) 4822 outs() << sym_name; 4823 else 4824 outs() << format("0x%" PRIx64, n_value); 4825 if (i.name != 0) 4826 outs() << " + " << format("0x%" PRIx64, i.name); 4827 } else 4828 outs() << format("0x%" PRIx64, i.name); 4829 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 4830 if (name != nullptr) 4831 outs() << format(" %.*s", left, name); 4832 outs() << "\n"; 4833 4834 outs() << "\t\t\t type "; 4835 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 4836 n_value, i.name); 4837 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 4838 if (n_value != 0) { 4839 if (info->verbose && sym_name != nullptr) 4840 outs() << sym_name; 4841 else 4842 outs() << format("0x%" PRIx64, n_value); 4843 if (i.type != 0) 4844 outs() << " + " << format("0x%" PRIx64, i.type); 4845 } else 4846 outs() << format("0x%" PRIx64, i.type); 4847 if (name != nullptr) 4848 outs() << format(" %.*s", left, name); 4849 outs() << "\n"; 4850 4851 outs() << "\t\t\talignment " << i.alignment << "\n"; 4852 outs() << "\t\t\t size " << i.size << "\n"; 4853 4854 p += sizeof(struct ivar64_t); 4855 offset += sizeof(struct ivar64_t); 4856 } 4857 } 4858 4859 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 4860 struct ivar_list32_t il; 4861 struct ivar32_t i; 4862 const char *r; 4863 uint32_t offset, xoffset, left, j; 4864 SectionRef S, xS; 4865 const char *name, *ivar_offset_p; 4866 uint32_t ivar_offset; 4867 4868 r = get_pointer_32(p, offset, left, S, info); 4869 if (r == nullptr) 4870 return; 4871 memset(&il, '\0', sizeof(struct ivar_list32_t)); 4872 if (left < sizeof(struct ivar_list32_t)) { 4873 memcpy(&il, r, left); 4874 outs() << " (ivar_list_t entends past the end of the section)\n"; 4875 } else 4876 memcpy(&il, r, sizeof(struct ivar_list32_t)); 4877 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4878 swapStruct(il); 4879 outs() << " entsize " << il.entsize << "\n"; 4880 outs() << " count " << il.count << "\n"; 4881 4882 p += sizeof(struct ivar_list32_t); 4883 offset += sizeof(struct ivar_list32_t); 4884 for (j = 0; j < il.count; j++) { 4885 r = get_pointer_32(p, offset, left, S, info); 4886 if (r == nullptr) 4887 return; 4888 memset(&i, '\0', sizeof(struct ivar32_t)); 4889 if (left < sizeof(struct ivar32_t)) { 4890 memcpy(&i, r, left); 4891 outs() << " (ivar_t entends past the end of the section)\n"; 4892 } else 4893 memcpy(&i, r, sizeof(struct ivar32_t)); 4894 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4895 swapStruct(i); 4896 4897 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 4898 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 4899 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4900 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4901 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4902 sys::swapByteOrder(ivar_offset); 4903 outs() << " " << ivar_offset << "\n"; 4904 } else 4905 outs() << "\n"; 4906 4907 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 4908 name = get_pointer_32(i.name, xoffset, left, xS, info); 4909 if (name != nullptr) 4910 outs() << format(" %.*s", left, name); 4911 outs() << "\n"; 4912 4913 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 4914 name = get_pointer_32(i.type, xoffset, left, xS, info); 4915 if (name != nullptr) 4916 outs() << format(" %.*s", left, name); 4917 outs() << "\n"; 4918 4919 outs() << "\t\t\talignment " << i.alignment << "\n"; 4920 outs() << "\t\t\t size " << i.size << "\n"; 4921 4922 p += sizeof(struct ivar32_t); 4923 offset += sizeof(struct ivar32_t); 4924 } 4925 } 4926 4927 static void print_objc_property_list64(uint64_t p, 4928 struct DisassembleInfo *info) { 4929 struct objc_property_list64 opl; 4930 struct objc_property64 op; 4931 const char *r; 4932 uint32_t offset, xoffset, left, j; 4933 SectionRef S, xS; 4934 const char *name, *sym_name; 4935 uint64_t n_value; 4936 4937 r = get_pointer_64(p, offset, left, S, info); 4938 if (r == nullptr) 4939 return; 4940 memset(&opl, '\0', sizeof(struct objc_property_list64)); 4941 if (left < sizeof(struct objc_property_list64)) { 4942 memcpy(&opl, r, left); 4943 outs() << " (objc_property_list entends past the end of the section)\n"; 4944 } else 4945 memcpy(&opl, r, sizeof(struct objc_property_list64)); 4946 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4947 swapStruct(opl); 4948 outs() << " entsize " << opl.entsize << "\n"; 4949 outs() << " count " << opl.count << "\n"; 4950 4951 p += sizeof(struct objc_property_list64); 4952 offset += sizeof(struct objc_property_list64); 4953 for (j = 0; j < opl.count; j++) { 4954 r = get_pointer_64(p, offset, left, S, info); 4955 if (r == nullptr) 4956 return; 4957 memset(&op, '\0', sizeof(struct objc_property64)); 4958 if (left < sizeof(struct objc_property64)) { 4959 memcpy(&op, r, left); 4960 outs() << " (objc_property entends past the end of the section)\n"; 4961 } else 4962 memcpy(&op, r, sizeof(struct objc_property64)); 4963 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4964 swapStruct(op); 4965 4966 outs() << "\t\t\t name "; 4967 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 4968 info, n_value, op.name); 4969 if (n_value != 0) { 4970 if (info->verbose && sym_name != nullptr) 4971 outs() << sym_name; 4972 else 4973 outs() << format("0x%" PRIx64, n_value); 4974 if (op.name != 0) 4975 outs() << " + " << format("0x%" PRIx64, op.name); 4976 } else 4977 outs() << format("0x%" PRIx64, op.name); 4978 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 4979 if (name != nullptr) 4980 outs() << format(" %.*s", left, name); 4981 outs() << "\n"; 4982 4983 outs() << "\t\t\tattributes "; 4984 sym_name = 4985 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 4986 info, n_value, op.attributes); 4987 if (n_value != 0) { 4988 if (info->verbose && sym_name != nullptr) 4989 outs() << sym_name; 4990 else 4991 outs() << format("0x%" PRIx64, n_value); 4992 if (op.attributes != 0) 4993 outs() << " + " << format("0x%" PRIx64, op.attributes); 4994 } else 4995 outs() << format("0x%" PRIx64, op.attributes); 4996 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 4997 if (name != nullptr) 4998 outs() << format(" %.*s", left, name); 4999 outs() << "\n"; 5000 5001 p += sizeof(struct objc_property64); 5002 offset += sizeof(struct objc_property64); 5003 } 5004 } 5005 5006 static void print_objc_property_list32(uint32_t p, 5007 struct DisassembleInfo *info) { 5008 struct objc_property_list32 opl; 5009 struct objc_property32 op; 5010 const char *r; 5011 uint32_t offset, xoffset, left, j; 5012 SectionRef S, xS; 5013 const char *name; 5014 5015 r = get_pointer_32(p, offset, left, S, info); 5016 if (r == nullptr) 5017 return; 5018 memset(&opl, '\0', sizeof(struct objc_property_list32)); 5019 if (left < sizeof(struct objc_property_list32)) { 5020 memcpy(&opl, r, left); 5021 outs() << " (objc_property_list entends past the end of the section)\n"; 5022 } else 5023 memcpy(&opl, r, sizeof(struct objc_property_list32)); 5024 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5025 swapStruct(opl); 5026 outs() << " entsize " << opl.entsize << "\n"; 5027 outs() << " count " << opl.count << "\n"; 5028 5029 p += sizeof(struct objc_property_list32); 5030 offset += sizeof(struct objc_property_list32); 5031 for (j = 0; j < opl.count; j++) { 5032 r = get_pointer_32(p, offset, left, S, info); 5033 if (r == nullptr) 5034 return; 5035 memset(&op, '\0', sizeof(struct objc_property32)); 5036 if (left < sizeof(struct objc_property32)) { 5037 memcpy(&op, r, left); 5038 outs() << " (objc_property entends past the end of the section)\n"; 5039 } else 5040 memcpy(&op, r, sizeof(struct objc_property32)); 5041 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5042 swapStruct(op); 5043 5044 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 5045 name = get_pointer_32(op.name, xoffset, left, xS, info); 5046 if (name != nullptr) 5047 outs() << format(" %.*s", left, name); 5048 outs() << "\n"; 5049 5050 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 5051 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 5052 if (name != nullptr) 5053 outs() << format(" %.*s", left, name); 5054 outs() << "\n"; 5055 5056 p += sizeof(struct objc_property32); 5057 offset += sizeof(struct objc_property32); 5058 } 5059 } 5060 5061 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 5062 bool &is_meta_class) { 5063 struct class_ro64_t cro; 5064 const char *r; 5065 uint32_t offset, xoffset, left; 5066 SectionRef S, xS; 5067 const char *name, *sym_name; 5068 uint64_t n_value; 5069 5070 r = get_pointer_64(p, offset, left, S, info); 5071 if (r == nullptr || left < sizeof(struct class_ro64_t)) 5072 return false; 5073 memcpy(&cro, r, sizeof(struct class_ro64_t)); 5074 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5075 swapStruct(cro); 5076 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5077 if (cro.flags & RO_META) 5078 outs() << " RO_META"; 5079 if (cro.flags & RO_ROOT) 5080 outs() << " RO_ROOT"; 5081 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5082 outs() << " RO_HAS_CXX_STRUCTORS"; 5083 outs() << "\n"; 5084 outs() << " instanceStart " << cro.instanceStart << "\n"; 5085 outs() << " instanceSize " << cro.instanceSize << "\n"; 5086 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 5087 << "\n"; 5088 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 5089 << "\n"; 5090 print_layout_map64(cro.ivarLayout, info); 5091 5092 outs() << " name "; 5093 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 5094 info, n_value, cro.name); 5095 if (n_value != 0) { 5096 if (info->verbose && sym_name != nullptr) 5097 outs() << sym_name; 5098 else 5099 outs() << format("0x%" PRIx64, n_value); 5100 if (cro.name != 0) 5101 outs() << " + " << format("0x%" PRIx64, cro.name); 5102 } else 5103 outs() << format("0x%" PRIx64, cro.name); 5104 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 5105 if (name != nullptr) 5106 outs() << format(" %.*s", left, name); 5107 outs() << "\n"; 5108 5109 outs() << " baseMethods "; 5110 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 5111 S, info, n_value, cro.baseMethods); 5112 if (n_value != 0) { 5113 if (info->verbose && sym_name != nullptr) 5114 outs() << sym_name; 5115 else 5116 outs() << format("0x%" PRIx64, n_value); 5117 if (cro.baseMethods != 0) 5118 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 5119 } else 5120 outs() << format("0x%" PRIx64, cro.baseMethods); 5121 outs() << " (struct method_list_t *)\n"; 5122 if (cro.baseMethods + n_value != 0) 5123 print_method_list64_t(cro.baseMethods + n_value, info, ""); 5124 5125 outs() << " baseProtocols "; 5126 sym_name = 5127 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 5128 info, n_value, cro.baseProtocols); 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 (cro.baseProtocols != 0) 5135 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 5136 } else 5137 outs() << format("0x%" PRIx64, cro.baseProtocols); 5138 outs() << "\n"; 5139 if (cro.baseProtocols + n_value != 0) 5140 print_protocol_list64_t(cro.baseProtocols + n_value, info); 5141 5142 outs() << " ivars "; 5143 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 5144 info, n_value, cro.ivars); 5145 if (n_value != 0) { 5146 if (info->verbose && sym_name != nullptr) 5147 outs() << sym_name; 5148 else 5149 outs() << format("0x%" PRIx64, n_value); 5150 if (cro.ivars != 0) 5151 outs() << " + " << format("0x%" PRIx64, cro.ivars); 5152 } else 5153 outs() << format("0x%" PRIx64, cro.ivars); 5154 outs() << "\n"; 5155 if (cro.ivars + n_value != 0) 5156 print_ivar_list64_t(cro.ivars + n_value, info); 5157 5158 outs() << " weakIvarLayout "; 5159 sym_name = 5160 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 5161 info, n_value, cro.weakIvarLayout); 5162 if (n_value != 0) { 5163 if (info->verbose && sym_name != nullptr) 5164 outs() << sym_name; 5165 else 5166 outs() << format("0x%" PRIx64, n_value); 5167 if (cro.weakIvarLayout != 0) 5168 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 5169 } else 5170 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 5171 outs() << "\n"; 5172 print_layout_map64(cro.weakIvarLayout + n_value, info); 5173 5174 outs() << " baseProperties "; 5175 sym_name = 5176 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 5177 info, n_value, cro.baseProperties); 5178 if (n_value != 0) { 5179 if (info->verbose && sym_name != nullptr) 5180 outs() << sym_name; 5181 else 5182 outs() << format("0x%" PRIx64, n_value); 5183 if (cro.baseProperties != 0) 5184 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 5185 } else 5186 outs() << format("0x%" PRIx64, cro.baseProperties); 5187 outs() << "\n"; 5188 if (cro.baseProperties + n_value != 0) 5189 print_objc_property_list64(cro.baseProperties + n_value, info); 5190 5191 is_meta_class = (cro.flags & RO_META) != 0; 5192 return true; 5193 } 5194 5195 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 5196 bool &is_meta_class) { 5197 struct class_ro32_t cro; 5198 const char *r; 5199 uint32_t offset, xoffset, left; 5200 SectionRef S, xS; 5201 const char *name; 5202 5203 r = get_pointer_32(p, offset, left, S, info); 5204 if (r == nullptr) 5205 return false; 5206 memset(&cro, '\0', sizeof(struct class_ro32_t)); 5207 if (left < sizeof(struct class_ro32_t)) { 5208 memcpy(&cro, r, left); 5209 outs() << " (class_ro_t entends past the end of the section)\n"; 5210 } else 5211 memcpy(&cro, r, sizeof(struct class_ro32_t)); 5212 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5213 swapStruct(cro); 5214 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5215 if (cro.flags & RO_META) 5216 outs() << " RO_META"; 5217 if (cro.flags & RO_ROOT) 5218 outs() << " RO_ROOT"; 5219 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5220 outs() << " RO_HAS_CXX_STRUCTORS"; 5221 outs() << "\n"; 5222 outs() << " instanceStart " << cro.instanceStart << "\n"; 5223 outs() << " instanceSize " << cro.instanceSize << "\n"; 5224 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 5225 << "\n"; 5226 print_layout_map32(cro.ivarLayout, info); 5227 5228 outs() << " name " << format("0x%" PRIx32, cro.name); 5229 name = get_pointer_32(cro.name, xoffset, left, xS, info); 5230 if (name != nullptr) 5231 outs() << format(" %.*s", left, name); 5232 outs() << "\n"; 5233 5234 outs() << " baseMethods " 5235 << format("0x%" PRIx32, cro.baseMethods) 5236 << " (struct method_list_t *)\n"; 5237 if (cro.baseMethods != 0) 5238 print_method_list32_t(cro.baseMethods, info, ""); 5239 5240 outs() << " baseProtocols " 5241 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 5242 if (cro.baseProtocols != 0) 5243 print_protocol_list32_t(cro.baseProtocols, info); 5244 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 5245 << "\n"; 5246 if (cro.ivars != 0) 5247 print_ivar_list32_t(cro.ivars, info); 5248 outs() << " weakIvarLayout " 5249 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 5250 print_layout_map32(cro.weakIvarLayout, info); 5251 outs() << " baseProperties " 5252 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 5253 if (cro.baseProperties != 0) 5254 print_objc_property_list32(cro.baseProperties, info); 5255 is_meta_class = (cro.flags & RO_META) != 0; 5256 return true; 5257 } 5258 5259 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 5260 struct class64_t c; 5261 const char *r; 5262 uint32_t offset, left; 5263 SectionRef S; 5264 const char *name; 5265 uint64_t isa_n_value, n_value; 5266 5267 r = get_pointer_64(p, offset, left, S, info); 5268 if (r == nullptr || left < sizeof(struct class64_t)) 5269 return; 5270 memcpy(&c, r, sizeof(struct class64_t)); 5271 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5272 swapStruct(c); 5273 5274 outs() << " isa " << format("0x%" PRIx64, c.isa); 5275 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 5276 isa_n_value, c.isa); 5277 if (name != nullptr) 5278 outs() << " " << name; 5279 outs() << "\n"; 5280 5281 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 5282 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 5283 n_value, c.superclass); 5284 if (name != nullptr) 5285 outs() << " " << name; 5286 else { 5287 name = get_dyld_bind_info_symbolname(S.getAddress() + 5288 offset + offsetof(struct class64_t, superclass), info); 5289 if (name != nullptr) 5290 outs() << " " << name; 5291 } 5292 outs() << "\n"; 5293 5294 outs() << " cache " << format("0x%" PRIx64, c.cache); 5295 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 5296 n_value, c.cache); 5297 if (name != nullptr) 5298 outs() << " " << name; 5299 outs() << "\n"; 5300 5301 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 5302 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 5303 n_value, c.vtable); 5304 if (name != nullptr) 5305 outs() << " " << name; 5306 outs() << "\n"; 5307 5308 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 5309 n_value, c.data); 5310 outs() << " data "; 5311 if (n_value != 0) { 5312 if (info->verbose && name != nullptr) 5313 outs() << name; 5314 else 5315 outs() << format("0x%" PRIx64, n_value); 5316 if (c.data != 0) 5317 outs() << " + " << format("0x%" PRIx64, c.data); 5318 } else 5319 outs() << format("0x%" PRIx64, c.data); 5320 outs() << " (struct class_ro_t *)"; 5321 5322 // This is a Swift class if some of the low bits of the pointer are set. 5323 if ((c.data + n_value) & 0x7) 5324 outs() << " Swift class"; 5325 outs() << "\n"; 5326 bool is_meta_class; 5327 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5328 return; 5329 5330 if (!is_meta_class && 5331 c.isa + isa_n_value != p && 5332 c.isa + isa_n_value != 0 && 5333 info->depth < 100) { 5334 info->depth++; 5335 outs() << "Meta Class\n"; 5336 print_class64_t(c.isa + isa_n_value, info); 5337 } 5338 } 5339 5340 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5341 struct class32_t c; 5342 const char *r; 5343 uint32_t offset, left; 5344 SectionRef S; 5345 const char *name; 5346 5347 r = get_pointer_32(p, offset, left, S, info); 5348 if (r == nullptr) 5349 return; 5350 memset(&c, '\0', sizeof(struct class32_t)); 5351 if (left < sizeof(struct class32_t)) { 5352 memcpy(&c, r, left); 5353 outs() << " (class_t entends past the end of the section)\n"; 5354 } else 5355 memcpy(&c, r, sizeof(struct class32_t)); 5356 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5357 swapStruct(c); 5358 5359 outs() << " isa " << format("0x%" PRIx32, c.isa); 5360 name = 5361 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5362 if (name != nullptr) 5363 outs() << " " << name; 5364 outs() << "\n"; 5365 5366 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5367 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5368 c.superclass); 5369 if (name != nullptr) 5370 outs() << " " << name; 5371 outs() << "\n"; 5372 5373 outs() << " cache " << format("0x%" PRIx32, c.cache); 5374 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5375 c.cache); 5376 if (name != nullptr) 5377 outs() << " " << name; 5378 outs() << "\n"; 5379 5380 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5381 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5382 c.vtable); 5383 if (name != nullptr) 5384 outs() << " " << name; 5385 outs() << "\n"; 5386 5387 name = 5388 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5389 outs() << " data " << format("0x%" PRIx32, c.data) 5390 << " (struct class_ro_t *)"; 5391 5392 // This is a Swift class if some of the low bits of the pointer are set. 5393 if (c.data & 0x3) 5394 outs() << " Swift class"; 5395 outs() << "\n"; 5396 bool is_meta_class; 5397 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5398 return; 5399 5400 if (!is_meta_class) { 5401 outs() << "Meta Class\n"; 5402 print_class32_t(c.isa, info); 5403 } 5404 } 5405 5406 static void print_objc_class_t(struct objc_class_t *objc_class, 5407 struct DisassembleInfo *info) { 5408 uint32_t offset, left, xleft; 5409 const char *name, *p, *ivar_list; 5410 SectionRef S; 5411 int32_t i; 5412 struct objc_ivar_list_t objc_ivar_list; 5413 struct objc_ivar_t ivar; 5414 5415 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5416 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5417 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5418 if (name != nullptr) 5419 outs() << format(" %.*s", left, name); 5420 else 5421 outs() << " (not in an __OBJC section)"; 5422 } 5423 outs() << "\n"; 5424 5425 outs() << "\t super_class " 5426 << format("0x%08" PRIx32, objc_class->super_class); 5427 if (info->verbose) { 5428 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5429 if (name != nullptr) 5430 outs() << format(" %.*s", left, name); 5431 else 5432 outs() << " (not in an __OBJC section)"; 5433 } 5434 outs() << "\n"; 5435 5436 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5437 if (info->verbose) { 5438 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5439 if (name != nullptr) 5440 outs() << format(" %.*s", left, name); 5441 else 5442 outs() << " (not in an __OBJC section)"; 5443 } 5444 outs() << "\n"; 5445 5446 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5447 << "\n"; 5448 5449 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5450 if (info->verbose) { 5451 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5452 outs() << " CLS_CLASS"; 5453 else if (CLS_GETINFO(objc_class, CLS_META)) 5454 outs() << " CLS_META"; 5455 } 5456 outs() << "\n"; 5457 5458 outs() << "\t instance_size " 5459 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5460 5461 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5462 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5463 if (p != nullptr) { 5464 if (left > sizeof(struct objc_ivar_list_t)) { 5465 outs() << "\n"; 5466 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5467 } else { 5468 outs() << " (entends past the end of the section)\n"; 5469 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5470 memcpy(&objc_ivar_list, p, left); 5471 } 5472 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5473 swapStruct(objc_ivar_list); 5474 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5475 ivar_list = p + sizeof(struct objc_ivar_list_t); 5476 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5477 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5478 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5479 break; 5480 } 5481 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5482 sizeof(struct objc_ivar_t)); 5483 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5484 swapStruct(ivar); 5485 5486 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5487 if (info->verbose) { 5488 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5489 if (name != nullptr) 5490 outs() << format(" %.*s", xleft, name); 5491 else 5492 outs() << " (not in an __OBJC section)"; 5493 } 5494 outs() << "\n"; 5495 5496 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5497 if (info->verbose) { 5498 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5499 if (name != nullptr) 5500 outs() << format(" %.*s", xleft, name); 5501 else 5502 outs() << " (not in an __OBJC section)"; 5503 } 5504 outs() << "\n"; 5505 5506 outs() << "\t\t ivar_offset " 5507 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5508 } 5509 } else { 5510 outs() << " (not in an __OBJC section)\n"; 5511 } 5512 5513 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5514 if (print_method_list(objc_class->methodLists, info)) 5515 outs() << " (not in an __OBJC section)\n"; 5516 5517 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5518 << "\n"; 5519 5520 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5521 if (print_protocol_list(objc_class->protocols, 16, info)) 5522 outs() << " (not in an __OBJC section)\n"; 5523 } 5524 5525 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5526 struct DisassembleInfo *info) { 5527 uint32_t offset, left; 5528 const char *name; 5529 SectionRef S; 5530 5531 outs() << "\t category name " 5532 << format("0x%08" PRIx32, objc_category->category_name); 5533 if (info->verbose) { 5534 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5535 true); 5536 if (name != nullptr) 5537 outs() << format(" %.*s", left, name); 5538 else 5539 outs() << " (not in an __OBJC section)"; 5540 } 5541 outs() << "\n"; 5542 5543 outs() << "\t\t class name " 5544 << format("0x%08" PRIx32, objc_category->class_name); 5545 if (info->verbose) { 5546 name = 5547 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5548 if (name != nullptr) 5549 outs() << format(" %.*s", left, name); 5550 else 5551 outs() << " (not in an __OBJC section)"; 5552 } 5553 outs() << "\n"; 5554 5555 outs() << "\t instance methods " 5556 << format("0x%08" PRIx32, objc_category->instance_methods); 5557 if (print_method_list(objc_category->instance_methods, info)) 5558 outs() << " (not in an __OBJC section)\n"; 5559 5560 outs() << "\t class methods " 5561 << format("0x%08" PRIx32, objc_category->class_methods); 5562 if (print_method_list(objc_category->class_methods, info)) 5563 outs() << " (not in an __OBJC section)\n"; 5564 } 5565 5566 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5567 struct category64_t c; 5568 const char *r; 5569 uint32_t offset, xoffset, left; 5570 SectionRef S, xS; 5571 const char *name, *sym_name; 5572 uint64_t n_value; 5573 5574 r = get_pointer_64(p, offset, left, S, info); 5575 if (r == nullptr) 5576 return; 5577 memset(&c, '\0', sizeof(struct category64_t)); 5578 if (left < sizeof(struct category64_t)) { 5579 memcpy(&c, r, left); 5580 outs() << " (category_t entends past the end of the section)\n"; 5581 } else 5582 memcpy(&c, r, sizeof(struct category64_t)); 5583 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5584 swapStruct(c); 5585 5586 outs() << " name "; 5587 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 5588 info, n_value, c.name); 5589 if (n_value != 0) { 5590 if (info->verbose && sym_name != nullptr) 5591 outs() << sym_name; 5592 else 5593 outs() << format("0x%" PRIx64, n_value); 5594 if (c.name != 0) 5595 outs() << " + " << format("0x%" PRIx64, c.name); 5596 } else 5597 outs() << format("0x%" PRIx64, c.name); 5598 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 5599 if (name != nullptr) 5600 outs() << format(" %.*s", left, name); 5601 outs() << "\n"; 5602 5603 outs() << " cls "; 5604 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 5605 n_value, c.cls); 5606 if (n_value != 0) { 5607 if (info->verbose && sym_name != nullptr) 5608 outs() << sym_name; 5609 else 5610 outs() << format("0x%" PRIx64, n_value); 5611 if (c.cls != 0) 5612 outs() << " + " << format("0x%" PRIx64, c.cls); 5613 } else 5614 outs() << format("0x%" PRIx64, c.cls); 5615 outs() << "\n"; 5616 if (c.cls + n_value != 0) 5617 print_class64_t(c.cls + n_value, info); 5618 5619 outs() << " instanceMethods "; 5620 sym_name = 5621 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 5622 info, n_value, c.instanceMethods); 5623 if (n_value != 0) { 5624 if (info->verbose && sym_name != nullptr) 5625 outs() << sym_name; 5626 else 5627 outs() << format("0x%" PRIx64, n_value); 5628 if (c.instanceMethods != 0) 5629 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 5630 } else 5631 outs() << format("0x%" PRIx64, c.instanceMethods); 5632 outs() << "\n"; 5633 if (c.instanceMethods + n_value != 0) 5634 print_method_list64_t(c.instanceMethods + n_value, info, ""); 5635 5636 outs() << " classMethods "; 5637 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 5638 S, info, n_value, c.classMethods); 5639 if (n_value != 0) { 5640 if (info->verbose && sym_name != nullptr) 5641 outs() << sym_name; 5642 else 5643 outs() << format("0x%" PRIx64, n_value); 5644 if (c.classMethods != 0) 5645 outs() << " + " << format("0x%" PRIx64, c.classMethods); 5646 } else 5647 outs() << format("0x%" PRIx64, c.classMethods); 5648 outs() << "\n"; 5649 if (c.classMethods + n_value != 0) 5650 print_method_list64_t(c.classMethods + n_value, info, ""); 5651 5652 outs() << " protocols "; 5653 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 5654 info, n_value, c.protocols); 5655 if (n_value != 0) { 5656 if (info->verbose && sym_name != nullptr) 5657 outs() << sym_name; 5658 else 5659 outs() << format("0x%" PRIx64, n_value); 5660 if (c.protocols != 0) 5661 outs() << " + " << format("0x%" PRIx64, c.protocols); 5662 } else 5663 outs() << format("0x%" PRIx64, c.protocols); 5664 outs() << "\n"; 5665 if (c.protocols + n_value != 0) 5666 print_protocol_list64_t(c.protocols + n_value, info); 5667 5668 outs() << "instanceProperties "; 5669 sym_name = 5670 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 5671 S, info, n_value, c.instanceProperties); 5672 if (n_value != 0) { 5673 if (info->verbose && sym_name != nullptr) 5674 outs() << sym_name; 5675 else 5676 outs() << format("0x%" PRIx64, n_value); 5677 if (c.instanceProperties != 0) 5678 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 5679 } else 5680 outs() << format("0x%" PRIx64, c.instanceProperties); 5681 outs() << "\n"; 5682 if (c.instanceProperties + n_value != 0) 5683 print_objc_property_list64(c.instanceProperties + n_value, info); 5684 } 5685 5686 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 5687 struct category32_t c; 5688 const char *r; 5689 uint32_t offset, left; 5690 SectionRef S, xS; 5691 const char *name; 5692 5693 r = get_pointer_32(p, offset, left, S, info); 5694 if (r == nullptr) 5695 return; 5696 memset(&c, '\0', sizeof(struct category32_t)); 5697 if (left < sizeof(struct category32_t)) { 5698 memcpy(&c, r, left); 5699 outs() << " (category_t entends past the end of the section)\n"; 5700 } else 5701 memcpy(&c, r, sizeof(struct category32_t)); 5702 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5703 swapStruct(c); 5704 5705 outs() << " name " << format("0x%" PRIx32, c.name); 5706 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 5707 c.name); 5708 if (name) 5709 outs() << " " << name; 5710 outs() << "\n"; 5711 5712 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 5713 if (c.cls != 0) 5714 print_class32_t(c.cls, info); 5715 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 5716 << "\n"; 5717 if (c.instanceMethods != 0) 5718 print_method_list32_t(c.instanceMethods, info, ""); 5719 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 5720 << "\n"; 5721 if (c.classMethods != 0) 5722 print_method_list32_t(c.classMethods, info, ""); 5723 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 5724 if (c.protocols != 0) 5725 print_protocol_list32_t(c.protocols, info); 5726 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 5727 << "\n"; 5728 if (c.instanceProperties != 0) 5729 print_objc_property_list32(c.instanceProperties, info); 5730 } 5731 5732 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 5733 uint32_t i, left, offset, xoffset; 5734 uint64_t p, n_value; 5735 struct message_ref64 mr; 5736 const char *name, *sym_name; 5737 const char *r; 5738 SectionRef xS; 5739 5740 if (S == SectionRef()) 5741 return; 5742 5743 StringRef SectName; 5744 S.getName(SectName); 5745 DataRefImpl Ref = S.getRawDataRefImpl(); 5746 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5747 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5748 offset = 0; 5749 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5750 p = S.getAddress() + i; 5751 r = get_pointer_64(p, offset, left, S, info); 5752 if (r == nullptr) 5753 return; 5754 memset(&mr, '\0', sizeof(struct message_ref64)); 5755 if (left < sizeof(struct message_ref64)) { 5756 memcpy(&mr, r, left); 5757 outs() << " (message_ref entends past the end of the section)\n"; 5758 } else 5759 memcpy(&mr, r, sizeof(struct message_ref64)); 5760 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5761 swapStruct(mr); 5762 5763 outs() << " imp "; 5764 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 5765 n_value, mr.imp); 5766 if (n_value != 0) { 5767 outs() << format("0x%" PRIx64, n_value) << " "; 5768 if (mr.imp != 0) 5769 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 5770 } else 5771 outs() << format("0x%" PRIx64, mr.imp) << " "; 5772 if (name != nullptr) 5773 outs() << " " << name; 5774 outs() << "\n"; 5775 5776 outs() << " sel "; 5777 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 5778 info, n_value, mr.sel); 5779 if (n_value != 0) { 5780 if (info->verbose && sym_name != nullptr) 5781 outs() << sym_name; 5782 else 5783 outs() << format("0x%" PRIx64, n_value); 5784 if (mr.sel != 0) 5785 outs() << " + " << format("0x%" PRIx64, mr.sel); 5786 } else 5787 outs() << format("0x%" PRIx64, mr.sel); 5788 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 5789 if (name != nullptr) 5790 outs() << format(" %.*s", left, name); 5791 outs() << "\n"; 5792 5793 offset += sizeof(struct message_ref64); 5794 } 5795 } 5796 5797 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 5798 uint32_t i, left, offset, xoffset, p; 5799 struct message_ref32 mr; 5800 const char *name, *r; 5801 SectionRef xS; 5802 5803 if (S == SectionRef()) 5804 return; 5805 5806 StringRef SectName; 5807 S.getName(SectName); 5808 DataRefImpl Ref = S.getRawDataRefImpl(); 5809 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5810 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5811 offset = 0; 5812 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5813 p = S.getAddress() + i; 5814 r = get_pointer_32(p, offset, left, S, info); 5815 if (r == nullptr) 5816 return; 5817 memset(&mr, '\0', sizeof(struct message_ref32)); 5818 if (left < sizeof(struct message_ref32)) { 5819 memcpy(&mr, r, left); 5820 outs() << " (message_ref entends past the end of the section)\n"; 5821 } else 5822 memcpy(&mr, r, sizeof(struct message_ref32)); 5823 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5824 swapStruct(mr); 5825 5826 outs() << " imp " << format("0x%" PRIx32, mr.imp); 5827 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 5828 mr.imp); 5829 if (name != nullptr) 5830 outs() << " " << name; 5831 outs() << "\n"; 5832 5833 outs() << " sel " << format("0x%" PRIx32, mr.sel); 5834 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 5835 if (name != nullptr) 5836 outs() << " " << name; 5837 outs() << "\n"; 5838 5839 offset += sizeof(struct message_ref32); 5840 } 5841 } 5842 5843 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 5844 uint32_t left, offset, swift_version; 5845 uint64_t p; 5846 struct objc_image_info64 o; 5847 const char *r; 5848 5849 if (S == SectionRef()) 5850 return; 5851 5852 StringRef SectName; 5853 S.getName(SectName); 5854 DataRefImpl Ref = S.getRawDataRefImpl(); 5855 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5856 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5857 p = S.getAddress(); 5858 r = get_pointer_64(p, offset, left, S, info); 5859 if (r == nullptr) 5860 return; 5861 memset(&o, '\0', sizeof(struct objc_image_info64)); 5862 if (left < sizeof(struct objc_image_info64)) { 5863 memcpy(&o, r, left); 5864 outs() << " (objc_image_info entends past the end of the section)\n"; 5865 } else 5866 memcpy(&o, r, sizeof(struct objc_image_info64)); 5867 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5868 swapStruct(o); 5869 outs() << " version " << o.version << "\n"; 5870 outs() << " flags " << format("0x%" PRIx32, o.flags); 5871 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5872 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5873 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5874 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5875 if (o.flags & OBJC_IMAGE_IS_SIMULATED) 5876 outs() << " OBJC_IMAGE_IS_SIMULATED"; 5877 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES) 5878 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES"; 5879 swift_version = (o.flags >> 8) & 0xff; 5880 if (swift_version != 0) { 5881 if (swift_version == 1) 5882 outs() << " Swift 1.0"; 5883 else if (swift_version == 2) 5884 outs() << " Swift 1.1"; 5885 else if(swift_version == 3) 5886 outs() << " Swift 2.0"; 5887 else if(swift_version == 4) 5888 outs() << " Swift 3.0"; 5889 else if(swift_version == 5) 5890 outs() << " Swift 4.0"; 5891 else if(swift_version == 6) 5892 outs() << " Swift 4.1/Swift 4.2"; 5893 else if(swift_version == 7) 5894 outs() << " Swift 5 or later"; 5895 else 5896 outs() << " unknown future Swift version (" << swift_version << ")"; 5897 } 5898 outs() << "\n"; 5899 } 5900 5901 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 5902 uint32_t left, offset, swift_version, p; 5903 struct objc_image_info32 o; 5904 const char *r; 5905 5906 if (S == SectionRef()) 5907 return; 5908 5909 StringRef SectName; 5910 S.getName(SectName); 5911 DataRefImpl Ref = S.getRawDataRefImpl(); 5912 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5913 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5914 p = S.getAddress(); 5915 r = get_pointer_32(p, offset, left, S, info); 5916 if (r == nullptr) 5917 return; 5918 memset(&o, '\0', sizeof(struct objc_image_info32)); 5919 if (left < sizeof(struct objc_image_info32)) { 5920 memcpy(&o, r, left); 5921 outs() << " (objc_image_info entends past the end of the section)\n"; 5922 } else 5923 memcpy(&o, r, sizeof(struct objc_image_info32)); 5924 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5925 swapStruct(o); 5926 outs() << " version " << o.version << "\n"; 5927 outs() << " flags " << format("0x%" PRIx32, o.flags); 5928 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5929 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5930 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5931 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5932 swift_version = (o.flags >> 8) & 0xff; 5933 if (swift_version != 0) { 5934 if (swift_version == 1) 5935 outs() << " Swift 1.0"; 5936 else if (swift_version == 2) 5937 outs() << " Swift 1.1"; 5938 else if(swift_version == 3) 5939 outs() << " Swift 2.0"; 5940 else if(swift_version == 4) 5941 outs() << " Swift 3.0"; 5942 else if(swift_version == 5) 5943 outs() << " Swift 4.0"; 5944 else if(swift_version == 6) 5945 outs() << " Swift 4.1/Swift 4.2"; 5946 else if(swift_version == 7) 5947 outs() << " Swift 5 or later"; 5948 else 5949 outs() << " unknown future Swift version (" << swift_version << ")"; 5950 } 5951 outs() << "\n"; 5952 } 5953 5954 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 5955 uint32_t left, offset, p; 5956 struct imageInfo_t o; 5957 const char *r; 5958 5959 StringRef SectName; 5960 S.getName(SectName); 5961 DataRefImpl Ref = S.getRawDataRefImpl(); 5962 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5963 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5964 p = S.getAddress(); 5965 r = get_pointer_32(p, offset, left, S, info); 5966 if (r == nullptr) 5967 return; 5968 memset(&o, '\0', sizeof(struct imageInfo_t)); 5969 if (left < sizeof(struct imageInfo_t)) { 5970 memcpy(&o, r, left); 5971 outs() << " (imageInfo entends past the end of the section)\n"; 5972 } else 5973 memcpy(&o, r, sizeof(struct imageInfo_t)); 5974 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5975 swapStruct(o); 5976 outs() << " version " << o.version << "\n"; 5977 outs() << " flags " << format("0x%" PRIx32, o.flags); 5978 if (o.flags & 0x1) 5979 outs() << " F&C"; 5980 if (o.flags & 0x2) 5981 outs() << " GC"; 5982 if (o.flags & 0x4) 5983 outs() << " GC-only"; 5984 else 5985 outs() << " RR"; 5986 outs() << "\n"; 5987 } 5988 5989 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 5990 SymbolAddressMap AddrMap; 5991 if (verbose) 5992 CreateSymbolAddressMap(O, &AddrMap); 5993 5994 std::vector<SectionRef> Sections; 5995 for (const SectionRef &Section : O->sections()) { 5996 StringRef SectName; 5997 Section.getName(SectName); 5998 Sections.push_back(Section); 5999 } 6000 6001 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6002 6003 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6004 if (CL == SectionRef()) 6005 CL = get_section(O, "__DATA", "__objc_classlist"); 6006 if (CL == SectionRef()) 6007 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6008 if (CL == SectionRef()) 6009 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6010 info.S = CL; 6011 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 6012 6013 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6014 if (CR == SectionRef()) 6015 CR = get_section(O, "__DATA", "__objc_classrefs"); 6016 if (CR == SectionRef()) 6017 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6018 if (CR == SectionRef()) 6019 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6020 info.S = CR; 6021 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 6022 6023 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6024 if (SR == SectionRef()) 6025 SR = get_section(O, "__DATA", "__objc_superrefs"); 6026 if (SR == SectionRef()) 6027 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6028 if (SR == SectionRef()) 6029 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6030 info.S = SR; 6031 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 6032 6033 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6034 if (CA == SectionRef()) 6035 CA = get_section(O, "__DATA", "__objc_catlist"); 6036 if (CA == SectionRef()) 6037 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6038 if (CA == SectionRef()) 6039 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6040 info.S = CA; 6041 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 6042 6043 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6044 if (PL == SectionRef()) 6045 PL = get_section(O, "__DATA", "__objc_protolist"); 6046 if (PL == SectionRef()) 6047 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6048 if (PL == SectionRef()) 6049 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6050 info.S = PL; 6051 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 6052 6053 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6054 if (MR == SectionRef()) 6055 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6056 if (MR == SectionRef()) 6057 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6058 if (MR == SectionRef()) 6059 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6060 info.S = MR; 6061 print_message_refs64(MR, &info); 6062 6063 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6064 if (II == SectionRef()) 6065 II = get_section(O, "__DATA", "__objc_imageinfo"); 6066 if (II == SectionRef()) 6067 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6068 if (II == SectionRef()) 6069 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6070 info.S = II; 6071 print_image_info64(II, &info); 6072 } 6073 6074 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6075 SymbolAddressMap AddrMap; 6076 if (verbose) 6077 CreateSymbolAddressMap(O, &AddrMap); 6078 6079 std::vector<SectionRef> Sections; 6080 for (const SectionRef &Section : O->sections()) { 6081 StringRef SectName; 6082 Section.getName(SectName); 6083 Sections.push_back(Section); 6084 } 6085 6086 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6087 6088 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6089 if (CL == SectionRef()) 6090 CL = get_section(O, "__DATA", "__objc_classlist"); 6091 if (CL == SectionRef()) 6092 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6093 if (CL == SectionRef()) 6094 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6095 info.S = CL; 6096 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 6097 6098 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6099 if (CR == SectionRef()) 6100 CR = get_section(O, "__DATA", "__objc_classrefs"); 6101 if (CR == SectionRef()) 6102 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6103 if (CR == SectionRef()) 6104 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6105 info.S = CR; 6106 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 6107 6108 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6109 if (SR == SectionRef()) 6110 SR = get_section(O, "__DATA", "__objc_superrefs"); 6111 if (SR == SectionRef()) 6112 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6113 if (SR == SectionRef()) 6114 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6115 info.S = SR; 6116 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 6117 6118 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6119 if (CA == SectionRef()) 6120 CA = get_section(O, "__DATA", "__objc_catlist"); 6121 if (CA == SectionRef()) 6122 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6123 if (CA == SectionRef()) 6124 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6125 info.S = CA; 6126 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 6127 6128 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6129 if (PL == SectionRef()) 6130 PL = get_section(O, "__DATA", "__objc_protolist"); 6131 if (PL == SectionRef()) 6132 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6133 if (PL == SectionRef()) 6134 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6135 info.S = PL; 6136 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 6137 6138 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6139 if (MR == SectionRef()) 6140 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6141 if (MR == SectionRef()) 6142 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6143 if (MR == SectionRef()) 6144 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6145 info.S = MR; 6146 print_message_refs32(MR, &info); 6147 6148 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6149 if (II == SectionRef()) 6150 II = get_section(O, "__DATA", "__objc_imageinfo"); 6151 if (II == SectionRef()) 6152 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6153 if (II == SectionRef()) 6154 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6155 info.S = II; 6156 print_image_info32(II, &info); 6157 } 6158 6159 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6160 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 6161 const char *r, *name, *defs; 6162 struct objc_module_t module; 6163 SectionRef S, xS; 6164 struct objc_symtab_t symtab; 6165 struct objc_class_t objc_class; 6166 struct objc_category_t objc_category; 6167 6168 outs() << "Objective-C segment\n"; 6169 S = get_section(O, "__OBJC", "__module_info"); 6170 if (S == SectionRef()) 6171 return false; 6172 6173 SymbolAddressMap AddrMap; 6174 if (verbose) 6175 CreateSymbolAddressMap(O, &AddrMap); 6176 6177 std::vector<SectionRef> Sections; 6178 for (const SectionRef &Section : O->sections()) { 6179 StringRef SectName; 6180 Section.getName(SectName); 6181 Sections.push_back(Section); 6182 } 6183 6184 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6185 6186 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 6187 p = S.getAddress() + i; 6188 r = get_pointer_32(p, offset, left, S, &info, true); 6189 if (r == nullptr) 6190 return true; 6191 memset(&module, '\0', sizeof(struct objc_module_t)); 6192 if (left < sizeof(struct objc_module_t)) { 6193 memcpy(&module, r, left); 6194 outs() << " (module extends past end of __module_info section)\n"; 6195 } else 6196 memcpy(&module, r, sizeof(struct objc_module_t)); 6197 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6198 swapStruct(module); 6199 6200 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 6201 outs() << " version " << module.version << "\n"; 6202 outs() << " size " << module.size << "\n"; 6203 outs() << " name "; 6204 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 6205 if (name != nullptr) 6206 outs() << format("%.*s", left, name); 6207 else 6208 outs() << format("0x%08" PRIx32, module.name) 6209 << "(not in an __OBJC section)"; 6210 outs() << "\n"; 6211 6212 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 6213 if (module.symtab == 0 || r == nullptr) { 6214 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 6215 << " (not in an __OBJC section)\n"; 6216 continue; 6217 } 6218 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 6219 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 6220 defs_left = 0; 6221 defs = nullptr; 6222 if (left < sizeof(struct objc_symtab_t)) { 6223 memcpy(&symtab, r, left); 6224 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 6225 } else { 6226 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 6227 if (left > sizeof(struct objc_symtab_t)) { 6228 defs_left = left - sizeof(struct objc_symtab_t); 6229 defs = r + sizeof(struct objc_symtab_t); 6230 } 6231 } 6232 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6233 swapStruct(symtab); 6234 6235 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 6236 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 6237 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 6238 if (r == nullptr) 6239 outs() << " (not in an __OBJC section)"; 6240 outs() << "\n"; 6241 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 6242 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 6243 if (symtab.cls_def_cnt > 0) 6244 outs() << "\tClass Definitions\n"; 6245 for (j = 0; j < symtab.cls_def_cnt; j++) { 6246 if ((j + 1) * sizeof(uint32_t) > defs_left) { 6247 outs() << "\t(remaining class defs entries entends past the end of the " 6248 << "section)\n"; 6249 break; 6250 } 6251 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 6252 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6253 sys::swapByteOrder(def); 6254 6255 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6256 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 6257 if (r != nullptr) { 6258 if (left > sizeof(struct objc_class_t)) { 6259 outs() << "\n"; 6260 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6261 } else { 6262 outs() << " (entends past the end of the section)\n"; 6263 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6264 memcpy(&objc_class, r, left); 6265 } 6266 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6267 swapStruct(objc_class); 6268 print_objc_class_t(&objc_class, &info); 6269 } else { 6270 outs() << "(not in an __OBJC section)\n"; 6271 } 6272 6273 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 6274 outs() << "\tMeta Class"; 6275 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 6276 if (r != nullptr) { 6277 if (left > sizeof(struct objc_class_t)) { 6278 outs() << "\n"; 6279 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6280 } else { 6281 outs() << " (entends past the end of the section)\n"; 6282 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6283 memcpy(&objc_class, r, left); 6284 } 6285 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6286 swapStruct(objc_class); 6287 print_objc_class_t(&objc_class, &info); 6288 } else { 6289 outs() << "(not in an __OBJC section)\n"; 6290 } 6291 } 6292 } 6293 if (symtab.cat_def_cnt > 0) 6294 outs() << "\tCategory Definitions\n"; 6295 for (j = 0; j < symtab.cat_def_cnt; j++) { 6296 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 6297 outs() << "\t(remaining category defs entries entends past the end of " 6298 << "the section)\n"; 6299 break; 6300 } 6301 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6302 sizeof(uint32_t)); 6303 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6304 sys::swapByteOrder(def); 6305 6306 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6307 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6308 << format("0x%08" PRIx32, def); 6309 if (r != nullptr) { 6310 if (left > sizeof(struct objc_category_t)) { 6311 outs() << "\n"; 6312 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6313 } else { 6314 outs() << " (entends past the end of the section)\n"; 6315 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6316 memcpy(&objc_category, r, left); 6317 } 6318 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6319 swapStruct(objc_category); 6320 print_objc_objc_category_t(&objc_category, &info); 6321 } else { 6322 outs() << "(not in an __OBJC section)\n"; 6323 } 6324 } 6325 } 6326 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6327 if (II != SectionRef()) 6328 print_image_info(II, &info); 6329 6330 return true; 6331 } 6332 6333 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6334 uint32_t size, uint32_t addr) { 6335 SymbolAddressMap AddrMap; 6336 CreateSymbolAddressMap(O, &AddrMap); 6337 6338 std::vector<SectionRef> Sections; 6339 for (const SectionRef &Section : O->sections()) { 6340 StringRef SectName; 6341 Section.getName(SectName); 6342 Sections.push_back(Section); 6343 } 6344 6345 struct DisassembleInfo info(O, &AddrMap, &Sections, true); 6346 6347 const char *p; 6348 struct objc_protocol_t protocol; 6349 uint32_t left, paddr; 6350 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6351 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6352 left = size - (p - sect); 6353 if (left < sizeof(struct objc_protocol_t)) { 6354 outs() << "Protocol extends past end of __protocol section\n"; 6355 memcpy(&protocol, p, left); 6356 } else 6357 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6358 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6359 swapStruct(protocol); 6360 paddr = addr + (p - sect); 6361 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6362 if (print_protocol(paddr, 0, &info)) 6363 outs() << "(not in an __OBJC section)\n"; 6364 } 6365 } 6366 6367 #ifdef HAVE_LIBXAR 6368 inline void swapStruct(struct xar_header &xar) { 6369 sys::swapByteOrder(xar.magic); 6370 sys::swapByteOrder(xar.size); 6371 sys::swapByteOrder(xar.version); 6372 sys::swapByteOrder(xar.toc_length_compressed); 6373 sys::swapByteOrder(xar.toc_length_uncompressed); 6374 sys::swapByteOrder(xar.cksum_alg); 6375 } 6376 6377 static void PrintModeVerbose(uint32_t mode) { 6378 switch(mode & S_IFMT){ 6379 case S_IFDIR: 6380 outs() << "d"; 6381 break; 6382 case S_IFCHR: 6383 outs() << "c"; 6384 break; 6385 case S_IFBLK: 6386 outs() << "b"; 6387 break; 6388 case S_IFREG: 6389 outs() << "-"; 6390 break; 6391 case S_IFLNK: 6392 outs() << "l"; 6393 break; 6394 case S_IFSOCK: 6395 outs() << "s"; 6396 break; 6397 default: 6398 outs() << "?"; 6399 break; 6400 } 6401 6402 /* owner permissions */ 6403 if(mode & S_IREAD) 6404 outs() << "r"; 6405 else 6406 outs() << "-"; 6407 if(mode & S_IWRITE) 6408 outs() << "w"; 6409 else 6410 outs() << "-"; 6411 if(mode & S_ISUID) 6412 outs() << "s"; 6413 else if(mode & S_IEXEC) 6414 outs() << "x"; 6415 else 6416 outs() << "-"; 6417 6418 /* group permissions */ 6419 if(mode & (S_IREAD >> 3)) 6420 outs() << "r"; 6421 else 6422 outs() << "-"; 6423 if(mode & (S_IWRITE >> 3)) 6424 outs() << "w"; 6425 else 6426 outs() << "-"; 6427 if(mode & S_ISGID) 6428 outs() << "s"; 6429 else if(mode & (S_IEXEC >> 3)) 6430 outs() << "x"; 6431 else 6432 outs() << "-"; 6433 6434 /* other permissions */ 6435 if(mode & (S_IREAD >> 6)) 6436 outs() << "r"; 6437 else 6438 outs() << "-"; 6439 if(mode & (S_IWRITE >> 6)) 6440 outs() << "w"; 6441 else 6442 outs() << "-"; 6443 if(mode & S_ISVTX) 6444 outs() << "t"; 6445 else if(mode & (S_IEXEC >> 6)) 6446 outs() << "x"; 6447 else 6448 outs() << "-"; 6449 } 6450 6451 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { 6452 xar_file_t xf; 6453 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; 6454 char *endp; 6455 uint32_t mode_value; 6456 6457 ScopedXarIter xi; 6458 if (!xi) { 6459 WithColor::error(errs(), "llvm-objdump") 6460 << "can't obtain an xar iterator for xar archive " << XarFilename 6461 << "\n"; 6462 return; 6463 } 6464 6465 // Go through the xar's files. 6466 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { 6467 ScopedXarIter xp; 6468 if(!xp){ 6469 WithColor::error(errs(), "llvm-objdump") 6470 << "can't obtain an xar iterator for xar archive " << XarFilename 6471 << "\n"; 6472 return; 6473 } 6474 type = nullptr; 6475 mode = nullptr; 6476 user = nullptr; 6477 group = nullptr; 6478 size = nullptr; 6479 mtime = nullptr; 6480 name = nullptr; 6481 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6482 const char *val = nullptr; 6483 xar_prop_get(xf, key, &val); 6484 #if 0 // Useful for debugging. 6485 outs() << "key: " << key << " value: " << val << "\n"; 6486 #endif 6487 if(strcmp(key, "type") == 0) 6488 type = val; 6489 if(strcmp(key, "mode") == 0) 6490 mode = val; 6491 if(strcmp(key, "user") == 0) 6492 user = val; 6493 if(strcmp(key, "group") == 0) 6494 group = val; 6495 if(strcmp(key, "data/size") == 0) 6496 size = val; 6497 if(strcmp(key, "mtime") == 0) 6498 mtime = val; 6499 if(strcmp(key, "name") == 0) 6500 name = val; 6501 } 6502 if(mode != nullptr){ 6503 mode_value = strtoul(mode, &endp, 8); 6504 if(*endp != '\0') 6505 outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; 6506 if(strcmp(type, "file") == 0) 6507 mode_value |= S_IFREG; 6508 PrintModeVerbose(mode_value); 6509 outs() << " "; 6510 } 6511 if(user != nullptr) 6512 outs() << format("%10s/", user); 6513 if(group != nullptr) 6514 outs() << format("%-10s ", group); 6515 if(size != nullptr) 6516 outs() << format("%7s ", size); 6517 if(mtime != nullptr){ 6518 for(m = mtime; *m != 'T' && *m != '\0'; m++) 6519 outs() << *m; 6520 if(*m == 'T') 6521 m++; 6522 outs() << " "; 6523 for( ; *m != 'Z' && *m != '\0'; m++) 6524 outs() << *m; 6525 outs() << " "; 6526 } 6527 if(name != nullptr) 6528 outs() << name; 6529 outs() << "\n"; 6530 } 6531 } 6532 6533 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 6534 uint32_t size, bool verbose, 6535 bool PrintXarHeader, bool PrintXarFileHeaders, 6536 std::string XarMemberName) { 6537 if(size < sizeof(struct xar_header)) { 6538 outs() << "size of (__LLVM,__bundle) section too small (smaller than size " 6539 "of struct xar_header)\n"; 6540 return; 6541 } 6542 struct xar_header XarHeader; 6543 memcpy(&XarHeader, sect, sizeof(struct xar_header)); 6544 if (sys::IsLittleEndianHost) 6545 swapStruct(XarHeader); 6546 if (PrintXarHeader) { 6547 if (!XarMemberName.empty()) 6548 outs() << "In xar member " << XarMemberName << ": "; 6549 else 6550 outs() << "For (__LLVM,__bundle) section: "; 6551 outs() << "xar header\n"; 6552 if (XarHeader.magic == XAR_HEADER_MAGIC) 6553 outs() << " magic XAR_HEADER_MAGIC\n"; 6554 else 6555 outs() << " magic " 6556 << format_hex(XarHeader.magic, 10, true) 6557 << " (not XAR_HEADER_MAGIC)\n"; 6558 outs() << " size " << XarHeader.size << "\n"; 6559 outs() << " version " << XarHeader.version << "\n"; 6560 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed 6561 << "\n"; 6562 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed 6563 << "\n"; 6564 outs() << " cksum_alg "; 6565 switch (XarHeader.cksum_alg) { 6566 case XAR_CKSUM_NONE: 6567 outs() << "XAR_CKSUM_NONE\n"; 6568 break; 6569 case XAR_CKSUM_SHA1: 6570 outs() << "XAR_CKSUM_SHA1\n"; 6571 break; 6572 case XAR_CKSUM_MD5: 6573 outs() << "XAR_CKSUM_MD5\n"; 6574 break; 6575 #ifdef XAR_CKSUM_SHA256 6576 case XAR_CKSUM_SHA256: 6577 outs() << "XAR_CKSUM_SHA256\n"; 6578 break; 6579 #endif 6580 #ifdef XAR_CKSUM_SHA512 6581 case XAR_CKSUM_SHA512: 6582 outs() << "XAR_CKSUM_SHA512\n"; 6583 break; 6584 #endif 6585 default: 6586 outs() << XarHeader.cksum_alg << "\n"; 6587 } 6588 } 6589 6590 SmallString<128> XarFilename; 6591 int FD; 6592 std::error_code XarEC = 6593 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); 6594 if (XarEC) { 6595 WithColor::error(errs(), "llvm-objdump") << XarEC.message() << "\n"; 6596 return; 6597 } 6598 ToolOutputFile XarFile(XarFilename, FD); 6599 raw_fd_ostream &XarOut = XarFile.os(); 6600 StringRef XarContents(sect, size); 6601 XarOut << XarContents; 6602 XarOut.close(); 6603 if (XarOut.has_error()) 6604 return; 6605 6606 ScopedXarFile xar(XarFilename.c_str(), READ); 6607 if (!xar) { 6608 WithColor::error(errs(), "llvm-objdump") 6609 << "can't create temporary xar archive " << XarFilename << "\n"; 6610 return; 6611 } 6612 6613 SmallString<128> TocFilename; 6614 std::error_code TocEC = 6615 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); 6616 if (TocEC) { 6617 WithColor::error(errs(), "llvm-objdump") << TocEC.message() << "\n"; 6618 return; 6619 } 6620 xar_serialize(xar, TocFilename.c_str()); 6621 6622 if (PrintXarFileHeaders) { 6623 if (!XarMemberName.empty()) 6624 outs() << "In xar member " << XarMemberName << ": "; 6625 else 6626 outs() << "For (__LLVM,__bundle) section: "; 6627 outs() << "xar archive files:\n"; 6628 PrintXarFilesSummary(XarFilename.c_str(), xar); 6629 } 6630 6631 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 6632 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); 6633 if (std::error_code EC = FileOrErr.getError()) { 6634 WithColor::error(errs(), "llvm-objdump") << EC.message() << "\n"; 6635 return; 6636 } 6637 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 6638 6639 if (!XarMemberName.empty()) 6640 outs() << "In xar member " << XarMemberName << ": "; 6641 else 6642 outs() << "For (__LLVM,__bundle) section: "; 6643 outs() << "xar table of contents:\n"; 6644 outs() << Buffer->getBuffer() << "\n"; 6645 6646 // TODO: Go through the xar's files. 6647 ScopedXarIter xi; 6648 if(!xi){ 6649 WithColor::error(errs(), "llvm-objdump") 6650 << "can't obtain an xar iterator for xar archive " 6651 << XarFilename.c_str() << "\n"; 6652 return; 6653 } 6654 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ 6655 const char *key; 6656 const char *member_name, *member_type, *member_size_string; 6657 size_t member_size; 6658 6659 ScopedXarIter xp; 6660 if(!xp){ 6661 WithColor::error(errs(), "llvm-objdump") 6662 << "can't obtain an xar iterator for xar archive " 6663 << XarFilename.c_str() << "\n"; 6664 return; 6665 } 6666 member_name = NULL; 6667 member_type = NULL; 6668 member_size_string = NULL; 6669 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6670 const char *val = nullptr; 6671 xar_prop_get(xf, key, &val); 6672 #if 0 // Useful for debugging. 6673 outs() << "key: " << key << " value: " << val << "\n"; 6674 #endif 6675 if (strcmp(key, "name") == 0) 6676 member_name = val; 6677 if (strcmp(key, "type") == 0) 6678 member_type = val; 6679 if (strcmp(key, "data/size") == 0) 6680 member_size_string = val; 6681 } 6682 /* 6683 * If we find a file with a name, date/size and type properties 6684 * and with the type being "file" see if that is a xar file. 6685 */ 6686 if (member_name != NULL && member_type != NULL && 6687 strcmp(member_type, "file") == 0 && 6688 member_size_string != NULL){ 6689 // Extract the file into a buffer. 6690 char *endptr; 6691 member_size = strtoul(member_size_string, &endptr, 10); 6692 if (*endptr == '\0' && member_size != 0) { 6693 char *buffer; 6694 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { 6695 #if 0 // Useful for debugging. 6696 outs() << "xar member: " << member_name << " extracted\n"; 6697 #endif 6698 // Set the XarMemberName we want to see printed in the header. 6699 std::string OldXarMemberName; 6700 // If XarMemberName is already set this is nested. So 6701 // save the old name and create the nested name. 6702 if (!XarMemberName.empty()) { 6703 OldXarMemberName = XarMemberName; 6704 XarMemberName = 6705 (Twine("[") + XarMemberName + "]" + member_name).str(); 6706 } else { 6707 OldXarMemberName = ""; 6708 XarMemberName = member_name; 6709 } 6710 // See if this is could be a xar file (nested). 6711 if (member_size >= sizeof(struct xar_header)) { 6712 #if 0 // Useful for debugging. 6713 outs() << "could be a xar file: " << member_name << "\n"; 6714 #endif 6715 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); 6716 if (sys::IsLittleEndianHost) 6717 swapStruct(XarHeader); 6718 if (XarHeader.magic == XAR_HEADER_MAGIC) 6719 DumpBitcodeSection(O, buffer, member_size, verbose, 6720 PrintXarHeader, PrintXarFileHeaders, 6721 XarMemberName); 6722 } 6723 XarMemberName = OldXarMemberName; 6724 delete buffer; 6725 } 6726 } 6727 } 6728 } 6729 } 6730 #endif // defined(HAVE_LIBXAR) 6731 6732 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6733 if (O->is64Bit()) 6734 printObjc2_64bit_MetaData(O, verbose); 6735 else { 6736 MachO::mach_header H; 6737 H = O->getHeader(); 6738 if (H.cputype == MachO::CPU_TYPE_ARM) 6739 printObjc2_32bit_MetaData(O, verbose); 6740 else { 6741 // This is the 32-bit non-arm cputype case. Which is normally 6742 // the first Objective-C ABI. But it may be the case of a 6743 // binary for the iOS simulator which is the second Objective-C 6744 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6745 // and return false. 6746 if (!printObjc1_32bit_MetaData(O, verbose)) 6747 printObjc2_32bit_MetaData(O, verbose); 6748 } 6749 } 6750 } 6751 6752 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6753 // for the address passed in as ReferenceValue for printing as a comment with 6754 // the instruction and also returns the corresponding type of that item 6755 // indirectly through ReferenceType. 6756 // 6757 // If ReferenceValue is an address of literal cstring then a pointer to the 6758 // cstring is returned and ReferenceType is set to 6759 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6760 // 6761 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6762 // Class ref that name is returned and the ReferenceType is set accordingly. 6763 // 6764 // Lastly, literals which are Symbol address in a literal pool are looked for 6765 // and if found the symbol name is returned and ReferenceType is set to 6766 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6767 // 6768 // If there is no item in the Mach-O file for the address passed in as 6769 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6770 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6771 uint64_t ReferencePC, 6772 uint64_t *ReferenceType, 6773 struct DisassembleInfo *info) { 6774 // First see if there is an external relocation entry at the ReferencePC. 6775 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6776 uint64_t sect_addr = info->S.getAddress(); 6777 uint64_t sect_offset = ReferencePC - sect_addr; 6778 bool reloc_found = false; 6779 DataRefImpl Rel; 6780 MachO::any_relocation_info RE; 6781 bool isExtern = false; 6782 SymbolRef Symbol; 6783 for (const RelocationRef &Reloc : info->S.relocations()) { 6784 uint64_t RelocOffset = Reloc.getOffset(); 6785 if (RelocOffset == sect_offset) { 6786 Rel = Reloc.getRawDataRefImpl(); 6787 RE = info->O->getRelocation(Rel); 6788 if (info->O->isRelocationScattered(RE)) 6789 continue; 6790 isExtern = info->O->getPlainRelocationExternal(RE); 6791 if (isExtern) { 6792 symbol_iterator RelocSym = Reloc.getSymbol(); 6793 Symbol = *RelocSym; 6794 } 6795 reloc_found = true; 6796 break; 6797 } 6798 } 6799 // If there is an external relocation entry for a symbol in a section 6800 // then used that symbol's value for the value of the reference. 6801 if (reloc_found && isExtern) { 6802 if (info->O->getAnyRelocationPCRel(RE)) { 6803 unsigned Type = info->O->getAnyRelocationType(RE); 6804 if (Type == MachO::X86_64_RELOC_SIGNED) { 6805 ReferenceValue = Symbol.getValue(); 6806 } 6807 } 6808 } 6809 } 6810 6811 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6812 // Message refs and Class refs. 6813 bool classref, selref, msgref, cfstring; 6814 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6815 selref, msgref, cfstring); 6816 if (classref && pointer_value == 0) { 6817 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6818 // And the pointer_value in that section is typically zero as it will be 6819 // set by dyld as part of the "bind information". 6820 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6821 if (name != nullptr) { 6822 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6823 const char *class_name = strrchr(name, '$'); 6824 if (class_name != nullptr && class_name[1] == '_' && 6825 class_name[2] != '\0') { 6826 info->class_name = class_name + 2; 6827 return name; 6828 } 6829 } 6830 } 6831 6832 if (classref) { 6833 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6834 const char *name = 6835 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6836 if (name != nullptr) 6837 info->class_name = name; 6838 else 6839 name = "bad class ref"; 6840 return name; 6841 } 6842 6843 if (cfstring) { 6844 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6845 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6846 return name; 6847 } 6848 6849 if (selref && pointer_value == 0) 6850 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6851 6852 if (pointer_value != 0) 6853 ReferenceValue = pointer_value; 6854 6855 const char *name = GuessCstringPointer(ReferenceValue, info); 6856 if (name) { 6857 if (pointer_value != 0 && selref) { 6858 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6859 info->selector_name = name; 6860 } else if (pointer_value != 0 && msgref) { 6861 info->class_name = nullptr; 6862 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6863 info->selector_name = name; 6864 } else 6865 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6866 return name; 6867 } 6868 6869 // Lastly look for an indirect symbol with this ReferenceValue which is in 6870 // a literal pool. If found return that symbol name. 6871 name = GuessIndirectSymbol(ReferenceValue, info); 6872 if (name) { 6873 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6874 return name; 6875 } 6876 6877 return nullptr; 6878 } 6879 6880 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6881 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6882 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6883 // is created and returns the symbol name that matches the ReferenceValue or 6884 // nullptr if none. The ReferenceType is passed in for the IN type of 6885 // reference the instruction is making from the values in defined in the header 6886 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6887 // Out type and the ReferenceName will also be set which is added as a comment 6888 // to the disassembled instruction. 6889 // 6890 // If the symbol name is a C++ mangled name then the demangled name is 6891 // returned through ReferenceName and ReferenceType is set to 6892 // LLVMDisassembler_ReferenceType_DeMangled_Name . 6893 // 6894 // When this is called to get a symbol name for a branch target then the 6895 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 6896 // SymbolValue will be looked for in the indirect symbol table to determine if 6897 // it is an address for a symbol stub. If so then the symbol name for that 6898 // stub is returned indirectly through ReferenceName and then ReferenceType is 6899 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 6900 // 6901 // When this is called with an value loaded via a PC relative load then 6902 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 6903 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 6904 // or an Objective-C meta data reference. If so the output ReferenceType is 6905 // set to correspond to that as well as setting the ReferenceName. 6906 static const char *SymbolizerSymbolLookUp(void *DisInfo, 6907 uint64_t ReferenceValue, 6908 uint64_t *ReferenceType, 6909 uint64_t ReferencePC, 6910 const char **ReferenceName) { 6911 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 6912 // If no verbose symbolic information is wanted then just return nullptr. 6913 if (!info->verbose) { 6914 *ReferenceName = nullptr; 6915 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6916 return nullptr; 6917 } 6918 6919 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 6920 6921 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 6922 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 6923 if (*ReferenceName != nullptr) { 6924 method_reference(info, ReferenceType, ReferenceName); 6925 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 6926 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 6927 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6928 if (info->demangled_name != nullptr) 6929 free(info->demangled_name); 6930 int status; 6931 info->demangled_name = 6932 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 6933 if (info->demangled_name != nullptr) { 6934 *ReferenceName = info->demangled_name; 6935 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6936 } else 6937 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6938 } else 6939 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6940 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 6941 *ReferenceName = 6942 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6943 if (*ReferenceName) 6944 method_reference(info, ReferenceType, ReferenceName); 6945 else 6946 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6947 // If this is arm64 and the reference is an adrp instruction save the 6948 // instruction, passed in ReferenceValue and the address of the instruction 6949 // for use later if we see and add immediate instruction. 6950 } else if (info->O->getArch() == Triple::aarch64 && 6951 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 6952 info->adrp_inst = ReferenceValue; 6953 info->adrp_addr = ReferencePC; 6954 SymbolName = nullptr; 6955 *ReferenceName = nullptr; 6956 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6957 // If this is arm64 and reference is an add immediate instruction and we 6958 // have 6959 // seen an adrp instruction just before it and the adrp's Xd register 6960 // matches 6961 // this add's Xn register reconstruct the value being referenced and look to 6962 // see if it is a literal pointer. Note the add immediate instruction is 6963 // passed in ReferenceValue. 6964 } else if (info->O->getArch() == Triple::aarch64 && 6965 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 6966 ReferencePC - 4 == info->adrp_addr && 6967 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6968 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6969 uint32_t addxri_inst; 6970 uint64_t adrp_imm, addxri_imm; 6971 6972 adrp_imm = 6973 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 6974 if (info->adrp_inst & 0x0200000) 6975 adrp_imm |= 0xfffffffffc000000LL; 6976 6977 addxri_inst = ReferenceValue; 6978 addxri_imm = (addxri_inst >> 10) & 0xfff; 6979 if (((addxri_inst >> 22) & 0x3) == 1) 6980 addxri_imm <<= 12; 6981 6982 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 6983 (adrp_imm << 12) + addxri_imm; 6984 6985 *ReferenceName = 6986 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 6987 if (*ReferenceName == nullptr) 6988 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6989 // If this is arm64 and the reference is a load register instruction and we 6990 // have seen an adrp instruction just before it and the adrp's Xd register 6991 // matches this add's Xn register reconstruct the value being referenced and 6992 // look to see if it is a literal pointer. Note the load register 6993 // instruction is passed in ReferenceValue. 6994 } else if (info->O->getArch() == Triple::aarch64 && 6995 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 6996 ReferencePC - 4 == info->adrp_addr && 6997 (info->adrp_inst & 0x9f000000) == 0x90000000 && 6998 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 6999 uint32_t ldrxui_inst; 7000 uint64_t adrp_imm, ldrxui_imm; 7001 7002 adrp_imm = 7003 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7004 if (info->adrp_inst & 0x0200000) 7005 adrp_imm |= 0xfffffffffc000000LL; 7006 7007 ldrxui_inst = ReferenceValue; 7008 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 7009 7010 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7011 (adrp_imm << 12) + (ldrxui_imm << 3); 7012 7013 *ReferenceName = 7014 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7015 if (*ReferenceName == nullptr) 7016 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7017 } 7018 // If this arm64 and is an load register (PC-relative) instruction the 7019 // ReferenceValue is the PC plus the immediate value. 7020 else if (info->O->getArch() == Triple::aarch64 && 7021 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 7022 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 7023 *ReferenceName = 7024 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7025 if (*ReferenceName == nullptr) 7026 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7027 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 7028 if (info->demangled_name != nullptr) 7029 free(info->demangled_name); 7030 int status; 7031 info->demangled_name = 7032 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 7033 if (info->demangled_name != nullptr) { 7034 *ReferenceName = info->demangled_name; 7035 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 7036 } 7037 } 7038 else { 7039 *ReferenceName = nullptr; 7040 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7041 } 7042 7043 return SymbolName; 7044 } 7045 7046 /// Emits the comments that are stored in the CommentStream. 7047 /// Each comment in the CommentStream must end with a newline. 7048 static void emitComments(raw_svector_ostream &CommentStream, 7049 SmallString<128> &CommentsToEmit, 7050 formatted_raw_ostream &FormattedOS, 7051 const MCAsmInfo &MAI) { 7052 // Flush the stream before taking its content. 7053 StringRef Comments = CommentsToEmit.str(); 7054 // Get the default information for printing a comment. 7055 StringRef CommentBegin = MAI.getCommentString(); 7056 unsigned CommentColumn = MAI.getCommentColumn(); 7057 bool IsFirst = true; 7058 while (!Comments.empty()) { 7059 if (!IsFirst) 7060 FormattedOS << '\n'; 7061 // Emit a line of comments. 7062 FormattedOS.PadToColumn(CommentColumn); 7063 size_t Position = Comments.find('\n'); 7064 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 7065 // Move after the newline character. 7066 Comments = Comments.substr(Position + 1); 7067 IsFirst = false; 7068 } 7069 FormattedOS.flush(); 7070 7071 // Tell the comment stream that the vector changed underneath it. 7072 CommentsToEmit.clear(); 7073 } 7074 7075 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 7076 StringRef DisSegName, StringRef DisSectName) { 7077 const char *McpuDefault = nullptr; 7078 const Target *ThumbTarget = nullptr; 7079 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 7080 if (!TheTarget) { 7081 // GetTarget prints out stuff. 7082 return; 7083 } 7084 std::string MachOMCPU; 7085 if (MCPU.empty() && McpuDefault) 7086 MachOMCPU = McpuDefault; 7087 else 7088 MachOMCPU = MCPU; 7089 7090 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 7091 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 7092 if (ThumbTarget) 7093 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 7094 7095 // Package up features to be passed to target/subtarget 7096 std::string FeaturesStr; 7097 if (!MAttrs.empty()) { 7098 SubtargetFeatures Features; 7099 for (unsigned i = 0; i != MAttrs.size(); ++i) 7100 Features.AddFeature(MAttrs[i]); 7101 FeaturesStr = Features.getString(); 7102 } 7103 7104 // Set up disassembler. 7105 std::unique_ptr<const MCRegisterInfo> MRI( 7106 TheTarget->createMCRegInfo(TripleName)); 7107 std::unique_ptr<const MCAsmInfo> AsmInfo( 7108 TheTarget->createMCAsmInfo(*MRI, TripleName)); 7109 std::unique_ptr<const MCSubtargetInfo> STI( 7110 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 7111 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 7112 std::unique_ptr<MCDisassembler> DisAsm( 7113 TheTarget->createMCDisassembler(*STI, Ctx)); 7114 std::unique_ptr<MCSymbolizer> Symbolizer; 7115 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false); 7116 std::unique_ptr<MCRelocationInfo> RelInfo( 7117 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 7118 if (RelInfo) { 7119 Symbolizer.reset(TheTarget->createMCSymbolizer( 7120 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7121 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 7122 DisAsm->setSymbolizer(std::move(Symbolizer)); 7123 } 7124 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 7125 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 7126 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 7127 // Set the display preference for hex vs. decimal immediates. 7128 IP->setPrintImmHex(PrintImmHex); 7129 // Comment stream and backing vector. 7130 SmallString<128> CommentsToEmit; 7131 raw_svector_ostream CommentStream(CommentsToEmit); 7132 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 7133 // if it is done then arm64 comments for string literals don't get printed 7134 // and some constant get printed instead and not setting it causes intel 7135 // (32-bit and 64-bit) comments printed with different spacing before the 7136 // comment causing different diffs with the 'C' disassembler library API. 7137 // IP->setCommentStream(CommentStream); 7138 7139 if (!AsmInfo || !STI || !DisAsm || !IP) { 7140 WithColor::error(errs(), "llvm-objdump") 7141 << "couldn't initialize disassembler for target " << TripleName << '\n'; 7142 return; 7143 } 7144 7145 // Set up separate thumb disassembler if needed. 7146 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 7147 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 7148 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 7149 std::unique_ptr<MCDisassembler> ThumbDisAsm; 7150 std::unique_ptr<MCInstPrinter> ThumbIP; 7151 std::unique_ptr<MCContext> ThumbCtx; 7152 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 7153 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false); 7154 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 7155 if (ThumbTarget) { 7156 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 7157 ThumbAsmInfo.reset( 7158 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName)); 7159 ThumbSTI.reset( 7160 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 7161 FeaturesStr)); 7162 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 7163 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 7164 MCContext *PtrThumbCtx = ThumbCtx.get(); 7165 ThumbRelInfo.reset( 7166 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 7167 if (ThumbRelInfo) { 7168 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 7169 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7170 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 7171 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 7172 } 7173 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 7174 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 7175 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 7176 *ThumbInstrInfo, *ThumbMRI)); 7177 // Set the display preference for hex vs. decimal immediates. 7178 ThumbIP->setPrintImmHex(PrintImmHex); 7179 } 7180 7181 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) { 7182 WithColor::error(errs(), "llvm-objdump") 7183 << "couldn't initialize disassembler for target " << ThumbTripleName 7184 << '\n'; 7185 return; 7186 } 7187 7188 MachO::mach_header Header = MachOOF->getHeader(); 7189 7190 // FIXME: Using the -cfg command line option, this code used to be able to 7191 // annotate relocations with the referenced symbol's name, and if this was 7192 // inside a __[cf]string section, the data it points to. This is now replaced 7193 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 7194 std::vector<SectionRef> Sections; 7195 std::vector<SymbolRef> Symbols; 7196 SmallVector<uint64_t, 8> FoundFns; 7197 uint64_t BaseSegmentAddress; 7198 7199 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 7200 BaseSegmentAddress); 7201 7202 // Sort the symbols by address, just in case they didn't come in that way. 7203 llvm::sort(Symbols, SymbolSorter()); 7204 7205 // Build a data in code table that is sorted on by the address of each entry. 7206 uint64_t BaseAddress = 0; 7207 if (Header.filetype == MachO::MH_OBJECT) 7208 BaseAddress = Sections[0].getAddress(); 7209 else 7210 BaseAddress = BaseSegmentAddress; 7211 DiceTable Dices; 7212 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 7213 DI != DE; ++DI) { 7214 uint32_t Offset; 7215 DI->getOffset(Offset); 7216 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 7217 } 7218 array_pod_sort(Dices.begin(), Dices.end()); 7219 7220 #ifndef NDEBUG 7221 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); 7222 #else 7223 raw_ostream &DebugOut = nulls(); 7224 #endif 7225 7226 std::unique_ptr<DIContext> diContext; 7227 ObjectFile *DbgObj = MachOOF; 7228 std::unique_ptr<MemoryBuffer> DSYMBuf; 7229 // Try to find debug info and set up the DIContext for it. 7230 if (UseDbg) { 7231 // A separate DSym file path was specified, parse it as a macho file, 7232 // get the sections and supply it to the section name parsing machinery. 7233 if (!DSYMFile.empty()) { 7234 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 7235 MemoryBuffer::getFileOrSTDIN(DSYMFile); 7236 if (std::error_code EC = BufOrErr.getError()) { 7237 report_error(errorCodeToError(EC), DSYMFile); 7238 return; 7239 } 7240 7241 std::unique_ptr<MachOObjectFile> DbgObjCheck = unwrapOrError( 7242 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()), 7243 DSYMFile.getValue()); 7244 DbgObj = DbgObjCheck.release(); 7245 // We need to keep the file alive, because we're replacing DbgObj with it. 7246 DSYMBuf = std::move(BufOrErr.get()); 7247 } 7248 7249 // Setup the DIContext 7250 diContext = DWARFContext::create(*DbgObj); 7251 } 7252 7253 if (FilterSections.empty()) 7254 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 7255 7256 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 7257 StringRef SectName; 7258 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName) 7259 continue; 7260 7261 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 7262 7263 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 7264 if (SegmentName != DisSegName) 7265 continue; 7266 7267 StringRef BytesStr = 7268 unwrapOrError(Sections[SectIdx].getContents(), Filename); 7269 ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr); 7270 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7271 7272 bool symbolTableWorked = false; 7273 7274 // Create a map of symbol addresses to symbol names for use by 7275 // the SymbolizerSymbolLookUp() routine. 7276 SymbolAddressMap AddrMap; 7277 bool DisSymNameFound = false; 7278 for (const SymbolRef &Symbol : MachOOF->symbols()) { 7279 SymbolRef::Type ST = 7280 unwrapOrError(Symbol.getType(), MachOOF->getFileName()); 7281 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 7282 ST == SymbolRef::ST_Other) { 7283 uint64_t Address = Symbol.getValue(); 7284 StringRef SymName = 7285 unwrapOrError(Symbol.getName(), MachOOF->getFileName()); 7286 AddrMap[Address] = SymName; 7287 if (!DisSymName.empty() && DisSymName == SymName) 7288 DisSymNameFound = true; 7289 } 7290 } 7291 if (!DisSymName.empty() && !DisSymNameFound) { 7292 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 7293 return; 7294 } 7295 // Set up the block of info used by the Symbolizer call backs. 7296 SymbolizerInfo.verbose = !NoSymbolicOperands; 7297 SymbolizerInfo.O = MachOOF; 7298 SymbolizerInfo.S = Sections[SectIdx]; 7299 SymbolizerInfo.AddrMap = &AddrMap; 7300 SymbolizerInfo.Sections = &Sections; 7301 // Same for the ThumbSymbolizer 7302 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands; 7303 ThumbSymbolizerInfo.O = MachOOF; 7304 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7305 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7306 ThumbSymbolizerInfo.Sections = &Sections; 7307 7308 unsigned int Arch = MachOOF->getArch(); 7309 7310 // Skip all symbols if this is a stubs file. 7311 if (Bytes.empty()) 7312 return; 7313 7314 // If the section has symbols but no symbol at the start of the section 7315 // these are used to make sure the bytes before the first symbol are 7316 // disassembled. 7317 bool FirstSymbol = true; 7318 bool FirstSymbolAtSectionStart = true; 7319 7320 // Disassemble symbol by symbol. 7321 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7322 StringRef SymName = 7323 unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName()); 7324 SymbolRef::Type ST = 7325 unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName()); 7326 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7327 continue; 7328 7329 // Make sure the symbol is defined in this section. 7330 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7331 if (!containsSym) { 7332 if (!DisSymName.empty() && DisSymName == SymName) { 7333 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7334 return; 7335 } 7336 continue; 7337 } 7338 // The __mh_execute_header is special and we need to deal with that fact 7339 // this symbol is before the start of the (__TEXT,__text) section and at the 7340 // address of the start of the __TEXT segment. This is because this symbol 7341 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7342 // start of the section in a standard MH_EXECUTE filetype. 7343 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7344 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7345 return; 7346 } 7347 // When this code is trying to disassemble a symbol at a time and in the 7348 // case there is only the __mh_execute_header symbol left as in a stripped 7349 // executable, we need to deal with this by ignoring this symbol so the 7350 // whole section is disassembled and this symbol is then not displayed. 7351 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7352 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7353 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7354 continue; 7355 7356 // If we are only disassembling one symbol see if this is that symbol. 7357 if (!DisSymName.empty() && DisSymName != SymName) 7358 continue; 7359 7360 // Start at the address of the symbol relative to the section's address. 7361 uint64_t SectSize = Sections[SectIdx].getSize(); 7362 uint64_t Start = Symbols[SymIdx].getValue(); 7363 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7364 Start -= SectionAddress; 7365 7366 if (Start > SectSize) { 7367 outs() << "section data ends, " << SymName 7368 << " lies outside valid range\n"; 7369 return; 7370 } 7371 7372 // Stop disassembling either at the beginning of the next symbol or at 7373 // the end of the section. 7374 bool containsNextSym = false; 7375 uint64_t NextSym = 0; 7376 uint64_t NextSymIdx = SymIdx + 1; 7377 while (Symbols.size() > NextSymIdx) { 7378 SymbolRef::Type NextSymType = unwrapOrError( 7379 Symbols[NextSymIdx].getType(), MachOOF->getFileName()); 7380 if (NextSymType == SymbolRef::ST_Function) { 7381 containsNextSym = 7382 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7383 NextSym = Symbols[NextSymIdx].getValue(); 7384 NextSym -= SectionAddress; 7385 break; 7386 } 7387 ++NextSymIdx; 7388 } 7389 7390 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7391 uint64_t Size; 7392 7393 symbolTableWorked = true; 7394 7395 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7396 bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb; 7397 7398 // We only need the dedicated Thumb target if there's a real choice 7399 // (i.e. we're not targeting M-class) and the function is Thumb. 7400 bool UseThumbTarget = IsThumb && ThumbTarget; 7401 7402 // If we are not specifying a symbol to start disassembly with and this 7403 // is the first symbol in the section but not at the start of the section 7404 // then move the disassembly index to the start of the section and 7405 // don't print the symbol name just yet. This is so the bytes before the 7406 // first symbol are disassembled. 7407 uint64_t SymbolStart = Start; 7408 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7409 FirstSymbolAtSectionStart = false; 7410 Start = 0; 7411 } 7412 else 7413 outs() << SymName << ":\n"; 7414 7415 DILineInfo lastLine; 7416 for (uint64_t Index = Start; Index < End; Index += Size) { 7417 MCInst Inst; 7418 7419 // If this is the first symbol in the section and it was not at the 7420 // start of the section, see if we are at its Index now and if so print 7421 // the symbol name. 7422 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7423 outs() << SymName << ":\n"; 7424 7425 uint64_t PC = SectAddress + Index; 7426 if (!NoLeadingAddr) { 7427 if (FullLeadingAddr) { 7428 if (MachOOF->is64Bit()) 7429 outs() << format("%016" PRIx64, PC); 7430 else 7431 outs() << format("%08" PRIx64, PC); 7432 } else { 7433 outs() << format("%8" PRIx64 ":", PC); 7434 } 7435 } 7436 if (!NoShowRawInsn || Arch == Triple::arm) 7437 outs() << "\t"; 7438 7439 // Check the data in code table here to see if this is data not an 7440 // instruction to be disassembled. 7441 DiceTable Dice; 7442 Dice.push_back(std::make_pair(PC, DiceRef())); 7443 dice_table_iterator DTI = 7444 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 7445 compareDiceTableEntries); 7446 if (DTI != Dices.end()) { 7447 uint16_t Length; 7448 DTI->second.getLength(Length); 7449 uint16_t Kind; 7450 DTI->second.getKind(Kind); 7451 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind); 7452 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 7453 (PC == (DTI->first + Length - 1)) && (Length & 1)) 7454 Size++; 7455 continue; 7456 } 7457 7458 SmallVector<char, 64> AnnotationsBytes; 7459 raw_svector_ostream Annotations(AnnotationsBytes); 7460 7461 bool gotInst; 7462 if (UseThumbTarget) 7463 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7464 PC, DebugOut, Annotations); 7465 else 7466 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7467 DebugOut, Annotations); 7468 if (gotInst) { 7469 if (!NoShowRawInsn || Arch == Triple::arm) { 7470 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); 7471 } 7472 formatted_raw_ostream FormattedOS(outs()); 7473 StringRef AnnotationsStr = Annotations.str(); 7474 if (UseThumbTarget) 7475 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI); 7476 else 7477 IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI); 7478 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7479 7480 // Print debug info. 7481 if (diContext) { 7482 DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx}); 7483 // Print valid line info if it changed. 7484 if (dli != lastLine && dli.Line != 0) 7485 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7486 << dli.Column; 7487 lastLine = dli; 7488 } 7489 outs() << "\n"; 7490 } else { 7491 unsigned int Arch = MachOOF->getArch(); 7492 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7493 outs() << format("\t.byte 0x%02x #bad opcode\n", 7494 *(Bytes.data() + Index) & 0xff); 7495 Size = 1; // skip exactly one illegible byte and move on. 7496 } else if (Arch == Triple::aarch64 || 7497 (Arch == Triple::arm && !IsThumb)) { 7498 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7499 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7500 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7501 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7502 outs() << format("\t.long\t0x%08x\n", opcode); 7503 Size = 4; 7504 } else if (Arch == Triple::arm) { 7505 assert(IsThumb && "ARM mode should have been dealt with above"); 7506 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7507 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7508 outs() << format("\t.short\t0x%04x\n", opcode); 7509 Size = 2; 7510 } else{ 7511 WithColor::warning(errs(), "llvm-objdump") 7512 << "invalid instruction encoding\n"; 7513 if (Size == 0) 7514 Size = 1; // skip illegible bytes 7515 } 7516 } 7517 } 7518 // Now that we are done disassembled the first symbol set the bool that 7519 // were doing this to false. 7520 FirstSymbol = false; 7521 } 7522 if (!symbolTableWorked) { 7523 // Reading the symbol table didn't work, disassemble the whole section. 7524 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7525 uint64_t SectSize = Sections[SectIdx].getSize(); 7526 uint64_t InstSize; 7527 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7528 MCInst Inst; 7529 7530 uint64_t PC = SectAddress + Index; 7531 SmallVector<char, 64> AnnotationsBytes; 7532 raw_svector_ostream Annotations(AnnotationsBytes); 7533 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7534 DebugOut, Annotations)) { 7535 if (!NoLeadingAddr) { 7536 if (FullLeadingAddr) { 7537 if (MachOOF->is64Bit()) 7538 outs() << format("%016" PRIx64, PC); 7539 else 7540 outs() << format("%08" PRIx64, PC); 7541 } else { 7542 outs() << format("%8" PRIx64 ":", PC); 7543 } 7544 } 7545 if (!NoShowRawInsn || Arch == Triple::arm) { 7546 outs() << "\t"; 7547 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); 7548 } 7549 StringRef AnnotationsStr = Annotations.str(); 7550 IP->printInst(&Inst, outs(), AnnotationsStr, *STI); 7551 outs() << "\n"; 7552 } else { 7553 unsigned int Arch = MachOOF->getArch(); 7554 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 7555 outs() << format("\t.byte 0x%02x #bad opcode\n", 7556 *(Bytes.data() + Index) & 0xff); 7557 InstSize = 1; // skip exactly one illegible byte and move on. 7558 } else { 7559 WithColor::warning(errs(), "llvm-objdump") 7560 << "invalid instruction encoding\n"; 7561 if (InstSize == 0) 7562 InstSize = 1; // skip illegible bytes 7563 } 7564 } 7565 } 7566 } 7567 // The TripleName's need to be reset if we are called again for a different 7568 // archtecture. 7569 TripleName = ""; 7570 ThumbTripleName = ""; 7571 7572 if (SymbolizerInfo.demangled_name != nullptr) 7573 free(SymbolizerInfo.demangled_name); 7574 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7575 free(ThumbSymbolizerInfo.demangled_name); 7576 } 7577 } 7578 7579 //===----------------------------------------------------------------------===// 7580 // __compact_unwind section dumping 7581 //===----------------------------------------------------------------------===// 7582 7583 namespace { 7584 7585 template <typename T> 7586 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7587 using llvm::support::little; 7588 using llvm::support::unaligned; 7589 7590 if (Offset + sizeof(T) > Contents.size()) { 7591 outs() << "warning: attempt to read past end of buffer\n"; 7592 return T(); 7593 } 7594 7595 uint64_t Val = 7596 support::endian::read<T, little, unaligned>(Contents.data() + Offset); 7597 return Val; 7598 } 7599 7600 template <typename T> 7601 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7602 T Val = read<T>(Contents, Offset); 7603 Offset += sizeof(T); 7604 return Val; 7605 } 7606 7607 struct CompactUnwindEntry { 7608 uint32_t OffsetInSection; 7609 7610 uint64_t FunctionAddr; 7611 uint32_t Length; 7612 uint32_t CompactEncoding; 7613 uint64_t PersonalityAddr; 7614 uint64_t LSDAAddr; 7615 7616 RelocationRef FunctionReloc; 7617 RelocationRef PersonalityReloc; 7618 RelocationRef LSDAReloc; 7619 7620 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7621 : OffsetInSection(Offset) { 7622 if (Is64) 7623 read<uint64_t>(Contents, Offset); 7624 else 7625 read<uint32_t>(Contents, Offset); 7626 } 7627 7628 private: 7629 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7630 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7631 Length = readNext<uint32_t>(Contents, Offset); 7632 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7633 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7634 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7635 } 7636 }; 7637 } 7638 7639 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7640 /// and data being relocated, determine the best base Name and Addend to use for 7641 /// display purposes. 7642 /// 7643 /// 1. An Extern relocation will directly reference a symbol (and the data is 7644 /// then already an addend), so use that. 7645 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7646 // a symbol before it in the same section, and use the offset from there. 7647 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7648 /// referenced section. 7649 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7650 std::map<uint64_t, SymbolRef> &Symbols, 7651 const RelocationRef &Reloc, uint64_t Addr, 7652 StringRef &Name, uint64_t &Addend) { 7653 if (Reloc.getSymbol() != Obj->symbol_end()) { 7654 Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName()); 7655 Addend = Addr; 7656 return; 7657 } 7658 7659 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7660 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7661 7662 uint64_t SectionAddr = RelocSection.getAddress(); 7663 7664 auto Sym = Symbols.upper_bound(Addr); 7665 if (Sym == Symbols.begin()) { 7666 // The first symbol in the object is after this reference, the best we can 7667 // do is section-relative notation. 7668 RelocSection.getName(Name); 7669 Addend = Addr - SectionAddr; 7670 return; 7671 } 7672 7673 // Go back one so that SymbolAddress <= Addr. 7674 --Sym; 7675 7676 section_iterator SymSection = 7677 unwrapOrError(Sym->second.getSection(), Obj->getFileName()); 7678 if (RelocSection == *SymSection) { 7679 // There's a valid symbol in the same section before this reference. 7680 Name = unwrapOrError(Sym->second.getName(), Obj->getFileName()); 7681 Addend = Addr - Sym->first; 7682 return; 7683 } 7684 7685 // There is a symbol before this reference, but it's in a different 7686 // section. Probably not helpful to mention it, so use the section name. 7687 RelocSection.getName(Name); 7688 Addend = Addr - SectionAddr; 7689 } 7690 7691 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7692 std::map<uint64_t, SymbolRef> &Symbols, 7693 const RelocationRef &Reloc, uint64_t Addr) { 7694 StringRef Name; 7695 uint64_t Addend; 7696 7697 if (!Reloc.getObject()) 7698 return; 7699 7700 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7701 7702 outs() << Name; 7703 if (Addend) 7704 outs() << " + " << format("0x%" PRIx64, Addend); 7705 } 7706 7707 static void 7708 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7709 std::map<uint64_t, SymbolRef> &Symbols, 7710 const SectionRef &CompactUnwind) { 7711 7712 if (!Obj->isLittleEndian()) { 7713 outs() << "Skipping big-endian __compact_unwind section\n"; 7714 return; 7715 } 7716 7717 bool Is64 = Obj->is64Bit(); 7718 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7719 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7720 7721 StringRef Contents = 7722 unwrapOrError(CompactUnwind.getContents(), Obj->getFileName()); 7723 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7724 7725 // First populate the initial raw offsets, encodings and so on from the entry. 7726 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7727 CompactUnwindEntry Entry(Contents, Offset, Is64); 7728 CompactUnwinds.push_back(Entry); 7729 } 7730 7731 // Next we need to look at the relocations to find out what objects are 7732 // actually being referred to. 7733 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7734 uint64_t RelocAddress = Reloc.getOffset(); 7735 7736 uint32_t EntryIdx = RelocAddress / EntrySize; 7737 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7738 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7739 7740 if (OffsetInEntry == 0) 7741 Entry.FunctionReloc = Reloc; 7742 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7743 Entry.PersonalityReloc = Reloc; 7744 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7745 Entry.LSDAReloc = Reloc; 7746 else { 7747 outs() << "Invalid relocation in __compact_unwind section\n"; 7748 return; 7749 } 7750 } 7751 7752 // Finally, we're ready to print the data we've gathered. 7753 outs() << "Contents of __compact_unwind section:\n"; 7754 for (auto &Entry : CompactUnwinds) { 7755 outs() << " Entry at offset " 7756 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7757 7758 // 1. Start of the region this entry applies to. 7759 outs() << " start: " << format("0x%" PRIx64, 7760 Entry.FunctionAddr) << ' '; 7761 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7762 outs() << '\n'; 7763 7764 // 2. Length of the region this entry applies to. 7765 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7766 << '\n'; 7767 // 3. The 32-bit compact encoding. 7768 outs() << " compact encoding: " 7769 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7770 7771 // 4. The personality function, if present. 7772 if (Entry.PersonalityReloc.getObject()) { 7773 outs() << " personality function: " 7774 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7775 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7776 Entry.PersonalityAddr); 7777 outs() << '\n'; 7778 } 7779 7780 // 5. This entry's language-specific data area. 7781 if (Entry.LSDAReloc.getObject()) { 7782 outs() << " LSDA: " << format("0x%" PRIx64, 7783 Entry.LSDAAddr) << ' '; 7784 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7785 outs() << '\n'; 7786 } 7787 } 7788 } 7789 7790 //===----------------------------------------------------------------------===// 7791 // __unwind_info section dumping 7792 //===----------------------------------------------------------------------===// 7793 7794 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 7795 ptrdiff_t Pos = 0; 7796 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7797 (void)Kind; 7798 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7799 7800 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7801 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7802 7803 Pos = EntriesStart; 7804 for (unsigned i = 0; i < NumEntries; ++i) { 7805 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 7806 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7807 7808 outs() << " [" << i << "]: " 7809 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7810 << ", " 7811 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7812 } 7813 } 7814 7815 static void printCompressedSecondLevelUnwindPage( 7816 StringRef PageData, uint32_t FunctionBase, 7817 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7818 ptrdiff_t Pos = 0; 7819 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7820 (void)Kind; 7821 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 7822 7823 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7824 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7825 7826 uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos); 7827 readNext<uint16_t>(PageData, Pos); 7828 StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos); 7829 7830 Pos = EntriesStart; 7831 for (unsigned i = 0; i < NumEntries; ++i) { 7832 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 7833 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 7834 uint32_t EncodingIdx = Entry >> 24; 7835 7836 uint32_t Encoding; 7837 if (EncodingIdx < CommonEncodings.size()) 7838 Encoding = CommonEncodings[EncodingIdx]; 7839 else 7840 Encoding = read<uint32_t>(PageEncodings, 7841 sizeof(uint32_t) * 7842 (EncodingIdx - CommonEncodings.size())); 7843 7844 outs() << " [" << i << "]: " 7845 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7846 << ", " 7847 << "encoding[" << EncodingIdx 7848 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 7849 } 7850 } 7851 7852 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 7853 std::map<uint64_t, SymbolRef> &Symbols, 7854 const SectionRef &UnwindInfo) { 7855 7856 if (!Obj->isLittleEndian()) { 7857 outs() << "Skipping big-endian __unwind_info section\n"; 7858 return; 7859 } 7860 7861 outs() << "Contents of __unwind_info section:\n"; 7862 7863 StringRef Contents = 7864 unwrapOrError(UnwindInfo.getContents(), Obj->getFileName()); 7865 ptrdiff_t Pos = 0; 7866 7867 //===---------------------------------- 7868 // Section header 7869 //===---------------------------------- 7870 7871 uint32_t Version = readNext<uint32_t>(Contents, Pos); 7872 outs() << " Version: " 7873 << format("0x%" PRIx32, Version) << '\n'; 7874 if (Version != 1) { 7875 outs() << " Skipping section with unknown version\n"; 7876 return; 7877 } 7878 7879 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 7880 outs() << " Common encodings array section offset: " 7881 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 7882 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 7883 outs() << " Number of common encodings in array: " 7884 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 7885 7886 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 7887 outs() << " Personality function array section offset: " 7888 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 7889 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 7890 outs() << " Number of personality functions in array: " 7891 << format("0x%" PRIx32, NumPersonalities) << '\n'; 7892 7893 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 7894 outs() << " Index array section offset: " 7895 << format("0x%" PRIx32, IndicesStart) << '\n'; 7896 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 7897 outs() << " Number of indices in array: " 7898 << format("0x%" PRIx32, NumIndices) << '\n'; 7899 7900 //===---------------------------------- 7901 // A shared list of common encodings 7902 //===---------------------------------- 7903 7904 // These occupy indices in the range [0, N] whenever an encoding is referenced 7905 // from a compressed 2nd level index table. In practice the linker only 7906 // creates ~128 of these, so that indices are available to embed encodings in 7907 // the 2nd level index. 7908 7909 SmallVector<uint32_t, 64> CommonEncodings; 7910 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 7911 Pos = CommonEncodingsStart; 7912 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 7913 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 7914 CommonEncodings.push_back(Encoding); 7915 7916 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 7917 << '\n'; 7918 } 7919 7920 //===---------------------------------- 7921 // Personality functions used in this executable 7922 //===---------------------------------- 7923 7924 // There should be only a handful of these (one per source language, 7925 // roughly). Particularly since they only get 2 bits in the compact encoding. 7926 7927 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 7928 Pos = PersonalitiesStart; 7929 for (unsigned i = 0; i < NumPersonalities; ++i) { 7930 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 7931 outs() << " personality[" << i + 1 7932 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 7933 } 7934 7935 //===---------------------------------- 7936 // The level 1 index entries 7937 //===---------------------------------- 7938 7939 // These specify an approximate place to start searching for the more detailed 7940 // information, sorted by PC. 7941 7942 struct IndexEntry { 7943 uint32_t FunctionOffset; 7944 uint32_t SecondLevelPageStart; 7945 uint32_t LSDAStart; 7946 }; 7947 7948 SmallVector<IndexEntry, 4> IndexEntries; 7949 7950 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 7951 Pos = IndicesStart; 7952 for (unsigned i = 0; i < NumIndices; ++i) { 7953 IndexEntry Entry; 7954 7955 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 7956 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 7957 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 7958 IndexEntries.push_back(Entry); 7959 7960 outs() << " [" << i << "]: " 7961 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 7962 << ", " 7963 << "2nd level page offset=" 7964 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 7965 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 7966 } 7967 7968 //===---------------------------------- 7969 // Next come the LSDA tables 7970 //===---------------------------------- 7971 7972 // The LSDA layout is rather implicit: it's a contiguous array of entries from 7973 // the first top-level index's LSDAOffset to the last (sentinel). 7974 7975 outs() << " LSDA descriptors:\n"; 7976 Pos = IndexEntries[0].LSDAStart; 7977 const uint32_t LSDASize = 2 * sizeof(uint32_t); 7978 int NumLSDAs = 7979 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 7980 7981 for (int i = 0; i < NumLSDAs; ++i) { 7982 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 7983 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 7984 outs() << " [" << i << "]: " 7985 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7986 << ", " 7987 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 7988 } 7989 7990 //===---------------------------------- 7991 // Finally, the 2nd level indices 7992 //===---------------------------------- 7993 7994 // Generally these are 4K in size, and have 2 possible forms: 7995 // + Regular stores up to 511 entries with disparate encodings 7996 // + Compressed stores up to 1021 entries if few enough compact encoding 7997 // values are used. 7998 outs() << " Second level indices:\n"; 7999 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 8000 // The final sentinel top-level index has no associated 2nd level page 8001 if (IndexEntries[i].SecondLevelPageStart == 0) 8002 break; 8003 8004 outs() << " Second level index[" << i << "]: " 8005 << "offset in section=" 8006 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 8007 << ", " 8008 << "base function offset=" 8009 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 8010 8011 Pos = IndexEntries[i].SecondLevelPageStart; 8012 if (Pos + sizeof(uint32_t) > Contents.size()) { 8013 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 8014 continue; 8015 } 8016 8017 uint32_t Kind = 8018 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 8019 if (Kind == 2) 8020 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 8021 else if (Kind == 3) 8022 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 8023 IndexEntries[i].FunctionOffset, 8024 CommonEncodings); 8025 else 8026 outs() << " Skipping 2nd level page with unknown kind " << Kind 8027 << '\n'; 8028 } 8029 } 8030 8031 void printMachOUnwindInfo(const MachOObjectFile *Obj) { 8032 std::map<uint64_t, SymbolRef> Symbols; 8033 for (const SymbolRef &SymRef : Obj->symbols()) { 8034 // Discard any undefined or absolute symbols. They're not going to take part 8035 // in the convenience lookup for unwind info and just take up resources. 8036 auto SectOrErr = SymRef.getSection(); 8037 if (!SectOrErr) { 8038 // TODO: Actually report errors helpfully. 8039 consumeError(SectOrErr.takeError()); 8040 continue; 8041 } 8042 section_iterator Section = *SectOrErr; 8043 if (Section == Obj->section_end()) 8044 continue; 8045 8046 uint64_t Addr = SymRef.getValue(); 8047 Symbols.insert(std::make_pair(Addr, SymRef)); 8048 } 8049 8050 for (const SectionRef &Section : Obj->sections()) { 8051 StringRef SectName; 8052 Section.getName(SectName); 8053 if (SectName == "__compact_unwind") 8054 printMachOCompactUnwindSection(Obj, Symbols, Section); 8055 else if (SectName == "__unwind_info") 8056 printMachOUnwindInfoSection(Obj, Symbols, Section); 8057 } 8058 } 8059 8060 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 8061 uint32_t cpusubtype, uint32_t filetype, 8062 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 8063 bool verbose) { 8064 outs() << "Mach header\n"; 8065 outs() << " magic cputype cpusubtype caps filetype ncmds " 8066 "sizeofcmds flags\n"; 8067 if (verbose) { 8068 if (magic == MachO::MH_MAGIC) 8069 outs() << " MH_MAGIC"; 8070 else if (magic == MachO::MH_MAGIC_64) 8071 outs() << "MH_MAGIC_64"; 8072 else 8073 outs() << format(" 0x%08" PRIx32, magic); 8074 switch (cputype) { 8075 case MachO::CPU_TYPE_I386: 8076 outs() << " I386"; 8077 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8078 case MachO::CPU_SUBTYPE_I386_ALL: 8079 outs() << " ALL"; 8080 break; 8081 default: 8082 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8083 break; 8084 } 8085 break; 8086 case MachO::CPU_TYPE_X86_64: 8087 outs() << " X86_64"; 8088 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8089 case MachO::CPU_SUBTYPE_X86_64_ALL: 8090 outs() << " ALL"; 8091 break; 8092 case MachO::CPU_SUBTYPE_X86_64_H: 8093 outs() << " Haswell"; 8094 break; 8095 default: 8096 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8097 break; 8098 } 8099 break; 8100 case MachO::CPU_TYPE_ARM: 8101 outs() << " ARM"; 8102 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8103 case MachO::CPU_SUBTYPE_ARM_ALL: 8104 outs() << " ALL"; 8105 break; 8106 case MachO::CPU_SUBTYPE_ARM_V4T: 8107 outs() << " V4T"; 8108 break; 8109 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 8110 outs() << " V5TEJ"; 8111 break; 8112 case MachO::CPU_SUBTYPE_ARM_XSCALE: 8113 outs() << " XSCALE"; 8114 break; 8115 case MachO::CPU_SUBTYPE_ARM_V6: 8116 outs() << " V6"; 8117 break; 8118 case MachO::CPU_SUBTYPE_ARM_V6M: 8119 outs() << " V6M"; 8120 break; 8121 case MachO::CPU_SUBTYPE_ARM_V7: 8122 outs() << " V7"; 8123 break; 8124 case MachO::CPU_SUBTYPE_ARM_V7EM: 8125 outs() << " V7EM"; 8126 break; 8127 case MachO::CPU_SUBTYPE_ARM_V7K: 8128 outs() << " V7K"; 8129 break; 8130 case MachO::CPU_SUBTYPE_ARM_V7M: 8131 outs() << " V7M"; 8132 break; 8133 case MachO::CPU_SUBTYPE_ARM_V7S: 8134 outs() << " V7S"; 8135 break; 8136 default: 8137 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8138 break; 8139 } 8140 break; 8141 case MachO::CPU_TYPE_ARM64: 8142 outs() << " ARM64"; 8143 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8144 case MachO::CPU_SUBTYPE_ARM64_ALL: 8145 outs() << " ALL"; 8146 break; 8147 case MachO::CPU_SUBTYPE_ARM64E: 8148 outs() << " E"; 8149 break; 8150 default: 8151 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8152 break; 8153 } 8154 break; 8155 case MachO::CPU_TYPE_ARM64_32: 8156 outs() << " ARM64_32"; 8157 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8158 case MachO::CPU_SUBTYPE_ARM64_32_V8: 8159 outs() << " V8"; 8160 break; 8161 default: 8162 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8163 break; 8164 } 8165 break; 8166 case MachO::CPU_TYPE_POWERPC: 8167 outs() << " PPC"; 8168 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8169 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8170 outs() << " ALL"; 8171 break; 8172 default: 8173 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8174 break; 8175 } 8176 break; 8177 case MachO::CPU_TYPE_POWERPC64: 8178 outs() << " PPC64"; 8179 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8180 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8181 outs() << " ALL"; 8182 break; 8183 default: 8184 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8185 break; 8186 } 8187 break; 8188 default: 8189 outs() << format(" %7d", cputype); 8190 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8191 break; 8192 } 8193 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 8194 outs() << " LIB64"; 8195 } else { 8196 outs() << format(" 0x%02" PRIx32, 8197 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8198 } 8199 switch (filetype) { 8200 case MachO::MH_OBJECT: 8201 outs() << " OBJECT"; 8202 break; 8203 case MachO::MH_EXECUTE: 8204 outs() << " EXECUTE"; 8205 break; 8206 case MachO::MH_FVMLIB: 8207 outs() << " FVMLIB"; 8208 break; 8209 case MachO::MH_CORE: 8210 outs() << " CORE"; 8211 break; 8212 case MachO::MH_PRELOAD: 8213 outs() << " PRELOAD"; 8214 break; 8215 case MachO::MH_DYLIB: 8216 outs() << " DYLIB"; 8217 break; 8218 case MachO::MH_DYLIB_STUB: 8219 outs() << " DYLIB_STUB"; 8220 break; 8221 case MachO::MH_DYLINKER: 8222 outs() << " DYLINKER"; 8223 break; 8224 case MachO::MH_BUNDLE: 8225 outs() << " BUNDLE"; 8226 break; 8227 case MachO::MH_DSYM: 8228 outs() << " DSYM"; 8229 break; 8230 case MachO::MH_KEXT_BUNDLE: 8231 outs() << " KEXTBUNDLE"; 8232 break; 8233 default: 8234 outs() << format(" %10u", filetype); 8235 break; 8236 } 8237 outs() << format(" %5u", ncmds); 8238 outs() << format(" %10u", sizeofcmds); 8239 uint32_t f = flags; 8240 if (f & MachO::MH_NOUNDEFS) { 8241 outs() << " NOUNDEFS"; 8242 f &= ~MachO::MH_NOUNDEFS; 8243 } 8244 if (f & MachO::MH_INCRLINK) { 8245 outs() << " INCRLINK"; 8246 f &= ~MachO::MH_INCRLINK; 8247 } 8248 if (f & MachO::MH_DYLDLINK) { 8249 outs() << " DYLDLINK"; 8250 f &= ~MachO::MH_DYLDLINK; 8251 } 8252 if (f & MachO::MH_BINDATLOAD) { 8253 outs() << " BINDATLOAD"; 8254 f &= ~MachO::MH_BINDATLOAD; 8255 } 8256 if (f & MachO::MH_PREBOUND) { 8257 outs() << " PREBOUND"; 8258 f &= ~MachO::MH_PREBOUND; 8259 } 8260 if (f & MachO::MH_SPLIT_SEGS) { 8261 outs() << " SPLIT_SEGS"; 8262 f &= ~MachO::MH_SPLIT_SEGS; 8263 } 8264 if (f & MachO::MH_LAZY_INIT) { 8265 outs() << " LAZY_INIT"; 8266 f &= ~MachO::MH_LAZY_INIT; 8267 } 8268 if (f & MachO::MH_TWOLEVEL) { 8269 outs() << " TWOLEVEL"; 8270 f &= ~MachO::MH_TWOLEVEL; 8271 } 8272 if (f & MachO::MH_FORCE_FLAT) { 8273 outs() << " FORCE_FLAT"; 8274 f &= ~MachO::MH_FORCE_FLAT; 8275 } 8276 if (f & MachO::MH_NOMULTIDEFS) { 8277 outs() << " NOMULTIDEFS"; 8278 f &= ~MachO::MH_NOMULTIDEFS; 8279 } 8280 if (f & MachO::MH_NOFIXPREBINDING) { 8281 outs() << " NOFIXPREBINDING"; 8282 f &= ~MachO::MH_NOFIXPREBINDING; 8283 } 8284 if (f & MachO::MH_PREBINDABLE) { 8285 outs() << " PREBINDABLE"; 8286 f &= ~MachO::MH_PREBINDABLE; 8287 } 8288 if (f & MachO::MH_ALLMODSBOUND) { 8289 outs() << " ALLMODSBOUND"; 8290 f &= ~MachO::MH_ALLMODSBOUND; 8291 } 8292 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8293 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8294 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8295 } 8296 if (f & MachO::MH_CANONICAL) { 8297 outs() << " CANONICAL"; 8298 f &= ~MachO::MH_CANONICAL; 8299 } 8300 if (f & MachO::MH_WEAK_DEFINES) { 8301 outs() << " WEAK_DEFINES"; 8302 f &= ~MachO::MH_WEAK_DEFINES; 8303 } 8304 if (f & MachO::MH_BINDS_TO_WEAK) { 8305 outs() << " BINDS_TO_WEAK"; 8306 f &= ~MachO::MH_BINDS_TO_WEAK; 8307 } 8308 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8309 outs() << " ALLOW_STACK_EXECUTION"; 8310 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8311 } 8312 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8313 outs() << " DEAD_STRIPPABLE_DYLIB"; 8314 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8315 } 8316 if (f & MachO::MH_PIE) { 8317 outs() << " PIE"; 8318 f &= ~MachO::MH_PIE; 8319 } 8320 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8321 outs() << " NO_REEXPORTED_DYLIBS"; 8322 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8323 } 8324 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8325 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8326 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8327 } 8328 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8329 outs() << " MH_NO_HEAP_EXECUTION"; 8330 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8331 } 8332 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8333 outs() << " APP_EXTENSION_SAFE"; 8334 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8335 } 8336 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8337 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8338 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8339 } 8340 if (f != 0 || flags == 0) 8341 outs() << format(" 0x%08" PRIx32, f); 8342 } else { 8343 outs() << format(" 0x%08" PRIx32, magic); 8344 outs() << format(" %7d", cputype); 8345 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8346 outs() << format(" 0x%02" PRIx32, 8347 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8348 outs() << format(" %10u", filetype); 8349 outs() << format(" %5u", ncmds); 8350 outs() << format(" %10u", sizeofcmds); 8351 outs() << format(" 0x%08" PRIx32, flags); 8352 } 8353 outs() << "\n"; 8354 } 8355 8356 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8357 StringRef SegName, uint64_t vmaddr, 8358 uint64_t vmsize, uint64_t fileoff, 8359 uint64_t filesize, uint32_t maxprot, 8360 uint32_t initprot, uint32_t nsects, 8361 uint32_t flags, uint32_t object_size, 8362 bool verbose) { 8363 uint64_t expected_cmdsize; 8364 if (cmd == MachO::LC_SEGMENT) { 8365 outs() << " cmd LC_SEGMENT\n"; 8366 expected_cmdsize = nsects; 8367 expected_cmdsize *= sizeof(struct MachO::section); 8368 expected_cmdsize += sizeof(struct MachO::segment_command); 8369 } else { 8370 outs() << " cmd LC_SEGMENT_64\n"; 8371 expected_cmdsize = nsects; 8372 expected_cmdsize *= sizeof(struct MachO::section_64); 8373 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8374 } 8375 outs() << " cmdsize " << cmdsize; 8376 if (cmdsize != expected_cmdsize) 8377 outs() << " Inconsistent size\n"; 8378 else 8379 outs() << "\n"; 8380 outs() << " segname " << SegName << "\n"; 8381 if (cmd == MachO::LC_SEGMENT_64) { 8382 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8383 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8384 } else { 8385 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8386 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8387 } 8388 outs() << " fileoff " << fileoff; 8389 if (fileoff > object_size) 8390 outs() << " (past end of file)\n"; 8391 else 8392 outs() << "\n"; 8393 outs() << " filesize " << filesize; 8394 if (fileoff + filesize > object_size) 8395 outs() << " (past end of file)\n"; 8396 else 8397 outs() << "\n"; 8398 if (verbose) { 8399 if ((maxprot & 8400 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8401 MachO::VM_PROT_EXECUTE)) != 0) 8402 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8403 else { 8404 outs() << " maxprot "; 8405 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8406 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8407 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8408 } 8409 if ((initprot & 8410 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8411 MachO::VM_PROT_EXECUTE)) != 0) 8412 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8413 else { 8414 outs() << " initprot "; 8415 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8416 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8417 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8418 } 8419 } else { 8420 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8421 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8422 } 8423 outs() << " nsects " << nsects << "\n"; 8424 if (verbose) { 8425 outs() << " flags"; 8426 if (flags == 0) 8427 outs() << " (none)\n"; 8428 else { 8429 if (flags & MachO::SG_HIGHVM) { 8430 outs() << " HIGHVM"; 8431 flags &= ~MachO::SG_HIGHVM; 8432 } 8433 if (flags & MachO::SG_FVMLIB) { 8434 outs() << " FVMLIB"; 8435 flags &= ~MachO::SG_FVMLIB; 8436 } 8437 if (flags & MachO::SG_NORELOC) { 8438 outs() << " NORELOC"; 8439 flags &= ~MachO::SG_NORELOC; 8440 } 8441 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8442 outs() << " PROTECTED_VERSION_1"; 8443 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8444 } 8445 if (flags) 8446 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8447 else 8448 outs() << "\n"; 8449 } 8450 } else { 8451 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8452 } 8453 } 8454 8455 static void PrintSection(const char *sectname, const char *segname, 8456 uint64_t addr, uint64_t size, uint32_t offset, 8457 uint32_t align, uint32_t reloff, uint32_t nreloc, 8458 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8459 uint32_t cmd, const char *sg_segname, 8460 uint32_t filetype, uint32_t object_size, 8461 bool verbose) { 8462 outs() << "Section\n"; 8463 outs() << " sectname " << format("%.16s\n", sectname); 8464 outs() << " segname " << format("%.16s", segname); 8465 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8466 outs() << " (does not match segment)\n"; 8467 else 8468 outs() << "\n"; 8469 if (cmd == MachO::LC_SEGMENT_64) { 8470 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8471 outs() << " size " << format("0x%016" PRIx64, size); 8472 } else { 8473 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8474 outs() << " size " << format("0x%08" PRIx64, size); 8475 } 8476 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8477 outs() << " (past end of file)\n"; 8478 else 8479 outs() << "\n"; 8480 outs() << " offset " << offset; 8481 if (offset > object_size) 8482 outs() << " (past end of file)\n"; 8483 else 8484 outs() << "\n"; 8485 uint32_t align_shifted = 1 << align; 8486 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8487 outs() << " reloff " << reloff; 8488 if (reloff > object_size) 8489 outs() << " (past end of file)\n"; 8490 else 8491 outs() << "\n"; 8492 outs() << " nreloc " << nreloc; 8493 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8494 outs() << " (past end of file)\n"; 8495 else 8496 outs() << "\n"; 8497 uint32_t section_type = flags & MachO::SECTION_TYPE; 8498 if (verbose) { 8499 outs() << " type"; 8500 if (section_type == MachO::S_REGULAR) 8501 outs() << " S_REGULAR\n"; 8502 else if (section_type == MachO::S_ZEROFILL) 8503 outs() << " S_ZEROFILL\n"; 8504 else if (section_type == MachO::S_CSTRING_LITERALS) 8505 outs() << " S_CSTRING_LITERALS\n"; 8506 else if (section_type == MachO::S_4BYTE_LITERALS) 8507 outs() << " S_4BYTE_LITERALS\n"; 8508 else if (section_type == MachO::S_8BYTE_LITERALS) 8509 outs() << " S_8BYTE_LITERALS\n"; 8510 else if (section_type == MachO::S_16BYTE_LITERALS) 8511 outs() << " S_16BYTE_LITERALS\n"; 8512 else if (section_type == MachO::S_LITERAL_POINTERS) 8513 outs() << " S_LITERAL_POINTERS\n"; 8514 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8515 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8516 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8517 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8518 else if (section_type == MachO::S_SYMBOL_STUBS) 8519 outs() << " S_SYMBOL_STUBS\n"; 8520 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8521 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8522 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8523 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8524 else if (section_type == MachO::S_COALESCED) 8525 outs() << " S_COALESCED\n"; 8526 else if (section_type == MachO::S_INTERPOSING) 8527 outs() << " S_INTERPOSING\n"; 8528 else if (section_type == MachO::S_DTRACE_DOF) 8529 outs() << " S_DTRACE_DOF\n"; 8530 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8531 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8532 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8533 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8534 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8535 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8536 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8537 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8538 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8539 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8540 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8541 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8542 else 8543 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8544 outs() << "attributes"; 8545 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8546 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8547 outs() << " PURE_INSTRUCTIONS"; 8548 if (section_attributes & MachO::S_ATTR_NO_TOC) 8549 outs() << " NO_TOC"; 8550 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8551 outs() << " STRIP_STATIC_SYMS"; 8552 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8553 outs() << " NO_DEAD_STRIP"; 8554 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8555 outs() << " LIVE_SUPPORT"; 8556 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8557 outs() << " SELF_MODIFYING_CODE"; 8558 if (section_attributes & MachO::S_ATTR_DEBUG) 8559 outs() << " DEBUG"; 8560 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8561 outs() << " SOME_INSTRUCTIONS"; 8562 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8563 outs() << " EXT_RELOC"; 8564 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8565 outs() << " LOC_RELOC"; 8566 if (section_attributes == 0) 8567 outs() << " (none)"; 8568 outs() << "\n"; 8569 } else 8570 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8571 outs() << " reserved1 " << reserved1; 8572 if (section_type == MachO::S_SYMBOL_STUBS || 8573 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8574 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8575 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8576 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8577 outs() << " (index into indirect symbol table)\n"; 8578 else 8579 outs() << "\n"; 8580 outs() << " reserved2 " << reserved2; 8581 if (section_type == MachO::S_SYMBOL_STUBS) 8582 outs() << " (size of stubs)\n"; 8583 else 8584 outs() << "\n"; 8585 } 8586 8587 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8588 uint32_t object_size) { 8589 outs() << " cmd LC_SYMTAB\n"; 8590 outs() << " cmdsize " << st.cmdsize; 8591 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8592 outs() << " Incorrect size\n"; 8593 else 8594 outs() << "\n"; 8595 outs() << " symoff " << st.symoff; 8596 if (st.symoff > object_size) 8597 outs() << " (past end of file)\n"; 8598 else 8599 outs() << "\n"; 8600 outs() << " nsyms " << st.nsyms; 8601 uint64_t big_size; 8602 if (Is64Bit) { 8603 big_size = st.nsyms; 8604 big_size *= sizeof(struct MachO::nlist_64); 8605 big_size += st.symoff; 8606 if (big_size > object_size) 8607 outs() << " (past end of file)\n"; 8608 else 8609 outs() << "\n"; 8610 } else { 8611 big_size = st.nsyms; 8612 big_size *= sizeof(struct MachO::nlist); 8613 big_size += st.symoff; 8614 if (big_size > object_size) 8615 outs() << " (past end of file)\n"; 8616 else 8617 outs() << "\n"; 8618 } 8619 outs() << " stroff " << st.stroff; 8620 if (st.stroff > object_size) 8621 outs() << " (past end of file)\n"; 8622 else 8623 outs() << "\n"; 8624 outs() << " strsize " << st.strsize; 8625 big_size = st.stroff; 8626 big_size += st.strsize; 8627 if (big_size > object_size) 8628 outs() << " (past end of file)\n"; 8629 else 8630 outs() << "\n"; 8631 } 8632 8633 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8634 uint32_t nsyms, uint32_t object_size, 8635 bool Is64Bit) { 8636 outs() << " cmd LC_DYSYMTAB\n"; 8637 outs() << " cmdsize " << dyst.cmdsize; 8638 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8639 outs() << " Incorrect size\n"; 8640 else 8641 outs() << "\n"; 8642 outs() << " ilocalsym " << dyst.ilocalsym; 8643 if (dyst.ilocalsym > nsyms) 8644 outs() << " (greater than the number of symbols)\n"; 8645 else 8646 outs() << "\n"; 8647 outs() << " nlocalsym " << dyst.nlocalsym; 8648 uint64_t big_size; 8649 big_size = dyst.ilocalsym; 8650 big_size += dyst.nlocalsym; 8651 if (big_size > nsyms) 8652 outs() << " (past the end of the symbol table)\n"; 8653 else 8654 outs() << "\n"; 8655 outs() << " iextdefsym " << dyst.iextdefsym; 8656 if (dyst.iextdefsym > nsyms) 8657 outs() << " (greater than the number of symbols)\n"; 8658 else 8659 outs() << "\n"; 8660 outs() << " nextdefsym " << dyst.nextdefsym; 8661 big_size = dyst.iextdefsym; 8662 big_size += dyst.nextdefsym; 8663 if (big_size > nsyms) 8664 outs() << " (past the end of the symbol table)\n"; 8665 else 8666 outs() << "\n"; 8667 outs() << " iundefsym " << dyst.iundefsym; 8668 if (dyst.iundefsym > nsyms) 8669 outs() << " (greater than the number of symbols)\n"; 8670 else 8671 outs() << "\n"; 8672 outs() << " nundefsym " << dyst.nundefsym; 8673 big_size = dyst.iundefsym; 8674 big_size += dyst.nundefsym; 8675 if (big_size > nsyms) 8676 outs() << " (past the end of the symbol table)\n"; 8677 else 8678 outs() << "\n"; 8679 outs() << " tocoff " << dyst.tocoff; 8680 if (dyst.tocoff > object_size) 8681 outs() << " (past end of file)\n"; 8682 else 8683 outs() << "\n"; 8684 outs() << " ntoc " << dyst.ntoc; 8685 big_size = dyst.ntoc; 8686 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8687 big_size += dyst.tocoff; 8688 if (big_size > object_size) 8689 outs() << " (past end of file)\n"; 8690 else 8691 outs() << "\n"; 8692 outs() << " modtaboff " << dyst.modtaboff; 8693 if (dyst.modtaboff > object_size) 8694 outs() << " (past end of file)\n"; 8695 else 8696 outs() << "\n"; 8697 outs() << " nmodtab " << dyst.nmodtab; 8698 uint64_t modtabend; 8699 if (Is64Bit) { 8700 modtabend = dyst.nmodtab; 8701 modtabend *= sizeof(struct MachO::dylib_module_64); 8702 modtabend += dyst.modtaboff; 8703 } else { 8704 modtabend = dyst.nmodtab; 8705 modtabend *= sizeof(struct MachO::dylib_module); 8706 modtabend += dyst.modtaboff; 8707 } 8708 if (modtabend > object_size) 8709 outs() << " (past end of file)\n"; 8710 else 8711 outs() << "\n"; 8712 outs() << " extrefsymoff " << dyst.extrefsymoff; 8713 if (dyst.extrefsymoff > object_size) 8714 outs() << " (past end of file)\n"; 8715 else 8716 outs() << "\n"; 8717 outs() << " nextrefsyms " << dyst.nextrefsyms; 8718 big_size = dyst.nextrefsyms; 8719 big_size *= sizeof(struct MachO::dylib_reference); 8720 big_size += dyst.extrefsymoff; 8721 if (big_size > object_size) 8722 outs() << " (past end of file)\n"; 8723 else 8724 outs() << "\n"; 8725 outs() << " indirectsymoff " << dyst.indirectsymoff; 8726 if (dyst.indirectsymoff > object_size) 8727 outs() << " (past end of file)\n"; 8728 else 8729 outs() << "\n"; 8730 outs() << " nindirectsyms " << dyst.nindirectsyms; 8731 big_size = dyst.nindirectsyms; 8732 big_size *= sizeof(uint32_t); 8733 big_size += dyst.indirectsymoff; 8734 if (big_size > object_size) 8735 outs() << " (past end of file)\n"; 8736 else 8737 outs() << "\n"; 8738 outs() << " extreloff " << dyst.extreloff; 8739 if (dyst.extreloff > object_size) 8740 outs() << " (past end of file)\n"; 8741 else 8742 outs() << "\n"; 8743 outs() << " nextrel " << dyst.nextrel; 8744 big_size = dyst.nextrel; 8745 big_size *= sizeof(struct MachO::relocation_info); 8746 big_size += dyst.extreloff; 8747 if (big_size > object_size) 8748 outs() << " (past end of file)\n"; 8749 else 8750 outs() << "\n"; 8751 outs() << " locreloff " << dyst.locreloff; 8752 if (dyst.locreloff > object_size) 8753 outs() << " (past end of file)\n"; 8754 else 8755 outs() << "\n"; 8756 outs() << " nlocrel " << dyst.nlocrel; 8757 big_size = dyst.nlocrel; 8758 big_size *= sizeof(struct MachO::relocation_info); 8759 big_size += dyst.locreloff; 8760 if (big_size > object_size) 8761 outs() << " (past end of file)\n"; 8762 else 8763 outs() << "\n"; 8764 } 8765 8766 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8767 uint32_t object_size) { 8768 if (dc.cmd == MachO::LC_DYLD_INFO) 8769 outs() << " cmd LC_DYLD_INFO\n"; 8770 else 8771 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8772 outs() << " cmdsize " << dc.cmdsize; 8773 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8774 outs() << " Incorrect size\n"; 8775 else 8776 outs() << "\n"; 8777 outs() << " rebase_off " << dc.rebase_off; 8778 if (dc.rebase_off > object_size) 8779 outs() << " (past end of file)\n"; 8780 else 8781 outs() << "\n"; 8782 outs() << " rebase_size " << dc.rebase_size; 8783 uint64_t big_size; 8784 big_size = dc.rebase_off; 8785 big_size += dc.rebase_size; 8786 if (big_size > object_size) 8787 outs() << " (past end of file)\n"; 8788 else 8789 outs() << "\n"; 8790 outs() << " bind_off " << dc.bind_off; 8791 if (dc.bind_off > object_size) 8792 outs() << " (past end of file)\n"; 8793 else 8794 outs() << "\n"; 8795 outs() << " bind_size " << dc.bind_size; 8796 big_size = dc.bind_off; 8797 big_size += dc.bind_size; 8798 if (big_size > object_size) 8799 outs() << " (past end of file)\n"; 8800 else 8801 outs() << "\n"; 8802 outs() << " weak_bind_off " << dc.weak_bind_off; 8803 if (dc.weak_bind_off > object_size) 8804 outs() << " (past end of file)\n"; 8805 else 8806 outs() << "\n"; 8807 outs() << " weak_bind_size " << dc.weak_bind_size; 8808 big_size = dc.weak_bind_off; 8809 big_size += dc.weak_bind_size; 8810 if (big_size > object_size) 8811 outs() << " (past end of file)\n"; 8812 else 8813 outs() << "\n"; 8814 outs() << " lazy_bind_off " << dc.lazy_bind_off; 8815 if (dc.lazy_bind_off > object_size) 8816 outs() << " (past end of file)\n"; 8817 else 8818 outs() << "\n"; 8819 outs() << " lazy_bind_size " << dc.lazy_bind_size; 8820 big_size = dc.lazy_bind_off; 8821 big_size += dc.lazy_bind_size; 8822 if (big_size > object_size) 8823 outs() << " (past end of file)\n"; 8824 else 8825 outs() << "\n"; 8826 outs() << " export_off " << dc.export_off; 8827 if (dc.export_off > object_size) 8828 outs() << " (past end of file)\n"; 8829 else 8830 outs() << "\n"; 8831 outs() << " export_size " << dc.export_size; 8832 big_size = dc.export_off; 8833 big_size += dc.export_size; 8834 if (big_size > object_size) 8835 outs() << " (past end of file)\n"; 8836 else 8837 outs() << "\n"; 8838 } 8839 8840 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 8841 const char *Ptr) { 8842 if (dyld.cmd == MachO::LC_ID_DYLINKER) 8843 outs() << " cmd LC_ID_DYLINKER\n"; 8844 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 8845 outs() << " cmd LC_LOAD_DYLINKER\n"; 8846 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 8847 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 8848 else 8849 outs() << " cmd ?(" << dyld.cmd << ")\n"; 8850 outs() << " cmdsize " << dyld.cmdsize; 8851 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 8852 outs() << " Incorrect size\n"; 8853 else 8854 outs() << "\n"; 8855 if (dyld.name >= dyld.cmdsize) 8856 outs() << " name ?(bad offset " << dyld.name << ")\n"; 8857 else { 8858 const char *P = (const char *)(Ptr) + dyld.name; 8859 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 8860 } 8861 } 8862 8863 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 8864 outs() << " cmd LC_UUID\n"; 8865 outs() << " cmdsize " << uuid.cmdsize; 8866 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 8867 outs() << " Incorrect size\n"; 8868 else 8869 outs() << "\n"; 8870 outs() << " uuid "; 8871 for (int i = 0; i < 16; ++i) { 8872 outs() << format("%02" PRIX32, uuid.uuid[i]); 8873 if (i == 3 || i == 5 || i == 7 || i == 9) 8874 outs() << "-"; 8875 } 8876 outs() << "\n"; 8877 } 8878 8879 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 8880 outs() << " cmd LC_RPATH\n"; 8881 outs() << " cmdsize " << rpath.cmdsize; 8882 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 8883 outs() << " Incorrect size\n"; 8884 else 8885 outs() << "\n"; 8886 if (rpath.path >= rpath.cmdsize) 8887 outs() << " path ?(bad offset " << rpath.path << ")\n"; 8888 else { 8889 const char *P = (const char *)(Ptr) + rpath.path; 8890 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 8891 } 8892 } 8893 8894 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 8895 StringRef LoadCmdName; 8896 switch (vd.cmd) { 8897 case MachO::LC_VERSION_MIN_MACOSX: 8898 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 8899 break; 8900 case MachO::LC_VERSION_MIN_IPHONEOS: 8901 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 8902 break; 8903 case MachO::LC_VERSION_MIN_TVOS: 8904 LoadCmdName = "LC_VERSION_MIN_TVOS"; 8905 break; 8906 case MachO::LC_VERSION_MIN_WATCHOS: 8907 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 8908 break; 8909 default: 8910 llvm_unreachable("Unknown version min load command"); 8911 } 8912 8913 outs() << " cmd " << LoadCmdName << '\n'; 8914 outs() << " cmdsize " << vd.cmdsize; 8915 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 8916 outs() << " Incorrect size\n"; 8917 else 8918 outs() << "\n"; 8919 outs() << " version " 8920 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 8921 << MachOObjectFile::getVersionMinMinor(vd, false); 8922 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 8923 if (Update != 0) 8924 outs() << "." << Update; 8925 outs() << "\n"; 8926 if (vd.sdk == 0) 8927 outs() << " sdk n/a"; 8928 else { 8929 outs() << " sdk " 8930 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 8931 << MachOObjectFile::getVersionMinMinor(vd, true); 8932 } 8933 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 8934 if (Update != 0) 8935 outs() << "." << Update; 8936 outs() << "\n"; 8937 } 8938 8939 static void PrintNoteLoadCommand(MachO::note_command Nt) { 8940 outs() << " cmd LC_NOTE\n"; 8941 outs() << " cmdsize " << Nt.cmdsize; 8942 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 8943 outs() << " Incorrect size\n"; 8944 else 8945 outs() << "\n"; 8946 const char *d = Nt.data_owner; 8947 outs() << "data_owner " << format("%.16s\n", d); 8948 outs() << " offset " << Nt.offset << "\n"; 8949 outs() << " size " << Nt.size << "\n"; 8950 } 8951 8952 static void PrintBuildToolVersion(MachO::build_tool_version bv) { 8953 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; 8954 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 8955 << "\n"; 8956 } 8957 8958 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 8959 MachO::build_version_command bd) { 8960 outs() << " cmd LC_BUILD_VERSION\n"; 8961 outs() << " cmdsize " << bd.cmdsize; 8962 if (bd.cmdsize != 8963 sizeof(struct MachO::build_version_command) + 8964 bd.ntools * sizeof(struct MachO::build_tool_version)) 8965 outs() << " Incorrect size\n"; 8966 else 8967 outs() << "\n"; 8968 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) 8969 << "\n"; 8970 if (bd.sdk) 8971 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 8972 << "\n"; 8973 else 8974 outs() << " sdk n/a\n"; 8975 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 8976 << "\n"; 8977 outs() << " ntools " << bd.ntools << "\n"; 8978 for (unsigned i = 0; i < bd.ntools; ++i) { 8979 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 8980 PrintBuildToolVersion(bv); 8981 } 8982 } 8983 8984 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 8985 outs() << " cmd LC_SOURCE_VERSION\n"; 8986 outs() << " cmdsize " << sd.cmdsize; 8987 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 8988 outs() << " Incorrect size\n"; 8989 else 8990 outs() << "\n"; 8991 uint64_t a = (sd.version >> 40) & 0xffffff; 8992 uint64_t b = (sd.version >> 30) & 0x3ff; 8993 uint64_t c = (sd.version >> 20) & 0x3ff; 8994 uint64_t d = (sd.version >> 10) & 0x3ff; 8995 uint64_t e = sd.version & 0x3ff; 8996 outs() << " version " << a << "." << b; 8997 if (e != 0) 8998 outs() << "." << c << "." << d << "." << e; 8999 else if (d != 0) 9000 outs() << "." << c << "." << d; 9001 else if (c != 0) 9002 outs() << "." << c; 9003 outs() << "\n"; 9004 } 9005 9006 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 9007 outs() << " cmd LC_MAIN\n"; 9008 outs() << " cmdsize " << ep.cmdsize; 9009 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 9010 outs() << " Incorrect size\n"; 9011 else 9012 outs() << "\n"; 9013 outs() << " entryoff " << ep.entryoff << "\n"; 9014 outs() << " stacksize " << ep.stacksize << "\n"; 9015 } 9016 9017 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 9018 uint32_t object_size) { 9019 outs() << " cmd LC_ENCRYPTION_INFO\n"; 9020 outs() << " cmdsize " << ec.cmdsize; 9021 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 9022 outs() << " Incorrect size\n"; 9023 else 9024 outs() << "\n"; 9025 outs() << " cryptoff " << ec.cryptoff; 9026 if (ec.cryptoff > object_size) 9027 outs() << " (past end of file)\n"; 9028 else 9029 outs() << "\n"; 9030 outs() << " cryptsize " << ec.cryptsize; 9031 if (ec.cryptsize > object_size) 9032 outs() << " (past end of file)\n"; 9033 else 9034 outs() << "\n"; 9035 outs() << " cryptid " << ec.cryptid << "\n"; 9036 } 9037 9038 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 9039 uint32_t object_size) { 9040 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 9041 outs() << " cmdsize " << ec.cmdsize; 9042 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 9043 outs() << " Incorrect size\n"; 9044 else 9045 outs() << "\n"; 9046 outs() << " cryptoff " << ec.cryptoff; 9047 if (ec.cryptoff > object_size) 9048 outs() << " (past end of file)\n"; 9049 else 9050 outs() << "\n"; 9051 outs() << " cryptsize " << ec.cryptsize; 9052 if (ec.cryptsize > object_size) 9053 outs() << " (past end of file)\n"; 9054 else 9055 outs() << "\n"; 9056 outs() << " cryptid " << ec.cryptid << "\n"; 9057 outs() << " pad " << ec.pad << "\n"; 9058 } 9059 9060 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 9061 const char *Ptr) { 9062 outs() << " cmd LC_LINKER_OPTION\n"; 9063 outs() << " cmdsize " << lo.cmdsize; 9064 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 9065 outs() << " Incorrect size\n"; 9066 else 9067 outs() << "\n"; 9068 outs() << " count " << lo.count << "\n"; 9069 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 9070 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 9071 uint32_t i = 0; 9072 while (left > 0) { 9073 while (*string == '\0' && left > 0) { 9074 string++; 9075 left--; 9076 } 9077 if (left > 0) { 9078 i++; 9079 outs() << " string #" << i << " " << format("%.*s\n", left, string); 9080 uint32_t NullPos = StringRef(string, left).find('\0'); 9081 uint32_t len = std::min(NullPos, left) + 1; 9082 string += len; 9083 left -= len; 9084 } 9085 } 9086 if (lo.count != i) 9087 outs() << " count " << lo.count << " does not match number of strings " 9088 << i << "\n"; 9089 } 9090 9091 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 9092 const char *Ptr) { 9093 outs() << " cmd LC_SUB_FRAMEWORK\n"; 9094 outs() << " cmdsize " << sub.cmdsize; 9095 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 9096 outs() << " Incorrect size\n"; 9097 else 9098 outs() << "\n"; 9099 if (sub.umbrella < sub.cmdsize) { 9100 const char *P = Ptr + sub.umbrella; 9101 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 9102 } else { 9103 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 9104 } 9105 } 9106 9107 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 9108 const char *Ptr) { 9109 outs() << " cmd LC_SUB_UMBRELLA\n"; 9110 outs() << " cmdsize " << sub.cmdsize; 9111 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 9112 outs() << " Incorrect size\n"; 9113 else 9114 outs() << "\n"; 9115 if (sub.sub_umbrella < sub.cmdsize) { 9116 const char *P = Ptr + sub.sub_umbrella; 9117 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 9118 } else { 9119 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 9120 } 9121 } 9122 9123 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 9124 const char *Ptr) { 9125 outs() << " cmd LC_SUB_LIBRARY\n"; 9126 outs() << " cmdsize " << sub.cmdsize; 9127 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 9128 outs() << " Incorrect size\n"; 9129 else 9130 outs() << "\n"; 9131 if (sub.sub_library < sub.cmdsize) { 9132 const char *P = Ptr + sub.sub_library; 9133 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 9134 } else { 9135 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 9136 } 9137 } 9138 9139 static void PrintSubClientCommand(MachO::sub_client_command sub, 9140 const char *Ptr) { 9141 outs() << " cmd LC_SUB_CLIENT\n"; 9142 outs() << " cmdsize " << sub.cmdsize; 9143 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 9144 outs() << " Incorrect size\n"; 9145 else 9146 outs() << "\n"; 9147 if (sub.client < sub.cmdsize) { 9148 const char *P = Ptr + sub.client; 9149 outs() << " client " << P << " (offset " << sub.client << ")\n"; 9150 } else { 9151 outs() << " client ?(bad offset " << sub.client << ")\n"; 9152 } 9153 } 9154 9155 static void PrintRoutinesCommand(MachO::routines_command r) { 9156 outs() << " cmd LC_ROUTINES\n"; 9157 outs() << " cmdsize " << r.cmdsize; 9158 if (r.cmdsize != sizeof(struct MachO::routines_command)) 9159 outs() << " Incorrect size\n"; 9160 else 9161 outs() << "\n"; 9162 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 9163 outs() << " init_module " << r.init_module << "\n"; 9164 outs() << " reserved1 " << r.reserved1 << "\n"; 9165 outs() << " reserved2 " << r.reserved2 << "\n"; 9166 outs() << " reserved3 " << r.reserved3 << "\n"; 9167 outs() << " reserved4 " << r.reserved4 << "\n"; 9168 outs() << " reserved5 " << r.reserved5 << "\n"; 9169 outs() << " reserved6 " << r.reserved6 << "\n"; 9170 } 9171 9172 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 9173 outs() << " cmd LC_ROUTINES_64\n"; 9174 outs() << " cmdsize " << r.cmdsize; 9175 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 9176 outs() << " Incorrect size\n"; 9177 else 9178 outs() << "\n"; 9179 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 9180 outs() << " init_module " << r.init_module << "\n"; 9181 outs() << " reserved1 " << r.reserved1 << "\n"; 9182 outs() << " reserved2 " << r.reserved2 << "\n"; 9183 outs() << " reserved3 " << r.reserved3 << "\n"; 9184 outs() << " reserved4 " << r.reserved4 << "\n"; 9185 outs() << " reserved5 " << r.reserved5 << "\n"; 9186 outs() << " reserved6 " << r.reserved6 << "\n"; 9187 } 9188 9189 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 9190 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 9191 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 9192 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 9193 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 9194 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 9195 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 9196 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 9197 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 9198 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 9199 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 9200 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 9201 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 9202 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 9203 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 9204 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 9205 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 9206 } 9207 9208 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 9209 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 9210 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 9211 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 9212 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 9213 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 9214 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 9215 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 9216 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 9217 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 9218 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 9219 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 9220 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 9221 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 9222 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 9223 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 9224 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 9225 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 9226 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 9227 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 9228 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 9229 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 9230 } 9231 9232 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 9233 uint32_t f; 9234 outs() << "\t mmst_reg "; 9235 for (f = 0; f < 10; f++) 9236 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 9237 outs() << "\n"; 9238 outs() << "\t mmst_rsrv "; 9239 for (f = 0; f < 6; f++) 9240 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 9241 outs() << "\n"; 9242 } 9243 9244 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 9245 uint32_t f; 9246 outs() << "\t xmm_reg "; 9247 for (f = 0; f < 16; f++) 9248 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 9249 outs() << "\n"; 9250 } 9251 9252 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 9253 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 9254 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 9255 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 9256 outs() << " denorm " << fpu.fpu_fcw.denorm; 9257 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 9258 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 9259 outs() << " undfl " << fpu.fpu_fcw.undfl; 9260 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 9261 outs() << "\t\t pc "; 9262 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 9263 outs() << "FP_PREC_24B "; 9264 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 9265 outs() << "FP_PREC_53B "; 9266 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 9267 outs() << "FP_PREC_64B "; 9268 else 9269 outs() << fpu.fpu_fcw.pc << " "; 9270 outs() << "rc "; 9271 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 9272 outs() << "FP_RND_NEAR "; 9273 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 9274 outs() << "FP_RND_DOWN "; 9275 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 9276 outs() << "FP_RND_UP "; 9277 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 9278 outs() << "FP_CHOP "; 9279 outs() << "\n"; 9280 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 9281 outs() << " denorm " << fpu.fpu_fsw.denorm; 9282 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 9283 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 9284 outs() << " undfl " << fpu.fpu_fsw.undfl; 9285 outs() << " precis " << fpu.fpu_fsw.precis; 9286 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 9287 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9288 outs() << " c0 " << fpu.fpu_fsw.c0; 9289 outs() << " c1 " << fpu.fpu_fsw.c1; 9290 outs() << " c2 " << fpu.fpu_fsw.c2; 9291 outs() << " tos " << fpu.fpu_fsw.tos; 9292 outs() << " c3 " << fpu.fpu_fsw.c3; 9293 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9294 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9295 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9296 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9297 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9298 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9299 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9300 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9301 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9302 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9303 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9304 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9305 outs() << "\n"; 9306 outs() << "\t fpu_stmm0:\n"; 9307 Print_mmst_reg(fpu.fpu_stmm0); 9308 outs() << "\t fpu_stmm1:\n"; 9309 Print_mmst_reg(fpu.fpu_stmm1); 9310 outs() << "\t fpu_stmm2:\n"; 9311 Print_mmst_reg(fpu.fpu_stmm2); 9312 outs() << "\t fpu_stmm3:\n"; 9313 Print_mmst_reg(fpu.fpu_stmm3); 9314 outs() << "\t fpu_stmm4:\n"; 9315 Print_mmst_reg(fpu.fpu_stmm4); 9316 outs() << "\t fpu_stmm5:\n"; 9317 Print_mmst_reg(fpu.fpu_stmm5); 9318 outs() << "\t fpu_stmm6:\n"; 9319 Print_mmst_reg(fpu.fpu_stmm6); 9320 outs() << "\t fpu_stmm7:\n"; 9321 Print_mmst_reg(fpu.fpu_stmm7); 9322 outs() << "\t fpu_xmm0:\n"; 9323 Print_xmm_reg(fpu.fpu_xmm0); 9324 outs() << "\t fpu_xmm1:\n"; 9325 Print_xmm_reg(fpu.fpu_xmm1); 9326 outs() << "\t fpu_xmm2:\n"; 9327 Print_xmm_reg(fpu.fpu_xmm2); 9328 outs() << "\t fpu_xmm3:\n"; 9329 Print_xmm_reg(fpu.fpu_xmm3); 9330 outs() << "\t fpu_xmm4:\n"; 9331 Print_xmm_reg(fpu.fpu_xmm4); 9332 outs() << "\t fpu_xmm5:\n"; 9333 Print_xmm_reg(fpu.fpu_xmm5); 9334 outs() << "\t fpu_xmm6:\n"; 9335 Print_xmm_reg(fpu.fpu_xmm6); 9336 outs() << "\t fpu_xmm7:\n"; 9337 Print_xmm_reg(fpu.fpu_xmm7); 9338 outs() << "\t fpu_xmm8:\n"; 9339 Print_xmm_reg(fpu.fpu_xmm8); 9340 outs() << "\t fpu_xmm9:\n"; 9341 Print_xmm_reg(fpu.fpu_xmm9); 9342 outs() << "\t fpu_xmm10:\n"; 9343 Print_xmm_reg(fpu.fpu_xmm10); 9344 outs() << "\t fpu_xmm11:\n"; 9345 Print_xmm_reg(fpu.fpu_xmm11); 9346 outs() << "\t fpu_xmm12:\n"; 9347 Print_xmm_reg(fpu.fpu_xmm12); 9348 outs() << "\t fpu_xmm13:\n"; 9349 Print_xmm_reg(fpu.fpu_xmm13); 9350 outs() << "\t fpu_xmm14:\n"; 9351 Print_xmm_reg(fpu.fpu_xmm14); 9352 outs() << "\t fpu_xmm15:\n"; 9353 Print_xmm_reg(fpu.fpu_xmm15); 9354 outs() << "\t fpu_rsrv4:\n"; 9355 for (uint32_t f = 0; f < 6; f++) { 9356 outs() << "\t "; 9357 for (uint32_t g = 0; g < 16; g++) 9358 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9359 outs() << "\n"; 9360 } 9361 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9362 outs() << "\n"; 9363 } 9364 9365 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9366 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9367 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9368 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9369 } 9370 9371 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9372 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9373 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9374 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9375 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9376 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9377 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9378 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9379 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9380 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9381 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9382 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9383 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9384 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9385 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9386 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9387 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9388 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9389 } 9390 9391 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9392 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9393 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9394 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9395 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9396 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9397 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9398 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9399 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9400 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9401 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9402 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9403 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9404 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9405 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9406 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9407 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9408 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9409 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9410 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9411 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9412 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9413 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9414 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9415 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9416 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9417 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9418 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9419 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9420 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9421 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9422 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9423 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9424 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9425 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9426 } 9427 9428 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9429 bool isLittleEndian, uint32_t cputype) { 9430 if (t.cmd == MachO::LC_THREAD) 9431 outs() << " cmd LC_THREAD\n"; 9432 else if (t.cmd == MachO::LC_UNIXTHREAD) 9433 outs() << " cmd LC_UNIXTHREAD\n"; 9434 else 9435 outs() << " cmd " << t.cmd << " (unknown)\n"; 9436 outs() << " cmdsize " << t.cmdsize; 9437 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9438 outs() << " Incorrect size\n"; 9439 else 9440 outs() << "\n"; 9441 9442 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9443 const char *end = Ptr + t.cmdsize; 9444 uint32_t flavor, count, left; 9445 if (cputype == MachO::CPU_TYPE_I386) { 9446 while (begin < end) { 9447 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9448 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9449 begin += sizeof(uint32_t); 9450 } else { 9451 flavor = 0; 9452 begin = end; 9453 } 9454 if (isLittleEndian != sys::IsLittleEndianHost) 9455 sys::swapByteOrder(flavor); 9456 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9457 memcpy((char *)&count, begin, sizeof(uint32_t)); 9458 begin += sizeof(uint32_t); 9459 } else { 9460 count = 0; 9461 begin = end; 9462 } 9463 if (isLittleEndian != sys::IsLittleEndianHost) 9464 sys::swapByteOrder(count); 9465 if (flavor == MachO::x86_THREAD_STATE32) { 9466 outs() << " flavor i386_THREAD_STATE\n"; 9467 if (count == MachO::x86_THREAD_STATE32_COUNT) 9468 outs() << " count i386_THREAD_STATE_COUNT\n"; 9469 else 9470 outs() << " count " << count 9471 << " (not x86_THREAD_STATE32_COUNT)\n"; 9472 MachO::x86_thread_state32_t cpu32; 9473 left = end - begin; 9474 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9475 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9476 begin += sizeof(MachO::x86_thread_state32_t); 9477 } else { 9478 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9479 memcpy(&cpu32, begin, left); 9480 begin += left; 9481 } 9482 if (isLittleEndian != sys::IsLittleEndianHost) 9483 swapStruct(cpu32); 9484 Print_x86_thread_state32_t(cpu32); 9485 } else if (flavor == MachO::x86_THREAD_STATE) { 9486 outs() << " flavor x86_THREAD_STATE\n"; 9487 if (count == MachO::x86_THREAD_STATE_COUNT) 9488 outs() << " count x86_THREAD_STATE_COUNT\n"; 9489 else 9490 outs() << " count " << count 9491 << " (not x86_THREAD_STATE_COUNT)\n"; 9492 struct MachO::x86_thread_state_t ts; 9493 left = end - begin; 9494 if (left >= sizeof(MachO::x86_thread_state_t)) { 9495 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9496 begin += sizeof(MachO::x86_thread_state_t); 9497 } else { 9498 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9499 memcpy(&ts, begin, left); 9500 begin += left; 9501 } 9502 if (isLittleEndian != sys::IsLittleEndianHost) 9503 swapStruct(ts); 9504 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9505 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9506 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9507 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9508 else 9509 outs() << "tsh.count " << ts.tsh.count 9510 << " (not x86_THREAD_STATE32_COUNT\n"; 9511 Print_x86_thread_state32_t(ts.uts.ts32); 9512 } else { 9513 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9514 << ts.tsh.count << "\n"; 9515 } 9516 } else { 9517 outs() << " flavor " << flavor << " (unknown)\n"; 9518 outs() << " count " << count << "\n"; 9519 outs() << " state (unknown)\n"; 9520 begin += count * sizeof(uint32_t); 9521 } 9522 } 9523 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9524 while (begin < end) { 9525 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9526 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9527 begin += sizeof(uint32_t); 9528 } else { 9529 flavor = 0; 9530 begin = end; 9531 } 9532 if (isLittleEndian != sys::IsLittleEndianHost) 9533 sys::swapByteOrder(flavor); 9534 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9535 memcpy((char *)&count, begin, sizeof(uint32_t)); 9536 begin += sizeof(uint32_t); 9537 } else { 9538 count = 0; 9539 begin = end; 9540 } 9541 if (isLittleEndian != sys::IsLittleEndianHost) 9542 sys::swapByteOrder(count); 9543 if (flavor == MachO::x86_THREAD_STATE64) { 9544 outs() << " flavor x86_THREAD_STATE64\n"; 9545 if (count == MachO::x86_THREAD_STATE64_COUNT) 9546 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9547 else 9548 outs() << " count " << count 9549 << " (not x86_THREAD_STATE64_COUNT)\n"; 9550 MachO::x86_thread_state64_t cpu64; 9551 left = end - begin; 9552 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9553 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9554 begin += sizeof(MachO::x86_thread_state64_t); 9555 } else { 9556 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9557 memcpy(&cpu64, begin, left); 9558 begin += left; 9559 } 9560 if (isLittleEndian != sys::IsLittleEndianHost) 9561 swapStruct(cpu64); 9562 Print_x86_thread_state64_t(cpu64); 9563 } else if (flavor == MachO::x86_THREAD_STATE) { 9564 outs() << " flavor x86_THREAD_STATE\n"; 9565 if (count == MachO::x86_THREAD_STATE_COUNT) 9566 outs() << " count x86_THREAD_STATE_COUNT\n"; 9567 else 9568 outs() << " count " << count 9569 << " (not x86_THREAD_STATE_COUNT)\n"; 9570 struct MachO::x86_thread_state_t ts; 9571 left = end - begin; 9572 if (left >= sizeof(MachO::x86_thread_state_t)) { 9573 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9574 begin += sizeof(MachO::x86_thread_state_t); 9575 } else { 9576 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9577 memcpy(&ts, begin, left); 9578 begin += left; 9579 } 9580 if (isLittleEndian != sys::IsLittleEndianHost) 9581 swapStruct(ts); 9582 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9583 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9584 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9585 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9586 else 9587 outs() << "tsh.count " << ts.tsh.count 9588 << " (not x86_THREAD_STATE64_COUNT\n"; 9589 Print_x86_thread_state64_t(ts.uts.ts64); 9590 } else { 9591 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9592 << ts.tsh.count << "\n"; 9593 } 9594 } else if (flavor == MachO::x86_FLOAT_STATE) { 9595 outs() << " flavor x86_FLOAT_STATE\n"; 9596 if (count == MachO::x86_FLOAT_STATE_COUNT) 9597 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9598 else 9599 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9600 struct MachO::x86_float_state_t fs; 9601 left = end - begin; 9602 if (left >= sizeof(MachO::x86_float_state_t)) { 9603 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9604 begin += sizeof(MachO::x86_float_state_t); 9605 } else { 9606 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9607 memcpy(&fs, begin, left); 9608 begin += left; 9609 } 9610 if (isLittleEndian != sys::IsLittleEndianHost) 9611 swapStruct(fs); 9612 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9613 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9614 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9615 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9616 else 9617 outs() << "fsh.count " << fs.fsh.count 9618 << " (not x86_FLOAT_STATE64_COUNT\n"; 9619 Print_x86_float_state_t(fs.ufs.fs64); 9620 } else { 9621 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9622 << fs.fsh.count << "\n"; 9623 } 9624 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9625 outs() << " flavor x86_EXCEPTION_STATE\n"; 9626 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9627 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9628 else 9629 outs() << " count " << count 9630 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9631 struct MachO::x86_exception_state_t es; 9632 left = end - begin; 9633 if (left >= sizeof(MachO::x86_exception_state_t)) { 9634 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9635 begin += sizeof(MachO::x86_exception_state_t); 9636 } else { 9637 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9638 memcpy(&es, begin, left); 9639 begin += left; 9640 } 9641 if (isLittleEndian != sys::IsLittleEndianHost) 9642 swapStruct(es); 9643 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9644 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9645 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9646 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9647 else 9648 outs() << "\t esh.count " << es.esh.count 9649 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9650 Print_x86_exception_state_t(es.ues.es64); 9651 } else { 9652 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9653 << es.esh.count << "\n"; 9654 } 9655 } else if (flavor == MachO::x86_EXCEPTION_STATE64) { 9656 outs() << " flavor x86_EXCEPTION_STATE64\n"; 9657 if (count == MachO::x86_EXCEPTION_STATE64_COUNT) 9658 outs() << " count x86_EXCEPTION_STATE64_COUNT\n"; 9659 else 9660 outs() << " count " << count 9661 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; 9662 struct MachO::x86_exception_state64_t es64; 9663 left = end - begin; 9664 if (left >= sizeof(MachO::x86_exception_state64_t)) { 9665 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); 9666 begin += sizeof(MachO::x86_exception_state64_t); 9667 } else { 9668 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); 9669 memcpy(&es64, begin, left); 9670 begin += left; 9671 } 9672 if (isLittleEndian != sys::IsLittleEndianHost) 9673 swapStruct(es64); 9674 Print_x86_exception_state_t(es64); 9675 } else { 9676 outs() << " flavor " << flavor << " (unknown)\n"; 9677 outs() << " count " << count << "\n"; 9678 outs() << " state (unknown)\n"; 9679 begin += count * sizeof(uint32_t); 9680 } 9681 } 9682 } else if (cputype == MachO::CPU_TYPE_ARM) { 9683 while (begin < end) { 9684 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9685 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9686 begin += sizeof(uint32_t); 9687 } else { 9688 flavor = 0; 9689 begin = end; 9690 } 9691 if (isLittleEndian != sys::IsLittleEndianHost) 9692 sys::swapByteOrder(flavor); 9693 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9694 memcpy((char *)&count, begin, sizeof(uint32_t)); 9695 begin += sizeof(uint32_t); 9696 } else { 9697 count = 0; 9698 begin = end; 9699 } 9700 if (isLittleEndian != sys::IsLittleEndianHost) 9701 sys::swapByteOrder(count); 9702 if (flavor == MachO::ARM_THREAD_STATE) { 9703 outs() << " flavor ARM_THREAD_STATE\n"; 9704 if (count == MachO::ARM_THREAD_STATE_COUNT) 9705 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9706 else 9707 outs() << " count " << count 9708 << " (not ARM_THREAD_STATE_COUNT)\n"; 9709 MachO::arm_thread_state32_t cpu32; 9710 left = end - begin; 9711 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9712 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9713 begin += sizeof(MachO::arm_thread_state32_t); 9714 } else { 9715 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9716 memcpy(&cpu32, begin, left); 9717 begin += left; 9718 } 9719 if (isLittleEndian != sys::IsLittleEndianHost) 9720 swapStruct(cpu32); 9721 Print_arm_thread_state32_t(cpu32); 9722 } else { 9723 outs() << " flavor " << flavor << " (unknown)\n"; 9724 outs() << " count " << count << "\n"; 9725 outs() << " state (unknown)\n"; 9726 begin += count * sizeof(uint32_t); 9727 } 9728 } 9729 } else if (cputype == MachO::CPU_TYPE_ARM64 || 9730 cputype == MachO::CPU_TYPE_ARM64_32) { 9731 while (begin < end) { 9732 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9733 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9734 begin += sizeof(uint32_t); 9735 } else { 9736 flavor = 0; 9737 begin = end; 9738 } 9739 if (isLittleEndian != sys::IsLittleEndianHost) 9740 sys::swapByteOrder(flavor); 9741 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9742 memcpy((char *)&count, begin, sizeof(uint32_t)); 9743 begin += sizeof(uint32_t); 9744 } else { 9745 count = 0; 9746 begin = end; 9747 } 9748 if (isLittleEndian != sys::IsLittleEndianHost) 9749 sys::swapByteOrder(count); 9750 if (flavor == MachO::ARM_THREAD_STATE64) { 9751 outs() << " flavor ARM_THREAD_STATE64\n"; 9752 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9753 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9754 else 9755 outs() << " count " << count 9756 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9757 MachO::arm_thread_state64_t cpu64; 9758 left = end - begin; 9759 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9760 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9761 begin += sizeof(MachO::arm_thread_state64_t); 9762 } else { 9763 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9764 memcpy(&cpu64, begin, left); 9765 begin += left; 9766 } 9767 if (isLittleEndian != sys::IsLittleEndianHost) 9768 swapStruct(cpu64); 9769 Print_arm_thread_state64_t(cpu64); 9770 } else { 9771 outs() << " flavor " << flavor << " (unknown)\n"; 9772 outs() << " count " << count << "\n"; 9773 outs() << " state (unknown)\n"; 9774 begin += count * sizeof(uint32_t); 9775 } 9776 } 9777 } else { 9778 while (begin < end) { 9779 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9780 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9781 begin += sizeof(uint32_t); 9782 } else { 9783 flavor = 0; 9784 begin = end; 9785 } 9786 if (isLittleEndian != sys::IsLittleEndianHost) 9787 sys::swapByteOrder(flavor); 9788 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9789 memcpy((char *)&count, begin, sizeof(uint32_t)); 9790 begin += sizeof(uint32_t); 9791 } else { 9792 count = 0; 9793 begin = end; 9794 } 9795 if (isLittleEndian != sys::IsLittleEndianHost) 9796 sys::swapByteOrder(count); 9797 outs() << " flavor " << flavor << "\n"; 9798 outs() << " count " << count << "\n"; 9799 outs() << " state (Unknown cputype/cpusubtype)\n"; 9800 begin += count * sizeof(uint32_t); 9801 } 9802 } 9803 } 9804 9805 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 9806 if (dl.cmd == MachO::LC_ID_DYLIB) 9807 outs() << " cmd LC_ID_DYLIB\n"; 9808 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 9809 outs() << " cmd LC_LOAD_DYLIB\n"; 9810 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 9811 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 9812 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 9813 outs() << " cmd LC_REEXPORT_DYLIB\n"; 9814 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 9815 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 9816 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 9817 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 9818 else 9819 outs() << " cmd " << dl.cmd << " (unknown)\n"; 9820 outs() << " cmdsize " << dl.cmdsize; 9821 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 9822 outs() << " Incorrect size\n"; 9823 else 9824 outs() << "\n"; 9825 if (dl.dylib.name < dl.cmdsize) { 9826 const char *P = (const char *)(Ptr) + dl.dylib.name; 9827 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 9828 } else { 9829 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 9830 } 9831 outs() << " time stamp " << dl.dylib.timestamp << " "; 9832 time_t t = dl.dylib.timestamp; 9833 outs() << ctime(&t); 9834 outs() << " current version "; 9835 if (dl.dylib.current_version == 0xffffffff) 9836 outs() << "n/a\n"; 9837 else 9838 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 9839 << ((dl.dylib.current_version >> 8) & 0xff) << "." 9840 << (dl.dylib.current_version & 0xff) << "\n"; 9841 outs() << "compatibility version "; 9842 if (dl.dylib.compatibility_version == 0xffffffff) 9843 outs() << "n/a\n"; 9844 else 9845 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 9846 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 9847 << (dl.dylib.compatibility_version & 0xff) << "\n"; 9848 } 9849 9850 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 9851 uint32_t object_size) { 9852 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 9853 outs() << " cmd LC_CODE_SIGNATURE\n"; 9854 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 9855 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 9856 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 9857 outs() << " cmd LC_FUNCTION_STARTS\n"; 9858 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 9859 outs() << " cmd LC_DATA_IN_CODE\n"; 9860 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 9861 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 9862 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 9863 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 9864 else 9865 outs() << " cmd " << ld.cmd << " (?)\n"; 9866 outs() << " cmdsize " << ld.cmdsize; 9867 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 9868 outs() << " Incorrect size\n"; 9869 else 9870 outs() << "\n"; 9871 outs() << " dataoff " << ld.dataoff; 9872 if (ld.dataoff > object_size) 9873 outs() << " (past end of file)\n"; 9874 else 9875 outs() << "\n"; 9876 outs() << " datasize " << ld.datasize; 9877 uint64_t big_size = ld.dataoff; 9878 big_size += ld.datasize; 9879 if (big_size > object_size) 9880 outs() << " (past end of file)\n"; 9881 else 9882 outs() << "\n"; 9883 } 9884 9885 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 9886 uint32_t cputype, bool verbose) { 9887 StringRef Buf = Obj->getData(); 9888 unsigned Index = 0; 9889 for (const auto &Command : Obj->load_commands()) { 9890 outs() << "Load command " << Index++ << "\n"; 9891 if (Command.C.cmd == MachO::LC_SEGMENT) { 9892 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 9893 const char *sg_segname = SLC.segname; 9894 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 9895 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 9896 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 9897 verbose); 9898 for (unsigned j = 0; j < SLC.nsects; j++) { 9899 MachO::section S = Obj->getSection(Command, j); 9900 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 9901 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 9902 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 9903 } 9904 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 9905 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 9906 const char *sg_segname = SLC_64.segname; 9907 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 9908 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 9909 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 9910 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 9911 for (unsigned j = 0; j < SLC_64.nsects; j++) { 9912 MachO::section_64 S_64 = Obj->getSection64(Command, j); 9913 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 9914 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 9915 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 9916 sg_segname, filetype, Buf.size(), verbose); 9917 } 9918 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 9919 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9920 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 9921 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 9922 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 9923 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 9924 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 9925 Obj->is64Bit()); 9926 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 9927 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 9928 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 9929 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 9930 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 9931 Command.C.cmd == MachO::LC_ID_DYLINKER || 9932 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 9933 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 9934 PrintDyldLoadCommand(Dyld, Command.Ptr); 9935 } else if (Command.C.cmd == MachO::LC_UUID) { 9936 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 9937 PrintUuidLoadCommand(Uuid); 9938 } else if (Command.C.cmd == MachO::LC_RPATH) { 9939 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 9940 PrintRpathLoadCommand(Rpath, Command.Ptr); 9941 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 9942 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 9943 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 9944 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 9945 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 9946 PrintVersionMinLoadCommand(Vd); 9947 } else if (Command.C.cmd == MachO::LC_NOTE) { 9948 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 9949 PrintNoteLoadCommand(Nt); 9950 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 9951 MachO::build_version_command Bv = 9952 Obj->getBuildVersionLoadCommand(Command); 9953 PrintBuildVersionLoadCommand(Obj, Bv); 9954 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 9955 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 9956 PrintSourceVersionCommand(Sd); 9957 } else if (Command.C.cmd == MachO::LC_MAIN) { 9958 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 9959 PrintEntryPointCommand(Ep); 9960 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 9961 MachO::encryption_info_command Ei = 9962 Obj->getEncryptionInfoCommand(Command); 9963 PrintEncryptionInfoCommand(Ei, Buf.size()); 9964 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 9965 MachO::encryption_info_command_64 Ei = 9966 Obj->getEncryptionInfoCommand64(Command); 9967 PrintEncryptionInfoCommand64(Ei, Buf.size()); 9968 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 9969 MachO::linker_option_command Lo = 9970 Obj->getLinkerOptionLoadCommand(Command); 9971 PrintLinkerOptionCommand(Lo, Command.Ptr); 9972 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 9973 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 9974 PrintSubFrameworkCommand(Sf, Command.Ptr); 9975 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 9976 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 9977 PrintSubUmbrellaCommand(Sf, Command.Ptr); 9978 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 9979 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 9980 PrintSubLibraryCommand(Sl, Command.Ptr); 9981 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 9982 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 9983 PrintSubClientCommand(Sc, Command.Ptr); 9984 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 9985 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 9986 PrintRoutinesCommand(Rc); 9987 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 9988 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 9989 PrintRoutinesCommand64(Rc); 9990 } else if (Command.C.cmd == MachO::LC_THREAD || 9991 Command.C.cmd == MachO::LC_UNIXTHREAD) { 9992 MachO::thread_command Tc = Obj->getThreadCommand(Command); 9993 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 9994 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 9995 Command.C.cmd == MachO::LC_ID_DYLIB || 9996 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 9997 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 9998 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 9999 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 10000 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 10001 PrintDylibCommand(Dl, Command.Ptr); 10002 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 10003 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 10004 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 10005 Command.C.cmd == MachO::LC_DATA_IN_CODE || 10006 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 10007 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 10008 MachO::linkedit_data_command Ld = 10009 Obj->getLinkeditDataLoadCommand(Command); 10010 PrintLinkEditDataCommand(Ld, Buf.size()); 10011 } else { 10012 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 10013 << ")\n"; 10014 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 10015 // TODO: get and print the raw bytes of the load command. 10016 } 10017 // TODO: print all the other kinds of load commands. 10018 } 10019 } 10020 10021 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 10022 if (Obj->is64Bit()) { 10023 MachO::mach_header_64 H_64; 10024 H_64 = Obj->getHeader64(); 10025 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 10026 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 10027 } else { 10028 MachO::mach_header H; 10029 H = Obj->getHeader(); 10030 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 10031 H.sizeofcmds, H.flags, verbose); 10032 } 10033 } 10034 10035 void printMachOFileHeader(const object::ObjectFile *Obj) { 10036 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 10037 PrintMachHeader(file, !NonVerbose); 10038 } 10039 10040 void printMachOLoadCommands(const object::ObjectFile *Obj) { 10041 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 10042 uint32_t filetype = 0; 10043 uint32_t cputype = 0; 10044 if (file->is64Bit()) { 10045 MachO::mach_header_64 H_64; 10046 H_64 = file->getHeader64(); 10047 filetype = H_64.filetype; 10048 cputype = H_64.cputype; 10049 } else { 10050 MachO::mach_header H; 10051 H = file->getHeader(); 10052 filetype = H.filetype; 10053 cputype = H.cputype; 10054 } 10055 PrintLoadCommands(file, filetype, cputype, !NonVerbose); 10056 } 10057 10058 //===----------------------------------------------------------------------===// 10059 // export trie dumping 10060 //===----------------------------------------------------------------------===// 10061 10062 void printMachOExportsTrie(const object::MachOObjectFile *Obj) { 10063 uint64_t BaseSegmentAddress = 0; 10064 for (const auto &Command : Obj->load_commands()) { 10065 if (Command.C.cmd == MachO::LC_SEGMENT) { 10066 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 10067 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10068 BaseSegmentAddress = Seg.vmaddr; 10069 break; 10070 } 10071 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10072 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 10073 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10074 BaseSegmentAddress = Seg.vmaddr; 10075 break; 10076 } 10077 } 10078 } 10079 Error Err = Error::success(); 10080 for (const object::ExportEntry &Entry : Obj->exports(Err)) { 10081 uint64_t Flags = Entry.flags(); 10082 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 10083 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 10084 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10085 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 10086 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10087 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 10088 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 10089 if (ReExport) 10090 outs() << "[re-export] "; 10091 else 10092 outs() << format("0x%08llX ", 10093 Entry.address() + BaseSegmentAddress); 10094 outs() << Entry.name(); 10095 if (WeakDef || ThreadLocal || Resolver || Abs) { 10096 bool NeedsComma = false; 10097 outs() << " ["; 10098 if (WeakDef) { 10099 outs() << "weak_def"; 10100 NeedsComma = true; 10101 } 10102 if (ThreadLocal) { 10103 if (NeedsComma) 10104 outs() << ", "; 10105 outs() << "per-thread"; 10106 NeedsComma = true; 10107 } 10108 if (Abs) { 10109 if (NeedsComma) 10110 outs() << ", "; 10111 outs() << "absolute"; 10112 NeedsComma = true; 10113 } 10114 if (Resolver) { 10115 if (NeedsComma) 10116 outs() << ", "; 10117 outs() << format("resolver=0x%08llX", Entry.other()); 10118 NeedsComma = true; 10119 } 10120 outs() << "]"; 10121 } 10122 if (ReExport) { 10123 StringRef DylibName = "unknown"; 10124 int Ordinal = Entry.other() - 1; 10125 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 10126 if (Entry.otherName().empty()) 10127 outs() << " (from " << DylibName << ")"; 10128 else 10129 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 10130 } 10131 outs() << "\n"; 10132 } 10133 if (Err) 10134 report_error(std::move(Err), Obj->getFileName()); 10135 } 10136 10137 //===----------------------------------------------------------------------===// 10138 // rebase table dumping 10139 //===----------------------------------------------------------------------===// 10140 10141 void printMachORebaseTable(object::MachOObjectFile *Obj) { 10142 outs() << "segment section address type\n"; 10143 Error Err = Error::success(); 10144 for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 10145 StringRef SegmentName = Entry.segmentName(); 10146 StringRef SectionName = Entry.sectionName(); 10147 uint64_t Address = Entry.address(); 10148 10149 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 10150 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 10151 SegmentName.str().c_str(), SectionName.str().c_str(), 10152 Address, Entry.typeName().str().c_str()); 10153 } 10154 if (Err) 10155 report_error(std::move(Err), Obj->getFileName()); 10156 } 10157 10158 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 10159 StringRef DylibName; 10160 switch (Ordinal) { 10161 case MachO::BIND_SPECIAL_DYLIB_SELF: 10162 return "this-image"; 10163 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 10164 return "main-executable"; 10165 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 10166 return "flat-namespace"; 10167 default: 10168 if (Ordinal > 0) { 10169 std::error_code EC = 10170 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 10171 if (EC) 10172 return "<<bad library ordinal>>"; 10173 return DylibName; 10174 } 10175 } 10176 return "<<unknown special ordinal>>"; 10177 } 10178 10179 //===----------------------------------------------------------------------===// 10180 // bind table dumping 10181 //===----------------------------------------------------------------------===// 10182 10183 void printMachOBindTable(object::MachOObjectFile *Obj) { 10184 // Build table of sections so names can used in final output. 10185 outs() << "segment section address type " 10186 "addend dylib symbol\n"; 10187 Error Err = Error::success(); 10188 for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 10189 StringRef SegmentName = Entry.segmentName(); 10190 StringRef SectionName = Entry.sectionName(); 10191 uint64_t Address = Entry.address(); 10192 10193 // Table lines look like: 10194 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 10195 StringRef Attr; 10196 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 10197 Attr = " (weak_import)"; 10198 outs() << left_justify(SegmentName, 8) << " " 10199 << left_justify(SectionName, 18) << " " 10200 << format_hex(Address, 10, true) << " " 10201 << left_justify(Entry.typeName(), 8) << " " 10202 << format_decimal(Entry.addend(), 8) << " " 10203 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10204 << Entry.symbolName() << Attr << "\n"; 10205 } 10206 if (Err) 10207 report_error(std::move(Err), Obj->getFileName()); 10208 } 10209 10210 //===----------------------------------------------------------------------===// 10211 // lazy bind table dumping 10212 //===----------------------------------------------------------------------===// 10213 10214 void printMachOLazyBindTable(object::MachOObjectFile *Obj) { 10215 outs() << "segment section address " 10216 "dylib symbol\n"; 10217 Error Err = Error::success(); 10218 for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 10219 StringRef SegmentName = Entry.segmentName(); 10220 StringRef SectionName = Entry.sectionName(); 10221 uint64_t Address = Entry.address(); 10222 10223 // Table lines look like: 10224 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 10225 outs() << left_justify(SegmentName, 8) << " " 10226 << left_justify(SectionName, 18) << " " 10227 << format_hex(Address, 10, true) << " " 10228 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10229 << Entry.symbolName() << "\n"; 10230 } 10231 if (Err) 10232 report_error(std::move(Err), Obj->getFileName()); 10233 } 10234 10235 //===----------------------------------------------------------------------===// 10236 // weak bind table dumping 10237 //===----------------------------------------------------------------------===// 10238 10239 void printMachOWeakBindTable(object::MachOObjectFile *Obj) { 10240 outs() << "segment section address " 10241 "type addend symbol\n"; 10242 Error Err = Error::success(); 10243 for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 10244 // Strong symbols don't have a location to update. 10245 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 10246 outs() << " strong " 10247 << Entry.symbolName() << "\n"; 10248 continue; 10249 } 10250 StringRef SegmentName = Entry.segmentName(); 10251 StringRef SectionName = Entry.sectionName(); 10252 uint64_t Address = Entry.address(); 10253 10254 // Table lines look like: 10255 // __DATA __data 0x00001000 pointer 0 _foo 10256 outs() << left_justify(SegmentName, 8) << " " 10257 << left_justify(SectionName, 18) << " " 10258 << format_hex(Address, 10, true) << " " 10259 << left_justify(Entry.typeName(), 8) << " " 10260 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 10261 << "\n"; 10262 } 10263 if (Err) 10264 report_error(std::move(Err), Obj->getFileName()); 10265 } 10266 10267 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 10268 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 10269 // information for that address. If the address is found its binding symbol 10270 // name is returned. If not nullptr is returned. 10271 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 10272 struct DisassembleInfo *info) { 10273 if (info->bindtable == nullptr) { 10274 info->bindtable = llvm::make_unique<SymbolAddressMap>(); 10275 Error Err = Error::success(); 10276 for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 10277 uint64_t Address = Entry.address(); 10278 StringRef name = Entry.symbolName(); 10279 if (!name.empty()) 10280 (*info->bindtable)[Address] = name; 10281 } 10282 if (Err) 10283 report_error(std::move(Err), info->O->getFileName()); 10284 } 10285 auto name = info->bindtable->lookup(ReferenceValue); 10286 return !name.empty() ? name.data() : nullptr; 10287 } 10288 10289 void printLazyBindTable(ObjectFile *o) { 10290 outs() << "Lazy bind table:\n"; 10291 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10292 printMachOLazyBindTable(MachO); 10293 else 10294 WithColor::error() 10295 << "This operation is only currently supported " 10296 "for Mach-O executable files.\n"; 10297 } 10298 10299 void printWeakBindTable(ObjectFile *o) { 10300 outs() << "Weak bind table:\n"; 10301 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10302 printMachOWeakBindTable(MachO); 10303 else 10304 WithColor::error() 10305 << "This operation is only currently supported " 10306 "for Mach-O executable files.\n"; 10307 } 10308 10309 void printExportsTrie(const ObjectFile *o) { 10310 outs() << "Exports trie:\n"; 10311 if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10312 printMachOExportsTrie(MachO); 10313 else 10314 WithColor::error() 10315 << "This operation is only currently supported " 10316 "for Mach-O executable files.\n"; 10317 } 10318 10319 void printRebaseTable(ObjectFile *o) { 10320 outs() << "Rebase table:\n"; 10321 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10322 printMachORebaseTable(MachO); 10323 else 10324 WithColor::error() 10325 << "This operation is only currently supported " 10326 "for Mach-O executable files.\n"; 10327 } 10328 10329 void printBindTable(ObjectFile *o) { 10330 outs() << "Bind table:\n"; 10331 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10332 printMachOBindTable(MachO); 10333 else 10334 WithColor::error() 10335 << "This operation is only currently supported " 10336 "for Mach-O executable files.\n"; 10337 } 10338 } // namespace llvm 10339