1 //===-- MachODump.cpp - Object file dumping utility for llvm --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the MachO-specific dumper for llvm-objdump. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MachODump.h" 14 15 #include "ObjdumpOptID.h" 16 #include "llvm-objdump.h" 17 #include "llvm-c/Disassembler.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/ADT/StringExtras.h" 20 #include "llvm/ADT/Triple.h" 21 #include "llvm/BinaryFormat/MachO.h" 22 #include "llvm/Config/config.h" 23 #include "llvm/DebugInfo/DIContext.h" 24 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 25 #include "llvm/Demangle/Demangle.h" 26 #include "llvm/MC/MCAsmInfo.h" 27 #include "llvm/MC/MCContext.h" 28 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 29 #include "llvm/MC/MCInst.h" 30 #include "llvm/MC/MCInstPrinter.h" 31 #include "llvm/MC/MCInstrDesc.h" 32 #include "llvm/MC/MCInstrInfo.h" 33 #include "llvm/MC/MCRegisterInfo.h" 34 #include "llvm/MC/MCSubtargetInfo.h" 35 #include "llvm/MC/MCTargetOptions.h" 36 #include "llvm/MC/TargetRegistry.h" 37 #include "llvm/Object/MachO.h" 38 #include "llvm/Object/MachOUniversal.h" 39 #include "llvm/Option/ArgList.h" 40 #include "llvm/Support/Casting.h" 41 #include "llvm/Support/Debug.h" 42 #include "llvm/Support/Endian.h" 43 #include "llvm/Support/Format.h" 44 #include "llvm/Support/FormattedStream.h" 45 #include "llvm/Support/GraphWriter.h" 46 #include "llvm/Support/LEB128.h" 47 #include "llvm/Support/MemoryBuffer.h" 48 #include "llvm/Support/TargetSelect.h" 49 #include "llvm/Support/ToolOutputFile.h" 50 #include "llvm/Support/WithColor.h" 51 #include "llvm/Support/raw_ostream.h" 52 #include <algorithm> 53 #include <cstring> 54 #include <system_error> 55 56 #ifdef LLVM_HAVE_LIBXAR 57 extern "C" { 58 #include <xar/xar.h> 59 } 60 #endif 61 62 using namespace llvm; 63 using namespace llvm::object; 64 using namespace llvm::objdump; 65 66 bool objdump::FirstPrivateHeader; 67 bool objdump::ExportsTrie; 68 bool objdump::Rebase; 69 bool objdump::Rpaths; 70 bool objdump::Bind; 71 bool objdump::LazyBind; 72 bool objdump::WeakBind; 73 static bool UseDbg; 74 static std::string DSYMFile; 75 bool objdump::FullLeadingAddr; 76 bool objdump::LeadingHeaders; 77 bool objdump::UniversalHeaders; 78 static bool ArchiveMemberOffsets; 79 bool objdump::IndirectSymbols; 80 bool objdump::DataInCode; 81 bool objdump::FunctionStarts; 82 bool objdump::LinkOptHints; 83 bool objdump::InfoPlist; 84 bool objdump::DylibsUsed; 85 bool objdump::DylibId; 86 bool objdump::Verbose; 87 bool objdump::ObjcMetaData; 88 std::string objdump::DisSymName; 89 bool objdump::SymbolicOperands; 90 static std::vector<std::string> ArchFlags; 91 92 static bool ArchAll = false; 93 static std::string ThumbTripleName; 94 95 void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) { 96 FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header); 97 ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie); 98 Rebase = InputArgs.hasArg(OBJDUMP_rebase); 99 Rpaths = InputArgs.hasArg(OBJDUMP_rpaths); 100 Bind = InputArgs.hasArg(OBJDUMP_bind); 101 LazyBind = InputArgs.hasArg(OBJDUMP_lazy_bind); 102 WeakBind = InputArgs.hasArg(OBJDUMP_weak_bind); 103 UseDbg = InputArgs.hasArg(OBJDUMP_g); 104 DSYMFile = InputArgs.getLastArgValue(OBJDUMP_dsym_EQ).str(); 105 FullLeadingAddr = InputArgs.hasArg(OBJDUMP_full_leading_addr); 106 LeadingHeaders = !InputArgs.hasArg(OBJDUMP_no_leading_headers); 107 UniversalHeaders = InputArgs.hasArg(OBJDUMP_universal_headers); 108 ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets); 109 IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols); 110 DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code); 111 FunctionStarts = InputArgs.hasArg(OBJDUMP_function_starts); 112 LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints); 113 InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist); 114 DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used); 115 DylibId = InputArgs.hasArg(OBJDUMP_dylib_id); 116 Verbose = !InputArgs.hasArg(OBJDUMP_non_verbose); 117 ObjcMetaData = InputArgs.hasArg(OBJDUMP_objc_meta_data); 118 DisSymName = InputArgs.getLastArgValue(OBJDUMP_dis_symname).str(); 119 SymbolicOperands = !InputArgs.hasArg(OBJDUMP_no_symbolic_operands); 120 ArchFlags = InputArgs.getAllArgValues(OBJDUMP_arch_EQ); 121 } 122 123 static const Target *GetTarget(const MachOObjectFile *MachOObj, 124 const char **McpuDefault, 125 const Target **ThumbTarget) { 126 // Figure out the target triple. 127 Triple TT(TripleName); 128 if (TripleName.empty()) { 129 TT = MachOObj->getArchTriple(McpuDefault); 130 TripleName = TT.str(); 131 } 132 133 if (TT.getArch() == Triple::arm) { 134 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs 135 // that support ARM are also capable of Thumb mode. 136 Triple ThumbTriple = TT; 137 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str(); 138 ThumbTriple.setArchName(ThumbName); 139 ThumbTripleName = ThumbTriple.str(); 140 } 141 142 // Get the target specific parser. 143 std::string Error; 144 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 145 if (TheTarget && ThumbTripleName.empty()) 146 return TheTarget; 147 148 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 149 if (*ThumbTarget) 150 return TheTarget; 151 152 WithColor::error(errs(), "llvm-objdump") << "unable to get target for '"; 153 if (!TheTarget) 154 errs() << TripleName; 155 else 156 errs() << ThumbTripleName; 157 errs() << "', see --version and --triple.\n"; 158 return nullptr; 159 } 160 161 namespace { 162 struct SymbolSorter { 163 bool operator()(const SymbolRef &A, const SymbolRef &B) { 164 Expected<SymbolRef::Type> ATypeOrErr = A.getType(); 165 if (!ATypeOrErr) 166 reportError(ATypeOrErr.takeError(), A.getObject()->getFileName()); 167 SymbolRef::Type AType = *ATypeOrErr; 168 Expected<SymbolRef::Type> BTypeOrErr = B.getType(); 169 if (!BTypeOrErr) 170 reportError(BTypeOrErr.takeError(), B.getObject()->getFileName()); 171 SymbolRef::Type BType = *BTypeOrErr; 172 uint64_t AAddr = 173 (AType != SymbolRef::ST_Function) ? 0 : cantFail(A.getValue()); 174 uint64_t BAddr = 175 (BType != SymbolRef::ST_Function) ? 0 : cantFail(B.getValue()); 176 return AAddr < BAddr; 177 } 178 }; 179 } // namespace 180 181 // Types for the storted data in code table that is built before disassembly 182 // and the predicate function to sort them. 183 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 184 typedef std::vector<DiceTableEntry> DiceTable; 185 typedef DiceTable::iterator dice_table_iterator; 186 187 #ifdef LLVM_HAVE_LIBXAR 188 namespace { 189 struct ScopedXarFile { 190 xar_t xar; 191 ScopedXarFile(const char *filename, int32_t flags) { 192 #pragma clang diagnostic push 193 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 194 xar = xar_open(filename, flags); 195 #pragma clang diagnostic pop 196 } 197 ~ScopedXarFile() { 198 if (xar) 199 xar_close(xar); 200 } 201 ScopedXarFile(const ScopedXarFile &) = delete; 202 ScopedXarFile &operator=(const ScopedXarFile &) = delete; 203 operator xar_t() { return xar; } 204 }; 205 206 struct ScopedXarIter { 207 xar_iter_t iter; 208 ScopedXarIter() : iter(xar_iter_new()) {} 209 ~ScopedXarIter() { 210 if (iter) 211 xar_iter_free(iter); 212 } 213 ScopedXarIter(const ScopedXarIter &) = delete; 214 ScopedXarIter &operator=(const ScopedXarIter &) = delete; 215 operator xar_iter_t() { return iter; } 216 }; 217 } // namespace 218 #endif // defined(LLVM_HAVE_LIBXAR) 219 220 // This is used to search for a data in code table entry for the PC being 221 // disassembled. The j parameter has the PC in j.first. A single data in code 222 // table entry can cover many bytes for each of its Kind's. So if the offset, 223 // aka the i.first value, of the data in code table entry plus its Length 224 // covers the PC being searched for this will return true. If not it will 225 // return false. 226 static bool compareDiceTableEntries(const DiceTableEntry &i, 227 const DiceTableEntry &j) { 228 uint16_t Length; 229 i.second.getLength(Length); 230 231 return j.first >= i.first && j.first < i.first + Length; 232 } 233 234 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 235 unsigned short Kind) { 236 uint32_t Value, Size = 1; 237 238 switch (Kind) { 239 default: 240 case MachO::DICE_KIND_DATA: 241 if (Length >= 4) { 242 if (ShowRawInsn) 243 dumpBytes(makeArrayRef(bytes, 4), outs()); 244 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 245 outs() << "\t.long " << Value; 246 Size = 4; 247 } else if (Length >= 2) { 248 if (ShowRawInsn) 249 dumpBytes(makeArrayRef(bytes, 2), outs()); 250 Value = bytes[1] << 8 | bytes[0]; 251 outs() << "\t.short " << Value; 252 Size = 2; 253 } else { 254 if (ShowRawInsn) 255 dumpBytes(makeArrayRef(bytes, 2), outs()); 256 Value = bytes[0]; 257 outs() << "\t.byte " << Value; 258 Size = 1; 259 } 260 if (Kind == MachO::DICE_KIND_DATA) 261 outs() << "\t@ KIND_DATA\n"; 262 else 263 outs() << "\t@ data in code kind = " << Kind << "\n"; 264 break; 265 case MachO::DICE_KIND_JUMP_TABLE8: 266 if (ShowRawInsn) 267 dumpBytes(makeArrayRef(bytes, 1), outs()); 268 Value = bytes[0]; 269 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 270 Size = 1; 271 break; 272 case MachO::DICE_KIND_JUMP_TABLE16: 273 if (ShowRawInsn) 274 dumpBytes(makeArrayRef(bytes, 2), outs()); 275 Value = bytes[1] << 8 | bytes[0]; 276 outs() << "\t.short " << format("%5u", Value & 0xffff) 277 << "\t@ KIND_JUMP_TABLE16\n"; 278 Size = 2; 279 break; 280 case MachO::DICE_KIND_JUMP_TABLE32: 281 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 282 if (ShowRawInsn) 283 dumpBytes(makeArrayRef(bytes, 4), outs()); 284 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 285 outs() << "\t.long " << Value; 286 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 287 outs() << "\t@ KIND_JUMP_TABLE32\n"; 288 else 289 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 290 Size = 4; 291 break; 292 } 293 return Size; 294 } 295 296 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 297 std::vector<SectionRef> &Sections, 298 std::vector<SymbolRef> &Symbols, 299 SmallVectorImpl<uint64_t> &FoundFns, 300 uint64_t &BaseSegmentAddress) { 301 const StringRef FileName = MachOObj->getFileName(); 302 for (const SymbolRef &Symbol : MachOObj->symbols()) { 303 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 304 if (!SymName.startswith("ltmp")) 305 Symbols.push_back(Symbol); 306 } 307 308 append_range(Sections, MachOObj->sections()); 309 310 bool BaseSegmentAddressSet = false; 311 for (const auto &Command : MachOObj->load_commands()) { 312 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 313 // We found a function starts segment, parse the addresses for later 314 // consumption. 315 MachO::linkedit_data_command LLC = 316 MachOObj->getLinkeditDataLoadCommand(Command); 317 318 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 319 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 320 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 321 StringRef SegName = SLC.segname; 322 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 323 BaseSegmentAddressSet = true; 324 BaseSegmentAddress = SLC.vmaddr; 325 } 326 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 327 MachO::segment_command_64 SLC = MachOObj->getSegment64LoadCommand(Command); 328 StringRef SegName = SLC.segname; 329 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 330 BaseSegmentAddressSet = true; 331 BaseSegmentAddress = SLC.vmaddr; 332 } 333 } 334 } 335 } 336 337 static bool DumpAndSkipDataInCode(uint64_t PC, const uint8_t *bytes, 338 DiceTable &Dices, uint64_t &InstSize) { 339 // Check the data in code table here to see if this is data not an 340 // instruction to be disassembled. 341 DiceTable Dice; 342 Dice.push_back(std::make_pair(PC, DiceRef())); 343 dice_table_iterator DTI = 344 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 345 compareDiceTableEntries); 346 if (DTI != Dices.end()) { 347 uint16_t Length; 348 DTI->second.getLength(Length); 349 uint16_t Kind; 350 DTI->second.getKind(Kind); 351 InstSize = DumpDataInCode(bytes, Length, Kind); 352 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 353 (PC == (DTI->first + Length - 1)) && (Length & 1)) 354 InstSize++; 355 return true; 356 } 357 return false; 358 } 359 360 static void printRelocationTargetName(const MachOObjectFile *O, 361 const MachO::any_relocation_info &RE, 362 raw_string_ostream &Fmt) { 363 // Target of a scattered relocation is an address. In the interest of 364 // generating pretty output, scan through the symbol table looking for a 365 // symbol that aligns with that address. If we find one, print it. 366 // Otherwise, we just print the hex address of the target. 367 const StringRef FileName = O->getFileName(); 368 if (O->isRelocationScattered(RE)) { 369 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 370 371 for (const SymbolRef &Symbol : O->symbols()) { 372 uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName); 373 if (Addr != Val) 374 continue; 375 Fmt << unwrapOrError(Symbol.getName(), FileName); 376 return; 377 } 378 379 // If we couldn't find a symbol that this relocation refers to, try 380 // to find a section beginning instead. 381 for (const SectionRef &Section : ToolSectionFilter(*O)) { 382 uint64_t Addr = Section.getAddress(); 383 if (Addr != Val) 384 continue; 385 StringRef NameOrErr = unwrapOrError(Section.getName(), O->getFileName()); 386 Fmt << NameOrErr; 387 return; 388 } 389 390 Fmt << format("0x%x", Val); 391 return; 392 } 393 394 StringRef S; 395 bool isExtern = O->getPlainRelocationExternal(RE); 396 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 397 398 if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND && 399 (O->getArch() == Triple::aarch64 || O->getArch() == Triple::aarch64_be)) { 400 Fmt << format("0x%0" PRIx64, Val); 401 return; 402 } 403 404 if (isExtern) { 405 symbol_iterator SI = O->symbol_begin(); 406 std::advance(SI, Val); 407 S = unwrapOrError(SI->getName(), FileName); 408 } else { 409 section_iterator SI = O->section_begin(); 410 // Adjust for the fact that sections are 1-indexed. 411 if (Val == 0) { 412 Fmt << "0 (?,?)"; 413 return; 414 } 415 uint32_t I = Val - 1; 416 while (I != 0 && SI != O->section_end()) { 417 --I; 418 std::advance(SI, 1); 419 } 420 if (SI == O->section_end()) { 421 Fmt << Val << " (?,?)"; 422 } else { 423 if (Expected<StringRef> NameOrErr = SI->getName()) 424 S = *NameOrErr; 425 else 426 consumeError(NameOrErr.takeError()); 427 } 428 } 429 430 Fmt << S; 431 } 432 433 Error objdump::getMachORelocationValueString(const MachOObjectFile *Obj, 434 const RelocationRef &RelRef, 435 SmallVectorImpl<char> &Result) { 436 DataRefImpl Rel = RelRef.getRawDataRefImpl(); 437 MachO::any_relocation_info RE = Obj->getRelocation(Rel); 438 439 unsigned Arch = Obj->getArch(); 440 441 std::string FmtBuf; 442 raw_string_ostream Fmt(FmtBuf); 443 unsigned Type = Obj->getAnyRelocationType(RE); 444 bool IsPCRel = Obj->getAnyRelocationPCRel(RE); 445 446 // Determine any addends that should be displayed with the relocation. 447 // These require decoding the relocation type, which is triple-specific. 448 449 // X86_64 has entirely custom relocation types. 450 if (Arch == Triple::x86_64) { 451 switch (Type) { 452 case MachO::X86_64_RELOC_GOT_LOAD: 453 case MachO::X86_64_RELOC_GOT: { 454 printRelocationTargetName(Obj, RE, Fmt); 455 Fmt << "@GOT"; 456 if (IsPCRel) 457 Fmt << "PCREL"; 458 break; 459 } 460 case MachO::X86_64_RELOC_SUBTRACTOR: { 461 DataRefImpl RelNext = Rel; 462 Obj->moveRelocationNext(RelNext); 463 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 464 465 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 466 // X86_64_RELOC_UNSIGNED. 467 // NOTE: Scattered relocations don't exist on x86_64. 468 unsigned RType = Obj->getAnyRelocationType(RENext); 469 if (RType != MachO::X86_64_RELOC_UNSIGNED) 470 reportError(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after " 471 "X86_64_RELOC_SUBTRACTOR."); 472 473 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 474 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 475 printRelocationTargetName(Obj, RENext, Fmt); 476 Fmt << "-"; 477 printRelocationTargetName(Obj, RE, Fmt); 478 break; 479 } 480 case MachO::X86_64_RELOC_TLV: 481 printRelocationTargetName(Obj, RE, Fmt); 482 Fmt << "@TLV"; 483 if (IsPCRel) 484 Fmt << "P"; 485 break; 486 case MachO::X86_64_RELOC_SIGNED_1: 487 printRelocationTargetName(Obj, RE, Fmt); 488 Fmt << "-1"; 489 break; 490 case MachO::X86_64_RELOC_SIGNED_2: 491 printRelocationTargetName(Obj, RE, Fmt); 492 Fmt << "-2"; 493 break; 494 case MachO::X86_64_RELOC_SIGNED_4: 495 printRelocationTargetName(Obj, RE, Fmt); 496 Fmt << "-4"; 497 break; 498 default: 499 printRelocationTargetName(Obj, RE, Fmt); 500 break; 501 } 502 // X86 and ARM share some relocation types in common. 503 } else if (Arch == Triple::x86 || Arch == Triple::arm || 504 Arch == Triple::ppc) { 505 // Generic relocation types... 506 switch (Type) { 507 case MachO::GENERIC_RELOC_PAIR: // prints no info 508 return Error::success(); 509 case MachO::GENERIC_RELOC_SECTDIFF: { 510 DataRefImpl RelNext = Rel; 511 Obj->moveRelocationNext(RelNext); 512 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 513 514 // X86 sect diff's must be followed by a relocation of type 515 // GENERIC_RELOC_PAIR. 516 unsigned RType = Obj->getAnyRelocationType(RENext); 517 518 if (RType != MachO::GENERIC_RELOC_PAIR) 519 reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 520 "GENERIC_RELOC_SECTDIFF."); 521 522 printRelocationTargetName(Obj, RE, Fmt); 523 Fmt << "-"; 524 printRelocationTargetName(Obj, RENext, Fmt); 525 break; 526 } 527 } 528 529 if (Arch == Triple::x86 || Arch == Triple::ppc) { 530 switch (Type) { 531 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 532 DataRefImpl RelNext = Rel; 533 Obj->moveRelocationNext(RelNext); 534 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 535 536 // X86 sect diff's must be followed by a relocation of type 537 // GENERIC_RELOC_PAIR. 538 unsigned RType = Obj->getAnyRelocationType(RENext); 539 if (RType != MachO::GENERIC_RELOC_PAIR) 540 reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 541 "GENERIC_RELOC_LOCAL_SECTDIFF."); 542 543 printRelocationTargetName(Obj, RE, Fmt); 544 Fmt << "-"; 545 printRelocationTargetName(Obj, RENext, Fmt); 546 break; 547 } 548 case MachO::GENERIC_RELOC_TLV: { 549 printRelocationTargetName(Obj, RE, Fmt); 550 Fmt << "@TLV"; 551 if (IsPCRel) 552 Fmt << "P"; 553 break; 554 } 555 default: 556 printRelocationTargetName(Obj, RE, Fmt); 557 } 558 } else { // ARM-specific relocations 559 switch (Type) { 560 case MachO::ARM_RELOC_HALF: 561 case MachO::ARM_RELOC_HALF_SECTDIFF: { 562 // Half relocations steal a bit from the length field to encode 563 // whether this is an upper16 or a lower16 relocation. 564 bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1; 565 566 if (isUpper) 567 Fmt << ":upper16:("; 568 else 569 Fmt << ":lower16:("; 570 printRelocationTargetName(Obj, RE, Fmt); 571 572 DataRefImpl RelNext = Rel; 573 Obj->moveRelocationNext(RelNext); 574 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 575 576 // ARM half relocs must be followed by a relocation of type 577 // ARM_RELOC_PAIR. 578 unsigned RType = Obj->getAnyRelocationType(RENext); 579 if (RType != MachO::ARM_RELOC_PAIR) 580 reportError(Obj->getFileName(), "Expected ARM_RELOC_PAIR after " 581 "ARM_RELOC_HALF"); 582 583 // NOTE: The half of the target virtual address is stashed in the 584 // address field of the secondary relocation, but we can't reverse 585 // engineer the constant offset from it without decoding the movw/movt 586 // instruction to find the other half in its immediate field. 587 588 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 589 // symbol/section pointer of the follow-on relocation. 590 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 591 Fmt << "-"; 592 printRelocationTargetName(Obj, RENext, Fmt); 593 } 594 595 Fmt << ")"; 596 break; 597 } 598 default: { 599 printRelocationTargetName(Obj, RE, Fmt); 600 } 601 } 602 } 603 } else 604 printRelocationTargetName(Obj, RE, Fmt); 605 606 Fmt.flush(); 607 Result.append(FmtBuf.begin(), FmtBuf.end()); 608 return Error::success(); 609 } 610 611 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 612 uint32_t n, uint32_t count, 613 uint32_t stride, uint64_t addr) { 614 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 615 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 616 if (n > nindirectsyms) 617 outs() << " (entries start past the end of the indirect symbol " 618 "table) (reserved1 field greater than the table size)"; 619 else if (n + count > nindirectsyms) 620 outs() << " (entries extends past the end of the indirect symbol " 621 "table)"; 622 outs() << "\n"; 623 uint32_t cputype = O->getHeader().cputype; 624 if (cputype & MachO::CPU_ARCH_ABI64) 625 outs() << "address index"; 626 else 627 outs() << "address index"; 628 if (verbose) 629 outs() << " name\n"; 630 else 631 outs() << "\n"; 632 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 633 if (cputype & MachO::CPU_ARCH_ABI64) 634 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 635 else 636 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 637 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 638 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 639 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 640 outs() << "LOCAL\n"; 641 continue; 642 } 643 if (indirect_symbol == 644 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 645 outs() << "LOCAL ABSOLUTE\n"; 646 continue; 647 } 648 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 649 outs() << "ABSOLUTE\n"; 650 continue; 651 } 652 outs() << format("%5u ", indirect_symbol); 653 if (verbose) { 654 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 655 if (indirect_symbol < Symtab.nsyms) { 656 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 657 SymbolRef Symbol = *Sym; 658 outs() << unwrapOrError(Symbol.getName(), O->getFileName()); 659 } else { 660 outs() << "?"; 661 } 662 } 663 outs() << "\n"; 664 } 665 } 666 667 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 668 for (const auto &Load : O->load_commands()) { 669 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 670 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 671 for (unsigned J = 0; J < Seg.nsects; ++J) { 672 MachO::section_64 Sec = O->getSection64(Load, J); 673 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 674 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 675 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 676 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 677 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 678 section_type == MachO::S_SYMBOL_STUBS) { 679 uint32_t stride; 680 if (section_type == MachO::S_SYMBOL_STUBS) 681 stride = Sec.reserved2; 682 else 683 stride = 8; 684 if (stride == 0) { 685 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 686 << Sec.sectname << ") " 687 << "(size of stubs in reserved2 field is zero)\n"; 688 continue; 689 } 690 uint32_t count = Sec.size / stride; 691 outs() << "Indirect symbols for (" << Sec.segname << "," 692 << Sec.sectname << ") " << count << " entries"; 693 uint32_t n = Sec.reserved1; 694 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 695 } 696 } 697 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 698 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 699 for (unsigned J = 0; J < Seg.nsects; ++J) { 700 MachO::section Sec = O->getSection(Load, J); 701 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 702 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 703 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 704 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 705 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 706 section_type == MachO::S_SYMBOL_STUBS) { 707 uint32_t stride; 708 if (section_type == MachO::S_SYMBOL_STUBS) 709 stride = Sec.reserved2; 710 else 711 stride = 4; 712 if (stride == 0) { 713 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 714 << Sec.sectname << ") " 715 << "(size of stubs in reserved2 field is zero)\n"; 716 continue; 717 } 718 uint32_t count = Sec.size / stride; 719 outs() << "Indirect symbols for (" << Sec.segname << "," 720 << Sec.sectname << ") " << count << " entries"; 721 uint32_t n = Sec.reserved1; 722 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 723 } 724 } 725 } 726 } 727 } 728 729 static void PrintRType(const uint64_t cputype, const unsigned r_type) { 730 static char const *generic_r_types[] = { 731 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ", 732 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", 733 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 734 }; 735 static char const *x86_64_r_types[] = { 736 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", 737 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ", 738 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 739 }; 740 static char const *arm_r_types[] = { 741 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", 742 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ", 743 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 744 }; 745 static char const *arm64_r_types[] = { 746 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", 747 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", 748 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 749 }; 750 751 if (r_type > 0xf){ 752 outs() << format("%-7u", r_type) << " "; 753 return; 754 } 755 switch (cputype) { 756 case MachO::CPU_TYPE_I386: 757 outs() << generic_r_types[r_type]; 758 break; 759 case MachO::CPU_TYPE_X86_64: 760 outs() << x86_64_r_types[r_type]; 761 break; 762 case MachO::CPU_TYPE_ARM: 763 outs() << arm_r_types[r_type]; 764 break; 765 case MachO::CPU_TYPE_ARM64: 766 case MachO::CPU_TYPE_ARM64_32: 767 outs() << arm64_r_types[r_type]; 768 break; 769 default: 770 outs() << format("%-7u ", r_type); 771 } 772 } 773 774 static void PrintRLength(const uint64_t cputype, const unsigned r_type, 775 const unsigned r_length, const bool previous_arm_half){ 776 if (cputype == MachO::CPU_TYPE_ARM && 777 (r_type == MachO::ARM_RELOC_HALF || 778 r_type == MachO::ARM_RELOC_HALF_SECTDIFF || previous_arm_half == true)) { 779 if ((r_length & 0x1) == 0) 780 outs() << "lo/"; 781 else 782 outs() << "hi/"; 783 if ((r_length & 0x1) == 0) 784 outs() << "arm "; 785 else 786 outs() << "thm "; 787 } else { 788 switch (r_length) { 789 case 0: 790 outs() << "byte "; 791 break; 792 case 1: 793 outs() << "word "; 794 break; 795 case 2: 796 outs() << "long "; 797 break; 798 case 3: 799 if (cputype == MachO::CPU_TYPE_X86_64) 800 outs() << "quad "; 801 else 802 outs() << format("?(%2d) ", r_length); 803 break; 804 default: 805 outs() << format("?(%2d) ", r_length); 806 } 807 } 808 } 809 810 static void PrintRelocationEntries(const MachOObjectFile *O, 811 const relocation_iterator Begin, 812 const relocation_iterator End, 813 const uint64_t cputype, 814 const bool verbose) { 815 const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 816 bool previous_arm_half = false; 817 bool previous_sectdiff = false; 818 uint32_t sectdiff_r_type = 0; 819 820 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { 821 const DataRefImpl Rel = Reloc->getRawDataRefImpl(); 822 const MachO::any_relocation_info RE = O->getRelocation(Rel); 823 const unsigned r_type = O->getAnyRelocationType(RE); 824 const bool r_scattered = O->isRelocationScattered(RE); 825 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); 826 const unsigned r_length = O->getAnyRelocationLength(RE); 827 const unsigned r_address = O->getAnyRelocationAddress(RE); 828 const bool r_extern = (r_scattered ? false : 829 O->getPlainRelocationExternal(RE)); 830 const uint32_t r_value = (r_scattered ? 831 O->getScatteredRelocationValue(RE) : 0); 832 const unsigned r_symbolnum = (r_scattered ? 0 : 833 O->getPlainRelocationSymbolNum(RE)); 834 835 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { 836 if (verbose) { 837 // scattered: address 838 if ((cputype == MachO::CPU_TYPE_I386 && 839 r_type == MachO::GENERIC_RELOC_PAIR) || 840 (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)) 841 outs() << " "; 842 else 843 outs() << format("%08x ", (unsigned int)r_address); 844 845 // scattered: pcrel 846 if (r_pcrel) 847 outs() << "True "; 848 else 849 outs() << "False "; 850 851 // scattered: length 852 PrintRLength(cputype, r_type, r_length, previous_arm_half); 853 854 // scattered: extern & type 855 outs() << "n/a "; 856 PrintRType(cputype, r_type); 857 858 // scattered: scattered & value 859 outs() << format("True 0x%08x", (unsigned int)r_value); 860 if (previous_sectdiff == false) { 861 if ((cputype == MachO::CPU_TYPE_ARM && 862 r_type == MachO::ARM_RELOC_PAIR)) 863 outs() << format(" half = 0x%04x ", (unsigned int)r_address); 864 } else if (cputype == MachO::CPU_TYPE_ARM && 865 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF) 866 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); 867 if ((cputype == MachO::CPU_TYPE_I386 && 868 (r_type == MachO::GENERIC_RELOC_SECTDIFF || 869 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || 870 (cputype == MachO::CPU_TYPE_ARM && 871 (sectdiff_r_type == MachO::ARM_RELOC_SECTDIFF || 872 sectdiff_r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 873 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF))) { 874 previous_sectdiff = true; 875 sectdiff_r_type = r_type; 876 } else { 877 previous_sectdiff = false; 878 sectdiff_r_type = 0; 879 } 880 if (cputype == MachO::CPU_TYPE_ARM && 881 (r_type == MachO::ARM_RELOC_HALF || 882 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 883 previous_arm_half = true; 884 else 885 previous_arm_half = false; 886 outs() << "\n"; 887 } 888 else { 889 // scattered: address pcrel length extern type scattered value 890 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n", 891 (unsigned int)r_address, r_pcrel, r_length, r_type, 892 (unsigned int)r_value); 893 } 894 } 895 else { 896 if (verbose) { 897 // plain: address 898 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 899 outs() << " "; 900 else 901 outs() << format("%08x ", (unsigned int)r_address); 902 903 // plain: pcrel 904 if (r_pcrel) 905 outs() << "True "; 906 else 907 outs() << "False "; 908 909 // plain: length 910 PrintRLength(cputype, r_type, r_length, previous_arm_half); 911 912 if (r_extern) { 913 // plain: extern & type & scattered 914 outs() << "True "; 915 PrintRType(cputype, r_type); 916 outs() << "False "; 917 918 // plain: symbolnum/value 919 if (r_symbolnum > Symtab.nsyms) 920 outs() << format("?(%d)\n", r_symbolnum); 921 else { 922 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); 923 Expected<StringRef> SymNameNext = Symbol.getName(); 924 const char *name = nullptr; 925 if (SymNameNext) 926 name = SymNameNext->data(); 927 if (name == nullptr) 928 outs() << format("?(%d)\n", r_symbolnum); 929 else 930 outs() << name << "\n"; 931 } 932 } 933 else { 934 // plain: extern & type & scattered 935 outs() << "False "; 936 PrintRType(cputype, r_type); 937 outs() << "False "; 938 939 // plain: symbolnum/value 940 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 941 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); 942 else if ((cputype == MachO::CPU_TYPE_ARM64 || 943 cputype == MachO::CPU_TYPE_ARM64_32) && 944 r_type == MachO::ARM64_RELOC_ADDEND) 945 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); 946 else { 947 outs() << format("%d ", r_symbolnum); 948 if (r_symbolnum == MachO::R_ABS) 949 outs() << "R_ABS\n"; 950 else { 951 // in this case, r_symbolnum is actually a 1-based section number 952 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; 953 if (r_symbolnum > 0 && r_symbolnum <= nsects) { 954 object::DataRefImpl DRI; 955 DRI.d.a = r_symbolnum-1; 956 StringRef SegName = O->getSectionFinalSegmentName(DRI); 957 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 958 outs() << "(" << SegName << "," << *NameOrErr << ")\n"; 959 else 960 outs() << "(?,?)\n"; 961 } 962 else { 963 outs() << "(?,?)\n"; 964 } 965 } 966 } 967 } 968 if (cputype == MachO::CPU_TYPE_ARM && 969 (r_type == MachO::ARM_RELOC_HALF || 970 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 971 previous_arm_half = true; 972 else 973 previous_arm_half = false; 974 } 975 else { 976 // plain: address pcrel length extern type scattered symbolnum/section 977 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n", 978 (unsigned int)r_address, r_pcrel, r_length, r_extern, 979 r_type, r_symbolnum); 980 } 981 } 982 } 983 } 984 985 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { 986 const uint64_t cputype = O->getHeader().cputype; 987 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 988 if (Dysymtab.nextrel != 0) { 989 outs() << "External relocation information " << Dysymtab.nextrel 990 << " entries"; 991 outs() << "\naddress pcrel length extern type scattered " 992 "symbolnum/value\n"; 993 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, 994 verbose); 995 } 996 if (Dysymtab.nlocrel != 0) { 997 outs() << format("Local relocation information %u entries", 998 Dysymtab.nlocrel); 999 outs() << "\naddress pcrel length extern type scattered " 1000 "symbolnum/value\n"; 1001 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, 1002 verbose); 1003 } 1004 for (const auto &Load : O->load_commands()) { 1005 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 1006 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 1007 for (unsigned J = 0; J < Seg.nsects; ++J) { 1008 const MachO::section_64 Sec = O->getSection64(Load, J); 1009 if (Sec.nreloc != 0) { 1010 DataRefImpl DRI; 1011 DRI.d.a = J; 1012 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1013 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1014 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1015 << format(") %u entries", Sec.nreloc); 1016 else 1017 outs() << "Relocation information (" << SegName << ",?) " 1018 << format("%u entries", Sec.nreloc); 1019 outs() << "\naddress pcrel length extern type scattered " 1020 "symbolnum/value\n"; 1021 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1022 O->section_rel_end(DRI), cputype, verbose); 1023 } 1024 } 1025 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1026 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 1027 for (unsigned J = 0; J < Seg.nsects; ++J) { 1028 const MachO::section Sec = O->getSection(Load, J); 1029 if (Sec.nreloc != 0) { 1030 DataRefImpl DRI; 1031 DRI.d.a = J; 1032 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1033 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1034 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1035 << format(") %u entries", Sec.nreloc); 1036 else 1037 outs() << "Relocation information (" << SegName << ",?) " 1038 << format("%u entries", Sec.nreloc); 1039 outs() << "\naddress pcrel length extern type scattered " 1040 "symbolnum/value\n"; 1041 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1042 O->section_rel_end(DRI), cputype, verbose); 1043 } 1044 } 1045 } 1046 } 1047 } 1048 1049 static void PrintFunctionStarts(MachOObjectFile *O) { 1050 uint64_t BaseSegmentAddress = 0; 1051 for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) { 1052 if (Command.C.cmd == MachO::LC_SEGMENT) { 1053 MachO::segment_command SLC = O->getSegmentLoadCommand(Command); 1054 if (StringRef(SLC.segname) == "__TEXT") { 1055 BaseSegmentAddress = SLC.vmaddr; 1056 break; 1057 } 1058 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 1059 MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command); 1060 if (StringRef(SLC.segname) == "__TEXT") { 1061 BaseSegmentAddress = SLC.vmaddr; 1062 break; 1063 } 1064 } 1065 } 1066 1067 SmallVector<uint64_t, 8> FunctionStarts; 1068 for (const MachOObjectFile::LoadCommandInfo &LC : O->load_commands()) { 1069 if (LC.C.cmd == MachO::LC_FUNCTION_STARTS) { 1070 MachO::linkedit_data_command FunctionStartsLC = 1071 O->getLinkeditDataLoadCommand(LC); 1072 O->ReadULEB128s(FunctionStartsLC.dataoff, FunctionStarts); 1073 break; 1074 } 1075 } 1076 1077 for (uint64_t S : FunctionStarts) { 1078 uint64_t Addr = BaseSegmentAddress + S; 1079 if (O->is64Bit()) 1080 outs() << format("%016" PRIx64, Addr) << "\n"; 1081 else 1082 outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr)) << "\n"; 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); 1210 if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 1211 outs() << ", weak"; 1212 if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 1213 outs() << ", reexport"; 1214 if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 1215 outs() << ", upward"; 1216 if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 1217 outs() << ", lazy"; 1218 outs() << ")\n"; 1219 } 1220 } else { 1221 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 1222 if (Load.C.cmd == MachO::LC_ID_DYLIB) 1223 outs() << "LC_ID_DYLIB "; 1224 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 1225 outs() << "LC_LOAD_DYLIB "; 1226 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 1227 outs() << "LC_LOAD_WEAK_DYLIB "; 1228 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 1229 outs() << "LC_LAZY_LOAD_DYLIB "; 1230 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 1231 outs() << "LC_REEXPORT_DYLIB "; 1232 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 1233 outs() << "LC_LOAD_UPWARD_DYLIB "; 1234 else 1235 outs() << "LC_??? "; 1236 outs() << "command " << Index++ << "\n"; 1237 } 1238 } 1239 } 1240 } 1241 1242 static void printRpaths(MachOObjectFile *O) { 1243 for (const auto &Command : O->load_commands()) { 1244 if (Command.C.cmd == MachO::LC_RPATH) { 1245 auto Rpath = O->getRpathCommand(Command); 1246 const char *P = (const char *)(Command.Ptr) + Rpath.path; 1247 outs() << P << "\n"; 1248 } 1249 } 1250 } 1251 1252 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 1253 1254 static void CreateSymbolAddressMap(MachOObjectFile *O, 1255 SymbolAddressMap *AddrMap) { 1256 // Create a map of symbol addresses to symbol names. 1257 const StringRef FileName = O->getFileName(); 1258 for (const SymbolRef &Symbol : O->symbols()) { 1259 SymbolRef::Type ST = unwrapOrError(Symbol.getType(), FileName); 1260 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 1261 ST == SymbolRef::ST_Other) { 1262 uint64_t Address = cantFail(Symbol.getValue()); 1263 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 1264 if (!SymName.startswith(".objc")) 1265 (*AddrMap)[Address] = SymName; 1266 } 1267 } 1268 } 1269 1270 // GuessSymbolName is passed the address of what might be a symbol and a 1271 // pointer to the SymbolAddressMap. It returns the name of a symbol 1272 // with that address or nullptr if no symbol is found with that address. 1273 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 1274 const char *SymbolName = nullptr; 1275 // A DenseMap can't lookup up some values. 1276 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 1277 StringRef name = AddrMap->lookup(value); 1278 if (!name.empty()) 1279 SymbolName = name.data(); 1280 } 1281 return SymbolName; 1282 } 1283 1284 static void DumpCstringChar(const char c) { 1285 char p[2]; 1286 p[0] = c; 1287 p[1] = '\0'; 1288 outs().write_escaped(p); 1289 } 1290 1291 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 1292 uint32_t sect_size, uint64_t sect_addr, 1293 bool print_addresses) { 1294 for (uint32_t i = 0; i < sect_size; i++) { 1295 if (print_addresses) { 1296 if (O->is64Bit()) 1297 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1298 else 1299 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1300 } 1301 for (; i < sect_size && sect[i] != '\0'; i++) 1302 DumpCstringChar(sect[i]); 1303 if (i < sect_size && sect[i] == '\0') 1304 outs() << "\n"; 1305 } 1306 } 1307 1308 static void DumpLiteral4(uint32_t l, float f) { 1309 outs() << format("0x%08" PRIx32, l); 1310 if ((l & 0x7f800000) != 0x7f800000) 1311 outs() << format(" (%.16e)\n", f); 1312 else { 1313 if (l == 0x7f800000) 1314 outs() << " (+Infinity)\n"; 1315 else if (l == 0xff800000) 1316 outs() << " (-Infinity)\n"; 1317 else if ((l & 0x00400000) == 0x00400000) 1318 outs() << " (non-signaling Not-a-Number)\n"; 1319 else 1320 outs() << " (signaling Not-a-Number)\n"; 1321 } 1322 } 1323 1324 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 1325 uint32_t sect_size, uint64_t sect_addr, 1326 bool print_addresses) { 1327 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 1328 if (print_addresses) { 1329 if (O->is64Bit()) 1330 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1331 else 1332 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1333 } 1334 float f; 1335 memcpy(&f, sect + i, sizeof(float)); 1336 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1337 sys::swapByteOrder(f); 1338 uint32_t l; 1339 memcpy(&l, sect + i, sizeof(uint32_t)); 1340 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1341 sys::swapByteOrder(l); 1342 DumpLiteral4(l, f); 1343 } 1344 } 1345 1346 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 1347 double d) { 1348 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 1349 uint32_t Hi, Lo; 1350 Hi = (O->isLittleEndian()) ? l1 : l0; 1351 Lo = (O->isLittleEndian()) ? l0 : l1; 1352 1353 // Hi is the high word, so this is equivalent to if(isfinite(d)) 1354 if ((Hi & 0x7ff00000) != 0x7ff00000) 1355 outs() << format(" (%.16e)\n", d); 1356 else { 1357 if (Hi == 0x7ff00000 && Lo == 0) 1358 outs() << " (+Infinity)\n"; 1359 else if (Hi == 0xfff00000 && Lo == 0) 1360 outs() << " (-Infinity)\n"; 1361 else if ((Hi & 0x00080000) == 0x00080000) 1362 outs() << " (non-signaling Not-a-Number)\n"; 1363 else 1364 outs() << " (signaling Not-a-Number)\n"; 1365 } 1366 } 1367 1368 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 1369 uint32_t sect_size, uint64_t sect_addr, 1370 bool print_addresses) { 1371 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 1372 if (print_addresses) { 1373 if (O->is64Bit()) 1374 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1375 else 1376 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1377 } 1378 double d; 1379 memcpy(&d, sect + i, sizeof(double)); 1380 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1381 sys::swapByteOrder(d); 1382 uint32_t l0, l1; 1383 memcpy(&l0, sect + i, sizeof(uint32_t)); 1384 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1385 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1386 sys::swapByteOrder(l0); 1387 sys::swapByteOrder(l1); 1388 } 1389 DumpLiteral8(O, l0, l1, d); 1390 } 1391 } 1392 1393 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 1394 outs() << format("0x%08" PRIx32, l0) << " "; 1395 outs() << format("0x%08" PRIx32, l1) << " "; 1396 outs() << format("0x%08" PRIx32, l2) << " "; 1397 outs() << format("0x%08" PRIx32, l3) << "\n"; 1398 } 1399 1400 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 1401 uint32_t sect_size, uint64_t sect_addr, 1402 bool print_addresses) { 1403 for (uint32_t i = 0; i < sect_size; i += 16) { 1404 if (print_addresses) { 1405 if (O->is64Bit()) 1406 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1407 else 1408 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1409 } 1410 uint32_t l0, l1, l2, l3; 1411 memcpy(&l0, sect + i, sizeof(uint32_t)); 1412 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1413 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 1414 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1415 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1416 sys::swapByteOrder(l0); 1417 sys::swapByteOrder(l1); 1418 sys::swapByteOrder(l2); 1419 sys::swapByteOrder(l3); 1420 } 1421 DumpLiteral16(l0, l1, l2, l3); 1422 } 1423 } 1424 1425 static void DumpLiteralPointerSection(MachOObjectFile *O, 1426 const SectionRef &Section, 1427 const char *sect, uint32_t sect_size, 1428 uint64_t sect_addr, 1429 bool print_addresses) { 1430 // Collect the literal sections in this Mach-O file. 1431 std::vector<SectionRef> LiteralSections; 1432 for (const SectionRef &Section : O->sections()) { 1433 DataRefImpl Ref = Section.getRawDataRefImpl(); 1434 uint32_t section_type; 1435 if (O->is64Bit()) { 1436 const MachO::section_64 Sec = O->getSection64(Ref); 1437 section_type = Sec.flags & MachO::SECTION_TYPE; 1438 } else { 1439 const MachO::section Sec = O->getSection(Ref); 1440 section_type = Sec.flags & MachO::SECTION_TYPE; 1441 } 1442 if (section_type == MachO::S_CSTRING_LITERALS || 1443 section_type == MachO::S_4BYTE_LITERALS || 1444 section_type == MachO::S_8BYTE_LITERALS || 1445 section_type == MachO::S_16BYTE_LITERALS) 1446 LiteralSections.push_back(Section); 1447 } 1448 1449 // Set the size of the literal pointer. 1450 uint32_t lp_size = O->is64Bit() ? 8 : 4; 1451 1452 // Collect the external relocation symbols for the literal pointers. 1453 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1454 for (const RelocationRef &Reloc : Section.relocations()) { 1455 DataRefImpl Rel; 1456 MachO::any_relocation_info RE; 1457 bool isExtern = false; 1458 Rel = Reloc.getRawDataRefImpl(); 1459 RE = O->getRelocation(Rel); 1460 isExtern = O->getPlainRelocationExternal(RE); 1461 if (isExtern) { 1462 uint64_t RelocOffset = Reloc.getOffset(); 1463 symbol_iterator RelocSym = Reloc.getSymbol(); 1464 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1465 } 1466 } 1467 array_pod_sort(Relocs.begin(), Relocs.end()); 1468 1469 // Dump each literal pointer. 1470 for (uint32_t i = 0; i < sect_size; i += lp_size) { 1471 if (print_addresses) { 1472 if (O->is64Bit()) 1473 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1474 else 1475 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1476 } 1477 uint64_t lp; 1478 if (O->is64Bit()) { 1479 memcpy(&lp, sect + i, sizeof(uint64_t)); 1480 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1481 sys::swapByteOrder(lp); 1482 } else { 1483 uint32_t li; 1484 memcpy(&li, sect + i, sizeof(uint32_t)); 1485 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1486 sys::swapByteOrder(li); 1487 lp = li; 1488 } 1489 1490 // First look for an external relocation entry for this literal pointer. 1491 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1492 return P.first == i; 1493 }); 1494 if (Reloc != Relocs.end()) { 1495 symbol_iterator RelocSym = Reloc->second; 1496 StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName()); 1497 outs() << "external relocation entry for symbol:" << SymName << "\n"; 1498 continue; 1499 } 1500 1501 // For local references see what the section the literal pointer points to. 1502 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 1503 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 1504 }); 1505 if (Sect == LiteralSections.end()) { 1506 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 1507 continue; 1508 } 1509 1510 uint64_t SectAddress = Sect->getAddress(); 1511 uint64_t SectSize = Sect->getSize(); 1512 1513 StringRef SectName; 1514 Expected<StringRef> SectNameOrErr = Sect->getName(); 1515 if (SectNameOrErr) 1516 SectName = *SectNameOrErr; 1517 else 1518 consumeError(SectNameOrErr.takeError()); 1519 1520 DataRefImpl Ref = Sect->getRawDataRefImpl(); 1521 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 1522 outs() << SegmentName << ":" << SectName << ":"; 1523 1524 uint32_t section_type; 1525 if (O->is64Bit()) { 1526 const MachO::section_64 Sec = O->getSection64(Ref); 1527 section_type = Sec.flags & MachO::SECTION_TYPE; 1528 } else { 1529 const MachO::section Sec = O->getSection(Ref); 1530 section_type = Sec.flags & MachO::SECTION_TYPE; 1531 } 1532 1533 StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName()); 1534 1535 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 1536 1537 switch (section_type) { 1538 case MachO::S_CSTRING_LITERALS: 1539 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 1540 i++) { 1541 DumpCstringChar(Contents[i]); 1542 } 1543 outs() << "\n"; 1544 break; 1545 case MachO::S_4BYTE_LITERALS: 1546 float f; 1547 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 1548 uint32_t l; 1549 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 1550 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1551 sys::swapByteOrder(f); 1552 sys::swapByteOrder(l); 1553 } 1554 DumpLiteral4(l, f); 1555 break; 1556 case MachO::S_8BYTE_LITERALS: { 1557 double d; 1558 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 1559 uint32_t l0, l1; 1560 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1561 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1562 sizeof(uint32_t)); 1563 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1564 sys::swapByteOrder(f); 1565 sys::swapByteOrder(l0); 1566 sys::swapByteOrder(l1); 1567 } 1568 DumpLiteral8(O, l0, l1, d); 1569 break; 1570 } 1571 case MachO::S_16BYTE_LITERALS: { 1572 uint32_t l0, l1, l2, l3; 1573 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1574 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1575 sizeof(uint32_t)); 1576 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 1577 sizeof(uint32_t)); 1578 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 1579 sizeof(uint32_t)); 1580 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1581 sys::swapByteOrder(l0); 1582 sys::swapByteOrder(l1); 1583 sys::swapByteOrder(l2); 1584 sys::swapByteOrder(l3); 1585 } 1586 DumpLiteral16(l0, l1, l2, l3); 1587 break; 1588 } 1589 } 1590 } 1591 } 1592 1593 static void DumpInitTermPointerSection(MachOObjectFile *O, 1594 const SectionRef &Section, 1595 const char *sect, 1596 uint32_t sect_size, uint64_t sect_addr, 1597 SymbolAddressMap *AddrMap, 1598 bool verbose) { 1599 uint32_t stride; 1600 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 1601 1602 // Collect the external relocation symbols for the pointers. 1603 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1604 for (const RelocationRef &Reloc : Section.relocations()) { 1605 DataRefImpl Rel; 1606 MachO::any_relocation_info RE; 1607 bool isExtern = false; 1608 Rel = Reloc.getRawDataRefImpl(); 1609 RE = O->getRelocation(Rel); 1610 isExtern = O->getPlainRelocationExternal(RE); 1611 if (isExtern) { 1612 uint64_t RelocOffset = Reloc.getOffset(); 1613 symbol_iterator RelocSym = Reloc.getSymbol(); 1614 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1615 } 1616 } 1617 array_pod_sort(Relocs.begin(), Relocs.end()); 1618 1619 for (uint32_t i = 0; i < sect_size; i += stride) { 1620 const char *SymbolName = nullptr; 1621 uint64_t p; 1622 if (O->is64Bit()) { 1623 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 1624 uint64_t pointer_value; 1625 memcpy(&pointer_value, sect + i, stride); 1626 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1627 sys::swapByteOrder(pointer_value); 1628 outs() << format("0x%016" PRIx64, pointer_value); 1629 p = pointer_value; 1630 } else { 1631 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 1632 uint32_t pointer_value; 1633 memcpy(&pointer_value, sect + i, stride); 1634 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1635 sys::swapByteOrder(pointer_value); 1636 outs() << format("0x%08" PRIx32, pointer_value); 1637 p = pointer_value; 1638 } 1639 if (verbose) { 1640 // First look for an external relocation entry for this pointer. 1641 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1642 return P.first == i; 1643 }); 1644 if (Reloc != Relocs.end()) { 1645 symbol_iterator RelocSym = Reloc->second; 1646 outs() << " " << unwrapOrError(RelocSym->getName(), O->getFileName()); 1647 } else { 1648 SymbolName = GuessSymbolName(p, AddrMap); 1649 if (SymbolName) 1650 outs() << " " << SymbolName; 1651 } 1652 } 1653 outs() << "\n"; 1654 } 1655 } 1656 1657 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 1658 uint32_t size, uint64_t addr) { 1659 uint32_t cputype = O->getHeader().cputype; 1660 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 1661 uint32_t j; 1662 for (uint32_t i = 0; i < size; i += j, addr += j) { 1663 if (O->is64Bit()) 1664 outs() << format("%016" PRIx64, addr) << "\t"; 1665 else 1666 outs() << format("%08" PRIx64, addr) << "\t"; 1667 for (j = 0; j < 16 && i + j < size; j++) { 1668 uint8_t byte_word = *(sect + i + j); 1669 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1670 } 1671 outs() << "\n"; 1672 } 1673 } else { 1674 uint32_t j; 1675 for (uint32_t i = 0; i < size; i += j, addr += j) { 1676 if (O->is64Bit()) 1677 outs() << format("%016" PRIx64, addr) << "\t"; 1678 else 1679 outs() << format("%08" PRIx64, addr) << "\t"; 1680 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 1681 j += sizeof(int32_t)) { 1682 if (i + j + sizeof(int32_t) <= size) { 1683 uint32_t long_word; 1684 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1685 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1686 sys::swapByteOrder(long_word); 1687 outs() << format("%08" PRIx32, long_word) << " "; 1688 } else { 1689 for (uint32_t k = 0; i + j + k < size; k++) { 1690 uint8_t byte_word = *(sect + i + j + k); 1691 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1692 } 1693 } 1694 } 1695 outs() << "\n"; 1696 } 1697 } 1698 } 1699 1700 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1701 StringRef DisSegName, StringRef DisSectName); 1702 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1703 uint32_t size, uint32_t addr); 1704 #ifdef LLVM_HAVE_LIBXAR 1705 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 1706 uint32_t size, bool verbose, 1707 bool PrintXarHeader, bool PrintXarFileHeaders, 1708 std::string XarMemberName); 1709 #endif // defined(LLVM_HAVE_LIBXAR) 1710 1711 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1712 bool verbose) { 1713 SymbolAddressMap AddrMap; 1714 if (verbose) 1715 CreateSymbolAddressMap(O, &AddrMap); 1716 1717 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1718 StringRef DumpSection = FilterSections[i]; 1719 std::pair<StringRef, StringRef> DumpSegSectName; 1720 DumpSegSectName = DumpSection.split(','); 1721 StringRef DumpSegName, DumpSectName; 1722 if (!DumpSegSectName.second.empty()) { 1723 DumpSegName = DumpSegSectName.first; 1724 DumpSectName = DumpSegSectName.second; 1725 } else { 1726 DumpSegName = ""; 1727 DumpSectName = DumpSegSectName.first; 1728 } 1729 for (const SectionRef &Section : O->sections()) { 1730 StringRef SectName; 1731 Expected<StringRef> SecNameOrErr = Section.getName(); 1732 if (SecNameOrErr) 1733 SectName = *SecNameOrErr; 1734 else 1735 consumeError(SecNameOrErr.takeError()); 1736 1737 if (!DumpSection.empty()) 1738 FoundSectionSet.insert(DumpSection); 1739 1740 DataRefImpl Ref = Section.getRawDataRefImpl(); 1741 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1742 if ((DumpSegName.empty() || SegName == DumpSegName) && 1743 (SectName == DumpSectName)) { 1744 1745 uint32_t section_flags; 1746 if (O->is64Bit()) { 1747 const MachO::section_64 Sec = O->getSection64(Ref); 1748 section_flags = Sec.flags; 1749 1750 } else { 1751 const MachO::section Sec = O->getSection(Ref); 1752 section_flags = Sec.flags; 1753 } 1754 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1755 1756 StringRef BytesStr = 1757 unwrapOrError(Section.getContents(), O->getFileName()); 1758 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1759 uint32_t sect_size = BytesStr.size(); 1760 uint64_t sect_addr = Section.getAddress(); 1761 1762 if (LeadingHeaders) 1763 outs() << "Contents of (" << SegName << "," << SectName 1764 << ") section\n"; 1765 1766 if (verbose) { 1767 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1768 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1769 DisassembleMachO(Filename, O, SegName, SectName); 1770 continue; 1771 } 1772 if (SegName == "__TEXT" && SectName == "__info_plist") { 1773 outs() << sect; 1774 continue; 1775 } 1776 if (SegName == "__OBJC" && SectName == "__protocol") { 1777 DumpProtocolSection(O, sect, sect_size, sect_addr); 1778 continue; 1779 } 1780 #ifdef LLVM_HAVE_LIBXAR 1781 if (SegName == "__LLVM" && SectName == "__bundle") { 1782 DumpBitcodeSection(O, sect, sect_size, verbose, SymbolicOperands, 1783 ArchiveHeaders, ""); 1784 continue; 1785 } 1786 #endif // defined(LLVM_HAVE_LIBXAR) 1787 switch (section_type) { 1788 case MachO::S_REGULAR: 1789 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1790 break; 1791 case MachO::S_ZEROFILL: 1792 outs() << "zerofill section and has no contents in the file\n"; 1793 break; 1794 case MachO::S_CSTRING_LITERALS: 1795 DumpCstringSection(O, sect, sect_size, sect_addr, LeadingAddr); 1796 break; 1797 case MachO::S_4BYTE_LITERALS: 1798 DumpLiteral4Section(O, sect, sect_size, sect_addr, LeadingAddr); 1799 break; 1800 case MachO::S_8BYTE_LITERALS: 1801 DumpLiteral8Section(O, sect, sect_size, sect_addr, LeadingAddr); 1802 break; 1803 case MachO::S_16BYTE_LITERALS: 1804 DumpLiteral16Section(O, sect, sect_size, sect_addr, LeadingAddr); 1805 break; 1806 case MachO::S_LITERAL_POINTERS: 1807 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1808 LeadingAddr); 1809 break; 1810 case MachO::S_MOD_INIT_FUNC_POINTERS: 1811 case MachO::S_MOD_TERM_FUNC_POINTERS: 1812 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr, 1813 &AddrMap, verbose); 1814 break; 1815 default: 1816 outs() << "Unknown section type (" 1817 << format("0x%08" PRIx32, section_type) << ")\n"; 1818 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1819 break; 1820 } 1821 } else { 1822 if (section_type == MachO::S_ZEROFILL) 1823 outs() << "zerofill section and has no contents in the file\n"; 1824 else 1825 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1826 } 1827 } 1828 } 1829 } 1830 } 1831 1832 static void DumpInfoPlistSectionContents(StringRef Filename, 1833 MachOObjectFile *O) { 1834 for (const SectionRef &Section : O->sections()) { 1835 StringRef SectName; 1836 Expected<StringRef> SecNameOrErr = Section.getName(); 1837 if (SecNameOrErr) 1838 SectName = *SecNameOrErr; 1839 else 1840 consumeError(SecNameOrErr.takeError()); 1841 1842 DataRefImpl Ref = Section.getRawDataRefImpl(); 1843 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1844 if (SegName == "__TEXT" && SectName == "__info_plist") { 1845 if (LeadingHeaders) 1846 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1847 StringRef BytesStr = 1848 unwrapOrError(Section.getContents(), O->getFileName()); 1849 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1850 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 1851 return; 1852 } 1853 } 1854 } 1855 1856 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1857 // and if it is and there is a list of architecture flags is specified then 1858 // check to make sure this Mach-O file is one of those architectures or all 1859 // architectures were specified. If not then an error is generated and this 1860 // routine returns false. Else it returns true. 1861 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1862 auto *MachO = dyn_cast<MachOObjectFile>(O); 1863 1864 if (!MachO || ArchAll || ArchFlags.empty()) 1865 return true; 1866 1867 MachO::mach_header H; 1868 MachO::mach_header_64 H_64; 1869 Triple T; 1870 const char *McpuDefault, *ArchFlag; 1871 if (MachO->is64Bit()) { 1872 H_64 = MachO->MachOObjectFile::getHeader64(); 1873 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 1874 &McpuDefault, &ArchFlag); 1875 } else { 1876 H = MachO->MachOObjectFile::getHeader(); 1877 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 1878 &McpuDefault, &ArchFlag); 1879 } 1880 const std::string ArchFlagName(ArchFlag); 1881 if (!llvm::is_contained(ArchFlags, ArchFlagName)) { 1882 WithColor::error(errs(), "llvm-objdump") 1883 << Filename << ": no architecture specified.\n"; 1884 return false; 1885 } 1886 return true; 1887 } 1888 1889 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 1890 1891 // ProcessMachO() is passed a single opened Mach-O file, which may be an 1892 // archive member and or in a slice of a universal file. It prints the 1893 // the file name and header info and then processes it according to the 1894 // command line options. 1895 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 1896 StringRef ArchiveMemberName = StringRef(), 1897 StringRef ArchitectureName = StringRef()) { 1898 // If we are doing some processing here on the Mach-O file print the header 1899 // info. And don't print it otherwise like in the case of printing the 1900 // UniversalHeaders or ArchiveHeaders. 1901 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || 1902 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || 1903 DataInCode || FunctionStarts || LinkOptHints || DylibsUsed || DylibId || 1904 Rpaths || ObjcMetaData || (!FilterSections.empty())) { 1905 if (LeadingHeaders) { 1906 outs() << Name; 1907 if (!ArchiveMemberName.empty()) 1908 outs() << '(' << ArchiveMemberName << ')'; 1909 if (!ArchitectureName.empty()) 1910 outs() << " (architecture " << ArchitectureName << ")"; 1911 outs() << ":\n"; 1912 } 1913 } 1914 // To use the report_error() form with an ArchiveName and FileName set 1915 // these up based on what is passed for Name and ArchiveMemberName. 1916 StringRef ArchiveName; 1917 StringRef FileName; 1918 if (!ArchiveMemberName.empty()) { 1919 ArchiveName = Name; 1920 FileName = ArchiveMemberName; 1921 } else { 1922 ArchiveName = StringRef(); 1923 FileName = Name; 1924 } 1925 1926 // If we need the symbol table to do the operation then check it here to 1927 // produce a good error message as to where the Mach-O file comes from in 1928 // the error message. 1929 if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo) 1930 if (Error Err = MachOOF->checkSymbolTable()) 1931 reportError(std::move(Err), FileName, ArchiveName, ArchitectureName); 1932 1933 if (DisassembleAll) { 1934 for (const SectionRef &Section : MachOOF->sections()) { 1935 StringRef SectName; 1936 if (Expected<StringRef> NameOrErr = Section.getName()) 1937 SectName = *NameOrErr; 1938 else 1939 consumeError(NameOrErr.takeError()); 1940 1941 if (SectName.equals("__text")) { 1942 DataRefImpl Ref = Section.getRawDataRefImpl(); 1943 StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref); 1944 DisassembleMachO(FileName, MachOOF, SegName, SectName); 1945 } 1946 } 1947 } 1948 else if (Disassemble) { 1949 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE && 1950 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64) 1951 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text"); 1952 else 1953 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 1954 } 1955 if (IndirectSymbols) 1956 PrintIndirectSymbols(MachOOF, Verbose); 1957 if (DataInCode) 1958 PrintDataInCodeTable(MachOOF, Verbose); 1959 if (FunctionStarts) 1960 PrintFunctionStarts(MachOOF); 1961 if (LinkOptHints) 1962 PrintLinkOptHints(MachOOF); 1963 if (Relocations) 1964 PrintRelocations(MachOOF, Verbose); 1965 if (SectionHeaders) 1966 printSectionHeaders(MachOOF); 1967 if (SectionContents) 1968 printSectionContents(MachOOF); 1969 if (!FilterSections.empty()) 1970 DumpSectionContents(FileName, MachOOF, Verbose); 1971 if (InfoPlist) 1972 DumpInfoPlistSectionContents(FileName, MachOOF); 1973 if (DylibsUsed) 1974 PrintDylibs(MachOOF, false); 1975 if (DylibId) 1976 PrintDylibs(MachOOF, true); 1977 if (SymbolTable) 1978 printSymbolTable(MachOOF, ArchiveName, ArchitectureName); 1979 if (UnwindInfo) 1980 printMachOUnwindInfo(MachOOF); 1981 if (PrivateHeaders) { 1982 printMachOFileHeader(MachOOF); 1983 printMachOLoadCommands(MachOOF); 1984 } 1985 if (FirstPrivateHeader) 1986 printMachOFileHeader(MachOOF); 1987 if (ObjcMetaData) 1988 printObjcMetaData(MachOOF, Verbose); 1989 if (ExportsTrie) 1990 printExportsTrie(MachOOF); 1991 if (Rebase) 1992 printRebaseTable(MachOOF); 1993 if (Rpaths) 1994 printRpaths(MachOOF); 1995 if (Bind) 1996 printBindTable(MachOOF); 1997 if (LazyBind) 1998 printLazyBindTable(MachOOF); 1999 if (WeakBind) 2000 printWeakBindTable(MachOOF); 2001 2002 if (DwarfDumpType != DIDT_Null) { 2003 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF); 2004 // Dump the complete DWARF structure. 2005 DIDumpOptions DumpOpts; 2006 DumpOpts.DumpType = DwarfDumpType; 2007 DICtx->dump(outs(), DumpOpts); 2008 } 2009 } 2010 2011 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 2012 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 2013 outs() << " cputype (" << cputype << ")\n"; 2014 outs() << " cpusubtype (" << cpusubtype << ")\n"; 2015 } 2016 2017 // printCPUType() helps print_fat_headers by printing the cputype and 2018 // pusubtype (symbolically for the one's it knows about). 2019 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 2020 switch (cputype) { 2021 case MachO::CPU_TYPE_I386: 2022 switch (cpusubtype) { 2023 case MachO::CPU_SUBTYPE_I386_ALL: 2024 outs() << " cputype CPU_TYPE_I386\n"; 2025 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 2026 break; 2027 default: 2028 printUnknownCPUType(cputype, cpusubtype); 2029 break; 2030 } 2031 break; 2032 case MachO::CPU_TYPE_X86_64: 2033 switch (cpusubtype) { 2034 case MachO::CPU_SUBTYPE_X86_64_ALL: 2035 outs() << " cputype CPU_TYPE_X86_64\n"; 2036 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 2037 break; 2038 case MachO::CPU_SUBTYPE_X86_64_H: 2039 outs() << " cputype CPU_TYPE_X86_64\n"; 2040 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 2041 break; 2042 default: 2043 printUnknownCPUType(cputype, cpusubtype); 2044 break; 2045 } 2046 break; 2047 case MachO::CPU_TYPE_ARM: 2048 switch (cpusubtype) { 2049 case MachO::CPU_SUBTYPE_ARM_ALL: 2050 outs() << " cputype CPU_TYPE_ARM\n"; 2051 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 2052 break; 2053 case MachO::CPU_SUBTYPE_ARM_V4T: 2054 outs() << " cputype CPU_TYPE_ARM\n"; 2055 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 2056 break; 2057 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2058 outs() << " cputype CPU_TYPE_ARM\n"; 2059 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 2060 break; 2061 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2062 outs() << " cputype CPU_TYPE_ARM\n"; 2063 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 2064 break; 2065 case MachO::CPU_SUBTYPE_ARM_V6: 2066 outs() << " cputype CPU_TYPE_ARM\n"; 2067 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 2068 break; 2069 case MachO::CPU_SUBTYPE_ARM_V6M: 2070 outs() << " cputype CPU_TYPE_ARM\n"; 2071 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 2072 break; 2073 case MachO::CPU_SUBTYPE_ARM_V7: 2074 outs() << " cputype CPU_TYPE_ARM\n"; 2075 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 2076 break; 2077 case MachO::CPU_SUBTYPE_ARM_V7EM: 2078 outs() << " cputype CPU_TYPE_ARM\n"; 2079 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 2080 break; 2081 case MachO::CPU_SUBTYPE_ARM_V7K: 2082 outs() << " cputype CPU_TYPE_ARM\n"; 2083 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 2084 break; 2085 case MachO::CPU_SUBTYPE_ARM_V7M: 2086 outs() << " cputype CPU_TYPE_ARM\n"; 2087 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 2088 break; 2089 case MachO::CPU_SUBTYPE_ARM_V7S: 2090 outs() << " cputype CPU_TYPE_ARM\n"; 2091 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 2092 break; 2093 default: 2094 printUnknownCPUType(cputype, cpusubtype); 2095 break; 2096 } 2097 break; 2098 case MachO::CPU_TYPE_ARM64: 2099 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2100 case MachO::CPU_SUBTYPE_ARM64_ALL: 2101 outs() << " cputype CPU_TYPE_ARM64\n"; 2102 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 2103 break; 2104 case MachO::CPU_SUBTYPE_ARM64_V8: 2105 outs() << " cputype CPU_TYPE_ARM64\n"; 2106 outs() << " cpusubtype CPU_SUBTYPE_ARM64_V8\n"; 2107 break; 2108 case MachO::CPU_SUBTYPE_ARM64E: 2109 outs() << " cputype CPU_TYPE_ARM64\n"; 2110 outs() << " cpusubtype CPU_SUBTYPE_ARM64E\n"; 2111 break; 2112 default: 2113 printUnknownCPUType(cputype, cpusubtype); 2114 break; 2115 } 2116 break; 2117 case MachO::CPU_TYPE_ARM64_32: 2118 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2119 case MachO::CPU_SUBTYPE_ARM64_32_V8: 2120 outs() << " cputype CPU_TYPE_ARM64_32\n"; 2121 outs() << " cpusubtype CPU_SUBTYPE_ARM64_32_V8\n"; 2122 break; 2123 default: 2124 printUnknownCPUType(cputype, cpusubtype); 2125 break; 2126 } 2127 break; 2128 default: 2129 printUnknownCPUType(cputype, cpusubtype); 2130 break; 2131 } 2132 } 2133 2134 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 2135 bool verbose) { 2136 outs() << "Fat headers\n"; 2137 if (verbose) { 2138 if (UB->getMagic() == MachO::FAT_MAGIC) 2139 outs() << "fat_magic FAT_MAGIC\n"; 2140 else // UB->getMagic() == MachO::FAT_MAGIC_64 2141 outs() << "fat_magic FAT_MAGIC_64\n"; 2142 } else 2143 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 2144 2145 uint32_t nfat_arch = UB->getNumberOfObjects(); 2146 StringRef Buf = UB->getData(); 2147 uint64_t size = Buf.size(); 2148 uint64_t big_size = sizeof(struct MachO::fat_header) + 2149 nfat_arch * sizeof(struct MachO::fat_arch); 2150 outs() << "nfat_arch " << UB->getNumberOfObjects(); 2151 if (nfat_arch == 0) 2152 outs() << " (malformed, contains zero architecture types)\n"; 2153 else if (big_size > size) 2154 outs() << " (malformed, architectures past end of file)\n"; 2155 else 2156 outs() << "\n"; 2157 2158 for (uint32_t i = 0; i < nfat_arch; ++i) { 2159 MachOUniversalBinary::ObjectForArch OFA(UB, i); 2160 uint32_t cputype = OFA.getCPUType(); 2161 uint32_t cpusubtype = OFA.getCPUSubType(); 2162 outs() << "architecture "; 2163 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 2164 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 2165 uint32_t other_cputype = other_OFA.getCPUType(); 2166 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 2167 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 2168 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 2169 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 2170 outs() << "(illegal duplicate architecture) "; 2171 break; 2172 } 2173 } 2174 if (verbose) { 2175 outs() << OFA.getArchFlagName() << "\n"; 2176 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2177 } else { 2178 outs() << i << "\n"; 2179 outs() << " cputype " << cputype << "\n"; 2180 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 2181 << "\n"; 2182 } 2183 if (verbose && 2184 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 2185 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 2186 else 2187 outs() << " capabilities " 2188 << format("0x%" PRIx32, 2189 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 2190 outs() << " offset " << OFA.getOffset(); 2191 if (OFA.getOffset() > size) 2192 outs() << " (past end of file)"; 2193 if (OFA.getOffset() % (1ull << OFA.getAlign()) != 0) 2194 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 2195 outs() << "\n"; 2196 outs() << " size " << OFA.getSize(); 2197 big_size = OFA.getOffset() + OFA.getSize(); 2198 if (big_size > size) 2199 outs() << " (past end of file)"; 2200 outs() << "\n"; 2201 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 2202 << ")\n"; 2203 } 2204 } 2205 2206 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 2207 size_t ChildIndex, bool verbose, 2208 bool print_offset, 2209 StringRef ArchitectureName = StringRef()) { 2210 if (print_offset) 2211 outs() << C.getChildOffset() << "\t"; 2212 sys::fs::perms Mode = 2213 unwrapOrError(C.getAccessMode(), getFileNameForError(C, ChildIndex), 2214 Filename, ArchitectureName); 2215 if (verbose) { 2216 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 2217 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 2218 outs() << "-"; 2219 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 2220 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 2221 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 2222 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 2223 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 2224 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 2225 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 2226 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 2227 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 2228 } else { 2229 outs() << format("0%o ", Mode); 2230 } 2231 2232 outs() << format("%3d/%-3d %5" PRId64 " ", 2233 unwrapOrError(C.getUID(), getFileNameForError(C, ChildIndex), 2234 Filename, ArchitectureName), 2235 unwrapOrError(C.getGID(), getFileNameForError(C, ChildIndex), 2236 Filename, ArchitectureName), 2237 unwrapOrError(C.getRawSize(), 2238 getFileNameForError(C, ChildIndex), Filename, 2239 ArchitectureName)); 2240 2241 StringRef RawLastModified = C.getRawLastModified(); 2242 if (verbose) { 2243 unsigned Seconds; 2244 if (RawLastModified.getAsInteger(10, Seconds)) 2245 outs() << "(date: \"" << RawLastModified 2246 << "\" contains non-decimal chars) "; 2247 else { 2248 // Since cime(3) returns a 26 character string of the form: 2249 // "Sun Sep 16 01:03:52 1973\n\0" 2250 // just print 24 characters. 2251 time_t t = Seconds; 2252 outs() << format("%.24s ", ctime(&t)); 2253 } 2254 } else { 2255 outs() << RawLastModified << " "; 2256 } 2257 2258 if (verbose) { 2259 Expected<StringRef> NameOrErr = C.getName(); 2260 if (!NameOrErr) { 2261 consumeError(NameOrErr.takeError()); 2262 outs() << unwrapOrError(C.getRawName(), 2263 getFileNameForError(C, ChildIndex), Filename, 2264 ArchitectureName) 2265 << "\n"; 2266 } else { 2267 StringRef Name = NameOrErr.get(); 2268 outs() << Name << "\n"; 2269 } 2270 } else { 2271 outs() << unwrapOrError(C.getRawName(), getFileNameForError(C, ChildIndex), 2272 Filename, ArchitectureName) 2273 << "\n"; 2274 } 2275 } 2276 2277 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 2278 bool print_offset, 2279 StringRef ArchitectureName = StringRef()) { 2280 Error Err = Error::success(); 2281 size_t I = 0; 2282 for (const auto &C : A->children(Err, false)) 2283 printArchiveChild(Filename, C, I++, verbose, print_offset, 2284 ArchitectureName); 2285 2286 if (Err) 2287 reportError(std::move(Err), Filename, "", ArchitectureName); 2288 } 2289 2290 static bool ValidateArchFlags() { 2291 // Check for -arch all and verifiy the -arch flags are valid. 2292 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2293 if (ArchFlags[i] == "all") { 2294 ArchAll = true; 2295 } else { 2296 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 2297 WithColor::error(errs(), "llvm-objdump") 2298 << "unknown architecture named '" + ArchFlags[i] + 2299 "'for the -arch option\n"; 2300 return false; 2301 } 2302 } 2303 } 2304 return true; 2305 } 2306 2307 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 2308 // -arch flags selecting just those slices as specified by them and also parses 2309 // archive files. Then for each individual Mach-O file ProcessMachO() is 2310 // called to process the file based on the command line options. 2311 void objdump::parseInputMachO(StringRef Filename) { 2312 if (!ValidateArchFlags()) 2313 return; 2314 2315 // Attempt to open the binary. 2316 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 2317 if (!BinaryOrErr) { 2318 if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 2319 reportError(std::move(E), Filename); 2320 else 2321 outs() << Filename << ": is not an object file\n"; 2322 return; 2323 } 2324 Binary &Bin = *BinaryOrErr.get().getBinary(); 2325 2326 if (Archive *A = dyn_cast<Archive>(&Bin)) { 2327 outs() << "Archive : " << Filename << "\n"; 2328 if (ArchiveHeaders) 2329 printArchiveHeaders(Filename, A, Verbose, ArchiveMemberOffsets); 2330 2331 Error Err = Error::success(); 2332 unsigned I = -1; 2333 for (auto &C : A->children(Err)) { 2334 ++I; 2335 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2336 if (!ChildOrErr) { 2337 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2338 reportError(std::move(E), getFileNameForError(C, I), Filename); 2339 continue; 2340 } 2341 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2342 if (!checkMachOAndArchFlags(O, Filename)) 2343 return; 2344 ProcessMachO(Filename, O, O->getFileName()); 2345 } 2346 } 2347 if (Err) 2348 reportError(std::move(Err), Filename); 2349 return; 2350 } 2351 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 2352 parseInputMachO(UB); 2353 return; 2354 } 2355 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2356 if (!checkMachOAndArchFlags(O, Filename)) 2357 return; 2358 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) 2359 ProcessMachO(Filename, MachOOF); 2360 else 2361 WithColor::error(errs(), "llvm-objdump") 2362 << Filename << "': " 2363 << "object is not a Mach-O file type.\n"; 2364 return; 2365 } 2366 llvm_unreachable("Input object can't be invalid at this point"); 2367 } 2368 2369 void objdump::parseInputMachO(MachOUniversalBinary *UB) { 2370 if (!ValidateArchFlags()) 2371 return; 2372 2373 auto Filename = UB->getFileName(); 2374 2375 if (UniversalHeaders) 2376 printMachOUniversalHeaders(UB, Verbose); 2377 2378 // If we have a list of architecture flags specified dump only those. 2379 if (!ArchAll && !ArchFlags.empty()) { 2380 // Look for a slice in the universal binary that matches each ArchFlag. 2381 bool ArchFound; 2382 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2383 ArchFound = false; 2384 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2385 E = UB->end_objects(); 2386 I != E; ++I) { 2387 if (ArchFlags[i] == I->getArchFlagName()) { 2388 ArchFound = true; 2389 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2390 I->getAsObjectFile(); 2391 std::string ArchitectureName; 2392 if (ArchFlags.size() > 1) 2393 ArchitectureName = I->getArchFlagName(); 2394 if (ObjOrErr) { 2395 ObjectFile &O = *ObjOrErr.get(); 2396 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2397 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2398 } else if (Error E = isNotObjectErrorInvalidFileType( 2399 ObjOrErr.takeError())) { 2400 reportError(std::move(E), "", Filename, ArchitectureName); 2401 continue; 2402 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2403 I->getAsArchive()) { 2404 std::unique_ptr<Archive> &A = *AOrErr; 2405 outs() << "Archive : " << Filename; 2406 if (!ArchitectureName.empty()) 2407 outs() << " (architecture " << ArchitectureName << ")"; 2408 outs() << "\n"; 2409 if (ArchiveHeaders) 2410 printArchiveHeaders(Filename, A.get(), Verbose, 2411 ArchiveMemberOffsets, ArchitectureName); 2412 Error Err = Error::success(); 2413 unsigned I = -1; 2414 for (auto &C : A->children(Err)) { 2415 ++I; 2416 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2417 if (!ChildOrErr) { 2418 if (Error E = 2419 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2420 reportError(std::move(E), getFileNameForError(C, I), Filename, 2421 ArchitectureName); 2422 continue; 2423 } 2424 if (MachOObjectFile *O = 2425 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2426 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2427 } 2428 if (Err) 2429 reportError(std::move(Err), Filename); 2430 } else { 2431 consumeError(AOrErr.takeError()); 2432 reportError(Filename, 2433 "Mach-O universal file for architecture " + 2434 StringRef(I->getArchFlagName()) + 2435 " is not a Mach-O file or an archive file"); 2436 } 2437 } 2438 } 2439 if (!ArchFound) { 2440 WithColor::error(errs(), "llvm-objdump") 2441 << "file: " + Filename + " does not contain " 2442 << "architecture: " + ArchFlags[i] + "\n"; 2443 return; 2444 } 2445 } 2446 return; 2447 } 2448 // No architecture flags were specified so if this contains a slice that 2449 // matches the host architecture dump only that. 2450 if (!ArchAll) { 2451 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2452 E = UB->end_objects(); 2453 I != E; ++I) { 2454 if (MachOObjectFile::getHostArch().getArchName() == 2455 I->getArchFlagName()) { 2456 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2457 std::string ArchiveName; 2458 ArchiveName.clear(); 2459 if (ObjOrErr) { 2460 ObjectFile &O = *ObjOrErr.get(); 2461 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2462 ProcessMachO(Filename, MachOOF); 2463 } else if (Error E = 2464 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2465 reportError(std::move(E), Filename); 2466 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2467 I->getAsArchive()) { 2468 std::unique_ptr<Archive> &A = *AOrErr; 2469 outs() << "Archive : " << Filename << "\n"; 2470 if (ArchiveHeaders) 2471 printArchiveHeaders(Filename, A.get(), Verbose, 2472 ArchiveMemberOffsets); 2473 Error Err = Error::success(); 2474 unsigned I = -1; 2475 for (auto &C : A->children(Err)) { 2476 ++I; 2477 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2478 if (!ChildOrErr) { 2479 if (Error E = 2480 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2481 reportError(std::move(E), getFileNameForError(C, I), Filename); 2482 continue; 2483 } 2484 if (MachOObjectFile *O = 2485 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2486 ProcessMachO(Filename, O, O->getFileName()); 2487 } 2488 if (Err) 2489 reportError(std::move(Err), Filename); 2490 } else { 2491 consumeError(AOrErr.takeError()); 2492 reportError(Filename, "Mach-O universal file for architecture " + 2493 StringRef(I->getArchFlagName()) + 2494 " is not a Mach-O file or an archive file"); 2495 } 2496 return; 2497 } 2498 } 2499 } 2500 // Either all architectures have been specified or none have been specified 2501 // and this does not contain the host architecture so dump all the slices. 2502 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2503 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2504 E = UB->end_objects(); 2505 I != E; ++I) { 2506 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2507 std::string ArchitectureName; 2508 if (moreThanOneArch) 2509 ArchitectureName = I->getArchFlagName(); 2510 if (ObjOrErr) { 2511 ObjectFile &Obj = *ObjOrErr.get(); 2512 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2513 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2514 } else if (Error E = 2515 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2516 reportError(std::move(E), Filename, "", ArchitectureName); 2517 } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { 2518 std::unique_ptr<Archive> &A = *AOrErr; 2519 outs() << "Archive : " << Filename; 2520 if (!ArchitectureName.empty()) 2521 outs() << " (architecture " << ArchitectureName << ")"; 2522 outs() << "\n"; 2523 if (ArchiveHeaders) 2524 printArchiveHeaders(Filename, A.get(), Verbose, ArchiveMemberOffsets, 2525 ArchitectureName); 2526 Error Err = Error::success(); 2527 unsigned I = -1; 2528 for (auto &C : A->children(Err)) { 2529 ++I; 2530 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2531 if (!ChildOrErr) { 2532 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2533 reportError(std::move(E), getFileNameForError(C, I), Filename, 2534 ArchitectureName); 2535 continue; 2536 } 2537 if (MachOObjectFile *O = 2538 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2539 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2540 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2541 ArchitectureName); 2542 } 2543 } 2544 if (Err) 2545 reportError(std::move(Err), Filename); 2546 } else { 2547 consumeError(AOrErr.takeError()); 2548 reportError(Filename, "Mach-O universal file for architecture " + 2549 StringRef(I->getArchFlagName()) + 2550 " is not a Mach-O file or an archive file"); 2551 } 2552 } 2553 } 2554 2555 namespace { 2556 // The block of info used by the Symbolizer call backs. 2557 struct DisassembleInfo { 2558 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, 2559 std::vector<SectionRef> *Sections, bool verbose) 2560 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {} 2561 bool verbose; 2562 MachOObjectFile *O; 2563 SectionRef S; 2564 SymbolAddressMap *AddrMap; 2565 std::vector<SectionRef> *Sections; 2566 const char *class_name = nullptr; 2567 const char *selector_name = nullptr; 2568 std::unique_ptr<char[]> method = nullptr; 2569 char *demangled_name = nullptr; 2570 uint64_t adrp_addr = 0; 2571 uint32_t adrp_inst = 0; 2572 std::unique_ptr<SymbolAddressMap> bindtable; 2573 uint32_t depth = 0; 2574 }; 2575 } // namespace 2576 2577 // SymbolizerGetOpInfo() is the operand information call back function. 2578 // This is called to get the symbolic information for operand(s) of an 2579 // instruction when it is being done. This routine does this from 2580 // the relocation information, symbol table, etc. That block of information 2581 // is a pointer to the struct DisassembleInfo that was passed when the 2582 // disassembler context was created and passed to back to here when 2583 // called back by the disassembler for instruction operands that could have 2584 // relocation information. The address of the instruction containing operand is 2585 // at the Pc parameter. The immediate value the operand has is passed in 2586 // op_info->Value and is at Offset past the start of the instruction and has a 2587 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2588 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2589 // names and addends of the symbolic expression to add for the operand. The 2590 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2591 // information is returned then this function returns 1 else it returns 0. 2592 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2593 uint64_t Size, int TagType, void *TagBuf) { 2594 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2595 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2596 uint64_t value = op_info->Value; 2597 2598 // Make sure all fields returned are zero if we don't set them. 2599 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2600 op_info->Value = value; 2601 2602 // If the TagType is not the value 1 which it code knows about or if no 2603 // verbose symbolic information is wanted then just return 0, indicating no 2604 // information is being returned. 2605 if (TagType != 1 || !info->verbose) 2606 return 0; 2607 2608 unsigned int Arch = info->O->getArch(); 2609 if (Arch == Triple::x86) { 2610 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2611 return 0; 2612 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2613 // TODO: 2614 // Search the external relocation entries of a fully linked image 2615 // (if any) for an entry that matches this segment offset. 2616 // uint32_t seg_offset = (Pc + Offset); 2617 return 0; 2618 } 2619 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2620 // for an entry for this section offset. 2621 uint32_t sect_addr = info->S.getAddress(); 2622 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2623 bool reloc_found = false; 2624 DataRefImpl Rel; 2625 MachO::any_relocation_info RE; 2626 bool isExtern = false; 2627 SymbolRef Symbol; 2628 bool r_scattered = false; 2629 uint32_t r_value, pair_r_value, r_type; 2630 for (const RelocationRef &Reloc : info->S.relocations()) { 2631 uint64_t RelocOffset = Reloc.getOffset(); 2632 if (RelocOffset == sect_offset) { 2633 Rel = Reloc.getRawDataRefImpl(); 2634 RE = info->O->getRelocation(Rel); 2635 r_type = info->O->getAnyRelocationType(RE); 2636 r_scattered = info->O->isRelocationScattered(RE); 2637 if (r_scattered) { 2638 r_value = info->O->getScatteredRelocationValue(RE); 2639 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2640 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2641 DataRefImpl RelNext = Rel; 2642 info->O->moveRelocationNext(RelNext); 2643 MachO::any_relocation_info RENext; 2644 RENext = info->O->getRelocation(RelNext); 2645 if (info->O->isRelocationScattered(RENext)) 2646 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2647 else 2648 return 0; 2649 } 2650 } else { 2651 isExtern = info->O->getPlainRelocationExternal(RE); 2652 if (isExtern) { 2653 symbol_iterator RelocSym = Reloc.getSymbol(); 2654 Symbol = *RelocSym; 2655 } 2656 } 2657 reloc_found = true; 2658 break; 2659 } 2660 } 2661 if (reloc_found && isExtern) { 2662 op_info->AddSymbol.Present = 1; 2663 op_info->AddSymbol.Name = 2664 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2665 // For i386 extern relocation entries the value in the instruction is 2666 // the offset from the symbol, and value is already set in op_info->Value. 2667 return 1; 2668 } 2669 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2670 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2671 const char *add = GuessSymbolName(r_value, info->AddrMap); 2672 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2673 uint32_t offset = value - (r_value - pair_r_value); 2674 op_info->AddSymbol.Present = 1; 2675 if (add != nullptr) 2676 op_info->AddSymbol.Name = add; 2677 else 2678 op_info->AddSymbol.Value = r_value; 2679 op_info->SubtractSymbol.Present = 1; 2680 if (sub != nullptr) 2681 op_info->SubtractSymbol.Name = sub; 2682 else 2683 op_info->SubtractSymbol.Value = pair_r_value; 2684 op_info->Value = offset; 2685 return 1; 2686 } 2687 return 0; 2688 } 2689 if (Arch == Triple::x86_64) { 2690 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 2691 return 0; 2692 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2693 // relocation entries of a linked image (if any) for an entry that matches 2694 // this segment offset. 2695 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2696 uint64_t seg_offset = Pc + Offset; 2697 bool reloc_found = false; 2698 DataRefImpl Rel; 2699 MachO::any_relocation_info RE; 2700 bool isExtern = false; 2701 SymbolRef Symbol; 2702 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2703 uint64_t RelocOffset = Reloc.getOffset(); 2704 if (RelocOffset == seg_offset) { 2705 Rel = Reloc.getRawDataRefImpl(); 2706 RE = info->O->getRelocation(Rel); 2707 // external relocation entries should always be external. 2708 isExtern = info->O->getPlainRelocationExternal(RE); 2709 if (isExtern) { 2710 symbol_iterator RelocSym = Reloc.getSymbol(); 2711 Symbol = *RelocSym; 2712 } 2713 reloc_found = true; 2714 break; 2715 } 2716 } 2717 if (reloc_found && isExtern) { 2718 // The Value passed in will be adjusted by the Pc if the instruction 2719 // adds the Pc. But for x86_64 external relocation entries the Value 2720 // is the offset from the external symbol. 2721 if (info->O->getAnyRelocationPCRel(RE)) 2722 op_info->Value -= Pc + Offset + Size; 2723 const char *name = 2724 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2725 op_info->AddSymbol.Present = 1; 2726 op_info->AddSymbol.Name = name; 2727 return 1; 2728 } 2729 return 0; 2730 } 2731 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2732 // for an entry for this section offset. 2733 uint64_t sect_addr = info->S.getAddress(); 2734 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2735 bool reloc_found = false; 2736 DataRefImpl Rel; 2737 MachO::any_relocation_info RE; 2738 bool isExtern = false; 2739 SymbolRef Symbol; 2740 for (const RelocationRef &Reloc : info->S.relocations()) { 2741 uint64_t RelocOffset = Reloc.getOffset(); 2742 if (RelocOffset == sect_offset) { 2743 Rel = Reloc.getRawDataRefImpl(); 2744 RE = info->O->getRelocation(Rel); 2745 // NOTE: Scattered relocations don't exist on x86_64. 2746 isExtern = info->O->getPlainRelocationExternal(RE); 2747 if (isExtern) { 2748 symbol_iterator RelocSym = Reloc.getSymbol(); 2749 Symbol = *RelocSym; 2750 } 2751 reloc_found = true; 2752 break; 2753 } 2754 } 2755 if (reloc_found && isExtern) { 2756 // The Value passed in will be adjusted by the Pc if the instruction 2757 // adds the Pc. But for x86_64 external relocation entries the Value 2758 // is the offset from the external symbol. 2759 if (info->O->getAnyRelocationPCRel(RE)) 2760 op_info->Value -= Pc + Offset + Size; 2761 const char *name = 2762 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2763 unsigned Type = info->O->getAnyRelocationType(RE); 2764 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2765 DataRefImpl RelNext = Rel; 2766 info->O->moveRelocationNext(RelNext); 2767 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2768 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2769 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2770 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2771 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2772 op_info->SubtractSymbol.Present = 1; 2773 op_info->SubtractSymbol.Name = name; 2774 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2775 Symbol = *RelocSymNext; 2776 name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2777 } 2778 } 2779 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 2780 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 2781 op_info->AddSymbol.Present = 1; 2782 op_info->AddSymbol.Name = name; 2783 return 1; 2784 } 2785 return 0; 2786 } 2787 if (Arch == Triple::arm) { 2788 if (Offset != 0 || (Size != 4 && Size != 2)) 2789 return 0; 2790 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2791 // TODO: 2792 // Search the external relocation entries of a fully linked image 2793 // (if any) for an entry that matches this segment offset. 2794 // uint32_t seg_offset = (Pc + Offset); 2795 return 0; 2796 } 2797 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2798 // for an entry for this section offset. 2799 uint32_t sect_addr = info->S.getAddress(); 2800 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2801 DataRefImpl Rel; 2802 MachO::any_relocation_info RE; 2803 bool isExtern = false; 2804 SymbolRef Symbol; 2805 bool r_scattered = false; 2806 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 2807 auto Reloc = 2808 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2809 uint64_t RelocOffset = Reloc.getOffset(); 2810 return RelocOffset == sect_offset; 2811 }); 2812 2813 if (Reloc == info->S.relocations().end()) 2814 return 0; 2815 2816 Rel = Reloc->getRawDataRefImpl(); 2817 RE = info->O->getRelocation(Rel); 2818 r_length = info->O->getAnyRelocationLength(RE); 2819 r_scattered = info->O->isRelocationScattered(RE); 2820 if (r_scattered) { 2821 r_value = info->O->getScatteredRelocationValue(RE); 2822 r_type = info->O->getScatteredRelocationType(RE); 2823 } else { 2824 r_type = info->O->getAnyRelocationType(RE); 2825 isExtern = info->O->getPlainRelocationExternal(RE); 2826 if (isExtern) { 2827 symbol_iterator RelocSym = Reloc->getSymbol(); 2828 Symbol = *RelocSym; 2829 } 2830 } 2831 if (r_type == MachO::ARM_RELOC_HALF || 2832 r_type == MachO::ARM_RELOC_SECTDIFF || 2833 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 2834 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2835 DataRefImpl RelNext = Rel; 2836 info->O->moveRelocationNext(RelNext); 2837 MachO::any_relocation_info RENext; 2838 RENext = info->O->getRelocation(RelNext); 2839 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 2840 if (info->O->isRelocationScattered(RENext)) 2841 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2842 } 2843 2844 if (isExtern) { 2845 const char *name = 2846 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2847 op_info->AddSymbol.Present = 1; 2848 op_info->AddSymbol.Name = name; 2849 switch (r_type) { 2850 case MachO::ARM_RELOC_HALF: 2851 if ((r_length & 0x1) == 1) { 2852 op_info->Value = value << 16 | other_half; 2853 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2854 } else { 2855 op_info->Value = other_half << 16 | value; 2856 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2857 } 2858 break; 2859 default: 2860 break; 2861 } 2862 return 1; 2863 } 2864 // If we have a branch that is not an external relocation entry then 2865 // return 0 so the code in tryAddingSymbolicOperand() can use the 2866 // SymbolLookUp call back with the branch target address to look up the 2867 // symbol and possibility add an annotation for a symbol stub. 2868 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 2869 r_type == MachO::ARM_THUMB_RELOC_BR22)) 2870 return 0; 2871 2872 uint32_t offset = 0; 2873 if (r_type == MachO::ARM_RELOC_HALF || 2874 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2875 if ((r_length & 0x1) == 1) 2876 value = value << 16 | other_half; 2877 else 2878 value = other_half << 16 | value; 2879 } 2880 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 2881 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 2882 offset = value - r_value; 2883 value = r_value; 2884 } 2885 2886 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 2887 if ((r_length & 0x1) == 1) 2888 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2889 else 2890 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2891 const char *add = GuessSymbolName(r_value, info->AddrMap); 2892 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2893 int32_t offset = value - (r_value - pair_r_value); 2894 op_info->AddSymbol.Present = 1; 2895 if (add != nullptr) 2896 op_info->AddSymbol.Name = add; 2897 else 2898 op_info->AddSymbol.Value = r_value; 2899 op_info->SubtractSymbol.Present = 1; 2900 if (sub != nullptr) 2901 op_info->SubtractSymbol.Name = sub; 2902 else 2903 op_info->SubtractSymbol.Value = pair_r_value; 2904 op_info->Value = offset; 2905 return 1; 2906 } 2907 2908 op_info->AddSymbol.Present = 1; 2909 op_info->Value = offset; 2910 if (r_type == MachO::ARM_RELOC_HALF) { 2911 if ((r_length & 0x1) == 1) 2912 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2913 else 2914 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2915 } 2916 const char *add = GuessSymbolName(value, info->AddrMap); 2917 if (add != nullptr) { 2918 op_info->AddSymbol.Name = add; 2919 return 1; 2920 } 2921 op_info->AddSymbol.Value = value; 2922 return 1; 2923 } 2924 if (Arch == Triple::aarch64) { 2925 if (Offset != 0 || Size != 4) 2926 return 0; 2927 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2928 // TODO: 2929 // Search the external relocation entries of a fully linked image 2930 // (if any) for an entry that matches this segment offset. 2931 // uint64_t seg_offset = (Pc + Offset); 2932 return 0; 2933 } 2934 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2935 // for an entry for this section offset. 2936 uint64_t sect_addr = info->S.getAddress(); 2937 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2938 auto Reloc = 2939 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 2940 uint64_t RelocOffset = Reloc.getOffset(); 2941 return RelocOffset == sect_offset; 2942 }); 2943 2944 if (Reloc == info->S.relocations().end()) 2945 return 0; 2946 2947 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2948 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 2949 uint32_t r_type = info->O->getAnyRelocationType(RE); 2950 if (r_type == MachO::ARM64_RELOC_ADDEND) { 2951 DataRefImpl RelNext = Rel; 2952 info->O->moveRelocationNext(RelNext); 2953 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2954 if (value == 0) { 2955 value = info->O->getPlainRelocationSymbolNum(RENext); 2956 op_info->Value = value; 2957 } 2958 } 2959 // NOTE: Scattered relocations don't exist on arm64. 2960 if (!info->O->getPlainRelocationExternal(RE)) 2961 return 0; 2962 const char *name = 2963 unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName()) 2964 .data(); 2965 op_info->AddSymbol.Present = 1; 2966 op_info->AddSymbol.Name = name; 2967 2968 switch (r_type) { 2969 case MachO::ARM64_RELOC_PAGE21: 2970 /* @page */ 2971 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 2972 break; 2973 case MachO::ARM64_RELOC_PAGEOFF12: 2974 /* @pageoff */ 2975 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 2976 break; 2977 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 2978 /* @gotpage */ 2979 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 2980 break; 2981 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 2982 /* @gotpageoff */ 2983 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 2984 break; 2985 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 2986 /* @tvlppage is not implemented in llvm-mc */ 2987 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 2988 break; 2989 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 2990 /* @tvlppageoff is not implemented in llvm-mc */ 2991 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 2992 break; 2993 default: 2994 case MachO::ARM64_RELOC_BRANCH26: 2995 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 2996 break; 2997 } 2998 return 1; 2999 } 3000 return 0; 3001 } 3002 3003 // GuessCstringPointer is passed the address of what might be a pointer to a 3004 // literal string in a cstring section. If that address is in a cstring section 3005 // it returns a pointer to that string. Else it returns nullptr. 3006 static const char *GuessCstringPointer(uint64_t ReferenceValue, 3007 struct DisassembleInfo *info) { 3008 for (const auto &Load : info->O->load_commands()) { 3009 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3010 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3011 for (unsigned J = 0; J < Seg.nsects; ++J) { 3012 MachO::section_64 Sec = info->O->getSection64(Load, J); 3013 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3014 if (section_type == MachO::S_CSTRING_LITERALS && 3015 ReferenceValue >= Sec.addr && 3016 ReferenceValue < Sec.addr + Sec.size) { 3017 uint64_t sect_offset = ReferenceValue - Sec.addr; 3018 uint64_t object_offset = Sec.offset + sect_offset; 3019 StringRef MachOContents = info->O->getData(); 3020 uint64_t object_size = MachOContents.size(); 3021 const char *object_addr = (const char *)MachOContents.data(); 3022 if (object_offset < object_size) { 3023 const char *name = object_addr + object_offset; 3024 return name; 3025 } else { 3026 return nullptr; 3027 } 3028 } 3029 } 3030 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3031 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3032 for (unsigned J = 0; J < Seg.nsects; ++J) { 3033 MachO::section Sec = info->O->getSection(Load, J); 3034 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3035 if (section_type == MachO::S_CSTRING_LITERALS && 3036 ReferenceValue >= Sec.addr && 3037 ReferenceValue < Sec.addr + Sec.size) { 3038 uint64_t sect_offset = ReferenceValue - Sec.addr; 3039 uint64_t object_offset = Sec.offset + sect_offset; 3040 StringRef MachOContents = info->O->getData(); 3041 uint64_t object_size = MachOContents.size(); 3042 const char *object_addr = (const char *)MachOContents.data(); 3043 if (object_offset < object_size) { 3044 const char *name = object_addr + object_offset; 3045 return name; 3046 } else { 3047 return nullptr; 3048 } 3049 } 3050 } 3051 } 3052 } 3053 return nullptr; 3054 } 3055 3056 // GuessIndirectSymbol returns the name of the indirect symbol for the 3057 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 3058 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 3059 // symbol name being referenced by the stub or pointer. 3060 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 3061 struct DisassembleInfo *info) { 3062 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 3063 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 3064 for (const auto &Load : info->O->load_commands()) { 3065 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3066 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3067 for (unsigned J = 0; J < Seg.nsects; ++J) { 3068 MachO::section_64 Sec = info->O->getSection64(Load, J); 3069 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3070 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3071 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3072 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3073 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3074 section_type == MachO::S_SYMBOL_STUBS) && 3075 ReferenceValue >= Sec.addr && 3076 ReferenceValue < Sec.addr + Sec.size) { 3077 uint32_t stride; 3078 if (section_type == MachO::S_SYMBOL_STUBS) 3079 stride = Sec.reserved2; 3080 else 3081 stride = 8; 3082 if (stride == 0) 3083 return nullptr; 3084 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3085 if (index < Dysymtab.nindirectsyms) { 3086 uint32_t indirect_symbol = 3087 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3088 if (indirect_symbol < Symtab.nsyms) { 3089 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3090 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3091 .data(); 3092 } 3093 } 3094 } 3095 } 3096 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3097 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3098 for (unsigned J = 0; J < Seg.nsects; ++J) { 3099 MachO::section Sec = info->O->getSection(Load, J); 3100 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3101 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3102 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3103 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3104 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3105 section_type == MachO::S_SYMBOL_STUBS) && 3106 ReferenceValue >= Sec.addr && 3107 ReferenceValue < Sec.addr + Sec.size) { 3108 uint32_t stride; 3109 if (section_type == MachO::S_SYMBOL_STUBS) 3110 stride = Sec.reserved2; 3111 else 3112 stride = 4; 3113 if (stride == 0) 3114 return nullptr; 3115 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3116 if (index < Dysymtab.nindirectsyms) { 3117 uint32_t indirect_symbol = 3118 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3119 if (indirect_symbol < Symtab.nsyms) { 3120 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3121 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3122 .data(); 3123 } 3124 } 3125 } 3126 } 3127 } 3128 } 3129 return nullptr; 3130 } 3131 3132 // method_reference() is called passing it the ReferenceName that might be 3133 // a reference it to an Objective-C method call. If so then it allocates and 3134 // assembles a method call string with the values last seen and saved in 3135 // the DisassembleInfo's class_name and selector_name fields. This is saved 3136 // into the method field of the info and any previous string is free'ed. 3137 // Then the class_name field in the info is set to nullptr. The method call 3138 // string is set into ReferenceName and ReferenceType is set to 3139 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 3140 // then both ReferenceType and ReferenceName are left unchanged. 3141 static void method_reference(struct DisassembleInfo *info, 3142 uint64_t *ReferenceType, 3143 const char **ReferenceName) { 3144 unsigned int Arch = info->O->getArch(); 3145 if (*ReferenceName != nullptr) { 3146 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 3147 if (info->selector_name != nullptr) { 3148 if (info->class_name != nullptr) { 3149 info->method = std::make_unique<char[]>( 3150 5 + strlen(info->class_name) + strlen(info->selector_name)); 3151 char *method = info->method.get(); 3152 if (method != nullptr) { 3153 strcpy(method, "+["); 3154 strcat(method, info->class_name); 3155 strcat(method, " "); 3156 strcat(method, info->selector_name); 3157 strcat(method, "]"); 3158 *ReferenceName = method; 3159 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3160 } 3161 } else { 3162 info->method = 3163 std::make_unique<char[]>(9 + strlen(info->selector_name)); 3164 char *method = info->method.get(); 3165 if (method != nullptr) { 3166 if (Arch == Triple::x86_64) 3167 strcpy(method, "-[%rdi "); 3168 else if (Arch == Triple::aarch64) 3169 strcpy(method, "-[x0 "); 3170 else 3171 strcpy(method, "-[r? "); 3172 strcat(method, info->selector_name); 3173 strcat(method, "]"); 3174 *ReferenceName = method; 3175 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3176 } 3177 } 3178 info->class_name = nullptr; 3179 } 3180 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 3181 if (info->selector_name != nullptr) { 3182 info->method = 3183 std::make_unique<char[]>(17 + strlen(info->selector_name)); 3184 char *method = info->method.get(); 3185 if (method != nullptr) { 3186 if (Arch == Triple::x86_64) 3187 strcpy(method, "-[[%rdi super] "); 3188 else if (Arch == Triple::aarch64) 3189 strcpy(method, "-[[x0 super] "); 3190 else 3191 strcpy(method, "-[[r? super] "); 3192 strcat(method, info->selector_name); 3193 strcat(method, "]"); 3194 *ReferenceName = method; 3195 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3196 } 3197 info->class_name = nullptr; 3198 } 3199 } 3200 } 3201 } 3202 3203 // GuessPointerPointer() is passed the address of what might be a pointer to 3204 // a reference to an Objective-C class, selector, message ref or cfstring. 3205 // If so the value of the pointer is returned and one of the booleans are set 3206 // to true. If not zero is returned and all the booleans are set to false. 3207 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 3208 struct DisassembleInfo *info, 3209 bool &classref, bool &selref, bool &msgref, 3210 bool &cfstring) { 3211 classref = false; 3212 selref = false; 3213 msgref = false; 3214 cfstring = false; 3215 for (const auto &Load : info->O->load_commands()) { 3216 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3217 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3218 for (unsigned J = 0; J < Seg.nsects; ++J) { 3219 MachO::section_64 Sec = info->O->getSection64(Load, J); 3220 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 3221 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3222 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 3223 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 3224 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 3225 ReferenceValue >= Sec.addr && 3226 ReferenceValue < Sec.addr + Sec.size) { 3227 uint64_t sect_offset = ReferenceValue - Sec.addr; 3228 uint64_t object_offset = Sec.offset + sect_offset; 3229 StringRef MachOContents = info->O->getData(); 3230 uint64_t object_size = MachOContents.size(); 3231 const char *object_addr = (const char *)MachOContents.data(); 3232 if (object_offset < object_size) { 3233 uint64_t pointer_value; 3234 memcpy(&pointer_value, object_addr + object_offset, 3235 sizeof(uint64_t)); 3236 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3237 sys::swapByteOrder(pointer_value); 3238 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 3239 selref = true; 3240 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3241 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 3242 classref = true; 3243 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 3244 ReferenceValue + 8 < Sec.addr + Sec.size) { 3245 msgref = true; 3246 memcpy(&pointer_value, object_addr + object_offset + 8, 3247 sizeof(uint64_t)); 3248 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3249 sys::swapByteOrder(pointer_value); 3250 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 3251 cfstring = true; 3252 return pointer_value; 3253 } else { 3254 return 0; 3255 } 3256 } 3257 } 3258 } 3259 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 3260 } 3261 return 0; 3262 } 3263 3264 // get_pointer_64 returns a pointer to the bytes in the object file at the 3265 // Address from a section in the Mach-O file. And indirectly returns the 3266 // offset into the section, number of bytes left in the section past the offset 3267 // and which section is was being referenced. If the Address is not in a 3268 // section nullptr is returned. 3269 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 3270 uint32_t &left, SectionRef &S, 3271 DisassembleInfo *info, 3272 bool objc_only = false) { 3273 offset = 0; 3274 left = 0; 3275 S = SectionRef(); 3276 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 3277 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 3278 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 3279 if (SectSize == 0) 3280 continue; 3281 if (objc_only) { 3282 StringRef SectName; 3283 Expected<StringRef> SecNameOrErr = 3284 ((*(info->Sections))[SectIdx]).getName(); 3285 if (SecNameOrErr) 3286 SectName = *SecNameOrErr; 3287 else 3288 consumeError(SecNameOrErr.takeError()); 3289 3290 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 3291 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 3292 if (SegName != "__OBJC" && SectName != "__cstring") 3293 continue; 3294 } 3295 if (Address >= SectAddress && Address < SectAddress + SectSize) { 3296 S = (*(info->Sections))[SectIdx]; 3297 offset = Address - SectAddress; 3298 left = SectSize - offset; 3299 StringRef SectContents = unwrapOrError( 3300 ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName()); 3301 return SectContents.data() + offset; 3302 } 3303 } 3304 return nullptr; 3305 } 3306 3307 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 3308 uint32_t &left, SectionRef &S, 3309 DisassembleInfo *info, 3310 bool objc_only = false) { 3311 return get_pointer_64(Address, offset, left, S, info, objc_only); 3312 } 3313 3314 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 3315 // the symbol indirectly through n_value. Based on the relocation information 3316 // for the specified section offset in the specified section reference. 3317 // If no relocation information is found and a non-zero ReferenceValue for the 3318 // symbol is passed, look up that address in the info's AddrMap. 3319 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 3320 DisassembleInfo *info, uint64_t &n_value, 3321 uint64_t ReferenceValue = 0) { 3322 n_value = 0; 3323 if (!info->verbose) 3324 return nullptr; 3325 3326 // See if there is an external relocation entry at the sect_offset. 3327 bool reloc_found = false; 3328 DataRefImpl Rel; 3329 MachO::any_relocation_info RE; 3330 bool isExtern = false; 3331 SymbolRef Symbol; 3332 for (const RelocationRef &Reloc : S.relocations()) { 3333 uint64_t RelocOffset = Reloc.getOffset(); 3334 if (RelocOffset == sect_offset) { 3335 Rel = Reloc.getRawDataRefImpl(); 3336 RE = info->O->getRelocation(Rel); 3337 if (info->O->isRelocationScattered(RE)) 3338 continue; 3339 isExtern = info->O->getPlainRelocationExternal(RE); 3340 if (isExtern) { 3341 symbol_iterator RelocSym = Reloc.getSymbol(); 3342 Symbol = *RelocSym; 3343 } 3344 reloc_found = true; 3345 break; 3346 } 3347 } 3348 // If there is an external relocation entry for a symbol in this section 3349 // at this section_offset then use that symbol's value for the n_value 3350 // and return its name. 3351 const char *SymbolName = nullptr; 3352 if (reloc_found && isExtern) { 3353 n_value = cantFail(Symbol.getValue()); 3354 StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName()); 3355 if (!Name.empty()) { 3356 SymbolName = Name.data(); 3357 return SymbolName; 3358 } 3359 } 3360 3361 // TODO: For fully linked images, look through the external relocation 3362 // entries off the dynamic symtab command. For these the r_offset is from the 3363 // start of the first writeable segment in the Mach-O file. So the offset 3364 // to this section from that segment is passed to this routine by the caller, 3365 // as the database_offset. Which is the difference of the section's starting 3366 // address and the first writable segment. 3367 // 3368 // NOTE: need add passing the database_offset to this routine. 3369 3370 // We did not find an external relocation entry so look up the ReferenceValue 3371 // as an address of a symbol and if found return that symbol's name. 3372 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 3373 3374 return SymbolName; 3375 } 3376 3377 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 3378 DisassembleInfo *info, 3379 uint32_t ReferenceValue) { 3380 uint64_t n_value64; 3381 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 3382 } 3383 3384 namespace { 3385 3386 // These are structs in the Objective-C meta data and read to produce the 3387 // comments for disassembly. While these are part of the ABI they are no 3388 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 3389 // . 3390 3391 // The cfstring object in a 64-bit Mach-O file. 3392 struct cfstring64_t { 3393 uint64_t isa; // class64_t * (64-bit pointer) 3394 uint64_t flags; // flag bits 3395 uint64_t characters; // char * (64-bit pointer) 3396 uint64_t length; // number of non-NULL characters in above 3397 }; 3398 3399 // The class object in a 64-bit Mach-O file. 3400 struct class64_t { 3401 uint64_t isa; // class64_t * (64-bit pointer) 3402 uint64_t superclass; // class64_t * (64-bit pointer) 3403 uint64_t cache; // Cache (64-bit pointer) 3404 uint64_t vtable; // IMP * (64-bit pointer) 3405 uint64_t data; // class_ro64_t * (64-bit pointer) 3406 }; 3407 3408 struct class32_t { 3409 uint32_t isa; /* class32_t * (32-bit pointer) */ 3410 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3411 uint32_t cache; /* Cache (32-bit pointer) */ 3412 uint32_t vtable; /* IMP * (32-bit pointer) */ 3413 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3414 }; 3415 3416 struct class_ro64_t { 3417 uint32_t flags; 3418 uint32_t instanceStart; 3419 uint32_t instanceSize; 3420 uint32_t reserved; 3421 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3422 uint64_t name; // const char * (64-bit pointer) 3423 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3424 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3425 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3426 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3427 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3428 }; 3429 3430 struct class_ro32_t { 3431 uint32_t flags; 3432 uint32_t instanceStart; 3433 uint32_t instanceSize; 3434 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3435 uint32_t name; /* const char * (32-bit pointer) */ 3436 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3437 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3438 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3439 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3440 uint32_t baseProperties; /* const struct objc_property_list * 3441 (32-bit pointer) */ 3442 }; 3443 3444 /* Values for class_ro{64,32}_t->flags */ 3445 #define RO_META (1 << 0) 3446 #define RO_ROOT (1 << 1) 3447 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3448 3449 struct method_list64_t { 3450 uint32_t entsize; 3451 uint32_t count; 3452 /* struct method64_t first; These structures follow inline */ 3453 }; 3454 3455 struct method_list32_t { 3456 uint32_t entsize; 3457 uint32_t count; 3458 /* struct method32_t first; These structures follow inline */ 3459 }; 3460 3461 struct method64_t { 3462 uint64_t name; /* SEL (64-bit pointer) */ 3463 uint64_t types; /* const char * (64-bit pointer) */ 3464 uint64_t imp; /* IMP (64-bit pointer) */ 3465 }; 3466 3467 struct method32_t { 3468 uint32_t name; /* SEL (32-bit pointer) */ 3469 uint32_t types; /* const char * (32-bit pointer) */ 3470 uint32_t imp; /* IMP (32-bit pointer) */ 3471 }; 3472 3473 struct protocol_list64_t { 3474 uint64_t count; /* uintptr_t (a 64-bit value) */ 3475 /* struct protocol64_t * list[0]; These pointers follow inline */ 3476 }; 3477 3478 struct protocol_list32_t { 3479 uint32_t count; /* uintptr_t (a 32-bit value) */ 3480 /* struct protocol32_t * list[0]; These pointers follow inline */ 3481 }; 3482 3483 struct protocol64_t { 3484 uint64_t isa; /* id * (64-bit pointer) */ 3485 uint64_t name; /* const char * (64-bit pointer) */ 3486 uint64_t protocols; /* struct protocol_list64_t * 3487 (64-bit pointer) */ 3488 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3489 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3490 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3491 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3492 uint64_t instanceProperties; /* struct objc_property_list * 3493 (64-bit pointer) */ 3494 }; 3495 3496 struct protocol32_t { 3497 uint32_t isa; /* id * (32-bit pointer) */ 3498 uint32_t name; /* const char * (32-bit pointer) */ 3499 uint32_t protocols; /* struct protocol_list_t * 3500 (32-bit pointer) */ 3501 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3502 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3503 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3504 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3505 uint32_t instanceProperties; /* struct objc_property_list * 3506 (32-bit pointer) */ 3507 }; 3508 3509 struct ivar_list64_t { 3510 uint32_t entsize; 3511 uint32_t count; 3512 /* struct ivar64_t first; These structures follow inline */ 3513 }; 3514 3515 struct ivar_list32_t { 3516 uint32_t entsize; 3517 uint32_t count; 3518 /* struct ivar32_t first; These structures follow inline */ 3519 }; 3520 3521 struct ivar64_t { 3522 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3523 uint64_t name; /* const char * (64-bit pointer) */ 3524 uint64_t type; /* const char * (64-bit pointer) */ 3525 uint32_t alignment; 3526 uint32_t size; 3527 }; 3528 3529 struct ivar32_t { 3530 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3531 uint32_t name; /* const char * (32-bit pointer) */ 3532 uint32_t type; /* const char * (32-bit pointer) */ 3533 uint32_t alignment; 3534 uint32_t size; 3535 }; 3536 3537 struct objc_property_list64 { 3538 uint32_t entsize; 3539 uint32_t count; 3540 /* struct objc_property64 first; These structures follow inline */ 3541 }; 3542 3543 struct objc_property_list32 { 3544 uint32_t entsize; 3545 uint32_t count; 3546 /* struct objc_property32 first; These structures follow inline */ 3547 }; 3548 3549 struct objc_property64 { 3550 uint64_t name; /* const char * (64-bit pointer) */ 3551 uint64_t attributes; /* const char * (64-bit pointer) */ 3552 }; 3553 3554 struct objc_property32 { 3555 uint32_t name; /* const char * (32-bit pointer) */ 3556 uint32_t attributes; /* const char * (32-bit pointer) */ 3557 }; 3558 3559 struct category64_t { 3560 uint64_t name; /* const char * (64-bit pointer) */ 3561 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3562 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3563 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3564 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3565 uint64_t instanceProperties; /* struct objc_property_list * 3566 (64-bit pointer) */ 3567 }; 3568 3569 struct category32_t { 3570 uint32_t name; /* const char * (32-bit pointer) */ 3571 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3572 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3573 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3574 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3575 uint32_t instanceProperties; /* struct objc_property_list * 3576 (32-bit pointer) */ 3577 }; 3578 3579 struct objc_image_info64 { 3580 uint32_t version; 3581 uint32_t flags; 3582 }; 3583 struct objc_image_info32 { 3584 uint32_t version; 3585 uint32_t flags; 3586 }; 3587 struct imageInfo_t { 3588 uint32_t version; 3589 uint32_t flags; 3590 }; 3591 /* masks for objc_image_info.flags */ 3592 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3593 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3594 #define OBJC_IMAGE_IS_SIMULATED (1 << 5) 3595 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6) 3596 3597 struct message_ref64 { 3598 uint64_t imp; /* IMP (64-bit pointer) */ 3599 uint64_t sel; /* SEL (64-bit pointer) */ 3600 }; 3601 3602 struct message_ref32 { 3603 uint32_t imp; /* IMP (32-bit pointer) */ 3604 uint32_t sel; /* SEL (32-bit pointer) */ 3605 }; 3606 3607 // Objective-C 1 (32-bit only) meta data structs. 3608 3609 struct objc_module_t { 3610 uint32_t version; 3611 uint32_t size; 3612 uint32_t name; /* char * (32-bit pointer) */ 3613 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3614 }; 3615 3616 struct objc_symtab_t { 3617 uint32_t sel_ref_cnt; 3618 uint32_t refs; /* SEL * (32-bit pointer) */ 3619 uint16_t cls_def_cnt; 3620 uint16_t cat_def_cnt; 3621 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3622 }; 3623 3624 struct objc_class_t { 3625 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3626 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3627 uint32_t name; /* const char * (32-bit pointer) */ 3628 int32_t version; 3629 int32_t info; 3630 int32_t instance_size; 3631 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3632 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3633 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3634 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3635 }; 3636 3637 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3638 // class is not a metaclass 3639 #define CLS_CLASS 0x1 3640 // class is a metaclass 3641 #define CLS_META 0x2 3642 3643 struct objc_category_t { 3644 uint32_t category_name; /* char * (32-bit pointer) */ 3645 uint32_t class_name; /* char * (32-bit pointer) */ 3646 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3647 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3648 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3649 }; 3650 3651 struct objc_ivar_t { 3652 uint32_t ivar_name; /* char * (32-bit pointer) */ 3653 uint32_t ivar_type; /* char * (32-bit pointer) */ 3654 int32_t ivar_offset; 3655 }; 3656 3657 struct objc_ivar_list_t { 3658 int32_t ivar_count; 3659 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3660 }; 3661 3662 struct objc_method_list_t { 3663 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3664 int32_t method_count; 3665 // struct objc_method_t method_list[1]; /* variable length structure */ 3666 }; 3667 3668 struct objc_method_t { 3669 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3670 uint32_t method_types; /* char * (32-bit pointer) */ 3671 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3672 (32-bit pointer) */ 3673 }; 3674 3675 struct objc_protocol_list_t { 3676 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3677 int32_t count; 3678 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3679 // (32-bit pointer) */ 3680 }; 3681 3682 struct objc_protocol_t { 3683 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3684 uint32_t protocol_name; /* char * (32-bit pointer) */ 3685 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3686 uint32_t instance_methods; /* struct objc_method_description_list * 3687 (32-bit pointer) */ 3688 uint32_t class_methods; /* struct objc_method_description_list * 3689 (32-bit pointer) */ 3690 }; 3691 3692 struct objc_method_description_list_t { 3693 int32_t count; 3694 // struct objc_method_description_t list[1]; 3695 }; 3696 3697 struct objc_method_description_t { 3698 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3699 uint32_t types; /* char * (32-bit pointer) */ 3700 }; 3701 3702 inline void swapStruct(struct cfstring64_t &cfs) { 3703 sys::swapByteOrder(cfs.isa); 3704 sys::swapByteOrder(cfs.flags); 3705 sys::swapByteOrder(cfs.characters); 3706 sys::swapByteOrder(cfs.length); 3707 } 3708 3709 inline void swapStruct(struct class64_t &c) { 3710 sys::swapByteOrder(c.isa); 3711 sys::swapByteOrder(c.superclass); 3712 sys::swapByteOrder(c.cache); 3713 sys::swapByteOrder(c.vtable); 3714 sys::swapByteOrder(c.data); 3715 } 3716 3717 inline void swapStruct(struct class32_t &c) { 3718 sys::swapByteOrder(c.isa); 3719 sys::swapByteOrder(c.superclass); 3720 sys::swapByteOrder(c.cache); 3721 sys::swapByteOrder(c.vtable); 3722 sys::swapByteOrder(c.data); 3723 } 3724 3725 inline void swapStruct(struct class_ro64_t &cro) { 3726 sys::swapByteOrder(cro.flags); 3727 sys::swapByteOrder(cro.instanceStart); 3728 sys::swapByteOrder(cro.instanceSize); 3729 sys::swapByteOrder(cro.reserved); 3730 sys::swapByteOrder(cro.ivarLayout); 3731 sys::swapByteOrder(cro.name); 3732 sys::swapByteOrder(cro.baseMethods); 3733 sys::swapByteOrder(cro.baseProtocols); 3734 sys::swapByteOrder(cro.ivars); 3735 sys::swapByteOrder(cro.weakIvarLayout); 3736 sys::swapByteOrder(cro.baseProperties); 3737 } 3738 3739 inline void swapStruct(struct class_ro32_t &cro) { 3740 sys::swapByteOrder(cro.flags); 3741 sys::swapByteOrder(cro.instanceStart); 3742 sys::swapByteOrder(cro.instanceSize); 3743 sys::swapByteOrder(cro.ivarLayout); 3744 sys::swapByteOrder(cro.name); 3745 sys::swapByteOrder(cro.baseMethods); 3746 sys::swapByteOrder(cro.baseProtocols); 3747 sys::swapByteOrder(cro.ivars); 3748 sys::swapByteOrder(cro.weakIvarLayout); 3749 sys::swapByteOrder(cro.baseProperties); 3750 } 3751 3752 inline void swapStruct(struct method_list64_t &ml) { 3753 sys::swapByteOrder(ml.entsize); 3754 sys::swapByteOrder(ml.count); 3755 } 3756 3757 inline void swapStruct(struct method_list32_t &ml) { 3758 sys::swapByteOrder(ml.entsize); 3759 sys::swapByteOrder(ml.count); 3760 } 3761 3762 inline void swapStruct(struct method64_t &m) { 3763 sys::swapByteOrder(m.name); 3764 sys::swapByteOrder(m.types); 3765 sys::swapByteOrder(m.imp); 3766 } 3767 3768 inline void swapStruct(struct method32_t &m) { 3769 sys::swapByteOrder(m.name); 3770 sys::swapByteOrder(m.types); 3771 sys::swapByteOrder(m.imp); 3772 } 3773 3774 inline void swapStruct(struct protocol_list64_t &pl) { 3775 sys::swapByteOrder(pl.count); 3776 } 3777 3778 inline void swapStruct(struct protocol_list32_t &pl) { 3779 sys::swapByteOrder(pl.count); 3780 } 3781 3782 inline void swapStruct(struct protocol64_t &p) { 3783 sys::swapByteOrder(p.isa); 3784 sys::swapByteOrder(p.name); 3785 sys::swapByteOrder(p.protocols); 3786 sys::swapByteOrder(p.instanceMethods); 3787 sys::swapByteOrder(p.classMethods); 3788 sys::swapByteOrder(p.optionalInstanceMethods); 3789 sys::swapByteOrder(p.optionalClassMethods); 3790 sys::swapByteOrder(p.instanceProperties); 3791 } 3792 3793 inline void swapStruct(struct protocol32_t &p) { 3794 sys::swapByteOrder(p.isa); 3795 sys::swapByteOrder(p.name); 3796 sys::swapByteOrder(p.protocols); 3797 sys::swapByteOrder(p.instanceMethods); 3798 sys::swapByteOrder(p.classMethods); 3799 sys::swapByteOrder(p.optionalInstanceMethods); 3800 sys::swapByteOrder(p.optionalClassMethods); 3801 sys::swapByteOrder(p.instanceProperties); 3802 } 3803 3804 inline void swapStruct(struct ivar_list64_t &il) { 3805 sys::swapByteOrder(il.entsize); 3806 sys::swapByteOrder(il.count); 3807 } 3808 3809 inline void swapStruct(struct ivar_list32_t &il) { 3810 sys::swapByteOrder(il.entsize); 3811 sys::swapByteOrder(il.count); 3812 } 3813 3814 inline void swapStruct(struct ivar64_t &i) { 3815 sys::swapByteOrder(i.offset); 3816 sys::swapByteOrder(i.name); 3817 sys::swapByteOrder(i.type); 3818 sys::swapByteOrder(i.alignment); 3819 sys::swapByteOrder(i.size); 3820 } 3821 3822 inline void swapStruct(struct ivar32_t &i) { 3823 sys::swapByteOrder(i.offset); 3824 sys::swapByteOrder(i.name); 3825 sys::swapByteOrder(i.type); 3826 sys::swapByteOrder(i.alignment); 3827 sys::swapByteOrder(i.size); 3828 } 3829 3830 inline void swapStruct(struct objc_property_list64 &pl) { 3831 sys::swapByteOrder(pl.entsize); 3832 sys::swapByteOrder(pl.count); 3833 } 3834 3835 inline void swapStruct(struct objc_property_list32 &pl) { 3836 sys::swapByteOrder(pl.entsize); 3837 sys::swapByteOrder(pl.count); 3838 } 3839 3840 inline void swapStruct(struct objc_property64 &op) { 3841 sys::swapByteOrder(op.name); 3842 sys::swapByteOrder(op.attributes); 3843 } 3844 3845 inline void swapStruct(struct objc_property32 &op) { 3846 sys::swapByteOrder(op.name); 3847 sys::swapByteOrder(op.attributes); 3848 } 3849 3850 inline void swapStruct(struct category64_t &c) { 3851 sys::swapByteOrder(c.name); 3852 sys::swapByteOrder(c.cls); 3853 sys::swapByteOrder(c.instanceMethods); 3854 sys::swapByteOrder(c.classMethods); 3855 sys::swapByteOrder(c.protocols); 3856 sys::swapByteOrder(c.instanceProperties); 3857 } 3858 3859 inline void swapStruct(struct category32_t &c) { 3860 sys::swapByteOrder(c.name); 3861 sys::swapByteOrder(c.cls); 3862 sys::swapByteOrder(c.instanceMethods); 3863 sys::swapByteOrder(c.classMethods); 3864 sys::swapByteOrder(c.protocols); 3865 sys::swapByteOrder(c.instanceProperties); 3866 } 3867 3868 inline void swapStruct(struct objc_image_info64 &o) { 3869 sys::swapByteOrder(o.version); 3870 sys::swapByteOrder(o.flags); 3871 } 3872 3873 inline void swapStruct(struct objc_image_info32 &o) { 3874 sys::swapByteOrder(o.version); 3875 sys::swapByteOrder(o.flags); 3876 } 3877 3878 inline void swapStruct(struct imageInfo_t &o) { 3879 sys::swapByteOrder(o.version); 3880 sys::swapByteOrder(o.flags); 3881 } 3882 3883 inline void swapStruct(struct message_ref64 &mr) { 3884 sys::swapByteOrder(mr.imp); 3885 sys::swapByteOrder(mr.sel); 3886 } 3887 3888 inline void swapStruct(struct message_ref32 &mr) { 3889 sys::swapByteOrder(mr.imp); 3890 sys::swapByteOrder(mr.sel); 3891 } 3892 3893 inline void swapStruct(struct objc_module_t &module) { 3894 sys::swapByteOrder(module.version); 3895 sys::swapByteOrder(module.size); 3896 sys::swapByteOrder(module.name); 3897 sys::swapByteOrder(module.symtab); 3898 } 3899 3900 inline void swapStruct(struct objc_symtab_t &symtab) { 3901 sys::swapByteOrder(symtab.sel_ref_cnt); 3902 sys::swapByteOrder(symtab.refs); 3903 sys::swapByteOrder(symtab.cls_def_cnt); 3904 sys::swapByteOrder(symtab.cat_def_cnt); 3905 } 3906 3907 inline void swapStruct(struct objc_class_t &objc_class) { 3908 sys::swapByteOrder(objc_class.isa); 3909 sys::swapByteOrder(objc_class.super_class); 3910 sys::swapByteOrder(objc_class.name); 3911 sys::swapByteOrder(objc_class.version); 3912 sys::swapByteOrder(objc_class.info); 3913 sys::swapByteOrder(objc_class.instance_size); 3914 sys::swapByteOrder(objc_class.ivars); 3915 sys::swapByteOrder(objc_class.methodLists); 3916 sys::swapByteOrder(objc_class.cache); 3917 sys::swapByteOrder(objc_class.protocols); 3918 } 3919 3920 inline void swapStruct(struct objc_category_t &objc_category) { 3921 sys::swapByteOrder(objc_category.category_name); 3922 sys::swapByteOrder(objc_category.class_name); 3923 sys::swapByteOrder(objc_category.instance_methods); 3924 sys::swapByteOrder(objc_category.class_methods); 3925 sys::swapByteOrder(objc_category.protocols); 3926 } 3927 3928 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 3929 sys::swapByteOrder(objc_ivar_list.ivar_count); 3930 } 3931 3932 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 3933 sys::swapByteOrder(objc_ivar.ivar_name); 3934 sys::swapByteOrder(objc_ivar.ivar_type); 3935 sys::swapByteOrder(objc_ivar.ivar_offset); 3936 } 3937 3938 inline void swapStruct(struct objc_method_list_t &method_list) { 3939 sys::swapByteOrder(method_list.obsolete); 3940 sys::swapByteOrder(method_list.method_count); 3941 } 3942 3943 inline void swapStruct(struct objc_method_t &method) { 3944 sys::swapByteOrder(method.method_name); 3945 sys::swapByteOrder(method.method_types); 3946 sys::swapByteOrder(method.method_imp); 3947 } 3948 3949 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 3950 sys::swapByteOrder(protocol_list.next); 3951 sys::swapByteOrder(protocol_list.count); 3952 } 3953 3954 inline void swapStruct(struct objc_protocol_t &protocol) { 3955 sys::swapByteOrder(protocol.isa); 3956 sys::swapByteOrder(protocol.protocol_name); 3957 sys::swapByteOrder(protocol.protocol_list); 3958 sys::swapByteOrder(protocol.instance_methods); 3959 sys::swapByteOrder(protocol.class_methods); 3960 } 3961 3962 inline void swapStruct(struct objc_method_description_list_t &mdl) { 3963 sys::swapByteOrder(mdl.count); 3964 } 3965 3966 inline void swapStruct(struct objc_method_description_t &md) { 3967 sys::swapByteOrder(md.name); 3968 sys::swapByteOrder(md.types); 3969 } 3970 3971 } // namespace 3972 3973 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 3974 struct DisassembleInfo *info); 3975 3976 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 3977 // to an Objective-C class and returns the class name. It is also passed the 3978 // address of the pointer, so when the pointer is zero as it can be in an .o 3979 // file, that is used to look for an external relocation entry with a symbol 3980 // name. 3981 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 3982 uint64_t ReferenceValue, 3983 struct DisassembleInfo *info) { 3984 const char *r; 3985 uint32_t offset, left; 3986 SectionRef S; 3987 3988 // The pointer_value can be 0 in an object file and have a relocation 3989 // entry for the class symbol at the ReferenceValue (the address of the 3990 // pointer). 3991 if (pointer_value == 0) { 3992 r = get_pointer_64(ReferenceValue, offset, left, S, info); 3993 if (r == nullptr || left < sizeof(uint64_t)) 3994 return nullptr; 3995 uint64_t n_value; 3996 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 3997 if (symbol_name == nullptr) 3998 return nullptr; 3999 const char *class_name = strrchr(symbol_name, '$'); 4000 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 4001 return class_name + 2; 4002 else 4003 return nullptr; 4004 } 4005 4006 // The case were the pointer_value is non-zero and points to a class defined 4007 // in this Mach-O file. 4008 r = get_pointer_64(pointer_value, offset, left, S, info); 4009 if (r == nullptr || left < sizeof(struct class64_t)) 4010 return nullptr; 4011 struct class64_t c; 4012 memcpy(&c, r, sizeof(struct class64_t)); 4013 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4014 swapStruct(c); 4015 if (c.data == 0) 4016 return nullptr; 4017 r = get_pointer_64(c.data, offset, left, S, info); 4018 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4019 return nullptr; 4020 struct class_ro64_t cro; 4021 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4022 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4023 swapStruct(cro); 4024 if (cro.name == 0) 4025 return nullptr; 4026 const char *name = get_pointer_64(cro.name, offset, left, S, info); 4027 return name; 4028 } 4029 4030 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 4031 // pointer to a cfstring and returns its name or nullptr. 4032 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 4033 struct DisassembleInfo *info) { 4034 const char *r, *name; 4035 uint32_t offset, left; 4036 SectionRef S; 4037 struct cfstring64_t cfs; 4038 uint64_t cfs_characters; 4039 4040 r = get_pointer_64(ReferenceValue, offset, left, S, info); 4041 if (r == nullptr || left < sizeof(struct cfstring64_t)) 4042 return nullptr; 4043 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 4044 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4045 swapStruct(cfs); 4046 if (cfs.characters == 0) { 4047 uint64_t n_value; 4048 const char *symbol_name = get_symbol_64( 4049 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 4050 if (symbol_name == nullptr) 4051 return nullptr; 4052 cfs_characters = n_value; 4053 } else 4054 cfs_characters = cfs.characters; 4055 name = get_pointer_64(cfs_characters, offset, left, S, info); 4056 4057 return name; 4058 } 4059 4060 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 4061 // of a pointer to an Objective-C selector reference when the pointer value is 4062 // zero as in a .o file and is likely to have a external relocation entry with 4063 // who's symbol's n_value is the real pointer to the selector name. If that is 4064 // the case the real pointer to the selector name is returned else 0 is 4065 // returned 4066 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 4067 struct DisassembleInfo *info) { 4068 uint32_t offset, left; 4069 SectionRef S; 4070 4071 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 4072 if (r == nullptr || left < sizeof(uint64_t)) 4073 return 0; 4074 uint64_t n_value; 4075 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 4076 if (symbol_name == nullptr) 4077 return 0; 4078 return n_value; 4079 } 4080 4081 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 4082 const char *sectname) { 4083 for (const SectionRef &Section : O->sections()) { 4084 StringRef SectName; 4085 Expected<StringRef> SecNameOrErr = Section.getName(); 4086 if (SecNameOrErr) 4087 SectName = *SecNameOrErr; 4088 else 4089 consumeError(SecNameOrErr.takeError()); 4090 4091 DataRefImpl Ref = Section.getRawDataRefImpl(); 4092 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4093 if (SegName == segname && SectName == sectname) 4094 return Section; 4095 } 4096 return SectionRef(); 4097 } 4098 4099 static void 4100 walk_pointer_list_64(const char *listname, const SectionRef S, 4101 MachOObjectFile *O, struct DisassembleInfo *info, 4102 void (*func)(uint64_t, struct DisassembleInfo *info)) { 4103 if (S == SectionRef()) 4104 return; 4105 4106 StringRef SectName; 4107 Expected<StringRef> SecNameOrErr = S.getName(); 4108 if (SecNameOrErr) 4109 SectName = *SecNameOrErr; 4110 else 4111 consumeError(SecNameOrErr.takeError()); 4112 4113 DataRefImpl Ref = S.getRawDataRefImpl(); 4114 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4115 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4116 4117 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4118 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4119 4120 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 4121 uint32_t left = S.getSize() - i; 4122 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 4123 uint64_t p = 0; 4124 memcpy(&p, Contents + i, size); 4125 if (i + sizeof(uint64_t) > S.getSize()) 4126 outs() << listname << " list pointer extends past end of (" << SegName 4127 << "," << SectName << ") section\n"; 4128 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 4129 4130 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4131 sys::swapByteOrder(p); 4132 4133 uint64_t n_value = 0; 4134 const char *name = get_symbol_64(i, S, info, n_value, p); 4135 if (name == nullptr) 4136 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 4137 4138 if (n_value != 0) { 4139 outs() << format("0x%" PRIx64, n_value); 4140 if (p != 0) 4141 outs() << " + " << format("0x%" PRIx64, p); 4142 } else 4143 outs() << format("0x%" PRIx64, p); 4144 if (name != nullptr) 4145 outs() << " " << name; 4146 outs() << "\n"; 4147 4148 p += n_value; 4149 if (func) 4150 func(p, info); 4151 } 4152 } 4153 4154 static void 4155 walk_pointer_list_32(const char *listname, const SectionRef S, 4156 MachOObjectFile *O, struct DisassembleInfo *info, 4157 void (*func)(uint32_t, struct DisassembleInfo *info)) { 4158 if (S == SectionRef()) 4159 return; 4160 4161 StringRef SectName = unwrapOrError(S.getName(), O->getFileName()); 4162 DataRefImpl Ref = S.getRawDataRefImpl(); 4163 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4164 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4165 4166 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4167 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4168 4169 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 4170 uint32_t left = S.getSize() - i; 4171 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 4172 uint32_t p = 0; 4173 memcpy(&p, Contents + i, size); 4174 if (i + sizeof(uint32_t) > S.getSize()) 4175 outs() << listname << " list pointer extends past end of (" << SegName 4176 << "," << SectName << ") section\n"; 4177 uint32_t Address = S.getAddress() + i; 4178 outs() << format("%08" PRIx32, Address) << " "; 4179 4180 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4181 sys::swapByteOrder(p); 4182 outs() << format("0x%" PRIx32, p); 4183 4184 const char *name = get_symbol_32(i, S, info, p); 4185 if (name != nullptr) 4186 outs() << " " << name; 4187 outs() << "\n"; 4188 4189 if (func) 4190 func(p, info); 4191 } 4192 } 4193 4194 static void print_layout_map(const char *layout_map, uint32_t left) { 4195 if (layout_map == nullptr) 4196 return; 4197 outs() << " layout map: "; 4198 do { 4199 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 4200 left--; 4201 layout_map++; 4202 } while (*layout_map != '\0' && left != 0); 4203 outs() << "\n"; 4204 } 4205 4206 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 4207 uint32_t offset, left; 4208 SectionRef S; 4209 const char *layout_map; 4210 4211 if (p == 0) 4212 return; 4213 layout_map = get_pointer_64(p, offset, left, S, info); 4214 print_layout_map(layout_map, left); 4215 } 4216 4217 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 4218 uint32_t offset, left; 4219 SectionRef S; 4220 const char *layout_map; 4221 4222 if (p == 0) 4223 return; 4224 layout_map = get_pointer_32(p, offset, left, S, info); 4225 print_layout_map(layout_map, left); 4226 } 4227 4228 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 4229 const char *indent) { 4230 struct method_list64_t ml; 4231 struct method64_t m; 4232 const char *r; 4233 uint32_t offset, xoffset, left, i; 4234 SectionRef S, xS; 4235 const char *name, *sym_name; 4236 uint64_t n_value; 4237 4238 r = get_pointer_64(p, offset, left, S, info); 4239 if (r == nullptr) 4240 return; 4241 memset(&ml, '\0', sizeof(struct method_list64_t)); 4242 if (left < sizeof(struct method_list64_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_list64_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_list64_t); 4253 offset += sizeof(struct method_list64_t); 4254 for (i = 0; i < ml.count; i++) { 4255 r = get_pointer_64(p, offset, left, S, info); 4256 if (r == nullptr) 4257 return; 4258 memset(&m, '\0', sizeof(struct method64_t)); 4259 if (left < sizeof(struct method64_t)) { 4260 memcpy(&m, r, left); 4261 outs() << indent << " (method_t extends past the end of the section)\n"; 4262 } else 4263 memcpy(&m, r, sizeof(struct method64_t)); 4264 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4265 swapStruct(m); 4266 4267 outs() << indent << "\t\t name "; 4268 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 4269 info, n_value, m.name); 4270 if (n_value != 0) { 4271 if (info->verbose && sym_name != nullptr) 4272 outs() << sym_name; 4273 else 4274 outs() << format("0x%" PRIx64, n_value); 4275 if (m.name != 0) 4276 outs() << " + " << format("0x%" PRIx64, m.name); 4277 } else 4278 outs() << format("0x%" PRIx64, m.name); 4279 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 4280 if (name != nullptr) 4281 outs() << format(" %.*s", left, name); 4282 outs() << "\n"; 4283 4284 outs() << indent << "\t\t types "; 4285 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 4286 info, n_value, m.types); 4287 if (n_value != 0) { 4288 if (info->verbose && sym_name != nullptr) 4289 outs() << sym_name; 4290 else 4291 outs() << format("0x%" PRIx64, n_value); 4292 if (m.types != 0) 4293 outs() << " + " << format("0x%" PRIx64, m.types); 4294 } else 4295 outs() << format("0x%" PRIx64, m.types); 4296 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 4297 if (name != nullptr) 4298 outs() << format(" %.*s", left, name); 4299 outs() << "\n"; 4300 4301 outs() << indent << "\t\t imp "; 4302 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 4303 n_value, m.imp); 4304 if (info->verbose && name == nullptr) { 4305 if (n_value != 0) { 4306 outs() << format("0x%" PRIx64, n_value) << " "; 4307 if (m.imp != 0) 4308 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 4309 } else 4310 outs() << format("0x%" PRIx64, m.imp) << " "; 4311 } 4312 if (name != nullptr) 4313 outs() << name; 4314 outs() << "\n"; 4315 4316 p += sizeof(struct method64_t); 4317 offset += sizeof(struct method64_t); 4318 } 4319 } 4320 4321 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 4322 const char *indent) { 4323 struct method_list32_t ml; 4324 struct method32_t m; 4325 const char *r, *name; 4326 uint32_t offset, xoffset, left, i; 4327 SectionRef S, xS; 4328 4329 r = get_pointer_32(p, offset, left, S, info); 4330 if (r == nullptr) 4331 return; 4332 memset(&ml, '\0', sizeof(struct method_list32_t)); 4333 if (left < sizeof(struct method_list32_t)) { 4334 memcpy(&ml, r, left); 4335 outs() << " (method_list_t entends past the end of the section)\n"; 4336 } else 4337 memcpy(&ml, r, sizeof(struct method_list32_t)); 4338 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4339 swapStruct(ml); 4340 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4341 outs() << indent << "\t\t count " << ml.count << "\n"; 4342 4343 p += sizeof(struct method_list32_t); 4344 offset += sizeof(struct method_list32_t); 4345 for (i = 0; i < ml.count; i++) { 4346 r = get_pointer_32(p, offset, left, S, info); 4347 if (r == nullptr) 4348 return; 4349 memset(&m, '\0', sizeof(struct method32_t)); 4350 if (left < sizeof(struct method32_t)) { 4351 memcpy(&ml, r, left); 4352 outs() << indent << " (method_t entends past the end of the section)\n"; 4353 } else 4354 memcpy(&m, r, sizeof(struct method32_t)); 4355 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4356 swapStruct(m); 4357 4358 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 4359 name = get_pointer_32(m.name, xoffset, left, xS, info); 4360 if (name != nullptr) 4361 outs() << format(" %.*s", left, name); 4362 outs() << "\n"; 4363 4364 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 4365 name = get_pointer_32(m.types, xoffset, left, xS, info); 4366 if (name != nullptr) 4367 outs() << format(" %.*s", left, name); 4368 outs() << "\n"; 4369 4370 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4371 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 4372 m.imp); 4373 if (name != nullptr) 4374 outs() << " " << name; 4375 outs() << "\n"; 4376 4377 p += sizeof(struct method32_t); 4378 offset += sizeof(struct method32_t); 4379 } 4380 } 4381 4382 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 4383 uint32_t offset, left, xleft; 4384 SectionRef S; 4385 struct objc_method_list_t method_list; 4386 struct objc_method_t method; 4387 const char *r, *methods, *name, *SymbolName; 4388 int32_t i; 4389 4390 r = get_pointer_32(p, offset, left, S, info, true); 4391 if (r == nullptr) 4392 return true; 4393 4394 outs() << "\n"; 4395 if (left > sizeof(struct objc_method_list_t)) { 4396 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 4397 } else { 4398 outs() << "\t\t objc_method_list extends past end of the section\n"; 4399 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 4400 memcpy(&method_list, r, left); 4401 } 4402 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4403 swapStruct(method_list); 4404 4405 outs() << "\t\t obsolete " 4406 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4407 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4408 4409 methods = r + sizeof(struct objc_method_list_t); 4410 for (i = 0; i < method_list.method_count; i++) { 4411 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4412 outs() << "\t\t remaining method's extend past the of the section\n"; 4413 break; 4414 } 4415 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4416 sizeof(struct objc_method_t)); 4417 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4418 swapStruct(method); 4419 4420 outs() << "\t\t method_name " 4421 << format("0x%08" PRIx32, method.method_name); 4422 if (info->verbose) { 4423 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4424 if (name != nullptr) 4425 outs() << format(" %.*s", xleft, name); 4426 else 4427 outs() << " (not in an __OBJC section)"; 4428 } 4429 outs() << "\n"; 4430 4431 outs() << "\t\t method_types " 4432 << format("0x%08" PRIx32, method.method_types); 4433 if (info->verbose) { 4434 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4435 if (name != nullptr) 4436 outs() << format(" %.*s", xleft, name); 4437 else 4438 outs() << " (not in an __OBJC section)"; 4439 } 4440 outs() << "\n"; 4441 4442 outs() << "\t\t method_imp " 4443 << format("0x%08" PRIx32, method.method_imp) << " "; 4444 if (info->verbose) { 4445 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4446 if (SymbolName != nullptr) 4447 outs() << SymbolName; 4448 } 4449 outs() << "\n"; 4450 } 4451 return false; 4452 } 4453 4454 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4455 struct protocol_list64_t pl; 4456 uint64_t q, n_value; 4457 struct protocol64_t pc; 4458 const char *r; 4459 uint32_t offset, xoffset, left, i; 4460 SectionRef S, xS; 4461 const char *name, *sym_name; 4462 4463 r = get_pointer_64(p, offset, left, S, info); 4464 if (r == nullptr) 4465 return; 4466 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4467 if (left < sizeof(struct protocol_list64_t)) { 4468 memcpy(&pl, r, left); 4469 outs() << " (protocol_list_t entends past the end of the section)\n"; 4470 } else 4471 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4472 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4473 swapStruct(pl); 4474 outs() << " count " << pl.count << "\n"; 4475 4476 p += sizeof(struct protocol_list64_t); 4477 offset += sizeof(struct protocol_list64_t); 4478 for (i = 0; i < pl.count; i++) { 4479 r = get_pointer_64(p, offset, left, S, info); 4480 if (r == nullptr) 4481 return; 4482 q = 0; 4483 if (left < sizeof(uint64_t)) { 4484 memcpy(&q, r, left); 4485 outs() << " (protocol_t * entends past the end of the section)\n"; 4486 } else 4487 memcpy(&q, r, sizeof(uint64_t)); 4488 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4489 sys::swapByteOrder(q); 4490 4491 outs() << "\t\t list[" << i << "] "; 4492 sym_name = get_symbol_64(offset, S, info, n_value, q); 4493 if (n_value != 0) { 4494 if (info->verbose && sym_name != nullptr) 4495 outs() << sym_name; 4496 else 4497 outs() << format("0x%" PRIx64, n_value); 4498 if (q != 0) 4499 outs() << " + " << format("0x%" PRIx64, q); 4500 } else 4501 outs() << format("0x%" PRIx64, q); 4502 outs() << " (struct protocol_t *)\n"; 4503 4504 r = get_pointer_64(q + n_value, offset, left, S, info); 4505 if (r == nullptr) 4506 return; 4507 memset(&pc, '\0', sizeof(struct protocol64_t)); 4508 if (left < sizeof(struct protocol64_t)) { 4509 memcpy(&pc, r, left); 4510 outs() << " (protocol_t entends past the end of the section)\n"; 4511 } else 4512 memcpy(&pc, r, sizeof(struct protocol64_t)); 4513 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4514 swapStruct(pc); 4515 4516 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4517 4518 outs() << "\t\t\t name "; 4519 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4520 info, n_value, pc.name); 4521 if (n_value != 0) { 4522 if (info->verbose && sym_name != nullptr) 4523 outs() << sym_name; 4524 else 4525 outs() << format("0x%" PRIx64, n_value); 4526 if (pc.name != 0) 4527 outs() << " + " << format("0x%" PRIx64, pc.name); 4528 } else 4529 outs() << format("0x%" PRIx64, pc.name); 4530 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4531 if (name != nullptr) 4532 outs() << format(" %.*s", left, name); 4533 outs() << "\n"; 4534 4535 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4536 4537 outs() << "\t\t instanceMethods "; 4538 sym_name = 4539 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4540 S, info, n_value, pc.instanceMethods); 4541 if (n_value != 0) { 4542 if (info->verbose && sym_name != nullptr) 4543 outs() << sym_name; 4544 else 4545 outs() << format("0x%" PRIx64, n_value); 4546 if (pc.instanceMethods != 0) 4547 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4548 } else 4549 outs() << format("0x%" PRIx64, pc.instanceMethods); 4550 outs() << " (struct method_list_t *)\n"; 4551 if (pc.instanceMethods + n_value != 0) 4552 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4553 4554 outs() << "\t\t classMethods "; 4555 sym_name = 4556 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4557 info, n_value, pc.classMethods); 4558 if (n_value != 0) { 4559 if (info->verbose && sym_name != nullptr) 4560 outs() << sym_name; 4561 else 4562 outs() << format("0x%" PRIx64, n_value); 4563 if (pc.classMethods != 0) 4564 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4565 } else 4566 outs() << format("0x%" PRIx64, pc.classMethods); 4567 outs() << " (struct method_list_t *)\n"; 4568 if (pc.classMethods + n_value != 0) 4569 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4570 4571 outs() << "\t optionalInstanceMethods " 4572 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4573 outs() << "\t optionalClassMethods " 4574 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4575 outs() << "\t instanceProperties " 4576 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4577 4578 p += sizeof(uint64_t); 4579 offset += sizeof(uint64_t); 4580 } 4581 } 4582 4583 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4584 struct protocol_list32_t pl; 4585 uint32_t q; 4586 struct protocol32_t pc; 4587 const char *r; 4588 uint32_t offset, xoffset, left, i; 4589 SectionRef S, xS; 4590 const char *name; 4591 4592 r = get_pointer_32(p, offset, left, S, info); 4593 if (r == nullptr) 4594 return; 4595 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4596 if (left < sizeof(struct protocol_list32_t)) { 4597 memcpy(&pl, r, left); 4598 outs() << " (protocol_list_t entends past the end of the section)\n"; 4599 } else 4600 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4601 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4602 swapStruct(pl); 4603 outs() << " count " << pl.count << "\n"; 4604 4605 p += sizeof(struct protocol_list32_t); 4606 offset += sizeof(struct protocol_list32_t); 4607 for (i = 0; i < pl.count; i++) { 4608 r = get_pointer_32(p, offset, left, S, info); 4609 if (r == nullptr) 4610 return; 4611 q = 0; 4612 if (left < sizeof(uint32_t)) { 4613 memcpy(&q, r, left); 4614 outs() << " (protocol_t * entends past the end of the section)\n"; 4615 } else 4616 memcpy(&q, r, sizeof(uint32_t)); 4617 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4618 sys::swapByteOrder(q); 4619 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4620 << " (struct protocol_t *)\n"; 4621 r = get_pointer_32(q, offset, left, S, info); 4622 if (r == nullptr) 4623 return; 4624 memset(&pc, '\0', sizeof(struct protocol32_t)); 4625 if (left < sizeof(struct protocol32_t)) { 4626 memcpy(&pc, r, left); 4627 outs() << " (protocol_t entends past the end of the section)\n"; 4628 } else 4629 memcpy(&pc, r, sizeof(struct protocol32_t)); 4630 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4631 swapStruct(pc); 4632 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4633 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4634 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4635 if (name != nullptr) 4636 outs() << format(" %.*s", left, name); 4637 outs() << "\n"; 4638 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4639 outs() << "\t\t instanceMethods " 4640 << format("0x%" PRIx32, pc.instanceMethods) 4641 << " (struct method_list_t *)\n"; 4642 if (pc.instanceMethods != 0) 4643 print_method_list32_t(pc.instanceMethods, info, "\t"); 4644 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4645 << " (struct method_list_t *)\n"; 4646 if (pc.classMethods != 0) 4647 print_method_list32_t(pc.classMethods, info, "\t"); 4648 outs() << "\t optionalInstanceMethods " 4649 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4650 outs() << "\t optionalClassMethods " 4651 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4652 outs() << "\t instanceProperties " 4653 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4654 p += sizeof(uint32_t); 4655 offset += sizeof(uint32_t); 4656 } 4657 } 4658 4659 static void print_indent(uint32_t indent) { 4660 for (uint32_t i = 0; i < indent;) { 4661 if (indent - i >= 8) { 4662 outs() << "\t"; 4663 i += 8; 4664 } else { 4665 for (uint32_t j = i; j < indent; j++) 4666 outs() << " "; 4667 return; 4668 } 4669 } 4670 } 4671 4672 static bool print_method_description_list(uint32_t p, uint32_t indent, 4673 struct DisassembleInfo *info) { 4674 uint32_t offset, left, xleft; 4675 SectionRef S; 4676 struct objc_method_description_list_t mdl; 4677 struct objc_method_description_t md; 4678 const char *r, *list, *name; 4679 int32_t i; 4680 4681 r = get_pointer_32(p, offset, left, S, info, true); 4682 if (r == nullptr) 4683 return true; 4684 4685 outs() << "\n"; 4686 if (left > sizeof(struct objc_method_description_list_t)) { 4687 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 4688 } else { 4689 print_indent(indent); 4690 outs() << " objc_method_description_list extends past end of the section\n"; 4691 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 4692 memcpy(&mdl, r, left); 4693 } 4694 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4695 swapStruct(mdl); 4696 4697 print_indent(indent); 4698 outs() << " count " << mdl.count << "\n"; 4699 4700 list = r + sizeof(struct objc_method_description_list_t); 4701 for (i = 0; i < mdl.count; i++) { 4702 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 4703 print_indent(indent); 4704 outs() << " remaining list entries extend past the of the section\n"; 4705 break; 4706 } 4707 print_indent(indent); 4708 outs() << " list[" << i << "]\n"; 4709 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 4710 sizeof(struct objc_method_description_t)); 4711 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4712 swapStruct(md); 4713 4714 print_indent(indent); 4715 outs() << " name " << format("0x%08" PRIx32, md.name); 4716 if (info->verbose) { 4717 name = get_pointer_32(md.name, offset, xleft, S, info, true); 4718 if (name != nullptr) 4719 outs() << format(" %.*s", xleft, name); 4720 else 4721 outs() << " (not in an __OBJC section)"; 4722 } 4723 outs() << "\n"; 4724 4725 print_indent(indent); 4726 outs() << " types " << format("0x%08" PRIx32, md.types); 4727 if (info->verbose) { 4728 name = get_pointer_32(md.types, offset, xleft, S, info, true); 4729 if (name != nullptr) 4730 outs() << format(" %.*s", xleft, name); 4731 else 4732 outs() << " (not in an __OBJC section)"; 4733 } 4734 outs() << "\n"; 4735 } 4736 return false; 4737 } 4738 4739 static bool print_protocol_list(uint32_t p, uint32_t indent, 4740 struct DisassembleInfo *info); 4741 4742 static bool print_protocol(uint32_t p, uint32_t indent, 4743 struct DisassembleInfo *info) { 4744 uint32_t offset, left; 4745 SectionRef S; 4746 struct objc_protocol_t protocol; 4747 const char *r, *name; 4748 4749 r = get_pointer_32(p, offset, left, S, info, true); 4750 if (r == nullptr) 4751 return true; 4752 4753 outs() << "\n"; 4754 if (left >= sizeof(struct objc_protocol_t)) { 4755 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 4756 } else { 4757 print_indent(indent); 4758 outs() << " Protocol extends past end of the section\n"; 4759 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 4760 memcpy(&protocol, r, left); 4761 } 4762 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4763 swapStruct(protocol); 4764 4765 print_indent(indent); 4766 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 4767 << "\n"; 4768 4769 print_indent(indent); 4770 outs() << " protocol_name " 4771 << format("0x%08" PRIx32, protocol.protocol_name); 4772 if (info->verbose) { 4773 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 4774 if (name != nullptr) 4775 outs() << format(" %.*s", left, name); 4776 else 4777 outs() << " (not in an __OBJC section)"; 4778 } 4779 outs() << "\n"; 4780 4781 print_indent(indent); 4782 outs() << " protocol_list " 4783 << format("0x%08" PRIx32, protocol.protocol_list); 4784 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 4785 outs() << " (not in an __OBJC section)\n"; 4786 4787 print_indent(indent); 4788 outs() << " instance_methods " 4789 << format("0x%08" PRIx32, protocol.instance_methods); 4790 if (print_method_description_list(protocol.instance_methods, indent, info)) 4791 outs() << " (not in an __OBJC section)\n"; 4792 4793 print_indent(indent); 4794 outs() << " class_methods " 4795 << format("0x%08" PRIx32, protocol.class_methods); 4796 if (print_method_description_list(protocol.class_methods, indent, info)) 4797 outs() << " (not in an __OBJC section)\n"; 4798 4799 return false; 4800 } 4801 4802 static bool print_protocol_list(uint32_t p, uint32_t indent, 4803 struct DisassembleInfo *info) { 4804 uint32_t offset, left, l; 4805 SectionRef S; 4806 struct objc_protocol_list_t protocol_list; 4807 const char *r, *list; 4808 int32_t i; 4809 4810 r = get_pointer_32(p, offset, left, S, info, true); 4811 if (r == nullptr) 4812 return true; 4813 4814 outs() << "\n"; 4815 if (left > sizeof(struct objc_protocol_list_t)) { 4816 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 4817 } else { 4818 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 4819 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 4820 memcpy(&protocol_list, r, left); 4821 } 4822 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4823 swapStruct(protocol_list); 4824 4825 print_indent(indent); 4826 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 4827 << "\n"; 4828 print_indent(indent); 4829 outs() << " count " << protocol_list.count << "\n"; 4830 4831 list = r + sizeof(struct objc_protocol_list_t); 4832 for (i = 0; i < protocol_list.count; i++) { 4833 if ((i + 1) * sizeof(uint32_t) > left) { 4834 outs() << "\t\t remaining list entries extend past the of the section\n"; 4835 break; 4836 } 4837 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 4838 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4839 sys::swapByteOrder(l); 4840 4841 print_indent(indent); 4842 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 4843 if (print_protocol(l, indent, info)) 4844 outs() << "(not in an __OBJC section)\n"; 4845 } 4846 return false; 4847 } 4848 4849 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 4850 struct ivar_list64_t il; 4851 struct ivar64_t i; 4852 const char *r; 4853 uint32_t offset, xoffset, left, j; 4854 SectionRef S, xS; 4855 const char *name, *sym_name, *ivar_offset_p; 4856 uint64_t ivar_offset, n_value; 4857 4858 r = get_pointer_64(p, offset, left, S, info); 4859 if (r == nullptr) 4860 return; 4861 memset(&il, '\0', sizeof(struct ivar_list64_t)); 4862 if (left < sizeof(struct ivar_list64_t)) { 4863 memcpy(&il, r, left); 4864 outs() << " (ivar_list_t entends past the end of the section)\n"; 4865 } else 4866 memcpy(&il, r, sizeof(struct ivar_list64_t)); 4867 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4868 swapStruct(il); 4869 outs() << " entsize " << il.entsize << "\n"; 4870 outs() << " count " << il.count << "\n"; 4871 4872 p += sizeof(struct ivar_list64_t); 4873 offset += sizeof(struct ivar_list64_t); 4874 for (j = 0; j < il.count; j++) { 4875 r = get_pointer_64(p, offset, left, S, info); 4876 if (r == nullptr) 4877 return; 4878 memset(&i, '\0', sizeof(struct ivar64_t)); 4879 if (left < sizeof(struct ivar64_t)) { 4880 memcpy(&i, r, left); 4881 outs() << " (ivar_t entends past the end of the section)\n"; 4882 } else 4883 memcpy(&i, r, sizeof(struct ivar64_t)); 4884 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4885 swapStruct(i); 4886 4887 outs() << "\t\t\t offset "; 4888 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 4889 info, n_value, i.offset); 4890 if (n_value != 0) { 4891 if (info->verbose && sym_name != nullptr) 4892 outs() << sym_name; 4893 else 4894 outs() << format("0x%" PRIx64, n_value); 4895 if (i.offset != 0) 4896 outs() << " + " << format("0x%" PRIx64, i.offset); 4897 } else 4898 outs() << format("0x%" PRIx64, i.offset); 4899 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 4900 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4901 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4902 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4903 sys::swapByteOrder(ivar_offset); 4904 outs() << " " << ivar_offset << "\n"; 4905 } else 4906 outs() << "\n"; 4907 4908 outs() << "\t\t\t name "; 4909 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 4910 n_value, i.name); 4911 if (n_value != 0) { 4912 if (info->verbose && sym_name != nullptr) 4913 outs() << sym_name; 4914 else 4915 outs() << format("0x%" PRIx64, n_value); 4916 if (i.name != 0) 4917 outs() << " + " << format("0x%" PRIx64, i.name); 4918 } else 4919 outs() << format("0x%" PRIx64, i.name); 4920 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 4921 if (name != nullptr) 4922 outs() << format(" %.*s", left, name); 4923 outs() << "\n"; 4924 4925 outs() << "\t\t\t type "; 4926 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 4927 n_value, i.name); 4928 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 4929 if (n_value != 0) { 4930 if (info->verbose && sym_name != nullptr) 4931 outs() << sym_name; 4932 else 4933 outs() << format("0x%" PRIx64, n_value); 4934 if (i.type != 0) 4935 outs() << " + " << format("0x%" PRIx64, i.type); 4936 } else 4937 outs() << format("0x%" PRIx64, i.type); 4938 if (name != nullptr) 4939 outs() << format(" %.*s", left, name); 4940 outs() << "\n"; 4941 4942 outs() << "\t\t\talignment " << i.alignment << "\n"; 4943 outs() << "\t\t\t size " << i.size << "\n"; 4944 4945 p += sizeof(struct ivar64_t); 4946 offset += sizeof(struct ivar64_t); 4947 } 4948 } 4949 4950 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 4951 struct ivar_list32_t il; 4952 struct ivar32_t i; 4953 const char *r; 4954 uint32_t offset, xoffset, left, j; 4955 SectionRef S, xS; 4956 const char *name, *ivar_offset_p; 4957 uint32_t ivar_offset; 4958 4959 r = get_pointer_32(p, offset, left, S, info); 4960 if (r == nullptr) 4961 return; 4962 memset(&il, '\0', sizeof(struct ivar_list32_t)); 4963 if (left < sizeof(struct ivar_list32_t)) { 4964 memcpy(&il, r, left); 4965 outs() << " (ivar_list_t entends past the end of the section)\n"; 4966 } else 4967 memcpy(&il, r, sizeof(struct ivar_list32_t)); 4968 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4969 swapStruct(il); 4970 outs() << " entsize " << il.entsize << "\n"; 4971 outs() << " count " << il.count << "\n"; 4972 4973 p += sizeof(struct ivar_list32_t); 4974 offset += sizeof(struct ivar_list32_t); 4975 for (j = 0; j < il.count; j++) { 4976 r = get_pointer_32(p, offset, left, S, info); 4977 if (r == nullptr) 4978 return; 4979 memset(&i, '\0', sizeof(struct ivar32_t)); 4980 if (left < sizeof(struct ivar32_t)) { 4981 memcpy(&i, r, left); 4982 outs() << " (ivar_t entends past the end of the section)\n"; 4983 } else 4984 memcpy(&i, r, sizeof(struct ivar32_t)); 4985 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4986 swapStruct(i); 4987 4988 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 4989 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 4990 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 4991 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 4992 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4993 sys::swapByteOrder(ivar_offset); 4994 outs() << " " << ivar_offset << "\n"; 4995 } else 4996 outs() << "\n"; 4997 4998 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 4999 name = get_pointer_32(i.name, xoffset, left, xS, info); 5000 if (name != nullptr) 5001 outs() << format(" %.*s", left, name); 5002 outs() << "\n"; 5003 5004 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 5005 name = get_pointer_32(i.type, xoffset, left, xS, info); 5006 if (name != nullptr) 5007 outs() << format(" %.*s", left, name); 5008 outs() << "\n"; 5009 5010 outs() << "\t\t\talignment " << i.alignment << "\n"; 5011 outs() << "\t\t\t size " << i.size << "\n"; 5012 5013 p += sizeof(struct ivar32_t); 5014 offset += sizeof(struct ivar32_t); 5015 } 5016 } 5017 5018 static void print_objc_property_list64(uint64_t p, 5019 struct DisassembleInfo *info) { 5020 struct objc_property_list64 opl; 5021 struct objc_property64 op; 5022 const char *r; 5023 uint32_t offset, xoffset, left, j; 5024 SectionRef S, xS; 5025 const char *name, *sym_name; 5026 uint64_t n_value; 5027 5028 r = get_pointer_64(p, offset, left, S, info); 5029 if (r == nullptr) 5030 return; 5031 memset(&opl, '\0', sizeof(struct objc_property_list64)); 5032 if (left < sizeof(struct objc_property_list64)) { 5033 memcpy(&opl, r, left); 5034 outs() << " (objc_property_list entends past the end of the section)\n"; 5035 } else 5036 memcpy(&opl, r, sizeof(struct objc_property_list64)); 5037 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5038 swapStruct(opl); 5039 outs() << " entsize " << opl.entsize << "\n"; 5040 outs() << " count " << opl.count << "\n"; 5041 5042 p += sizeof(struct objc_property_list64); 5043 offset += sizeof(struct objc_property_list64); 5044 for (j = 0; j < opl.count; j++) { 5045 r = get_pointer_64(p, offset, left, S, info); 5046 if (r == nullptr) 5047 return; 5048 memset(&op, '\0', sizeof(struct objc_property64)); 5049 if (left < sizeof(struct objc_property64)) { 5050 memcpy(&op, r, left); 5051 outs() << " (objc_property entends past the end of the section)\n"; 5052 } else 5053 memcpy(&op, r, sizeof(struct objc_property64)); 5054 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5055 swapStruct(op); 5056 5057 outs() << "\t\t\t name "; 5058 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 5059 info, n_value, op.name); 5060 if (n_value != 0) { 5061 if (info->verbose && sym_name != nullptr) 5062 outs() << sym_name; 5063 else 5064 outs() << format("0x%" PRIx64, n_value); 5065 if (op.name != 0) 5066 outs() << " + " << format("0x%" PRIx64, op.name); 5067 } else 5068 outs() << format("0x%" PRIx64, op.name); 5069 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 5070 if (name != nullptr) 5071 outs() << format(" %.*s", left, name); 5072 outs() << "\n"; 5073 5074 outs() << "\t\t\tattributes "; 5075 sym_name = 5076 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 5077 info, n_value, op.attributes); 5078 if (n_value != 0) { 5079 if (info->verbose && sym_name != nullptr) 5080 outs() << sym_name; 5081 else 5082 outs() << format("0x%" PRIx64, n_value); 5083 if (op.attributes != 0) 5084 outs() << " + " << format("0x%" PRIx64, op.attributes); 5085 } else 5086 outs() << format("0x%" PRIx64, op.attributes); 5087 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 5088 if (name != nullptr) 5089 outs() << format(" %.*s", left, name); 5090 outs() << "\n"; 5091 5092 p += sizeof(struct objc_property64); 5093 offset += sizeof(struct objc_property64); 5094 } 5095 } 5096 5097 static void print_objc_property_list32(uint32_t p, 5098 struct DisassembleInfo *info) { 5099 struct objc_property_list32 opl; 5100 struct objc_property32 op; 5101 const char *r; 5102 uint32_t offset, xoffset, left, j; 5103 SectionRef S, xS; 5104 const char *name; 5105 5106 r = get_pointer_32(p, offset, left, S, info); 5107 if (r == nullptr) 5108 return; 5109 memset(&opl, '\0', sizeof(struct objc_property_list32)); 5110 if (left < sizeof(struct objc_property_list32)) { 5111 memcpy(&opl, r, left); 5112 outs() << " (objc_property_list entends past the end of the section)\n"; 5113 } else 5114 memcpy(&opl, r, sizeof(struct objc_property_list32)); 5115 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5116 swapStruct(opl); 5117 outs() << " entsize " << opl.entsize << "\n"; 5118 outs() << " count " << opl.count << "\n"; 5119 5120 p += sizeof(struct objc_property_list32); 5121 offset += sizeof(struct objc_property_list32); 5122 for (j = 0; j < opl.count; j++) { 5123 r = get_pointer_32(p, offset, left, S, info); 5124 if (r == nullptr) 5125 return; 5126 memset(&op, '\0', sizeof(struct objc_property32)); 5127 if (left < sizeof(struct objc_property32)) { 5128 memcpy(&op, r, left); 5129 outs() << " (objc_property entends past the end of the section)\n"; 5130 } else 5131 memcpy(&op, r, sizeof(struct objc_property32)); 5132 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5133 swapStruct(op); 5134 5135 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 5136 name = get_pointer_32(op.name, xoffset, left, xS, info); 5137 if (name != nullptr) 5138 outs() << format(" %.*s", left, name); 5139 outs() << "\n"; 5140 5141 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 5142 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 5143 if (name != nullptr) 5144 outs() << format(" %.*s", left, name); 5145 outs() << "\n"; 5146 5147 p += sizeof(struct objc_property32); 5148 offset += sizeof(struct objc_property32); 5149 } 5150 } 5151 5152 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 5153 bool &is_meta_class) { 5154 struct class_ro64_t cro; 5155 const char *r; 5156 uint32_t offset, xoffset, left; 5157 SectionRef S, xS; 5158 const char *name, *sym_name; 5159 uint64_t n_value; 5160 5161 r = get_pointer_64(p, offset, left, S, info); 5162 if (r == nullptr || left < sizeof(struct class_ro64_t)) 5163 return false; 5164 memcpy(&cro, r, sizeof(struct class_ro64_t)); 5165 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5166 swapStruct(cro); 5167 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5168 if (cro.flags & RO_META) 5169 outs() << " RO_META"; 5170 if (cro.flags & RO_ROOT) 5171 outs() << " RO_ROOT"; 5172 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5173 outs() << " RO_HAS_CXX_STRUCTORS"; 5174 outs() << "\n"; 5175 outs() << " instanceStart " << cro.instanceStart << "\n"; 5176 outs() << " instanceSize " << cro.instanceSize << "\n"; 5177 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 5178 << "\n"; 5179 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 5180 << "\n"; 5181 print_layout_map64(cro.ivarLayout, info); 5182 5183 outs() << " name "; 5184 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 5185 info, n_value, cro.name); 5186 if (n_value != 0) { 5187 if (info->verbose && sym_name != nullptr) 5188 outs() << sym_name; 5189 else 5190 outs() << format("0x%" PRIx64, n_value); 5191 if (cro.name != 0) 5192 outs() << " + " << format("0x%" PRIx64, cro.name); 5193 } else 5194 outs() << format("0x%" PRIx64, cro.name); 5195 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 5196 if (name != nullptr) 5197 outs() << format(" %.*s", left, name); 5198 outs() << "\n"; 5199 5200 outs() << " baseMethods "; 5201 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 5202 S, info, n_value, cro.baseMethods); 5203 if (n_value != 0) { 5204 if (info->verbose && sym_name != nullptr) 5205 outs() << sym_name; 5206 else 5207 outs() << format("0x%" PRIx64, n_value); 5208 if (cro.baseMethods != 0) 5209 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 5210 } else 5211 outs() << format("0x%" PRIx64, cro.baseMethods); 5212 outs() << " (struct method_list_t *)\n"; 5213 if (cro.baseMethods + n_value != 0) 5214 print_method_list64_t(cro.baseMethods + n_value, info, ""); 5215 5216 outs() << " baseProtocols "; 5217 sym_name = 5218 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 5219 info, n_value, cro.baseProtocols); 5220 if (n_value != 0) { 5221 if (info->verbose && sym_name != nullptr) 5222 outs() << sym_name; 5223 else 5224 outs() << format("0x%" PRIx64, n_value); 5225 if (cro.baseProtocols != 0) 5226 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 5227 } else 5228 outs() << format("0x%" PRIx64, cro.baseProtocols); 5229 outs() << "\n"; 5230 if (cro.baseProtocols + n_value != 0) 5231 print_protocol_list64_t(cro.baseProtocols + n_value, info); 5232 5233 outs() << " ivars "; 5234 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 5235 info, n_value, cro.ivars); 5236 if (n_value != 0) { 5237 if (info->verbose && sym_name != nullptr) 5238 outs() << sym_name; 5239 else 5240 outs() << format("0x%" PRIx64, n_value); 5241 if (cro.ivars != 0) 5242 outs() << " + " << format("0x%" PRIx64, cro.ivars); 5243 } else 5244 outs() << format("0x%" PRIx64, cro.ivars); 5245 outs() << "\n"; 5246 if (cro.ivars + n_value != 0) 5247 print_ivar_list64_t(cro.ivars + n_value, info); 5248 5249 outs() << " weakIvarLayout "; 5250 sym_name = 5251 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 5252 info, n_value, cro.weakIvarLayout); 5253 if (n_value != 0) { 5254 if (info->verbose && sym_name != nullptr) 5255 outs() << sym_name; 5256 else 5257 outs() << format("0x%" PRIx64, n_value); 5258 if (cro.weakIvarLayout != 0) 5259 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 5260 } else 5261 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 5262 outs() << "\n"; 5263 print_layout_map64(cro.weakIvarLayout + n_value, info); 5264 5265 outs() << " baseProperties "; 5266 sym_name = 5267 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 5268 info, n_value, cro.baseProperties); 5269 if (n_value != 0) { 5270 if (info->verbose && sym_name != nullptr) 5271 outs() << sym_name; 5272 else 5273 outs() << format("0x%" PRIx64, n_value); 5274 if (cro.baseProperties != 0) 5275 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 5276 } else 5277 outs() << format("0x%" PRIx64, cro.baseProperties); 5278 outs() << "\n"; 5279 if (cro.baseProperties + n_value != 0) 5280 print_objc_property_list64(cro.baseProperties + n_value, info); 5281 5282 is_meta_class = (cro.flags & RO_META) != 0; 5283 return true; 5284 } 5285 5286 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 5287 bool &is_meta_class) { 5288 struct class_ro32_t cro; 5289 const char *r; 5290 uint32_t offset, xoffset, left; 5291 SectionRef S, xS; 5292 const char *name; 5293 5294 r = get_pointer_32(p, offset, left, S, info); 5295 if (r == nullptr) 5296 return false; 5297 memset(&cro, '\0', sizeof(struct class_ro32_t)); 5298 if (left < sizeof(struct class_ro32_t)) { 5299 memcpy(&cro, r, left); 5300 outs() << " (class_ro_t entends past the end of the section)\n"; 5301 } else 5302 memcpy(&cro, r, sizeof(struct class_ro32_t)); 5303 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5304 swapStruct(cro); 5305 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5306 if (cro.flags & RO_META) 5307 outs() << " RO_META"; 5308 if (cro.flags & RO_ROOT) 5309 outs() << " RO_ROOT"; 5310 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5311 outs() << " RO_HAS_CXX_STRUCTORS"; 5312 outs() << "\n"; 5313 outs() << " instanceStart " << cro.instanceStart << "\n"; 5314 outs() << " instanceSize " << cro.instanceSize << "\n"; 5315 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 5316 << "\n"; 5317 print_layout_map32(cro.ivarLayout, info); 5318 5319 outs() << " name " << format("0x%" PRIx32, cro.name); 5320 name = get_pointer_32(cro.name, xoffset, left, xS, info); 5321 if (name != nullptr) 5322 outs() << format(" %.*s", left, name); 5323 outs() << "\n"; 5324 5325 outs() << " baseMethods " 5326 << format("0x%" PRIx32, cro.baseMethods) 5327 << " (struct method_list_t *)\n"; 5328 if (cro.baseMethods != 0) 5329 print_method_list32_t(cro.baseMethods, info, ""); 5330 5331 outs() << " baseProtocols " 5332 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 5333 if (cro.baseProtocols != 0) 5334 print_protocol_list32_t(cro.baseProtocols, info); 5335 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 5336 << "\n"; 5337 if (cro.ivars != 0) 5338 print_ivar_list32_t(cro.ivars, info); 5339 outs() << " weakIvarLayout " 5340 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 5341 print_layout_map32(cro.weakIvarLayout, info); 5342 outs() << " baseProperties " 5343 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 5344 if (cro.baseProperties != 0) 5345 print_objc_property_list32(cro.baseProperties, info); 5346 is_meta_class = (cro.flags & RO_META) != 0; 5347 return true; 5348 } 5349 5350 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 5351 struct class64_t c; 5352 const char *r; 5353 uint32_t offset, left; 5354 SectionRef S; 5355 const char *name; 5356 uint64_t isa_n_value, n_value; 5357 5358 r = get_pointer_64(p, offset, left, S, info); 5359 if (r == nullptr || left < sizeof(struct class64_t)) 5360 return; 5361 memcpy(&c, r, sizeof(struct class64_t)); 5362 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5363 swapStruct(c); 5364 5365 outs() << " isa " << format("0x%" PRIx64, c.isa); 5366 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 5367 isa_n_value, c.isa); 5368 if (name != nullptr) 5369 outs() << " " << name; 5370 outs() << "\n"; 5371 5372 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 5373 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 5374 n_value, c.superclass); 5375 if (name != nullptr) 5376 outs() << " " << name; 5377 else { 5378 name = get_dyld_bind_info_symbolname(S.getAddress() + 5379 offset + offsetof(struct class64_t, superclass), info); 5380 if (name != nullptr) 5381 outs() << " " << name; 5382 } 5383 outs() << "\n"; 5384 5385 outs() << " cache " << format("0x%" PRIx64, c.cache); 5386 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 5387 n_value, c.cache); 5388 if (name != nullptr) 5389 outs() << " " << name; 5390 outs() << "\n"; 5391 5392 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 5393 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 5394 n_value, c.vtable); 5395 if (name != nullptr) 5396 outs() << " " << name; 5397 outs() << "\n"; 5398 5399 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 5400 n_value, c.data); 5401 outs() << " data "; 5402 if (n_value != 0) { 5403 if (info->verbose && name != nullptr) 5404 outs() << name; 5405 else 5406 outs() << format("0x%" PRIx64, n_value); 5407 if (c.data != 0) 5408 outs() << " + " << format("0x%" PRIx64, c.data); 5409 } else 5410 outs() << format("0x%" PRIx64, c.data); 5411 outs() << " (struct class_ro_t *)"; 5412 5413 // This is a Swift class if some of the low bits of the pointer are set. 5414 if ((c.data + n_value) & 0x7) 5415 outs() << " Swift class"; 5416 outs() << "\n"; 5417 bool is_meta_class; 5418 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5419 return; 5420 5421 if (!is_meta_class && 5422 c.isa + isa_n_value != p && 5423 c.isa + isa_n_value != 0 && 5424 info->depth < 100) { 5425 info->depth++; 5426 outs() << "Meta Class\n"; 5427 print_class64_t(c.isa + isa_n_value, info); 5428 } 5429 } 5430 5431 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5432 struct class32_t c; 5433 const char *r; 5434 uint32_t offset, left; 5435 SectionRef S; 5436 const char *name; 5437 5438 r = get_pointer_32(p, offset, left, S, info); 5439 if (r == nullptr) 5440 return; 5441 memset(&c, '\0', sizeof(struct class32_t)); 5442 if (left < sizeof(struct class32_t)) { 5443 memcpy(&c, r, left); 5444 outs() << " (class_t entends past the end of the section)\n"; 5445 } else 5446 memcpy(&c, r, sizeof(struct class32_t)); 5447 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5448 swapStruct(c); 5449 5450 outs() << " isa " << format("0x%" PRIx32, c.isa); 5451 name = 5452 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5453 if (name != nullptr) 5454 outs() << " " << name; 5455 outs() << "\n"; 5456 5457 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5458 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5459 c.superclass); 5460 if (name != nullptr) 5461 outs() << " " << name; 5462 outs() << "\n"; 5463 5464 outs() << " cache " << format("0x%" PRIx32, c.cache); 5465 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5466 c.cache); 5467 if (name != nullptr) 5468 outs() << " " << name; 5469 outs() << "\n"; 5470 5471 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5472 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5473 c.vtable); 5474 if (name != nullptr) 5475 outs() << " " << name; 5476 outs() << "\n"; 5477 5478 name = 5479 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5480 outs() << " data " << format("0x%" PRIx32, c.data) 5481 << " (struct class_ro_t *)"; 5482 5483 // This is a Swift class if some of the low bits of the pointer are set. 5484 if (c.data & 0x3) 5485 outs() << " Swift class"; 5486 outs() << "\n"; 5487 bool is_meta_class; 5488 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5489 return; 5490 5491 if (!is_meta_class) { 5492 outs() << "Meta Class\n"; 5493 print_class32_t(c.isa, info); 5494 } 5495 } 5496 5497 static void print_objc_class_t(struct objc_class_t *objc_class, 5498 struct DisassembleInfo *info) { 5499 uint32_t offset, left, xleft; 5500 const char *name, *p, *ivar_list; 5501 SectionRef S; 5502 int32_t i; 5503 struct objc_ivar_list_t objc_ivar_list; 5504 struct objc_ivar_t ivar; 5505 5506 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5507 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5508 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5509 if (name != nullptr) 5510 outs() << format(" %.*s", left, name); 5511 else 5512 outs() << " (not in an __OBJC section)"; 5513 } 5514 outs() << "\n"; 5515 5516 outs() << "\t super_class " 5517 << format("0x%08" PRIx32, objc_class->super_class); 5518 if (info->verbose) { 5519 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5520 if (name != nullptr) 5521 outs() << format(" %.*s", left, name); 5522 else 5523 outs() << " (not in an __OBJC section)"; 5524 } 5525 outs() << "\n"; 5526 5527 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5528 if (info->verbose) { 5529 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5530 if (name != nullptr) 5531 outs() << format(" %.*s", left, name); 5532 else 5533 outs() << " (not in an __OBJC section)"; 5534 } 5535 outs() << "\n"; 5536 5537 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5538 << "\n"; 5539 5540 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5541 if (info->verbose) { 5542 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5543 outs() << " CLS_CLASS"; 5544 else if (CLS_GETINFO(objc_class, CLS_META)) 5545 outs() << " CLS_META"; 5546 } 5547 outs() << "\n"; 5548 5549 outs() << "\t instance_size " 5550 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5551 5552 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5553 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5554 if (p != nullptr) { 5555 if (left > sizeof(struct objc_ivar_list_t)) { 5556 outs() << "\n"; 5557 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5558 } else { 5559 outs() << " (entends past the end of the section)\n"; 5560 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5561 memcpy(&objc_ivar_list, p, left); 5562 } 5563 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5564 swapStruct(objc_ivar_list); 5565 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5566 ivar_list = p + sizeof(struct objc_ivar_list_t); 5567 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5568 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5569 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5570 break; 5571 } 5572 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5573 sizeof(struct objc_ivar_t)); 5574 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5575 swapStruct(ivar); 5576 5577 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5578 if (info->verbose) { 5579 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5580 if (name != nullptr) 5581 outs() << format(" %.*s", xleft, name); 5582 else 5583 outs() << " (not in an __OBJC section)"; 5584 } 5585 outs() << "\n"; 5586 5587 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5588 if (info->verbose) { 5589 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5590 if (name != nullptr) 5591 outs() << format(" %.*s", xleft, name); 5592 else 5593 outs() << " (not in an __OBJC section)"; 5594 } 5595 outs() << "\n"; 5596 5597 outs() << "\t\t ivar_offset " 5598 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5599 } 5600 } else { 5601 outs() << " (not in an __OBJC section)\n"; 5602 } 5603 5604 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5605 if (print_method_list(objc_class->methodLists, info)) 5606 outs() << " (not in an __OBJC section)\n"; 5607 5608 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5609 << "\n"; 5610 5611 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5612 if (print_protocol_list(objc_class->protocols, 16, info)) 5613 outs() << " (not in an __OBJC section)\n"; 5614 } 5615 5616 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5617 struct DisassembleInfo *info) { 5618 uint32_t offset, left; 5619 const char *name; 5620 SectionRef S; 5621 5622 outs() << "\t category name " 5623 << format("0x%08" PRIx32, objc_category->category_name); 5624 if (info->verbose) { 5625 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5626 true); 5627 if (name != nullptr) 5628 outs() << format(" %.*s", left, name); 5629 else 5630 outs() << " (not in an __OBJC section)"; 5631 } 5632 outs() << "\n"; 5633 5634 outs() << "\t\t class name " 5635 << format("0x%08" PRIx32, objc_category->class_name); 5636 if (info->verbose) { 5637 name = 5638 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5639 if (name != nullptr) 5640 outs() << format(" %.*s", left, name); 5641 else 5642 outs() << " (not in an __OBJC section)"; 5643 } 5644 outs() << "\n"; 5645 5646 outs() << "\t instance methods " 5647 << format("0x%08" PRIx32, objc_category->instance_methods); 5648 if (print_method_list(objc_category->instance_methods, info)) 5649 outs() << " (not in an __OBJC section)\n"; 5650 5651 outs() << "\t class methods " 5652 << format("0x%08" PRIx32, objc_category->class_methods); 5653 if (print_method_list(objc_category->class_methods, info)) 5654 outs() << " (not in an __OBJC section)\n"; 5655 } 5656 5657 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5658 struct category64_t c; 5659 const char *r; 5660 uint32_t offset, xoffset, left; 5661 SectionRef S, xS; 5662 const char *name, *sym_name; 5663 uint64_t n_value; 5664 5665 r = get_pointer_64(p, offset, left, S, info); 5666 if (r == nullptr) 5667 return; 5668 memset(&c, '\0', sizeof(struct category64_t)); 5669 if (left < sizeof(struct category64_t)) { 5670 memcpy(&c, r, left); 5671 outs() << " (category_t entends past the end of the section)\n"; 5672 } else 5673 memcpy(&c, r, sizeof(struct category64_t)); 5674 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5675 swapStruct(c); 5676 5677 outs() << " name "; 5678 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 5679 info, n_value, c.name); 5680 if (n_value != 0) { 5681 if (info->verbose && sym_name != nullptr) 5682 outs() << sym_name; 5683 else 5684 outs() << format("0x%" PRIx64, n_value); 5685 if (c.name != 0) 5686 outs() << " + " << format("0x%" PRIx64, c.name); 5687 } else 5688 outs() << format("0x%" PRIx64, c.name); 5689 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 5690 if (name != nullptr) 5691 outs() << format(" %.*s", left, name); 5692 outs() << "\n"; 5693 5694 outs() << " cls "; 5695 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 5696 n_value, c.cls); 5697 if (n_value != 0) { 5698 if (info->verbose && sym_name != nullptr) 5699 outs() << sym_name; 5700 else 5701 outs() << format("0x%" PRIx64, n_value); 5702 if (c.cls != 0) 5703 outs() << " + " << format("0x%" PRIx64, c.cls); 5704 } else 5705 outs() << format("0x%" PRIx64, c.cls); 5706 outs() << "\n"; 5707 if (c.cls + n_value != 0) 5708 print_class64_t(c.cls + n_value, info); 5709 5710 outs() << " instanceMethods "; 5711 sym_name = 5712 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 5713 info, n_value, c.instanceMethods); 5714 if (n_value != 0) { 5715 if (info->verbose && sym_name != nullptr) 5716 outs() << sym_name; 5717 else 5718 outs() << format("0x%" PRIx64, n_value); 5719 if (c.instanceMethods != 0) 5720 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 5721 } else 5722 outs() << format("0x%" PRIx64, c.instanceMethods); 5723 outs() << "\n"; 5724 if (c.instanceMethods + n_value != 0) 5725 print_method_list64_t(c.instanceMethods + n_value, info, ""); 5726 5727 outs() << " classMethods "; 5728 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 5729 S, info, n_value, c.classMethods); 5730 if (n_value != 0) { 5731 if (info->verbose && sym_name != nullptr) 5732 outs() << sym_name; 5733 else 5734 outs() << format("0x%" PRIx64, n_value); 5735 if (c.classMethods != 0) 5736 outs() << " + " << format("0x%" PRIx64, c.classMethods); 5737 } else 5738 outs() << format("0x%" PRIx64, c.classMethods); 5739 outs() << "\n"; 5740 if (c.classMethods + n_value != 0) 5741 print_method_list64_t(c.classMethods + n_value, info, ""); 5742 5743 outs() << " protocols "; 5744 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 5745 info, n_value, c.protocols); 5746 if (n_value != 0) { 5747 if (info->verbose && sym_name != nullptr) 5748 outs() << sym_name; 5749 else 5750 outs() << format("0x%" PRIx64, n_value); 5751 if (c.protocols != 0) 5752 outs() << " + " << format("0x%" PRIx64, c.protocols); 5753 } else 5754 outs() << format("0x%" PRIx64, c.protocols); 5755 outs() << "\n"; 5756 if (c.protocols + n_value != 0) 5757 print_protocol_list64_t(c.protocols + n_value, info); 5758 5759 outs() << "instanceProperties "; 5760 sym_name = 5761 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 5762 S, info, n_value, c.instanceProperties); 5763 if (n_value != 0) { 5764 if (info->verbose && sym_name != nullptr) 5765 outs() << sym_name; 5766 else 5767 outs() << format("0x%" PRIx64, n_value); 5768 if (c.instanceProperties != 0) 5769 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 5770 } else 5771 outs() << format("0x%" PRIx64, c.instanceProperties); 5772 outs() << "\n"; 5773 if (c.instanceProperties + n_value != 0) 5774 print_objc_property_list64(c.instanceProperties + n_value, info); 5775 } 5776 5777 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 5778 struct category32_t c; 5779 const char *r; 5780 uint32_t offset, left; 5781 SectionRef S, xS; 5782 const char *name; 5783 5784 r = get_pointer_32(p, offset, left, S, info); 5785 if (r == nullptr) 5786 return; 5787 memset(&c, '\0', sizeof(struct category32_t)); 5788 if (left < sizeof(struct category32_t)) { 5789 memcpy(&c, r, left); 5790 outs() << " (category_t entends past the end of the section)\n"; 5791 } else 5792 memcpy(&c, r, sizeof(struct category32_t)); 5793 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5794 swapStruct(c); 5795 5796 outs() << " name " << format("0x%" PRIx32, c.name); 5797 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 5798 c.name); 5799 if (name) 5800 outs() << " " << name; 5801 outs() << "\n"; 5802 5803 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 5804 if (c.cls != 0) 5805 print_class32_t(c.cls, info); 5806 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 5807 << "\n"; 5808 if (c.instanceMethods != 0) 5809 print_method_list32_t(c.instanceMethods, info, ""); 5810 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 5811 << "\n"; 5812 if (c.classMethods != 0) 5813 print_method_list32_t(c.classMethods, info, ""); 5814 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 5815 if (c.protocols != 0) 5816 print_protocol_list32_t(c.protocols, info); 5817 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 5818 << "\n"; 5819 if (c.instanceProperties != 0) 5820 print_objc_property_list32(c.instanceProperties, info); 5821 } 5822 5823 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 5824 uint32_t i, left, offset, xoffset; 5825 uint64_t p, n_value; 5826 struct message_ref64 mr; 5827 const char *name, *sym_name; 5828 const char *r; 5829 SectionRef xS; 5830 5831 if (S == SectionRef()) 5832 return; 5833 5834 StringRef SectName; 5835 Expected<StringRef> SecNameOrErr = S.getName(); 5836 if (SecNameOrErr) 5837 SectName = *SecNameOrErr; 5838 else 5839 consumeError(SecNameOrErr.takeError()); 5840 5841 DataRefImpl Ref = S.getRawDataRefImpl(); 5842 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5843 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5844 offset = 0; 5845 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5846 p = S.getAddress() + i; 5847 r = get_pointer_64(p, offset, left, S, info); 5848 if (r == nullptr) 5849 return; 5850 memset(&mr, '\0', sizeof(struct message_ref64)); 5851 if (left < sizeof(struct message_ref64)) { 5852 memcpy(&mr, r, left); 5853 outs() << " (message_ref entends past the end of the section)\n"; 5854 } else 5855 memcpy(&mr, r, sizeof(struct message_ref64)); 5856 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5857 swapStruct(mr); 5858 5859 outs() << " imp "; 5860 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 5861 n_value, mr.imp); 5862 if (n_value != 0) { 5863 outs() << format("0x%" PRIx64, n_value) << " "; 5864 if (mr.imp != 0) 5865 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 5866 } else 5867 outs() << format("0x%" PRIx64, mr.imp) << " "; 5868 if (name != nullptr) 5869 outs() << " " << name; 5870 outs() << "\n"; 5871 5872 outs() << " sel "; 5873 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 5874 info, n_value, mr.sel); 5875 if (n_value != 0) { 5876 if (info->verbose && sym_name != nullptr) 5877 outs() << sym_name; 5878 else 5879 outs() << format("0x%" PRIx64, n_value); 5880 if (mr.sel != 0) 5881 outs() << " + " << format("0x%" PRIx64, mr.sel); 5882 } else 5883 outs() << format("0x%" PRIx64, mr.sel); 5884 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 5885 if (name != nullptr) 5886 outs() << format(" %.*s", left, name); 5887 outs() << "\n"; 5888 5889 offset += sizeof(struct message_ref64); 5890 } 5891 } 5892 5893 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 5894 uint32_t i, left, offset, xoffset, p; 5895 struct message_ref32 mr; 5896 const char *name, *r; 5897 SectionRef xS; 5898 5899 if (S == SectionRef()) 5900 return; 5901 5902 StringRef SectName; 5903 Expected<StringRef> SecNameOrErr = S.getName(); 5904 if (SecNameOrErr) 5905 SectName = *SecNameOrErr; 5906 else 5907 consumeError(SecNameOrErr.takeError()); 5908 5909 DataRefImpl Ref = S.getRawDataRefImpl(); 5910 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5911 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5912 offset = 0; 5913 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 5914 p = S.getAddress() + i; 5915 r = get_pointer_32(p, offset, left, S, info); 5916 if (r == nullptr) 5917 return; 5918 memset(&mr, '\0', sizeof(struct message_ref32)); 5919 if (left < sizeof(struct message_ref32)) { 5920 memcpy(&mr, r, left); 5921 outs() << " (message_ref entends past the end of the section)\n"; 5922 } else 5923 memcpy(&mr, r, sizeof(struct message_ref32)); 5924 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5925 swapStruct(mr); 5926 5927 outs() << " imp " << format("0x%" PRIx32, mr.imp); 5928 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 5929 mr.imp); 5930 if (name != nullptr) 5931 outs() << " " << name; 5932 outs() << "\n"; 5933 5934 outs() << " sel " << format("0x%" PRIx32, mr.sel); 5935 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 5936 if (name != nullptr) 5937 outs() << " " << name; 5938 outs() << "\n"; 5939 5940 offset += sizeof(struct message_ref32); 5941 } 5942 } 5943 5944 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 5945 uint32_t left, offset, swift_version; 5946 uint64_t p; 5947 struct objc_image_info64 o; 5948 const char *r; 5949 5950 if (S == SectionRef()) 5951 return; 5952 5953 StringRef SectName; 5954 Expected<StringRef> SecNameOrErr = S.getName(); 5955 if (SecNameOrErr) 5956 SectName = *SecNameOrErr; 5957 else 5958 consumeError(SecNameOrErr.takeError()); 5959 5960 DataRefImpl Ref = S.getRawDataRefImpl(); 5961 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 5962 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 5963 p = S.getAddress(); 5964 r = get_pointer_64(p, offset, left, S, info); 5965 if (r == nullptr) 5966 return; 5967 memset(&o, '\0', sizeof(struct objc_image_info64)); 5968 if (left < sizeof(struct objc_image_info64)) { 5969 memcpy(&o, r, left); 5970 outs() << " (objc_image_info entends past the end of the section)\n"; 5971 } else 5972 memcpy(&o, r, sizeof(struct objc_image_info64)); 5973 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5974 swapStruct(o); 5975 outs() << " version " << o.version << "\n"; 5976 outs() << " flags " << format("0x%" PRIx32, o.flags); 5977 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 5978 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 5979 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 5980 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 5981 if (o.flags & OBJC_IMAGE_IS_SIMULATED) 5982 outs() << " OBJC_IMAGE_IS_SIMULATED"; 5983 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES) 5984 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES"; 5985 swift_version = (o.flags >> 8) & 0xff; 5986 if (swift_version != 0) { 5987 if (swift_version == 1) 5988 outs() << " Swift 1.0"; 5989 else if (swift_version == 2) 5990 outs() << " Swift 1.1"; 5991 else if(swift_version == 3) 5992 outs() << " Swift 2.0"; 5993 else if(swift_version == 4) 5994 outs() << " Swift 3.0"; 5995 else if(swift_version == 5) 5996 outs() << " Swift 4.0"; 5997 else if(swift_version == 6) 5998 outs() << " Swift 4.1/Swift 4.2"; 5999 else if(swift_version == 7) 6000 outs() << " Swift 5 or later"; 6001 else 6002 outs() << " unknown future Swift version (" << swift_version << ")"; 6003 } 6004 outs() << "\n"; 6005 } 6006 6007 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 6008 uint32_t left, offset, swift_version, p; 6009 struct objc_image_info32 o; 6010 const char *r; 6011 6012 if (S == SectionRef()) 6013 return; 6014 6015 StringRef SectName; 6016 Expected<StringRef> SecNameOrErr = S.getName(); 6017 if (SecNameOrErr) 6018 SectName = *SecNameOrErr; 6019 else 6020 consumeError(SecNameOrErr.takeError()); 6021 6022 DataRefImpl Ref = S.getRawDataRefImpl(); 6023 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6024 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6025 p = S.getAddress(); 6026 r = get_pointer_32(p, offset, left, S, info); 6027 if (r == nullptr) 6028 return; 6029 memset(&o, '\0', sizeof(struct objc_image_info32)); 6030 if (left < sizeof(struct objc_image_info32)) { 6031 memcpy(&o, r, left); 6032 outs() << " (objc_image_info entends past the end of the section)\n"; 6033 } else 6034 memcpy(&o, r, sizeof(struct objc_image_info32)); 6035 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6036 swapStruct(o); 6037 outs() << " version " << o.version << "\n"; 6038 outs() << " flags " << format("0x%" PRIx32, o.flags); 6039 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 6040 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 6041 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 6042 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 6043 swift_version = (o.flags >> 8) & 0xff; 6044 if (swift_version != 0) { 6045 if (swift_version == 1) 6046 outs() << " Swift 1.0"; 6047 else if (swift_version == 2) 6048 outs() << " Swift 1.1"; 6049 else if(swift_version == 3) 6050 outs() << " Swift 2.0"; 6051 else if(swift_version == 4) 6052 outs() << " Swift 3.0"; 6053 else if(swift_version == 5) 6054 outs() << " Swift 4.0"; 6055 else if(swift_version == 6) 6056 outs() << " Swift 4.1/Swift 4.2"; 6057 else if(swift_version == 7) 6058 outs() << " Swift 5 or later"; 6059 else 6060 outs() << " unknown future Swift version (" << swift_version << ")"; 6061 } 6062 outs() << "\n"; 6063 } 6064 6065 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 6066 uint32_t left, offset, p; 6067 struct imageInfo_t o; 6068 const char *r; 6069 6070 StringRef SectName; 6071 Expected<StringRef> SecNameOrErr = S.getName(); 6072 if (SecNameOrErr) 6073 SectName = *SecNameOrErr; 6074 else 6075 consumeError(SecNameOrErr.takeError()); 6076 6077 DataRefImpl Ref = S.getRawDataRefImpl(); 6078 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6079 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6080 p = S.getAddress(); 6081 r = get_pointer_32(p, offset, left, S, info); 6082 if (r == nullptr) 6083 return; 6084 memset(&o, '\0', sizeof(struct imageInfo_t)); 6085 if (left < sizeof(struct imageInfo_t)) { 6086 memcpy(&o, r, left); 6087 outs() << " (imageInfo entends past the end of the section)\n"; 6088 } else 6089 memcpy(&o, r, sizeof(struct imageInfo_t)); 6090 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6091 swapStruct(o); 6092 outs() << " version " << o.version << "\n"; 6093 outs() << " flags " << format("0x%" PRIx32, o.flags); 6094 if (o.flags & 0x1) 6095 outs() << " F&C"; 6096 if (o.flags & 0x2) 6097 outs() << " GC"; 6098 if (o.flags & 0x4) 6099 outs() << " GC-only"; 6100 else 6101 outs() << " RR"; 6102 outs() << "\n"; 6103 } 6104 6105 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 6106 SymbolAddressMap AddrMap; 6107 if (verbose) 6108 CreateSymbolAddressMap(O, &AddrMap); 6109 6110 std::vector<SectionRef> Sections; 6111 append_range(Sections, O->sections()); 6112 6113 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6114 6115 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6116 if (CL == SectionRef()) 6117 CL = get_section(O, "__DATA", "__objc_classlist"); 6118 if (CL == SectionRef()) 6119 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6120 if (CL == SectionRef()) 6121 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6122 info.S = CL; 6123 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 6124 6125 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6126 if (CR == SectionRef()) 6127 CR = get_section(O, "__DATA", "__objc_classrefs"); 6128 if (CR == SectionRef()) 6129 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6130 if (CR == SectionRef()) 6131 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6132 info.S = CR; 6133 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 6134 6135 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6136 if (SR == SectionRef()) 6137 SR = get_section(O, "__DATA", "__objc_superrefs"); 6138 if (SR == SectionRef()) 6139 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6140 if (SR == SectionRef()) 6141 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6142 info.S = SR; 6143 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 6144 6145 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6146 if (CA == SectionRef()) 6147 CA = get_section(O, "__DATA", "__objc_catlist"); 6148 if (CA == SectionRef()) 6149 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6150 if (CA == SectionRef()) 6151 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6152 info.S = CA; 6153 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 6154 6155 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6156 if (PL == SectionRef()) 6157 PL = get_section(O, "__DATA", "__objc_protolist"); 6158 if (PL == SectionRef()) 6159 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6160 if (PL == SectionRef()) 6161 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6162 info.S = PL; 6163 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 6164 6165 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6166 if (MR == SectionRef()) 6167 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6168 if (MR == SectionRef()) 6169 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6170 if (MR == SectionRef()) 6171 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6172 info.S = MR; 6173 print_message_refs64(MR, &info); 6174 6175 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6176 if (II == SectionRef()) 6177 II = get_section(O, "__DATA", "__objc_imageinfo"); 6178 if (II == SectionRef()) 6179 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6180 if (II == SectionRef()) 6181 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6182 info.S = II; 6183 print_image_info64(II, &info); 6184 } 6185 6186 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6187 SymbolAddressMap AddrMap; 6188 if (verbose) 6189 CreateSymbolAddressMap(O, &AddrMap); 6190 6191 std::vector<SectionRef> Sections; 6192 append_range(Sections, O->sections()); 6193 6194 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6195 6196 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6197 if (CL == SectionRef()) 6198 CL = get_section(O, "__DATA", "__objc_classlist"); 6199 if (CL == SectionRef()) 6200 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6201 if (CL == SectionRef()) 6202 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6203 info.S = CL; 6204 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 6205 6206 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6207 if (CR == SectionRef()) 6208 CR = get_section(O, "__DATA", "__objc_classrefs"); 6209 if (CR == SectionRef()) 6210 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6211 if (CR == SectionRef()) 6212 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6213 info.S = CR; 6214 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 6215 6216 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6217 if (SR == SectionRef()) 6218 SR = get_section(O, "__DATA", "__objc_superrefs"); 6219 if (SR == SectionRef()) 6220 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6221 if (SR == SectionRef()) 6222 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6223 info.S = SR; 6224 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 6225 6226 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6227 if (CA == SectionRef()) 6228 CA = get_section(O, "__DATA", "__objc_catlist"); 6229 if (CA == SectionRef()) 6230 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6231 if (CA == SectionRef()) 6232 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6233 info.S = CA; 6234 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 6235 6236 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6237 if (PL == SectionRef()) 6238 PL = get_section(O, "__DATA", "__objc_protolist"); 6239 if (PL == SectionRef()) 6240 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6241 if (PL == SectionRef()) 6242 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6243 info.S = PL; 6244 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 6245 6246 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6247 if (MR == SectionRef()) 6248 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6249 if (MR == SectionRef()) 6250 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6251 if (MR == SectionRef()) 6252 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6253 info.S = MR; 6254 print_message_refs32(MR, &info); 6255 6256 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6257 if (II == SectionRef()) 6258 II = get_section(O, "__DATA", "__objc_imageinfo"); 6259 if (II == SectionRef()) 6260 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6261 if (II == SectionRef()) 6262 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6263 info.S = II; 6264 print_image_info32(II, &info); 6265 } 6266 6267 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6268 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 6269 const char *r, *name, *defs; 6270 struct objc_module_t module; 6271 SectionRef S, xS; 6272 struct objc_symtab_t symtab; 6273 struct objc_class_t objc_class; 6274 struct objc_category_t objc_category; 6275 6276 outs() << "Objective-C segment\n"; 6277 S = get_section(O, "__OBJC", "__module_info"); 6278 if (S == SectionRef()) 6279 return false; 6280 6281 SymbolAddressMap AddrMap; 6282 if (verbose) 6283 CreateSymbolAddressMap(O, &AddrMap); 6284 6285 std::vector<SectionRef> Sections; 6286 append_range(Sections, O->sections()); 6287 6288 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6289 6290 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 6291 p = S.getAddress() + i; 6292 r = get_pointer_32(p, offset, left, S, &info, true); 6293 if (r == nullptr) 6294 return true; 6295 memset(&module, '\0', sizeof(struct objc_module_t)); 6296 if (left < sizeof(struct objc_module_t)) { 6297 memcpy(&module, r, left); 6298 outs() << " (module extends past end of __module_info section)\n"; 6299 } else 6300 memcpy(&module, r, sizeof(struct objc_module_t)); 6301 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6302 swapStruct(module); 6303 6304 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 6305 outs() << " version " << module.version << "\n"; 6306 outs() << " size " << module.size << "\n"; 6307 outs() << " name "; 6308 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 6309 if (name != nullptr) 6310 outs() << format("%.*s", left, name); 6311 else 6312 outs() << format("0x%08" PRIx32, module.name) 6313 << "(not in an __OBJC section)"; 6314 outs() << "\n"; 6315 6316 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 6317 if (module.symtab == 0 || r == nullptr) { 6318 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 6319 << " (not in an __OBJC section)\n"; 6320 continue; 6321 } 6322 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 6323 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 6324 defs_left = 0; 6325 defs = nullptr; 6326 if (left < sizeof(struct objc_symtab_t)) { 6327 memcpy(&symtab, r, left); 6328 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 6329 } else { 6330 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 6331 if (left > sizeof(struct objc_symtab_t)) { 6332 defs_left = left - sizeof(struct objc_symtab_t); 6333 defs = r + sizeof(struct objc_symtab_t); 6334 } 6335 } 6336 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6337 swapStruct(symtab); 6338 6339 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 6340 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 6341 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 6342 if (r == nullptr) 6343 outs() << " (not in an __OBJC section)"; 6344 outs() << "\n"; 6345 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 6346 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 6347 if (symtab.cls_def_cnt > 0) 6348 outs() << "\tClass Definitions\n"; 6349 for (j = 0; j < symtab.cls_def_cnt; j++) { 6350 if ((j + 1) * sizeof(uint32_t) > defs_left) { 6351 outs() << "\t(remaining class defs entries entends past the end of the " 6352 << "section)\n"; 6353 break; 6354 } 6355 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 6356 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6357 sys::swapByteOrder(def); 6358 6359 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6360 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 6361 if (r != nullptr) { 6362 if (left > sizeof(struct objc_class_t)) { 6363 outs() << "\n"; 6364 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6365 } else { 6366 outs() << " (entends past the end of the section)\n"; 6367 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6368 memcpy(&objc_class, r, left); 6369 } 6370 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6371 swapStruct(objc_class); 6372 print_objc_class_t(&objc_class, &info); 6373 } else { 6374 outs() << "(not in an __OBJC section)\n"; 6375 } 6376 6377 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 6378 outs() << "\tMeta Class"; 6379 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 6380 if (r != nullptr) { 6381 if (left > sizeof(struct objc_class_t)) { 6382 outs() << "\n"; 6383 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6384 } else { 6385 outs() << " (entends past the end of the section)\n"; 6386 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6387 memcpy(&objc_class, r, left); 6388 } 6389 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6390 swapStruct(objc_class); 6391 print_objc_class_t(&objc_class, &info); 6392 } else { 6393 outs() << "(not in an __OBJC section)\n"; 6394 } 6395 } 6396 } 6397 if (symtab.cat_def_cnt > 0) 6398 outs() << "\tCategory Definitions\n"; 6399 for (j = 0; j < symtab.cat_def_cnt; j++) { 6400 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 6401 outs() << "\t(remaining category defs entries entends past the end of " 6402 << "the section)\n"; 6403 break; 6404 } 6405 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6406 sizeof(uint32_t)); 6407 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6408 sys::swapByteOrder(def); 6409 6410 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6411 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6412 << format("0x%08" PRIx32, def); 6413 if (r != nullptr) { 6414 if (left > sizeof(struct objc_category_t)) { 6415 outs() << "\n"; 6416 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6417 } else { 6418 outs() << " (entends past the end of the section)\n"; 6419 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6420 memcpy(&objc_category, r, left); 6421 } 6422 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6423 swapStruct(objc_category); 6424 print_objc_objc_category_t(&objc_category, &info); 6425 } else { 6426 outs() << "(not in an __OBJC section)\n"; 6427 } 6428 } 6429 } 6430 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6431 if (II != SectionRef()) 6432 print_image_info(II, &info); 6433 6434 return true; 6435 } 6436 6437 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6438 uint32_t size, uint32_t addr) { 6439 SymbolAddressMap AddrMap; 6440 CreateSymbolAddressMap(O, &AddrMap); 6441 6442 std::vector<SectionRef> Sections; 6443 append_range(Sections, O->sections()); 6444 6445 struct DisassembleInfo info(O, &AddrMap, &Sections, true); 6446 6447 const char *p; 6448 struct objc_protocol_t protocol; 6449 uint32_t left, paddr; 6450 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6451 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6452 left = size - (p - sect); 6453 if (left < sizeof(struct objc_protocol_t)) { 6454 outs() << "Protocol extends past end of __protocol section\n"; 6455 memcpy(&protocol, p, left); 6456 } else 6457 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6458 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6459 swapStruct(protocol); 6460 paddr = addr + (p - sect); 6461 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6462 if (print_protocol(paddr, 0, &info)) 6463 outs() << "(not in an __OBJC section)\n"; 6464 } 6465 } 6466 6467 #ifdef LLVM_HAVE_LIBXAR 6468 static inline void swapStruct(struct xar_header &xar) { 6469 sys::swapByteOrder(xar.magic); 6470 sys::swapByteOrder(xar.size); 6471 sys::swapByteOrder(xar.version); 6472 sys::swapByteOrder(xar.toc_length_compressed); 6473 sys::swapByteOrder(xar.toc_length_uncompressed); 6474 sys::swapByteOrder(xar.cksum_alg); 6475 } 6476 6477 static void PrintModeVerbose(uint32_t mode) { 6478 switch(mode & S_IFMT){ 6479 case S_IFDIR: 6480 outs() << "d"; 6481 break; 6482 case S_IFCHR: 6483 outs() << "c"; 6484 break; 6485 case S_IFBLK: 6486 outs() << "b"; 6487 break; 6488 case S_IFREG: 6489 outs() << "-"; 6490 break; 6491 case S_IFLNK: 6492 outs() << "l"; 6493 break; 6494 case S_IFSOCK: 6495 outs() << "s"; 6496 break; 6497 default: 6498 outs() << "?"; 6499 break; 6500 } 6501 6502 /* owner permissions */ 6503 if(mode & S_IREAD) 6504 outs() << "r"; 6505 else 6506 outs() << "-"; 6507 if(mode & S_IWRITE) 6508 outs() << "w"; 6509 else 6510 outs() << "-"; 6511 if(mode & S_ISUID) 6512 outs() << "s"; 6513 else if(mode & S_IEXEC) 6514 outs() << "x"; 6515 else 6516 outs() << "-"; 6517 6518 /* group permissions */ 6519 if(mode & (S_IREAD >> 3)) 6520 outs() << "r"; 6521 else 6522 outs() << "-"; 6523 if(mode & (S_IWRITE >> 3)) 6524 outs() << "w"; 6525 else 6526 outs() << "-"; 6527 if(mode & S_ISGID) 6528 outs() << "s"; 6529 else if(mode & (S_IEXEC >> 3)) 6530 outs() << "x"; 6531 else 6532 outs() << "-"; 6533 6534 /* other permissions */ 6535 if(mode & (S_IREAD >> 6)) 6536 outs() << "r"; 6537 else 6538 outs() << "-"; 6539 if(mode & (S_IWRITE >> 6)) 6540 outs() << "w"; 6541 else 6542 outs() << "-"; 6543 if(mode & S_ISVTX) 6544 outs() << "t"; 6545 else if(mode & (S_IEXEC >> 6)) 6546 outs() << "x"; 6547 else 6548 outs() << "-"; 6549 } 6550 6551 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { 6552 xar_file_t xf; 6553 const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; 6554 char *endp; 6555 uint32_t mode_value; 6556 6557 ScopedXarIter xi; 6558 if (!xi) { 6559 WithColor::error(errs(), "llvm-objdump") 6560 << "can't obtain an xar iterator for xar archive " << XarFilename 6561 << "\n"; 6562 return; 6563 } 6564 6565 // Go through the xar's files. 6566 for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { 6567 ScopedXarIter xp; 6568 if(!xp){ 6569 WithColor::error(errs(), "llvm-objdump") 6570 << "can't obtain an xar iterator for xar archive " << XarFilename 6571 << "\n"; 6572 return; 6573 } 6574 type = nullptr; 6575 mode = nullptr; 6576 user = nullptr; 6577 group = nullptr; 6578 size = nullptr; 6579 mtime = nullptr; 6580 name = nullptr; 6581 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6582 const char *val = nullptr; 6583 xar_prop_get(xf, key, &val); 6584 #if 0 // Useful for debugging. 6585 outs() << "key: " << key << " value: " << val << "\n"; 6586 #endif 6587 if(strcmp(key, "type") == 0) 6588 type = val; 6589 if(strcmp(key, "mode") == 0) 6590 mode = val; 6591 if(strcmp(key, "user") == 0) 6592 user = val; 6593 if(strcmp(key, "group") == 0) 6594 group = val; 6595 if(strcmp(key, "data/size") == 0) 6596 size = val; 6597 if(strcmp(key, "mtime") == 0) 6598 mtime = val; 6599 if(strcmp(key, "name") == 0) 6600 name = val; 6601 } 6602 if(mode != nullptr){ 6603 mode_value = strtoul(mode, &endp, 8); 6604 if(*endp != '\0') 6605 outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; 6606 if(strcmp(type, "file") == 0) 6607 mode_value |= S_IFREG; 6608 PrintModeVerbose(mode_value); 6609 outs() << " "; 6610 } 6611 if(user != nullptr) 6612 outs() << format("%10s/", user); 6613 if(group != nullptr) 6614 outs() << format("%-10s ", group); 6615 if(size != nullptr) 6616 outs() << format("%7s ", size); 6617 if(mtime != nullptr){ 6618 for(m = mtime; *m != 'T' && *m != '\0'; m++) 6619 outs() << *m; 6620 if(*m == 'T') 6621 m++; 6622 outs() << " "; 6623 for( ; *m != 'Z' && *m != '\0'; m++) 6624 outs() << *m; 6625 outs() << " "; 6626 } 6627 if(name != nullptr) 6628 outs() << name; 6629 outs() << "\n"; 6630 } 6631 } 6632 6633 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, 6634 uint32_t size, bool verbose, 6635 bool PrintXarHeader, bool PrintXarFileHeaders, 6636 std::string XarMemberName) { 6637 if(size < sizeof(struct xar_header)) { 6638 outs() << "size of (__LLVM,__bundle) section too small (smaller than size " 6639 "of struct xar_header)\n"; 6640 return; 6641 } 6642 struct xar_header XarHeader; 6643 memcpy(&XarHeader, sect, sizeof(struct xar_header)); 6644 if (sys::IsLittleEndianHost) 6645 swapStruct(XarHeader); 6646 if (PrintXarHeader) { 6647 if (!XarMemberName.empty()) 6648 outs() << "In xar member " << XarMemberName << ": "; 6649 else 6650 outs() << "For (__LLVM,__bundle) section: "; 6651 outs() << "xar header\n"; 6652 if (XarHeader.magic == XAR_HEADER_MAGIC) 6653 outs() << " magic XAR_HEADER_MAGIC\n"; 6654 else 6655 outs() << " magic " 6656 << format_hex(XarHeader.magic, 10, true) 6657 << " (not XAR_HEADER_MAGIC)\n"; 6658 outs() << " size " << XarHeader.size << "\n"; 6659 outs() << " version " << XarHeader.version << "\n"; 6660 outs() << " toc_length_compressed " << XarHeader.toc_length_compressed 6661 << "\n"; 6662 outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed 6663 << "\n"; 6664 outs() << " cksum_alg "; 6665 switch (XarHeader.cksum_alg) { 6666 case XAR_CKSUM_NONE: 6667 outs() << "XAR_CKSUM_NONE\n"; 6668 break; 6669 case XAR_CKSUM_SHA1: 6670 outs() << "XAR_CKSUM_SHA1\n"; 6671 break; 6672 case XAR_CKSUM_MD5: 6673 outs() << "XAR_CKSUM_MD5\n"; 6674 break; 6675 #ifdef XAR_CKSUM_SHA256 6676 case XAR_CKSUM_SHA256: 6677 outs() << "XAR_CKSUM_SHA256\n"; 6678 break; 6679 #endif 6680 #ifdef XAR_CKSUM_SHA512 6681 case XAR_CKSUM_SHA512: 6682 outs() << "XAR_CKSUM_SHA512\n"; 6683 break; 6684 #endif 6685 default: 6686 outs() << XarHeader.cksum_alg << "\n"; 6687 } 6688 } 6689 6690 SmallString<128> XarFilename; 6691 int FD; 6692 std::error_code XarEC = 6693 sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); 6694 if (XarEC) { 6695 WithColor::error(errs(), "llvm-objdump") << XarEC.message() << "\n"; 6696 return; 6697 } 6698 ToolOutputFile XarFile(XarFilename, FD); 6699 raw_fd_ostream &XarOut = XarFile.os(); 6700 StringRef XarContents(sect, size); 6701 XarOut << XarContents; 6702 XarOut.close(); 6703 if (XarOut.has_error()) 6704 return; 6705 6706 ScopedXarFile xar(XarFilename.c_str(), READ); 6707 if (!xar) { 6708 WithColor::error(errs(), "llvm-objdump") 6709 << "can't create temporary xar archive " << XarFilename << "\n"; 6710 return; 6711 } 6712 6713 SmallString<128> TocFilename; 6714 std::error_code TocEC = 6715 sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); 6716 if (TocEC) { 6717 WithColor::error(errs(), "llvm-objdump") << TocEC.message() << "\n"; 6718 return; 6719 } 6720 xar_serialize(xar, TocFilename.c_str()); 6721 6722 if (PrintXarFileHeaders) { 6723 if (!XarMemberName.empty()) 6724 outs() << "In xar member " << XarMemberName << ": "; 6725 else 6726 outs() << "For (__LLVM,__bundle) section: "; 6727 outs() << "xar archive files:\n"; 6728 PrintXarFilesSummary(XarFilename.c_str(), xar); 6729 } 6730 6731 ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 6732 MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); 6733 if (std::error_code EC = FileOrErr.getError()) { 6734 WithColor::error(errs(), "llvm-objdump") << EC.message() << "\n"; 6735 return; 6736 } 6737 std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 6738 6739 if (!XarMemberName.empty()) 6740 outs() << "In xar member " << XarMemberName << ": "; 6741 else 6742 outs() << "For (__LLVM,__bundle) section: "; 6743 outs() << "xar table of contents:\n"; 6744 outs() << Buffer->getBuffer() << "\n"; 6745 6746 // TODO: Go through the xar's files. 6747 ScopedXarIter xi; 6748 if(!xi){ 6749 WithColor::error(errs(), "llvm-objdump") 6750 << "can't obtain an xar iterator for xar archive " 6751 << XarFilename.c_str() << "\n"; 6752 return; 6753 } 6754 for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ 6755 const char *key; 6756 const char *member_name, *member_type, *member_size_string; 6757 size_t member_size; 6758 6759 ScopedXarIter xp; 6760 if(!xp){ 6761 WithColor::error(errs(), "llvm-objdump") 6762 << "can't obtain an xar iterator for xar archive " 6763 << XarFilename.c_str() << "\n"; 6764 return; 6765 } 6766 member_name = NULL; 6767 member_type = NULL; 6768 member_size_string = NULL; 6769 for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ 6770 const char *val = nullptr; 6771 xar_prop_get(xf, key, &val); 6772 #if 0 // Useful for debugging. 6773 outs() << "key: " << key << " value: " << val << "\n"; 6774 #endif 6775 if (strcmp(key, "name") == 0) 6776 member_name = val; 6777 if (strcmp(key, "type") == 0) 6778 member_type = val; 6779 if (strcmp(key, "data/size") == 0) 6780 member_size_string = val; 6781 } 6782 /* 6783 * If we find a file with a name, date/size and type properties 6784 * and with the type being "file" see if that is a xar file. 6785 */ 6786 if (member_name != NULL && member_type != NULL && 6787 strcmp(member_type, "file") == 0 && 6788 member_size_string != NULL){ 6789 // Extract the file into a buffer. 6790 char *endptr; 6791 member_size = strtoul(member_size_string, &endptr, 10); 6792 if (*endptr == '\0' && member_size != 0) { 6793 char *buffer; 6794 if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { 6795 #if 0 // Useful for debugging. 6796 outs() << "xar member: " << member_name << " extracted\n"; 6797 #endif 6798 // Set the XarMemberName we want to see printed in the header. 6799 std::string OldXarMemberName; 6800 // If XarMemberName is already set this is nested. So 6801 // save the old name and create the nested name. 6802 if (!XarMemberName.empty()) { 6803 OldXarMemberName = XarMemberName; 6804 XarMemberName = 6805 (Twine("[") + XarMemberName + "]" + member_name).str(); 6806 } else { 6807 OldXarMemberName = ""; 6808 XarMemberName = member_name; 6809 } 6810 // See if this is could be a xar file (nested). 6811 if (member_size >= sizeof(struct xar_header)) { 6812 #if 0 // Useful for debugging. 6813 outs() << "could be a xar file: " << member_name << "\n"; 6814 #endif 6815 memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); 6816 if (sys::IsLittleEndianHost) 6817 swapStruct(XarHeader); 6818 if (XarHeader.magic == XAR_HEADER_MAGIC) 6819 DumpBitcodeSection(O, buffer, member_size, verbose, 6820 PrintXarHeader, PrintXarFileHeaders, 6821 XarMemberName); 6822 } 6823 XarMemberName = OldXarMemberName; 6824 delete buffer; 6825 } 6826 } 6827 } 6828 } 6829 } 6830 #endif // defined(LLVM_HAVE_LIBXAR) 6831 6832 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6833 if (O->is64Bit()) 6834 printObjc2_64bit_MetaData(O, verbose); 6835 else { 6836 MachO::mach_header H; 6837 H = O->getHeader(); 6838 if (H.cputype == MachO::CPU_TYPE_ARM) 6839 printObjc2_32bit_MetaData(O, verbose); 6840 else { 6841 // This is the 32-bit non-arm cputype case. Which is normally 6842 // the first Objective-C ABI. But it may be the case of a 6843 // binary for the iOS simulator which is the second Objective-C 6844 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6845 // and return false. 6846 if (!printObjc1_32bit_MetaData(O, verbose)) 6847 printObjc2_32bit_MetaData(O, verbose); 6848 } 6849 } 6850 } 6851 6852 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6853 // for the address passed in as ReferenceValue for printing as a comment with 6854 // the instruction and also returns the corresponding type of that item 6855 // indirectly through ReferenceType. 6856 // 6857 // If ReferenceValue is an address of literal cstring then a pointer to the 6858 // cstring is returned and ReferenceType is set to 6859 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6860 // 6861 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6862 // Class ref that name is returned and the ReferenceType is set accordingly. 6863 // 6864 // Lastly, literals which are Symbol address in a literal pool are looked for 6865 // and if found the symbol name is returned and ReferenceType is set to 6866 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6867 // 6868 // If there is no item in the Mach-O file for the address passed in as 6869 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6870 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6871 uint64_t ReferencePC, 6872 uint64_t *ReferenceType, 6873 struct DisassembleInfo *info) { 6874 // First see if there is an external relocation entry at the ReferencePC. 6875 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6876 uint64_t sect_addr = info->S.getAddress(); 6877 uint64_t sect_offset = ReferencePC - sect_addr; 6878 bool reloc_found = false; 6879 DataRefImpl Rel; 6880 MachO::any_relocation_info RE; 6881 bool isExtern = false; 6882 SymbolRef Symbol; 6883 for (const RelocationRef &Reloc : info->S.relocations()) { 6884 uint64_t RelocOffset = Reloc.getOffset(); 6885 if (RelocOffset == sect_offset) { 6886 Rel = Reloc.getRawDataRefImpl(); 6887 RE = info->O->getRelocation(Rel); 6888 if (info->O->isRelocationScattered(RE)) 6889 continue; 6890 isExtern = info->O->getPlainRelocationExternal(RE); 6891 if (isExtern) { 6892 symbol_iterator RelocSym = Reloc.getSymbol(); 6893 Symbol = *RelocSym; 6894 } 6895 reloc_found = true; 6896 break; 6897 } 6898 } 6899 // If there is an external relocation entry for a symbol in a section 6900 // then used that symbol's value for the value of the reference. 6901 if (reloc_found && isExtern) { 6902 if (info->O->getAnyRelocationPCRel(RE)) { 6903 unsigned Type = info->O->getAnyRelocationType(RE); 6904 if (Type == MachO::X86_64_RELOC_SIGNED) { 6905 ReferenceValue = cantFail(Symbol.getValue()); 6906 } 6907 } 6908 } 6909 } 6910 6911 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6912 // Message refs and Class refs. 6913 bool classref, selref, msgref, cfstring; 6914 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6915 selref, msgref, cfstring); 6916 if (classref && pointer_value == 0) { 6917 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6918 // And the pointer_value in that section is typically zero as it will be 6919 // set by dyld as part of the "bind information". 6920 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6921 if (name != nullptr) { 6922 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6923 const char *class_name = strrchr(name, '$'); 6924 if (class_name != nullptr && class_name[1] == '_' && 6925 class_name[2] != '\0') { 6926 info->class_name = class_name + 2; 6927 return name; 6928 } 6929 } 6930 } 6931 6932 if (classref) { 6933 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6934 const char *name = 6935 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6936 if (name != nullptr) 6937 info->class_name = name; 6938 else 6939 name = "bad class ref"; 6940 return name; 6941 } 6942 6943 if (cfstring) { 6944 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6945 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6946 return name; 6947 } 6948 6949 if (selref && pointer_value == 0) 6950 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6951 6952 if (pointer_value != 0) 6953 ReferenceValue = pointer_value; 6954 6955 const char *name = GuessCstringPointer(ReferenceValue, info); 6956 if (name) { 6957 if (pointer_value != 0 && selref) { 6958 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6959 info->selector_name = name; 6960 } else if (pointer_value != 0 && msgref) { 6961 info->class_name = nullptr; 6962 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6963 info->selector_name = name; 6964 } else 6965 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6966 return name; 6967 } 6968 6969 // Lastly look for an indirect symbol with this ReferenceValue which is in 6970 // a literal pool. If found return that symbol name. 6971 name = GuessIndirectSymbol(ReferenceValue, info); 6972 if (name) { 6973 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6974 return name; 6975 } 6976 6977 return nullptr; 6978 } 6979 6980 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6981 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6982 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6983 // is created and returns the symbol name that matches the ReferenceValue or 6984 // nullptr if none. The ReferenceType is passed in for the IN type of 6985 // reference the instruction is making from the values in defined in the header 6986 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6987 // Out type and the ReferenceName will also be set which is added as a comment 6988 // to the disassembled instruction. 6989 // 6990 // If the symbol name is a C++ mangled name then the demangled name is 6991 // returned through ReferenceName and ReferenceType is set to 6992 // LLVMDisassembler_ReferenceType_DeMangled_Name . 6993 // 6994 // When this is called to get a symbol name for a branch target then the 6995 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 6996 // SymbolValue will be looked for in the indirect symbol table to determine if 6997 // it is an address for a symbol stub. If so then the symbol name for that 6998 // stub is returned indirectly through ReferenceName and then ReferenceType is 6999 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 7000 // 7001 // When this is called with an value loaded via a PC relative load then 7002 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 7003 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 7004 // or an Objective-C meta data reference. If so the output ReferenceType is 7005 // set to correspond to that as well as setting the ReferenceName. 7006 static const char *SymbolizerSymbolLookUp(void *DisInfo, 7007 uint64_t ReferenceValue, 7008 uint64_t *ReferenceType, 7009 uint64_t ReferencePC, 7010 const char **ReferenceName) { 7011 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 7012 // If no verbose symbolic information is wanted then just return nullptr. 7013 if (!info->verbose) { 7014 *ReferenceName = nullptr; 7015 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7016 return nullptr; 7017 } 7018 7019 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 7020 7021 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 7022 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 7023 if (*ReferenceName != nullptr) { 7024 method_reference(info, ReferenceType, ReferenceName); 7025 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 7026 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 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 } else 7037 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7038 } else 7039 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7040 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 7041 *ReferenceName = 7042 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7043 if (*ReferenceName) 7044 method_reference(info, ReferenceType, ReferenceName); 7045 else 7046 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7047 // If this is arm64 and the reference is an adrp instruction save the 7048 // instruction, passed in ReferenceValue and the address of the instruction 7049 // for use later if we see and add immediate instruction. 7050 } else if (info->O->getArch() == Triple::aarch64 && 7051 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 7052 info->adrp_inst = ReferenceValue; 7053 info->adrp_addr = ReferencePC; 7054 SymbolName = nullptr; 7055 *ReferenceName = nullptr; 7056 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7057 // If this is arm64 and reference is an add immediate instruction and we 7058 // have 7059 // seen an adrp instruction just before it and the adrp's Xd register 7060 // matches 7061 // this add's Xn register reconstruct the value being referenced and look to 7062 // see if it is a literal pointer. Note the add immediate instruction is 7063 // passed in ReferenceValue. 7064 } else if (info->O->getArch() == Triple::aarch64 && 7065 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 7066 ReferencePC - 4 == info->adrp_addr && 7067 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7068 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7069 uint32_t addxri_inst; 7070 uint64_t adrp_imm, addxri_imm; 7071 7072 adrp_imm = 7073 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7074 if (info->adrp_inst & 0x0200000) 7075 adrp_imm |= 0xfffffffffc000000LL; 7076 7077 addxri_inst = ReferenceValue; 7078 addxri_imm = (addxri_inst >> 10) & 0xfff; 7079 if (((addxri_inst >> 22) & 0x3) == 1) 7080 addxri_imm <<= 12; 7081 7082 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7083 (adrp_imm << 12) + addxri_imm; 7084 7085 *ReferenceName = 7086 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7087 if (*ReferenceName == nullptr) 7088 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7089 // If this is arm64 and the reference is a load register instruction and we 7090 // have seen an adrp instruction just before it and the adrp's Xd register 7091 // matches this add's Xn register reconstruct the value being referenced and 7092 // look to see if it is a literal pointer. Note the load register 7093 // instruction is passed in ReferenceValue. 7094 } else if (info->O->getArch() == Triple::aarch64 && 7095 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 7096 ReferencePC - 4 == info->adrp_addr && 7097 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7098 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7099 uint32_t ldrxui_inst; 7100 uint64_t adrp_imm, ldrxui_imm; 7101 7102 adrp_imm = 7103 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7104 if (info->adrp_inst & 0x0200000) 7105 adrp_imm |= 0xfffffffffc000000LL; 7106 7107 ldrxui_inst = ReferenceValue; 7108 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 7109 7110 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7111 (adrp_imm << 12) + (ldrxui_imm << 3); 7112 7113 *ReferenceName = 7114 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7115 if (*ReferenceName == nullptr) 7116 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7117 } 7118 // If this arm64 and is an load register (PC-relative) instruction the 7119 // ReferenceValue is the PC plus the immediate value. 7120 else if (info->O->getArch() == Triple::aarch64 && 7121 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 7122 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 7123 *ReferenceName = 7124 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7125 if (*ReferenceName == nullptr) 7126 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7127 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 7128 if (info->demangled_name != nullptr) 7129 free(info->demangled_name); 7130 int status; 7131 info->demangled_name = 7132 itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); 7133 if (info->demangled_name != nullptr) { 7134 *ReferenceName = info->demangled_name; 7135 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 7136 } 7137 } 7138 else { 7139 *ReferenceName = nullptr; 7140 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7141 } 7142 7143 return SymbolName; 7144 } 7145 7146 /// Emits the comments that are stored in the CommentStream. 7147 /// Each comment in the CommentStream must end with a newline. 7148 static void emitComments(raw_svector_ostream &CommentStream, 7149 SmallString<128> &CommentsToEmit, 7150 formatted_raw_ostream &FormattedOS, 7151 const MCAsmInfo &MAI) { 7152 // Flush the stream before taking its content. 7153 StringRef Comments = CommentsToEmit.str(); 7154 // Get the default information for printing a comment. 7155 StringRef CommentBegin = MAI.getCommentString(); 7156 unsigned CommentColumn = MAI.getCommentColumn(); 7157 ListSeparator LS("\n"); 7158 while (!Comments.empty()) { 7159 FormattedOS << LS; 7160 // Emit a line of comments. 7161 FormattedOS.PadToColumn(CommentColumn); 7162 size_t Position = Comments.find('\n'); 7163 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 7164 // Move after the newline character. 7165 Comments = Comments.substr(Position + 1); 7166 } 7167 FormattedOS.flush(); 7168 7169 // Tell the comment stream that the vector changed underneath it. 7170 CommentsToEmit.clear(); 7171 } 7172 7173 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 7174 StringRef DisSegName, StringRef DisSectName) { 7175 const char *McpuDefault = nullptr; 7176 const Target *ThumbTarget = nullptr; 7177 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 7178 if (!TheTarget) { 7179 // GetTarget prints out stuff. 7180 return; 7181 } 7182 std::string MachOMCPU; 7183 if (MCPU.empty() && McpuDefault) 7184 MachOMCPU = McpuDefault; 7185 else 7186 MachOMCPU = MCPU; 7187 7188 #define CHECK_TARGET_INFO_CREATION(NAME) \ 7189 do { \ 7190 if (!NAME) { \ 7191 WithColor::error(errs(), "llvm-objdump") \ 7192 << "couldn't initialize disassembler for target " << TripleName \ 7193 << '\n'; \ 7194 return; \ 7195 } \ 7196 } while (false) 7197 #define CHECK_THUMB_TARGET_INFO_CREATION(NAME) \ 7198 do { \ 7199 if (!NAME) { \ 7200 WithColor::error(errs(), "llvm-objdump") \ 7201 << "couldn't initialize disassembler for target " << ThumbTripleName \ 7202 << '\n'; \ 7203 return; \ 7204 } \ 7205 } while (false) 7206 7207 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 7208 CHECK_TARGET_INFO_CREATION(InstrInfo); 7209 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 7210 if (ThumbTarget) { 7211 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 7212 CHECK_THUMB_TARGET_INFO_CREATION(ThumbInstrInfo); 7213 } 7214 7215 // Package up features to be passed to target/subtarget 7216 std::string FeaturesStr; 7217 if (!MAttrs.empty()) { 7218 SubtargetFeatures Features; 7219 for (unsigned i = 0; i != MAttrs.size(); ++i) 7220 Features.AddFeature(MAttrs[i]); 7221 FeaturesStr = Features.getString(); 7222 } 7223 7224 MCTargetOptions MCOptions; 7225 // Set up disassembler. 7226 std::unique_ptr<const MCRegisterInfo> MRI( 7227 TheTarget->createMCRegInfo(TripleName)); 7228 CHECK_TARGET_INFO_CREATION(MRI); 7229 std::unique_ptr<const MCAsmInfo> AsmInfo( 7230 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 7231 CHECK_TARGET_INFO_CREATION(AsmInfo); 7232 std::unique_ptr<const MCSubtargetInfo> STI( 7233 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 7234 CHECK_TARGET_INFO_CREATION(STI); 7235 MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get()); 7236 std::unique_ptr<MCDisassembler> DisAsm( 7237 TheTarget->createMCDisassembler(*STI, Ctx)); 7238 CHECK_TARGET_INFO_CREATION(DisAsm); 7239 std::unique_ptr<MCSymbolizer> Symbolizer; 7240 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false); 7241 std::unique_ptr<MCRelocationInfo> RelInfo( 7242 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 7243 if (RelInfo) { 7244 Symbolizer.reset(TheTarget->createMCSymbolizer( 7245 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7246 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 7247 DisAsm->setSymbolizer(std::move(Symbolizer)); 7248 } 7249 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 7250 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 7251 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 7252 CHECK_TARGET_INFO_CREATION(IP); 7253 // Set the display preference for hex vs. decimal immediates. 7254 IP->setPrintImmHex(PrintImmHex); 7255 // Comment stream and backing vector. 7256 SmallString<128> CommentsToEmit; 7257 raw_svector_ostream CommentStream(CommentsToEmit); 7258 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 7259 // if it is done then arm64 comments for string literals don't get printed 7260 // and some constant get printed instead and not setting it causes intel 7261 // (32-bit and 64-bit) comments printed with different spacing before the 7262 // comment causing different diffs with the 'C' disassembler library API. 7263 // IP->setCommentStream(CommentStream); 7264 7265 // Set up separate thumb disassembler if needed. 7266 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 7267 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 7268 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 7269 std::unique_ptr<MCDisassembler> ThumbDisAsm; 7270 std::unique_ptr<MCInstPrinter> ThumbIP; 7271 std::unique_ptr<MCContext> ThumbCtx; 7272 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 7273 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false); 7274 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 7275 if (ThumbTarget) { 7276 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 7277 CHECK_THUMB_TARGET_INFO_CREATION(ThumbMRI); 7278 ThumbAsmInfo.reset( 7279 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions)); 7280 CHECK_THUMB_TARGET_INFO_CREATION(ThumbAsmInfo); 7281 ThumbSTI.reset( 7282 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 7283 FeaturesStr)); 7284 CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI); 7285 ThumbCtx.reset(new MCContext(Triple(ThumbTripleName), ThumbAsmInfo.get(), 7286 ThumbMRI.get(), ThumbSTI.get())); 7287 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 7288 CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm); 7289 MCContext *PtrThumbCtx = ThumbCtx.get(); 7290 ThumbRelInfo.reset( 7291 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 7292 if (ThumbRelInfo) { 7293 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 7294 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7295 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 7296 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 7297 } 7298 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 7299 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 7300 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 7301 *ThumbInstrInfo, *ThumbMRI)); 7302 CHECK_THUMB_TARGET_INFO_CREATION(ThumbIP); 7303 // Set the display preference for hex vs. decimal immediates. 7304 ThumbIP->setPrintImmHex(PrintImmHex); 7305 } 7306 7307 #undef CHECK_TARGET_INFO_CREATION 7308 #undef CHECK_THUMB_TARGET_INFO_CREATION 7309 7310 MachO::mach_header Header = MachOOF->getHeader(); 7311 7312 // FIXME: Using the -cfg command line option, this code used to be able to 7313 // annotate relocations with the referenced symbol's name, and if this was 7314 // inside a __[cf]string section, the data it points to. This is now replaced 7315 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 7316 std::vector<SectionRef> Sections; 7317 std::vector<SymbolRef> Symbols; 7318 SmallVector<uint64_t, 8> FoundFns; 7319 uint64_t BaseSegmentAddress = 0; 7320 7321 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 7322 BaseSegmentAddress); 7323 7324 // Sort the symbols by address, just in case they didn't come in that way. 7325 llvm::stable_sort(Symbols, SymbolSorter()); 7326 7327 // Build a data in code table that is sorted on by the address of each entry. 7328 uint64_t BaseAddress = 0; 7329 if (Header.filetype == MachO::MH_OBJECT) 7330 BaseAddress = Sections[0].getAddress(); 7331 else 7332 BaseAddress = BaseSegmentAddress; 7333 DiceTable Dices; 7334 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 7335 DI != DE; ++DI) { 7336 uint32_t Offset; 7337 DI->getOffset(Offset); 7338 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 7339 } 7340 array_pod_sort(Dices.begin(), Dices.end()); 7341 7342 // Try to find debug info and set up the DIContext for it. 7343 std::unique_ptr<DIContext> diContext; 7344 std::unique_ptr<Binary> DSYMBinary; 7345 std::unique_ptr<MemoryBuffer> DSYMBuf; 7346 if (UseDbg) { 7347 ObjectFile *DbgObj = MachOOF; 7348 7349 // A separate DSym file path was specified, parse it as a macho file, 7350 // get the sections and supply it to the section name parsing machinery. 7351 if (!DSYMFile.empty()) { 7352 std::string DSYMPath(DSYMFile); 7353 7354 // If DSYMPath is a .dSYM directory, append the Mach-O file. 7355 if (llvm::sys::fs::is_directory(DSYMPath) && 7356 llvm::sys::path::extension(DSYMPath) == ".dSYM") { 7357 SmallString<128> ShortName(llvm::sys::path::filename(DSYMPath)); 7358 llvm::sys::path::replace_extension(ShortName, ""); 7359 SmallString<1024> FullPath(DSYMPath); 7360 llvm::sys::path::append(FullPath, "Contents", "Resources", "DWARF", 7361 ShortName); 7362 DSYMPath = std::string(FullPath.str()); 7363 } 7364 7365 // Load the file. 7366 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 7367 MemoryBuffer::getFileOrSTDIN(DSYMPath); 7368 if (std::error_code EC = BufOrErr.getError()) { 7369 reportError(errorCodeToError(EC), DSYMPath); 7370 return; 7371 } 7372 7373 // We need to keep the file alive, because we're replacing DbgObj with it. 7374 DSYMBuf = std::move(BufOrErr.get()); 7375 7376 Expected<std::unique_ptr<Binary>> BinaryOrErr = 7377 createBinary(DSYMBuf.get()->getMemBufferRef()); 7378 if (!BinaryOrErr) { 7379 reportError(BinaryOrErr.takeError(), DSYMPath); 7380 return; 7381 } 7382 7383 // We need to keep the Binary alive with the buffer 7384 DSYMBinary = std::move(BinaryOrErr.get()); 7385 if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) { 7386 // this is a Mach-O object file, use it 7387 if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) { 7388 DbgObj = MachDSYM; 7389 } 7390 else { 7391 WithColor::error(errs(), "llvm-objdump") 7392 << DSYMPath << " is not a Mach-O file type.\n"; 7393 return; 7394 } 7395 } 7396 else if (auto UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())){ 7397 // this is a Universal Binary, find a Mach-O for this architecture 7398 uint32_t CPUType, CPUSubType; 7399 const char *ArchFlag; 7400 if (MachOOF->is64Bit()) { 7401 const MachO::mach_header_64 H_64 = MachOOF->getHeader64(); 7402 CPUType = H_64.cputype; 7403 CPUSubType = H_64.cpusubtype; 7404 } else { 7405 const MachO::mach_header H = MachOOF->getHeader(); 7406 CPUType = H.cputype; 7407 CPUSubType = H.cpusubtype; 7408 } 7409 Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr, 7410 &ArchFlag); 7411 Expected<std::unique_ptr<MachOObjectFile>> MachDSYM = 7412 UB->getMachOObjectForArch(ArchFlag); 7413 if (!MachDSYM) { 7414 reportError(MachDSYM.takeError(), DSYMPath); 7415 return; 7416 } 7417 7418 // We need to keep the Binary alive with the buffer 7419 DbgObj = &*MachDSYM.get(); 7420 DSYMBinary = std::move(*MachDSYM); 7421 } 7422 else { 7423 WithColor::error(errs(), "llvm-objdump") 7424 << DSYMPath << " is not a Mach-O or Universal file type.\n"; 7425 return; 7426 } 7427 } 7428 7429 // Setup the DIContext 7430 diContext = DWARFContext::create(*DbgObj); 7431 } 7432 7433 if (FilterSections.empty()) 7434 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 7435 7436 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 7437 Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName(); 7438 if (!SecNameOrErr) { 7439 consumeError(SecNameOrErr.takeError()); 7440 continue; 7441 } 7442 if (*SecNameOrErr != DisSectName) 7443 continue; 7444 7445 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 7446 7447 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 7448 if (SegmentName != DisSegName) 7449 continue; 7450 7451 StringRef BytesStr = 7452 unwrapOrError(Sections[SectIdx].getContents(), Filename); 7453 ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr); 7454 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7455 7456 bool symbolTableWorked = false; 7457 7458 // Create a map of symbol addresses to symbol names for use by 7459 // the SymbolizerSymbolLookUp() routine. 7460 SymbolAddressMap AddrMap; 7461 bool DisSymNameFound = false; 7462 for (const SymbolRef &Symbol : MachOOF->symbols()) { 7463 SymbolRef::Type ST = 7464 unwrapOrError(Symbol.getType(), MachOOF->getFileName()); 7465 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 7466 ST == SymbolRef::ST_Other) { 7467 uint64_t Address = cantFail(Symbol.getValue()); 7468 StringRef SymName = 7469 unwrapOrError(Symbol.getName(), MachOOF->getFileName()); 7470 AddrMap[Address] = SymName; 7471 if (!DisSymName.empty() && DisSymName == SymName) 7472 DisSymNameFound = true; 7473 } 7474 } 7475 if (!DisSymName.empty() && !DisSymNameFound) { 7476 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 7477 return; 7478 } 7479 // Set up the block of info used by the Symbolizer call backs. 7480 SymbolizerInfo.verbose = SymbolicOperands; 7481 SymbolizerInfo.O = MachOOF; 7482 SymbolizerInfo.S = Sections[SectIdx]; 7483 SymbolizerInfo.AddrMap = &AddrMap; 7484 SymbolizerInfo.Sections = &Sections; 7485 // Same for the ThumbSymbolizer 7486 ThumbSymbolizerInfo.verbose = SymbolicOperands; 7487 ThumbSymbolizerInfo.O = MachOOF; 7488 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7489 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7490 ThumbSymbolizerInfo.Sections = &Sections; 7491 7492 unsigned int Arch = MachOOF->getArch(); 7493 7494 // Skip all symbols if this is a stubs file. 7495 if (Bytes.empty()) 7496 return; 7497 7498 // If the section has symbols but no symbol at the start of the section 7499 // these are used to make sure the bytes before the first symbol are 7500 // disassembled. 7501 bool FirstSymbol = true; 7502 bool FirstSymbolAtSectionStart = true; 7503 7504 // Disassemble symbol by symbol. 7505 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7506 StringRef SymName = 7507 unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName()); 7508 SymbolRef::Type ST = 7509 unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName()); 7510 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7511 continue; 7512 7513 // Make sure the symbol is defined in this section. 7514 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7515 if (!containsSym) { 7516 if (!DisSymName.empty() && DisSymName == SymName) { 7517 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7518 return; 7519 } 7520 continue; 7521 } 7522 // The __mh_execute_header is special and we need to deal with that fact 7523 // this symbol is before the start of the (__TEXT,__text) section and at the 7524 // address of the start of the __TEXT segment. This is because this symbol 7525 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7526 // start of the section in a standard MH_EXECUTE filetype. 7527 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7528 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7529 return; 7530 } 7531 // When this code is trying to disassemble a symbol at a time and in the 7532 // case there is only the __mh_execute_header symbol left as in a stripped 7533 // executable, we need to deal with this by ignoring this symbol so the 7534 // whole section is disassembled and this symbol is then not displayed. 7535 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7536 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7537 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7538 continue; 7539 7540 // If we are only disassembling one symbol see if this is that symbol. 7541 if (!DisSymName.empty() && DisSymName != SymName) 7542 continue; 7543 7544 // Start at the address of the symbol relative to the section's address. 7545 uint64_t SectSize = Sections[SectIdx].getSize(); 7546 uint64_t Start = cantFail(Symbols[SymIdx].getValue()); 7547 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7548 Start -= SectionAddress; 7549 7550 if (Start > SectSize) { 7551 outs() << "section data ends, " << SymName 7552 << " lies outside valid range\n"; 7553 return; 7554 } 7555 7556 // Stop disassembling either at the beginning of the next symbol or at 7557 // the end of the section. 7558 bool containsNextSym = false; 7559 uint64_t NextSym = 0; 7560 uint64_t NextSymIdx = SymIdx + 1; 7561 while (Symbols.size() > NextSymIdx) { 7562 SymbolRef::Type NextSymType = unwrapOrError( 7563 Symbols[NextSymIdx].getType(), MachOOF->getFileName()); 7564 if (NextSymType == SymbolRef::ST_Function) { 7565 containsNextSym = 7566 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7567 NextSym = cantFail(Symbols[NextSymIdx].getValue()); 7568 NextSym -= SectionAddress; 7569 break; 7570 } 7571 ++NextSymIdx; 7572 } 7573 7574 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7575 uint64_t Size; 7576 7577 symbolTableWorked = true; 7578 7579 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7580 uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb)); 7581 bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb; 7582 7583 // We only need the dedicated Thumb target if there's a real choice 7584 // (i.e. we're not targeting M-class) and the function is Thumb. 7585 bool UseThumbTarget = IsThumb && ThumbTarget; 7586 7587 // If we are not specifying a symbol to start disassembly with and this 7588 // is the first symbol in the section but not at the start of the section 7589 // then move the disassembly index to the start of the section and 7590 // don't print the symbol name just yet. This is so the bytes before the 7591 // first symbol are disassembled. 7592 uint64_t SymbolStart = Start; 7593 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7594 FirstSymbolAtSectionStart = false; 7595 Start = 0; 7596 } 7597 else 7598 outs() << SymName << ":\n"; 7599 7600 DILineInfo lastLine; 7601 for (uint64_t Index = Start; Index < End; Index += Size) { 7602 MCInst Inst; 7603 7604 // If this is the first symbol in the section and it was not at the 7605 // start of the section, see if we are at its Index now and if so print 7606 // the symbol name. 7607 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7608 outs() << SymName << ":\n"; 7609 7610 uint64_t PC = SectAddress + Index; 7611 if (LeadingAddr) { 7612 if (FullLeadingAddr) { 7613 if (MachOOF->is64Bit()) 7614 outs() << format("%016" PRIx64, PC); 7615 else 7616 outs() << format("%08" PRIx64, PC); 7617 } else { 7618 outs() << format("%8" PRIx64 ":", PC); 7619 } 7620 } 7621 if (ShowRawInsn || Arch == Triple::arm) 7622 outs() << "\t"; 7623 7624 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size)) 7625 continue; 7626 7627 SmallVector<char, 64> AnnotationsBytes; 7628 raw_svector_ostream Annotations(AnnotationsBytes); 7629 7630 bool gotInst; 7631 if (UseThumbTarget) 7632 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7633 PC, Annotations); 7634 else 7635 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7636 Annotations); 7637 if (gotInst) { 7638 if (ShowRawInsn || Arch == Triple::arm) { 7639 dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs()); 7640 } 7641 formatted_raw_ostream FormattedOS(outs()); 7642 StringRef AnnotationsStr = Annotations.str(); 7643 if (UseThumbTarget) 7644 ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI, 7645 FormattedOS); 7646 else 7647 IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS); 7648 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7649 7650 // Print debug info. 7651 if (diContext) { 7652 DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx}); 7653 // Print valid line info if it changed. 7654 if (dli != lastLine && dli.Line != 0) 7655 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7656 << dli.Column; 7657 lastLine = dli; 7658 } 7659 outs() << "\n"; 7660 } else { 7661 if (MachOOF->getArchTriple().isX86()) { 7662 outs() << format("\t.byte 0x%02x #bad opcode\n", 7663 *(Bytes.data() + Index) & 0xff); 7664 Size = 1; // skip exactly one illegible byte and move on. 7665 } else if (Arch == Triple::aarch64 || 7666 (Arch == Triple::arm && !IsThumb)) { 7667 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7668 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7669 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7670 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7671 outs() << format("\t.long\t0x%08x\n", opcode); 7672 Size = 4; 7673 } else if (Arch == Triple::arm) { 7674 assert(IsThumb && "ARM mode should have been dealt with above"); 7675 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7676 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7677 outs() << format("\t.short\t0x%04x\n", opcode); 7678 Size = 2; 7679 } else{ 7680 WithColor::warning(errs(), "llvm-objdump") 7681 << "invalid instruction encoding\n"; 7682 if (Size == 0) 7683 Size = 1; // skip illegible bytes 7684 } 7685 } 7686 } 7687 // Now that we are done disassembled the first symbol set the bool that 7688 // were doing this to false. 7689 FirstSymbol = false; 7690 } 7691 if (!symbolTableWorked) { 7692 // Reading the symbol table didn't work, disassemble the whole section. 7693 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7694 uint64_t SectSize = Sections[SectIdx].getSize(); 7695 uint64_t InstSize; 7696 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7697 MCInst Inst; 7698 7699 uint64_t PC = SectAddress + Index; 7700 7701 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize)) 7702 continue; 7703 7704 SmallVector<char, 64> AnnotationsBytes; 7705 raw_svector_ostream Annotations(AnnotationsBytes); 7706 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7707 Annotations)) { 7708 if (LeadingAddr) { 7709 if (FullLeadingAddr) { 7710 if (MachOOF->is64Bit()) 7711 outs() << format("%016" PRIx64, PC); 7712 else 7713 outs() << format("%08" PRIx64, PC); 7714 } else { 7715 outs() << format("%8" PRIx64 ":", PC); 7716 } 7717 } 7718 if (ShowRawInsn || Arch == Triple::arm) { 7719 outs() << "\t"; 7720 dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs()); 7721 } 7722 StringRef AnnotationsStr = Annotations.str(); 7723 IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs()); 7724 outs() << "\n"; 7725 } else { 7726 if (MachOOF->getArchTriple().isX86()) { 7727 outs() << format("\t.byte 0x%02x #bad opcode\n", 7728 *(Bytes.data() + Index) & 0xff); 7729 InstSize = 1; // skip exactly one illegible byte and move on. 7730 } else { 7731 WithColor::warning(errs(), "llvm-objdump") 7732 << "invalid instruction encoding\n"; 7733 if (InstSize == 0) 7734 InstSize = 1; // skip illegible bytes 7735 } 7736 } 7737 } 7738 } 7739 // The TripleName's need to be reset if we are called again for a different 7740 // architecture. 7741 TripleName = ""; 7742 ThumbTripleName = ""; 7743 7744 if (SymbolizerInfo.demangled_name != nullptr) 7745 free(SymbolizerInfo.demangled_name); 7746 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7747 free(ThumbSymbolizerInfo.demangled_name); 7748 } 7749 } 7750 7751 //===----------------------------------------------------------------------===// 7752 // __compact_unwind section dumping 7753 //===----------------------------------------------------------------------===// 7754 7755 namespace { 7756 7757 template <typename T> 7758 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7759 using llvm::support::little; 7760 using llvm::support::unaligned; 7761 7762 if (Offset + sizeof(T) > Contents.size()) { 7763 outs() << "warning: attempt to read past end of buffer\n"; 7764 return T(); 7765 } 7766 7767 uint64_t Val = 7768 support::endian::read<T, little, unaligned>(Contents.data() + Offset); 7769 return Val; 7770 } 7771 7772 template <typename T> 7773 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7774 T Val = read<T>(Contents, Offset); 7775 Offset += sizeof(T); 7776 return Val; 7777 } 7778 7779 struct CompactUnwindEntry { 7780 uint32_t OffsetInSection; 7781 7782 uint64_t FunctionAddr; 7783 uint32_t Length; 7784 uint32_t CompactEncoding; 7785 uint64_t PersonalityAddr; 7786 uint64_t LSDAAddr; 7787 7788 RelocationRef FunctionReloc; 7789 RelocationRef PersonalityReloc; 7790 RelocationRef LSDAReloc; 7791 7792 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7793 : OffsetInSection(Offset) { 7794 if (Is64) 7795 read<uint64_t>(Contents, Offset); 7796 else 7797 read<uint32_t>(Contents, Offset); 7798 } 7799 7800 private: 7801 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7802 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7803 Length = readNext<uint32_t>(Contents, Offset); 7804 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7805 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7806 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7807 } 7808 }; 7809 } 7810 7811 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7812 /// and data being relocated, determine the best base Name and Addend to use for 7813 /// display purposes. 7814 /// 7815 /// 1. An Extern relocation will directly reference a symbol (and the data is 7816 /// then already an addend), so use that. 7817 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7818 // a symbol before it in the same section, and use the offset from there. 7819 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7820 /// referenced section. 7821 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7822 std::map<uint64_t, SymbolRef> &Symbols, 7823 const RelocationRef &Reloc, uint64_t Addr, 7824 StringRef &Name, uint64_t &Addend) { 7825 if (Reloc.getSymbol() != Obj->symbol_end()) { 7826 Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName()); 7827 Addend = Addr; 7828 return; 7829 } 7830 7831 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7832 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7833 7834 uint64_t SectionAddr = RelocSection.getAddress(); 7835 7836 auto Sym = Symbols.upper_bound(Addr); 7837 if (Sym == Symbols.begin()) { 7838 // The first symbol in the object is after this reference, the best we can 7839 // do is section-relative notation. 7840 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7841 Name = *NameOrErr; 7842 else 7843 consumeError(NameOrErr.takeError()); 7844 7845 Addend = Addr - SectionAddr; 7846 return; 7847 } 7848 7849 // Go back one so that SymbolAddress <= Addr. 7850 --Sym; 7851 7852 section_iterator SymSection = 7853 unwrapOrError(Sym->second.getSection(), Obj->getFileName()); 7854 if (RelocSection == *SymSection) { 7855 // There's a valid symbol in the same section before this reference. 7856 Name = unwrapOrError(Sym->second.getName(), Obj->getFileName()); 7857 Addend = Addr - Sym->first; 7858 return; 7859 } 7860 7861 // There is a symbol before this reference, but it's in a different 7862 // section. Probably not helpful to mention it, so use the section name. 7863 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7864 Name = *NameOrErr; 7865 else 7866 consumeError(NameOrErr.takeError()); 7867 7868 Addend = Addr - SectionAddr; 7869 } 7870 7871 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7872 std::map<uint64_t, SymbolRef> &Symbols, 7873 const RelocationRef &Reloc, uint64_t Addr) { 7874 StringRef Name; 7875 uint64_t Addend; 7876 7877 if (!Reloc.getObject()) 7878 return; 7879 7880 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7881 7882 outs() << Name; 7883 if (Addend) 7884 outs() << " + " << format("0x%" PRIx64, Addend); 7885 } 7886 7887 static void 7888 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7889 std::map<uint64_t, SymbolRef> &Symbols, 7890 const SectionRef &CompactUnwind) { 7891 7892 if (!Obj->isLittleEndian()) { 7893 outs() << "Skipping big-endian __compact_unwind section\n"; 7894 return; 7895 } 7896 7897 bool Is64 = Obj->is64Bit(); 7898 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7899 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7900 7901 StringRef Contents = 7902 unwrapOrError(CompactUnwind.getContents(), Obj->getFileName()); 7903 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7904 7905 // First populate the initial raw offsets, encodings and so on from the entry. 7906 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7907 CompactUnwindEntry Entry(Contents, Offset, Is64); 7908 CompactUnwinds.push_back(Entry); 7909 } 7910 7911 // Next we need to look at the relocations to find out what objects are 7912 // actually being referred to. 7913 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7914 uint64_t RelocAddress = Reloc.getOffset(); 7915 7916 uint32_t EntryIdx = RelocAddress / EntrySize; 7917 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7918 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7919 7920 if (OffsetInEntry == 0) 7921 Entry.FunctionReloc = Reloc; 7922 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7923 Entry.PersonalityReloc = Reloc; 7924 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7925 Entry.LSDAReloc = Reloc; 7926 else { 7927 outs() << "Invalid relocation in __compact_unwind section\n"; 7928 return; 7929 } 7930 } 7931 7932 // Finally, we're ready to print the data we've gathered. 7933 outs() << "Contents of __compact_unwind section:\n"; 7934 for (auto &Entry : CompactUnwinds) { 7935 outs() << " Entry at offset " 7936 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7937 7938 // 1. Start of the region this entry applies to. 7939 outs() << " start: " << format("0x%" PRIx64, 7940 Entry.FunctionAddr) << ' '; 7941 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7942 outs() << '\n'; 7943 7944 // 2. Length of the region this entry applies to. 7945 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7946 << '\n'; 7947 // 3. The 32-bit compact encoding. 7948 outs() << " compact encoding: " 7949 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7950 7951 // 4. The personality function, if present. 7952 if (Entry.PersonalityReloc.getObject()) { 7953 outs() << " personality function: " 7954 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7955 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7956 Entry.PersonalityAddr); 7957 outs() << '\n'; 7958 } 7959 7960 // 5. This entry's language-specific data area. 7961 if (Entry.LSDAReloc.getObject()) { 7962 outs() << " LSDA: " << format("0x%" PRIx64, 7963 Entry.LSDAAddr) << ' '; 7964 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7965 outs() << '\n'; 7966 } 7967 } 7968 } 7969 7970 //===----------------------------------------------------------------------===// 7971 // __unwind_info section dumping 7972 //===----------------------------------------------------------------------===// 7973 7974 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 7975 ptrdiff_t Pos = 0; 7976 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7977 (void)Kind; 7978 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7979 7980 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7981 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7982 7983 Pos = EntriesStart; 7984 for (unsigned i = 0; i < NumEntries; ++i) { 7985 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 7986 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7987 7988 outs() << " [" << i << "]: " 7989 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7990 << ", " 7991 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7992 } 7993 } 7994 7995 static void printCompressedSecondLevelUnwindPage( 7996 StringRef PageData, uint32_t FunctionBase, 7997 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7998 ptrdiff_t Pos = 0; 7999 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 8000 (void)Kind; 8001 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 8002 8003 uint32_t NumCommonEncodings = CommonEncodings.size(); 8004 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 8005 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 8006 8007 uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos); 8008 uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos); 8009 SmallVector<uint32_t, 64> PageEncodings; 8010 if (NumPageEncodings) { 8011 outs() << " Page encodings: (count = " << NumPageEncodings << ")\n"; 8012 Pos = PageEncodingsStart; 8013 for (unsigned i = 0; i < NumPageEncodings; ++i) { 8014 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 8015 PageEncodings.push_back(Encoding); 8016 outs() << " encoding[" << (i + NumCommonEncodings) 8017 << "]: " << format("0x%08" PRIx32, Encoding) << '\n'; 8018 } 8019 } 8020 8021 Pos = EntriesStart; 8022 for (unsigned i = 0; i < NumEntries; ++i) { 8023 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 8024 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 8025 uint32_t EncodingIdx = Entry >> 24; 8026 8027 uint32_t Encoding; 8028 if (EncodingIdx < NumCommonEncodings) 8029 Encoding = CommonEncodings[EncodingIdx]; 8030 else 8031 Encoding = PageEncodings[EncodingIdx - NumCommonEncodings]; 8032 8033 outs() << " [" << i << "]: " 8034 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8035 << ", " 8036 << "encoding[" << EncodingIdx 8037 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 8038 } 8039 } 8040 8041 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 8042 std::map<uint64_t, SymbolRef> &Symbols, 8043 const SectionRef &UnwindInfo) { 8044 8045 if (!Obj->isLittleEndian()) { 8046 outs() << "Skipping big-endian __unwind_info section\n"; 8047 return; 8048 } 8049 8050 outs() << "Contents of __unwind_info section:\n"; 8051 8052 StringRef Contents = 8053 unwrapOrError(UnwindInfo.getContents(), Obj->getFileName()); 8054 ptrdiff_t Pos = 0; 8055 8056 //===---------------------------------- 8057 // Section header 8058 //===---------------------------------- 8059 8060 uint32_t Version = readNext<uint32_t>(Contents, Pos); 8061 outs() << " Version: " 8062 << format("0x%" PRIx32, Version) << '\n'; 8063 if (Version != 1) { 8064 outs() << " Skipping section with unknown version\n"; 8065 return; 8066 } 8067 8068 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 8069 outs() << " Common encodings array section offset: " 8070 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 8071 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 8072 outs() << " Number of common encodings in array: " 8073 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 8074 8075 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 8076 outs() << " Personality function array section offset: " 8077 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 8078 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 8079 outs() << " Number of personality functions in array: " 8080 << format("0x%" PRIx32, NumPersonalities) << '\n'; 8081 8082 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 8083 outs() << " Index array section offset: " 8084 << format("0x%" PRIx32, IndicesStart) << '\n'; 8085 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 8086 outs() << " Number of indices in array: " 8087 << format("0x%" PRIx32, NumIndices) << '\n'; 8088 8089 //===---------------------------------- 8090 // A shared list of common encodings 8091 //===---------------------------------- 8092 8093 // These occupy indices in the range [0, N] whenever an encoding is referenced 8094 // from a compressed 2nd level index table. In practice the linker only 8095 // creates ~128 of these, so that indices are available to embed encodings in 8096 // the 2nd level index. 8097 8098 SmallVector<uint32_t, 64> CommonEncodings; 8099 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 8100 Pos = CommonEncodingsStart; 8101 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 8102 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 8103 CommonEncodings.push_back(Encoding); 8104 8105 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 8106 << '\n'; 8107 } 8108 8109 //===---------------------------------- 8110 // Personality functions used in this executable 8111 //===---------------------------------- 8112 8113 // There should be only a handful of these (one per source language, 8114 // roughly). Particularly since they only get 2 bits in the compact encoding. 8115 8116 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 8117 Pos = PersonalitiesStart; 8118 for (unsigned i = 0; i < NumPersonalities; ++i) { 8119 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 8120 outs() << " personality[" << i + 1 8121 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 8122 } 8123 8124 //===---------------------------------- 8125 // The level 1 index entries 8126 //===---------------------------------- 8127 8128 // These specify an approximate place to start searching for the more detailed 8129 // information, sorted by PC. 8130 8131 struct IndexEntry { 8132 uint32_t FunctionOffset; 8133 uint32_t SecondLevelPageStart; 8134 uint32_t LSDAStart; 8135 }; 8136 8137 SmallVector<IndexEntry, 4> IndexEntries; 8138 8139 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 8140 Pos = IndicesStart; 8141 for (unsigned i = 0; i < NumIndices; ++i) { 8142 IndexEntry Entry; 8143 8144 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 8145 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 8146 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 8147 IndexEntries.push_back(Entry); 8148 8149 outs() << " [" << i << "]: " 8150 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 8151 << ", " 8152 << "2nd level page offset=" 8153 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 8154 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 8155 } 8156 8157 //===---------------------------------- 8158 // Next come the LSDA tables 8159 //===---------------------------------- 8160 8161 // The LSDA layout is rather implicit: it's a contiguous array of entries from 8162 // the first top-level index's LSDAOffset to the last (sentinel). 8163 8164 outs() << " LSDA descriptors:\n"; 8165 Pos = IndexEntries[0].LSDAStart; 8166 const uint32_t LSDASize = 2 * sizeof(uint32_t); 8167 int NumLSDAs = 8168 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 8169 8170 for (int i = 0; i < NumLSDAs; ++i) { 8171 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 8172 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 8173 outs() << " [" << i << "]: " 8174 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8175 << ", " 8176 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 8177 } 8178 8179 //===---------------------------------- 8180 // Finally, the 2nd level indices 8181 //===---------------------------------- 8182 8183 // Generally these are 4K in size, and have 2 possible forms: 8184 // + Regular stores up to 511 entries with disparate encodings 8185 // + Compressed stores up to 1021 entries if few enough compact encoding 8186 // values are used. 8187 outs() << " Second level indices:\n"; 8188 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 8189 // The final sentinel top-level index has no associated 2nd level page 8190 if (IndexEntries[i].SecondLevelPageStart == 0) 8191 break; 8192 8193 outs() << " Second level index[" << i << "]: " 8194 << "offset in section=" 8195 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 8196 << ", " 8197 << "base function offset=" 8198 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 8199 8200 Pos = IndexEntries[i].SecondLevelPageStart; 8201 if (Pos + sizeof(uint32_t) > Contents.size()) { 8202 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 8203 continue; 8204 } 8205 8206 uint32_t Kind = 8207 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 8208 if (Kind == 2) 8209 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 8210 else if (Kind == 3) 8211 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 8212 IndexEntries[i].FunctionOffset, 8213 CommonEncodings); 8214 else 8215 outs() << " Skipping 2nd level page with unknown kind " << Kind 8216 << '\n'; 8217 } 8218 } 8219 8220 void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) { 8221 std::map<uint64_t, SymbolRef> Symbols; 8222 for (const SymbolRef &SymRef : Obj->symbols()) { 8223 // Discard any undefined or absolute symbols. They're not going to take part 8224 // in the convenience lookup for unwind info and just take up resources. 8225 auto SectOrErr = SymRef.getSection(); 8226 if (!SectOrErr) { 8227 // TODO: Actually report errors helpfully. 8228 consumeError(SectOrErr.takeError()); 8229 continue; 8230 } 8231 section_iterator Section = *SectOrErr; 8232 if (Section == Obj->section_end()) 8233 continue; 8234 8235 uint64_t Addr = cantFail(SymRef.getValue()); 8236 Symbols.insert(std::make_pair(Addr, SymRef)); 8237 } 8238 8239 for (const SectionRef &Section : Obj->sections()) { 8240 StringRef SectName; 8241 if (Expected<StringRef> NameOrErr = Section.getName()) 8242 SectName = *NameOrErr; 8243 else 8244 consumeError(NameOrErr.takeError()); 8245 8246 if (SectName == "__compact_unwind") 8247 printMachOCompactUnwindSection(Obj, Symbols, Section); 8248 else if (SectName == "__unwind_info") 8249 printMachOUnwindInfoSection(Obj, Symbols, Section); 8250 } 8251 } 8252 8253 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 8254 uint32_t cpusubtype, uint32_t filetype, 8255 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 8256 bool verbose) { 8257 outs() << "Mach header\n"; 8258 outs() << " magic cputype cpusubtype caps filetype ncmds " 8259 "sizeofcmds flags\n"; 8260 if (verbose) { 8261 if (magic == MachO::MH_MAGIC) 8262 outs() << " MH_MAGIC"; 8263 else if (magic == MachO::MH_MAGIC_64) 8264 outs() << "MH_MAGIC_64"; 8265 else 8266 outs() << format(" 0x%08" PRIx32, magic); 8267 switch (cputype) { 8268 case MachO::CPU_TYPE_I386: 8269 outs() << " I386"; 8270 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8271 case MachO::CPU_SUBTYPE_I386_ALL: 8272 outs() << " ALL"; 8273 break; 8274 default: 8275 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8276 break; 8277 } 8278 break; 8279 case MachO::CPU_TYPE_X86_64: 8280 outs() << " X86_64"; 8281 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8282 case MachO::CPU_SUBTYPE_X86_64_ALL: 8283 outs() << " ALL"; 8284 break; 8285 case MachO::CPU_SUBTYPE_X86_64_H: 8286 outs() << " Haswell"; 8287 break; 8288 default: 8289 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8290 break; 8291 } 8292 break; 8293 case MachO::CPU_TYPE_ARM: 8294 outs() << " ARM"; 8295 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8296 case MachO::CPU_SUBTYPE_ARM_ALL: 8297 outs() << " ALL"; 8298 break; 8299 case MachO::CPU_SUBTYPE_ARM_V4T: 8300 outs() << " V4T"; 8301 break; 8302 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 8303 outs() << " V5TEJ"; 8304 break; 8305 case MachO::CPU_SUBTYPE_ARM_XSCALE: 8306 outs() << " XSCALE"; 8307 break; 8308 case MachO::CPU_SUBTYPE_ARM_V6: 8309 outs() << " V6"; 8310 break; 8311 case MachO::CPU_SUBTYPE_ARM_V6M: 8312 outs() << " V6M"; 8313 break; 8314 case MachO::CPU_SUBTYPE_ARM_V7: 8315 outs() << " V7"; 8316 break; 8317 case MachO::CPU_SUBTYPE_ARM_V7EM: 8318 outs() << " V7EM"; 8319 break; 8320 case MachO::CPU_SUBTYPE_ARM_V7K: 8321 outs() << " V7K"; 8322 break; 8323 case MachO::CPU_SUBTYPE_ARM_V7M: 8324 outs() << " V7M"; 8325 break; 8326 case MachO::CPU_SUBTYPE_ARM_V7S: 8327 outs() << " V7S"; 8328 break; 8329 default: 8330 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8331 break; 8332 } 8333 break; 8334 case MachO::CPU_TYPE_ARM64: 8335 outs() << " ARM64"; 8336 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8337 case MachO::CPU_SUBTYPE_ARM64_ALL: 8338 outs() << " ALL"; 8339 break; 8340 case MachO::CPU_SUBTYPE_ARM64_V8: 8341 outs() << " V8"; 8342 break; 8343 case MachO::CPU_SUBTYPE_ARM64E: 8344 outs() << " E"; 8345 break; 8346 default: 8347 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8348 break; 8349 } 8350 break; 8351 case MachO::CPU_TYPE_ARM64_32: 8352 outs() << " ARM64_32"; 8353 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8354 case MachO::CPU_SUBTYPE_ARM64_32_V8: 8355 outs() << " V8"; 8356 break; 8357 default: 8358 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8359 break; 8360 } 8361 break; 8362 case MachO::CPU_TYPE_POWERPC: 8363 outs() << " PPC"; 8364 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8365 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8366 outs() << " ALL"; 8367 break; 8368 default: 8369 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8370 break; 8371 } 8372 break; 8373 case MachO::CPU_TYPE_POWERPC64: 8374 outs() << " PPC64"; 8375 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8376 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8377 outs() << " ALL"; 8378 break; 8379 default: 8380 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8381 break; 8382 } 8383 break; 8384 default: 8385 outs() << format(" %7d", cputype); 8386 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8387 break; 8388 } 8389 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 8390 outs() << " LIB64"; 8391 } else { 8392 outs() << format(" 0x%02" PRIx32, 8393 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8394 } 8395 switch (filetype) { 8396 case MachO::MH_OBJECT: 8397 outs() << " OBJECT"; 8398 break; 8399 case MachO::MH_EXECUTE: 8400 outs() << " EXECUTE"; 8401 break; 8402 case MachO::MH_FVMLIB: 8403 outs() << " FVMLIB"; 8404 break; 8405 case MachO::MH_CORE: 8406 outs() << " CORE"; 8407 break; 8408 case MachO::MH_PRELOAD: 8409 outs() << " PRELOAD"; 8410 break; 8411 case MachO::MH_DYLIB: 8412 outs() << " DYLIB"; 8413 break; 8414 case MachO::MH_DYLIB_STUB: 8415 outs() << " DYLIB_STUB"; 8416 break; 8417 case MachO::MH_DYLINKER: 8418 outs() << " DYLINKER"; 8419 break; 8420 case MachO::MH_BUNDLE: 8421 outs() << " BUNDLE"; 8422 break; 8423 case MachO::MH_DSYM: 8424 outs() << " DSYM"; 8425 break; 8426 case MachO::MH_KEXT_BUNDLE: 8427 outs() << " KEXTBUNDLE"; 8428 break; 8429 default: 8430 outs() << format(" %10u", filetype); 8431 break; 8432 } 8433 outs() << format(" %5u", ncmds); 8434 outs() << format(" %10u", sizeofcmds); 8435 uint32_t f = flags; 8436 if (f & MachO::MH_NOUNDEFS) { 8437 outs() << " NOUNDEFS"; 8438 f &= ~MachO::MH_NOUNDEFS; 8439 } 8440 if (f & MachO::MH_INCRLINK) { 8441 outs() << " INCRLINK"; 8442 f &= ~MachO::MH_INCRLINK; 8443 } 8444 if (f & MachO::MH_DYLDLINK) { 8445 outs() << " DYLDLINK"; 8446 f &= ~MachO::MH_DYLDLINK; 8447 } 8448 if (f & MachO::MH_BINDATLOAD) { 8449 outs() << " BINDATLOAD"; 8450 f &= ~MachO::MH_BINDATLOAD; 8451 } 8452 if (f & MachO::MH_PREBOUND) { 8453 outs() << " PREBOUND"; 8454 f &= ~MachO::MH_PREBOUND; 8455 } 8456 if (f & MachO::MH_SPLIT_SEGS) { 8457 outs() << " SPLIT_SEGS"; 8458 f &= ~MachO::MH_SPLIT_SEGS; 8459 } 8460 if (f & MachO::MH_LAZY_INIT) { 8461 outs() << " LAZY_INIT"; 8462 f &= ~MachO::MH_LAZY_INIT; 8463 } 8464 if (f & MachO::MH_TWOLEVEL) { 8465 outs() << " TWOLEVEL"; 8466 f &= ~MachO::MH_TWOLEVEL; 8467 } 8468 if (f & MachO::MH_FORCE_FLAT) { 8469 outs() << " FORCE_FLAT"; 8470 f &= ~MachO::MH_FORCE_FLAT; 8471 } 8472 if (f & MachO::MH_NOMULTIDEFS) { 8473 outs() << " NOMULTIDEFS"; 8474 f &= ~MachO::MH_NOMULTIDEFS; 8475 } 8476 if (f & MachO::MH_NOFIXPREBINDING) { 8477 outs() << " NOFIXPREBINDING"; 8478 f &= ~MachO::MH_NOFIXPREBINDING; 8479 } 8480 if (f & MachO::MH_PREBINDABLE) { 8481 outs() << " PREBINDABLE"; 8482 f &= ~MachO::MH_PREBINDABLE; 8483 } 8484 if (f & MachO::MH_ALLMODSBOUND) { 8485 outs() << " ALLMODSBOUND"; 8486 f &= ~MachO::MH_ALLMODSBOUND; 8487 } 8488 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8489 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8490 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8491 } 8492 if (f & MachO::MH_CANONICAL) { 8493 outs() << " CANONICAL"; 8494 f &= ~MachO::MH_CANONICAL; 8495 } 8496 if (f & MachO::MH_WEAK_DEFINES) { 8497 outs() << " WEAK_DEFINES"; 8498 f &= ~MachO::MH_WEAK_DEFINES; 8499 } 8500 if (f & MachO::MH_BINDS_TO_WEAK) { 8501 outs() << " BINDS_TO_WEAK"; 8502 f &= ~MachO::MH_BINDS_TO_WEAK; 8503 } 8504 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8505 outs() << " ALLOW_STACK_EXECUTION"; 8506 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8507 } 8508 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8509 outs() << " DEAD_STRIPPABLE_DYLIB"; 8510 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8511 } 8512 if (f & MachO::MH_PIE) { 8513 outs() << " PIE"; 8514 f &= ~MachO::MH_PIE; 8515 } 8516 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8517 outs() << " NO_REEXPORTED_DYLIBS"; 8518 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8519 } 8520 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8521 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8522 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8523 } 8524 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8525 outs() << " MH_NO_HEAP_EXECUTION"; 8526 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8527 } 8528 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8529 outs() << " APP_EXTENSION_SAFE"; 8530 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8531 } 8532 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8533 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8534 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8535 } 8536 if (f != 0 || flags == 0) 8537 outs() << format(" 0x%08" PRIx32, f); 8538 } else { 8539 outs() << format(" 0x%08" PRIx32, magic); 8540 outs() << format(" %7d", cputype); 8541 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8542 outs() << format(" 0x%02" PRIx32, 8543 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8544 outs() << format(" %10u", filetype); 8545 outs() << format(" %5u", ncmds); 8546 outs() << format(" %10u", sizeofcmds); 8547 outs() << format(" 0x%08" PRIx32, flags); 8548 } 8549 outs() << "\n"; 8550 } 8551 8552 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8553 StringRef SegName, uint64_t vmaddr, 8554 uint64_t vmsize, uint64_t fileoff, 8555 uint64_t filesize, uint32_t maxprot, 8556 uint32_t initprot, uint32_t nsects, 8557 uint32_t flags, uint32_t object_size, 8558 bool verbose) { 8559 uint64_t expected_cmdsize; 8560 if (cmd == MachO::LC_SEGMENT) { 8561 outs() << " cmd LC_SEGMENT\n"; 8562 expected_cmdsize = nsects; 8563 expected_cmdsize *= sizeof(struct MachO::section); 8564 expected_cmdsize += sizeof(struct MachO::segment_command); 8565 } else { 8566 outs() << " cmd LC_SEGMENT_64\n"; 8567 expected_cmdsize = nsects; 8568 expected_cmdsize *= sizeof(struct MachO::section_64); 8569 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8570 } 8571 outs() << " cmdsize " << cmdsize; 8572 if (cmdsize != expected_cmdsize) 8573 outs() << " Inconsistent size\n"; 8574 else 8575 outs() << "\n"; 8576 outs() << " segname " << SegName << "\n"; 8577 if (cmd == MachO::LC_SEGMENT_64) { 8578 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8579 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8580 } else { 8581 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8582 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8583 } 8584 outs() << " fileoff " << fileoff; 8585 if (fileoff > object_size) 8586 outs() << " (past end of file)\n"; 8587 else 8588 outs() << "\n"; 8589 outs() << " filesize " << filesize; 8590 if (fileoff + filesize > object_size) 8591 outs() << " (past end of file)\n"; 8592 else 8593 outs() << "\n"; 8594 if (verbose) { 8595 if ((maxprot & 8596 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8597 MachO::VM_PROT_EXECUTE)) != 0) 8598 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8599 else { 8600 outs() << " maxprot "; 8601 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8602 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8603 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8604 } 8605 if ((initprot & 8606 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8607 MachO::VM_PROT_EXECUTE)) != 0) 8608 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8609 else { 8610 outs() << " initprot "; 8611 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8612 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8613 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8614 } 8615 } else { 8616 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8617 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8618 } 8619 outs() << " nsects " << nsects << "\n"; 8620 if (verbose) { 8621 outs() << " flags"; 8622 if (flags == 0) 8623 outs() << " (none)\n"; 8624 else { 8625 if (flags & MachO::SG_HIGHVM) { 8626 outs() << " HIGHVM"; 8627 flags &= ~MachO::SG_HIGHVM; 8628 } 8629 if (flags & MachO::SG_FVMLIB) { 8630 outs() << " FVMLIB"; 8631 flags &= ~MachO::SG_FVMLIB; 8632 } 8633 if (flags & MachO::SG_NORELOC) { 8634 outs() << " NORELOC"; 8635 flags &= ~MachO::SG_NORELOC; 8636 } 8637 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8638 outs() << " PROTECTED_VERSION_1"; 8639 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8640 } 8641 if (flags) 8642 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8643 else 8644 outs() << "\n"; 8645 } 8646 } else { 8647 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8648 } 8649 } 8650 8651 static void PrintSection(const char *sectname, const char *segname, 8652 uint64_t addr, uint64_t size, uint32_t offset, 8653 uint32_t align, uint32_t reloff, uint32_t nreloc, 8654 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8655 uint32_t cmd, const char *sg_segname, 8656 uint32_t filetype, uint32_t object_size, 8657 bool verbose) { 8658 outs() << "Section\n"; 8659 outs() << " sectname " << format("%.16s\n", sectname); 8660 outs() << " segname " << format("%.16s", segname); 8661 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8662 outs() << " (does not match segment)\n"; 8663 else 8664 outs() << "\n"; 8665 if (cmd == MachO::LC_SEGMENT_64) { 8666 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8667 outs() << " size " << format("0x%016" PRIx64, size); 8668 } else { 8669 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8670 outs() << " size " << format("0x%08" PRIx64, size); 8671 } 8672 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8673 outs() << " (past end of file)\n"; 8674 else 8675 outs() << "\n"; 8676 outs() << " offset " << offset; 8677 if (offset > object_size) 8678 outs() << " (past end of file)\n"; 8679 else 8680 outs() << "\n"; 8681 uint32_t align_shifted = 1 << align; 8682 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8683 outs() << " reloff " << reloff; 8684 if (reloff > object_size) 8685 outs() << " (past end of file)\n"; 8686 else 8687 outs() << "\n"; 8688 outs() << " nreloc " << nreloc; 8689 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8690 outs() << " (past end of file)\n"; 8691 else 8692 outs() << "\n"; 8693 uint32_t section_type = flags & MachO::SECTION_TYPE; 8694 if (verbose) { 8695 outs() << " type"; 8696 if (section_type == MachO::S_REGULAR) 8697 outs() << " S_REGULAR\n"; 8698 else if (section_type == MachO::S_ZEROFILL) 8699 outs() << " S_ZEROFILL\n"; 8700 else if (section_type == MachO::S_CSTRING_LITERALS) 8701 outs() << " S_CSTRING_LITERALS\n"; 8702 else if (section_type == MachO::S_4BYTE_LITERALS) 8703 outs() << " S_4BYTE_LITERALS\n"; 8704 else if (section_type == MachO::S_8BYTE_LITERALS) 8705 outs() << " S_8BYTE_LITERALS\n"; 8706 else if (section_type == MachO::S_16BYTE_LITERALS) 8707 outs() << " S_16BYTE_LITERALS\n"; 8708 else if (section_type == MachO::S_LITERAL_POINTERS) 8709 outs() << " S_LITERAL_POINTERS\n"; 8710 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8711 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8712 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8713 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8714 else if (section_type == MachO::S_SYMBOL_STUBS) 8715 outs() << " S_SYMBOL_STUBS\n"; 8716 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8717 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8718 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8719 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8720 else if (section_type == MachO::S_COALESCED) 8721 outs() << " S_COALESCED\n"; 8722 else if (section_type == MachO::S_INTERPOSING) 8723 outs() << " S_INTERPOSING\n"; 8724 else if (section_type == MachO::S_DTRACE_DOF) 8725 outs() << " S_DTRACE_DOF\n"; 8726 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8727 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8728 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8729 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8730 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8731 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8732 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8733 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8734 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8735 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8736 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8737 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8738 else 8739 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8740 outs() << "attributes"; 8741 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8742 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8743 outs() << " PURE_INSTRUCTIONS"; 8744 if (section_attributes & MachO::S_ATTR_NO_TOC) 8745 outs() << " NO_TOC"; 8746 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8747 outs() << " STRIP_STATIC_SYMS"; 8748 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8749 outs() << " NO_DEAD_STRIP"; 8750 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8751 outs() << " LIVE_SUPPORT"; 8752 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8753 outs() << " SELF_MODIFYING_CODE"; 8754 if (section_attributes & MachO::S_ATTR_DEBUG) 8755 outs() << " DEBUG"; 8756 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8757 outs() << " SOME_INSTRUCTIONS"; 8758 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8759 outs() << " EXT_RELOC"; 8760 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8761 outs() << " LOC_RELOC"; 8762 if (section_attributes == 0) 8763 outs() << " (none)"; 8764 outs() << "\n"; 8765 } else 8766 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8767 outs() << " reserved1 " << reserved1; 8768 if (section_type == MachO::S_SYMBOL_STUBS || 8769 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8770 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8771 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8772 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8773 outs() << " (index into indirect symbol table)\n"; 8774 else 8775 outs() << "\n"; 8776 outs() << " reserved2 " << reserved2; 8777 if (section_type == MachO::S_SYMBOL_STUBS) 8778 outs() << " (size of stubs)\n"; 8779 else 8780 outs() << "\n"; 8781 } 8782 8783 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8784 uint32_t object_size) { 8785 outs() << " cmd LC_SYMTAB\n"; 8786 outs() << " cmdsize " << st.cmdsize; 8787 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8788 outs() << " Incorrect size\n"; 8789 else 8790 outs() << "\n"; 8791 outs() << " symoff " << st.symoff; 8792 if (st.symoff > object_size) 8793 outs() << " (past end of file)\n"; 8794 else 8795 outs() << "\n"; 8796 outs() << " nsyms " << st.nsyms; 8797 uint64_t big_size; 8798 if (Is64Bit) { 8799 big_size = st.nsyms; 8800 big_size *= sizeof(struct MachO::nlist_64); 8801 big_size += st.symoff; 8802 if (big_size > object_size) 8803 outs() << " (past end of file)\n"; 8804 else 8805 outs() << "\n"; 8806 } else { 8807 big_size = st.nsyms; 8808 big_size *= sizeof(struct MachO::nlist); 8809 big_size += st.symoff; 8810 if (big_size > object_size) 8811 outs() << " (past end of file)\n"; 8812 else 8813 outs() << "\n"; 8814 } 8815 outs() << " stroff " << st.stroff; 8816 if (st.stroff > object_size) 8817 outs() << " (past end of file)\n"; 8818 else 8819 outs() << "\n"; 8820 outs() << " strsize " << st.strsize; 8821 big_size = st.stroff; 8822 big_size += st.strsize; 8823 if (big_size > object_size) 8824 outs() << " (past end of file)\n"; 8825 else 8826 outs() << "\n"; 8827 } 8828 8829 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8830 uint32_t nsyms, uint32_t object_size, 8831 bool Is64Bit) { 8832 outs() << " cmd LC_DYSYMTAB\n"; 8833 outs() << " cmdsize " << dyst.cmdsize; 8834 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8835 outs() << " Incorrect size\n"; 8836 else 8837 outs() << "\n"; 8838 outs() << " ilocalsym " << dyst.ilocalsym; 8839 if (dyst.ilocalsym > nsyms) 8840 outs() << " (greater than the number of symbols)\n"; 8841 else 8842 outs() << "\n"; 8843 outs() << " nlocalsym " << dyst.nlocalsym; 8844 uint64_t big_size; 8845 big_size = dyst.ilocalsym; 8846 big_size += dyst.nlocalsym; 8847 if (big_size > nsyms) 8848 outs() << " (past the end of the symbol table)\n"; 8849 else 8850 outs() << "\n"; 8851 outs() << " iextdefsym " << dyst.iextdefsym; 8852 if (dyst.iextdefsym > nsyms) 8853 outs() << " (greater than the number of symbols)\n"; 8854 else 8855 outs() << "\n"; 8856 outs() << " nextdefsym " << dyst.nextdefsym; 8857 big_size = dyst.iextdefsym; 8858 big_size += dyst.nextdefsym; 8859 if (big_size > nsyms) 8860 outs() << " (past the end of the symbol table)\n"; 8861 else 8862 outs() << "\n"; 8863 outs() << " iundefsym " << dyst.iundefsym; 8864 if (dyst.iundefsym > nsyms) 8865 outs() << " (greater than the number of symbols)\n"; 8866 else 8867 outs() << "\n"; 8868 outs() << " nundefsym " << dyst.nundefsym; 8869 big_size = dyst.iundefsym; 8870 big_size += dyst.nundefsym; 8871 if (big_size > nsyms) 8872 outs() << " (past the end of the symbol table)\n"; 8873 else 8874 outs() << "\n"; 8875 outs() << " tocoff " << dyst.tocoff; 8876 if (dyst.tocoff > object_size) 8877 outs() << " (past end of file)\n"; 8878 else 8879 outs() << "\n"; 8880 outs() << " ntoc " << dyst.ntoc; 8881 big_size = dyst.ntoc; 8882 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8883 big_size += dyst.tocoff; 8884 if (big_size > object_size) 8885 outs() << " (past end of file)\n"; 8886 else 8887 outs() << "\n"; 8888 outs() << " modtaboff " << dyst.modtaboff; 8889 if (dyst.modtaboff > object_size) 8890 outs() << " (past end of file)\n"; 8891 else 8892 outs() << "\n"; 8893 outs() << " nmodtab " << dyst.nmodtab; 8894 uint64_t modtabend; 8895 if (Is64Bit) { 8896 modtabend = dyst.nmodtab; 8897 modtabend *= sizeof(struct MachO::dylib_module_64); 8898 modtabend += dyst.modtaboff; 8899 } else { 8900 modtabend = dyst.nmodtab; 8901 modtabend *= sizeof(struct MachO::dylib_module); 8902 modtabend += dyst.modtaboff; 8903 } 8904 if (modtabend > object_size) 8905 outs() << " (past end of file)\n"; 8906 else 8907 outs() << "\n"; 8908 outs() << " extrefsymoff " << dyst.extrefsymoff; 8909 if (dyst.extrefsymoff > object_size) 8910 outs() << " (past end of file)\n"; 8911 else 8912 outs() << "\n"; 8913 outs() << " nextrefsyms " << dyst.nextrefsyms; 8914 big_size = dyst.nextrefsyms; 8915 big_size *= sizeof(struct MachO::dylib_reference); 8916 big_size += dyst.extrefsymoff; 8917 if (big_size > object_size) 8918 outs() << " (past end of file)\n"; 8919 else 8920 outs() << "\n"; 8921 outs() << " indirectsymoff " << dyst.indirectsymoff; 8922 if (dyst.indirectsymoff > object_size) 8923 outs() << " (past end of file)\n"; 8924 else 8925 outs() << "\n"; 8926 outs() << " nindirectsyms " << dyst.nindirectsyms; 8927 big_size = dyst.nindirectsyms; 8928 big_size *= sizeof(uint32_t); 8929 big_size += dyst.indirectsymoff; 8930 if (big_size > object_size) 8931 outs() << " (past end of file)\n"; 8932 else 8933 outs() << "\n"; 8934 outs() << " extreloff " << dyst.extreloff; 8935 if (dyst.extreloff > object_size) 8936 outs() << " (past end of file)\n"; 8937 else 8938 outs() << "\n"; 8939 outs() << " nextrel " << dyst.nextrel; 8940 big_size = dyst.nextrel; 8941 big_size *= sizeof(struct MachO::relocation_info); 8942 big_size += dyst.extreloff; 8943 if (big_size > object_size) 8944 outs() << " (past end of file)\n"; 8945 else 8946 outs() << "\n"; 8947 outs() << " locreloff " << dyst.locreloff; 8948 if (dyst.locreloff > object_size) 8949 outs() << " (past end of file)\n"; 8950 else 8951 outs() << "\n"; 8952 outs() << " nlocrel " << dyst.nlocrel; 8953 big_size = dyst.nlocrel; 8954 big_size *= sizeof(struct MachO::relocation_info); 8955 big_size += dyst.locreloff; 8956 if (big_size > object_size) 8957 outs() << " (past end of file)\n"; 8958 else 8959 outs() << "\n"; 8960 } 8961 8962 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8963 uint32_t object_size) { 8964 if (dc.cmd == MachO::LC_DYLD_INFO) 8965 outs() << " cmd LC_DYLD_INFO\n"; 8966 else 8967 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8968 outs() << " cmdsize " << dc.cmdsize; 8969 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8970 outs() << " Incorrect size\n"; 8971 else 8972 outs() << "\n"; 8973 outs() << " rebase_off " << dc.rebase_off; 8974 if (dc.rebase_off > object_size) 8975 outs() << " (past end of file)\n"; 8976 else 8977 outs() << "\n"; 8978 outs() << " rebase_size " << dc.rebase_size; 8979 uint64_t big_size; 8980 big_size = dc.rebase_off; 8981 big_size += dc.rebase_size; 8982 if (big_size > object_size) 8983 outs() << " (past end of file)\n"; 8984 else 8985 outs() << "\n"; 8986 outs() << " bind_off " << dc.bind_off; 8987 if (dc.bind_off > object_size) 8988 outs() << " (past end of file)\n"; 8989 else 8990 outs() << "\n"; 8991 outs() << " bind_size " << dc.bind_size; 8992 big_size = dc.bind_off; 8993 big_size += dc.bind_size; 8994 if (big_size > object_size) 8995 outs() << " (past end of file)\n"; 8996 else 8997 outs() << "\n"; 8998 outs() << " weak_bind_off " << dc.weak_bind_off; 8999 if (dc.weak_bind_off > object_size) 9000 outs() << " (past end of file)\n"; 9001 else 9002 outs() << "\n"; 9003 outs() << " weak_bind_size " << dc.weak_bind_size; 9004 big_size = dc.weak_bind_off; 9005 big_size += dc.weak_bind_size; 9006 if (big_size > object_size) 9007 outs() << " (past end of file)\n"; 9008 else 9009 outs() << "\n"; 9010 outs() << " lazy_bind_off " << dc.lazy_bind_off; 9011 if (dc.lazy_bind_off > object_size) 9012 outs() << " (past end of file)\n"; 9013 else 9014 outs() << "\n"; 9015 outs() << " lazy_bind_size " << dc.lazy_bind_size; 9016 big_size = dc.lazy_bind_off; 9017 big_size += dc.lazy_bind_size; 9018 if (big_size > object_size) 9019 outs() << " (past end of file)\n"; 9020 else 9021 outs() << "\n"; 9022 outs() << " export_off " << dc.export_off; 9023 if (dc.export_off > object_size) 9024 outs() << " (past end of file)\n"; 9025 else 9026 outs() << "\n"; 9027 outs() << " export_size " << dc.export_size; 9028 big_size = dc.export_off; 9029 big_size += dc.export_size; 9030 if (big_size > object_size) 9031 outs() << " (past end of file)\n"; 9032 else 9033 outs() << "\n"; 9034 } 9035 9036 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 9037 const char *Ptr) { 9038 if (dyld.cmd == MachO::LC_ID_DYLINKER) 9039 outs() << " cmd LC_ID_DYLINKER\n"; 9040 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 9041 outs() << " cmd LC_LOAD_DYLINKER\n"; 9042 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 9043 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 9044 else 9045 outs() << " cmd ?(" << dyld.cmd << ")\n"; 9046 outs() << " cmdsize " << dyld.cmdsize; 9047 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 9048 outs() << " Incorrect size\n"; 9049 else 9050 outs() << "\n"; 9051 if (dyld.name >= dyld.cmdsize) 9052 outs() << " name ?(bad offset " << dyld.name << ")\n"; 9053 else { 9054 const char *P = (const char *)(Ptr) + dyld.name; 9055 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 9056 } 9057 } 9058 9059 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 9060 outs() << " cmd LC_UUID\n"; 9061 outs() << " cmdsize " << uuid.cmdsize; 9062 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 9063 outs() << " Incorrect size\n"; 9064 else 9065 outs() << "\n"; 9066 outs() << " uuid "; 9067 for (int i = 0; i < 16; ++i) { 9068 outs() << format("%02" PRIX32, uuid.uuid[i]); 9069 if (i == 3 || i == 5 || i == 7 || i == 9) 9070 outs() << "-"; 9071 } 9072 outs() << "\n"; 9073 } 9074 9075 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 9076 outs() << " cmd LC_RPATH\n"; 9077 outs() << " cmdsize " << rpath.cmdsize; 9078 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 9079 outs() << " Incorrect size\n"; 9080 else 9081 outs() << "\n"; 9082 if (rpath.path >= rpath.cmdsize) 9083 outs() << " path ?(bad offset " << rpath.path << ")\n"; 9084 else { 9085 const char *P = (const char *)(Ptr) + rpath.path; 9086 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 9087 } 9088 } 9089 9090 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 9091 StringRef LoadCmdName; 9092 switch (vd.cmd) { 9093 case MachO::LC_VERSION_MIN_MACOSX: 9094 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 9095 break; 9096 case MachO::LC_VERSION_MIN_IPHONEOS: 9097 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 9098 break; 9099 case MachO::LC_VERSION_MIN_TVOS: 9100 LoadCmdName = "LC_VERSION_MIN_TVOS"; 9101 break; 9102 case MachO::LC_VERSION_MIN_WATCHOS: 9103 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 9104 break; 9105 default: 9106 llvm_unreachable("Unknown version min load command"); 9107 } 9108 9109 outs() << " cmd " << LoadCmdName << '\n'; 9110 outs() << " cmdsize " << vd.cmdsize; 9111 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 9112 outs() << " Incorrect size\n"; 9113 else 9114 outs() << "\n"; 9115 outs() << " version " 9116 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 9117 << MachOObjectFile::getVersionMinMinor(vd, false); 9118 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 9119 if (Update != 0) 9120 outs() << "." << Update; 9121 outs() << "\n"; 9122 if (vd.sdk == 0) 9123 outs() << " sdk n/a"; 9124 else { 9125 outs() << " sdk " 9126 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 9127 << MachOObjectFile::getVersionMinMinor(vd, true); 9128 } 9129 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 9130 if (Update != 0) 9131 outs() << "." << Update; 9132 outs() << "\n"; 9133 } 9134 9135 static void PrintNoteLoadCommand(MachO::note_command Nt) { 9136 outs() << " cmd LC_NOTE\n"; 9137 outs() << " cmdsize " << Nt.cmdsize; 9138 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 9139 outs() << " Incorrect size\n"; 9140 else 9141 outs() << "\n"; 9142 const char *d = Nt.data_owner; 9143 outs() << "data_owner " << format("%.16s\n", d); 9144 outs() << " offset " << Nt.offset << "\n"; 9145 outs() << " size " << Nt.size << "\n"; 9146 } 9147 9148 static void PrintBuildToolVersion(MachO::build_tool_version bv) { 9149 outs() << " tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n"; 9150 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 9151 << "\n"; 9152 } 9153 9154 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 9155 MachO::build_version_command bd) { 9156 outs() << " cmd LC_BUILD_VERSION\n"; 9157 outs() << " cmdsize " << bd.cmdsize; 9158 if (bd.cmdsize != 9159 sizeof(struct MachO::build_version_command) + 9160 bd.ntools * sizeof(struct MachO::build_tool_version)) 9161 outs() << " Incorrect size\n"; 9162 else 9163 outs() << "\n"; 9164 outs() << " platform " << MachOObjectFile::getBuildPlatform(bd.platform) 9165 << "\n"; 9166 if (bd.sdk) 9167 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 9168 << "\n"; 9169 else 9170 outs() << " sdk n/a\n"; 9171 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 9172 << "\n"; 9173 outs() << " ntools " << bd.ntools << "\n"; 9174 for (unsigned i = 0; i < bd.ntools; ++i) { 9175 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 9176 PrintBuildToolVersion(bv); 9177 } 9178 } 9179 9180 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 9181 outs() << " cmd LC_SOURCE_VERSION\n"; 9182 outs() << " cmdsize " << sd.cmdsize; 9183 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 9184 outs() << " Incorrect size\n"; 9185 else 9186 outs() << "\n"; 9187 uint64_t a = (sd.version >> 40) & 0xffffff; 9188 uint64_t b = (sd.version >> 30) & 0x3ff; 9189 uint64_t c = (sd.version >> 20) & 0x3ff; 9190 uint64_t d = (sd.version >> 10) & 0x3ff; 9191 uint64_t e = sd.version & 0x3ff; 9192 outs() << " version " << a << "." << b; 9193 if (e != 0) 9194 outs() << "." << c << "." << d << "." << e; 9195 else if (d != 0) 9196 outs() << "." << c << "." << d; 9197 else if (c != 0) 9198 outs() << "." << c; 9199 outs() << "\n"; 9200 } 9201 9202 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 9203 outs() << " cmd LC_MAIN\n"; 9204 outs() << " cmdsize " << ep.cmdsize; 9205 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 9206 outs() << " Incorrect size\n"; 9207 else 9208 outs() << "\n"; 9209 outs() << " entryoff " << ep.entryoff << "\n"; 9210 outs() << " stacksize " << ep.stacksize << "\n"; 9211 } 9212 9213 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 9214 uint32_t object_size) { 9215 outs() << " cmd LC_ENCRYPTION_INFO\n"; 9216 outs() << " cmdsize " << ec.cmdsize; 9217 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 9218 outs() << " Incorrect size\n"; 9219 else 9220 outs() << "\n"; 9221 outs() << " cryptoff " << ec.cryptoff; 9222 if (ec.cryptoff > object_size) 9223 outs() << " (past end of file)\n"; 9224 else 9225 outs() << "\n"; 9226 outs() << " cryptsize " << ec.cryptsize; 9227 if (ec.cryptsize > object_size) 9228 outs() << " (past end of file)\n"; 9229 else 9230 outs() << "\n"; 9231 outs() << " cryptid " << ec.cryptid << "\n"; 9232 } 9233 9234 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 9235 uint32_t object_size) { 9236 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 9237 outs() << " cmdsize " << ec.cmdsize; 9238 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 9239 outs() << " Incorrect size\n"; 9240 else 9241 outs() << "\n"; 9242 outs() << " cryptoff " << ec.cryptoff; 9243 if (ec.cryptoff > object_size) 9244 outs() << " (past end of file)\n"; 9245 else 9246 outs() << "\n"; 9247 outs() << " cryptsize " << ec.cryptsize; 9248 if (ec.cryptsize > object_size) 9249 outs() << " (past end of file)\n"; 9250 else 9251 outs() << "\n"; 9252 outs() << " cryptid " << ec.cryptid << "\n"; 9253 outs() << " pad " << ec.pad << "\n"; 9254 } 9255 9256 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 9257 const char *Ptr) { 9258 outs() << " cmd LC_LINKER_OPTION\n"; 9259 outs() << " cmdsize " << lo.cmdsize; 9260 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 9261 outs() << " Incorrect size\n"; 9262 else 9263 outs() << "\n"; 9264 outs() << " count " << lo.count << "\n"; 9265 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 9266 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 9267 uint32_t i = 0; 9268 while (left > 0) { 9269 while (*string == '\0' && left > 0) { 9270 string++; 9271 left--; 9272 } 9273 if (left > 0) { 9274 i++; 9275 outs() << " string #" << i << " " << format("%.*s\n", left, string); 9276 uint32_t NullPos = StringRef(string, left).find('\0'); 9277 uint32_t len = std::min(NullPos, left) + 1; 9278 string += len; 9279 left -= len; 9280 } 9281 } 9282 if (lo.count != i) 9283 outs() << " count " << lo.count << " does not match number of strings " 9284 << i << "\n"; 9285 } 9286 9287 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 9288 const char *Ptr) { 9289 outs() << " cmd LC_SUB_FRAMEWORK\n"; 9290 outs() << " cmdsize " << sub.cmdsize; 9291 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 9292 outs() << " Incorrect size\n"; 9293 else 9294 outs() << "\n"; 9295 if (sub.umbrella < sub.cmdsize) { 9296 const char *P = Ptr + sub.umbrella; 9297 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 9298 } else { 9299 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 9300 } 9301 } 9302 9303 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 9304 const char *Ptr) { 9305 outs() << " cmd LC_SUB_UMBRELLA\n"; 9306 outs() << " cmdsize " << sub.cmdsize; 9307 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 9308 outs() << " Incorrect size\n"; 9309 else 9310 outs() << "\n"; 9311 if (sub.sub_umbrella < sub.cmdsize) { 9312 const char *P = Ptr + sub.sub_umbrella; 9313 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 9314 } else { 9315 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 9316 } 9317 } 9318 9319 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 9320 const char *Ptr) { 9321 outs() << " cmd LC_SUB_LIBRARY\n"; 9322 outs() << " cmdsize " << sub.cmdsize; 9323 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 9324 outs() << " Incorrect size\n"; 9325 else 9326 outs() << "\n"; 9327 if (sub.sub_library < sub.cmdsize) { 9328 const char *P = Ptr + sub.sub_library; 9329 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 9330 } else { 9331 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 9332 } 9333 } 9334 9335 static void PrintSubClientCommand(MachO::sub_client_command sub, 9336 const char *Ptr) { 9337 outs() << " cmd LC_SUB_CLIENT\n"; 9338 outs() << " cmdsize " << sub.cmdsize; 9339 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 9340 outs() << " Incorrect size\n"; 9341 else 9342 outs() << "\n"; 9343 if (sub.client < sub.cmdsize) { 9344 const char *P = Ptr + sub.client; 9345 outs() << " client " << P << " (offset " << sub.client << ")\n"; 9346 } else { 9347 outs() << " client ?(bad offset " << sub.client << ")\n"; 9348 } 9349 } 9350 9351 static void PrintRoutinesCommand(MachO::routines_command r) { 9352 outs() << " cmd LC_ROUTINES\n"; 9353 outs() << " cmdsize " << r.cmdsize; 9354 if (r.cmdsize != sizeof(struct MachO::routines_command)) 9355 outs() << " Incorrect size\n"; 9356 else 9357 outs() << "\n"; 9358 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 9359 outs() << " init_module " << r.init_module << "\n"; 9360 outs() << " reserved1 " << r.reserved1 << "\n"; 9361 outs() << " reserved2 " << r.reserved2 << "\n"; 9362 outs() << " reserved3 " << r.reserved3 << "\n"; 9363 outs() << " reserved4 " << r.reserved4 << "\n"; 9364 outs() << " reserved5 " << r.reserved5 << "\n"; 9365 outs() << " reserved6 " << r.reserved6 << "\n"; 9366 } 9367 9368 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 9369 outs() << " cmd LC_ROUTINES_64\n"; 9370 outs() << " cmdsize " << r.cmdsize; 9371 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 9372 outs() << " Incorrect size\n"; 9373 else 9374 outs() << "\n"; 9375 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 9376 outs() << " init_module " << r.init_module << "\n"; 9377 outs() << " reserved1 " << r.reserved1 << "\n"; 9378 outs() << " reserved2 " << r.reserved2 << "\n"; 9379 outs() << " reserved3 " << r.reserved3 << "\n"; 9380 outs() << " reserved4 " << r.reserved4 << "\n"; 9381 outs() << " reserved5 " << r.reserved5 << "\n"; 9382 outs() << " reserved6 " << r.reserved6 << "\n"; 9383 } 9384 9385 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 9386 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 9387 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 9388 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 9389 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 9390 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 9391 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 9392 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 9393 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 9394 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 9395 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 9396 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 9397 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 9398 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 9399 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 9400 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 9401 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 9402 } 9403 9404 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 9405 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 9406 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 9407 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 9408 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 9409 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 9410 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 9411 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 9412 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 9413 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 9414 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 9415 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 9416 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 9417 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 9418 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 9419 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 9420 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 9421 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 9422 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 9423 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 9424 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 9425 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 9426 } 9427 9428 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 9429 uint32_t f; 9430 outs() << "\t mmst_reg "; 9431 for (f = 0; f < 10; f++) 9432 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 9433 outs() << "\n"; 9434 outs() << "\t mmst_rsrv "; 9435 for (f = 0; f < 6; f++) 9436 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 9437 outs() << "\n"; 9438 } 9439 9440 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 9441 uint32_t f; 9442 outs() << "\t xmm_reg "; 9443 for (f = 0; f < 16; f++) 9444 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 9445 outs() << "\n"; 9446 } 9447 9448 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 9449 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 9450 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 9451 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 9452 outs() << " denorm " << fpu.fpu_fcw.denorm; 9453 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 9454 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 9455 outs() << " undfl " << fpu.fpu_fcw.undfl; 9456 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 9457 outs() << "\t\t pc "; 9458 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 9459 outs() << "FP_PREC_24B "; 9460 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 9461 outs() << "FP_PREC_53B "; 9462 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 9463 outs() << "FP_PREC_64B "; 9464 else 9465 outs() << fpu.fpu_fcw.pc << " "; 9466 outs() << "rc "; 9467 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 9468 outs() << "FP_RND_NEAR "; 9469 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 9470 outs() << "FP_RND_DOWN "; 9471 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 9472 outs() << "FP_RND_UP "; 9473 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 9474 outs() << "FP_CHOP "; 9475 outs() << "\n"; 9476 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 9477 outs() << " denorm " << fpu.fpu_fsw.denorm; 9478 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 9479 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 9480 outs() << " undfl " << fpu.fpu_fsw.undfl; 9481 outs() << " precis " << fpu.fpu_fsw.precis; 9482 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 9483 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9484 outs() << " c0 " << fpu.fpu_fsw.c0; 9485 outs() << " c1 " << fpu.fpu_fsw.c1; 9486 outs() << " c2 " << fpu.fpu_fsw.c2; 9487 outs() << " tos " << fpu.fpu_fsw.tos; 9488 outs() << " c3 " << fpu.fpu_fsw.c3; 9489 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9490 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9491 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9492 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9493 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9494 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9495 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9496 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9497 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9498 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9499 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9500 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9501 outs() << "\n"; 9502 outs() << "\t fpu_stmm0:\n"; 9503 Print_mmst_reg(fpu.fpu_stmm0); 9504 outs() << "\t fpu_stmm1:\n"; 9505 Print_mmst_reg(fpu.fpu_stmm1); 9506 outs() << "\t fpu_stmm2:\n"; 9507 Print_mmst_reg(fpu.fpu_stmm2); 9508 outs() << "\t fpu_stmm3:\n"; 9509 Print_mmst_reg(fpu.fpu_stmm3); 9510 outs() << "\t fpu_stmm4:\n"; 9511 Print_mmst_reg(fpu.fpu_stmm4); 9512 outs() << "\t fpu_stmm5:\n"; 9513 Print_mmst_reg(fpu.fpu_stmm5); 9514 outs() << "\t fpu_stmm6:\n"; 9515 Print_mmst_reg(fpu.fpu_stmm6); 9516 outs() << "\t fpu_stmm7:\n"; 9517 Print_mmst_reg(fpu.fpu_stmm7); 9518 outs() << "\t fpu_xmm0:\n"; 9519 Print_xmm_reg(fpu.fpu_xmm0); 9520 outs() << "\t fpu_xmm1:\n"; 9521 Print_xmm_reg(fpu.fpu_xmm1); 9522 outs() << "\t fpu_xmm2:\n"; 9523 Print_xmm_reg(fpu.fpu_xmm2); 9524 outs() << "\t fpu_xmm3:\n"; 9525 Print_xmm_reg(fpu.fpu_xmm3); 9526 outs() << "\t fpu_xmm4:\n"; 9527 Print_xmm_reg(fpu.fpu_xmm4); 9528 outs() << "\t fpu_xmm5:\n"; 9529 Print_xmm_reg(fpu.fpu_xmm5); 9530 outs() << "\t fpu_xmm6:\n"; 9531 Print_xmm_reg(fpu.fpu_xmm6); 9532 outs() << "\t fpu_xmm7:\n"; 9533 Print_xmm_reg(fpu.fpu_xmm7); 9534 outs() << "\t fpu_xmm8:\n"; 9535 Print_xmm_reg(fpu.fpu_xmm8); 9536 outs() << "\t fpu_xmm9:\n"; 9537 Print_xmm_reg(fpu.fpu_xmm9); 9538 outs() << "\t fpu_xmm10:\n"; 9539 Print_xmm_reg(fpu.fpu_xmm10); 9540 outs() << "\t fpu_xmm11:\n"; 9541 Print_xmm_reg(fpu.fpu_xmm11); 9542 outs() << "\t fpu_xmm12:\n"; 9543 Print_xmm_reg(fpu.fpu_xmm12); 9544 outs() << "\t fpu_xmm13:\n"; 9545 Print_xmm_reg(fpu.fpu_xmm13); 9546 outs() << "\t fpu_xmm14:\n"; 9547 Print_xmm_reg(fpu.fpu_xmm14); 9548 outs() << "\t fpu_xmm15:\n"; 9549 Print_xmm_reg(fpu.fpu_xmm15); 9550 outs() << "\t fpu_rsrv4:\n"; 9551 for (uint32_t f = 0; f < 6; f++) { 9552 outs() << "\t "; 9553 for (uint32_t g = 0; g < 16; g++) 9554 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9555 outs() << "\n"; 9556 } 9557 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9558 outs() << "\n"; 9559 } 9560 9561 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9562 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9563 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9564 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9565 } 9566 9567 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9568 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9569 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9570 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9571 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9572 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9573 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9574 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9575 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9576 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9577 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9578 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9579 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9580 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9581 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9582 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9583 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9584 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9585 } 9586 9587 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9588 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9589 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9590 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9591 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9592 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9593 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9594 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9595 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9596 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9597 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9598 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9599 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9600 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9601 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9602 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9603 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9604 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9605 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9606 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9607 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9608 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9609 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9610 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9611 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9612 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9613 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9614 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9615 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9616 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9617 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9618 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9619 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9620 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9621 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9622 } 9623 9624 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9625 bool isLittleEndian, uint32_t cputype) { 9626 if (t.cmd == MachO::LC_THREAD) 9627 outs() << " cmd LC_THREAD\n"; 9628 else if (t.cmd == MachO::LC_UNIXTHREAD) 9629 outs() << " cmd LC_UNIXTHREAD\n"; 9630 else 9631 outs() << " cmd " << t.cmd << " (unknown)\n"; 9632 outs() << " cmdsize " << t.cmdsize; 9633 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9634 outs() << " Incorrect size\n"; 9635 else 9636 outs() << "\n"; 9637 9638 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9639 const char *end = Ptr + t.cmdsize; 9640 uint32_t flavor, count, left; 9641 if (cputype == MachO::CPU_TYPE_I386) { 9642 while (begin < end) { 9643 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9644 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9645 begin += sizeof(uint32_t); 9646 } else { 9647 flavor = 0; 9648 begin = end; 9649 } 9650 if (isLittleEndian != sys::IsLittleEndianHost) 9651 sys::swapByteOrder(flavor); 9652 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9653 memcpy((char *)&count, begin, sizeof(uint32_t)); 9654 begin += sizeof(uint32_t); 9655 } else { 9656 count = 0; 9657 begin = end; 9658 } 9659 if (isLittleEndian != sys::IsLittleEndianHost) 9660 sys::swapByteOrder(count); 9661 if (flavor == MachO::x86_THREAD_STATE32) { 9662 outs() << " flavor i386_THREAD_STATE\n"; 9663 if (count == MachO::x86_THREAD_STATE32_COUNT) 9664 outs() << " count i386_THREAD_STATE_COUNT\n"; 9665 else 9666 outs() << " count " << count 9667 << " (not x86_THREAD_STATE32_COUNT)\n"; 9668 MachO::x86_thread_state32_t cpu32; 9669 left = end - begin; 9670 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9671 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9672 begin += sizeof(MachO::x86_thread_state32_t); 9673 } else { 9674 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9675 memcpy(&cpu32, begin, left); 9676 begin += left; 9677 } 9678 if (isLittleEndian != sys::IsLittleEndianHost) 9679 swapStruct(cpu32); 9680 Print_x86_thread_state32_t(cpu32); 9681 } else if (flavor == MachO::x86_THREAD_STATE) { 9682 outs() << " flavor x86_THREAD_STATE\n"; 9683 if (count == MachO::x86_THREAD_STATE_COUNT) 9684 outs() << " count x86_THREAD_STATE_COUNT\n"; 9685 else 9686 outs() << " count " << count 9687 << " (not x86_THREAD_STATE_COUNT)\n"; 9688 struct MachO::x86_thread_state_t ts; 9689 left = end - begin; 9690 if (left >= sizeof(MachO::x86_thread_state_t)) { 9691 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9692 begin += sizeof(MachO::x86_thread_state_t); 9693 } else { 9694 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9695 memcpy(&ts, begin, left); 9696 begin += left; 9697 } 9698 if (isLittleEndian != sys::IsLittleEndianHost) 9699 swapStruct(ts); 9700 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9701 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9702 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9703 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9704 else 9705 outs() << "tsh.count " << ts.tsh.count 9706 << " (not x86_THREAD_STATE32_COUNT\n"; 9707 Print_x86_thread_state32_t(ts.uts.ts32); 9708 } else { 9709 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9710 << ts.tsh.count << "\n"; 9711 } 9712 } else { 9713 outs() << " flavor " << flavor << " (unknown)\n"; 9714 outs() << " count " << count << "\n"; 9715 outs() << " state (unknown)\n"; 9716 begin += count * sizeof(uint32_t); 9717 } 9718 } 9719 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9720 while (begin < end) { 9721 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9722 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9723 begin += sizeof(uint32_t); 9724 } else { 9725 flavor = 0; 9726 begin = end; 9727 } 9728 if (isLittleEndian != sys::IsLittleEndianHost) 9729 sys::swapByteOrder(flavor); 9730 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9731 memcpy((char *)&count, begin, sizeof(uint32_t)); 9732 begin += sizeof(uint32_t); 9733 } else { 9734 count = 0; 9735 begin = end; 9736 } 9737 if (isLittleEndian != sys::IsLittleEndianHost) 9738 sys::swapByteOrder(count); 9739 if (flavor == MachO::x86_THREAD_STATE64) { 9740 outs() << " flavor x86_THREAD_STATE64\n"; 9741 if (count == MachO::x86_THREAD_STATE64_COUNT) 9742 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9743 else 9744 outs() << " count " << count 9745 << " (not x86_THREAD_STATE64_COUNT)\n"; 9746 MachO::x86_thread_state64_t cpu64; 9747 left = end - begin; 9748 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9749 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9750 begin += sizeof(MachO::x86_thread_state64_t); 9751 } else { 9752 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9753 memcpy(&cpu64, begin, left); 9754 begin += left; 9755 } 9756 if (isLittleEndian != sys::IsLittleEndianHost) 9757 swapStruct(cpu64); 9758 Print_x86_thread_state64_t(cpu64); 9759 } else if (flavor == MachO::x86_THREAD_STATE) { 9760 outs() << " flavor x86_THREAD_STATE\n"; 9761 if (count == MachO::x86_THREAD_STATE_COUNT) 9762 outs() << " count x86_THREAD_STATE_COUNT\n"; 9763 else 9764 outs() << " count " << count 9765 << " (not x86_THREAD_STATE_COUNT)\n"; 9766 struct MachO::x86_thread_state_t ts; 9767 left = end - begin; 9768 if (left >= sizeof(MachO::x86_thread_state_t)) { 9769 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9770 begin += sizeof(MachO::x86_thread_state_t); 9771 } else { 9772 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9773 memcpy(&ts, begin, left); 9774 begin += left; 9775 } 9776 if (isLittleEndian != sys::IsLittleEndianHost) 9777 swapStruct(ts); 9778 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9779 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9780 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9781 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9782 else 9783 outs() << "tsh.count " << ts.tsh.count 9784 << " (not x86_THREAD_STATE64_COUNT\n"; 9785 Print_x86_thread_state64_t(ts.uts.ts64); 9786 } else { 9787 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9788 << ts.tsh.count << "\n"; 9789 } 9790 } else if (flavor == MachO::x86_FLOAT_STATE) { 9791 outs() << " flavor x86_FLOAT_STATE\n"; 9792 if (count == MachO::x86_FLOAT_STATE_COUNT) 9793 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9794 else 9795 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9796 struct MachO::x86_float_state_t fs; 9797 left = end - begin; 9798 if (left >= sizeof(MachO::x86_float_state_t)) { 9799 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9800 begin += sizeof(MachO::x86_float_state_t); 9801 } else { 9802 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9803 memcpy(&fs, begin, left); 9804 begin += left; 9805 } 9806 if (isLittleEndian != sys::IsLittleEndianHost) 9807 swapStruct(fs); 9808 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9809 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9810 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9811 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9812 else 9813 outs() << "fsh.count " << fs.fsh.count 9814 << " (not x86_FLOAT_STATE64_COUNT\n"; 9815 Print_x86_float_state_t(fs.ufs.fs64); 9816 } else { 9817 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9818 << fs.fsh.count << "\n"; 9819 } 9820 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9821 outs() << " flavor x86_EXCEPTION_STATE\n"; 9822 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9823 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9824 else 9825 outs() << " count " << count 9826 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9827 struct MachO::x86_exception_state_t es; 9828 left = end - begin; 9829 if (left >= sizeof(MachO::x86_exception_state_t)) { 9830 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9831 begin += sizeof(MachO::x86_exception_state_t); 9832 } else { 9833 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9834 memcpy(&es, begin, left); 9835 begin += left; 9836 } 9837 if (isLittleEndian != sys::IsLittleEndianHost) 9838 swapStruct(es); 9839 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9840 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9841 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9842 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9843 else 9844 outs() << "\t esh.count " << es.esh.count 9845 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9846 Print_x86_exception_state_t(es.ues.es64); 9847 } else { 9848 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9849 << es.esh.count << "\n"; 9850 } 9851 } else if (flavor == MachO::x86_EXCEPTION_STATE64) { 9852 outs() << " flavor x86_EXCEPTION_STATE64\n"; 9853 if (count == MachO::x86_EXCEPTION_STATE64_COUNT) 9854 outs() << " count x86_EXCEPTION_STATE64_COUNT\n"; 9855 else 9856 outs() << " count " << count 9857 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; 9858 struct MachO::x86_exception_state64_t es64; 9859 left = end - begin; 9860 if (left >= sizeof(MachO::x86_exception_state64_t)) { 9861 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); 9862 begin += sizeof(MachO::x86_exception_state64_t); 9863 } else { 9864 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); 9865 memcpy(&es64, begin, left); 9866 begin += left; 9867 } 9868 if (isLittleEndian != sys::IsLittleEndianHost) 9869 swapStruct(es64); 9870 Print_x86_exception_state_t(es64); 9871 } else { 9872 outs() << " flavor " << flavor << " (unknown)\n"; 9873 outs() << " count " << count << "\n"; 9874 outs() << " state (unknown)\n"; 9875 begin += count * sizeof(uint32_t); 9876 } 9877 } 9878 } else if (cputype == MachO::CPU_TYPE_ARM) { 9879 while (begin < end) { 9880 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9881 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9882 begin += sizeof(uint32_t); 9883 } else { 9884 flavor = 0; 9885 begin = end; 9886 } 9887 if (isLittleEndian != sys::IsLittleEndianHost) 9888 sys::swapByteOrder(flavor); 9889 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9890 memcpy((char *)&count, begin, sizeof(uint32_t)); 9891 begin += sizeof(uint32_t); 9892 } else { 9893 count = 0; 9894 begin = end; 9895 } 9896 if (isLittleEndian != sys::IsLittleEndianHost) 9897 sys::swapByteOrder(count); 9898 if (flavor == MachO::ARM_THREAD_STATE) { 9899 outs() << " flavor ARM_THREAD_STATE\n"; 9900 if (count == MachO::ARM_THREAD_STATE_COUNT) 9901 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9902 else 9903 outs() << " count " << count 9904 << " (not ARM_THREAD_STATE_COUNT)\n"; 9905 MachO::arm_thread_state32_t cpu32; 9906 left = end - begin; 9907 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9908 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9909 begin += sizeof(MachO::arm_thread_state32_t); 9910 } else { 9911 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9912 memcpy(&cpu32, begin, left); 9913 begin += left; 9914 } 9915 if (isLittleEndian != sys::IsLittleEndianHost) 9916 swapStruct(cpu32); 9917 Print_arm_thread_state32_t(cpu32); 9918 } else { 9919 outs() << " flavor " << flavor << " (unknown)\n"; 9920 outs() << " count " << count << "\n"; 9921 outs() << " state (unknown)\n"; 9922 begin += count * sizeof(uint32_t); 9923 } 9924 } 9925 } else if (cputype == MachO::CPU_TYPE_ARM64 || 9926 cputype == MachO::CPU_TYPE_ARM64_32) { 9927 while (begin < end) { 9928 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9929 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9930 begin += sizeof(uint32_t); 9931 } else { 9932 flavor = 0; 9933 begin = end; 9934 } 9935 if (isLittleEndian != sys::IsLittleEndianHost) 9936 sys::swapByteOrder(flavor); 9937 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9938 memcpy((char *)&count, begin, sizeof(uint32_t)); 9939 begin += sizeof(uint32_t); 9940 } else { 9941 count = 0; 9942 begin = end; 9943 } 9944 if (isLittleEndian != sys::IsLittleEndianHost) 9945 sys::swapByteOrder(count); 9946 if (flavor == MachO::ARM_THREAD_STATE64) { 9947 outs() << " flavor ARM_THREAD_STATE64\n"; 9948 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9949 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9950 else 9951 outs() << " count " << count 9952 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9953 MachO::arm_thread_state64_t cpu64; 9954 left = end - begin; 9955 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9956 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9957 begin += sizeof(MachO::arm_thread_state64_t); 9958 } else { 9959 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9960 memcpy(&cpu64, begin, left); 9961 begin += left; 9962 } 9963 if (isLittleEndian != sys::IsLittleEndianHost) 9964 swapStruct(cpu64); 9965 Print_arm_thread_state64_t(cpu64); 9966 } else { 9967 outs() << " flavor " << flavor << " (unknown)\n"; 9968 outs() << " count " << count << "\n"; 9969 outs() << " state (unknown)\n"; 9970 begin += count * sizeof(uint32_t); 9971 } 9972 } 9973 } else { 9974 while (begin < end) { 9975 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9976 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9977 begin += sizeof(uint32_t); 9978 } else { 9979 flavor = 0; 9980 begin = end; 9981 } 9982 if (isLittleEndian != sys::IsLittleEndianHost) 9983 sys::swapByteOrder(flavor); 9984 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9985 memcpy((char *)&count, begin, sizeof(uint32_t)); 9986 begin += sizeof(uint32_t); 9987 } else { 9988 count = 0; 9989 begin = end; 9990 } 9991 if (isLittleEndian != sys::IsLittleEndianHost) 9992 sys::swapByteOrder(count); 9993 outs() << " flavor " << flavor << "\n"; 9994 outs() << " count " << count << "\n"; 9995 outs() << " state (Unknown cputype/cpusubtype)\n"; 9996 begin += count * sizeof(uint32_t); 9997 } 9998 } 9999 } 10000 10001 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 10002 if (dl.cmd == MachO::LC_ID_DYLIB) 10003 outs() << " cmd LC_ID_DYLIB\n"; 10004 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 10005 outs() << " cmd LC_LOAD_DYLIB\n"; 10006 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 10007 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 10008 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 10009 outs() << " cmd LC_REEXPORT_DYLIB\n"; 10010 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 10011 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 10012 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 10013 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 10014 else 10015 outs() << " cmd " << dl.cmd << " (unknown)\n"; 10016 outs() << " cmdsize " << dl.cmdsize; 10017 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 10018 outs() << " Incorrect size\n"; 10019 else 10020 outs() << "\n"; 10021 if (dl.dylib.name < dl.cmdsize) { 10022 const char *P = (const char *)(Ptr) + dl.dylib.name; 10023 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 10024 } else { 10025 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 10026 } 10027 outs() << " time stamp " << dl.dylib.timestamp << " "; 10028 time_t t = dl.dylib.timestamp; 10029 outs() << ctime(&t); 10030 outs() << " current version "; 10031 if (dl.dylib.current_version == 0xffffffff) 10032 outs() << "n/a\n"; 10033 else 10034 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 10035 << ((dl.dylib.current_version >> 8) & 0xff) << "." 10036 << (dl.dylib.current_version & 0xff) << "\n"; 10037 outs() << "compatibility version "; 10038 if (dl.dylib.compatibility_version == 0xffffffff) 10039 outs() << "n/a\n"; 10040 else 10041 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 10042 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 10043 << (dl.dylib.compatibility_version & 0xff) << "\n"; 10044 } 10045 10046 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 10047 uint32_t object_size) { 10048 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 10049 outs() << " cmd LC_CODE_SIGNATURE\n"; 10050 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 10051 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 10052 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 10053 outs() << " cmd LC_FUNCTION_STARTS\n"; 10054 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 10055 outs() << " cmd LC_DATA_IN_CODE\n"; 10056 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 10057 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 10058 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 10059 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 10060 else if (ld.cmd == MachO::LC_DYLD_EXPORTS_TRIE) 10061 outs() << " cmd LC_DYLD_EXPORTS_TRIE\n"; 10062 else if (ld.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) 10063 outs() << " cmd LC_DYLD_CHAINED_FIXUPS\n"; 10064 else 10065 outs() << " cmd " << ld.cmd << " (?)\n"; 10066 outs() << " cmdsize " << ld.cmdsize; 10067 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 10068 outs() << " Incorrect size\n"; 10069 else 10070 outs() << "\n"; 10071 outs() << " dataoff " << ld.dataoff; 10072 if (ld.dataoff > object_size) 10073 outs() << " (past end of file)\n"; 10074 else 10075 outs() << "\n"; 10076 outs() << " datasize " << ld.datasize; 10077 uint64_t big_size = ld.dataoff; 10078 big_size += ld.datasize; 10079 if (big_size > object_size) 10080 outs() << " (past end of file)\n"; 10081 else 10082 outs() << "\n"; 10083 } 10084 10085 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 10086 uint32_t cputype, bool verbose) { 10087 StringRef Buf = Obj->getData(); 10088 unsigned Index = 0; 10089 for (const auto &Command : Obj->load_commands()) { 10090 outs() << "Load command " << Index++ << "\n"; 10091 if (Command.C.cmd == MachO::LC_SEGMENT) { 10092 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 10093 const char *sg_segname = SLC.segname; 10094 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 10095 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 10096 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 10097 verbose); 10098 for (unsigned j = 0; j < SLC.nsects; j++) { 10099 MachO::section S = Obj->getSection(Command, j); 10100 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 10101 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 10102 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 10103 } 10104 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10105 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 10106 const char *sg_segname = SLC_64.segname; 10107 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 10108 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 10109 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 10110 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 10111 for (unsigned j = 0; j < SLC_64.nsects; j++) { 10112 MachO::section_64 S_64 = Obj->getSection64(Command, j); 10113 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 10114 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 10115 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 10116 sg_segname, filetype, Buf.size(), verbose); 10117 } 10118 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 10119 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10120 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 10121 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 10122 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 10123 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10124 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 10125 Obj->is64Bit()); 10126 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 10127 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 10128 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 10129 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 10130 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 10131 Command.C.cmd == MachO::LC_ID_DYLINKER || 10132 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 10133 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 10134 PrintDyldLoadCommand(Dyld, Command.Ptr); 10135 } else if (Command.C.cmd == MachO::LC_UUID) { 10136 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 10137 PrintUuidLoadCommand(Uuid); 10138 } else if (Command.C.cmd == MachO::LC_RPATH) { 10139 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 10140 PrintRpathLoadCommand(Rpath, Command.Ptr); 10141 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 10142 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 10143 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 10144 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 10145 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 10146 PrintVersionMinLoadCommand(Vd); 10147 } else if (Command.C.cmd == MachO::LC_NOTE) { 10148 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 10149 PrintNoteLoadCommand(Nt); 10150 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 10151 MachO::build_version_command Bv = 10152 Obj->getBuildVersionLoadCommand(Command); 10153 PrintBuildVersionLoadCommand(Obj, Bv); 10154 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 10155 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 10156 PrintSourceVersionCommand(Sd); 10157 } else if (Command.C.cmd == MachO::LC_MAIN) { 10158 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 10159 PrintEntryPointCommand(Ep); 10160 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 10161 MachO::encryption_info_command Ei = 10162 Obj->getEncryptionInfoCommand(Command); 10163 PrintEncryptionInfoCommand(Ei, Buf.size()); 10164 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 10165 MachO::encryption_info_command_64 Ei = 10166 Obj->getEncryptionInfoCommand64(Command); 10167 PrintEncryptionInfoCommand64(Ei, Buf.size()); 10168 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 10169 MachO::linker_option_command Lo = 10170 Obj->getLinkerOptionLoadCommand(Command); 10171 PrintLinkerOptionCommand(Lo, Command.Ptr); 10172 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 10173 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 10174 PrintSubFrameworkCommand(Sf, Command.Ptr); 10175 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 10176 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 10177 PrintSubUmbrellaCommand(Sf, Command.Ptr); 10178 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 10179 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 10180 PrintSubLibraryCommand(Sl, Command.Ptr); 10181 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 10182 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 10183 PrintSubClientCommand(Sc, Command.Ptr); 10184 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 10185 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 10186 PrintRoutinesCommand(Rc); 10187 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 10188 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 10189 PrintRoutinesCommand64(Rc); 10190 } else if (Command.C.cmd == MachO::LC_THREAD || 10191 Command.C.cmd == MachO::LC_UNIXTHREAD) { 10192 MachO::thread_command Tc = Obj->getThreadCommand(Command); 10193 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 10194 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 10195 Command.C.cmd == MachO::LC_ID_DYLIB || 10196 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 10197 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 10198 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 10199 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 10200 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 10201 PrintDylibCommand(Dl, Command.Ptr); 10202 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 10203 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 10204 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 10205 Command.C.cmd == MachO::LC_DATA_IN_CODE || 10206 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 10207 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT || 10208 Command.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE || 10209 Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) { 10210 MachO::linkedit_data_command Ld = 10211 Obj->getLinkeditDataLoadCommand(Command); 10212 PrintLinkEditDataCommand(Ld, Buf.size()); 10213 } else { 10214 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 10215 << ")\n"; 10216 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 10217 // TODO: get and print the raw bytes of the load command. 10218 } 10219 // TODO: print all the other kinds of load commands. 10220 } 10221 } 10222 10223 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 10224 if (Obj->is64Bit()) { 10225 MachO::mach_header_64 H_64; 10226 H_64 = Obj->getHeader64(); 10227 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 10228 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 10229 } else { 10230 MachO::mach_header H; 10231 H = Obj->getHeader(); 10232 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 10233 H.sizeofcmds, H.flags, verbose); 10234 } 10235 } 10236 10237 void objdump::printMachOFileHeader(const object::ObjectFile *Obj) { 10238 const MachOObjectFile *file = cast<const MachOObjectFile>(Obj); 10239 PrintMachHeader(file, Verbose); 10240 } 10241 10242 void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) { 10243 const MachOObjectFile *file = cast<const MachOObjectFile>(Obj); 10244 uint32_t filetype = 0; 10245 uint32_t cputype = 0; 10246 if (file->is64Bit()) { 10247 MachO::mach_header_64 H_64; 10248 H_64 = file->getHeader64(); 10249 filetype = H_64.filetype; 10250 cputype = H_64.cputype; 10251 } else { 10252 MachO::mach_header H; 10253 H = file->getHeader(); 10254 filetype = H.filetype; 10255 cputype = H.cputype; 10256 } 10257 PrintLoadCommands(file, filetype, cputype, Verbose); 10258 } 10259 10260 //===----------------------------------------------------------------------===// 10261 // export trie dumping 10262 //===----------------------------------------------------------------------===// 10263 10264 static void printMachOExportsTrie(const object::MachOObjectFile *Obj) { 10265 uint64_t BaseSegmentAddress = 0; 10266 for (const auto &Command : Obj->load_commands()) { 10267 if (Command.C.cmd == MachO::LC_SEGMENT) { 10268 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 10269 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10270 BaseSegmentAddress = Seg.vmaddr; 10271 break; 10272 } 10273 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10274 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 10275 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10276 BaseSegmentAddress = Seg.vmaddr; 10277 break; 10278 } 10279 } 10280 } 10281 Error Err = Error::success(); 10282 for (const object::ExportEntry &Entry : Obj->exports(Err)) { 10283 uint64_t Flags = Entry.flags(); 10284 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 10285 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 10286 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10287 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 10288 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10289 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 10290 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 10291 if (ReExport) 10292 outs() << "[re-export] "; 10293 else 10294 outs() << format("0x%08llX ", 10295 Entry.address() + BaseSegmentAddress); 10296 outs() << Entry.name(); 10297 if (WeakDef || ThreadLocal || Resolver || Abs) { 10298 ListSeparator LS; 10299 outs() << " ["; 10300 if (WeakDef) 10301 outs() << LS << "weak_def"; 10302 if (ThreadLocal) 10303 outs() << LS << "per-thread"; 10304 if (Abs) 10305 outs() << LS << "absolute"; 10306 if (Resolver) 10307 outs() << LS << format("resolver=0x%08llX", Entry.other()); 10308 outs() << "]"; 10309 } 10310 if (ReExport) { 10311 StringRef DylibName = "unknown"; 10312 int Ordinal = Entry.other() - 1; 10313 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 10314 if (Entry.otherName().empty()) 10315 outs() << " (from " << DylibName << ")"; 10316 else 10317 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 10318 } 10319 outs() << "\n"; 10320 } 10321 if (Err) 10322 reportError(std::move(Err), Obj->getFileName()); 10323 } 10324 10325 //===----------------------------------------------------------------------===// 10326 // rebase table dumping 10327 //===----------------------------------------------------------------------===// 10328 10329 static void printMachORebaseTable(object::MachOObjectFile *Obj) { 10330 outs() << "segment section address type\n"; 10331 Error Err = Error::success(); 10332 for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 10333 StringRef SegmentName = Entry.segmentName(); 10334 StringRef SectionName = Entry.sectionName(); 10335 uint64_t Address = Entry.address(); 10336 10337 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 10338 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 10339 SegmentName.str().c_str(), SectionName.str().c_str(), 10340 Address, Entry.typeName().str().c_str()); 10341 } 10342 if (Err) 10343 reportError(std::move(Err), Obj->getFileName()); 10344 } 10345 10346 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 10347 StringRef DylibName; 10348 switch (Ordinal) { 10349 case MachO::BIND_SPECIAL_DYLIB_SELF: 10350 return "this-image"; 10351 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 10352 return "main-executable"; 10353 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 10354 return "flat-namespace"; 10355 default: 10356 if (Ordinal > 0) { 10357 std::error_code EC = 10358 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 10359 if (EC) 10360 return "<<bad library ordinal>>"; 10361 return DylibName; 10362 } 10363 } 10364 return "<<unknown special ordinal>>"; 10365 } 10366 10367 //===----------------------------------------------------------------------===// 10368 // bind table dumping 10369 //===----------------------------------------------------------------------===// 10370 10371 static void printMachOBindTable(object::MachOObjectFile *Obj) { 10372 // Build table of sections so names can used in final output. 10373 outs() << "segment section address type " 10374 "addend dylib symbol\n"; 10375 Error Err = Error::success(); 10376 for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 10377 StringRef SegmentName = Entry.segmentName(); 10378 StringRef SectionName = Entry.sectionName(); 10379 uint64_t Address = Entry.address(); 10380 10381 // Table lines look like: 10382 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 10383 StringRef Attr; 10384 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 10385 Attr = " (weak_import)"; 10386 outs() << left_justify(SegmentName, 8) << " " 10387 << left_justify(SectionName, 18) << " " 10388 << format_hex(Address, 10, true) << " " 10389 << left_justify(Entry.typeName(), 8) << " " 10390 << format_decimal(Entry.addend(), 8) << " " 10391 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10392 << Entry.symbolName() << Attr << "\n"; 10393 } 10394 if (Err) 10395 reportError(std::move(Err), Obj->getFileName()); 10396 } 10397 10398 //===----------------------------------------------------------------------===// 10399 // lazy bind table dumping 10400 //===----------------------------------------------------------------------===// 10401 10402 static void printMachOLazyBindTable(object::MachOObjectFile *Obj) { 10403 outs() << "segment section address " 10404 "dylib symbol\n"; 10405 Error Err = Error::success(); 10406 for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 10407 StringRef SegmentName = Entry.segmentName(); 10408 StringRef SectionName = Entry.sectionName(); 10409 uint64_t Address = Entry.address(); 10410 10411 // Table lines look like: 10412 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 10413 outs() << left_justify(SegmentName, 8) << " " 10414 << left_justify(SectionName, 18) << " " 10415 << format_hex(Address, 10, true) << " " 10416 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10417 << Entry.symbolName() << "\n"; 10418 } 10419 if (Err) 10420 reportError(std::move(Err), Obj->getFileName()); 10421 } 10422 10423 //===----------------------------------------------------------------------===// 10424 // weak bind table dumping 10425 //===----------------------------------------------------------------------===// 10426 10427 static void printMachOWeakBindTable(object::MachOObjectFile *Obj) { 10428 outs() << "segment section address " 10429 "type addend symbol\n"; 10430 Error Err = Error::success(); 10431 for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 10432 // Strong symbols don't have a location to update. 10433 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 10434 outs() << " strong " 10435 << Entry.symbolName() << "\n"; 10436 continue; 10437 } 10438 StringRef SegmentName = Entry.segmentName(); 10439 StringRef SectionName = Entry.sectionName(); 10440 uint64_t Address = Entry.address(); 10441 10442 // Table lines look like: 10443 // __DATA __data 0x00001000 pointer 0 _foo 10444 outs() << left_justify(SegmentName, 8) << " " 10445 << left_justify(SectionName, 18) << " " 10446 << format_hex(Address, 10, true) << " " 10447 << left_justify(Entry.typeName(), 8) << " " 10448 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 10449 << "\n"; 10450 } 10451 if (Err) 10452 reportError(std::move(Err), Obj->getFileName()); 10453 } 10454 10455 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 10456 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 10457 // information for that address. If the address is found its binding symbol 10458 // name is returned. If not nullptr is returned. 10459 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 10460 struct DisassembleInfo *info) { 10461 if (info->bindtable == nullptr) { 10462 info->bindtable = std::make_unique<SymbolAddressMap>(); 10463 Error Err = Error::success(); 10464 for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 10465 uint64_t Address = Entry.address(); 10466 StringRef name = Entry.symbolName(); 10467 if (!name.empty()) 10468 (*info->bindtable)[Address] = name; 10469 } 10470 if (Err) 10471 reportError(std::move(Err), info->O->getFileName()); 10472 } 10473 auto name = info->bindtable->lookup(ReferenceValue); 10474 return !name.empty() ? name.data() : nullptr; 10475 } 10476 10477 void objdump::printLazyBindTable(ObjectFile *o) { 10478 outs() << "\nLazy bind table:\n"; 10479 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10480 printMachOLazyBindTable(MachO); 10481 else 10482 WithColor::error() 10483 << "This operation is only currently supported " 10484 "for Mach-O executable files.\n"; 10485 } 10486 10487 void objdump::printWeakBindTable(ObjectFile *o) { 10488 outs() << "\nWeak bind table:\n"; 10489 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10490 printMachOWeakBindTable(MachO); 10491 else 10492 WithColor::error() 10493 << "This operation is only currently supported " 10494 "for Mach-O executable files.\n"; 10495 } 10496 10497 void objdump::printExportsTrie(const ObjectFile *o) { 10498 outs() << "\nExports trie:\n"; 10499 if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10500 printMachOExportsTrie(MachO); 10501 else 10502 WithColor::error() 10503 << "This operation is only currently supported " 10504 "for Mach-O executable files.\n"; 10505 } 10506 10507 void objdump::printRebaseTable(ObjectFile *o) { 10508 outs() << "\nRebase table:\n"; 10509 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10510 printMachORebaseTable(MachO); 10511 else 10512 WithColor::error() 10513 << "This operation is only currently supported " 10514 "for Mach-O executable files.\n"; 10515 } 10516 10517 void objdump::printBindTable(ObjectFile *o) { 10518 outs() << "\nBind table:\n"; 10519 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10520 printMachOBindTable(MachO); 10521 else 10522 WithColor::error() 10523 << "This operation is only currently supported " 10524 "for Mach-O executable files.\n"; 10525 } 10526