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/BinaryFormat/MachO.h" 21 #include "llvm/Config/config.h" 22 #include "llvm/DebugInfo/DIContext.h" 23 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 24 #include "llvm/Demangle/Demangle.h" 25 #include "llvm/MC/MCAsmInfo.h" 26 #include "llvm/MC/MCContext.h" 27 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 28 #include "llvm/MC/MCInst.h" 29 #include "llvm/MC/MCInstPrinter.h" 30 #include "llvm/MC/MCInstrDesc.h" 31 #include "llvm/MC/MCInstrInfo.h" 32 #include "llvm/MC/MCRegisterInfo.h" 33 #include "llvm/MC/MCSubtargetInfo.h" 34 #include "llvm/MC/MCTargetOptions.h" 35 #include "llvm/MC/TargetRegistry.h" 36 #include "llvm/Object/MachO.h" 37 #include "llvm/Object/MachOUniversal.h" 38 #include "llvm/Option/ArgList.h" 39 #include "llvm/Support/Casting.h" 40 #include "llvm/Support/Debug.h" 41 #include "llvm/Support/Endian.h" 42 #include "llvm/Support/Format.h" 43 #include "llvm/Support/FormattedStream.h" 44 #include "llvm/Support/GraphWriter.h" 45 #include "llvm/Support/LEB128.h" 46 #include "llvm/Support/MemoryBuffer.h" 47 #include "llvm/Support/TargetSelect.h" 48 #include "llvm/Support/ToolOutputFile.h" 49 #include "llvm/Support/WithColor.h" 50 #include "llvm/Support/raw_ostream.h" 51 #include "llvm/TargetParser/Triple.h" 52 #include <algorithm> 53 #include <cstring> 54 #include <system_error> 55 56 using namespace llvm; 57 using namespace llvm::object; 58 using namespace llvm::objdump; 59 60 bool objdump::FirstPrivateHeader; 61 bool objdump::ExportsTrie; 62 bool objdump::Rebase; 63 bool objdump::Rpaths; 64 bool objdump::Bind; 65 bool objdump::LazyBind; 66 bool objdump::WeakBind; 67 static bool UseDbg; 68 static std::string DSYMFile; 69 bool objdump::FullLeadingAddr; 70 bool objdump::LeadingHeaders; 71 bool objdump::UniversalHeaders; 72 static bool ArchiveMemberOffsets; 73 bool objdump::IndirectSymbols; 74 bool objdump::DataInCode; 75 FunctionStartsMode objdump::FunctionStartsType = 76 objdump::FunctionStartsMode::None; 77 bool objdump::LinkOptHints; 78 bool objdump::InfoPlist; 79 bool objdump::ChainedFixups; 80 bool objdump::DyldInfo; 81 bool objdump::DylibsUsed; 82 bool objdump::DylibId; 83 bool objdump::Verbose; 84 bool objdump::ObjcMetaData; 85 std::string objdump::DisSymName; 86 bool objdump::SymbolicOperands; 87 static std::vector<std::string> ArchFlags; 88 89 static bool ArchAll = false; 90 static std::string ThumbTripleName; 91 92 static StringRef ordinalName(const object::MachOObjectFile *, int); 93 94 void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) { 95 FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header); 96 ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie); 97 Rebase = InputArgs.hasArg(OBJDUMP_rebase); 98 Rpaths = InputArgs.hasArg(OBJDUMP_rpaths); 99 Bind = InputArgs.hasArg(OBJDUMP_bind); 100 LazyBind = InputArgs.hasArg(OBJDUMP_lazy_bind); 101 WeakBind = InputArgs.hasArg(OBJDUMP_weak_bind); 102 UseDbg = InputArgs.hasArg(OBJDUMP_g); 103 DSYMFile = InputArgs.getLastArgValue(OBJDUMP_dsym_EQ).str(); 104 FullLeadingAddr = InputArgs.hasArg(OBJDUMP_full_leading_addr); 105 LeadingHeaders = !InputArgs.hasArg(OBJDUMP_no_leading_headers); 106 UniversalHeaders = InputArgs.hasArg(OBJDUMP_universal_headers); 107 ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets); 108 IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols); 109 DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code); 110 if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_function_starts_EQ)) { 111 FunctionStartsType = StringSwitch<FunctionStartsMode>(A->getValue()) 112 .Case("addrs", FunctionStartsMode::Addrs) 113 .Case("names", FunctionStartsMode::Names) 114 .Case("both", FunctionStartsMode::Both) 115 .Default(FunctionStartsMode::None); 116 if (FunctionStartsType == FunctionStartsMode::None) 117 invalidArgValue(A); 118 } 119 LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints); 120 InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist); 121 ChainedFixups = InputArgs.hasArg(OBJDUMP_chained_fixups); 122 DyldInfo = InputArgs.hasArg(OBJDUMP_dyld_info); 123 DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used); 124 DylibId = InputArgs.hasArg(OBJDUMP_dylib_id); 125 Verbose = !InputArgs.hasArg(OBJDUMP_non_verbose); 126 ObjcMetaData = InputArgs.hasArg(OBJDUMP_objc_meta_data); 127 DisSymName = InputArgs.getLastArgValue(OBJDUMP_dis_symname).str(); 128 SymbolicOperands = !InputArgs.hasArg(OBJDUMP_no_symbolic_operands); 129 ArchFlags = InputArgs.getAllArgValues(OBJDUMP_arch_EQ); 130 } 131 132 static const Target *GetTarget(const MachOObjectFile *MachOObj, 133 const char **McpuDefault, 134 const Target **ThumbTarget) { 135 // Figure out the target triple. 136 Triple TT(TripleName); 137 if (TripleName.empty()) { 138 TT = MachOObj->getArchTriple(McpuDefault); 139 TripleName = TT.str(); 140 } 141 142 if (TT.getArch() == Triple::arm) { 143 // We've inferred a 32-bit ARM target from the object file. All MachO CPUs 144 // that support ARM are also capable of Thumb mode. 145 Triple ThumbTriple = TT; 146 std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str(); 147 ThumbTriple.setArchName(ThumbName); 148 ThumbTripleName = ThumbTriple.str(); 149 } 150 151 // Get the target specific parser. 152 std::string Error; 153 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 154 if (TheTarget && ThumbTripleName.empty()) 155 return TheTarget; 156 157 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 158 if (*ThumbTarget) 159 return TheTarget; 160 161 WithColor::error(errs(), "llvm-objdump") << "unable to get target for '"; 162 if (!TheTarget) 163 errs() << TripleName; 164 else 165 errs() << ThumbTripleName; 166 errs() << "', see --version and --triple.\n"; 167 return nullptr; 168 } 169 170 namespace { 171 struct SymbolSorter { 172 bool operator()(const SymbolRef &A, const SymbolRef &B) { 173 Expected<SymbolRef::Type> ATypeOrErr = A.getType(); 174 if (!ATypeOrErr) 175 reportError(ATypeOrErr.takeError(), A.getObject()->getFileName()); 176 SymbolRef::Type AType = *ATypeOrErr; 177 Expected<SymbolRef::Type> BTypeOrErr = B.getType(); 178 if (!BTypeOrErr) 179 reportError(BTypeOrErr.takeError(), B.getObject()->getFileName()); 180 SymbolRef::Type BType = *BTypeOrErr; 181 uint64_t AAddr = 182 (AType != SymbolRef::ST_Function) ? 0 : cantFail(A.getValue()); 183 uint64_t BAddr = 184 (BType != SymbolRef::ST_Function) ? 0 : cantFail(B.getValue()); 185 return AAddr < BAddr; 186 } 187 }; 188 189 class MachODumper : public Dumper { 190 const object::MachOObjectFile &Obj; 191 192 public: 193 MachODumper(const object::MachOObjectFile &O) : Dumper(O), Obj(O) {} 194 void printPrivateHeaders() override; 195 }; 196 } // namespace 197 198 std::unique_ptr<Dumper> 199 objdump::createMachODumper(const object::MachOObjectFile &Obj) { 200 return std::make_unique<MachODumper>(Obj); 201 } 202 203 // Types for the storted data in code table that is built before disassembly 204 // and the predicate function to sort them. 205 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 206 typedef std::vector<DiceTableEntry> DiceTable; 207 typedef DiceTable::iterator dice_table_iterator; 208 209 // This is used to search for a data in code table entry for the PC being 210 // disassembled. The j parameter has the PC in j.first. A single data in code 211 // table entry can cover many bytes for each of its Kind's. So if the offset, 212 // aka the i.first value, of the data in code table entry plus its Length 213 // covers the PC being searched for this will return true. If not it will 214 // return false. 215 static bool compareDiceTableEntries(const DiceTableEntry &i, 216 const DiceTableEntry &j) { 217 uint16_t Length; 218 i.second.getLength(Length); 219 220 return j.first >= i.first && j.first < i.first + Length; 221 } 222 223 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 224 unsigned short Kind) { 225 uint32_t Value, Size = 1; 226 227 switch (Kind) { 228 default: 229 case MachO::DICE_KIND_DATA: 230 if (Length >= 4) { 231 if (ShowRawInsn) 232 dumpBytes(ArrayRef(bytes, 4), outs()); 233 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 234 outs() << "\t.long " << Value; 235 Size = 4; 236 } else if (Length >= 2) { 237 if (ShowRawInsn) 238 dumpBytes(ArrayRef(bytes, 2), outs()); 239 Value = bytes[1] << 8 | bytes[0]; 240 outs() << "\t.short " << Value; 241 Size = 2; 242 } else { 243 if (ShowRawInsn) 244 dumpBytes(ArrayRef(bytes, 2), outs()); 245 Value = bytes[0]; 246 outs() << "\t.byte " << Value; 247 Size = 1; 248 } 249 if (Kind == MachO::DICE_KIND_DATA) 250 outs() << "\t@ KIND_DATA\n"; 251 else 252 outs() << "\t@ data in code kind = " << Kind << "\n"; 253 break; 254 case MachO::DICE_KIND_JUMP_TABLE8: 255 if (ShowRawInsn) 256 dumpBytes(ArrayRef(bytes, 1), outs()); 257 Value = bytes[0]; 258 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 259 Size = 1; 260 break; 261 case MachO::DICE_KIND_JUMP_TABLE16: 262 if (ShowRawInsn) 263 dumpBytes(ArrayRef(bytes, 2), outs()); 264 Value = bytes[1] << 8 | bytes[0]; 265 outs() << "\t.short " << format("%5u", Value & 0xffff) 266 << "\t@ KIND_JUMP_TABLE16\n"; 267 Size = 2; 268 break; 269 case MachO::DICE_KIND_JUMP_TABLE32: 270 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 271 if (ShowRawInsn) 272 dumpBytes(ArrayRef(bytes, 4), outs()); 273 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 274 outs() << "\t.long " << Value; 275 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 276 outs() << "\t@ KIND_JUMP_TABLE32\n"; 277 else 278 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 279 Size = 4; 280 break; 281 } 282 return Size; 283 } 284 285 static void getSectionsAndSymbols(MachOObjectFile *MachOObj, 286 std::vector<SectionRef> &Sections, 287 std::vector<SymbolRef> &Symbols, 288 SmallVectorImpl<uint64_t> &FoundFns, 289 uint64_t &BaseSegmentAddress) { 290 const StringRef FileName = MachOObj->getFileName(); 291 for (const SymbolRef &Symbol : MachOObj->symbols()) { 292 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 293 if (!SymName.starts_with("ltmp")) 294 Symbols.push_back(Symbol); 295 } 296 297 append_range(Sections, MachOObj->sections()); 298 299 bool BaseSegmentAddressSet = false; 300 for (const auto &Command : MachOObj->load_commands()) { 301 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 302 // We found a function starts segment, parse the addresses for later 303 // consumption. 304 MachO::linkedit_data_command LLC = 305 MachOObj->getLinkeditDataLoadCommand(Command); 306 307 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 308 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 309 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 310 StringRef SegName = SLC.segname; 311 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 312 BaseSegmentAddressSet = true; 313 BaseSegmentAddress = SLC.vmaddr; 314 } 315 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 316 MachO::segment_command_64 SLC = MachOObj->getSegment64LoadCommand(Command); 317 StringRef SegName = SLC.segname; 318 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 319 BaseSegmentAddressSet = true; 320 BaseSegmentAddress = SLC.vmaddr; 321 } 322 } 323 } 324 } 325 326 static bool DumpAndSkipDataInCode(uint64_t PC, const uint8_t *bytes, 327 DiceTable &Dices, uint64_t &InstSize) { 328 // Check the data in code table here to see if this is data not an 329 // instruction to be disassembled. 330 DiceTable Dice; 331 Dice.push_back(std::make_pair(PC, DiceRef())); 332 dice_table_iterator DTI = 333 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 334 compareDiceTableEntries); 335 if (DTI != Dices.end()) { 336 uint16_t Length; 337 DTI->second.getLength(Length); 338 uint16_t Kind; 339 DTI->second.getKind(Kind); 340 InstSize = DumpDataInCode(bytes, Length, Kind); 341 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 342 (PC == (DTI->first + Length - 1)) && (Length & 1)) 343 InstSize++; 344 return true; 345 } 346 return false; 347 } 348 349 static void printRelocationTargetName(const MachOObjectFile *O, 350 const MachO::any_relocation_info &RE, 351 raw_string_ostream &Fmt) { 352 // Target of a scattered relocation is an address. In the interest of 353 // generating pretty output, scan through the symbol table looking for a 354 // symbol that aligns with that address. If we find one, print it. 355 // Otherwise, we just print the hex address of the target. 356 const StringRef FileName = O->getFileName(); 357 if (O->isRelocationScattered(RE)) { 358 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 359 360 for (const SymbolRef &Symbol : O->symbols()) { 361 uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName); 362 if (Addr != Val) 363 continue; 364 Fmt << unwrapOrError(Symbol.getName(), FileName); 365 return; 366 } 367 368 // If we couldn't find a symbol that this relocation refers to, try 369 // to find a section beginning instead. 370 for (const SectionRef &Section : ToolSectionFilter(*O)) { 371 uint64_t Addr = Section.getAddress(); 372 if (Addr != Val) 373 continue; 374 StringRef NameOrErr = unwrapOrError(Section.getName(), O->getFileName()); 375 Fmt << NameOrErr; 376 return; 377 } 378 379 Fmt << format("0x%x", Val); 380 return; 381 } 382 383 StringRef S; 384 bool isExtern = O->getPlainRelocationExternal(RE); 385 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 386 387 if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND && 388 (O->getArch() == Triple::aarch64 || O->getArch() == Triple::aarch64_be)) { 389 Fmt << format("0x%0" PRIx64, Val); 390 return; 391 } 392 393 if (isExtern) { 394 symbol_iterator SI = O->symbol_begin(); 395 std::advance(SI, Val); 396 S = unwrapOrError(SI->getName(), FileName); 397 } else { 398 section_iterator SI = O->section_begin(); 399 // Adjust for the fact that sections are 1-indexed. 400 if (Val == 0) { 401 Fmt << "0 (?,?)"; 402 return; 403 } 404 uint32_t I = Val - 1; 405 while (I != 0 && SI != O->section_end()) { 406 --I; 407 std::advance(SI, 1); 408 } 409 if (SI == O->section_end()) { 410 Fmt << Val << " (?,?)"; 411 } else { 412 if (Expected<StringRef> NameOrErr = SI->getName()) 413 S = *NameOrErr; 414 else 415 consumeError(NameOrErr.takeError()); 416 } 417 } 418 419 Fmt << S; 420 } 421 422 Error objdump::getMachORelocationValueString(const MachOObjectFile *Obj, 423 const RelocationRef &RelRef, 424 SmallVectorImpl<char> &Result) { 425 DataRefImpl Rel = RelRef.getRawDataRefImpl(); 426 MachO::any_relocation_info RE = Obj->getRelocation(Rel); 427 428 unsigned Arch = Obj->getArch(); 429 430 std::string FmtBuf; 431 raw_string_ostream Fmt(FmtBuf); 432 unsigned Type = Obj->getAnyRelocationType(RE); 433 bool IsPCRel = Obj->getAnyRelocationPCRel(RE); 434 435 // Determine any addends that should be displayed with the relocation. 436 // These require decoding the relocation type, which is triple-specific. 437 438 // X86_64 has entirely custom relocation types. 439 if (Arch == Triple::x86_64) { 440 switch (Type) { 441 case MachO::X86_64_RELOC_GOT_LOAD: 442 case MachO::X86_64_RELOC_GOT: { 443 printRelocationTargetName(Obj, RE, Fmt); 444 Fmt << "@GOT"; 445 if (IsPCRel) 446 Fmt << "PCREL"; 447 break; 448 } 449 case MachO::X86_64_RELOC_SUBTRACTOR: { 450 DataRefImpl RelNext = Rel; 451 Obj->moveRelocationNext(RelNext); 452 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 453 454 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 455 // X86_64_RELOC_UNSIGNED. 456 // NOTE: Scattered relocations don't exist on x86_64. 457 unsigned RType = Obj->getAnyRelocationType(RENext); 458 if (RType != MachO::X86_64_RELOC_UNSIGNED) 459 reportError(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after " 460 "X86_64_RELOC_SUBTRACTOR."); 461 462 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 463 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 464 printRelocationTargetName(Obj, RENext, Fmt); 465 Fmt << "-"; 466 printRelocationTargetName(Obj, RE, Fmt); 467 break; 468 } 469 case MachO::X86_64_RELOC_TLV: 470 printRelocationTargetName(Obj, RE, Fmt); 471 Fmt << "@TLV"; 472 if (IsPCRel) 473 Fmt << "P"; 474 break; 475 case MachO::X86_64_RELOC_SIGNED_1: 476 printRelocationTargetName(Obj, RE, Fmt); 477 Fmt << "-1"; 478 break; 479 case MachO::X86_64_RELOC_SIGNED_2: 480 printRelocationTargetName(Obj, RE, Fmt); 481 Fmt << "-2"; 482 break; 483 case MachO::X86_64_RELOC_SIGNED_4: 484 printRelocationTargetName(Obj, RE, Fmt); 485 Fmt << "-4"; 486 break; 487 default: 488 printRelocationTargetName(Obj, RE, Fmt); 489 break; 490 } 491 // X86 and ARM share some relocation types in common. 492 } else if (Arch == Triple::x86 || Arch == Triple::arm || 493 Arch == Triple::ppc) { 494 // Generic relocation types... 495 switch (Type) { 496 case MachO::GENERIC_RELOC_PAIR: // prints no info 497 return Error::success(); 498 case MachO::GENERIC_RELOC_SECTDIFF: { 499 DataRefImpl RelNext = Rel; 500 Obj->moveRelocationNext(RelNext); 501 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 502 503 // X86 sect diff's must be followed by a relocation of type 504 // GENERIC_RELOC_PAIR. 505 unsigned RType = Obj->getAnyRelocationType(RENext); 506 507 if (RType != MachO::GENERIC_RELOC_PAIR) 508 reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 509 "GENERIC_RELOC_SECTDIFF."); 510 511 printRelocationTargetName(Obj, RE, Fmt); 512 Fmt << "-"; 513 printRelocationTargetName(Obj, RENext, Fmt); 514 break; 515 } 516 } 517 518 if (Arch == Triple::x86 || Arch == Triple::ppc) { 519 switch (Type) { 520 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 521 DataRefImpl RelNext = Rel; 522 Obj->moveRelocationNext(RelNext); 523 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 524 525 // X86 sect diff's must be followed by a relocation of type 526 // GENERIC_RELOC_PAIR. 527 unsigned RType = Obj->getAnyRelocationType(RENext); 528 if (RType != MachO::GENERIC_RELOC_PAIR) 529 reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " 530 "GENERIC_RELOC_LOCAL_SECTDIFF."); 531 532 printRelocationTargetName(Obj, RE, Fmt); 533 Fmt << "-"; 534 printRelocationTargetName(Obj, RENext, Fmt); 535 break; 536 } 537 case MachO::GENERIC_RELOC_TLV: { 538 printRelocationTargetName(Obj, RE, Fmt); 539 Fmt << "@TLV"; 540 if (IsPCRel) 541 Fmt << "P"; 542 break; 543 } 544 default: 545 printRelocationTargetName(Obj, RE, Fmt); 546 } 547 } else { // ARM-specific relocations 548 switch (Type) { 549 case MachO::ARM_RELOC_HALF: 550 case MachO::ARM_RELOC_HALF_SECTDIFF: { 551 // Half relocations steal a bit from the length field to encode 552 // whether this is an upper16 or a lower16 relocation. 553 bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1; 554 555 if (isUpper) 556 Fmt << ":upper16:("; 557 else 558 Fmt << ":lower16:("; 559 printRelocationTargetName(Obj, RE, Fmt); 560 561 DataRefImpl RelNext = Rel; 562 Obj->moveRelocationNext(RelNext); 563 MachO::any_relocation_info RENext = Obj->getRelocation(RelNext); 564 565 // ARM half relocs must be followed by a relocation of type 566 // ARM_RELOC_PAIR. 567 unsigned RType = Obj->getAnyRelocationType(RENext); 568 if (RType != MachO::ARM_RELOC_PAIR) 569 reportError(Obj->getFileName(), "Expected ARM_RELOC_PAIR after " 570 "ARM_RELOC_HALF"); 571 572 // NOTE: The half of the target virtual address is stashed in the 573 // address field of the secondary relocation, but we can't reverse 574 // engineer the constant offset from it without decoding the movw/movt 575 // instruction to find the other half in its immediate field. 576 577 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 578 // symbol/section pointer of the follow-on relocation. 579 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 580 Fmt << "-"; 581 printRelocationTargetName(Obj, RENext, Fmt); 582 } 583 584 Fmt << ")"; 585 break; 586 } 587 default: { 588 printRelocationTargetName(Obj, RE, Fmt); 589 } 590 } 591 } 592 } else 593 printRelocationTargetName(Obj, RE, Fmt); 594 595 Fmt.flush(); 596 Result.append(FmtBuf.begin(), FmtBuf.end()); 597 return Error::success(); 598 } 599 600 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 601 uint32_t n, uint32_t count, 602 uint32_t stride, uint64_t addr) { 603 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 604 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 605 if (n > nindirectsyms) 606 outs() << " (entries start past the end of the indirect symbol " 607 "table) (reserved1 field greater than the table size)"; 608 else if (n + count > nindirectsyms) 609 outs() << " (entries extends past the end of the indirect symbol " 610 "table)"; 611 outs() << "\n"; 612 uint32_t cputype = O->getHeader().cputype; 613 if (cputype & MachO::CPU_ARCH_ABI64) 614 outs() << "address index"; 615 else 616 outs() << "address index"; 617 if (verbose) 618 outs() << " name\n"; 619 else 620 outs() << "\n"; 621 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 622 if (cputype & MachO::CPU_ARCH_ABI64) 623 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 624 else 625 outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " "; 626 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 627 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 628 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 629 outs() << "LOCAL\n"; 630 continue; 631 } 632 if (indirect_symbol == 633 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 634 outs() << "LOCAL ABSOLUTE\n"; 635 continue; 636 } 637 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 638 outs() << "ABSOLUTE\n"; 639 continue; 640 } 641 outs() << format("%5u ", indirect_symbol); 642 if (verbose) { 643 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 644 if (indirect_symbol < Symtab.nsyms) { 645 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 646 SymbolRef Symbol = *Sym; 647 outs() << unwrapOrError(Symbol.getName(), O->getFileName()); 648 } else { 649 outs() << "?"; 650 } 651 } 652 outs() << "\n"; 653 } 654 } 655 656 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 657 for (const auto &Load : O->load_commands()) { 658 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 659 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 660 for (unsigned J = 0; J < Seg.nsects; ++J) { 661 MachO::section_64 Sec = O->getSection64(Load, J); 662 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 663 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 664 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 665 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 666 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 667 section_type == MachO::S_SYMBOL_STUBS) { 668 uint32_t stride; 669 if (section_type == MachO::S_SYMBOL_STUBS) 670 stride = Sec.reserved2; 671 else 672 stride = 8; 673 if (stride == 0) { 674 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 675 << Sec.sectname << ") " 676 << "(size of stubs in reserved2 field is zero)\n"; 677 continue; 678 } 679 uint32_t count = Sec.size / stride; 680 outs() << "Indirect symbols for (" << Sec.segname << "," 681 << Sec.sectname << ") " << count << " entries"; 682 uint32_t n = Sec.reserved1; 683 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 684 } 685 } 686 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 687 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 688 for (unsigned J = 0; J < Seg.nsects; ++J) { 689 MachO::section Sec = O->getSection(Load, J); 690 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 691 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 692 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 693 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 694 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 695 section_type == MachO::S_SYMBOL_STUBS) { 696 uint32_t stride; 697 if (section_type == MachO::S_SYMBOL_STUBS) 698 stride = Sec.reserved2; 699 else 700 stride = 4; 701 if (stride == 0) { 702 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 703 << Sec.sectname << ") " 704 << "(size of stubs in reserved2 field is zero)\n"; 705 continue; 706 } 707 uint32_t count = Sec.size / stride; 708 outs() << "Indirect symbols for (" << Sec.segname << "," 709 << Sec.sectname << ") " << count << " entries"; 710 uint32_t n = Sec.reserved1; 711 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 712 } 713 } 714 } 715 } 716 } 717 718 static void PrintRType(const uint64_t cputype, const unsigned r_type) { 719 static char const *generic_r_types[] = { 720 "VANILLA ", "PAIR ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV ", 721 " 6 (?) ", " 7 (?) ", " 8 (?) ", " 9 (?) ", " 10 (?) ", " 11 (?) ", 722 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 723 }; 724 static char const *x86_64_r_types[] = { 725 "UNSIGND ", "SIGNED ", "BRANCH ", "GOT_LD ", "GOT ", "SUB ", 726 "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV ", " 10 (?) ", " 11 (?) ", 727 " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 728 }; 729 static char const *arm_r_types[] = { 730 "VANILLA ", "PAIR ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ", 731 "BR24 ", "T_BR22 ", "T_BR32 ", "HALF ", "HALFDIF ", 732 " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 733 }; 734 static char const *arm64_r_types[] = { 735 "UNSIGND ", "SUB ", "BR26 ", "PAGE21 ", "PAGOF12 ", 736 "GOTLDP ", "GOTLDPOF", "PTRTGOT ", "TLVLDP ", "TLVLDPOF", 737 "ADDEND ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) " 738 }; 739 740 if (r_type > 0xf){ 741 outs() << format("%-7u", r_type) << " "; 742 return; 743 } 744 switch (cputype) { 745 case MachO::CPU_TYPE_I386: 746 outs() << generic_r_types[r_type]; 747 break; 748 case MachO::CPU_TYPE_X86_64: 749 outs() << x86_64_r_types[r_type]; 750 break; 751 case MachO::CPU_TYPE_ARM: 752 outs() << arm_r_types[r_type]; 753 break; 754 case MachO::CPU_TYPE_ARM64: 755 case MachO::CPU_TYPE_ARM64_32: 756 outs() << arm64_r_types[r_type]; 757 break; 758 default: 759 outs() << format("%-7u ", r_type); 760 } 761 } 762 763 static void PrintRLength(const uint64_t cputype, const unsigned r_type, 764 const unsigned r_length, const bool previous_arm_half){ 765 if (cputype == MachO::CPU_TYPE_ARM && 766 (r_type == MachO::ARM_RELOC_HALF || 767 r_type == MachO::ARM_RELOC_HALF_SECTDIFF || previous_arm_half == true)) { 768 if ((r_length & 0x1) == 0) 769 outs() << "lo/"; 770 else 771 outs() << "hi/"; 772 if ((r_length & 0x1) == 0) 773 outs() << "arm "; 774 else 775 outs() << "thm "; 776 } else { 777 switch (r_length) { 778 case 0: 779 outs() << "byte "; 780 break; 781 case 1: 782 outs() << "word "; 783 break; 784 case 2: 785 outs() << "long "; 786 break; 787 case 3: 788 if (cputype == MachO::CPU_TYPE_X86_64) 789 outs() << "quad "; 790 else 791 outs() << format("?(%2d) ", r_length); 792 break; 793 default: 794 outs() << format("?(%2d) ", r_length); 795 } 796 } 797 } 798 799 static void PrintRelocationEntries(const MachOObjectFile *O, 800 const relocation_iterator Begin, 801 const relocation_iterator End, 802 const uint64_t cputype, 803 const bool verbose) { 804 const MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 805 bool previous_arm_half = false; 806 bool previous_sectdiff = false; 807 uint32_t sectdiff_r_type = 0; 808 809 for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) { 810 const DataRefImpl Rel = Reloc->getRawDataRefImpl(); 811 const MachO::any_relocation_info RE = O->getRelocation(Rel); 812 const unsigned r_type = O->getAnyRelocationType(RE); 813 const bool r_scattered = O->isRelocationScattered(RE); 814 const unsigned r_pcrel = O->getAnyRelocationPCRel(RE); 815 const unsigned r_length = O->getAnyRelocationLength(RE); 816 const unsigned r_address = O->getAnyRelocationAddress(RE); 817 const bool r_extern = (r_scattered ? false : 818 O->getPlainRelocationExternal(RE)); 819 const uint32_t r_value = (r_scattered ? 820 O->getScatteredRelocationValue(RE) : 0); 821 const unsigned r_symbolnum = (r_scattered ? 0 : 822 O->getPlainRelocationSymbolNum(RE)); 823 824 if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) { 825 if (verbose) { 826 // scattered: address 827 if ((cputype == MachO::CPU_TYPE_I386 && 828 r_type == MachO::GENERIC_RELOC_PAIR) || 829 (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)) 830 outs() << " "; 831 else 832 outs() << format("%08x ", (unsigned int)r_address); 833 834 // scattered: pcrel 835 if (r_pcrel) 836 outs() << "True "; 837 else 838 outs() << "False "; 839 840 // scattered: length 841 PrintRLength(cputype, r_type, r_length, previous_arm_half); 842 843 // scattered: extern & type 844 outs() << "n/a "; 845 PrintRType(cputype, r_type); 846 847 // scattered: scattered & value 848 outs() << format("True 0x%08x", (unsigned int)r_value); 849 if (previous_sectdiff == false) { 850 if ((cputype == MachO::CPU_TYPE_ARM && 851 r_type == MachO::ARM_RELOC_PAIR)) 852 outs() << format(" half = 0x%04x ", (unsigned int)r_address); 853 } else if (cputype == MachO::CPU_TYPE_ARM && 854 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF) 855 outs() << format(" other_half = 0x%04x ", (unsigned int)r_address); 856 if ((cputype == MachO::CPU_TYPE_I386 && 857 (r_type == MachO::GENERIC_RELOC_SECTDIFF || 858 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) || 859 (cputype == MachO::CPU_TYPE_ARM && 860 (sectdiff_r_type == MachO::ARM_RELOC_SECTDIFF || 861 sectdiff_r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 862 sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF))) { 863 previous_sectdiff = true; 864 sectdiff_r_type = r_type; 865 } else { 866 previous_sectdiff = false; 867 sectdiff_r_type = 0; 868 } 869 if (cputype == MachO::CPU_TYPE_ARM && 870 (r_type == MachO::ARM_RELOC_HALF || 871 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 872 previous_arm_half = true; 873 else 874 previous_arm_half = false; 875 outs() << "\n"; 876 } 877 else { 878 // scattered: address pcrel length extern type scattered value 879 outs() << format("%08x %1d %-2d n/a %-7d 1 0x%08x\n", 880 (unsigned int)r_address, r_pcrel, r_length, r_type, 881 (unsigned int)r_value); 882 } 883 } 884 else { 885 if (verbose) { 886 // plain: address 887 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 888 outs() << " "; 889 else 890 outs() << format("%08x ", (unsigned int)r_address); 891 892 // plain: pcrel 893 if (r_pcrel) 894 outs() << "True "; 895 else 896 outs() << "False "; 897 898 // plain: length 899 PrintRLength(cputype, r_type, r_length, previous_arm_half); 900 901 if (r_extern) { 902 // plain: extern & type & scattered 903 outs() << "True "; 904 PrintRType(cputype, r_type); 905 outs() << "False "; 906 907 // plain: symbolnum/value 908 if (r_symbolnum > Symtab.nsyms) 909 outs() << format("?(%d)\n", r_symbolnum); 910 else { 911 SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum); 912 Expected<StringRef> SymNameNext = Symbol.getName(); 913 const char *name = nullptr; 914 if (SymNameNext) 915 name = SymNameNext->data(); 916 if (name == nullptr) 917 outs() << format("?(%d)\n", r_symbolnum); 918 else 919 outs() << name << "\n"; 920 } 921 } 922 else { 923 // plain: extern & type & scattered 924 outs() << "False "; 925 PrintRType(cputype, r_type); 926 outs() << "False "; 927 928 // plain: symbolnum/value 929 if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR) 930 outs() << format("other_half = 0x%04x\n", (unsigned int)r_address); 931 else if ((cputype == MachO::CPU_TYPE_ARM64 || 932 cputype == MachO::CPU_TYPE_ARM64_32) && 933 r_type == MachO::ARM64_RELOC_ADDEND) 934 outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum); 935 else { 936 outs() << format("%d ", r_symbolnum); 937 if (r_symbolnum == MachO::R_ABS) 938 outs() << "R_ABS\n"; 939 else { 940 // in this case, r_symbolnum is actually a 1-based section number 941 uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a; 942 if (r_symbolnum > 0 && r_symbolnum <= nsects) { 943 object::DataRefImpl DRI; 944 DRI.d.a = r_symbolnum-1; 945 StringRef SegName = O->getSectionFinalSegmentName(DRI); 946 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 947 outs() << "(" << SegName << "," << *NameOrErr << ")\n"; 948 else 949 outs() << "(?,?)\n"; 950 } 951 else { 952 outs() << "(?,?)\n"; 953 } 954 } 955 } 956 } 957 if (cputype == MachO::CPU_TYPE_ARM && 958 (r_type == MachO::ARM_RELOC_HALF || 959 r_type == MachO::ARM_RELOC_HALF_SECTDIFF)) 960 previous_arm_half = true; 961 else 962 previous_arm_half = false; 963 } 964 else { 965 // plain: address pcrel length extern type scattered symbolnum/section 966 outs() << format("%08x %1d %-2d %1d %-7d 0 %d\n", 967 (unsigned int)r_address, r_pcrel, r_length, r_extern, 968 r_type, r_symbolnum); 969 } 970 } 971 } 972 } 973 974 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) { 975 const uint64_t cputype = O->getHeader().cputype; 976 const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 977 if (Dysymtab.nextrel != 0) { 978 outs() << "External relocation information " << Dysymtab.nextrel 979 << " entries"; 980 outs() << "\naddress pcrel length extern type scattered " 981 "symbolnum/value\n"; 982 PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype, 983 verbose); 984 } 985 if (Dysymtab.nlocrel != 0) { 986 outs() << format("Local relocation information %u entries", 987 Dysymtab.nlocrel); 988 outs() << "\naddress pcrel length extern type scattered " 989 "symbolnum/value\n"; 990 PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype, 991 verbose); 992 } 993 for (const auto &Load : O->load_commands()) { 994 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 995 const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 996 for (unsigned J = 0; J < Seg.nsects; ++J) { 997 const MachO::section_64 Sec = O->getSection64(Load, J); 998 if (Sec.nreloc != 0) { 999 DataRefImpl DRI; 1000 DRI.d.a = J; 1001 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1002 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1003 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1004 << format(") %u entries", Sec.nreloc); 1005 else 1006 outs() << "Relocation information (" << SegName << ",?) " 1007 << format("%u entries", Sec.nreloc); 1008 outs() << "\naddress pcrel length extern type scattered " 1009 "symbolnum/value\n"; 1010 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1011 O->section_rel_end(DRI), cputype, verbose); 1012 } 1013 } 1014 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1015 const MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 1016 for (unsigned J = 0; J < Seg.nsects; ++J) { 1017 const MachO::section Sec = O->getSection(Load, J); 1018 if (Sec.nreloc != 0) { 1019 DataRefImpl DRI; 1020 DRI.d.a = J; 1021 const StringRef SegName = O->getSectionFinalSegmentName(DRI); 1022 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI)) 1023 outs() << "Relocation information (" << SegName << "," << *NameOrErr 1024 << format(") %u entries", Sec.nreloc); 1025 else 1026 outs() << "Relocation information (" << SegName << ",?) " 1027 << format("%u entries", Sec.nreloc); 1028 outs() << "\naddress pcrel length extern type scattered " 1029 "symbolnum/value\n"; 1030 PrintRelocationEntries(O, O->section_rel_begin(DRI), 1031 O->section_rel_end(DRI), cputype, verbose); 1032 } 1033 } 1034 } 1035 } 1036 } 1037 1038 static void PrintFunctionStarts(MachOObjectFile *O) { 1039 uint64_t BaseSegmentAddress = 0; 1040 for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) { 1041 if (Command.C.cmd == MachO::LC_SEGMENT) { 1042 MachO::segment_command SLC = O->getSegmentLoadCommand(Command); 1043 if (StringRef(SLC.segname) == "__TEXT") { 1044 BaseSegmentAddress = SLC.vmaddr; 1045 break; 1046 } 1047 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 1048 MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command); 1049 if (StringRef(SLC.segname) == "__TEXT") { 1050 BaseSegmentAddress = SLC.vmaddr; 1051 break; 1052 } 1053 } 1054 } 1055 1056 SmallVector<uint64_t, 8> FunctionStarts; 1057 for (const MachOObjectFile::LoadCommandInfo &LC : O->load_commands()) { 1058 if (LC.C.cmd == MachO::LC_FUNCTION_STARTS) { 1059 MachO::linkedit_data_command FunctionStartsLC = 1060 O->getLinkeditDataLoadCommand(LC); 1061 O->ReadULEB128s(FunctionStartsLC.dataoff, FunctionStarts); 1062 break; 1063 } 1064 } 1065 1066 DenseMap<uint64_t, StringRef> SymbolNames; 1067 if (FunctionStartsType == FunctionStartsMode::Names || 1068 FunctionStartsType == FunctionStartsMode::Both) { 1069 for (SymbolRef Sym : O->symbols()) { 1070 if (Expected<uint64_t> Addr = Sym.getAddress()) { 1071 if (Expected<StringRef> Name = Sym.getName()) { 1072 SymbolNames[*Addr] = *Name; 1073 } 1074 } 1075 } 1076 } 1077 1078 for (uint64_t S : FunctionStarts) { 1079 uint64_t Addr = BaseSegmentAddress + S; 1080 if (FunctionStartsType == FunctionStartsMode::Names) { 1081 auto It = SymbolNames.find(Addr); 1082 if (It != SymbolNames.end()) 1083 outs() << It->second << "\n"; 1084 } else { 1085 if (O->is64Bit()) 1086 outs() << format("%016" PRIx64, Addr); 1087 else 1088 outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr)); 1089 1090 if (FunctionStartsType == FunctionStartsMode::Both) { 1091 auto It = SymbolNames.find(Addr); 1092 if (It != SymbolNames.end()) 1093 outs() << " " << It->second; 1094 else 1095 outs() << " ?"; 1096 } 1097 outs() << "\n"; 1098 } 1099 } 1100 } 1101 1102 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 1103 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 1104 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 1105 outs() << "Data in code table (" << nentries << " entries)\n"; 1106 outs() << "offset length kind\n"; 1107 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 1108 ++DI) { 1109 uint32_t Offset; 1110 DI->getOffset(Offset); 1111 outs() << format("0x%08" PRIx32, Offset) << " "; 1112 uint16_t Length; 1113 DI->getLength(Length); 1114 outs() << format("%6u", Length) << " "; 1115 uint16_t Kind; 1116 DI->getKind(Kind); 1117 if (verbose) { 1118 switch (Kind) { 1119 case MachO::DICE_KIND_DATA: 1120 outs() << "DATA"; 1121 break; 1122 case MachO::DICE_KIND_JUMP_TABLE8: 1123 outs() << "JUMP_TABLE8"; 1124 break; 1125 case MachO::DICE_KIND_JUMP_TABLE16: 1126 outs() << "JUMP_TABLE16"; 1127 break; 1128 case MachO::DICE_KIND_JUMP_TABLE32: 1129 outs() << "JUMP_TABLE32"; 1130 break; 1131 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 1132 outs() << "ABS_JUMP_TABLE32"; 1133 break; 1134 default: 1135 outs() << format("0x%04" PRIx32, Kind); 1136 break; 1137 } 1138 } else 1139 outs() << format("0x%04" PRIx32, Kind); 1140 outs() << "\n"; 1141 } 1142 } 1143 1144 static void PrintLinkOptHints(MachOObjectFile *O) { 1145 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 1146 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 1147 uint32_t nloh = LohLC.datasize; 1148 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 1149 for (uint32_t i = 0; i < nloh;) { 1150 unsigned n; 1151 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 1152 i += n; 1153 outs() << " identifier " << identifier << " "; 1154 if (i >= nloh) 1155 return; 1156 switch (identifier) { 1157 case 1: 1158 outs() << "AdrpAdrp\n"; 1159 break; 1160 case 2: 1161 outs() << "AdrpLdr\n"; 1162 break; 1163 case 3: 1164 outs() << "AdrpAddLdr\n"; 1165 break; 1166 case 4: 1167 outs() << "AdrpLdrGotLdr\n"; 1168 break; 1169 case 5: 1170 outs() << "AdrpAddStr\n"; 1171 break; 1172 case 6: 1173 outs() << "AdrpLdrGotStr\n"; 1174 break; 1175 case 7: 1176 outs() << "AdrpAdd\n"; 1177 break; 1178 case 8: 1179 outs() << "AdrpLdrGot\n"; 1180 break; 1181 default: 1182 outs() << "Unknown identifier value\n"; 1183 break; 1184 } 1185 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 1186 i += n; 1187 outs() << " narguments " << narguments << "\n"; 1188 if (i >= nloh) 1189 return; 1190 1191 for (uint32_t j = 0; j < narguments; j++) { 1192 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 1193 i += n; 1194 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 1195 if (i >= nloh) 1196 return; 1197 } 1198 } 1199 } 1200 1201 static SmallVector<std::string> GetSegmentNames(object::MachOObjectFile *O) { 1202 SmallVector<std::string> Ret; 1203 for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) { 1204 if (Command.C.cmd == MachO::LC_SEGMENT) { 1205 MachO::segment_command SLC = O->getSegmentLoadCommand(Command); 1206 Ret.push_back(SLC.segname); 1207 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 1208 MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command); 1209 Ret.push_back(SLC.segname); 1210 } 1211 } 1212 return Ret; 1213 } 1214 1215 static void 1216 PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) { 1217 outs() << "chained fixups header (LC_DYLD_CHAINED_FIXUPS)\n"; 1218 outs() << " fixups_version = " << H.fixups_version << '\n'; 1219 outs() << " starts_offset = " << H.starts_offset << '\n'; 1220 outs() << " imports_offset = " << H.imports_offset << '\n'; 1221 outs() << " symbols_offset = " << H.symbols_offset << '\n'; 1222 outs() << " imports_count = " << H.imports_count << '\n'; 1223 1224 outs() << " imports_format = " << H.imports_format; 1225 switch (H.imports_format) { 1226 case llvm::MachO::DYLD_CHAINED_IMPORT: 1227 outs() << " (DYLD_CHAINED_IMPORT)"; 1228 break; 1229 case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND: 1230 outs() << " (DYLD_CHAINED_IMPORT_ADDEND)"; 1231 break; 1232 case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND64: 1233 outs() << " (DYLD_CHAINED_IMPORT_ADDEND64)"; 1234 break; 1235 } 1236 outs() << '\n'; 1237 1238 outs() << " symbols_format = " << H.symbols_format; 1239 if (H.symbols_format == llvm::MachO::DYLD_CHAINED_SYMBOL_ZLIB) 1240 outs() << " (zlib compressed)"; 1241 outs() << '\n'; 1242 } 1243 1244 static constexpr std::array<StringRef, 13> PointerFormats{ 1245 "DYLD_CHAINED_PTR_ARM64E", 1246 "DYLD_CHAINED_PTR_64", 1247 "DYLD_CHAINED_PTR_32", 1248 "DYLD_CHAINED_PTR_32_CACHE", 1249 "DYLD_CHAINED_PTR_32_FIRMWARE", 1250 "DYLD_CHAINED_PTR_64_OFFSET", 1251 "DYLD_CHAINED_PTR_ARM64E_KERNEL", 1252 "DYLD_CHAINED_PTR_64_KERNEL_CACHE", 1253 "DYLD_CHAINED_PTR_ARM64E_USERLAND", 1254 "DYLD_CHAINED_PTR_ARM64E_FIRMWARE", 1255 "DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE", 1256 "DYLD_CHAINED_PTR_ARM64E_USERLAND24", 1257 }; 1258 1259 static void PrintChainedFixupsSegment(const ChainedFixupsSegment &Segment, 1260 StringRef SegName) { 1261 outs() << "chained starts in segment " << Segment.SegIdx << " (" << SegName 1262 << ")\n"; 1263 outs() << " size = " << Segment.Header.size << '\n'; 1264 outs() << " page_size = " << format("0x%0" PRIx16, Segment.Header.page_size) 1265 << '\n'; 1266 1267 outs() << " pointer_format = " << Segment.Header.pointer_format; 1268 if ((Segment.Header.pointer_format - 1) < 1269 MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24) 1270 outs() << " (" << PointerFormats[Segment.Header.pointer_format - 1] << ")"; 1271 outs() << '\n'; 1272 1273 outs() << " segment_offset = " 1274 << format("0x%0" PRIx64, Segment.Header.segment_offset) << '\n'; 1275 outs() << " max_valid_pointer = " << Segment.Header.max_valid_pointer 1276 << '\n'; 1277 outs() << " page_count = " << Segment.Header.page_count << '\n'; 1278 for (auto [Index, PageStart] : enumerate(Segment.PageStarts)) { 1279 outs() << " page_start[" << Index << "] = " << PageStart; 1280 // FIXME: Support DYLD_CHAINED_PTR_START_MULTI (32-bit only) 1281 if (PageStart == MachO::DYLD_CHAINED_PTR_START_NONE) 1282 outs() << " (DYLD_CHAINED_PTR_START_NONE)"; 1283 outs() << '\n'; 1284 } 1285 } 1286 1287 static void PrintChainedFixupTarget(ChainedFixupTarget &Target, size_t Idx, 1288 int Format, MachOObjectFile *O) { 1289 if (Format == MachO::DYLD_CHAINED_IMPORT) 1290 outs() << "dyld chained import"; 1291 else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND) 1292 outs() << "dyld chained import addend"; 1293 else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND64) 1294 outs() << "dyld chained import addend64"; 1295 // FIXME: otool prints the encoded value as well. 1296 outs() << '[' << Idx << "]\n"; 1297 1298 outs() << " lib_ordinal = " << Target.libOrdinal() << " (" 1299 << ordinalName(O, Target.libOrdinal()) << ")\n"; 1300 outs() << " weak_import = " << Target.weakImport() << '\n'; 1301 outs() << " name_offset = " << Target.nameOffset() << " (" 1302 << Target.symbolName() << ")\n"; 1303 if (Format != MachO::DYLD_CHAINED_IMPORT) 1304 outs() << " addend = " << (int64_t)Target.addend() << '\n'; 1305 } 1306 1307 static void PrintChainedFixups(MachOObjectFile *O) { 1308 // MachOObjectFile::getChainedFixupsHeader() reads LC_DYLD_CHAINED_FIXUPS. 1309 // FIXME: Support chained fixups in __TEXT,__chain_starts section too. 1310 auto ChainedFixupHeader = 1311 unwrapOrError(O->getChainedFixupsHeader(), O->getFileName()); 1312 if (!ChainedFixupHeader) 1313 return; 1314 1315 PrintChainedFixupsHeader(*ChainedFixupHeader); 1316 1317 auto [SegCount, Segments] = 1318 unwrapOrError(O->getChainedFixupsSegments(), O->getFileName()); 1319 1320 auto SegNames = GetSegmentNames(O); 1321 1322 size_t StartsIdx = 0; 1323 outs() << "chained starts in image\n"; 1324 outs() << " seg_count = " << SegCount << '\n'; 1325 for (size_t I = 0; I < SegCount; ++I) { 1326 uint64_t SegOffset = 0; 1327 if (StartsIdx < Segments.size() && I == Segments[StartsIdx].SegIdx) { 1328 SegOffset = Segments[StartsIdx].Offset; 1329 ++StartsIdx; 1330 } 1331 1332 outs() << " seg_offset[" << I << "] = " << SegOffset << " (" 1333 << SegNames[I] << ")\n"; 1334 } 1335 1336 for (const ChainedFixupsSegment &S : Segments) 1337 PrintChainedFixupsSegment(S, SegNames[S.SegIdx]); 1338 1339 auto FixupTargets = 1340 unwrapOrError(O->getDyldChainedFixupTargets(), O->getFileName()); 1341 1342 uint32_t ImportsFormat = ChainedFixupHeader->imports_format; 1343 for (auto [Idx, Target] : enumerate(FixupTargets)) 1344 PrintChainedFixupTarget(Target, Idx, ImportsFormat, O); 1345 } 1346 1347 static void PrintDyldInfo(MachOObjectFile *O) { 1348 Error Err = Error::success(); 1349 1350 size_t SegmentWidth = strlen("segment"); 1351 size_t SectionWidth = strlen("section"); 1352 size_t AddressWidth = strlen("address"); 1353 size_t AddendWidth = strlen("addend"); 1354 size_t DylibWidth = strlen("dylib"); 1355 const size_t PointerWidth = 2 + O->getBytesInAddress() * 2; 1356 1357 auto HexLength = [](uint64_t Num) { 1358 return Num ? (size_t)divideCeil(Log2_64(Num), 4) : 1; 1359 }; 1360 for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) { 1361 SegmentWidth = std::max(SegmentWidth, Entry.segmentName().size()); 1362 SectionWidth = std::max(SectionWidth, Entry.sectionName().size()); 1363 AddressWidth = std::max(AddressWidth, HexLength(Entry.address()) + 2); 1364 if (Entry.isBind()) { 1365 AddendWidth = std::max(AddendWidth, HexLength(Entry.addend()) + 2); 1366 DylibWidth = std::max(DylibWidth, Entry.symbolName().size()); 1367 } 1368 } 1369 // Errors will be handled when printing the table. 1370 if (Err) 1371 consumeError(std::move(Err)); 1372 1373 outs() << "dyld information:\n"; 1374 outs() << left_justify("segment", SegmentWidth) << ' ' 1375 << left_justify("section", SectionWidth) << ' ' 1376 << left_justify("address", AddressWidth) << ' ' 1377 << left_justify("pointer", PointerWidth) << " type " 1378 << left_justify("addend", AddendWidth) << ' ' 1379 << left_justify("dylib", DylibWidth) << " symbol/vm address\n"; 1380 for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) { 1381 outs() << left_justify(Entry.segmentName(), SegmentWidth) << ' ' 1382 << left_justify(Entry.sectionName(), SectionWidth) << ' ' << "0x" 1383 << left_justify(utohexstr(Entry.address()), AddressWidth - 2) << ' ' 1384 << format_hex(Entry.rawValue(), PointerWidth, true) << ' '; 1385 if (Entry.isBind()) { 1386 outs() << "bind " 1387 << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2) 1388 << ' ' << left_justify(ordinalName(O, Entry.ordinal()), DylibWidth) 1389 << ' ' << Entry.symbolName(); 1390 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 1391 outs() << " (weak import)"; 1392 outs() << '\n'; 1393 } else { 1394 assert(Entry.isRebase()); 1395 outs() << "rebase"; 1396 outs().indent(AddendWidth + DylibWidth + 2); 1397 outs() << format("0x%" PRIX64, Entry.pointerValue()) << '\n'; 1398 } 1399 } 1400 if (Err) 1401 reportError(std::move(Err), O->getFileName()); 1402 1403 // TODO: Print opcode-based fixups if the object uses those. 1404 } 1405 1406 static void PrintDylibs(MachOObjectFile *O, bool JustId) { 1407 unsigned Index = 0; 1408 for (const auto &Load : O->load_commands()) { 1409 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 1410 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 1411 Load.C.cmd == MachO::LC_LOAD_DYLIB || 1412 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 1413 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 1414 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 1415 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 1416 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 1417 if (dl.dylib.name < dl.cmdsize) { 1418 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 1419 if (JustId) 1420 outs() << p << "\n"; 1421 else { 1422 outs() << "\t" << p; 1423 outs() << " (compatibility version " 1424 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 1425 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 1426 << (dl.dylib.compatibility_version & 0xff) << ","; 1427 outs() << " current version " 1428 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 1429 << ((dl.dylib.current_version >> 8) & 0xff) << "." 1430 << (dl.dylib.current_version & 0xff); 1431 if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 1432 outs() << ", weak"; 1433 if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 1434 outs() << ", reexport"; 1435 if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 1436 outs() << ", upward"; 1437 if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 1438 outs() << ", lazy"; 1439 outs() << ")\n"; 1440 } 1441 } else { 1442 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 1443 if (Load.C.cmd == MachO::LC_ID_DYLIB) 1444 outs() << "LC_ID_DYLIB "; 1445 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 1446 outs() << "LC_LOAD_DYLIB "; 1447 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 1448 outs() << "LC_LOAD_WEAK_DYLIB "; 1449 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 1450 outs() << "LC_LAZY_LOAD_DYLIB "; 1451 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 1452 outs() << "LC_REEXPORT_DYLIB "; 1453 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 1454 outs() << "LC_LOAD_UPWARD_DYLIB "; 1455 else 1456 outs() << "LC_??? "; 1457 outs() << "command " << Index++ << "\n"; 1458 } 1459 } 1460 } 1461 } 1462 1463 static void printRpaths(MachOObjectFile *O) { 1464 for (const auto &Command : O->load_commands()) { 1465 if (Command.C.cmd == MachO::LC_RPATH) { 1466 auto Rpath = O->getRpathCommand(Command); 1467 const char *P = (const char *)(Command.Ptr) + Rpath.path; 1468 outs() << P << "\n"; 1469 } 1470 } 1471 } 1472 1473 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 1474 1475 static void CreateSymbolAddressMap(MachOObjectFile *O, 1476 SymbolAddressMap *AddrMap) { 1477 // Create a map of symbol addresses to symbol names. 1478 const StringRef FileName = O->getFileName(); 1479 for (const SymbolRef &Symbol : O->symbols()) { 1480 SymbolRef::Type ST = unwrapOrError(Symbol.getType(), FileName); 1481 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 1482 ST == SymbolRef::ST_Other) { 1483 uint64_t Address = cantFail(Symbol.getValue()); 1484 StringRef SymName = unwrapOrError(Symbol.getName(), FileName); 1485 if (!SymName.starts_with(".objc")) 1486 (*AddrMap)[Address] = SymName; 1487 } 1488 } 1489 } 1490 1491 // GuessSymbolName is passed the address of what might be a symbol and a 1492 // pointer to the SymbolAddressMap. It returns the name of a symbol 1493 // with that address or nullptr if no symbol is found with that address. 1494 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 1495 const char *SymbolName = nullptr; 1496 // A DenseMap can't lookup up some values. 1497 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 1498 StringRef name = AddrMap->lookup(value); 1499 if (!name.empty()) 1500 SymbolName = name.data(); 1501 } 1502 return SymbolName; 1503 } 1504 1505 static void DumpCstringChar(const char c) { 1506 char p[2]; 1507 p[0] = c; 1508 p[1] = '\0'; 1509 outs().write_escaped(p); 1510 } 1511 1512 static void DumpCstringSection(MachOObjectFile *O, const char *sect, 1513 uint32_t sect_size, uint64_t sect_addr, 1514 bool print_addresses) { 1515 for (uint32_t i = 0; i < sect_size; i++) { 1516 if (print_addresses) { 1517 if (O->is64Bit()) 1518 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1519 else 1520 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1521 } 1522 for (; i < sect_size && sect[i] != '\0'; i++) 1523 DumpCstringChar(sect[i]); 1524 if (i < sect_size && sect[i] == '\0') 1525 outs() << "\n"; 1526 } 1527 } 1528 1529 static void DumpLiteral4(uint32_t l, float f) { 1530 outs() << format("0x%08" PRIx32, l); 1531 if ((l & 0x7f800000) != 0x7f800000) 1532 outs() << format(" (%.16e)\n", f); 1533 else { 1534 if (l == 0x7f800000) 1535 outs() << " (+Infinity)\n"; 1536 else if (l == 0xff800000) 1537 outs() << " (-Infinity)\n"; 1538 else if ((l & 0x00400000) == 0x00400000) 1539 outs() << " (non-signaling Not-a-Number)\n"; 1540 else 1541 outs() << " (signaling Not-a-Number)\n"; 1542 } 1543 } 1544 1545 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 1546 uint32_t sect_size, uint64_t sect_addr, 1547 bool print_addresses) { 1548 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 1549 if (print_addresses) { 1550 if (O->is64Bit()) 1551 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1552 else 1553 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1554 } 1555 float f; 1556 memcpy(&f, sect + i, sizeof(float)); 1557 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1558 sys::swapByteOrder(f); 1559 uint32_t l; 1560 memcpy(&l, sect + i, sizeof(uint32_t)); 1561 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1562 sys::swapByteOrder(l); 1563 DumpLiteral4(l, f); 1564 } 1565 } 1566 1567 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 1568 double d) { 1569 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 1570 uint32_t Hi, Lo; 1571 Hi = (O->isLittleEndian()) ? l1 : l0; 1572 Lo = (O->isLittleEndian()) ? l0 : l1; 1573 1574 // Hi is the high word, so this is equivalent to if(isfinite(d)) 1575 if ((Hi & 0x7ff00000) != 0x7ff00000) 1576 outs() << format(" (%.16e)\n", d); 1577 else { 1578 if (Hi == 0x7ff00000 && Lo == 0) 1579 outs() << " (+Infinity)\n"; 1580 else if (Hi == 0xfff00000 && Lo == 0) 1581 outs() << " (-Infinity)\n"; 1582 else if ((Hi & 0x00080000) == 0x00080000) 1583 outs() << " (non-signaling Not-a-Number)\n"; 1584 else 1585 outs() << " (signaling Not-a-Number)\n"; 1586 } 1587 } 1588 1589 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 1590 uint32_t sect_size, uint64_t sect_addr, 1591 bool print_addresses) { 1592 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 1593 if (print_addresses) { 1594 if (O->is64Bit()) 1595 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1596 else 1597 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1598 } 1599 double d; 1600 memcpy(&d, sect + i, sizeof(double)); 1601 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1602 sys::swapByteOrder(d); 1603 uint32_t l0, l1; 1604 memcpy(&l0, sect + i, sizeof(uint32_t)); 1605 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1606 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1607 sys::swapByteOrder(l0); 1608 sys::swapByteOrder(l1); 1609 } 1610 DumpLiteral8(O, l0, l1, d); 1611 } 1612 } 1613 1614 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 1615 outs() << format("0x%08" PRIx32, l0) << " "; 1616 outs() << format("0x%08" PRIx32, l1) << " "; 1617 outs() << format("0x%08" PRIx32, l2) << " "; 1618 outs() << format("0x%08" PRIx32, l3) << "\n"; 1619 } 1620 1621 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 1622 uint32_t sect_size, uint64_t sect_addr, 1623 bool print_addresses) { 1624 for (uint32_t i = 0; i < sect_size; i += 16) { 1625 if (print_addresses) { 1626 if (O->is64Bit()) 1627 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1628 else 1629 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1630 } 1631 uint32_t l0, l1, l2, l3; 1632 memcpy(&l0, sect + i, sizeof(uint32_t)); 1633 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 1634 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 1635 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1636 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1637 sys::swapByteOrder(l0); 1638 sys::swapByteOrder(l1); 1639 sys::swapByteOrder(l2); 1640 sys::swapByteOrder(l3); 1641 } 1642 DumpLiteral16(l0, l1, l2, l3); 1643 } 1644 } 1645 1646 static void DumpLiteralPointerSection(MachOObjectFile *O, 1647 const SectionRef &Section, 1648 const char *sect, uint32_t sect_size, 1649 uint64_t sect_addr, 1650 bool print_addresses) { 1651 // Collect the literal sections in this Mach-O file. 1652 std::vector<SectionRef> LiteralSections; 1653 for (const SectionRef &Section : O->sections()) { 1654 DataRefImpl Ref = Section.getRawDataRefImpl(); 1655 uint32_t section_type; 1656 if (O->is64Bit()) { 1657 const MachO::section_64 Sec = O->getSection64(Ref); 1658 section_type = Sec.flags & MachO::SECTION_TYPE; 1659 } else { 1660 const MachO::section Sec = O->getSection(Ref); 1661 section_type = Sec.flags & MachO::SECTION_TYPE; 1662 } 1663 if (section_type == MachO::S_CSTRING_LITERALS || 1664 section_type == MachO::S_4BYTE_LITERALS || 1665 section_type == MachO::S_8BYTE_LITERALS || 1666 section_type == MachO::S_16BYTE_LITERALS) 1667 LiteralSections.push_back(Section); 1668 } 1669 1670 // Set the size of the literal pointer. 1671 uint32_t lp_size = O->is64Bit() ? 8 : 4; 1672 1673 // Collect the external relocation symbols for the literal pointers. 1674 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1675 for (const RelocationRef &Reloc : Section.relocations()) { 1676 DataRefImpl Rel; 1677 MachO::any_relocation_info RE; 1678 bool isExtern = false; 1679 Rel = Reloc.getRawDataRefImpl(); 1680 RE = O->getRelocation(Rel); 1681 isExtern = O->getPlainRelocationExternal(RE); 1682 if (isExtern) { 1683 uint64_t RelocOffset = Reloc.getOffset(); 1684 symbol_iterator RelocSym = Reloc.getSymbol(); 1685 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1686 } 1687 } 1688 array_pod_sort(Relocs.begin(), Relocs.end()); 1689 1690 // Dump each literal pointer. 1691 for (uint32_t i = 0; i < sect_size; i += lp_size) { 1692 if (print_addresses) { 1693 if (O->is64Bit()) 1694 outs() << format("%016" PRIx64, sect_addr + i) << " "; 1695 else 1696 outs() << format("%08" PRIx64, sect_addr + i) << " "; 1697 } 1698 uint64_t lp; 1699 if (O->is64Bit()) { 1700 memcpy(&lp, sect + i, sizeof(uint64_t)); 1701 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1702 sys::swapByteOrder(lp); 1703 } else { 1704 uint32_t li; 1705 memcpy(&li, sect + i, sizeof(uint32_t)); 1706 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1707 sys::swapByteOrder(li); 1708 lp = li; 1709 } 1710 1711 // First look for an external relocation entry for this literal pointer. 1712 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1713 return P.first == i; 1714 }); 1715 if (Reloc != Relocs.end()) { 1716 symbol_iterator RelocSym = Reloc->second; 1717 StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName()); 1718 outs() << "external relocation entry for symbol:" << SymName << "\n"; 1719 continue; 1720 } 1721 1722 // For local references see what the section the literal pointer points to. 1723 auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { 1724 return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); 1725 }); 1726 if (Sect == LiteralSections.end()) { 1727 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 1728 continue; 1729 } 1730 1731 uint64_t SectAddress = Sect->getAddress(); 1732 uint64_t SectSize = Sect->getSize(); 1733 1734 StringRef SectName; 1735 Expected<StringRef> SectNameOrErr = Sect->getName(); 1736 if (SectNameOrErr) 1737 SectName = *SectNameOrErr; 1738 else 1739 consumeError(SectNameOrErr.takeError()); 1740 1741 DataRefImpl Ref = Sect->getRawDataRefImpl(); 1742 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 1743 outs() << SegmentName << ":" << SectName << ":"; 1744 1745 uint32_t section_type; 1746 if (O->is64Bit()) { 1747 const MachO::section_64 Sec = O->getSection64(Ref); 1748 section_type = Sec.flags & MachO::SECTION_TYPE; 1749 } else { 1750 const MachO::section Sec = O->getSection(Ref); 1751 section_type = Sec.flags & MachO::SECTION_TYPE; 1752 } 1753 1754 StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName()); 1755 1756 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 1757 1758 switch (section_type) { 1759 case MachO::S_CSTRING_LITERALS: 1760 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 1761 i++) { 1762 DumpCstringChar(Contents[i]); 1763 } 1764 outs() << "\n"; 1765 break; 1766 case MachO::S_4BYTE_LITERALS: 1767 float f; 1768 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 1769 uint32_t l; 1770 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 1771 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1772 sys::swapByteOrder(f); 1773 sys::swapByteOrder(l); 1774 } 1775 DumpLiteral4(l, f); 1776 break; 1777 case MachO::S_8BYTE_LITERALS: { 1778 double d; 1779 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 1780 uint32_t l0, l1; 1781 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1782 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1783 sizeof(uint32_t)); 1784 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1785 sys::swapByteOrder(f); 1786 sys::swapByteOrder(l0); 1787 sys::swapByteOrder(l1); 1788 } 1789 DumpLiteral8(O, l0, l1, d); 1790 break; 1791 } 1792 case MachO::S_16BYTE_LITERALS: { 1793 uint32_t l0, l1, l2, l3; 1794 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 1795 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 1796 sizeof(uint32_t)); 1797 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 1798 sizeof(uint32_t)); 1799 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 1800 sizeof(uint32_t)); 1801 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 1802 sys::swapByteOrder(l0); 1803 sys::swapByteOrder(l1); 1804 sys::swapByteOrder(l2); 1805 sys::swapByteOrder(l3); 1806 } 1807 DumpLiteral16(l0, l1, l2, l3); 1808 break; 1809 } 1810 } 1811 } 1812 } 1813 1814 static void DumpInitTermPointerSection(MachOObjectFile *O, 1815 const SectionRef &Section, 1816 const char *sect, 1817 uint32_t sect_size, uint64_t sect_addr, 1818 SymbolAddressMap *AddrMap, 1819 bool verbose) { 1820 uint32_t stride; 1821 stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); 1822 1823 // Collect the external relocation symbols for the pointers. 1824 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1825 for (const RelocationRef &Reloc : Section.relocations()) { 1826 DataRefImpl Rel; 1827 MachO::any_relocation_info RE; 1828 bool isExtern = false; 1829 Rel = Reloc.getRawDataRefImpl(); 1830 RE = O->getRelocation(Rel); 1831 isExtern = O->getPlainRelocationExternal(RE); 1832 if (isExtern) { 1833 uint64_t RelocOffset = Reloc.getOffset(); 1834 symbol_iterator RelocSym = Reloc.getSymbol(); 1835 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 1836 } 1837 } 1838 array_pod_sort(Relocs.begin(), Relocs.end()); 1839 1840 for (uint32_t i = 0; i < sect_size; i += stride) { 1841 const char *SymbolName = nullptr; 1842 uint64_t p; 1843 if (O->is64Bit()) { 1844 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 1845 uint64_t pointer_value; 1846 memcpy(&pointer_value, sect + i, stride); 1847 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1848 sys::swapByteOrder(pointer_value); 1849 outs() << format("0x%016" PRIx64, pointer_value); 1850 p = pointer_value; 1851 } else { 1852 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 1853 uint32_t pointer_value; 1854 memcpy(&pointer_value, sect + i, stride); 1855 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1856 sys::swapByteOrder(pointer_value); 1857 outs() << format("0x%08" PRIx32, pointer_value); 1858 p = pointer_value; 1859 } 1860 if (verbose) { 1861 // First look for an external relocation entry for this pointer. 1862 auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { 1863 return P.first == i; 1864 }); 1865 if (Reloc != Relocs.end()) { 1866 symbol_iterator RelocSym = Reloc->second; 1867 outs() << " " << unwrapOrError(RelocSym->getName(), O->getFileName()); 1868 } else { 1869 SymbolName = GuessSymbolName(p, AddrMap); 1870 if (SymbolName) 1871 outs() << " " << SymbolName; 1872 } 1873 } 1874 outs() << "\n"; 1875 } 1876 } 1877 1878 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 1879 uint32_t size, uint64_t addr) { 1880 uint32_t cputype = O->getHeader().cputype; 1881 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 1882 uint32_t j; 1883 for (uint32_t i = 0; i < size; i += j, addr += j) { 1884 if (O->is64Bit()) 1885 outs() << format("%016" PRIx64, addr) << "\t"; 1886 else 1887 outs() << format("%08" PRIx64, addr) << "\t"; 1888 for (j = 0; j < 16 && i + j < size; j++) { 1889 uint8_t byte_word = *(sect + i + j); 1890 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1891 } 1892 outs() << "\n"; 1893 } 1894 } else { 1895 uint32_t j; 1896 for (uint32_t i = 0; i < size; i += j, addr += j) { 1897 if (O->is64Bit()) 1898 outs() << format("%016" PRIx64, addr) << "\t"; 1899 else 1900 outs() << format("%08" PRIx64, addr) << "\t"; 1901 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 1902 j += sizeof(int32_t)) { 1903 if (i + j + sizeof(int32_t) <= size) { 1904 uint32_t long_word; 1905 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1906 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1907 sys::swapByteOrder(long_word); 1908 outs() << format("%08" PRIx32, long_word) << " "; 1909 } else { 1910 for (uint32_t k = 0; i + j + k < size; k++) { 1911 uint8_t byte_word = *(sect + i + j + k); 1912 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1913 } 1914 } 1915 } 1916 outs() << "\n"; 1917 } 1918 } 1919 } 1920 1921 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1922 StringRef DisSegName, StringRef DisSectName); 1923 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 1924 uint32_t size, uint32_t addr); 1925 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1926 bool verbose) { 1927 SymbolAddressMap AddrMap; 1928 if (verbose) 1929 CreateSymbolAddressMap(O, &AddrMap); 1930 1931 for (unsigned i = 0; i < FilterSections.size(); ++i) { 1932 StringRef DumpSection = FilterSections[i]; 1933 std::pair<StringRef, StringRef> DumpSegSectName; 1934 DumpSegSectName = DumpSection.split(','); 1935 StringRef DumpSegName, DumpSectName; 1936 if (!DumpSegSectName.second.empty()) { 1937 DumpSegName = DumpSegSectName.first; 1938 DumpSectName = DumpSegSectName.second; 1939 } else { 1940 DumpSegName = ""; 1941 DumpSectName = DumpSegSectName.first; 1942 } 1943 for (const SectionRef &Section : O->sections()) { 1944 StringRef SectName; 1945 Expected<StringRef> SecNameOrErr = Section.getName(); 1946 if (SecNameOrErr) 1947 SectName = *SecNameOrErr; 1948 else 1949 consumeError(SecNameOrErr.takeError()); 1950 1951 if (!DumpSection.empty()) 1952 FoundSectionSet.insert(DumpSection); 1953 1954 DataRefImpl Ref = Section.getRawDataRefImpl(); 1955 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1956 if ((DumpSegName.empty() || SegName == DumpSegName) && 1957 (SectName == DumpSectName)) { 1958 1959 uint32_t section_flags; 1960 if (O->is64Bit()) { 1961 const MachO::section_64 Sec = O->getSection64(Ref); 1962 section_flags = Sec.flags; 1963 1964 } else { 1965 const MachO::section Sec = O->getSection(Ref); 1966 section_flags = Sec.flags; 1967 } 1968 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1969 1970 StringRef BytesStr = 1971 unwrapOrError(Section.getContents(), O->getFileName()); 1972 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1973 uint32_t sect_size = BytesStr.size(); 1974 uint64_t sect_addr = Section.getAddress(); 1975 1976 if (LeadingHeaders) 1977 outs() << "Contents of (" << SegName << "," << SectName 1978 << ") section\n"; 1979 1980 if (verbose) { 1981 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1982 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1983 DisassembleMachO(Filename, O, SegName, SectName); 1984 continue; 1985 } 1986 if (SegName == "__TEXT" && SectName == "__info_plist") { 1987 outs() << sect; 1988 continue; 1989 } 1990 if (SegName == "__OBJC" && SectName == "__protocol") { 1991 DumpProtocolSection(O, sect, sect_size, sect_addr); 1992 continue; 1993 } 1994 switch (section_type) { 1995 case MachO::S_REGULAR: 1996 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1997 break; 1998 case MachO::S_ZEROFILL: 1999 outs() << "zerofill section and has no contents in the file\n"; 2000 break; 2001 case MachO::S_CSTRING_LITERALS: 2002 DumpCstringSection(O, sect, sect_size, sect_addr, LeadingAddr); 2003 break; 2004 case MachO::S_4BYTE_LITERALS: 2005 DumpLiteral4Section(O, sect, sect_size, sect_addr, LeadingAddr); 2006 break; 2007 case MachO::S_8BYTE_LITERALS: 2008 DumpLiteral8Section(O, sect, sect_size, sect_addr, LeadingAddr); 2009 break; 2010 case MachO::S_16BYTE_LITERALS: 2011 DumpLiteral16Section(O, sect, sect_size, sect_addr, LeadingAddr); 2012 break; 2013 case MachO::S_LITERAL_POINTERS: 2014 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 2015 LeadingAddr); 2016 break; 2017 case MachO::S_MOD_INIT_FUNC_POINTERS: 2018 case MachO::S_MOD_TERM_FUNC_POINTERS: 2019 DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr, 2020 &AddrMap, verbose); 2021 break; 2022 default: 2023 outs() << "Unknown section type (" 2024 << format("0x%08" PRIx32, section_type) << ")\n"; 2025 DumpRawSectionContents(O, sect, sect_size, sect_addr); 2026 break; 2027 } 2028 } else { 2029 if (section_type == MachO::S_ZEROFILL) 2030 outs() << "zerofill section and has no contents in the file\n"; 2031 else 2032 DumpRawSectionContents(O, sect, sect_size, sect_addr); 2033 } 2034 } 2035 } 2036 } 2037 } 2038 2039 static void DumpInfoPlistSectionContents(StringRef Filename, 2040 MachOObjectFile *O) { 2041 for (const SectionRef &Section : O->sections()) { 2042 StringRef SectName; 2043 Expected<StringRef> SecNameOrErr = Section.getName(); 2044 if (SecNameOrErr) 2045 SectName = *SecNameOrErr; 2046 else 2047 consumeError(SecNameOrErr.takeError()); 2048 2049 DataRefImpl Ref = Section.getRawDataRefImpl(); 2050 StringRef SegName = O->getSectionFinalSegmentName(Ref); 2051 if (SegName == "__TEXT" && SectName == "__info_plist") { 2052 if (LeadingHeaders) 2053 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 2054 StringRef BytesStr = 2055 unwrapOrError(Section.getContents(), O->getFileName()); 2056 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 2057 outs() << format("%.*s", BytesStr.size(), sect) << "\n"; 2058 return; 2059 } 2060 } 2061 } 2062 2063 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 2064 // and if it is and there is a list of architecture flags is specified then 2065 // check to make sure this Mach-O file is one of those architectures or all 2066 // architectures were specified. If not then an error is generated and this 2067 // routine returns false. Else it returns true. 2068 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 2069 auto *MachO = dyn_cast<MachOObjectFile>(O); 2070 2071 if (!MachO || ArchAll || ArchFlags.empty()) 2072 return true; 2073 2074 MachO::mach_header H; 2075 MachO::mach_header_64 H_64; 2076 Triple T; 2077 const char *McpuDefault, *ArchFlag; 2078 if (MachO->is64Bit()) { 2079 H_64 = MachO->MachOObjectFile::getHeader64(); 2080 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 2081 &McpuDefault, &ArchFlag); 2082 } else { 2083 H = MachO->MachOObjectFile::getHeader(); 2084 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 2085 &McpuDefault, &ArchFlag); 2086 } 2087 const std::string ArchFlagName(ArchFlag); 2088 if (!llvm::is_contained(ArchFlags, ArchFlagName)) { 2089 WithColor::error(errs(), "llvm-objdump") 2090 << Filename << ": no architecture specified.\n"; 2091 return false; 2092 } 2093 return true; 2094 } 2095 2096 static void printObjcMetaData(MachOObjectFile *O, bool verbose); 2097 2098 // ProcessMachO() is passed a single opened Mach-O file, which may be an 2099 // archive member and or in a slice of a universal file. It prints the 2100 // the file name and header info and then processes it according to the 2101 // command line options. 2102 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, 2103 StringRef ArchiveMemberName = StringRef(), 2104 StringRef ArchitectureName = StringRef()) { 2105 std::unique_ptr<Dumper> D = createMachODumper(*MachOOF); 2106 2107 // If we are doing some processing here on the Mach-O file print the header 2108 // info. And don't print it otherwise like in the case of printing the 2109 // UniversalHeaders or ArchiveHeaders. 2110 if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase || 2111 Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || 2112 DataInCode || FunctionStartsType != FunctionStartsMode::None || 2113 LinkOptHints || ChainedFixups || DyldInfo || DylibsUsed || DylibId || 2114 Rpaths || ObjcMetaData || (!FilterSections.empty())) { 2115 if (LeadingHeaders) { 2116 outs() << Name; 2117 if (!ArchiveMemberName.empty()) 2118 outs() << '(' << ArchiveMemberName << ')'; 2119 if (!ArchitectureName.empty()) 2120 outs() << " (architecture " << ArchitectureName << ")"; 2121 outs() << ":\n"; 2122 } 2123 } 2124 // To use the report_error() form with an ArchiveName and FileName set 2125 // these up based on what is passed for Name and ArchiveMemberName. 2126 StringRef ArchiveName; 2127 StringRef FileName; 2128 if (!ArchiveMemberName.empty()) { 2129 ArchiveName = Name; 2130 FileName = ArchiveMemberName; 2131 } else { 2132 ArchiveName = StringRef(); 2133 FileName = Name; 2134 } 2135 2136 // If we need the symbol table to do the operation then check it here to 2137 // produce a good error message as to where the Mach-O file comes from in 2138 // the error message. 2139 if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo) 2140 if (Error Err = MachOOF->checkSymbolTable()) 2141 reportError(std::move(Err), FileName, ArchiveName, ArchitectureName); 2142 2143 if (DisassembleAll) { 2144 for (const SectionRef &Section : MachOOF->sections()) { 2145 StringRef SectName; 2146 if (Expected<StringRef> NameOrErr = Section.getName()) 2147 SectName = *NameOrErr; 2148 else 2149 consumeError(NameOrErr.takeError()); 2150 2151 if (SectName == "__text") { 2152 DataRefImpl Ref = Section.getRawDataRefImpl(); 2153 StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref); 2154 DisassembleMachO(FileName, MachOOF, SegName, SectName); 2155 } 2156 } 2157 } 2158 else if (Disassemble) { 2159 if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE && 2160 MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64) 2161 DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text"); 2162 else 2163 DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); 2164 } 2165 if (IndirectSymbols) 2166 PrintIndirectSymbols(MachOOF, Verbose); 2167 if (DataInCode) 2168 PrintDataInCodeTable(MachOOF, Verbose); 2169 if (FunctionStartsType != FunctionStartsMode::None) 2170 PrintFunctionStarts(MachOOF); 2171 if (LinkOptHints) 2172 PrintLinkOptHints(MachOOF); 2173 if (Relocations) 2174 PrintRelocations(MachOOF, Verbose); 2175 if (SectionHeaders) 2176 printSectionHeaders(*MachOOF); 2177 if (SectionContents) 2178 printSectionContents(MachOOF); 2179 if (!FilterSections.empty()) 2180 DumpSectionContents(FileName, MachOOF, Verbose); 2181 if (InfoPlist) 2182 DumpInfoPlistSectionContents(FileName, MachOOF); 2183 if (DyldInfo) 2184 PrintDyldInfo(MachOOF); 2185 if (ChainedFixups) 2186 PrintChainedFixups(MachOOF); 2187 if (DylibsUsed) 2188 PrintDylibs(MachOOF, false); 2189 if (DylibId) 2190 PrintDylibs(MachOOF, true); 2191 if (SymbolTable) 2192 D->printSymbolTable(ArchiveName, ArchitectureName); 2193 if (UnwindInfo) 2194 printMachOUnwindInfo(MachOOF); 2195 if (PrivateHeaders) { 2196 printMachOFileHeader(MachOOF); 2197 printMachOLoadCommands(MachOOF); 2198 } 2199 if (FirstPrivateHeader) 2200 printMachOFileHeader(MachOOF); 2201 if (ObjcMetaData) 2202 printObjcMetaData(MachOOF, Verbose); 2203 if (ExportsTrie) 2204 printExportsTrie(MachOOF); 2205 if (Rebase) 2206 printRebaseTable(MachOOF); 2207 if (Rpaths) 2208 printRpaths(MachOOF); 2209 if (Bind) 2210 printBindTable(MachOOF); 2211 if (LazyBind) 2212 printLazyBindTable(MachOOF); 2213 if (WeakBind) 2214 printWeakBindTable(MachOOF); 2215 2216 if (DwarfDumpType != DIDT_Null) { 2217 std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF); 2218 // Dump the complete DWARF structure. 2219 DIDumpOptions DumpOpts; 2220 DumpOpts.DumpType = DwarfDumpType; 2221 DICtx->dump(outs(), DumpOpts); 2222 } 2223 } 2224 2225 // printUnknownCPUType() helps print_fat_headers for unknown CPU's. 2226 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 2227 outs() << " cputype (" << cputype << ")\n"; 2228 outs() << " cpusubtype (" << cpusubtype << ")\n"; 2229 } 2230 2231 // printCPUType() helps print_fat_headers by printing the cputype and 2232 // pusubtype (symbolically for the one's it knows about). 2233 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 2234 switch (cputype) { 2235 case MachO::CPU_TYPE_I386: 2236 switch (cpusubtype) { 2237 case MachO::CPU_SUBTYPE_I386_ALL: 2238 outs() << " cputype CPU_TYPE_I386\n"; 2239 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 2240 break; 2241 default: 2242 printUnknownCPUType(cputype, cpusubtype); 2243 break; 2244 } 2245 break; 2246 case MachO::CPU_TYPE_X86_64: 2247 switch (cpusubtype) { 2248 case MachO::CPU_SUBTYPE_X86_64_ALL: 2249 outs() << " cputype CPU_TYPE_X86_64\n"; 2250 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 2251 break; 2252 case MachO::CPU_SUBTYPE_X86_64_H: 2253 outs() << " cputype CPU_TYPE_X86_64\n"; 2254 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 2255 break; 2256 default: 2257 printUnknownCPUType(cputype, cpusubtype); 2258 break; 2259 } 2260 break; 2261 case MachO::CPU_TYPE_ARM: 2262 switch (cpusubtype) { 2263 case MachO::CPU_SUBTYPE_ARM_ALL: 2264 outs() << " cputype CPU_TYPE_ARM\n"; 2265 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 2266 break; 2267 case MachO::CPU_SUBTYPE_ARM_V4T: 2268 outs() << " cputype CPU_TYPE_ARM\n"; 2269 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 2270 break; 2271 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2272 outs() << " cputype CPU_TYPE_ARM\n"; 2273 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 2274 break; 2275 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2276 outs() << " cputype CPU_TYPE_ARM\n"; 2277 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 2278 break; 2279 case MachO::CPU_SUBTYPE_ARM_V6: 2280 outs() << " cputype CPU_TYPE_ARM\n"; 2281 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 2282 break; 2283 case MachO::CPU_SUBTYPE_ARM_V6M: 2284 outs() << " cputype CPU_TYPE_ARM\n"; 2285 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 2286 break; 2287 case MachO::CPU_SUBTYPE_ARM_V7: 2288 outs() << " cputype CPU_TYPE_ARM\n"; 2289 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 2290 break; 2291 case MachO::CPU_SUBTYPE_ARM_V7EM: 2292 outs() << " cputype CPU_TYPE_ARM\n"; 2293 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 2294 break; 2295 case MachO::CPU_SUBTYPE_ARM_V7K: 2296 outs() << " cputype CPU_TYPE_ARM\n"; 2297 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 2298 break; 2299 case MachO::CPU_SUBTYPE_ARM_V7M: 2300 outs() << " cputype CPU_TYPE_ARM\n"; 2301 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 2302 break; 2303 case MachO::CPU_SUBTYPE_ARM_V7S: 2304 outs() << " cputype CPU_TYPE_ARM\n"; 2305 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 2306 break; 2307 default: 2308 printUnknownCPUType(cputype, cpusubtype); 2309 break; 2310 } 2311 break; 2312 case MachO::CPU_TYPE_ARM64: 2313 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2314 case MachO::CPU_SUBTYPE_ARM64_ALL: 2315 outs() << " cputype CPU_TYPE_ARM64\n"; 2316 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 2317 break; 2318 case MachO::CPU_SUBTYPE_ARM64_V8: 2319 outs() << " cputype CPU_TYPE_ARM64\n"; 2320 outs() << " cpusubtype CPU_SUBTYPE_ARM64_V8\n"; 2321 break; 2322 case MachO::CPU_SUBTYPE_ARM64E: 2323 outs() << " cputype CPU_TYPE_ARM64\n"; 2324 outs() << " cpusubtype CPU_SUBTYPE_ARM64E\n"; 2325 break; 2326 default: 2327 printUnknownCPUType(cputype, cpusubtype); 2328 break; 2329 } 2330 break; 2331 case MachO::CPU_TYPE_ARM64_32: 2332 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2333 case MachO::CPU_SUBTYPE_ARM64_32_V8: 2334 outs() << " cputype CPU_TYPE_ARM64_32\n"; 2335 outs() << " cpusubtype CPU_SUBTYPE_ARM64_32_V8\n"; 2336 break; 2337 default: 2338 printUnknownCPUType(cputype, cpusubtype); 2339 break; 2340 } 2341 break; 2342 default: 2343 printUnknownCPUType(cputype, cpusubtype); 2344 break; 2345 } 2346 } 2347 2348 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 2349 bool verbose) { 2350 outs() << "Fat headers\n"; 2351 if (verbose) { 2352 if (UB->getMagic() == MachO::FAT_MAGIC) 2353 outs() << "fat_magic FAT_MAGIC\n"; 2354 else // UB->getMagic() == MachO::FAT_MAGIC_64 2355 outs() << "fat_magic FAT_MAGIC_64\n"; 2356 } else 2357 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 2358 2359 uint32_t nfat_arch = UB->getNumberOfObjects(); 2360 StringRef Buf = UB->getData(); 2361 uint64_t size = Buf.size(); 2362 uint64_t big_size = sizeof(struct MachO::fat_header) + 2363 nfat_arch * sizeof(struct MachO::fat_arch); 2364 outs() << "nfat_arch " << UB->getNumberOfObjects(); 2365 if (nfat_arch == 0) 2366 outs() << " (malformed, contains zero architecture types)\n"; 2367 else if (big_size > size) 2368 outs() << " (malformed, architectures past end of file)\n"; 2369 else 2370 outs() << "\n"; 2371 2372 for (uint32_t i = 0; i < nfat_arch; ++i) { 2373 MachOUniversalBinary::ObjectForArch OFA(UB, i); 2374 uint32_t cputype = OFA.getCPUType(); 2375 uint32_t cpusubtype = OFA.getCPUSubType(); 2376 outs() << "architecture "; 2377 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 2378 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 2379 uint32_t other_cputype = other_OFA.getCPUType(); 2380 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 2381 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 2382 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 2383 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 2384 outs() << "(illegal duplicate architecture) "; 2385 break; 2386 } 2387 } 2388 if (verbose) { 2389 outs() << OFA.getArchFlagName() << "\n"; 2390 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2391 } else { 2392 outs() << i << "\n"; 2393 outs() << " cputype " << cputype << "\n"; 2394 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 2395 << "\n"; 2396 } 2397 if (verbose && 2398 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 2399 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 2400 else 2401 outs() << " capabilities " 2402 << format("0x%" PRIx32, 2403 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 2404 outs() << " offset " << OFA.getOffset(); 2405 if (OFA.getOffset() > size) 2406 outs() << " (past end of file)"; 2407 if (OFA.getOffset() % (1ull << OFA.getAlign()) != 0) 2408 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 2409 outs() << "\n"; 2410 outs() << " size " << OFA.getSize(); 2411 big_size = OFA.getOffset() + OFA.getSize(); 2412 if (big_size > size) 2413 outs() << " (past end of file)"; 2414 outs() << "\n"; 2415 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 2416 << ")\n"; 2417 } 2418 } 2419 2420 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 2421 size_t ChildIndex, bool verbose, 2422 bool print_offset, 2423 StringRef ArchitectureName = StringRef()) { 2424 if (print_offset) 2425 outs() << C.getChildOffset() << "\t"; 2426 sys::fs::perms Mode = 2427 unwrapOrError(C.getAccessMode(), getFileNameForError(C, ChildIndex), 2428 Filename, ArchitectureName); 2429 if (verbose) { 2430 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 2431 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 2432 outs() << "-"; 2433 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 2434 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 2435 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 2436 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 2437 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 2438 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 2439 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 2440 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 2441 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 2442 } else { 2443 outs() << format("0%o ", Mode); 2444 } 2445 2446 outs() << format("%3d/%-3d %5" PRId64 " ", 2447 unwrapOrError(C.getUID(), getFileNameForError(C, ChildIndex), 2448 Filename, ArchitectureName), 2449 unwrapOrError(C.getGID(), getFileNameForError(C, ChildIndex), 2450 Filename, ArchitectureName), 2451 unwrapOrError(C.getRawSize(), 2452 getFileNameForError(C, ChildIndex), Filename, 2453 ArchitectureName)); 2454 2455 StringRef RawLastModified = C.getRawLastModified(); 2456 if (verbose) { 2457 unsigned Seconds; 2458 if (RawLastModified.getAsInteger(10, Seconds)) 2459 outs() << "(date: \"" << RawLastModified 2460 << "\" contains non-decimal chars) "; 2461 else { 2462 // Since cime(3) returns a 26 character string of the form: 2463 // "Sun Sep 16 01:03:52 1973\n\0" 2464 // just print 24 characters. 2465 time_t t = Seconds; 2466 outs() << format("%.24s ", ctime(&t)); 2467 } 2468 } else { 2469 outs() << RawLastModified << " "; 2470 } 2471 2472 if (verbose) { 2473 Expected<StringRef> NameOrErr = C.getName(); 2474 if (!NameOrErr) { 2475 consumeError(NameOrErr.takeError()); 2476 outs() << unwrapOrError(C.getRawName(), 2477 getFileNameForError(C, ChildIndex), Filename, 2478 ArchitectureName) 2479 << "\n"; 2480 } else { 2481 StringRef Name = NameOrErr.get(); 2482 outs() << Name << "\n"; 2483 } 2484 } else { 2485 outs() << unwrapOrError(C.getRawName(), getFileNameForError(C, ChildIndex), 2486 Filename, ArchitectureName) 2487 << "\n"; 2488 } 2489 } 2490 2491 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 2492 bool print_offset, 2493 StringRef ArchitectureName = StringRef()) { 2494 Error Err = Error::success(); 2495 size_t I = 0; 2496 for (const auto &C : A->children(Err, false)) 2497 printArchiveChild(Filename, C, I++, verbose, print_offset, 2498 ArchitectureName); 2499 2500 if (Err) 2501 reportError(std::move(Err), Filename, "", ArchitectureName); 2502 } 2503 2504 static bool ValidateArchFlags() { 2505 // Check for -arch all and verifiy the -arch flags are valid. 2506 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2507 if (ArchFlags[i] == "all") { 2508 ArchAll = true; 2509 } else { 2510 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 2511 WithColor::error(errs(), "llvm-objdump") 2512 << "unknown architecture named '" + ArchFlags[i] + 2513 "'for the -arch option\n"; 2514 return false; 2515 } 2516 } 2517 } 2518 return true; 2519 } 2520 2521 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 2522 // -arch flags selecting just those slices as specified by them and also parses 2523 // archive files. Then for each individual Mach-O file ProcessMachO() is 2524 // called to process the file based on the command line options. 2525 void objdump::parseInputMachO(StringRef Filename) { 2526 if (!ValidateArchFlags()) 2527 return; 2528 2529 // Attempt to open the binary. 2530 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 2531 if (!BinaryOrErr) { 2532 if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 2533 reportError(std::move(E), Filename); 2534 else 2535 outs() << Filename << ": is not an object file\n"; 2536 return; 2537 } 2538 Binary &Bin = *BinaryOrErr.get().getBinary(); 2539 2540 if (Archive *A = dyn_cast<Archive>(&Bin)) { 2541 outs() << "Archive : " << Filename << "\n"; 2542 if (ArchiveHeaders) 2543 printArchiveHeaders(Filename, A, Verbose, ArchiveMemberOffsets); 2544 2545 Error Err = Error::success(); 2546 unsigned I = -1; 2547 for (auto &C : A->children(Err)) { 2548 ++I; 2549 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2550 if (!ChildOrErr) { 2551 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2552 reportError(std::move(E), getFileNameForError(C, I), Filename); 2553 continue; 2554 } 2555 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2556 if (!checkMachOAndArchFlags(O, Filename)) 2557 return; 2558 ProcessMachO(Filename, O, O->getFileName()); 2559 } 2560 } 2561 if (Err) 2562 reportError(std::move(Err), Filename); 2563 return; 2564 } 2565 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 2566 parseInputMachO(UB); 2567 return; 2568 } 2569 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2570 if (!checkMachOAndArchFlags(O, Filename)) 2571 return; 2572 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) 2573 ProcessMachO(Filename, MachOOF); 2574 else 2575 WithColor::error(errs(), "llvm-objdump") 2576 << Filename << "': " 2577 << "object is not a Mach-O file type.\n"; 2578 return; 2579 } 2580 llvm_unreachable("Input object can't be invalid at this point"); 2581 } 2582 2583 void objdump::parseInputMachO(MachOUniversalBinary *UB) { 2584 if (!ValidateArchFlags()) 2585 return; 2586 2587 auto Filename = UB->getFileName(); 2588 2589 if (UniversalHeaders) 2590 printMachOUniversalHeaders(UB, Verbose); 2591 2592 // If we have a list of architecture flags specified dump only those. 2593 if (!ArchAll && !ArchFlags.empty()) { 2594 // Look for a slice in the universal binary that matches each ArchFlag. 2595 bool ArchFound; 2596 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2597 ArchFound = false; 2598 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2599 E = UB->end_objects(); 2600 I != E; ++I) { 2601 if (ArchFlags[i] == I->getArchFlagName()) { 2602 ArchFound = true; 2603 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2604 I->getAsObjectFile(); 2605 std::string ArchitectureName; 2606 if (ArchFlags.size() > 1) 2607 ArchitectureName = I->getArchFlagName(); 2608 if (ObjOrErr) { 2609 ObjectFile &O = *ObjOrErr.get(); 2610 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2611 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2612 } else if (Error E = isNotObjectErrorInvalidFileType( 2613 ObjOrErr.takeError())) { 2614 reportError(std::move(E), "", Filename, ArchitectureName); 2615 continue; 2616 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2617 I->getAsArchive()) { 2618 std::unique_ptr<Archive> &A = *AOrErr; 2619 outs() << "Archive : " << Filename; 2620 if (!ArchitectureName.empty()) 2621 outs() << " (architecture " << ArchitectureName << ")"; 2622 outs() << "\n"; 2623 if (ArchiveHeaders) 2624 printArchiveHeaders(Filename, A.get(), Verbose, 2625 ArchiveMemberOffsets, ArchitectureName); 2626 Error Err = Error::success(); 2627 unsigned I = -1; 2628 for (auto &C : A->children(Err)) { 2629 ++I; 2630 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2631 if (!ChildOrErr) { 2632 if (Error E = 2633 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2634 reportError(std::move(E), getFileNameForError(C, I), Filename, 2635 ArchitectureName); 2636 continue; 2637 } 2638 if (MachOObjectFile *O = 2639 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2640 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2641 } 2642 if (Err) 2643 reportError(std::move(Err), Filename); 2644 } else { 2645 consumeError(AOrErr.takeError()); 2646 reportError(Filename, 2647 "Mach-O universal file for architecture " + 2648 StringRef(I->getArchFlagName()) + 2649 " is not a Mach-O file or an archive file"); 2650 } 2651 } 2652 } 2653 if (!ArchFound) { 2654 WithColor::error(errs(), "llvm-objdump") 2655 << "file: " + Filename + " does not contain " 2656 << "architecture: " + ArchFlags[i] + "\n"; 2657 return; 2658 } 2659 } 2660 return; 2661 } 2662 // No architecture flags were specified so if this contains a slice that 2663 // matches the host architecture dump only that. 2664 if (!ArchAll) { 2665 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2666 E = UB->end_objects(); 2667 I != E; ++I) { 2668 if (MachOObjectFile::getHostArch().getArchName() == 2669 I->getArchFlagName()) { 2670 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2671 std::string ArchiveName; 2672 ArchiveName.clear(); 2673 if (ObjOrErr) { 2674 ObjectFile &O = *ObjOrErr.get(); 2675 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2676 ProcessMachO(Filename, MachOOF); 2677 } else if (Error E = 2678 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2679 reportError(std::move(E), Filename); 2680 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2681 I->getAsArchive()) { 2682 std::unique_ptr<Archive> &A = *AOrErr; 2683 outs() << "Archive : " << Filename << "\n"; 2684 if (ArchiveHeaders) 2685 printArchiveHeaders(Filename, A.get(), Verbose, 2686 ArchiveMemberOffsets); 2687 Error Err = Error::success(); 2688 unsigned I = -1; 2689 for (auto &C : A->children(Err)) { 2690 ++I; 2691 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2692 if (!ChildOrErr) { 2693 if (Error E = 2694 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2695 reportError(std::move(E), getFileNameForError(C, I), Filename); 2696 continue; 2697 } 2698 if (MachOObjectFile *O = 2699 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2700 ProcessMachO(Filename, O, O->getFileName()); 2701 } 2702 if (Err) 2703 reportError(std::move(Err), Filename); 2704 } else { 2705 consumeError(AOrErr.takeError()); 2706 reportError(Filename, "Mach-O universal file for architecture " + 2707 StringRef(I->getArchFlagName()) + 2708 " is not a Mach-O file or an archive file"); 2709 } 2710 return; 2711 } 2712 } 2713 } 2714 // Either all architectures have been specified or none have been specified 2715 // and this does not contain the host architecture so dump all the slices. 2716 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2717 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2718 E = UB->end_objects(); 2719 I != E; ++I) { 2720 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2721 std::string ArchitectureName; 2722 if (moreThanOneArch) 2723 ArchitectureName = I->getArchFlagName(); 2724 if (ObjOrErr) { 2725 ObjectFile &Obj = *ObjOrErr.get(); 2726 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2727 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2728 } else if (Error E = 2729 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2730 reportError(std::move(E), Filename, "", ArchitectureName); 2731 } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { 2732 std::unique_ptr<Archive> &A = *AOrErr; 2733 outs() << "Archive : " << Filename; 2734 if (!ArchitectureName.empty()) 2735 outs() << " (architecture " << ArchitectureName << ")"; 2736 outs() << "\n"; 2737 if (ArchiveHeaders) 2738 printArchiveHeaders(Filename, A.get(), Verbose, ArchiveMemberOffsets, 2739 ArchitectureName); 2740 Error Err = Error::success(); 2741 unsigned I = -1; 2742 for (auto &C : A->children(Err)) { 2743 ++I; 2744 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2745 if (!ChildOrErr) { 2746 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2747 reportError(std::move(E), getFileNameForError(C, I), Filename, 2748 ArchitectureName); 2749 continue; 2750 } 2751 if (MachOObjectFile *O = 2752 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2753 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2754 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2755 ArchitectureName); 2756 } 2757 } 2758 if (Err) 2759 reportError(std::move(Err), Filename); 2760 } else { 2761 consumeError(AOrErr.takeError()); 2762 reportError(Filename, "Mach-O universal file for architecture " + 2763 StringRef(I->getArchFlagName()) + 2764 " is not a Mach-O file or an archive file"); 2765 } 2766 } 2767 } 2768 2769 namespace { 2770 // The block of info used by the Symbolizer call backs. 2771 struct DisassembleInfo { 2772 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, 2773 std::vector<SectionRef> *Sections, bool verbose) 2774 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {} 2775 bool verbose; 2776 MachOObjectFile *O; 2777 SectionRef S; 2778 SymbolAddressMap *AddrMap; 2779 std::vector<SectionRef> *Sections; 2780 const char *class_name = nullptr; 2781 const char *selector_name = nullptr; 2782 std::unique_ptr<char[]> method = nullptr; 2783 char *demangled_name = nullptr; 2784 uint64_t adrp_addr = 0; 2785 uint32_t adrp_inst = 0; 2786 std::unique_ptr<SymbolAddressMap> bindtable; 2787 uint32_t depth = 0; 2788 }; 2789 } // namespace 2790 2791 // SymbolizerGetOpInfo() is the operand information call back function. 2792 // This is called to get the symbolic information for operand(s) of an 2793 // instruction when it is being done. This routine does this from 2794 // the relocation information, symbol table, etc. That block of information 2795 // is a pointer to the struct DisassembleInfo that was passed when the 2796 // disassembler context was created and passed to back to here when 2797 // called back by the disassembler for instruction operands that could have 2798 // relocation information. The address of the instruction containing operand is 2799 // at the Pc parameter. The immediate value the operand has is passed in 2800 // op_info->Value and is at Offset past the start of the instruction and has a 2801 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2802 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2803 // names and addends of the symbolic expression to add for the operand. The 2804 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2805 // information is returned then this function returns 1 else it returns 0. 2806 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2807 uint64_t OpSize, uint64_t InstSize, int TagType, 2808 void *TagBuf) { 2809 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2810 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2811 uint64_t value = op_info->Value; 2812 2813 // Make sure all fields returned are zero if we don't set them. 2814 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2815 op_info->Value = value; 2816 2817 // If the TagType is not the value 1 which it code knows about or if no 2818 // verbose symbolic information is wanted then just return 0, indicating no 2819 // information is being returned. 2820 if (TagType != 1 || !info->verbose) 2821 return 0; 2822 2823 unsigned int Arch = info->O->getArch(); 2824 if (Arch == Triple::x86) { 2825 if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0) 2826 return 0; 2827 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2828 // TODO: 2829 // Search the external relocation entries of a fully linked image 2830 // (if any) for an entry that matches this segment offset. 2831 // uint32_t seg_offset = (Pc + Offset); 2832 return 0; 2833 } 2834 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2835 // for an entry for this section offset. 2836 uint32_t sect_addr = info->S.getAddress(); 2837 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2838 bool reloc_found = false; 2839 DataRefImpl Rel; 2840 MachO::any_relocation_info RE; 2841 bool isExtern = false; 2842 SymbolRef Symbol; 2843 bool r_scattered = false; 2844 uint32_t r_value, pair_r_value, r_type; 2845 for (const RelocationRef &Reloc : info->S.relocations()) { 2846 uint64_t RelocOffset = Reloc.getOffset(); 2847 if (RelocOffset == sect_offset) { 2848 Rel = Reloc.getRawDataRefImpl(); 2849 RE = info->O->getRelocation(Rel); 2850 r_type = info->O->getAnyRelocationType(RE); 2851 r_scattered = info->O->isRelocationScattered(RE); 2852 if (r_scattered) { 2853 r_value = info->O->getScatteredRelocationValue(RE); 2854 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2855 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2856 DataRefImpl RelNext = Rel; 2857 info->O->moveRelocationNext(RelNext); 2858 MachO::any_relocation_info RENext; 2859 RENext = info->O->getRelocation(RelNext); 2860 if (info->O->isRelocationScattered(RENext)) 2861 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2862 else 2863 return 0; 2864 } 2865 } else { 2866 isExtern = info->O->getPlainRelocationExternal(RE); 2867 if (isExtern) { 2868 symbol_iterator RelocSym = Reloc.getSymbol(); 2869 Symbol = *RelocSym; 2870 } 2871 } 2872 reloc_found = true; 2873 break; 2874 } 2875 } 2876 if (reloc_found && isExtern) { 2877 op_info->AddSymbol.Present = 1; 2878 op_info->AddSymbol.Name = 2879 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2880 // For i386 extern relocation entries the value in the instruction is 2881 // the offset from the symbol, and value is already set in op_info->Value. 2882 return 1; 2883 } 2884 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2885 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2886 const char *add = GuessSymbolName(r_value, info->AddrMap); 2887 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2888 uint32_t offset = value - (r_value - pair_r_value); 2889 op_info->AddSymbol.Present = 1; 2890 if (add != nullptr) 2891 op_info->AddSymbol.Name = add; 2892 else 2893 op_info->AddSymbol.Value = r_value; 2894 op_info->SubtractSymbol.Present = 1; 2895 if (sub != nullptr) 2896 op_info->SubtractSymbol.Name = sub; 2897 else 2898 op_info->SubtractSymbol.Value = pair_r_value; 2899 op_info->Value = offset; 2900 return 1; 2901 } 2902 return 0; 2903 } 2904 if (Arch == Triple::x86_64) { 2905 if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0) 2906 return 0; 2907 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2908 // relocation entries of a linked image (if any) for an entry that matches 2909 // this segment offset. 2910 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2911 uint64_t seg_offset = Pc + Offset; 2912 bool reloc_found = false; 2913 DataRefImpl Rel; 2914 MachO::any_relocation_info RE; 2915 bool isExtern = false; 2916 SymbolRef Symbol; 2917 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2918 uint64_t RelocOffset = Reloc.getOffset(); 2919 if (RelocOffset == seg_offset) { 2920 Rel = Reloc.getRawDataRefImpl(); 2921 RE = info->O->getRelocation(Rel); 2922 // external relocation entries should always be external. 2923 isExtern = info->O->getPlainRelocationExternal(RE); 2924 if (isExtern) { 2925 symbol_iterator RelocSym = Reloc.getSymbol(); 2926 Symbol = *RelocSym; 2927 } 2928 reloc_found = true; 2929 break; 2930 } 2931 } 2932 if (reloc_found && isExtern) { 2933 // The Value passed in will be adjusted by the Pc if the instruction 2934 // adds the Pc. But for x86_64 external relocation entries the Value 2935 // is the offset from the external symbol. 2936 if (info->O->getAnyRelocationPCRel(RE)) 2937 op_info->Value -= Pc + InstSize; 2938 const char *name = 2939 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2940 op_info->AddSymbol.Present = 1; 2941 op_info->AddSymbol.Name = name; 2942 return 1; 2943 } 2944 return 0; 2945 } 2946 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2947 // for an entry for this section offset. 2948 uint64_t sect_addr = info->S.getAddress(); 2949 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2950 bool reloc_found = false; 2951 DataRefImpl Rel; 2952 MachO::any_relocation_info RE; 2953 bool isExtern = false; 2954 SymbolRef Symbol; 2955 for (const RelocationRef &Reloc : info->S.relocations()) { 2956 uint64_t RelocOffset = Reloc.getOffset(); 2957 if (RelocOffset == sect_offset) { 2958 Rel = Reloc.getRawDataRefImpl(); 2959 RE = info->O->getRelocation(Rel); 2960 // NOTE: Scattered relocations don't exist on x86_64. 2961 isExtern = info->O->getPlainRelocationExternal(RE); 2962 if (isExtern) { 2963 symbol_iterator RelocSym = Reloc.getSymbol(); 2964 Symbol = *RelocSym; 2965 } 2966 reloc_found = true; 2967 break; 2968 } 2969 } 2970 if (reloc_found && isExtern) { 2971 // The Value passed in will be adjusted by the Pc if the instruction 2972 // adds the Pc. But for x86_64 external relocation entries the Value 2973 // is the offset from the external symbol. 2974 if (info->O->getAnyRelocationPCRel(RE)) 2975 op_info->Value -= Pc + InstSize; 2976 const char *name = 2977 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2978 unsigned Type = info->O->getAnyRelocationType(RE); 2979 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2980 DataRefImpl RelNext = Rel; 2981 info->O->moveRelocationNext(RelNext); 2982 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2983 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2984 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2985 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2986 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2987 op_info->SubtractSymbol.Present = 1; 2988 op_info->SubtractSymbol.Name = name; 2989 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2990 Symbol = *RelocSymNext; 2991 name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2992 } 2993 } 2994 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 2995 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 2996 op_info->AddSymbol.Present = 1; 2997 op_info->AddSymbol.Name = name; 2998 return 1; 2999 } 3000 return 0; 3001 } 3002 if (Arch == Triple::arm) { 3003 if (Offset != 0 || (InstSize != 4 && InstSize != 2)) 3004 return 0; 3005 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 3006 // TODO: 3007 // Search the external relocation entries of a fully linked image 3008 // (if any) for an entry that matches this segment offset. 3009 // uint32_t seg_offset = (Pc + Offset); 3010 return 0; 3011 } 3012 // In MH_OBJECT filetypes search the section's relocation entries (if any) 3013 // for an entry for this section offset. 3014 uint32_t sect_addr = info->S.getAddress(); 3015 uint32_t sect_offset = (Pc + Offset) - sect_addr; 3016 DataRefImpl Rel; 3017 MachO::any_relocation_info RE; 3018 bool isExtern = false; 3019 SymbolRef Symbol; 3020 bool r_scattered = false; 3021 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 3022 auto Reloc = 3023 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 3024 uint64_t RelocOffset = Reloc.getOffset(); 3025 return RelocOffset == sect_offset; 3026 }); 3027 3028 if (Reloc == info->S.relocations().end()) 3029 return 0; 3030 3031 Rel = Reloc->getRawDataRefImpl(); 3032 RE = info->O->getRelocation(Rel); 3033 r_length = info->O->getAnyRelocationLength(RE); 3034 r_scattered = info->O->isRelocationScattered(RE); 3035 if (r_scattered) { 3036 r_value = info->O->getScatteredRelocationValue(RE); 3037 r_type = info->O->getScatteredRelocationType(RE); 3038 } else { 3039 r_type = info->O->getAnyRelocationType(RE); 3040 isExtern = info->O->getPlainRelocationExternal(RE); 3041 if (isExtern) { 3042 symbol_iterator RelocSym = Reloc->getSymbol(); 3043 Symbol = *RelocSym; 3044 } 3045 } 3046 if (r_type == MachO::ARM_RELOC_HALF || 3047 r_type == MachO::ARM_RELOC_SECTDIFF || 3048 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 3049 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 3050 DataRefImpl RelNext = Rel; 3051 info->O->moveRelocationNext(RelNext); 3052 MachO::any_relocation_info RENext; 3053 RENext = info->O->getRelocation(RelNext); 3054 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 3055 if (info->O->isRelocationScattered(RENext)) 3056 pair_r_value = info->O->getScatteredRelocationValue(RENext); 3057 } 3058 3059 if (isExtern) { 3060 const char *name = 3061 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 3062 op_info->AddSymbol.Present = 1; 3063 op_info->AddSymbol.Name = name; 3064 switch (r_type) { 3065 case MachO::ARM_RELOC_HALF: 3066 if ((r_length & 0x1) == 1) { 3067 op_info->Value = value << 16 | other_half; 3068 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 3069 } else { 3070 op_info->Value = other_half << 16 | value; 3071 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 3072 } 3073 break; 3074 default: 3075 break; 3076 } 3077 return 1; 3078 } 3079 // If we have a branch that is not an external relocation entry then 3080 // return 0 so the code in tryAddingSymbolicOperand() can use the 3081 // SymbolLookUp call back with the branch target address to look up the 3082 // symbol and possibility add an annotation for a symbol stub. 3083 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 3084 r_type == MachO::ARM_THUMB_RELOC_BR22)) 3085 return 0; 3086 3087 uint32_t offset = 0; 3088 if (r_type == MachO::ARM_RELOC_HALF || 3089 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 3090 if ((r_length & 0x1) == 1) 3091 value = value << 16 | other_half; 3092 else 3093 value = other_half << 16 | value; 3094 } 3095 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 3096 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 3097 offset = value - r_value; 3098 value = r_value; 3099 } 3100 3101 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 3102 if ((r_length & 0x1) == 1) 3103 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 3104 else 3105 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 3106 const char *add = GuessSymbolName(r_value, info->AddrMap); 3107 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 3108 int32_t offset = value - (r_value - pair_r_value); 3109 op_info->AddSymbol.Present = 1; 3110 if (add != nullptr) 3111 op_info->AddSymbol.Name = add; 3112 else 3113 op_info->AddSymbol.Value = r_value; 3114 op_info->SubtractSymbol.Present = 1; 3115 if (sub != nullptr) 3116 op_info->SubtractSymbol.Name = sub; 3117 else 3118 op_info->SubtractSymbol.Value = pair_r_value; 3119 op_info->Value = offset; 3120 return 1; 3121 } 3122 3123 op_info->AddSymbol.Present = 1; 3124 op_info->Value = offset; 3125 if (r_type == MachO::ARM_RELOC_HALF) { 3126 if ((r_length & 0x1) == 1) 3127 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 3128 else 3129 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 3130 } 3131 const char *add = GuessSymbolName(value, info->AddrMap); 3132 if (add != nullptr) { 3133 op_info->AddSymbol.Name = add; 3134 return 1; 3135 } 3136 op_info->AddSymbol.Value = value; 3137 return 1; 3138 } 3139 if (Arch == Triple::aarch64) { 3140 if (Offset != 0 || InstSize != 4) 3141 return 0; 3142 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 3143 // TODO: 3144 // Search the external relocation entries of a fully linked image 3145 // (if any) for an entry that matches this segment offset. 3146 // uint64_t seg_offset = (Pc + Offset); 3147 return 0; 3148 } 3149 // In MH_OBJECT filetypes search the section's relocation entries (if any) 3150 // for an entry for this section offset. 3151 uint64_t sect_addr = info->S.getAddress(); 3152 uint64_t sect_offset = (Pc + Offset) - sect_addr; 3153 auto Reloc = 3154 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 3155 uint64_t RelocOffset = Reloc.getOffset(); 3156 return RelocOffset == sect_offset; 3157 }); 3158 3159 if (Reloc == info->S.relocations().end()) 3160 return 0; 3161 3162 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 3163 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 3164 uint32_t r_type = info->O->getAnyRelocationType(RE); 3165 if (r_type == MachO::ARM64_RELOC_ADDEND) { 3166 DataRefImpl RelNext = Rel; 3167 info->O->moveRelocationNext(RelNext); 3168 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 3169 if (value == 0) { 3170 value = info->O->getPlainRelocationSymbolNum(RENext); 3171 op_info->Value = value; 3172 } 3173 } 3174 // NOTE: Scattered relocations don't exist on arm64. 3175 if (!info->O->getPlainRelocationExternal(RE)) 3176 return 0; 3177 const char *name = 3178 unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName()) 3179 .data(); 3180 op_info->AddSymbol.Present = 1; 3181 op_info->AddSymbol.Name = name; 3182 3183 switch (r_type) { 3184 case MachO::ARM64_RELOC_PAGE21: 3185 /* @page */ 3186 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 3187 break; 3188 case MachO::ARM64_RELOC_PAGEOFF12: 3189 /* @pageoff */ 3190 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 3191 break; 3192 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 3193 /* @gotpage */ 3194 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 3195 break; 3196 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 3197 /* @gotpageoff */ 3198 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 3199 break; 3200 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 3201 /* @tvlppage is not implemented in llvm-mc */ 3202 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 3203 break; 3204 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 3205 /* @tvlppageoff is not implemented in llvm-mc */ 3206 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 3207 break; 3208 default: 3209 case MachO::ARM64_RELOC_BRANCH26: 3210 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 3211 break; 3212 } 3213 return 1; 3214 } 3215 return 0; 3216 } 3217 3218 // GuessCstringPointer is passed the address of what might be a pointer to a 3219 // literal string in a cstring section. If that address is in a cstring section 3220 // it returns a pointer to that string. Else it returns nullptr. 3221 static const char *GuessCstringPointer(uint64_t ReferenceValue, 3222 struct DisassembleInfo *info) { 3223 for (const auto &Load : info->O->load_commands()) { 3224 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3225 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3226 for (unsigned J = 0; J < Seg.nsects; ++J) { 3227 MachO::section_64 Sec = info->O->getSection64(Load, J); 3228 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3229 if (section_type == MachO::S_CSTRING_LITERALS && 3230 ReferenceValue >= Sec.addr && 3231 ReferenceValue < Sec.addr + Sec.size) { 3232 uint64_t sect_offset = ReferenceValue - Sec.addr; 3233 uint64_t object_offset = Sec.offset + sect_offset; 3234 StringRef MachOContents = info->O->getData(); 3235 uint64_t object_size = MachOContents.size(); 3236 const char *object_addr = (const char *)MachOContents.data(); 3237 if (object_offset < object_size) { 3238 const char *name = object_addr + object_offset; 3239 return name; 3240 } else { 3241 return nullptr; 3242 } 3243 } 3244 } 3245 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3246 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3247 for (unsigned J = 0; J < Seg.nsects; ++J) { 3248 MachO::section Sec = info->O->getSection(Load, J); 3249 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3250 if (section_type == MachO::S_CSTRING_LITERALS && 3251 ReferenceValue >= Sec.addr && 3252 ReferenceValue < Sec.addr + Sec.size) { 3253 uint64_t sect_offset = ReferenceValue - Sec.addr; 3254 uint64_t object_offset = Sec.offset + sect_offset; 3255 StringRef MachOContents = info->O->getData(); 3256 uint64_t object_size = MachOContents.size(); 3257 const char *object_addr = (const char *)MachOContents.data(); 3258 if (object_offset < object_size) { 3259 const char *name = object_addr + object_offset; 3260 return name; 3261 } else { 3262 return nullptr; 3263 } 3264 } 3265 } 3266 } 3267 } 3268 return nullptr; 3269 } 3270 3271 // GuessIndirectSymbol returns the name of the indirect symbol for the 3272 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 3273 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 3274 // symbol name being referenced by the stub or pointer. 3275 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 3276 struct DisassembleInfo *info) { 3277 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 3278 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 3279 for (const auto &Load : info->O->load_commands()) { 3280 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3281 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3282 for (unsigned J = 0; J < Seg.nsects; ++J) { 3283 MachO::section_64 Sec = info->O->getSection64(Load, J); 3284 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3285 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3286 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3287 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3288 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3289 section_type == MachO::S_SYMBOL_STUBS) && 3290 ReferenceValue >= Sec.addr && 3291 ReferenceValue < Sec.addr + Sec.size) { 3292 uint32_t stride; 3293 if (section_type == MachO::S_SYMBOL_STUBS) 3294 stride = Sec.reserved2; 3295 else 3296 stride = 8; 3297 if (stride == 0) 3298 return nullptr; 3299 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3300 if (index < Dysymtab.nindirectsyms) { 3301 uint32_t indirect_symbol = 3302 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3303 if (indirect_symbol < Symtab.nsyms) { 3304 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3305 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3306 .data(); 3307 } 3308 } 3309 } 3310 } 3311 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3312 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3313 for (unsigned J = 0; J < Seg.nsects; ++J) { 3314 MachO::section Sec = info->O->getSection(Load, J); 3315 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3316 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3317 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3318 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3319 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3320 section_type == MachO::S_SYMBOL_STUBS) && 3321 ReferenceValue >= Sec.addr && 3322 ReferenceValue < Sec.addr + Sec.size) { 3323 uint32_t stride; 3324 if (section_type == MachO::S_SYMBOL_STUBS) 3325 stride = Sec.reserved2; 3326 else 3327 stride = 4; 3328 if (stride == 0) 3329 return nullptr; 3330 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3331 if (index < Dysymtab.nindirectsyms) { 3332 uint32_t indirect_symbol = 3333 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3334 if (indirect_symbol < Symtab.nsyms) { 3335 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3336 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3337 .data(); 3338 } 3339 } 3340 } 3341 } 3342 } 3343 } 3344 return nullptr; 3345 } 3346 3347 // method_reference() is called passing it the ReferenceName that might be 3348 // a reference it to an Objective-C method call. If so then it allocates and 3349 // assembles a method call string with the values last seen and saved in 3350 // the DisassembleInfo's class_name and selector_name fields. This is saved 3351 // into the method field of the info and any previous string is free'ed. 3352 // Then the class_name field in the info is set to nullptr. The method call 3353 // string is set into ReferenceName and ReferenceType is set to 3354 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 3355 // then both ReferenceType and ReferenceName are left unchanged. 3356 static void method_reference(struct DisassembleInfo *info, 3357 uint64_t *ReferenceType, 3358 const char **ReferenceName) { 3359 unsigned int Arch = info->O->getArch(); 3360 if (*ReferenceName != nullptr) { 3361 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 3362 if (info->selector_name != nullptr) { 3363 if (info->class_name != nullptr) { 3364 info->method = std::make_unique<char[]>( 3365 5 + strlen(info->class_name) + strlen(info->selector_name)); 3366 char *method = info->method.get(); 3367 if (method != nullptr) { 3368 strcpy(method, "+["); 3369 strcat(method, info->class_name); 3370 strcat(method, " "); 3371 strcat(method, info->selector_name); 3372 strcat(method, "]"); 3373 *ReferenceName = method; 3374 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3375 } 3376 } else { 3377 info->method = 3378 std::make_unique<char[]>(9 + strlen(info->selector_name)); 3379 char *method = info->method.get(); 3380 if (method != nullptr) { 3381 if (Arch == Triple::x86_64) 3382 strcpy(method, "-[%rdi "); 3383 else if (Arch == Triple::aarch64) 3384 strcpy(method, "-[x0 "); 3385 else 3386 strcpy(method, "-[r? "); 3387 strcat(method, info->selector_name); 3388 strcat(method, "]"); 3389 *ReferenceName = method; 3390 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3391 } 3392 } 3393 info->class_name = nullptr; 3394 } 3395 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 3396 if (info->selector_name != nullptr) { 3397 info->method = 3398 std::make_unique<char[]>(17 + strlen(info->selector_name)); 3399 char *method = info->method.get(); 3400 if (method != nullptr) { 3401 if (Arch == Triple::x86_64) 3402 strcpy(method, "-[[%rdi super] "); 3403 else if (Arch == Triple::aarch64) 3404 strcpy(method, "-[[x0 super] "); 3405 else 3406 strcpy(method, "-[[r? super] "); 3407 strcat(method, info->selector_name); 3408 strcat(method, "]"); 3409 *ReferenceName = method; 3410 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3411 } 3412 info->class_name = nullptr; 3413 } 3414 } 3415 } 3416 } 3417 3418 // GuessPointerPointer() is passed the address of what might be a pointer to 3419 // a reference to an Objective-C class, selector, message ref or cfstring. 3420 // If so the value of the pointer is returned and one of the booleans are set 3421 // to true. If not zero is returned and all the booleans are set to false. 3422 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 3423 struct DisassembleInfo *info, 3424 bool &classref, bool &selref, bool &msgref, 3425 bool &cfstring) { 3426 classref = false; 3427 selref = false; 3428 msgref = false; 3429 cfstring = false; 3430 for (const auto &Load : info->O->load_commands()) { 3431 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3432 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3433 for (unsigned J = 0; J < Seg.nsects; ++J) { 3434 MachO::section_64 Sec = info->O->getSection64(Load, J); 3435 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 3436 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3437 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 3438 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 3439 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 3440 ReferenceValue >= Sec.addr && 3441 ReferenceValue < Sec.addr + Sec.size) { 3442 uint64_t sect_offset = ReferenceValue - Sec.addr; 3443 uint64_t object_offset = Sec.offset + sect_offset; 3444 StringRef MachOContents = info->O->getData(); 3445 uint64_t object_size = MachOContents.size(); 3446 const char *object_addr = (const char *)MachOContents.data(); 3447 if (object_offset < object_size) { 3448 uint64_t pointer_value; 3449 memcpy(&pointer_value, object_addr + object_offset, 3450 sizeof(uint64_t)); 3451 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3452 sys::swapByteOrder(pointer_value); 3453 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 3454 selref = true; 3455 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3456 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 3457 classref = true; 3458 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 3459 ReferenceValue + 8 < Sec.addr + Sec.size) { 3460 msgref = true; 3461 memcpy(&pointer_value, object_addr + object_offset + 8, 3462 sizeof(uint64_t)); 3463 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3464 sys::swapByteOrder(pointer_value); 3465 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 3466 cfstring = true; 3467 return pointer_value; 3468 } else { 3469 return 0; 3470 } 3471 } 3472 } 3473 } 3474 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 3475 } 3476 return 0; 3477 } 3478 3479 // get_pointer_64 returns a pointer to the bytes in the object file at the 3480 // Address from a section in the Mach-O file. And indirectly returns the 3481 // offset into the section, number of bytes left in the section past the offset 3482 // and which section is was being referenced. If the Address is not in a 3483 // section nullptr is returned. 3484 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 3485 uint32_t &left, SectionRef &S, 3486 DisassembleInfo *info, 3487 bool objc_only = false) { 3488 offset = 0; 3489 left = 0; 3490 S = SectionRef(); 3491 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 3492 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 3493 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 3494 if (SectSize == 0) 3495 continue; 3496 if (objc_only) { 3497 StringRef SectName; 3498 Expected<StringRef> SecNameOrErr = 3499 ((*(info->Sections))[SectIdx]).getName(); 3500 if (SecNameOrErr) 3501 SectName = *SecNameOrErr; 3502 else 3503 consumeError(SecNameOrErr.takeError()); 3504 3505 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 3506 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 3507 if (SegName != "__OBJC" && SectName != "__cstring") 3508 continue; 3509 } 3510 if (Address >= SectAddress && Address < SectAddress + SectSize) { 3511 S = (*(info->Sections))[SectIdx]; 3512 offset = Address - SectAddress; 3513 left = SectSize - offset; 3514 StringRef SectContents = unwrapOrError( 3515 ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName()); 3516 return SectContents.data() + offset; 3517 } 3518 } 3519 return nullptr; 3520 } 3521 3522 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 3523 uint32_t &left, SectionRef &S, 3524 DisassembleInfo *info, 3525 bool objc_only = false) { 3526 return get_pointer_64(Address, offset, left, S, info, objc_only); 3527 } 3528 3529 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 3530 // the symbol indirectly through n_value. Based on the relocation information 3531 // for the specified section offset in the specified section reference. 3532 // If no relocation information is found and a non-zero ReferenceValue for the 3533 // symbol is passed, look up that address in the info's AddrMap. 3534 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 3535 DisassembleInfo *info, uint64_t &n_value, 3536 uint64_t ReferenceValue = 0) { 3537 n_value = 0; 3538 if (!info->verbose) 3539 return nullptr; 3540 3541 // See if there is an external relocation entry at the sect_offset. 3542 bool reloc_found = false; 3543 DataRefImpl Rel; 3544 MachO::any_relocation_info RE; 3545 bool isExtern = false; 3546 SymbolRef Symbol; 3547 for (const RelocationRef &Reloc : S.relocations()) { 3548 uint64_t RelocOffset = Reloc.getOffset(); 3549 if (RelocOffset == sect_offset) { 3550 Rel = Reloc.getRawDataRefImpl(); 3551 RE = info->O->getRelocation(Rel); 3552 if (info->O->isRelocationScattered(RE)) 3553 continue; 3554 isExtern = info->O->getPlainRelocationExternal(RE); 3555 if (isExtern) { 3556 symbol_iterator RelocSym = Reloc.getSymbol(); 3557 Symbol = *RelocSym; 3558 } 3559 reloc_found = true; 3560 break; 3561 } 3562 } 3563 // If there is an external relocation entry for a symbol in this section 3564 // at this section_offset then use that symbol's value for the n_value 3565 // and return its name. 3566 const char *SymbolName = nullptr; 3567 if (reloc_found && isExtern) { 3568 n_value = cantFail(Symbol.getValue()); 3569 StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName()); 3570 if (!Name.empty()) { 3571 SymbolName = Name.data(); 3572 return SymbolName; 3573 } 3574 } 3575 3576 // TODO: For fully linked images, look through the external relocation 3577 // entries off the dynamic symtab command. For these the r_offset is from the 3578 // start of the first writeable segment in the Mach-O file. So the offset 3579 // to this section from that segment is passed to this routine by the caller, 3580 // as the database_offset. Which is the difference of the section's starting 3581 // address and the first writable segment. 3582 // 3583 // NOTE: need add passing the database_offset to this routine. 3584 3585 // We did not find an external relocation entry so look up the ReferenceValue 3586 // as an address of a symbol and if found return that symbol's name. 3587 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 3588 3589 return SymbolName; 3590 } 3591 3592 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 3593 DisassembleInfo *info, 3594 uint32_t ReferenceValue) { 3595 uint64_t n_value64; 3596 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 3597 } 3598 3599 namespace { 3600 3601 // These are structs in the Objective-C meta data and read to produce the 3602 // comments for disassembly. While these are part of the ABI they are no 3603 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 3604 // . 3605 3606 // The cfstring object in a 64-bit Mach-O file. 3607 struct cfstring64_t { 3608 uint64_t isa; // class64_t * (64-bit pointer) 3609 uint64_t flags; // flag bits 3610 uint64_t characters; // char * (64-bit pointer) 3611 uint64_t length; // number of non-NULL characters in above 3612 }; 3613 3614 // The class object in a 64-bit Mach-O file. 3615 struct class64_t { 3616 uint64_t isa; // class64_t * (64-bit pointer) 3617 uint64_t superclass; // class64_t * (64-bit pointer) 3618 uint64_t cache; // Cache (64-bit pointer) 3619 uint64_t vtable; // IMP * (64-bit pointer) 3620 uint64_t data; // class_ro64_t * (64-bit pointer) 3621 }; 3622 3623 struct class32_t { 3624 uint32_t isa; /* class32_t * (32-bit pointer) */ 3625 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3626 uint32_t cache; /* Cache (32-bit pointer) */ 3627 uint32_t vtable; /* IMP * (32-bit pointer) */ 3628 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3629 }; 3630 3631 struct class_ro64_t { 3632 uint32_t flags; 3633 uint32_t instanceStart; 3634 uint32_t instanceSize; 3635 uint32_t reserved; 3636 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3637 uint64_t name; // const char * (64-bit pointer) 3638 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3639 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3640 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3641 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3642 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3643 }; 3644 3645 struct class_ro32_t { 3646 uint32_t flags; 3647 uint32_t instanceStart; 3648 uint32_t instanceSize; 3649 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3650 uint32_t name; /* const char * (32-bit pointer) */ 3651 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3652 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3653 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3654 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3655 uint32_t baseProperties; /* const struct objc_property_list * 3656 (32-bit pointer) */ 3657 }; 3658 3659 /* Values for class_ro{64,32}_t->flags */ 3660 #define RO_META (1 << 0) 3661 #define RO_ROOT (1 << 1) 3662 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3663 3664 /* Values for method_list{64,32}_t->entsize */ 3665 #define ML_HAS_RELATIVE_PTRS (1 << 31) 3666 #define ML_ENTSIZE_MASK 0xFFFF 3667 3668 struct method_list64_t { 3669 uint32_t entsize; 3670 uint32_t count; 3671 /* struct method64_t first; These structures follow inline */ 3672 }; 3673 3674 struct method_list32_t { 3675 uint32_t entsize; 3676 uint32_t count; 3677 /* struct method32_t first; These structures follow inline */ 3678 }; 3679 3680 struct method64_t { 3681 uint64_t name; /* SEL (64-bit pointer) */ 3682 uint64_t types; /* const char * (64-bit pointer) */ 3683 uint64_t imp; /* IMP (64-bit pointer) */ 3684 }; 3685 3686 struct method32_t { 3687 uint32_t name; /* SEL (32-bit pointer) */ 3688 uint32_t types; /* const char * (32-bit pointer) */ 3689 uint32_t imp; /* IMP (32-bit pointer) */ 3690 }; 3691 3692 struct method_relative_t { 3693 int32_t name; /* SEL (32-bit relative) */ 3694 int32_t types; /* const char * (32-bit relative) */ 3695 int32_t imp; /* IMP (32-bit relative) */ 3696 }; 3697 3698 struct protocol_list64_t { 3699 uint64_t count; /* uintptr_t (a 64-bit value) */ 3700 /* struct protocol64_t * list[0]; These pointers follow inline */ 3701 }; 3702 3703 struct protocol_list32_t { 3704 uint32_t count; /* uintptr_t (a 32-bit value) */ 3705 /* struct protocol32_t * list[0]; These pointers follow inline */ 3706 }; 3707 3708 struct protocol64_t { 3709 uint64_t isa; /* id * (64-bit pointer) */ 3710 uint64_t name; /* const char * (64-bit pointer) */ 3711 uint64_t protocols; /* struct protocol_list64_t * 3712 (64-bit pointer) */ 3713 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3714 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3715 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3716 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3717 uint64_t instanceProperties; /* struct objc_property_list * 3718 (64-bit pointer) */ 3719 }; 3720 3721 struct protocol32_t { 3722 uint32_t isa; /* id * (32-bit pointer) */ 3723 uint32_t name; /* const char * (32-bit pointer) */ 3724 uint32_t protocols; /* struct protocol_list_t * 3725 (32-bit pointer) */ 3726 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3727 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3728 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3729 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3730 uint32_t instanceProperties; /* struct objc_property_list * 3731 (32-bit pointer) */ 3732 }; 3733 3734 struct ivar_list64_t { 3735 uint32_t entsize; 3736 uint32_t count; 3737 /* struct ivar64_t first; These structures follow inline */ 3738 }; 3739 3740 struct ivar_list32_t { 3741 uint32_t entsize; 3742 uint32_t count; 3743 /* struct ivar32_t first; These structures follow inline */ 3744 }; 3745 3746 struct ivar64_t { 3747 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3748 uint64_t name; /* const char * (64-bit pointer) */ 3749 uint64_t type; /* const char * (64-bit pointer) */ 3750 uint32_t alignment; 3751 uint32_t size; 3752 }; 3753 3754 struct ivar32_t { 3755 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3756 uint32_t name; /* const char * (32-bit pointer) */ 3757 uint32_t type; /* const char * (32-bit pointer) */ 3758 uint32_t alignment; 3759 uint32_t size; 3760 }; 3761 3762 struct objc_property_list64 { 3763 uint32_t entsize; 3764 uint32_t count; 3765 /* struct objc_property64 first; These structures follow inline */ 3766 }; 3767 3768 struct objc_property_list32 { 3769 uint32_t entsize; 3770 uint32_t count; 3771 /* struct objc_property32 first; These structures follow inline */ 3772 }; 3773 3774 struct objc_property64 { 3775 uint64_t name; /* const char * (64-bit pointer) */ 3776 uint64_t attributes; /* const char * (64-bit pointer) */ 3777 }; 3778 3779 struct objc_property32 { 3780 uint32_t name; /* const char * (32-bit pointer) */ 3781 uint32_t attributes; /* const char * (32-bit pointer) */ 3782 }; 3783 3784 struct category64_t { 3785 uint64_t name; /* const char * (64-bit pointer) */ 3786 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3787 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3788 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3789 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3790 uint64_t instanceProperties; /* struct objc_property_list * 3791 (64-bit pointer) */ 3792 }; 3793 3794 struct category32_t { 3795 uint32_t name; /* const char * (32-bit pointer) */ 3796 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3797 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3798 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3799 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3800 uint32_t instanceProperties; /* struct objc_property_list * 3801 (32-bit pointer) */ 3802 }; 3803 3804 struct objc_image_info64 { 3805 uint32_t version; 3806 uint32_t flags; 3807 }; 3808 struct objc_image_info32 { 3809 uint32_t version; 3810 uint32_t flags; 3811 }; 3812 struct imageInfo_t { 3813 uint32_t version; 3814 uint32_t flags; 3815 }; 3816 /* masks for objc_image_info.flags */ 3817 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3818 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3819 #define OBJC_IMAGE_IS_SIMULATED (1 << 5) 3820 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6) 3821 3822 struct message_ref64 { 3823 uint64_t imp; /* IMP (64-bit pointer) */ 3824 uint64_t sel; /* SEL (64-bit pointer) */ 3825 }; 3826 3827 struct message_ref32 { 3828 uint32_t imp; /* IMP (32-bit pointer) */ 3829 uint32_t sel; /* SEL (32-bit pointer) */ 3830 }; 3831 3832 // Objective-C 1 (32-bit only) meta data structs. 3833 3834 struct objc_module_t { 3835 uint32_t version; 3836 uint32_t size; 3837 uint32_t name; /* char * (32-bit pointer) */ 3838 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3839 }; 3840 3841 struct objc_symtab_t { 3842 uint32_t sel_ref_cnt; 3843 uint32_t refs; /* SEL * (32-bit pointer) */ 3844 uint16_t cls_def_cnt; 3845 uint16_t cat_def_cnt; 3846 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3847 }; 3848 3849 struct objc_class_t { 3850 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3851 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3852 uint32_t name; /* const char * (32-bit pointer) */ 3853 int32_t version; 3854 int32_t info; 3855 int32_t instance_size; 3856 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3857 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3858 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3859 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3860 }; 3861 3862 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3863 // class is not a metaclass 3864 #define CLS_CLASS 0x1 3865 // class is a metaclass 3866 #define CLS_META 0x2 3867 3868 struct objc_category_t { 3869 uint32_t category_name; /* char * (32-bit pointer) */ 3870 uint32_t class_name; /* char * (32-bit pointer) */ 3871 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3872 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3873 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3874 }; 3875 3876 struct objc_ivar_t { 3877 uint32_t ivar_name; /* char * (32-bit pointer) */ 3878 uint32_t ivar_type; /* char * (32-bit pointer) */ 3879 int32_t ivar_offset; 3880 }; 3881 3882 struct objc_ivar_list_t { 3883 int32_t ivar_count; 3884 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3885 }; 3886 3887 struct objc_method_list_t { 3888 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3889 int32_t method_count; 3890 // struct objc_method_t method_list[1]; /* variable length structure */ 3891 }; 3892 3893 struct objc_method_t { 3894 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3895 uint32_t method_types; /* char * (32-bit pointer) */ 3896 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3897 (32-bit pointer) */ 3898 }; 3899 3900 struct objc_protocol_list_t { 3901 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3902 int32_t count; 3903 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3904 // (32-bit pointer) */ 3905 }; 3906 3907 struct objc_protocol_t { 3908 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3909 uint32_t protocol_name; /* char * (32-bit pointer) */ 3910 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3911 uint32_t instance_methods; /* struct objc_method_description_list * 3912 (32-bit pointer) */ 3913 uint32_t class_methods; /* struct objc_method_description_list * 3914 (32-bit pointer) */ 3915 }; 3916 3917 struct objc_method_description_list_t { 3918 int32_t count; 3919 // struct objc_method_description_t list[1]; 3920 }; 3921 3922 struct objc_method_description_t { 3923 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3924 uint32_t types; /* char * (32-bit pointer) */ 3925 }; 3926 3927 inline void swapStruct(struct cfstring64_t &cfs) { 3928 sys::swapByteOrder(cfs.isa); 3929 sys::swapByteOrder(cfs.flags); 3930 sys::swapByteOrder(cfs.characters); 3931 sys::swapByteOrder(cfs.length); 3932 } 3933 3934 inline void swapStruct(struct class64_t &c) { 3935 sys::swapByteOrder(c.isa); 3936 sys::swapByteOrder(c.superclass); 3937 sys::swapByteOrder(c.cache); 3938 sys::swapByteOrder(c.vtable); 3939 sys::swapByteOrder(c.data); 3940 } 3941 3942 inline void swapStruct(struct class32_t &c) { 3943 sys::swapByteOrder(c.isa); 3944 sys::swapByteOrder(c.superclass); 3945 sys::swapByteOrder(c.cache); 3946 sys::swapByteOrder(c.vtable); 3947 sys::swapByteOrder(c.data); 3948 } 3949 3950 inline void swapStruct(struct class_ro64_t &cro) { 3951 sys::swapByteOrder(cro.flags); 3952 sys::swapByteOrder(cro.instanceStart); 3953 sys::swapByteOrder(cro.instanceSize); 3954 sys::swapByteOrder(cro.reserved); 3955 sys::swapByteOrder(cro.ivarLayout); 3956 sys::swapByteOrder(cro.name); 3957 sys::swapByteOrder(cro.baseMethods); 3958 sys::swapByteOrder(cro.baseProtocols); 3959 sys::swapByteOrder(cro.ivars); 3960 sys::swapByteOrder(cro.weakIvarLayout); 3961 sys::swapByteOrder(cro.baseProperties); 3962 } 3963 3964 inline void swapStruct(struct class_ro32_t &cro) { 3965 sys::swapByteOrder(cro.flags); 3966 sys::swapByteOrder(cro.instanceStart); 3967 sys::swapByteOrder(cro.instanceSize); 3968 sys::swapByteOrder(cro.ivarLayout); 3969 sys::swapByteOrder(cro.name); 3970 sys::swapByteOrder(cro.baseMethods); 3971 sys::swapByteOrder(cro.baseProtocols); 3972 sys::swapByteOrder(cro.ivars); 3973 sys::swapByteOrder(cro.weakIvarLayout); 3974 sys::swapByteOrder(cro.baseProperties); 3975 } 3976 3977 inline void swapStruct(struct method_list64_t &ml) { 3978 sys::swapByteOrder(ml.entsize); 3979 sys::swapByteOrder(ml.count); 3980 } 3981 3982 inline void swapStruct(struct method_list32_t &ml) { 3983 sys::swapByteOrder(ml.entsize); 3984 sys::swapByteOrder(ml.count); 3985 } 3986 3987 inline void swapStruct(struct method64_t &m) { 3988 sys::swapByteOrder(m.name); 3989 sys::swapByteOrder(m.types); 3990 sys::swapByteOrder(m.imp); 3991 } 3992 3993 inline void swapStruct(struct method32_t &m) { 3994 sys::swapByteOrder(m.name); 3995 sys::swapByteOrder(m.types); 3996 sys::swapByteOrder(m.imp); 3997 } 3998 3999 inline void swapStruct(struct method_relative_t &m) { 4000 sys::swapByteOrder(m.name); 4001 sys::swapByteOrder(m.types); 4002 sys::swapByteOrder(m.imp); 4003 } 4004 4005 inline void swapStruct(struct protocol_list64_t &pl) { 4006 sys::swapByteOrder(pl.count); 4007 } 4008 4009 inline void swapStruct(struct protocol_list32_t &pl) { 4010 sys::swapByteOrder(pl.count); 4011 } 4012 4013 inline void swapStruct(struct protocol64_t &p) { 4014 sys::swapByteOrder(p.isa); 4015 sys::swapByteOrder(p.name); 4016 sys::swapByteOrder(p.protocols); 4017 sys::swapByteOrder(p.instanceMethods); 4018 sys::swapByteOrder(p.classMethods); 4019 sys::swapByteOrder(p.optionalInstanceMethods); 4020 sys::swapByteOrder(p.optionalClassMethods); 4021 sys::swapByteOrder(p.instanceProperties); 4022 } 4023 4024 inline void swapStruct(struct protocol32_t &p) { 4025 sys::swapByteOrder(p.isa); 4026 sys::swapByteOrder(p.name); 4027 sys::swapByteOrder(p.protocols); 4028 sys::swapByteOrder(p.instanceMethods); 4029 sys::swapByteOrder(p.classMethods); 4030 sys::swapByteOrder(p.optionalInstanceMethods); 4031 sys::swapByteOrder(p.optionalClassMethods); 4032 sys::swapByteOrder(p.instanceProperties); 4033 } 4034 4035 inline void swapStruct(struct ivar_list64_t &il) { 4036 sys::swapByteOrder(il.entsize); 4037 sys::swapByteOrder(il.count); 4038 } 4039 4040 inline void swapStruct(struct ivar_list32_t &il) { 4041 sys::swapByteOrder(il.entsize); 4042 sys::swapByteOrder(il.count); 4043 } 4044 4045 inline void swapStruct(struct ivar64_t &i) { 4046 sys::swapByteOrder(i.offset); 4047 sys::swapByteOrder(i.name); 4048 sys::swapByteOrder(i.type); 4049 sys::swapByteOrder(i.alignment); 4050 sys::swapByteOrder(i.size); 4051 } 4052 4053 inline void swapStruct(struct ivar32_t &i) { 4054 sys::swapByteOrder(i.offset); 4055 sys::swapByteOrder(i.name); 4056 sys::swapByteOrder(i.type); 4057 sys::swapByteOrder(i.alignment); 4058 sys::swapByteOrder(i.size); 4059 } 4060 4061 inline void swapStruct(struct objc_property_list64 &pl) { 4062 sys::swapByteOrder(pl.entsize); 4063 sys::swapByteOrder(pl.count); 4064 } 4065 4066 inline void swapStruct(struct objc_property_list32 &pl) { 4067 sys::swapByteOrder(pl.entsize); 4068 sys::swapByteOrder(pl.count); 4069 } 4070 4071 inline void swapStruct(struct objc_property64 &op) { 4072 sys::swapByteOrder(op.name); 4073 sys::swapByteOrder(op.attributes); 4074 } 4075 4076 inline void swapStruct(struct objc_property32 &op) { 4077 sys::swapByteOrder(op.name); 4078 sys::swapByteOrder(op.attributes); 4079 } 4080 4081 inline void swapStruct(struct category64_t &c) { 4082 sys::swapByteOrder(c.name); 4083 sys::swapByteOrder(c.cls); 4084 sys::swapByteOrder(c.instanceMethods); 4085 sys::swapByteOrder(c.classMethods); 4086 sys::swapByteOrder(c.protocols); 4087 sys::swapByteOrder(c.instanceProperties); 4088 } 4089 4090 inline void swapStruct(struct category32_t &c) { 4091 sys::swapByteOrder(c.name); 4092 sys::swapByteOrder(c.cls); 4093 sys::swapByteOrder(c.instanceMethods); 4094 sys::swapByteOrder(c.classMethods); 4095 sys::swapByteOrder(c.protocols); 4096 sys::swapByteOrder(c.instanceProperties); 4097 } 4098 4099 inline void swapStruct(struct objc_image_info64 &o) { 4100 sys::swapByteOrder(o.version); 4101 sys::swapByteOrder(o.flags); 4102 } 4103 4104 inline void swapStruct(struct objc_image_info32 &o) { 4105 sys::swapByteOrder(o.version); 4106 sys::swapByteOrder(o.flags); 4107 } 4108 4109 inline void swapStruct(struct imageInfo_t &o) { 4110 sys::swapByteOrder(o.version); 4111 sys::swapByteOrder(o.flags); 4112 } 4113 4114 inline void swapStruct(struct message_ref64 &mr) { 4115 sys::swapByteOrder(mr.imp); 4116 sys::swapByteOrder(mr.sel); 4117 } 4118 4119 inline void swapStruct(struct message_ref32 &mr) { 4120 sys::swapByteOrder(mr.imp); 4121 sys::swapByteOrder(mr.sel); 4122 } 4123 4124 inline void swapStruct(struct objc_module_t &module) { 4125 sys::swapByteOrder(module.version); 4126 sys::swapByteOrder(module.size); 4127 sys::swapByteOrder(module.name); 4128 sys::swapByteOrder(module.symtab); 4129 } 4130 4131 inline void swapStruct(struct objc_symtab_t &symtab) { 4132 sys::swapByteOrder(symtab.sel_ref_cnt); 4133 sys::swapByteOrder(symtab.refs); 4134 sys::swapByteOrder(symtab.cls_def_cnt); 4135 sys::swapByteOrder(symtab.cat_def_cnt); 4136 } 4137 4138 inline void swapStruct(struct objc_class_t &objc_class) { 4139 sys::swapByteOrder(objc_class.isa); 4140 sys::swapByteOrder(objc_class.super_class); 4141 sys::swapByteOrder(objc_class.name); 4142 sys::swapByteOrder(objc_class.version); 4143 sys::swapByteOrder(objc_class.info); 4144 sys::swapByteOrder(objc_class.instance_size); 4145 sys::swapByteOrder(objc_class.ivars); 4146 sys::swapByteOrder(objc_class.methodLists); 4147 sys::swapByteOrder(objc_class.cache); 4148 sys::swapByteOrder(objc_class.protocols); 4149 } 4150 4151 inline void swapStruct(struct objc_category_t &objc_category) { 4152 sys::swapByteOrder(objc_category.category_name); 4153 sys::swapByteOrder(objc_category.class_name); 4154 sys::swapByteOrder(objc_category.instance_methods); 4155 sys::swapByteOrder(objc_category.class_methods); 4156 sys::swapByteOrder(objc_category.protocols); 4157 } 4158 4159 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 4160 sys::swapByteOrder(objc_ivar_list.ivar_count); 4161 } 4162 4163 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 4164 sys::swapByteOrder(objc_ivar.ivar_name); 4165 sys::swapByteOrder(objc_ivar.ivar_type); 4166 sys::swapByteOrder(objc_ivar.ivar_offset); 4167 } 4168 4169 inline void swapStruct(struct objc_method_list_t &method_list) { 4170 sys::swapByteOrder(method_list.obsolete); 4171 sys::swapByteOrder(method_list.method_count); 4172 } 4173 4174 inline void swapStruct(struct objc_method_t &method) { 4175 sys::swapByteOrder(method.method_name); 4176 sys::swapByteOrder(method.method_types); 4177 sys::swapByteOrder(method.method_imp); 4178 } 4179 4180 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 4181 sys::swapByteOrder(protocol_list.next); 4182 sys::swapByteOrder(protocol_list.count); 4183 } 4184 4185 inline void swapStruct(struct objc_protocol_t &protocol) { 4186 sys::swapByteOrder(protocol.isa); 4187 sys::swapByteOrder(protocol.protocol_name); 4188 sys::swapByteOrder(protocol.protocol_list); 4189 sys::swapByteOrder(protocol.instance_methods); 4190 sys::swapByteOrder(protocol.class_methods); 4191 } 4192 4193 inline void swapStruct(struct objc_method_description_list_t &mdl) { 4194 sys::swapByteOrder(mdl.count); 4195 } 4196 4197 inline void swapStruct(struct objc_method_description_t &md) { 4198 sys::swapByteOrder(md.name); 4199 sys::swapByteOrder(md.types); 4200 } 4201 4202 } // namespace 4203 4204 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 4205 struct DisassembleInfo *info); 4206 4207 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 4208 // to an Objective-C class and returns the class name. It is also passed the 4209 // address of the pointer, so when the pointer is zero as it can be in an .o 4210 // file, that is used to look for an external relocation entry with a symbol 4211 // name. 4212 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 4213 uint64_t ReferenceValue, 4214 struct DisassembleInfo *info) { 4215 const char *r; 4216 uint32_t offset, left; 4217 SectionRef S; 4218 4219 // The pointer_value can be 0 in an object file and have a relocation 4220 // entry for the class symbol at the ReferenceValue (the address of the 4221 // pointer). 4222 if (pointer_value == 0) { 4223 r = get_pointer_64(ReferenceValue, offset, left, S, info); 4224 if (r == nullptr || left < sizeof(uint64_t)) 4225 return nullptr; 4226 uint64_t n_value; 4227 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 4228 if (symbol_name == nullptr) 4229 return nullptr; 4230 const char *class_name = strrchr(symbol_name, '$'); 4231 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 4232 return class_name + 2; 4233 else 4234 return nullptr; 4235 } 4236 4237 // The case were the pointer_value is non-zero and points to a class defined 4238 // in this Mach-O file. 4239 r = get_pointer_64(pointer_value, offset, left, S, info); 4240 if (r == nullptr || left < sizeof(struct class64_t)) 4241 return nullptr; 4242 struct class64_t c; 4243 memcpy(&c, r, sizeof(struct class64_t)); 4244 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4245 swapStruct(c); 4246 if (c.data == 0) 4247 return nullptr; 4248 r = get_pointer_64(c.data, offset, left, S, info); 4249 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4250 return nullptr; 4251 struct class_ro64_t cro; 4252 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4253 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4254 swapStruct(cro); 4255 if (cro.name == 0) 4256 return nullptr; 4257 const char *name = get_pointer_64(cro.name, offset, left, S, info); 4258 return name; 4259 } 4260 4261 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 4262 // pointer to a cfstring and returns its name or nullptr. 4263 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 4264 struct DisassembleInfo *info) { 4265 const char *r, *name; 4266 uint32_t offset, left; 4267 SectionRef S; 4268 struct cfstring64_t cfs; 4269 uint64_t cfs_characters; 4270 4271 r = get_pointer_64(ReferenceValue, offset, left, S, info); 4272 if (r == nullptr || left < sizeof(struct cfstring64_t)) 4273 return nullptr; 4274 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 4275 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4276 swapStruct(cfs); 4277 if (cfs.characters == 0) { 4278 uint64_t n_value; 4279 const char *symbol_name = get_symbol_64( 4280 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 4281 if (symbol_name == nullptr) 4282 return nullptr; 4283 cfs_characters = n_value; 4284 } else 4285 cfs_characters = cfs.characters; 4286 name = get_pointer_64(cfs_characters, offset, left, S, info); 4287 4288 return name; 4289 } 4290 4291 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 4292 // of a pointer to an Objective-C selector reference when the pointer value is 4293 // zero as in a .o file and is likely to have a external relocation entry with 4294 // who's symbol's n_value is the real pointer to the selector name. If that is 4295 // the case the real pointer to the selector name is returned else 0 is 4296 // returned 4297 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 4298 struct DisassembleInfo *info) { 4299 uint32_t offset, left; 4300 SectionRef S; 4301 4302 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 4303 if (r == nullptr || left < sizeof(uint64_t)) 4304 return 0; 4305 uint64_t n_value; 4306 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 4307 if (symbol_name == nullptr) 4308 return 0; 4309 return n_value; 4310 } 4311 4312 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 4313 const char *sectname) { 4314 for (const SectionRef &Section : O->sections()) { 4315 StringRef SectName; 4316 Expected<StringRef> SecNameOrErr = Section.getName(); 4317 if (SecNameOrErr) 4318 SectName = *SecNameOrErr; 4319 else 4320 consumeError(SecNameOrErr.takeError()); 4321 4322 DataRefImpl Ref = Section.getRawDataRefImpl(); 4323 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4324 if (SegName == segname && SectName == sectname) 4325 return Section; 4326 } 4327 return SectionRef(); 4328 } 4329 4330 static void 4331 walk_pointer_list_64(const char *listname, const SectionRef S, 4332 MachOObjectFile *O, struct DisassembleInfo *info, 4333 void (*func)(uint64_t, struct DisassembleInfo *info)) { 4334 if (S == SectionRef()) 4335 return; 4336 4337 StringRef SectName; 4338 Expected<StringRef> SecNameOrErr = S.getName(); 4339 if (SecNameOrErr) 4340 SectName = *SecNameOrErr; 4341 else 4342 consumeError(SecNameOrErr.takeError()); 4343 4344 DataRefImpl Ref = S.getRawDataRefImpl(); 4345 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4346 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4347 4348 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4349 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4350 4351 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 4352 uint32_t left = S.getSize() - i; 4353 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 4354 uint64_t p = 0; 4355 memcpy(&p, Contents + i, size); 4356 if (i + sizeof(uint64_t) > S.getSize()) 4357 outs() << listname << " list pointer extends past end of (" << SegName 4358 << "," << SectName << ") section\n"; 4359 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 4360 4361 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4362 sys::swapByteOrder(p); 4363 4364 uint64_t n_value = 0; 4365 const char *name = get_symbol_64(i, S, info, n_value, p); 4366 if (name == nullptr) 4367 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 4368 4369 if (n_value != 0) { 4370 outs() << format("0x%" PRIx64, n_value); 4371 if (p != 0) 4372 outs() << " + " << format("0x%" PRIx64, p); 4373 } else 4374 outs() << format("0x%" PRIx64, p); 4375 if (name != nullptr) 4376 outs() << " " << name; 4377 outs() << "\n"; 4378 4379 p += n_value; 4380 if (func) 4381 func(p, info); 4382 } 4383 } 4384 4385 static void 4386 walk_pointer_list_32(const char *listname, const SectionRef S, 4387 MachOObjectFile *O, struct DisassembleInfo *info, 4388 void (*func)(uint32_t, struct DisassembleInfo *info)) { 4389 if (S == SectionRef()) 4390 return; 4391 4392 StringRef SectName = unwrapOrError(S.getName(), O->getFileName()); 4393 DataRefImpl Ref = S.getRawDataRefImpl(); 4394 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4395 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4396 4397 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4398 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4399 4400 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 4401 uint32_t left = S.getSize() - i; 4402 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 4403 uint32_t p = 0; 4404 memcpy(&p, Contents + i, size); 4405 if (i + sizeof(uint32_t) > S.getSize()) 4406 outs() << listname << " list pointer extends past end of (" << SegName 4407 << "," << SectName << ") section\n"; 4408 uint32_t Address = S.getAddress() + i; 4409 outs() << format("%08" PRIx32, Address) << " "; 4410 4411 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4412 sys::swapByteOrder(p); 4413 outs() << format("0x%" PRIx32, p); 4414 4415 const char *name = get_symbol_32(i, S, info, p); 4416 if (name != nullptr) 4417 outs() << " " << name; 4418 outs() << "\n"; 4419 4420 if (func) 4421 func(p, info); 4422 } 4423 } 4424 4425 static void print_layout_map(const char *layout_map, uint32_t left) { 4426 if (layout_map == nullptr) 4427 return; 4428 outs() << " layout map: "; 4429 do { 4430 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 4431 left--; 4432 layout_map++; 4433 } while (*layout_map != '\0' && left != 0); 4434 outs() << "\n"; 4435 } 4436 4437 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 4438 uint32_t offset, left; 4439 SectionRef S; 4440 const char *layout_map; 4441 4442 if (p == 0) 4443 return; 4444 layout_map = get_pointer_64(p, offset, left, S, info); 4445 print_layout_map(layout_map, left); 4446 } 4447 4448 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 4449 uint32_t offset, left; 4450 SectionRef S; 4451 const char *layout_map; 4452 4453 if (p == 0) 4454 return; 4455 layout_map = get_pointer_32(p, offset, left, S, info); 4456 print_layout_map(layout_map, left); 4457 } 4458 4459 static void print_relative_method_list(uint32_t structSizeAndFlags, 4460 uint32_t structCount, uint64_t p, 4461 struct DisassembleInfo *info, 4462 const char *indent, 4463 uint32_t pointerBits) { 4464 struct method_relative_t m; 4465 const char *r, *name; 4466 uint32_t offset, xoffset, left, i; 4467 SectionRef S, xS; 4468 4469 assert(((structSizeAndFlags & ML_HAS_RELATIVE_PTRS) != 0) && 4470 "expected structSizeAndFlags to have ML_HAS_RELATIVE_PTRS flag"); 4471 4472 outs() << indent << "\t\t entsize " 4473 << (structSizeAndFlags & ML_ENTSIZE_MASK) << " (relative) \n"; 4474 outs() << indent << "\t\t count " << structCount << "\n"; 4475 4476 for (i = 0; i < structCount; i++) { 4477 r = get_pointer_64(p, offset, left, S, info); 4478 memset(&m, '\0', sizeof(struct method_relative_t)); 4479 if (left < sizeof(struct method_relative_t)) { 4480 memcpy(&m, r, left); 4481 outs() << indent << " (method_t extends past the end of the section)\n"; 4482 } else 4483 memcpy(&m, r, sizeof(struct method_relative_t)); 4484 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4485 swapStruct(m); 4486 4487 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 4488 uint64_t relNameRefVA = p + offsetof(struct method_relative_t, name); 4489 uint64_t absNameRefVA = relNameRefVA + m.name; 4490 outs() << " (" << format("0x%" PRIx32, absNameRefVA) << ")"; 4491 4492 // since this is a relative list, absNameRefVA is the address of the 4493 // __objc_selrefs entry, so a pointer, not the actual name 4494 const char *nameRefPtr = 4495 get_pointer_64(absNameRefVA, xoffset, left, xS, info); 4496 if (nameRefPtr) { 4497 uint32_t pointerSize = pointerBits / CHAR_BIT; 4498 if (left < pointerSize) 4499 outs() << indent << " (nameRefPtr extends past the end of the section)"; 4500 else { 4501 if (pointerSize == 64) { 4502 uint64_t nameOff_64 = *reinterpret_cast<const uint64_t *>(nameRefPtr); 4503 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4504 sys::swapByteOrder(nameOff_64); 4505 name = get_pointer_64(nameOff_64, xoffset, left, xS, info); 4506 } else { 4507 uint32_t nameOff_32 = *reinterpret_cast<const uint32_t *>(nameRefPtr); 4508 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4509 sys::swapByteOrder(nameOff_32); 4510 name = get_pointer_32(nameOff_32, xoffset, left, xS, info); 4511 } 4512 if (name != nullptr) 4513 outs() << format(" %.*s", left, name); 4514 } 4515 } 4516 outs() << "\n"; 4517 4518 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 4519 uint64_t relTypesVA = p + offsetof(struct method_relative_t, types); 4520 uint64_t absTypesVA = relTypesVA + m.types; 4521 outs() << " (" << format("0x%" PRIx32, absTypesVA) << ")"; 4522 name = get_pointer_32(absTypesVA, xoffset, left, xS, info); 4523 if (name != nullptr) 4524 outs() << format(" %.*s", left, name); 4525 outs() << "\n"; 4526 4527 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4528 uint64_t relImpVA = p + offsetof(struct method_relative_t, imp); 4529 uint64_t absImpVA = relImpVA + m.imp; 4530 outs() << " (" << format("0x%" PRIx32, absImpVA) << ")"; 4531 name = GuessSymbolName(absImpVA, info->AddrMap); 4532 if (name != nullptr) 4533 outs() << " " << name; 4534 outs() << "\n"; 4535 4536 p += sizeof(struct method_relative_t); 4537 offset += sizeof(struct method_relative_t); 4538 } 4539 } 4540 4541 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 4542 const char *indent) { 4543 struct method_list64_t ml; 4544 struct method64_t m; 4545 const char *r; 4546 uint32_t offset, xoffset, left, i; 4547 SectionRef S, xS; 4548 const char *name, *sym_name; 4549 uint64_t n_value; 4550 4551 r = get_pointer_64(p, offset, left, S, info); 4552 if (r == nullptr) 4553 return; 4554 memset(&ml, '\0', sizeof(struct method_list64_t)); 4555 if (left < sizeof(struct method_list64_t)) { 4556 memcpy(&ml, r, left); 4557 outs() << " (method_list_t entends past the end of the section)\n"; 4558 } else 4559 memcpy(&ml, r, sizeof(struct method_list64_t)); 4560 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4561 swapStruct(ml); 4562 p += sizeof(struct method_list64_t); 4563 4564 if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) { 4565 print_relative_method_list(ml.entsize, ml.count, p, info, indent, 4566 /*pointerBits=*/64); 4567 return; 4568 } 4569 4570 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4571 outs() << indent << "\t\t count " << ml.count << "\n"; 4572 4573 offset += sizeof(struct method_list64_t); 4574 for (i = 0; i < ml.count; i++) { 4575 r = get_pointer_64(p, offset, left, S, info); 4576 if (r == nullptr) 4577 return; 4578 memset(&m, '\0', sizeof(struct method64_t)); 4579 if (left < sizeof(struct method64_t)) { 4580 memcpy(&m, r, left); 4581 outs() << indent << " (method_t extends past the end of the section)\n"; 4582 } else 4583 memcpy(&m, r, sizeof(struct method64_t)); 4584 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4585 swapStruct(m); 4586 4587 outs() << indent << "\t\t name "; 4588 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 4589 info, n_value, m.name); 4590 if (n_value != 0) { 4591 if (info->verbose && sym_name != nullptr) 4592 outs() << sym_name; 4593 else 4594 outs() << format("0x%" PRIx64, n_value); 4595 if (m.name != 0) 4596 outs() << " + " << format("0x%" PRIx64, m.name); 4597 } else 4598 outs() << format("0x%" PRIx64, m.name); 4599 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 4600 if (name != nullptr) 4601 outs() << format(" %.*s", left, name); 4602 outs() << "\n"; 4603 4604 outs() << indent << "\t\t types "; 4605 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 4606 info, n_value, m.types); 4607 if (n_value != 0) { 4608 if (info->verbose && sym_name != nullptr) 4609 outs() << sym_name; 4610 else 4611 outs() << format("0x%" PRIx64, n_value); 4612 if (m.types != 0) 4613 outs() << " + " << format("0x%" PRIx64, m.types); 4614 } else 4615 outs() << format("0x%" PRIx64, m.types); 4616 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 4617 if (name != nullptr) 4618 outs() << format(" %.*s", left, name); 4619 outs() << "\n"; 4620 4621 outs() << indent << "\t\t imp "; 4622 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 4623 n_value, m.imp); 4624 if (info->verbose && name == nullptr) { 4625 if (n_value != 0) { 4626 outs() << format("0x%" PRIx64, n_value) << " "; 4627 if (m.imp != 0) 4628 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 4629 } else 4630 outs() << format("0x%" PRIx64, m.imp) << " "; 4631 } 4632 if (name != nullptr) 4633 outs() << name; 4634 outs() << "\n"; 4635 4636 p += sizeof(struct method64_t); 4637 offset += sizeof(struct method64_t); 4638 } 4639 } 4640 4641 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 4642 const char *indent) { 4643 struct method_list32_t ml; 4644 struct method32_t m; 4645 const char *r, *name; 4646 uint32_t offset, xoffset, left, i; 4647 SectionRef S, xS; 4648 4649 r = get_pointer_32(p, offset, left, S, info); 4650 if (r == nullptr) 4651 return; 4652 memset(&ml, '\0', sizeof(struct method_list32_t)); 4653 if (left < sizeof(struct method_list32_t)) { 4654 memcpy(&ml, r, left); 4655 outs() << " (method_list_t entends past the end of the section)\n"; 4656 } else 4657 memcpy(&ml, r, sizeof(struct method_list32_t)); 4658 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4659 swapStruct(ml); 4660 p += sizeof(struct method_list32_t); 4661 4662 if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) { 4663 print_relative_method_list(ml.entsize, ml.count, p, info, indent, 4664 /*pointerBits=*/32); 4665 return; 4666 } 4667 4668 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4669 outs() << indent << "\t\t count " << ml.count << "\n"; 4670 4671 offset += sizeof(struct method_list32_t); 4672 for (i = 0; i < ml.count; i++) { 4673 r = get_pointer_32(p, offset, left, S, info); 4674 if (r == nullptr) 4675 return; 4676 memset(&m, '\0', sizeof(struct method32_t)); 4677 if (left < sizeof(struct method32_t)) { 4678 memcpy(&ml, r, left); 4679 outs() << indent << " (method_t entends past the end of the section)\n"; 4680 } else 4681 memcpy(&m, r, sizeof(struct method32_t)); 4682 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4683 swapStruct(m); 4684 4685 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 4686 name = get_pointer_32(m.name, xoffset, left, xS, info); 4687 if (name != nullptr) 4688 outs() << format(" %.*s", left, name); 4689 outs() << "\n"; 4690 4691 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 4692 name = get_pointer_32(m.types, xoffset, left, xS, info); 4693 if (name != nullptr) 4694 outs() << format(" %.*s", left, name); 4695 outs() << "\n"; 4696 4697 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4698 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 4699 m.imp); 4700 if (name != nullptr) 4701 outs() << " " << name; 4702 outs() << "\n"; 4703 4704 p += sizeof(struct method32_t); 4705 offset += sizeof(struct method32_t); 4706 } 4707 } 4708 4709 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 4710 uint32_t offset, left, xleft; 4711 SectionRef S; 4712 struct objc_method_list_t method_list; 4713 struct objc_method_t method; 4714 const char *r, *methods, *name, *SymbolName; 4715 int32_t i; 4716 4717 r = get_pointer_32(p, offset, left, S, info, true); 4718 if (r == nullptr) 4719 return true; 4720 4721 outs() << "\n"; 4722 if (left > sizeof(struct objc_method_list_t)) { 4723 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 4724 } else { 4725 outs() << "\t\t objc_method_list extends past end of the section\n"; 4726 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 4727 memcpy(&method_list, r, left); 4728 } 4729 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4730 swapStruct(method_list); 4731 4732 outs() << "\t\t obsolete " 4733 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4734 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4735 4736 methods = r + sizeof(struct objc_method_list_t); 4737 for (i = 0; i < method_list.method_count; i++) { 4738 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4739 outs() << "\t\t remaining method's extend past the of the section\n"; 4740 break; 4741 } 4742 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4743 sizeof(struct objc_method_t)); 4744 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4745 swapStruct(method); 4746 4747 outs() << "\t\t method_name " 4748 << format("0x%08" PRIx32, method.method_name); 4749 if (info->verbose) { 4750 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4751 if (name != nullptr) 4752 outs() << format(" %.*s", xleft, name); 4753 else 4754 outs() << " (not in an __OBJC section)"; 4755 } 4756 outs() << "\n"; 4757 4758 outs() << "\t\t method_types " 4759 << format("0x%08" PRIx32, method.method_types); 4760 if (info->verbose) { 4761 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4762 if (name != nullptr) 4763 outs() << format(" %.*s", xleft, name); 4764 else 4765 outs() << " (not in an __OBJC section)"; 4766 } 4767 outs() << "\n"; 4768 4769 outs() << "\t\t method_imp " 4770 << format("0x%08" PRIx32, method.method_imp) << " "; 4771 if (info->verbose) { 4772 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4773 if (SymbolName != nullptr) 4774 outs() << SymbolName; 4775 } 4776 outs() << "\n"; 4777 } 4778 return false; 4779 } 4780 4781 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4782 struct protocol_list64_t pl; 4783 uint64_t q, n_value; 4784 struct protocol64_t pc; 4785 const char *r; 4786 uint32_t offset, xoffset, left, i; 4787 SectionRef S, xS; 4788 const char *name, *sym_name; 4789 4790 r = get_pointer_64(p, offset, left, S, info); 4791 if (r == nullptr) 4792 return; 4793 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4794 if (left < sizeof(struct protocol_list64_t)) { 4795 memcpy(&pl, r, left); 4796 outs() << " (protocol_list_t entends past the end of the section)\n"; 4797 } else 4798 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4799 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4800 swapStruct(pl); 4801 outs() << " count " << pl.count << "\n"; 4802 4803 p += sizeof(struct protocol_list64_t); 4804 offset += sizeof(struct protocol_list64_t); 4805 for (i = 0; i < pl.count; i++) { 4806 r = get_pointer_64(p, offset, left, S, info); 4807 if (r == nullptr) 4808 return; 4809 q = 0; 4810 if (left < sizeof(uint64_t)) { 4811 memcpy(&q, r, left); 4812 outs() << " (protocol_t * entends past the end of the section)\n"; 4813 } else 4814 memcpy(&q, r, sizeof(uint64_t)); 4815 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4816 sys::swapByteOrder(q); 4817 4818 outs() << "\t\t list[" << i << "] "; 4819 sym_name = get_symbol_64(offset, S, info, n_value, q); 4820 if (n_value != 0) { 4821 if (info->verbose && sym_name != nullptr) 4822 outs() << sym_name; 4823 else 4824 outs() << format("0x%" PRIx64, n_value); 4825 if (q != 0) 4826 outs() << " + " << format("0x%" PRIx64, q); 4827 } else 4828 outs() << format("0x%" PRIx64, q); 4829 outs() << " (struct protocol_t *)\n"; 4830 4831 r = get_pointer_64(q + n_value, offset, left, S, info); 4832 if (r == nullptr) 4833 return; 4834 memset(&pc, '\0', sizeof(struct protocol64_t)); 4835 if (left < sizeof(struct protocol64_t)) { 4836 memcpy(&pc, r, left); 4837 outs() << " (protocol_t entends past the end of the section)\n"; 4838 } else 4839 memcpy(&pc, r, sizeof(struct protocol64_t)); 4840 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4841 swapStruct(pc); 4842 4843 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4844 4845 outs() << "\t\t\t name "; 4846 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4847 info, n_value, pc.name); 4848 if (n_value != 0) { 4849 if (info->verbose && sym_name != nullptr) 4850 outs() << sym_name; 4851 else 4852 outs() << format("0x%" PRIx64, n_value); 4853 if (pc.name != 0) 4854 outs() << " + " << format("0x%" PRIx64, pc.name); 4855 } else 4856 outs() << format("0x%" PRIx64, pc.name); 4857 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4858 if (name != nullptr) 4859 outs() << format(" %.*s", left, name); 4860 outs() << "\n"; 4861 4862 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4863 4864 outs() << "\t\t instanceMethods "; 4865 sym_name = 4866 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4867 S, info, n_value, pc.instanceMethods); 4868 if (n_value != 0) { 4869 if (info->verbose && sym_name != nullptr) 4870 outs() << sym_name; 4871 else 4872 outs() << format("0x%" PRIx64, n_value); 4873 if (pc.instanceMethods != 0) 4874 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4875 } else 4876 outs() << format("0x%" PRIx64, pc.instanceMethods); 4877 outs() << " (struct method_list_t *)\n"; 4878 if (pc.instanceMethods + n_value != 0) 4879 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4880 4881 outs() << "\t\t classMethods "; 4882 sym_name = 4883 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4884 info, n_value, pc.classMethods); 4885 if (n_value != 0) { 4886 if (info->verbose && sym_name != nullptr) 4887 outs() << sym_name; 4888 else 4889 outs() << format("0x%" PRIx64, n_value); 4890 if (pc.classMethods != 0) 4891 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4892 } else 4893 outs() << format("0x%" PRIx64, pc.classMethods); 4894 outs() << " (struct method_list_t *)\n"; 4895 if (pc.classMethods + n_value != 0) 4896 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4897 4898 outs() << "\t optionalInstanceMethods " 4899 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4900 outs() << "\t optionalClassMethods " 4901 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4902 outs() << "\t instanceProperties " 4903 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4904 4905 p += sizeof(uint64_t); 4906 offset += sizeof(uint64_t); 4907 } 4908 } 4909 4910 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4911 struct protocol_list32_t pl; 4912 uint32_t q; 4913 struct protocol32_t pc; 4914 const char *r; 4915 uint32_t offset, xoffset, left, i; 4916 SectionRef S, xS; 4917 const char *name; 4918 4919 r = get_pointer_32(p, offset, left, S, info); 4920 if (r == nullptr) 4921 return; 4922 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4923 if (left < sizeof(struct protocol_list32_t)) { 4924 memcpy(&pl, r, left); 4925 outs() << " (protocol_list_t entends past the end of the section)\n"; 4926 } else 4927 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4928 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4929 swapStruct(pl); 4930 outs() << " count " << pl.count << "\n"; 4931 4932 p += sizeof(struct protocol_list32_t); 4933 offset += sizeof(struct protocol_list32_t); 4934 for (i = 0; i < pl.count; i++) { 4935 r = get_pointer_32(p, offset, left, S, info); 4936 if (r == nullptr) 4937 return; 4938 q = 0; 4939 if (left < sizeof(uint32_t)) { 4940 memcpy(&q, r, left); 4941 outs() << " (protocol_t * entends past the end of the section)\n"; 4942 } else 4943 memcpy(&q, r, sizeof(uint32_t)); 4944 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4945 sys::swapByteOrder(q); 4946 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4947 << " (struct protocol_t *)\n"; 4948 r = get_pointer_32(q, offset, left, S, info); 4949 if (r == nullptr) 4950 return; 4951 memset(&pc, '\0', sizeof(struct protocol32_t)); 4952 if (left < sizeof(struct protocol32_t)) { 4953 memcpy(&pc, r, left); 4954 outs() << " (protocol_t entends past the end of the section)\n"; 4955 } else 4956 memcpy(&pc, r, sizeof(struct protocol32_t)); 4957 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4958 swapStruct(pc); 4959 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4960 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4961 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4962 if (name != nullptr) 4963 outs() << format(" %.*s", left, name); 4964 outs() << "\n"; 4965 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4966 outs() << "\t\t instanceMethods " 4967 << format("0x%" PRIx32, pc.instanceMethods) 4968 << " (struct method_list_t *)\n"; 4969 if (pc.instanceMethods != 0) 4970 print_method_list32_t(pc.instanceMethods, info, "\t"); 4971 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4972 << " (struct method_list_t *)\n"; 4973 if (pc.classMethods != 0) 4974 print_method_list32_t(pc.classMethods, info, "\t"); 4975 outs() << "\t optionalInstanceMethods " 4976 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4977 outs() << "\t optionalClassMethods " 4978 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4979 outs() << "\t instanceProperties " 4980 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4981 p += sizeof(uint32_t); 4982 offset += sizeof(uint32_t); 4983 } 4984 } 4985 4986 static void print_indent(uint32_t indent) { 4987 for (uint32_t i = 0; i < indent;) { 4988 if (indent - i >= 8) { 4989 outs() << "\t"; 4990 i += 8; 4991 } else { 4992 for (uint32_t j = i; j < indent; j++) 4993 outs() << " "; 4994 return; 4995 } 4996 } 4997 } 4998 4999 static bool print_method_description_list(uint32_t p, uint32_t indent, 5000 struct DisassembleInfo *info) { 5001 uint32_t offset, left, xleft; 5002 SectionRef S; 5003 struct objc_method_description_list_t mdl; 5004 struct objc_method_description_t md; 5005 const char *r, *list, *name; 5006 int32_t i; 5007 5008 r = get_pointer_32(p, offset, left, S, info, true); 5009 if (r == nullptr) 5010 return true; 5011 5012 outs() << "\n"; 5013 if (left > sizeof(struct objc_method_description_list_t)) { 5014 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 5015 } else { 5016 print_indent(indent); 5017 outs() << " objc_method_description_list extends past end of the section\n"; 5018 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 5019 memcpy(&mdl, r, left); 5020 } 5021 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5022 swapStruct(mdl); 5023 5024 print_indent(indent); 5025 outs() << " count " << mdl.count << "\n"; 5026 5027 list = r + sizeof(struct objc_method_description_list_t); 5028 for (i = 0; i < mdl.count; i++) { 5029 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 5030 print_indent(indent); 5031 outs() << " remaining list entries extend past the of the section\n"; 5032 break; 5033 } 5034 print_indent(indent); 5035 outs() << " list[" << i << "]\n"; 5036 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 5037 sizeof(struct objc_method_description_t)); 5038 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5039 swapStruct(md); 5040 5041 print_indent(indent); 5042 outs() << " name " << format("0x%08" PRIx32, md.name); 5043 if (info->verbose) { 5044 name = get_pointer_32(md.name, offset, xleft, S, info, true); 5045 if (name != nullptr) 5046 outs() << format(" %.*s", xleft, name); 5047 else 5048 outs() << " (not in an __OBJC section)"; 5049 } 5050 outs() << "\n"; 5051 5052 print_indent(indent); 5053 outs() << " types " << format("0x%08" PRIx32, md.types); 5054 if (info->verbose) { 5055 name = get_pointer_32(md.types, offset, xleft, S, info, true); 5056 if (name != nullptr) 5057 outs() << format(" %.*s", xleft, name); 5058 else 5059 outs() << " (not in an __OBJC section)"; 5060 } 5061 outs() << "\n"; 5062 } 5063 return false; 5064 } 5065 5066 static bool print_protocol_list(uint32_t p, uint32_t indent, 5067 struct DisassembleInfo *info); 5068 5069 static bool print_protocol(uint32_t p, uint32_t indent, 5070 struct DisassembleInfo *info) { 5071 uint32_t offset, left; 5072 SectionRef S; 5073 struct objc_protocol_t protocol; 5074 const char *r, *name; 5075 5076 r = get_pointer_32(p, offset, left, S, info, true); 5077 if (r == nullptr) 5078 return true; 5079 5080 outs() << "\n"; 5081 if (left >= sizeof(struct objc_protocol_t)) { 5082 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 5083 } else { 5084 print_indent(indent); 5085 outs() << " Protocol extends past end of the section\n"; 5086 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 5087 memcpy(&protocol, r, left); 5088 } 5089 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5090 swapStruct(protocol); 5091 5092 print_indent(indent); 5093 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 5094 << "\n"; 5095 5096 print_indent(indent); 5097 outs() << " protocol_name " 5098 << format("0x%08" PRIx32, protocol.protocol_name); 5099 if (info->verbose) { 5100 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 5101 if (name != nullptr) 5102 outs() << format(" %.*s", left, name); 5103 else 5104 outs() << " (not in an __OBJC section)"; 5105 } 5106 outs() << "\n"; 5107 5108 print_indent(indent); 5109 outs() << " protocol_list " 5110 << format("0x%08" PRIx32, protocol.protocol_list); 5111 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 5112 outs() << " (not in an __OBJC section)\n"; 5113 5114 print_indent(indent); 5115 outs() << " instance_methods " 5116 << format("0x%08" PRIx32, protocol.instance_methods); 5117 if (print_method_description_list(protocol.instance_methods, indent, info)) 5118 outs() << " (not in an __OBJC section)\n"; 5119 5120 print_indent(indent); 5121 outs() << " class_methods " 5122 << format("0x%08" PRIx32, protocol.class_methods); 5123 if (print_method_description_list(protocol.class_methods, indent, info)) 5124 outs() << " (not in an __OBJC section)\n"; 5125 5126 return false; 5127 } 5128 5129 static bool print_protocol_list(uint32_t p, uint32_t indent, 5130 struct DisassembleInfo *info) { 5131 uint32_t offset, left, l; 5132 SectionRef S; 5133 struct objc_protocol_list_t protocol_list; 5134 const char *r, *list; 5135 int32_t i; 5136 5137 r = get_pointer_32(p, offset, left, S, info, true); 5138 if (r == nullptr) 5139 return true; 5140 5141 outs() << "\n"; 5142 if (left > sizeof(struct objc_protocol_list_t)) { 5143 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 5144 } else { 5145 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 5146 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 5147 memcpy(&protocol_list, r, left); 5148 } 5149 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5150 swapStruct(protocol_list); 5151 5152 print_indent(indent); 5153 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 5154 << "\n"; 5155 print_indent(indent); 5156 outs() << " count " << protocol_list.count << "\n"; 5157 5158 list = r + sizeof(struct objc_protocol_list_t); 5159 for (i = 0; i < protocol_list.count; i++) { 5160 if ((i + 1) * sizeof(uint32_t) > left) { 5161 outs() << "\t\t remaining list entries extend past the of the section\n"; 5162 break; 5163 } 5164 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 5165 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5166 sys::swapByteOrder(l); 5167 5168 print_indent(indent); 5169 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 5170 if (print_protocol(l, indent, info)) 5171 outs() << "(not in an __OBJC section)\n"; 5172 } 5173 return false; 5174 } 5175 5176 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 5177 struct ivar_list64_t il; 5178 struct ivar64_t i; 5179 const char *r; 5180 uint32_t offset, xoffset, left, j; 5181 SectionRef S, xS; 5182 const char *name, *sym_name, *ivar_offset_p; 5183 uint64_t ivar_offset, n_value; 5184 5185 r = get_pointer_64(p, offset, left, S, info); 5186 if (r == nullptr) 5187 return; 5188 memset(&il, '\0', sizeof(struct ivar_list64_t)); 5189 if (left < sizeof(struct ivar_list64_t)) { 5190 memcpy(&il, r, left); 5191 outs() << " (ivar_list_t entends past the end of the section)\n"; 5192 } else 5193 memcpy(&il, r, sizeof(struct ivar_list64_t)); 5194 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5195 swapStruct(il); 5196 outs() << " entsize " << il.entsize << "\n"; 5197 outs() << " count " << il.count << "\n"; 5198 5199 p += sizeof(struct ivar_list64_t); 5200 offset += sizeof(struct ivar_list64_t); 5201 for (j = 0; j < il.count; j++) { 5202 r = get_pointer_64(p, offset, left, S, info); 5203 if (r == nullptr) 5204 return; 5205 memset(&i, '\0', sizeof(struct ivar64_t)); 5206 if (left < sizeof(struct ivar64_t)) { 5207 memcpy(&i, r, left); 5208 outs() << " (ivar_t entends past the end of the section)\n"; 5209 } else 5210 memcpy(&i, r, sizeof(struct ivar64_t)); 5211 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5212 swapStruct(i); 5213 5214 outs() << "\t\t\t offset "; 5215 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 5216 info, n_value, i.offset); 5217 if (n_value != 0) { 5218 if (info->verbose && sym_name != nullptr) 5219 outs() << sym_name; 5220 else 5221 outs() << format("0x%" PRIx64, n_value); 5222 if (i.offset != 0) 5223 outs() << " + " << format("0x%" PRIx64, i.offset); 5224 } else 5225 outs() << format("0x%" PRIx64, i.offset); 5226 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 5227 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 5228 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 5229 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5230 sys::swapByteOrder(ivar_offset); 5231 outs() << " " << ivar_offset << "\n"; 5232 } else 5233 outs() << "\n"; 5234 5235 outs() << "\t\t\t name "; 5236 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 5237 n_value, i.name); 5238 if (n_value != 0) { 5239 if (info->verbose && sym_name != nullptr) 5240 outs() << sym_name; 5241 else 5242 outs() << format("0x%" PRIx64, n_value); 5243 if (i.name != 0) 5244 outs() << " + " << format("0x%" PRIx64, i.name); 5245 } else 5246 outs() << format("0x%" PRIx64, i.name); 5247 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 5248 if (name != nullptr) 5249 outs() << format(" %.*s", left, name); 5250 outs() << "\n"; 5251 5252 outs() << "\t\t\t type "; 5253 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 5254 n_value, i.name); 5255 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 5256 if (n_value != 0) { 5257 if (info->verbose && sym_name != nullptr) 5258 outs() << sym_name; 5259 else 5260 outs() << format("0x%" PRIx64, n_value); 5261 if (i.type != 0) 5262 outs() << " + " << format("0x%" PRIx64, i.type); 5263 } else 5264 outs() << format("0x%" PRIx64, i.type); 5265 if (name != nullptr) 5266 outs() << format(" %.*s", left, name); 5267 outs() << "\n"; 5268 5269 outs() << "\t\t\talignment " << i.alignment << "\n"; 5270 outs() << "\t\t\t size " << i.size << "\n"; 5271 5272 p += sizeof(struct ivar64_t); 5273 offset += sizeof(struct ivar64_t); 5274 } 5275 } 5276 5277 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 5278 struct ivar_list32_t il; 5279 struct ivar32_t i; 5280 const char *r; 5281 uint32_t offset, xoffset, left, j; 5282 SectionRef S, xS; 5283 const char *name, *ivar_offset_p; 5284 uint32_t ivar_offset; 5285 5286 r = get_pointer_32(p, offset, left, S, info); 5287 if (r == nullptr) 5288 return; 5289 memset(&il, '\0', sizeof(struct ivar_list32_t)); 5290 if (left < sizeof(struct ivar_list32_t)) { 5291 memcpy(&il, r, left); 5292 outs() << " (ivar_list_t entends past the end of the section)\n"; 5293 } else 5294 memcpy(&il, r, sizeof(struct ivar_list32_t)); 5295 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5296 swapStruct(il); 5297 outs() << " entsize " << il.entsize << "\n"; 5298 outs() << " count " << il.count << "\n"; 5299 5300 p += sizeof(struct ivar_list32_t); 5301 offset += sizeof(struct ivar_list32_t); 5302 for (j = 0; j < il.count; j++) { 5303 r = get_pointer_32(p, offset, left, S, info); 5304 if (r == nullptr) 5305 return; 5306 memset(&i, '\0', sizeof(struct ivar32_t)); 5307 if (left < sizeof(struct ivar32_t)) { 5308 memcpy(&i, r, left); 5309 outs() << " (ivar_t entends past the end of the section)\n"; 5310 } else 5311 memcpy(&i, r, sizeof(struct ivar32_t)); 5312 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5313 swapStruct(i); 5314 5315 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 5316 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 5317 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 5318 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 5319 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5320 sys::swapByteOrder(ivar_offset); 5321 outs() << " " << ivar_offset << "\n"; 5322 } else 5323 outs() << "\n"; 5324 5325 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 5326 name = get_pointer_32(i.name, xoffset, left, xS, info); 5327 if (name != nullptr) 5328 outs() << format(" %.*s", left, name); 5329 outs() << "\n"; 5330 5331 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 5332 name = get_pointer_32(i.type, xoffset, left, xS, info); 5333 if (name != nullptr) 5334 outs() << format(" %.*s", left, name); 5335 outs() << "\n"; 5336 5337 outs() << "\t\t\talignment " << i.alignment << "\n"; 5338 outs() << "\t\t\t size " << i.size << "\n"; 5339 5340 p += sizeof(struct ivar32_t); 5341 offset += sizeof(struct ivar32_t); 5342 } 5343 } 5344 5345 static void print_objc_property_list64(uint64_t p, 5346 struct DisassembleInfo *info) { 5347 struct objc_property_list64 opl; 5348 struct objc_property64 op; 5349 const char *r; 5350 uint32_t offset, xoffset, left, j; 5351 SectionRef S, xS; 5352 const char *name, *sym_name; 5353 uint64_t n_value; 5354 5355 r = get_pointer_64(p, offset, left, S, info); 5356 if (r == nullptr) 5357 return; 5358 memset(&opl, '\0', sizeof(struct objc_property_list64)); 5359 if (left < sizeof(struct objc_property_list64)) { 5360 memcpy(&opl, r, left); 5361 outs() << " (objc_property_list entends past the end of the section)\n"; 5362 } else 5363 memcpy(&opl, r, sizeof(struct objc_property_list64)); 5364 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5365 swapStruct(opl); 5366 outs() << " entsize " << opl.entsize << "\n"; 5367 outs() << " count " << opl.count << "\n"; 5368 5369 p += sizeof(struct objc_property_list64); 5370 offset += sizeof(struct objc_property_list64); 5371 for (j = 0; j < opl.count; j++) { 5372 r = get_pointer_64(p, offset, left, S, info); 5373 if (r == nullptr) 5374 return; 5375 memset(&op, '\0', sizeof(struct objc_property64)); 5376 if (left < sizeof(struct objc_property64)) { 5377 memcpy(&op, r, left); 5378 outs() << " (objc_property entends past the end of the section)\n"; 5379 } else 5380 memcpy(&op, r, sizeof(struct objc_property64)); 5381 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5382 swapStruct(op); 5383 5384 outs() << "\t\t\t name "; 5385 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 5386 info, n_value, op.name); 5387 if (n_value != 0) { 5388 if (info->verbose && sym_name != nullptr) 5389 outs() << sym_name; 5390 else 5391 outs() << format("0x%" PRIx64, n_value); 5392 if (op.name != 0) 5393 outs() << " + " << format("0x%" PRIx64, op.name); 5394 } else 5395 outs() << format("0x%" PRIx64, op.name); 5396 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 5397 if (name != nullptr) 5398 outs() << format(" %.*s", left, name); 5399 outs() << "\n"; 5400 5401 outs() << "\t\t\tattributes "; 5402 sym_name = 5403 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 5404 info, n_value, op.attributes); 5405 if (n_value != 0) { 5406 if (info->verbose && sym_name != nullptr) 5407 outs() << sym_name; 5408 else 5409 outs() << format("0x%" PRIx64, n_value); 5410 if (op.attributes != 0) 5411 outs() << " + " << format("0x%" PRIx64, op.attributes); 5412 } else 5413 outs() << format("0x%" PRIx64, op.attributes); 5414 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 5415 if (name != nullptr) 5416 outs() << format(" %.*s", left, name); 5417 outs() << "\n"; 5418 5419 p += sizeof(struct objc_property64); 5420 offset += sizeof(struct objc_property64); 5421 } 5422 } 5423 5424 static void print_objc_property_list32(uint32_t p, 5425 struct DisassembleInfo *info) { 5426 struct objc_property_list32 opl; 5427 struct objc_property32 op; 5428 const char *r; 5429 uint32_t offset, xoffset, left, j; 5430 SectionRef S, xS; 5431 const char *name; 5432 5433 r = get_pointer_32(p, offset, left, S, info); 5434 if (r == nullptr) 5435 return; 5436 memset(&opl, '\0', sizeof(struct objc_property_list32)); 5437 if (left < sizeof(struct objc_property_list32)) { 5438 memcpy(&opl, r, left); 5439 outs() << " (objc_property_list entends past the end of the section)\n"; 5440 } else 5441 memcpy(&opl, r, sizeof(struct objc_property_list32)); 5442 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5443 swapStruct(opl); 5444 outs() << " entsize " << opl.entsize << "\n"; 5445 outs() << " count " << opl.count << "\n"; 5446 5447 p += sizeof(struct objc_property_list32); 5448 offset += sizeof(struct objc_property_list32); 5449 for (j = 0; j < opl.count; j++) { 5450 r = get_pointer_32(p, offset, left, S, info); 5451 if (r == nullptr) 5452 return; 5453 memset(&op, '\0', sizeof(struct objc_property32)); 5454 if (left < sizeof(struct objc_property32)) { 5455 memcpy(&op, r, left); 5456 outs() << " (objc_property entends past the end of the section)\n"; 5457 } else 5458 memcpy(&op, r, sizeof(struct objc_property32)); 5459 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5460 swapStruct(op); 5461 5462 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 5463 name = get_pointer_32(op.name, xoffset, left, xS, info); 5464 if (name != nullptr) 5465 outs() << format(" %.*s", left, name); 5466 outs() << "\n"; 5467 5468 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 5469 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 5470 if (name != nullptr) 5471 outs() << format(" %.*s", left, name); 5472 outs() << "\n"; 5473 5474 p += sizeof(struct objc_property32); 5475 offset += sizeof(struct objc_property32); 5476 } 5477 } 5478 5479 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 5480 bool &is_meta_class) { 5481 struct class_ro64_t cro; 5482 const char *r; 5483 uint32_t offset, xoffset, left; 5484 SectionRef S, xS; 5485 const char *name, *sym_name; 5486 uint64_t n_value; 5487 5488 r = get_pointer_64(p, offset, left, S, info); 5489 if (r == nullptr || left < sizeof(struct class_ro64_t)) 5490 return false; 5491 memcpy(&cro, r, sizeof(struct class_ro64_t)); 5492 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5493 swapStruct(cro); 5494 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5495 if (cro.flags & RO_META) 5496 outs() << " RO_META"; 5497 if (cro.flags & RO_ROOT) 5498 outs() << " RO_ROOT"; 5499 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5500 outs() << " RO_HAS_CXX_STRUCTORS"; 5501 outs() << "\n"; 5502 outs() << " instanceStart " << cro.instanceStart << "\n"; 5503 outs() << " instanceSize " << cro.instanceSize << "\n"; 5504 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 5505 << "\n"; 5506 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 5507 << "\n"; 5508 print_layout_map64(cro.ivarLayout, info); 5509 5510 outs() << " name "; 5511 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 5512 info, n_value, cro.name); 5513 if (n_value != 0) { 5514 if (info->verbose && sym_name != nullptr) 5515 outs() << sym_name; 5516 else 5517 outs() << format("0x%" PRIx64, n_value); 5518 if (cro.name != 0) 5519 outs() << " + " << format("0x%" PRIx64, cro.name); 5520 } else 5521 outs() << format("0x%" PRIx64, cro.name); 5522 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 5523 if (name != nullptr) 5524 outs() << format(" %.*s", left, name); 5525 outs() << "\n"; 5526 5527 outs() << " baseMethods "; 5528 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 5529 S, info, n_value, cro.baseMethods); 5530 if (n_value != 0) { 5531 if (info->verbose && sym_name != nullptr) 5532 outs() << sym_name; 5533 else 5534 outs() << format("0x%" PRIx64, n_value); 5535 if (cro.baseMethods != 0) 5536 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 5537 } else 5538 outs() << format("0x%" PRIx64, cro.baseMethods); 5539 outs() << " (struct method_list_t *)\n"; 5540 if (cro.baseMethods + n_value != 0) 5541 print_method_list64_t(cro.baseMethods + n_value, info, ""); 5542 5543 outs() << " baseProtocols "; 5544 sym_name = 5545 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 5546 info, n_value, cro.baseProtocols); 5547 if (n_value != 0) { 5548 if (info->verbose && sym_name != nullptr) 5549 outs() << sym_name; 5550 else 5551 outs() << format("0x%" PRIx64, n_value); 5552 if (cro.baseProtocols != 0) 5553 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 5554 } else 5555 outs() << format("0x%" PRIx64, cro.baseProtocols); 5556 outs() << "\n"; 5557 if (cro.baseProtocols + n_value != 0) 5558 print_protocol_list64_t(cro.baseProtocols + n_value, info); 5559 5560 outs() << " ivars "; 5561 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 5562 info, n_value, cro.ivars); 5563 if (n_value != 0) { 5564 if (info->verbose && sym_name != nullptr) 5565 outs() << sym_name; 5566 else 5567 outs() << format("0x%" PRIx64, n_value); 5568 if (cro.ivars != 0) 5569 outs() << " + " << format("0x%" PRIx64, cro.ivars); 5570 } else 5571 outs() << format("0x%" PRIx64, cro.ivars); 5572 outs() << "\n"; 5573 if (cro.ivars + n_value != 0) 5574 print_ivar_list64_t(cro.ivars + n_value, info); 5575 5576 outs() << " weakIvarLayout "; 5577 sym_name = 5578 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 5579 info, n_value, cro.weakIvarLayout); 5580 if (n_value != 0) { 5581 if (info->verbose && sym_name != nullptr) 5582 outs() << sym_name; 5583 else 5584 outs() << format("0x%" PRIx64, n_value); 5585 if (cro.weakIvarLayout != 0) 5586 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 5587 } else 5588 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 5589 outs() << "\n"; 5590 print_layout_map64(cro.weakIvarLayout + n_value, info); 5591 5592 outs() << " baseProperties "; 5593 sym_name = 5594 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 5595 info, n_value, cro.baseProperties); 5596 if (n_value != 0) { 5597 if (info->verbose && sym_name != nullptr) 5598 outs() << sym_name; 5599 else 5600 outs() << format("0x%" PRIx64, n_value); 5601 if (cro.baseProperties != 0) 5602 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 5603 } else 5604 outs() << format("0x%" PRIx64, cro.baseProperties); 5605 outs() << "\n"; 5606 if (cro.baseProperties + n_value != 0) 5607 print_objc_property_list64(cro.baseProperties + n_value, info); 5608 5609 is_meta_class = (cro.flags & RO_META) != 0; 5610 return true; 5611 } 5612 5613 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 5614 bool &is_meta_class) { 5615 struct class_ro32_t cro; 5616 const char *r; 5617 uint32_t offset, xoffset, left; 5618 SectionRef S, xS; 5619 const char *name; 5620 5621 r = get_pointer_32(p, offset, left, S, info); 5622 if (r == nullptr) 5623 return false; 5624 memset(&cro, '\0', sizeof(struct class_ro32_t)); 5625 if (left < sizeof(struct class_ro32_t)) { 5626 memcpy(&cro, r, left); 5627 outs() << " (class_ro_t entends past the end of the section)\n"; 5628 } else 5629 memcpy(&cro, r, sizeof(struct class_ro32_t)); 5630 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5631 swapStruct(cro); 5632 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5633 if (cro.flags & RO_META) 5634 outs() << " RO_META"; 5635 if (cro.flags & RO_ROOT) 5636 outs() << " RO_ROOT"; 5637 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5638 outs() << " RO_HAS_CXX_STRUCTORS"; 5639 outs() << "\n"; 5640 outs() << " instanceStart " << cro.instanceStart << "\n"; 5641 outs() << " instanceSize " << cro.instanceSize << "\n"; 5642 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 5643 << "\n"; 5644 print_layout_map32(cro.ivarLayout, info); 5645 5646 outs() << " name " << format("0x%" PRIx32, cro.name); 5647 name = get_pointer_32(cro.name, xoffset, left, xS, info); 5648 if (name != nullptr) 5649 outs() << format(" %.*s", left, name); 5650 outs() << "\n"; 5651 5652 outs() << " baseMethods " 5653 << format("0x%" PRIx32, cro.baseMethods) 5654 << " (struct method_list_t *)\n"; 5655 if (cro.baseMethods != 0) 5656 print_method_list32_t(cro.baseMethods, info, ""); 5657 5658 outs() << " baseProtocols " 5659 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 5660 if (cro.baseProtocols != 0) 5661 print_protocol_list32_t(cro.baseProtocols, info); 5662 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 5663 << "\n"; 5664 if (cro.ivars != 0) 5665 print_ivar_list32_t(cro.ivars, info); 5666 outs() << " weakIvarLayout " 5667 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 5668 print_layout_map32(cro.weakIvarLayout, info); 5669 outs() << " baseProperties " 5670 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 5671 if (cro.baseProperties != 0) 5672 print_objc_property_list32(cro.baseProperties, info); 5673 is_meta_class = (cro.flags & RO_META) != 0; 5674 return true; 5675 } 5676 5677 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 5678 struct class64_t c; 5679 const char *r; 5680 uint32_t offset, left; 5681 SectionRef S; 5682 const char *name; 5683 uint64_t isa_n_value, n_value; 5684 5685 r = get_pointer_64(p, offset, left, S, info); 5686 if (r == nullptr || left < sizeof(struct class64_t)) 5687 return; 5688 memcpy(&c, r, sizeof(struct class64_t)); 5689 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5690 swapStruct(c); 5691 5692 outs() << " isa " << format("0x%" PRIx64, c.isa); 5693 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 5694 isa_n_value, c.isa); 5695 if (name != nullptr) 5696 outs() << " " << name; 5697 outs() << "\n"; 5698 5699 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 5700 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 5701 n_value, c.superclass); 5702 if (name != nullptr) 5703 outs() << " " << name; 5704 else { 5705 name = get_dyld_bind_info_symbolname(S.getAddress() + 5706 offset + offsetof(struct class64_t, superclass), info); 5707 if (name != nullptr) 5708 outs() << " " << name; 5709 } 5710 outs() << "\n"; 5711 5712 outs() << " cache " << format("0x%" PRIx64, c.cache); 5713 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 5714 n_value, c.cache); 5715 if (name != nullptr) 5716 outs() << " " << name; 5717 outs() << "\n"; 5718 5719 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 5720 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 5721 n_value, c.vtable); 5722 if (name != nullptr) 5723 outs() << " " << name; 5724 outs() << "\n"; 5725 5726 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 5727 n_value, c.data); 5728 outs() << " data "; 5729 if (n_value != 0) { 5730 if (info->verbose && name != nullptr) 5731 outs() << name; 5732 else 5733 outs() << format("0x%" PRIx64, n_value); 5734 if (c.data != 0) 5735 outs() << " + " << format("0x%" PRIx64, c.data); 5736 } else 5737 outs() << format("0x%" PRIx64, c.data); 5738 outs() << " (struct class_ro_t *)"; 5739 5740 // This is a Swift class if some of the low bits of the pointer are set. 5741 if ((c.data + n_value) & 0x7) 5742 outs() << " Swift class"; 5743 outs() << "\n"; 5744 bool is_meta_class; 5745 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5746 return; 5747 5748 if (!is_meta_class && 5749 c.isa + isa_n_value != p && 5750 c.isa + isa_n_value != 0 && 5751 info->depth < 100) { 5752 info->depth++; 5753 outs() << "Meta Class\n"; 5754 print_class64_t(c.isa + isa_n_value, info); 5755 } 5756 } 5757 5758 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5759 struct class32_t c; 5760 const char *r; 5761 uint32_t offset, left; 5762 SectionRef S; 5763 const char *name; 5764 5765 r = get_pointer_32(p, offset, left, S, info); 5766 if (r == nullptr) 5767 return; 5768 memset(&c, '\0', sizeof(struct class32_t)); 5769 if (left < sizeof(struct class32_t)) { 5770 memcpy(&c, r, left); 5771 outs() << " (class_t entends past the end of the section)\n"; 5772 } else 5773 memcpy(&c, r, sizeof(struct class32_t)); 5774 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5775 swapStruct(c); 5776 5777 outs() << " isa " << format("0x%" PRIx32, c.isa); 5778 name = 5779 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5780 if (name != nullptr) 5781 outs() << " " << name; 5782 outs() << "\n"; 5783 5784 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5785 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5786 c.superclass); 5787 if (name != nullptr) 5788 outs() << " " << name; 5789 outs() << "\n"; 5790 5791 outs() << " cache " << format("0x%" PRIx32, c.cache); 5792 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5793 c.cache); 5794 if (name != nullptr) 5795 outs() << " " << name; 5796 outs() << "\n"; 5797 5798 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5799 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5800 c.vtable); 5801 if (name != nullptr) 5802 outs() << " " << name; 5803 outs() << "\n"; 5804 5805 name = 5806 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5807 outs() << " data " << format("0x%" PRIx32, c.data) 5808 << " (struct class_ro_t *)"; 5809 5810 // This is a Swift class if some of the low bits of the pointer are set. 5811 if (c.data & 0x3) 5812 outs() << " Swift class"; 5813 outs() << "\n"; 5814 bool is_meta_class; 5815 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5816 return; 5817 5818 if (!is_meta_class) { 5819 outs() << "Meta Class\n"; 5820 print_class32_t(c.isa, info); 5821 } 5822 } 5823 5824 static void print_objc_class_t(struct objc_class_t *objc_class, 5825 struct DisassembleInfo *info) { 5826 uint32_t offset, left, xleft; 5827 const char *name, *p, *ivar_list; 5828 SectionRef S; 5829 int32_t i; 5830 struct objc_ivar_list_t objc_ivar_list; 5831 struct objc_ivar_t ivar; 5832 5833 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5834 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5835 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5836 if (name != nullptr) 5837 outs() << format(" %.*s", left, name); 5838 else 5839 outs() << " (not in an __OBJC section)"; 5840 } 5841 outs() << "\n"; 5842 5843 outs() << "\t super_class " 5844 << format("0x%08" PRIx32, objc_class->super_class); 5845 if (info->verbose) { 5846 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5847 if (name != nullptr) 5848 outs() << format(" %.*s", left, name); 5849 else 5850 outs() << " (not in an __OBJC section)"; 5851 } 5852 outs() << "\n"; 5853 5854 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5855 if (info->verbose) { 5856 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5857 if (name != nullptr) 5858 outs() << format(" %.*s", left, name); 5859 else 5860 outs() << " (not in an __OBJC section)"; 5861 } 5862 outs() << "\n"; 5863 5864 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5865 << "\n"; 5866 5867 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5868 if (info->verbose) { 5869 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5870 outs() << " CLS_CLASS"; 5871 else if (CLS_GETINFO(objc_class, CLS_META)) 5872 outs() << " CLS_META"; 5873 } 5874 outs() << "\n"; 5875 5876 outs() << "\t instance_size " 5877 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5878 5879 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5880 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5881 if (p != nullptr) { 5882 if (left > sizeof(struct objc_ivar_list_t)) { 5883 outs() << "\n"; 5884 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5885 } else { 5886 outs() << " (entends past the end of the section)\n"; 5887 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5888 memcpy(&objc_ivar_list, p, left); 5889 } 5890 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5891 swapStruct(objc_ivar_list); 5892 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5893 ivar_list = p + sizeof(struct objc_ivar_list_t); 5894 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5895 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5896 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5897 break; 5898 } 5899 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5900 sizeof(struct objc_ivar_t)); 5901 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5902 swapStruct(ivar); 5903 5904 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5905 if (info->verbose) { 5906 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5907 if (name != nullptr) 5908 outs() << format(" %.*s", xleft, name); 5909 else 5910 outs() << " (not in an __OBJC section)"; 5911 } 5912 outs() << "\n"; 5913 5914 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5915 if (info->verbose) { 5916 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5917 if (name != nullptr) 5918 outs() << format(" %.*s", xleft, name); 5919 else 5920 outs() << " (not in an __OBJC section)"; 5921 } 5922 outs() << "\n"; 5923 5924 outs() << "\t\t ivar_offset " 5925 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5926 } 5927 } else { 5928 outs() << " (not in an __OBJC section)\n"; 5929 } 5930 5931 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5932 if (print_method_list(objc_class->methodLists, info)) 5933 outs() << " (not in an __OBJC section)\n"; 5934 5935 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5936 << "\n"; 5937 5938 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5939 if (print_protocol_list(objc_class->protocols, 16, info)) 5940 outs() << " (not in an __OBJC section)\n"; 5941 } 5942 5943 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5944 struct DisassembleInfo *info) { 5945 uint32_t offset, left; 5946 const char *name; 5947 SectionRef S; 5948 5949 outs() << "\t category name " 5950 << format("0x%08" PRIx32, objc_category->category_name); 5951 if (info->verbose) { 5952 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5953 true); 5954 if (name != nullptr) 5955 outs() << format(" %.*s", left, name); 5956 else 5957 outs() << " (not in an __OBJC section)"; 5958 } 5959 outs() << "\n"; 5960 5961 outs() << "\t\t class name " 5962 << format("0x%08" PRIx32, objc_category->class_name); 5963 if (info->verbose) { 5964 name = 5965 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5966 if (name != nullptr) 5967 outs() << format(" %.*s", left, name); 5968 else 5969 outs() << " (not in an __OBJC section)"; 5970 } 5971 outs() << "\n"; 5972 5973 outs() << "\t instance methods " 5974 << format("0x%08" PRIx32, objc_category->instance_methods); 5975 if (print_method_list(objc_category->instance_methods, info)) 5976 outs() << " (not in an __OBJC section)\n"; 5977 5978 outs() << "\t class methods " 5979 << format("0x%08" PRIx32, objc_category->class_methods); 5980 if (print_method_list(objc_category->class_methods, info)) 5981 outs() << " (not in an __OBJC section)\n"; 5982 } 5983 5984 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5985 struct category64_t c; 5986 const char *r; 5987 uint32_t offset, xoffset, left; 5988 SectionRef S, xS; 5989 const char *name, *sym_name; 5990 uint64_t n_value; 5991 5992 r = get_pointer_64(p, offset, left, S, info); 5993 if (r == nullptr) 5994 return; 5995 memset(&c, '\0', sizeof(struct category64_t)); 5996 if (left < sizeof(struct category64_t)) { 5997 memcpy(&c, r, left); 5998 outs() << " (category_t entends past the end of the section)\n"; 5999 } else 6000 memcpy(&c, r, sizeof(struct category64_t)); 6001 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6002 swapStruct(c); 6003 6004 outs() << " name "; 6005 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 6006 info, n_value, c.name); 6007 if (n_value != 0) { 6008 if (info->verbose && sym_name != nullptr) 6009 outs() << sym_name; 6010 else 6011 outs() << format("0x%" PRIx64, n_value); 6012 if (c.name != 0) 6013 outs() << " + " << format("0x%" PRIx64, c.name); 6014 } else 6015 outs() << format("0x%" PRIx64, c.name); 6016 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 6017 if (name != nullptr) 6018 outs() << format(" %.*s", left, name); 6019 outs() << "\n"; 6020 6021 outs() << " cls "; 6022 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 6023 n_value, c.cls); 6024 if (n_value != 0) { 6025 if (info->verbose && sym_name != nullptr) 6026 outs() << sym_name; 6027 else 6028 outs() << format("0x%" PRIx64, n_value); 6029 if (c.cls != 0) 6030 outs() << " + " << format("0x%" PRIx64, c.cls); 6031 } else 6032 outs() << format("0x%" PRIx64, c.cls); 6033 outs() << "\n"; 6034 if (c.cls + n_value != 0) 6035 print_class64_t(c.cls + n_value, info); 6036 6037 outs() << " instanceMethods "; 6038 sym_name = 6039 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 6040 info, n_value, c.instanceMethods); 6041 if (n_value != 0) { 6042 if (info->verbose && sym_name != nullptr) 6043 outs() << sym_name; 6044 else 6045 outs() << format("0x%" PRIx64, n_value); 6046 if (c.instanceMethods != 0) 6047 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 6048 } else 6049 outs() << format("0x%" PRIx64, c.instanceMethods); 6050 outs() << "\n"; 6051 if (c.instanceMethods + n_value != 0) 6052 print_method_list64_t(c.instanceMethods + n_value, info, ""); 6053 6054 outs() << " classMethods "; 6055 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 6056 S, info, n_value, c.classMethods); 6057 if (n_value != 0) { 6058 if (info->verbose && sym_name != nullptr) 6059 outs() << sym_name; 6060 else 6061 outs() << format("0x%" PRIx64, n_value); 6062 if (c.classMethods != 0) 6063 outs() << " + " << format("0x%" PRIx64, c.classMethods); 6064 } else 6065 outs() << format("0x%" PRIx64, c.classMethods); 6066 outs() << "\n"; 6067 if (c.classMethods + n_value != 0) 6068 print_method_list64_t(c.classMethods + n_value, info, ""); 6069 6070 outs() << " protocols "; 6071 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 6072 info, n_value, c.protocols); 6073 if (n_value != 0) { 6074 if (info->verbose && sym_name != nullptr) 6075 outs() << sym_name; 6076 else 6077 outs() << format("0x%" PRIx64, n_value); 6078 if (c.protocols != 0) 6079 outs() << " + " << format("0x%" PRIx64, c.protocols); 6080 } else 6081 outs() << format("0x%" PRIx64, c.protocols); 6082 outs() << "\n"; 6083 if (c.protocols + n_value != 0) 6084 print_protocol_list64_t(c.protocols + n_value, info); 6085 6086 outs() << "instanceProperties "; 6087 sym_name = 6088 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 6089 S, info, n_value, c.instanceProperties); 6090 if (n_value != 0) { 6091 if (info->verbose && sym_name != nullptr) 6092 outs() << sym_name; 6093 else 6094 outs() << format("0x%" PRIx64, n_value); 6095 if (c.instanceProperties != 0) 6096 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 6097 } else 6098 outs() << format("0x%" PRIx64, c.instanceProperties); 6099 outs() << "\n"; 6100 if (c.instanceProperties + n_value != 0) 6101 print_objc_property_list64(c.instanceProperties + n_value, info); 6102 } 6103 6104 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 6105 struct category32_t c; 6106 const char *r; 6107 uint32_t offset, left; 6108 SectionRef S, xS; 6109 const char *name; 6110 6111 r = get_pointer_32(p, offset, left, S, info); 6112 if (r == nullptr) 6113 return; 6114 memset(&c, '\0', sizeof(struct category32_t)); 6115 if (left < sizeof(struct category32_t)) { 6116 memcpy(&c, r, left); 6117 outs() << " (category_t entends past the end of the section)\n"; 6118 } else 6119 memcpy(&c, r, sizeof(struct category32_t)); 6120 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6121 swapStruct(c); 6122 6123 outs() << " name " << format("0x%" PRIx32, c.name); 6124 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 6125 c.name); 6126 if (name) 6127 outs() << " " << name; 6128 outs() << "\n"; 6129 6130 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 6131 if (c.cls != 0) 6132 print_class32_t(c.cls, info); 6133 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 6134 << "\n"; 6135 if (c.instanceMethods != 0) 6136 print_method_list32_t(c.instanceMethods, info, ""); 6137 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 6138 << "\n"; 6139 if (c.classMethods != 0) 6140 print_method_list32_t(c.classMethods, info, ""); 6141 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 6142 if (c.protocols != 0) 6143 print_protocol_list32_t(c.protocols, info); 6144 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 6145 << "\n"; 6146 if (c.instanceProperties != 0) 6147 print_objc_property_list32(c.instanceProperties, info); 6148 } 6149 6150 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 6151 uint32_t i, left, offset, xoffset; 6152 uint64_t p, n_value; 6153 struct message_ref64 mr; 6154 const char *name, *sym_name; 6155 const char *r; 6156 SectionRef xS; 6157 6158 if (S == SectionRef()) 6159 return; 6160 6161 StringRef SectName; 6162 Expected<StringRef> SecNameOrErr = S.getName(); 6163 if (SecNameOrErr) 6164 SectName = *SecNameOrErr; 6165 else 6166 consumeError(SecNameOrErr.takeError()); 6167 6168 DataRefImpl Ref = S.getRawDataRefImpl(); 6169 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6170 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6171 offset = 0; 6172 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 6173 p = S.getAddress() + i; 6174 r = get_pointer_64(p, offset, left, S, info); 6175 if (r == nullptr) 6176 return; 6177 memset(&mr, '\0', sizeof(struct message_ref64)); 6178 if (left < sizeof(struct message_ref64)) { 6179 memcpy(&mr, r, left); 6180 outs() << " (message_ref entends past the end of the section)\n"; 6181 } else 6182 memcpy(&mr, r, sizeof(struct message_ref64)); 6183 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6184 swapStruct(mr); 6185 6186 outs() << " imp "; 6187 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 6188 n_value, mr.imp); 6189 if (n_value != 0) { 6190 outs() << format("0x%" PRIx64, n_value) << " "; 6191 if (mr.imp != 0) 6192 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 6193 } else 6194 outs() << format("0x%" PRIx64, mr.imp) << " "; 6195 if (name != nullptr) 6196 outs() << " " << name; 6197 outs() << "\n"; 6198 6199 outs() << " sel "; 6200 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 6201 info, n_value, mr.sel); 6202 if (n_value != 0) { 6203 if (info->verbose && sym_name != nullptr) 6204 outs() << sym_name; 6205 else 6206 outs() << format("0x%" PRIx64, n_value); 6207 if (mr.sel != 0) 6208 outs() << " + " << format("0x%" PRIx64, mr.sel); 6209 } else 6210 outs() << format("0x%" PRIx64, mr.sel); 6211 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 6212 if (name != nullptr) 6213 outs() << format(" %.*s", left, name); 6214 outs() << "\n"; 6215 6216 offset += sizeof(struct message_ref64); 6217 } 6218 } 6219 6220 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 6221 uint32_t i, left, offset, xoffset, p; 6222 struct message_ref32 mr; 6223 const char *name, *r; 6224 SectionRef xS; 6225 6226 if (S == SectionRef()) 6227 return; 6228 6229 StringRef SectName; 6230 Expected<StringRef> SecNameOrErr = S.getName(); 6231 if (SecNameOrErr) 6232 SectName = *SecNameOrErr; 6233 else 6234 consumeError(SecNameOrErr.takeError()); 6235 6236 DataRefImpl Ref = S.getRawDataRefImpl(); 6237 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6238 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6239 offset = 0; 6240 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 6241 p = S.getAddress() + i; 6242 r = get_pointer_32(p, offset, left, S, info); 6243 if (r == nullptr) 6244 return; 6245 memset(&mr, '\0', sizeof(struct message_ref32)); 6246 if (left < sizeof(struct message_ref32)) { 6247 memcpy(&mr, r, left); 6248 outs() << " (message_ref entends past the end of the section)\n"; 6249 } else 6250 memcpy(&mr, r, sizeof(struct message_ref32)); 6251 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6252 swapStruct(mr); 6253 6254 outs() << " imp " << format("0x%" PRIx32, mr.imp); 6255 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 6256 mr.imp); 6257 if (name != nullptr) 6258 outs() << " " << name; 6259 outs() << "\n"; 6260 6261 outs() << " sel " << format("0x%" PRIx32, mr.sel); 6262 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 6263 if (name != nullptr) 6264 outs() << " " << name; 6265 outs() << "\n"; 6266 6267 offset += sizeof(struct message_ref32); 6268 } 6269 } 6270 6271 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 6272 uint32_t left, offset, swift_version; 6273 uint64_t p; 6274 struct objc_image_info64 o; 6275 const char *r; 6276 6277 if (S == SectionRef()) 6278 return; 6279 6280 StringRef SectName; 6281 Expected<StringRef> SecNameOrErr = S.getName(); 6282 if (SecNameOrErr) 6283 SectName = *SecNameOrErr; 6284 else 6285 consumeError(SecNameOrErr.takeError()); 6286 6287 DataRefImpl Ref = S.getRawDataRefImpl(); 6288 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6289 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6290 p = S.getAddress(); 6291 r = get_pointer_64(p, offset, left, S, info); 6292 if (r == nullptr) 6293 return; 6294 memset(&o, '\0', sizeof(struct objc_image_info64)); 6295 if (left < sizeof(struct objc_image_info64)) { 6296 memcpy(&o, r, left); 6297 outs() << " (objc_image_info entends past the end of the section)\n"; 6298 } else 6299 memcpy(&o, r, sizeof(struct objc_image_info64)); 6300 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6301 swapStruct(o); 6302 outs() << " version " << o.version << "\n"; 6303 outs() << " flags " << format("0x%" PRIx32, o.flags); 6304 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 6305 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 6306 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 6307 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 6308 if (o.flags & OBJC_IMAGE_IS_SIMULATED) 6309 outs() << " OBJC_IMAGE_IS_SIMULATED"; 6310 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES) 6311 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES"; 6312 swift_version = (o.flags >> 8) & 0xff; 6313 if (swift_version != 0) { 6314 if (swift_version == 1) 6315 outs() << " Swift 1.0"; 6316 else if (swift_version == 2) 6317 outs() << " Swift 1.1"; 6318 else if(swift_version == 3) 6319 outs() << " Swift 2.0"; 6320 else if(swift_version == 4) 6321 outs() << " Swift 3.0"; 6322 else if(swift_version == 5) 6323 outs() << " Swift 4.0"; 6324 else if(swift_version == 6) 6325 outs() << " Swift 4.1/Swift 4.2"; 6326 else if(swift_version == 7) 6327 outs() << " Swift 5 or later"; 6328 else 6329 outs() << " unknown future Swift version (" << swift_version << ")"; 6330 } 6331 outs() << "\n"; 6332 } 6333 6334 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 6335 uint32_t left, offset, swift_version, p; 6336 struct objc_image_info32 o; 6337 const char *r; 6338 6339 if (S == SectionRef()) 6340 return; 6341 6342 StringRef SectName; 6343 Expected<StringRef> SecNameOrErr = S.getName(); 6344 if (SecNameOrErr) 6345 SectName = *SecNameOrErr; 6346 else 6347 consumeError(SecNameOrErr.takeError()); 6348 6349 DataRefImpl Ref = S.getRawDataRefImpl(); 6350 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6351 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6352 p = S.getAddress(); 6353 r = get_pointer_32(p, offset, left, S, info); 6354 if (r == nullptr) 6355 return; 6356 memset(&o, '\0', sizeof(struct objc_image_info32)); 6357 if (left < sizeof(struct objc_image_info32)) { 6358 memcpy(&o, r, left); 6359 outs() << " (objc_image_info entends past the end of the section)\n"; 6360 } else 6361 memcpy(&o, r, sizeof(struct objc_image_info32)); 6362 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6363 swapStruct(o); 6364 outs() << " version " << o.version << "\n"; 6365 outs() << " flags " << format("0x%" PRIx32, o.flags); 6366 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 6367 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 6368 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 6369 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 6370 swift_version = (o.flags >> 8) & 0xff; 6371 if (swift_version != 0) { 6372 if (swift_version == 1) 6373 outs() << " Swift 1.0"; 6374 else if (swift_version == 2) 6375 outs() << " Swift 1.1"; 6376 else if(swift_version == 3) 6377 outs() << " Swift 2.0"; 6378 else if(swift_version == 4) 6379 outs() << " Swift 3.0"; 6380 else if(swift_version == 5) 6381 outs() << " Swift 4.0"; 6382 else if(swift_version == 6) 6383 outs() << " Swift 4.1/Swift 4.2"; 6384 else if(swift_version == 7) 6385 outs() << " Swift 5 or later"; 6386 else 6387 outs() << " unknown future Swift version (" << swift_version << ")"; 6388 } 6389 outs() << "\n"; 6390 } 6391 6392 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 6393 uint32_t left, offset, p; 6394 struct imageInfo_t o; 6395 const char *r; 6396 6397 StringRef SectName; 6398 Expected<StringRef> SecNameOrErr = S.getName(); 6399 if (SecNameOrErr) 6400 SectName = *SecNameOrErr; 6401 else 6402 consumeError(SecNameOrErr.takeError()); 6403 6404 DataRefImpl Ref = S.getRawDataRefImpl(); 6405 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6406 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6407 p = S.getAddress(); 6408 r = get_pointer_32(p, offset, left, S, info); 6409 if (r == nullptr) 6410 return; 6411 memset(&o, '\0', sizeof(struct imageInfo_t)); 6412 if (left < sizeof(struct imageInfo_t)) { 6413 memcpy(&o, r, left); 6414 outs() << " (imageInfo entends past the end of the section)\n"; 6415 } else 6416 memcpy(&o, r, sizeof(struct imageInfo_t)); 6417 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6418 swapStruct(o); 6419 outs() << " version " << o.version << "\n"; 6420 outs() << " flags " << format("0x%" PRIx32, o.flags); 6421 if (o.flags & 0x1) 6422 outs() << " F&C"; 6423 if (o.flags & 0x2) 6424 outs() << " GC"; 6425 if (o.flags & 0x4) 6426 outs() << " GC-only"; 6427 else 6428 outs() << " RR"; 6429 outs() << "\n"; 6430 } 6431 6432 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 6433 SymbolAddressMap AddrMap; 6434 if (verbose) 6435 CreateSymbolAddressMap(O, &AddrMap); 6436 6437 std::vector<SectionRef> Sections; 6438 append_range(Sections, O->sections()); 6439 6440 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6441 6442 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6443 if (CL == SectionRef()) 6444 CL = get_section(O, "__DATA", "__objc_classlist"); 6445 if (CL == SectionRef()) 6446 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6447 if (CL == SectionRef()) 6448 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6449 info.S = CL; 6450 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 6451 6452 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6453 if (CR == SectionRef()) 6454 CR = get_section(O, "__DATA", "__objc_classrefs"); 6455 if (CR == SectionRef()) 6456 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6457 if (CR == SectionRef()) 6458 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6459 info.S = CR; 6460 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 6461 6462 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6463 if (SR == SectionRef()) 6464 SR = get_section(O, "__DATA", "__objc_superrefs"); 6465 if (SR == SectionRef()) 6466 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6467 if (SR == SectionRef()) 6468 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6469 info.S = SR; 6470 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 6471 6472 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6473 if (CA == SectionRef()) 6474 CA = get_section(O, "__DATA", "__objc_catlist"); 6475 if (CA == SectionRef()) 6476 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6477 if (CA == SectionRef()) 6478 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6479 info.S = CA; 6480 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 6481 6482 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6483 if (PL == SectionRef()) 6484 PL = get_section(O, "__DATA", "__objc_protolist"); 6485 if (PL == SectionRef()) 6486 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6487 if (PL == SectionRef()) 6488 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6489 info.S = PL; 6490 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 6491 6492 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6493 if (MR == SectionRef()) 6494 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6495 if (MR == SectionRef()) 6496 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6497 if (MR == SectionRef()) 6498 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6499 info.S = MR; 6500 print_message_refs64(MR, &info); 6501 6502 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6503 if (II == SectionRef()) 6504 II = get_section(O, "__DATA", "__objc_imageinfo"); 6505 if (II == SectionRef()) 6506 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6507 if (II == SectionRef()) 6508 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6509 info.S = II; 6510 print_image_info64(II, &info); 6511 } 6512 6513 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6514 SymbolAddressMap AddrMap; 6515 if (verbose) 6516 CreateSymbolAddressMap(O, &AddrMap); 6517 6518 std::vector<SectionRef> Sections; 6519 append_range(Sections, O->sections()); 6520 6521 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6522 6523 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6524 if (CL == SectionRef()) 6525 CL = get_section(O, "__DATA", "__objc_classlist"); 6526 if (CL == SectionRef()) 6527 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6528 if (CL == SectionRef()) 6529 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6530 info.S = CL; 6531 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 6532 6533 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6534 if (CR == SectionRef()) 6535 CR = get_section(O, "__DATA", "__objc_classrefs"); 6536 if (CR == SectionRef()) 6537 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6538 if (CR == SectionRef()) 6539 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6540 info.S = CR; 6541 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 6542 6543 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6544 if (SR == SectionRef()) 6545 SR = get_section(O, "__DATA", "__objc_superrefs"); 6546 if (SR == SectionRef()) 6547 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6548 if (SR == SectionRef()) 6549 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6550 info.S = SR; 6551 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 6552 6553 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6554 if (CA == SectionRef()) 6555 CA = get_section(O, "__DATA", "__objc_catlist"); 6556 if (CA == SectionRef()) 6557 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6558 if (CA == SectionRef()) 6559 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6560 info.S = CA; 6561 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 6562 6563 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6564 if (PL == SectionRef()) 6565 PL = get_section(O, "__DATA", "__objc_protolist"); 6566 if (PL == SectionRef()) 6567 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6568 if (PL == SectionRef()) 6569 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6570 info.S = PL; 6571 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 6572 6573 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6574 if (MR == SectionRef()) 6575 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6576 if (MR == SectionRef()) 6577 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6578 if (MR == SectionRef()) 6579 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6580 info.S = MR; 6581 print_message_refs32(MR, &info); 6582 6583 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6584 if (II == SectionRef()) 6585 II = get_section(O, "__DATA", "__objc_imageinfo"); 6586 if (II == SectionRef()) 6587 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6588 if (II == SectionRef()) 6589 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6590 info.S = II; 6591 print_image_info32(II, &info); 6592 } 6593 6594 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6595 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 6596 const char *r, *name, *defs; 6597 struct objc_module_t module; 6598 SectionRef S, xS; 6599 struct objc_symtab_t symtab; 6600 struct objc_class_t objc_class; 6601 struct objc_category_t objc_category; 6602 6603 outs() << "Objective-C segment\n"; 6604 S = get_section(O, "__OBJC", "__module_info"); 6605 if (S == SectionRef()) 6606 return false; 6607 6608 SymbolAddressMap AddrMap; 6609 if (verbose) 6610 CreateSymbolAddressMap(O, &AddrMap); 6611 6612 std::vector<SectionRef> Sections; 6613 append_range(Sections, O->sections()); 6614 6615 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6616 6617 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 6618 p = S.getAddress() + i; 6619 r = get_pointer_32(p, offset, left, S, &info, true); 6620 if (r == nullptr) 6621 return true; 6622 memset(&module, '\0', sizeof(struct objc_module_t)); 6623 if (left < sizeof(struct objc_module_t)) { 6624 memcpy(&module, r, left); 6625 outs() << " (module extends past end of __module_info section)\n"; 6626 } else 6627 memcpy(&module, r, sizeof(struct objc_module_t)); 6628 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6629 swapStruct(module); 6630 6631 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 6632 outs() << " version " << module.version << "\n"; 6633 outs() << " size " << module.size << "\n"; 6634 outs() << " name "; 6635 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 6636 if (name != nullptr) 6637 outs() << format("%.*s", left, name); 6638 else 6639 outs() << format("0x%08" PRIx32, module.name) 6640 << "(not in an __OBJC section)"; 6641 outs() << "\n"; 6642 6643 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 6644 if (module.symtab == 0 || r == nullptr) { 6645 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 6646 << " (not in an __OBJC section)\n"; 6647 continue; 6648 } 6649 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 6650 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 6651 defs_left = 0; 6652 defs = nullptr; 6653 if (left < sizeof(struct objc_symtab_t)) { 6654 memcpy(&symtab, r, left); 6655 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 6656 } else { 6657 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 6658 if (left > sizeof(struct objc_symtab_t)) { 6659 defs_left = left - sizeof(struct objc_symtab_t); 6660 defs = r + sizeof(struct objc_symtab_t); 6661 } 6662 } 6663 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6664 swapStruct(symtab); 6665 6666 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 6667 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 6668 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 6669 if (r == nullptr) 6670 outs() << " (not in an __OBJC section)"; 6671 outs() << "\n"; 6672 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 6673 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 6674 if (symtab.cls_def_cnt > 0) 6675 outs() << "\tClass Definitions\n"; 6676 for (j = 0; j < symtab.cls_def_cnt; j++) { 6677 if ((j + 1) * sizeof(uint32_t) > defs_left) { 6678 outs() << "\t(remaining class defs entries entends past the end of the " 6679 << "section)\n"; 6680 break; 6681 } 6682 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 6683 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6684 sys::swapByteOrder(def); 6685 6686 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6687 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 6688 if (r != nullptr) { 6689 if (left > sizeof(struct objc_class_t)) { 6690 outs() << "\n"; 6691 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6692 } else { 6693 outs() << " (entends past the end of the section)\n"; 6694 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6695 memcpy(&objc_class, r, left); 6696 } 6697 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6698 swapStruct(objc_class); 6699 print_objc_class_t(&objc_class, &info); 6700 } else { 6701 outs() << "(not in an __OBJC section)\n"; 6702 } 6703 6704 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 6705 outs() << "\tMeta Class"; 6706 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 6707 if (r != nullptr) { 6708 if (left > sizeof(struct objc_class_t)) { 6709 outs() << "\n"; 6710 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6711 } else { 6712 outs() << " (entends past the end of the section)\n"; 6713 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6714 memcpy(&objc_class, r, left); 6715 } 6716 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6717 swapStruct(objc_class); 6718 print_objc_class_t(&objc_class, &info); 6719 } else { 6720 outs() << "(not in an __OBJC section)\n"; 6721 } 6722 } 6723 } 6724 if (symtab.cat_def_cnt > 0) 6725 outs() << "\tCategory Definitions\n"; 6726 for (j = 0; j < symtab.cat_def_cnt; j++) { 6727 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 6728 outs() << "\t(remaining category defs entries entends past the end of " 6729 << "the section)\n"; 6730 break; 6731 } 6732 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6733 sizeof(uint32_t)); 6734 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6735 sys::swapByteOrder(def); 6736 6737 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6738 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6739 << format("0x%08" PRIx32, def); 6740 if (r != nullptr) { 6741 if (left > sizeof(struct objc_category_t)) { 6742 outs() << "\n"; 6743 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6744 } else { 6745 outs() << " (entends past the end of the section)\n"; 6746 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6747 memcpy(&objc_category, r, left); 6748 } 6749 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6750 swapStruct(objc_category); 6751 print_objc_objc_category_t(&objc_category, &info); 6752 } else { 6753 outs() << "(not in an __OBJC section)\n"; 6754 } 6755 } 6756 } 6757 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6758 if (II != SectionRef()) 6759 print_image_info(II, &info); 6760 6761 return true; 6762 } 6763 6764 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6765 uint32_t size, uint32_t addr) { 6766 SymbolAddressMap AddrMap; 6767 CreateSymbolAddressMap(O, &AddrMap); 6768 6769 std::vector<SectionRef> Sections; 6770 append_range(Sections, O->sections()); 6771 6772 struct DisassembleInfo info(O, &AddrMap, &Sections, true); 6773 6774 const char *p; 6775 struct objc_protocol_t protocol; 6776 uint32_t left, paddr; 6777 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6778 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6779 left = size - (p - sect); 6780 if (left < sizeof(struct objc_protocol_t)) { 6781 outs() << "Protocol extends past end of __protocol section\n"; 6782 memcpy(&protocol, p, left); 6783 } else 6784 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6785 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6786 swapStruct(protocol); 6787 paddr = addr + (p - sect); 6788 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6789 if (print_protocol(paddr, 0, &info)) 6790 outs() << "(not in an __OBJC section)\n"; 6791 } 6792 } 6793 6794 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6795 if (O->is64Bit()) 6796 printObjc2_64bit_MetaData(O, verbose); 6797 else { 6798 MachO::mach_header H; 6799 H = O->getHeader(); 6800 if (H.cputype == MachO::CPU_TYPE_ARM) 6801 printObjc2_32bit_MetaData(O, verbose); 6802 else { 6803 // This is the 32-bit non-arm cputype case. Which is normally 6804 // the first Objective-C ABI. But it may be the case of a 6805 // binary for the iOS simulator which is the second Objective-C 6806 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6807 // and return false. 6808 if (!printObjc1_32bit_MetaData(O, verbose)) 6809 printObjc2_32bit_MetaData(O, verbose); 6810 } 6811 } 6812 } 6813 6814 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6815 // for the address passed in as ReferenceValue for printing as a comment with 6816 // the instruction and also returns the corresponding type of that item 6817 // indirectly through ReferenceType. 6818 // 6819 // If ReferenceValue is an address of literal cstring then a pointer to the 6820 // cstring is returned and ReferenceType is set to 6821 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6822 // 6823 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6824 // Class ref that name is returned and the ReferenceType is set accordingly. 6825 // 6826 // Lastly, literals which are Symbol address in a literal pool are looked for 6827 // and if found the symbol name is returned and ReferenceType is set to 6828 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6829 // 6830 // If there is no item in the Mach-O file for the address passed in as 6831 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6832 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6833 uint64_t ReferencePC, 6834 uint64_t *ReferenceType, 6835 struct DisassembleInfo *info) { 6836 // First see if there is an external relocation entry at the ReferencePC. 6837 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6838 uint64_t sect_addr = info->S.getAddress(); 6839 uint64_t sect_offset = ReferencePC - sect_addr; 6840 bool reloc_found = false; 6841 DataRefImpl Rel; 6842 MachO::any_relocation_info RE; 6843 bool isExtern = false; 6844 SymbolRef Symbol; 6845 for (const RelocationRef &Reloc : info->S.relocations()) { 6846 uint64_t RelocOffset = Reloc.getOffset(); 6847 if (RelocOffset == sect_offset) { 6848 Rel = Reloc.getRawDataRefImpl(); 6849 RE = info->O->getRelocation(Rel); 6850 if (info->O->isRelocationScattered(RE)) 6851 continue; 6852 isExtern = info->O->getPlainRelocationExternal(RE); 6853 if (isExtern) { 6854 symbol_iterator RelocSym = Reloc.getSymbol(); 6855 Symbol = *RelocSym; 6856 } 6857 reloc_found = true; 6858 break; 6859 } 6860 } 6861 // If there is an external relocation entry for a symbol in a section 6862 // then used that symbol's value for the value of the reference. 6863 if (reloc_found && isExtern) { 6864 if (info->O->getAnyRelocationPCRel(RE)) { 6865 unsigned Type = info->O->getAnyRelocationType(RE); 6866 if (Type == MachO::X86_64_RELOC_SIGNED) { 6867 ReferenceValue = cantFail(Symbol.getValue()); 6868 } 6869 } 6870 } 6871 } 6872 6873 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6874 // Message refs and Class refs. 6875 bool classref, selref, msgref, cfstring; 6876 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6877 selref, msgref, cfstring); 6878 if (classref && pointer_value == 0) { 6879 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6880 // And the pointer_value in that section is typically zero as it will be 6881 // set by dyld as part of the "bind information". 6882 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6883 if (name != nullptr) { 6884 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6885 const char *class_name = strrchr(name, '$'); 6886 if (class_name != nullptr && class_name[1] == '_' && 6887 class_name[2] != '\0') { 6888 info->class_name = class_name + 2; 6889 return name; 6890 } 6891 } 6892 } 6893 6894 if (classref) { 6895 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6896 const char *name = 6897 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6898 if (name != nullptr) 6899 info->class_name = name; 6900 else 6901 name = "bad class ref"; 6902 return name; 6903 } 6904 6905 if (cfstring) { 6906 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6907 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6908 return name; 6909 } 6910 6911 if (selref && pointer_value == 0) 6912 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6913 6914 if (pointer_value != 0) 6915 ReferenceValue = pointer_value; 6916 6917 const char *name = GuessCstringPointer(ReferenceValue, info); 6918 if (name) { 6919 if (pointer_value != 0 && selref) { 6920 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6921 info->selector_name = name; 6922 } else if (pointer_value != 0 && msgref) { 6923 info->class_name = nullptr; 6924 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6925 info->selector_name = name; 6926 } else 6927 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6928 return name; 6929 } 6930 6931 // Lastly look for an indirect symbol with this ReferenceValue which is in 6932 // a literal pool. If found return that symbol name. 6933 name = GuessIndirectSymbol(ReferenceValue, info); 6934 if (name) { 6935 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6936 return name; 6937 } 6938 6939 return nullptr; 6940 } 6941 6942 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6943 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6944 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6945 // is created and returns the symbol name that matches the ReferenceValue or 6946 // nullptr if none. The ReferenceType is passed in for the IN type of 6947 // reference the instruction is making from the values in defined in the header 6948 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6949 // Out type and the ReferenceName will also be set which is added as a comment 6950 // to the disassembled instruction. 6951 // 6952 // If the symbol name is a C++ mangled name then the demangled name is 6953 // returned through ReferenceName and ReferenceType is set to 6954 // LLVMDisassembler_ReferenceType_DeMangled_Name . 6955 // 6956 // When this is called to get a symbol name for a branch target then the 6957 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 6958 // SymbolValue will be looked for in the indirect symbol table to determine if 6959 // it is an address for a symbol stub. If so then the symbol name for that 6960 // stub is returned indirectly through ReferenceName and then ReferenceType is 6961 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 6962 // 6963 // When this is called with an value loaded via a PC relative load then 6964 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 6965 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 6966 // or an Objective-C meta data reference. If so the output ReferenceType is 6967 // set to correspond to that as well as setting the ReferenceName. 6968 static const char *SymbolizerSymbolLookUp(void *DisInfo, 6969 uint64_t ReferenceValue, 6970 uint64_t *ReferenceType, 6971 uint64_t ReferencePC, 6972 const char **ReferenceName) { 6973 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 6974 // If no verbose symbolic information is wanted then just return nullptr. 6975 if (!info->verbose) { 6976 *ReferenceName = nullptr; 6977 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6978 return nullptr; 6979 } 6980 6981 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 6982 6983 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 6984 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 6985 if (*ReferenceName != nullptr) { 6986 method_reference(info, ReferenceType, ReferenceName); 6987 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 6988 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 6989 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6990 if (info->demangled_name != nullptr) 6991 free(info->demangled_name); 6992 info->demangled_name = itaniumDemangle(SymbolName + 1); 6993 if (info->demangled_name != nullptr) { 6994 *ReferenceName = info->demangled_name; 6995 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 6996 } else 6997 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6998 } else 6999 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7000 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 7001 *ReferenceName = 7002 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7003 if (*ReferenceName) 7004 method_reference(info, ReferenceType, ReferenceName); 7005 else 7006 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7007 // If this is arm64 and the reference is an adrp instruction save the 7008 // instruction, passed in ReferenceValue and the address of the instruction 7009 // for use later if we see and add immediate instruction. 7010 } else if (info->O->getArch() == Triple::aarch64 && 7011 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 7012 info->adrp_inst = ReferenceValue; 7013 info->adrp_addr = ReferencePC; 7014 SymbolName = nullptr; 7015 *ReferenceName = nullptr; 7016 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7017 // If this is arm64 and reference is an add immediate instruction and we 7018 // have 7019 // seen an adrp instruction just before it and the adrp's Xd register 7020 // matches 7021 // this add's Xn register reconstruct the value being referenced and look to 7022 // see if it is a literal pointer. Note the add immediate instruction is 7023 // passed in ReferenceValue. 7024 } else if (info->O->getArch() == Triple::aarch64 && 7025 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 7026 ReferencePC - 4 == info->adrp_addr && 7027 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7028 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7029 uint32_t addxri_inst; 7030 uint64_t adrp_imm, addxri_imm; 7031 7032 adrp_imm = 7033 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7034 if (info->adrp_inst & 0x0200000) 7035 adrp_imm |= 0xfffffffffc000000LL; 7036 7037 addxri_inst = ReferenceValue; 7038 addxri_imm = (addxri_inst >> 10) & 0xfff; 7039 if (((addxri_inst >> 22) & 0x3) == 1) 7040 addxri_imm <<= 12; 7041 7042 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7043 (adrp_imm << 12) + addxri_imm; 7044 7045 *ReferenceName = 7046 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7047 if (*ReferenceName == nullptr) 7048 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7049 // If this is arm64 and the reference is a load register instruction and we 7050 // have seen an adrp instruction just before it and the adrp's Xd register 7051 // matches this add's Xn register reconstruct the value being referenced and 7052 // look to see if it is a literal pointer. Note the load register 7053 // instruction is passed in ReferenceValue. 7054 } else if (info->O->getArch() == Triple::aarch64 && 7055 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 7056 ReferencePC - 4 == info->adrp_addr && 7057 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7058 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7059 uint32_t ldrxui_inst; 7060 uint64_t adrp_imm, ldrxui_imm; 7061 7062 adrp_imm = 7063 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7064 if (info->adrp_inst & 0x0200000) 7065 adrp_imm |= 0xfffffffffc000000LL; 7066 7067 ldrxui_inst = ReferenceValue; 7068 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 7069 7070 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7071 (adrp_imm << 12) + (ldrxui_imm << 3); 7072 7073 *ReferenceName = 7074 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7075 if (*ReferenceName == nullptr) 7076 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7077 } 7078 // If this arm64 and is an load register (PC-relative) instruction the 7079 // ReferenceValue is the PC plus the immediate value. 7080 else if (info->O->getArch() == Triple::aarch64 && 7081 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 7082 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 7083 *ReferenceName = 7084 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7085 if (*ReferenceName == nullptr) 7086 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7087 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 7088 if (info->demangled_name != nullptr) 7089 free(info->demangled_name); 7090 info->demangled_name = itaniumDemangle(SymbolName + 1); 7091 if (info->demangled_name != nullptr) { 7092 *ReferenceName = info->demangled_name; 7093 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 7094 } 7095 } 7096 else { 7097 *ReferenceName = nullptr; 7098 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7099 } 7100 7101 return SymbolName; 7102 } 7103 7104 /// Emits the comments that are stored in the CommentStream. 7105 /// Each comment in the CommentStream must end with a newline. 7106 static void emitComments(raw_svector_ostream &CommentStream, 7107 SmallString<128> &CommentsToEmit, 7108 formatted_raw_ostream &FormattedOS, 7109 const MCAsmInfo &MAI) { 7110 // Flush the stream before taking its content. 7111 StringRef Comments = CommentsToEmit.str(); 7112 // Get the default information for printing a comment. 7113 StringRef CommentBegin = MAI.getCommentString(); 7114 unsigned CommentColumn = MAI.getCommentColumn(); 7115 ListSeparator LS("\n"); 7116 while (!Comments.empty()) { 7117 FormattedOS << LS; 7118 // Emit a line of comments. 7119 FormattedOS.PadToColumn(CommentColumn); 7120 size_t Position = Comments.find('\n'); 7121 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 7122 // Move after the newline character. 7123 Comments = Comments.substr(Position + 1); 7124 } 7125 FormattedOS.flush(); 7126 7127 // Tell the comment stream that the vector changed underneath it. 7128 CommentsToEmit.clear(); 7129 } 7130 7131 const MachOObjectFile * 7132 objdump::getMachODSymObject(const MachOObjectFile *MachOOF, StringRef Filename, 7133 std::unique_ptr<Binary> &DSYMBinary, 7134 std::unique_ptr<MemoryBuffer> &DSYMBuf) { 7135 const MachOObjectFile *DbgObj = MachOOF; 7136 std::string DSYMPath; 7137 7138 // Auto-detect w/o --dsym. 7139 if (DSYMFile.empty()) { 7140 sys::fs::file_status DSYMStatus; 7141 Twine FilenameDSYM = Filename + ".dSYM"; 7142 if (!status(FilenameDSYM, DSYMStatus)) { 7143 if (sys::fs::is_directory(DSYMStatus)) { 7144 SmallString<1024> Path; 7145 FilenameDSYM.toVector(Path); 7146 sys::path::append(Path, "Contents", "Resources", "DWARF", 7147 sys::path::filename(Filename)); 7148 DSYMPath = std::string(Path); 7149 } else if (sys::fs::is_regular_file(DSYMStatus)) { 7150 DSYMPath = FilenameDSYM.str(); 7151 } 7152 } 7153 } 7154 7155 if (DSYMPath.empty() && !DSYMFile.empty()) { 7156 // If DSYMPath is a .dSYM directory, append the Mach-O file. 7157 if (sys::fs::is_directory(DSYMFile) && 7158 sys::path::extension(DSYMFile) == ".dSYM") { 7159 SmallString<128> ShortName(sys::path::filename(DSYMFile)); 7160 sys::path::replace_extension(ShortName, ""); 7161 SmallString<1024> FullPath(DSYMFile); 7162 sys::path::append(FullPath, "Contents", "Resources", "DWARF", ShortName); 7163 DSYMPath = FullPath.str(); 7164 } else { 7165 DSYMPath = DSYMFile; 7166 } 7167 } 7168 7169 if (!DSYMPath.empty()) { 7170 // Load the file. 7171 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 7172 MemoryBuffer::getFileOrSTDIN(DSYMPath); 7173 if (std::error_code EC = BufOrErr.getError()) { 7174 reportError(errorCodeToError(EC), DSYMPath); 7175 return nullptr; 7176 } 7177 7178 // We need to keep the file alive, because we're replacing DbgObj with it. 7179 DSYMBuf = std::move(BufOrErr.get()); 7180 7181 Expected<std::unique_ptr<Binary>> BinaryOrErr = 7182 createBinary(DSYMBuf->getMemBufferRef()); 7183 if (!BinaryOrErr) { 7184 reportError(BinaryOrErr.takeError(), DSYMPath); 7185 return nullptr; 7186 } 7187 7188 // We need to keep the Binary alive with the buffer 7189 DSYMBinary = std::move(BinaryOrErr.get()); 7190 if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) { 7191 // this is a Mach-O object file, use it 7192 if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) { 7193 DbgObj = MachDSYM; 7194 } else { 7195 WithColor::error(errs(), "llvm-objdump") 7196 << DSYMPath << " is not a Mach-O file type.\n"; 7197 return nullptr; 7198 } 7199 } else if (auto *UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())) { 7200 // this is a Universal Binary, find a Mach-O for this architecture 7201 uint32_t CPUType, CPUSubType; 7202 const char *ArchFlag; 7203 if (MachOOF->is64Bit()) { 7204 const MachO::mach_header_64 H_64 = MachOOF->getHeader64(); 7205 CPUType = H_64.cputype; 7206 CPUSubType = H_64.cpusubtype; 7207 } else { 7208 const MachO::mach_header H = MachOOF->getHeader(); 7209 CPUType = H.cputype; 7210 CPUSubType = H.cpusubtype; 7211 } 7212 Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr, 7213 &ArchFlag); 7214 Expected<std::unique_ptr<MachOObjectFile>> MachDSYM = 7215 UB->getMachOObjectForArch(ArchFlag); 7216 if (!MachDSYM) { 7217 reportError(MachDSYM.takeError(), DSYMPath); 7218 return nullptr; 7219 } 7220 7221 // We need to keep the Binary alive with the buffer 7222 DbgObj = &*MachDSYM.get(); 7223 DSYMBinary = std::move(*MachDSYM); 7224 } else { 7225 WithColor::error(errs(), "llvm-objdump") 7226 << DSYMPath << " is not a Mach-O or Universal file type.\n"; 7227 return nullptr; 7228 } 7229 } 7230 return DbgObj; 7231 } 7232 7233 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 7234 StringRef DisSegName, StringRef DisSectName) { 7235 const char *McpuDefault = nullptr; 7236 const Target *ThumbTarget = nullptr; 7237 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 7238 if (!TheTarget) { 7239 // GetTarget prints out stuff. 7240 return; 7241 } 7242 std::string MachOMCPU; 7243 if (MCPU.empty() && McpuDefault) 7244 MachOMCPU = McpuDefault; 7245 else 7246 MachOMCPU = MCPU; 7247 7248 #define CHECK_TARGET_INFO_CREATION(NAME) \ 7249 do { \ 7250 if (!NAME) { \ 7251 WithColor::error(errs(), "llvm-objdump") \ 7252 << "couldn't initialize disassembler for target " << TripleName \ 7253 << '\n'; \ 7254 return; \ 7255 } \ 7256 } while (false) 7257 #define CHECK_THUMB_TARGET_INFO_CREATION(NAME) \ 7258 do { \ 7259 if (!NAME) { \ 7260 WithColor::error(errs(), "llvm-objdump") \ 7261 << "couldn't initialize disassembler for target " << ThumbTripleName \ 7262 << '\n'; \ 7263 return; \ 7264 } \ 7265 } while (false) 7266 7267 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 7268 CHECK_TARGET_INFO_CREATION(InstrInfo); 7269 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 7270 if (ThumbTarget) { 7271 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 7272 CHECK_THUMB_TARGET_INFO_CREATION(ThumbInstrInfo); 7273 } 7274 7275 // Package up features to be passed to target/subtarget 7276 std::string FeaturesStr; 7277 if (!MAttrs.empty()) { 7278 SubtargetFeatures Features; 7279 for (unsigned i = 0; i != MAttrs.size(); ++i) 7280 Features.AddFeature(MAttrs[i]); 7281 FeaturesStr = Features.getString(); 7282 } 7283 7284 MCTargetOptions MCOptions; 7285 // Set up disassembler. 7286 std::unique_ptr<const MCRegisterInfo> MRI( 7287 TheTarget->createMCRegInfo(TripleName)); 7288 CHECK_TARGET_INFO_CREATION(MRI); 7289 std::unique_ptr<const MCAsmInfo> AsmInfo( 7290 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 7291 CHECK_TARGET_INFO_CREATION(AsmInfo); 7292 std::unique_ptr<const MCSubtargetInfo> STI( 7293 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 7294 CHECK_TARGET_INFO_CREATION(STI); 7295 MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get()); 7296 std::unique_ptr<MCDisassembler> DisAsm( 7297 TheTarget->createMCDisassembler(*STI, Ctx)); 7298 CHECK_TARGET_INFO_CREATION(DisAsm); 7299 std::unique_ptr<MCSymbolizer> Symbolizer; 7300 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false); 7301 std::unique_ptr<MCRelocationInfo> RelInfo( 7302 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 7303 if (RelInfo) { 7304 Symbolizer.reset(TheTarget->createMCSymbolizer( 7305 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7306 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 7307 DisAsm->setSymbolizer(std::move(Symbolizer)); 7308 } 7309 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 7310 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 7311 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 7312 CHECK_TARGET_INFO_CREATION(IP); 7313 // Set the display preference for hex vs. decimal immediates. 7314 IP->setPrintImmHex(PrintImmHex); 7315 // Comment stream and backing vector. 7316 SmallString<128> CommentsToEmit; 7317 raw_svector_ostream CommentStream(CommentsToEmit); 7318 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 7319 // if it is done then arm64 comments for string literals don't get printed 7320 // and some constant get printed instead and not setting it causes intel 7321 // (32-bit and 64-bit) comments printed with different spacing before the 7322 // comment causing different diffs with the 'C' disassembler library API. 7323 // IP->setCommentStream(CommentStream); 7324 7325 // Set up separate thumb disassembler if needed. 7326 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 7327 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 7328 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 7329 std::unique_ptr<MCDisassembler> ThumbDisAsm; 7330 std::unique_ptr<MCInstPrinter> ThumbIP; 7331 std::unique_ptr<MCContext> ThumbCtx; 7332 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 7333 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false); 7334 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 7335 if (ThumbTarget) { 7336 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 7337 CHECK_THUMB_TARGET_INFO_CREATION(ThumbMRI); 7338 ThumbAsmInfo.reset( 7339 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions)); 7340 CHECK_THUMB_TARGET_INFO_CREATION(ThumbAsmInfo); 7341 ThumbSTI.reset( 7342 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 7343 FeaturesStr)); 7344 CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI); 7345 ThumbCtx.reset(new MCContext(Triple(ThumbTripleName), ThumbAsmInfo.get(), 7346 ThumbMRI.get(), ThumbSTI.get())); 7347 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 7348 CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm); 7349 MCContext *PtrThumbCtx = ThumbCtx.get(); 7350 ThumbRelInfo.reset( 7351 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 7352 if (ThumbRelInfo) { 7353 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 7354 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7355 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 7356 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 7357 } 7358 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 7359 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 7360 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 7361 *ThumbInstrInfo, *ThumbMRI)); 7362 CHECK_THUMB_TARGET_INFO_CREATION(ThumbIP); 7363 // Set the display preference for hex vs. decimal immediates. 7364 ThumbIP->setPrintImmHex(PrintImmHex); 7365 } 7366 7367 #undef CHECK_TARGET_INFO_CREATION 7368 #undef CHECK_THUMB_TARGET_INFO_CREATION 7369 7370 MachO::mach_header Header = MachOOF->getHeader(); 7371 7372 // FIXME: Using the -cfg command line option, this code used to be able to 7373 // annotate relocations with the referenced symbol's name, and if this was 7374 // inside a __[cf]string section, the data it points to. This is now replaced 7375 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 7376 std::vector<SectionRef> Sections; 7377 std::vector<SymbolRef> Symbols; 7378 SmallVector<uint64_t, 8> FoundFns; 7379 uint64_t BaseSegmentAddress = 0; 7380 7381 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 7382 BaseSegmentAddress); 7383 7384 // Sort the symbols by address, just in case they didn't come in that way. 7385 llvm::stable_sort(Symbols, SymbolSorter()); 7386 7387 // Build a data in code table that is sorted on by the address of each entry. 7388 uint64_t BaseAddress = 0; 7389 if (Header.filetype == MachO::MH_OBJECT) 7390 BaseAddress = Sections[0].getAddress(); 7391 else 7392 BaseAddress = BaseSegmentAddress; 7393 DiceTable Dices; 7394 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 7395 DI != DE; ++DI) { 7396 uint32_t Offset; 7397 DI->getOffset(Offset); 7398 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 7399 } 7400 array_pod_sort(Dices.begin(), Dices.end()); 7401 7402 // Try to find debug info and set up the DIContext for it. 7403 std::unique_ptr<DIContext> diContext; 7404 std::unique_ptr<Binary> DSYMBinary; 7405 std::unique_ptr<MemoryBuffer> DSYMBuf; 7406 if (UseDbg) { 7407 // If separate DSym file path was specified, parse it as a macho file, 7408 // get the sections and supply it to the section name parsing machinery. 7409 if (const ObjectFile *DbgObj = 7410 getMachODSymObject(MachOOF, Filename, DSYMBinary, DSYMBuf)) { 7411 // Setup the DIContext 7412 diContext = DWARFContext::create(*DbgObj); 7413 } else { 7414 return; 7415 } 7416 } 7417 7418 if (FilterSections.empty()) 7419 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 7420 7421 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 7422 Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName(); 7423 if (!SecNameOrErr) { 7424 consumeError(SecNameOrErr.takeError()); 7425 continue; 7426 } 7427 if (*SecNameOrErr != DisSectName) 7428 continue; 7429 7430 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 7431 7432 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 7433 if (SegmentName != DisSegName) 7434 continue; 7435 7436 StringRef BytesStr = 7437 unwrapOrError(Sections[SectIdx].getContents(), Filename); 7438 ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr); 7439 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7440 7441 bool symbolTableWorked = false; 7442 7443 // Create a map of symbol addresses to symbol names for use by 7444 // the SymbolizerSymbolLookUp() routine. 7445 SymbolAddressMap AddrMap; 7446 bool DisSymNameFound = false; 7447 for (const SymbolRef &Symbol : MachOOF->symbols()) { 7448 SymbolRef::Type ST = 7449 unwrapOrError(Symbol.getType(), MachOOF->getFileName()); 7450 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 7451 ST == SymbolRef::ST_Other) { 7452 uint64_t Address = cantFail(Symbol.getValue()); 7453 StringRef SymName = 7454 unwrapOrError(Symbol.getName(), MachOOF->getFileName()); 7455 AddrMap[Address] = SymName; 7456 if (!DisSymName.empty() && DisSymName == SymName) 7457 DisSymNameFound = true; 7458 } 7459 } 7460 if (!DisSymName.empty() && !DisSymNameFound) { 7461 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 7462 return; 7463 } 7464 // Set up the block of info used by the Symbolizer call backs. 7465 SymbolizerInfo.verbose = SymbolicOperands; 7466 SymbolizerInfo.O = MachOOF; 7467 SymbolizerInfo.S = Sections[SectIdx]; 7468 SymbolizerInfo.AddrMap = &AddrMap; 7469 SymbolizerInfo.Sections = &Sections; 7470 // Same for the ThumbSymbolizer 7471 ThumbSymbolizerInfo.verbose = SymbolicOperands; 7472 ThumbSymbolizerInfo.O = MachOOF; 7473 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7474 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7475 ThumbSymbolizerInfo.Sections = &Sections; 7476 7477 unsigned int Arch = MachOOF->getArch(); 7478 7479 // Skip all symbols if this is a stubs file. 7480 if (Bytes.empty()) 7481 return; 7482 7483 // If the section has symbols but no symbol at the start of the section 7484 // these are used to make sure the bytes before the first symbol are 7485 // disassembled. 7486 bool FirstSymbol = true; 7487 bool FirstSymbolAtSectionStart = true; 7488 7489 // Disassemble symbol by symbol. 7490 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7491 StringRef SymName = 7492 unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName()); 7493 SymbolRef::Type ST = 7494 unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName()); 7495 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7496 continue; 7497 7498 // Make sure the symbol is defined in this section. 7499 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7500 if (!containsSym) { 7501 if (!DisSymName.empty() && DisSymName == SymName) { 7502 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7503 return; 7504 } 7505 continue; 7506 } 7507 // The __mh_execute_header is special and we need to deal with that fact 7508 // this symbol is before the start of the (__TEXT,__text) section and at the 7509 // address of the start of the __TEXT segment. This is because this symbol 7510 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7511 // start of the section in a standard MH_EXECUTE filetype. 7512 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7513 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7514 return; 7515 } 7516 // When this code is trying to disassemble a symbol at a time and in the 7517 // case there is only the __mh_execute_header symbol left as in a stripped 7518 // executable, we need to deal with this by ignoring this symbol so the 7519 // whole section is disassembled and this symbol is then not displayed. 7520 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7521 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7522 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7523 continue; 7524 7525 // If we are only disassembling one symbol see if this is that symbol. 7526 if (!DisSymName.empty() && DisSymName != SymName) 7527 continue; 7528 7529 // Start at the address of the symbol relative to the section's address. 7530 uint64_t SectSize = Sections[SectIdx].getSize(); 7531 uint64_t Start = cantFail(Symbols[SymIdx].getValue()); 7532 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7533 Start -= SectionAddress; 7534 7535 if (Start > SectSize) { 7536 outs() << "section data ends, " << SymName 7537 << " lies outside valid range\n"; 7538 return; 7539 } 7540 7541 // Stop disassembling either at the beginning of the next symbol or at 7542 // the end of the section. 7543 bool containsNextSym = false; 7544 uint64_t NextSym = 0; 7545 uint64_t NextSymIdx = SymIdx + 1; 7546 while (Symbols.size() > NextSymIdx) { 7547 SymbolRef::Type NextSymType = unwrapOrError( 7548 Symbols[NextSymIdx].getType(), MachOOF->getFileName()); 7549 if (NextSymType == SymbolRef::ST_Function) { 7550 containsNextSym = 7551 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7552 NextSym = cantFail(Symbols[NextSymIdx].getValue()); 7553 NextSym -= SectionAddress; 7554 break; 7555 } 7556 ++NextSymIdx; 7557 } 7558 7559 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7560 uint64_t Size; 7561 7562 symbolTableWorked = true; 7563 7564 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7565 uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb)); 7566 bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb; 7567 7568 // We only need the dedicated Thumb target if there's a real choice 7569 // (i.e. we're not targeting M-class) and the function is Thumb. 7570 bool UseThumbTarget = IsThumb && ThumbTarget; 7571 7572 // If we are not specifying a symbol to start disassembly with and this 7573 // is the first symbol in the section but not at the start of the section 7574 // then move the disassembly index to the start of the section and 7575 // don't print the symbol name just yet. This is so the bytes before the 7576 // first symbol are disassembled. 7577 uint64_t SymbolStart = Start; 7578 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7579 FirstSymbolAtSectionStart = false; 7580 Start = 0; 7581 } 7582 else 7583 outs() << SymName << ":\n"; 7584 7585 DILineInfo lastLine; 7586 for (uint64_t Index = Start; Index < End; Index += Size) { 7587 MCInst Inst; 7588 7589 // If this is the first symbol in the section and it was not at the 7590 // start of the section, see if we are at its Index now and if so print 7591 // the symbol name. 7592 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7593 outs() << SymName << ":\n"; 7594 7595 uint64_t PC = SectAddress + Index; 7596 if (LeadingAddr) { 7597 if (FullLeadingAddr) { 7598 if (MachOOF->is64Bit()) 7599 outs() << format("%016" PRIx64, PC); 7600 else 7601 outs() << format("%08" PRIx64, PC); 7602 } else { 7603 outs() << format("%8" PRIx64 ":", PC); 7604 } 7605 } 7606 if (ShowRawInsn || Arch == Triple::arm) 7607 outs() << "\t"; 7608 7609 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size)) 7610 continue; 7611 7612 SmallVector<char, 64> AnnotationsBytes; 7613 raw_svector_ostream Annotations(AnnotationsBytes); 7614 7615 bool gotInst; 7616 if (UseThumbTarget) 7617 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7618 PC, Annotations); 7619 else 7620 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7621 Annotations); 7622 if (gotInst) { 7623 if (ShowRawInsn || Arch == Triple::arm) { 7624 dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs()); 7625 } 7626 formatted_raw_ostream FormattedOS(outs()); 7627 StringRef AnnotationsStr = Annotations.str(); 7628 if (UseThumbTarget) 7629 ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI, 7630 FormattedOS); 7631 else 7632 IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS); 7633 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7634 7635 // Print debug info. 7636 if (diContext) { 7637 DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx}); 7638 // Print valid line info if it changed. 7639 if (dli != lastLine && dli.Line != 0) 7640 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7641 << dli.Column; 7642 lastLine = dli; 7643 } 7644 outs() << "\n"; 7645 } else { 7646 if (MachOOF->getArchTriple().isX86()) { 7647 outs() << format("\t.byte 0x%02x #bad opcode\n", 7648 *(Bytes.data() + Index) & 0xff); 7649 Size = 1; // skip exactly one illegible byte and move on. 7650 } else if (Arch == Triple::aarch64 || 7651 (Arch == Triple::arm && !IsThumb)) { 7652 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7653 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7654 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7655 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7656 outs() << format("\t.long\t0x%08x\n", opcode); 7657 Size = 4; 7658 } else if (Arch == Triple::arm) { 7659 assert(IsThumb && "ARM mode should have been dealt with above"); 7660 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7661 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7662 outs() << format("\t.short\t0x%04x\n", opcode); 7663 Size = 2; 7664 } else{ 7665 WithColor::warning(errs(), "llvm-objdump") 7666 << "invalid instruction encoding\n"; 7667 if (Size == 0) 7668 Size = 1; // skip illegible bytes 7669 } 7670 } 7671 } 7672 // Now that we are done disassembled the first symbol set the bool that 7673 // were doing this to false. 7674 FirstSymbol = false; 7675 } 7676 if (!symbolTableWorked) { 7677 // Reading the symbol table didn't work, disassemble the whole section. 7678 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7679 uint64_t SectSize = Sections[SectIdx].getSize(); 7680 uint64_t InstSize; 7681 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7682 MCInst Inst; 7683 7684 uint64_t PC = SectAddress + Index; 7685 7686 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize)) 7687 continue; 7688 7689 SmallVector<char, 64> AnnotationsBytes; 7690 raw_svector_ostream Annotations(AnnotationsBytes); 7691 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7692 Annotations)) { 7693 if (LeadingAddr) { 7694 if (FullLeadingAddr) { 7695 if (MachOOF->is64Bit()) 7696 outs() << format("%016" PRIx64, PC); 7697 else 7698 outs() << format("%08" PRIx64, PC); 7699 } else { 7700 outs() << format("%8" PRIx64 ":", PC); 7701 } 7702 } 7703 if (ShowRawInsn || Arch == Triple::arm) { 7704 outs() << "\t"; 7705 dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs()); 7706 } 7707 StringRef AnnotationsStr = Annotations.str(); 7708 IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs()); 7709 outs() << "\n"; 7710 } else { 7711 if (MachOOF->getArchTriple().isX86()) { 7712 outs() << format("\t.byte 0x%02x #bad opcode\n", 7713 *(Bytes.data() + Index) & 0xff); 7714 InstSize = 1; // skip exactly one illegible byte and move on. 7715 } else { 7716 WithColor::warning(errs(), "llvm-objdump") 7717 << "invalid instruction encoding\n"; 7718 if (InstSize == 0) 7719 InstSize = 1; // skip illegible bytes 7720 } 7721 } 7722 } 7723 } 7724 // The TripleName's need to be reset if we are called again for a different 7725 // architecture. 7726 TripleName = ""; 7727 ThumbTripleName = ""; 7728 7729 if (SymbolizerInfo.demangled_name != nullptr) 7730 free(SymbolizerInfo.demangled_name); 7731 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7732 free(ThumbSymbolizerInfo.demangled_name); 7733 } 7734 } 7735 7736 //===----------------------------------------------------------------------===// 7737 // __compact_unwind section dumping 7738 //===----------------------------------------------------------------------===// 7739 7740 namespace { 7741 7742 template <typename T> 7743 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7744 if (Offset + sizeof(T) > Contents.size()) { 7745 outs() << "warning: attempt to read past end of buffer\n"; 7746 return T(); 7747 } 7748 7749 uint64_t Val = support::endian::read<T, llvm::endianness::little>( 7750 Contents.data() + Offset); 7751 return Val; 7752 } 7753 7754 template <typename T> 7755 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7756 T Val = read<T>(Contents, Offset); 7757 Offset += sizeof(T); 7758 return Val; 7759 } 7760 7761 struct CompactUnwindEntry { 7762 uint32_t OffsetInSection; 7763 7764 uint64_t FunctionAddr; 7765 uint32_t Length; 7766 uint32_t CompactEncoding; 7767 uint64_t PersonalityAddr; 7768 uint64_t LSDAAddr; 7769 7770 RelocationRef FunctionReloc; 7771 RelocationRef PersonalityReloc; 7772 RelocationRef LSDAReloc; 7773 7774 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7775 : OffsetInSection(Offset) { 7776 if (Is64) 7777 read<uint64_t>(Contents, Offset); 7778 else 7779 read<uint32_t>(Contents, Offset); 7780 } 7781 7782 private: 7783 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7784 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7785 Length = readNext<uint32_t>(Contents, Offset); 7786 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7787 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7788 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7789 } 7790 }; 7791 } 7792 7793 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7794 /// and data being relocated, determine the best base Name and Addend to use for 7795 /// display purposes. 7796 /// 7797 /// 1. An Extern relocation will directly reference a symbol (and the data is 7798 /// then already an addend), so use that. 7799 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7800 // a symbol before it in the same section, and use the offset from there. 7801 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7802 /// referenced section. 7803 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7804 std::map<uint64_t, SymbolRef> &Symbols, 7805 const RelocationRef &Reloc, uint64_t Addr, 7806 StringRef &Name, uint64_t &Addend) { 7807 if (Reloc.getSymbol() != Obj->symbol_end()) { 7808 Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName()); 7809 Addend = Addr; 7810 return; 7811 } 7812 7813 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7814 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7815 7816 uint64_t SectionAddr = RelocSection.getAddress(); 7817 7818 auto Sym = Symbols.upper_bound(Addr); 7819 if (Sym == Symbols.begin()) { 7820 // The first symbol in the object is after this reference, the best we can 7821 // do is section-relative notation. 7822 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7823 Name = *NameOrErr; 7824 else 7825 consumeError(NameOrErr.takeError()); 7826 7827 Addend = Addr - SectionAddr; 7828 return; 7829 } 7830 7831 // Go back one so that SymbolAddress <= Addr. 7832 --Sym; 7833 7834 section_iterator SymSection = 7835 unwrapOrError(Sym->second.getSection(), Obj->getFileName()); 7836 if (RelocSection == *SymSection) { 7837 // There's a valid symbol in the same section before this reference. 7838 Name = unwrapOrError(Sym->second.getName(), Obj->getFileName()); 7839 Addend = Addr - Sym->first; 7840 return; 7841 } 7842 7843 // There is a symbol before this reference, but it's in a different 7844 // section. Probably not helpful to mention it, so use the section name. 7845 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7846 Name = *NameOrErr; 7847 else 7848 consumeError(NameOrErr.takeError()); 7849 7850 Addend = Addr - SectionAddr; 7851 } 7852 7853 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7854 std::map<uint64_t, SymbolRef> &Symbols, 7855 const RelocationRef &Reloc, uint64_t Addr) { 7856 StringRef Name; 7857 uint64_t Addend; 7858 7859 if (!Reloc.getObject()) 7860 return; 7861 7862 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7863 7864 outs() << Name; 7865 if (Addend) 7866 outs() << " + " << format("0x%" PRIx64, Addend); 7867 } 7868 7869 static void 7870 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7871 std::map<uint64_t, SymbolRef> &Symbols, 7872 const SectionRef &CompactUnwind) { 7873 7874 if (!Obj->isLittleEndian()) { 7875 outs() << "Skipping big-endian __compact_unwind section\n"; 7876 return; 7877 } 7878 7879 bool Is64 = Obj->is64Bit(); 7880 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7881 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7882 7883 StringRef Contents = 7884 unwrapOrError(CompactUnwind.getContents(), Obj->getFileName()); 7885 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7886 7887 // First populate the initial raw offsets, encodings and so on from the entry. 7888 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7889 CompactUnwindEntry Entry(Contents, Offset, Is64); 7890 CompactUnwinds.push_back(Entry); 7891 } 7892 7893 // Next we need to look at the relocations to find out what objects are 7894 // actually being referred to. 7895 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7896 uint64_t RelocAddress = Reloc.getOffset(); 7897 7898 uint32_t EntryIdx = RelocAddress / EntrySize; 7899 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7900 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7901 7902 if (OffsetInEntry == 0) 7903 Entry.FunctionReloc = Reloc; 7904 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7905 Entry.PersonalityReloc = Reloc; 7906 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7907 Entry.LSDAReloc = Reloc; 7908 else { 7909 outs() << "Invalid relocation in __compact_unwind section\n"; 7910 return; 7911 } 7912 } 7913 7914 // Finally, we're ready to print the data we've gathered. 7915 outs() << "Contents of __compact_unwind section:\n"; 7916 for (auto &Entry : CompactUnwinds) { 7917 outs() << " Entry at offset " 7918 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7919 7920 // 1. Start of the region this entry applies to. 7921 outs() << " start: " << format("0x%" PRIx64, 7922 Entry.FunctionAddr) << ' '; 7923 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7924 outs() << '\n'; 7925 7926 // 2. Length of the region this entry applies to. 7927 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7928 << '\n'; 7929 // 3. The 32-bit compact encoding. 7930 outs() << " compact encoding: " 7931 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7932 7933 // 4. The personality function, if present. 7934 if (Entry.PersonalityReloc.getObject()) { 7935 outs() << " personality function: " 7936 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7937 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7938 Entry.PersonalityAddr); 7939 outs() << '\n'; 7940 } 7941 7942 // 5. This entry's language-specific data area. 7943 if (Entry.LSDAReloc.getObject()) { 7944 outs() << " LSDA: " << format("0x%" PRIx64, 7945 Entry.LSDAAddr) << ' '; 7946 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7947 outs() << '\n'; 7948 } 7949 } 7950 } 7951 7952 //===----------------------------------------------------------------------===// 7953 // __unwind_info section dumping 7954 //===----------------------------------------------------------------------===// 7955 7956 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 7957 ptrdiff_t Pos = 0; 7958 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7959 (void)Kind; 7960 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7961 7962 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7963 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7964 7965 Pos = EntriesStart; 7966 for (unsigned i = 0; i < NumEntries; ++i) { 7967 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 7968 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7969 7970 outs() << " [" << i << "]: " 7971 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7972 << ", " 7973 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7974 } 7975 } 7976 7977 static void printCompressedSecondLevelUnwindPage( 7978 StringRef PageData, uint32_t FunctionBase, 7979 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7980 ptrdiff_t Pos = 0; 7981 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7982 (void)Kind; 7983 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 7984 7985 uint32_t NumCommonEncodings = CommonEncodings.size(); 7986 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7987 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7988 7989 uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos); 7990 uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos); 7991 SmallVector<uint32_t, 64> PageEncodings; 7992 if (NumPageEncodings) { 7993 outs() << " Page encodings: (count = " << NumPageEncodings << ")\n"; 7994 Pos = PageEncodingsStart; 7995 for (unsigned i = 0; i < NumPageEncodings; ++i) { 7996 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7997 PageEncodings.push_back(Encoding); 7998 outs() << " encoding[" << (i + NumCommonEncodings) 7999 << "]: " << format("0x%08" PRIx32, Encoding) << '\n'; 8000 } 8001 } 8002 8003 Pos = EntriesStart; 8004 for (unsigned i = 0; i < NumEntries; ++i) { 8005 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 8006 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 8007 uint32_t EncodingIdx = Entry >> 24; 8008 8009 uint32_t Encoding; 8010 if (EncodingIdx < NumCommonEncodings) 8011 Encoding = CommonEncodings[EncodingIdx]; 8012 else 8013 Encoding = PageEncodings[EncodingIdx - NumCommonEncodings]; 8014 8015 outs() << " [" << i << "]: " 8016 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8017 << ", " 8018 << "encoding[" << EncodingIdx 8019 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 8020 } 8021 } 8022 8023 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 8024 std::map<uint64_t, SymbolRef> &Symbols, 8025 const SectionRef &UnwindInfo) { 8026 8027 if (!Obj->isLittleEndian()) { 8028 outs() << "Skipping big-endian __unwind_info section\n"; 8029 return; 8030 } 8031 8032 outs() << "Contents of __unwind_info section:\n"; 8033 8034 StringRef Contents = 8035 unwrapOrError(UnwindInfo.getContents(), Obj->getFileName()); 8036 ptrdiff_t Pos = 0; 8037 8038 //===---------------------------------- 8039 // Section header 8040 //===---------------------------------- 8041 8042 uint32_t Version = readNext<uint32_t>(Contents, Pos); 8043 outs() << " Version: " 8044 << format("0x%" PRIx32, Version) << '\n'; 8045 if (Version != 1) { 8046 outs() << " Skipping section with unknown version\n"; 8047 return; 8048 } 8049 8050 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 8051 outs() << " Common encodings array section offset: " 8052 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 8053 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 8054 outs() << " Number of common encodings in array: " 8055 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 8056 8057 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 8058 outs() << " Personality function array section offset: " 8059 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 8060 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 8061 outs() << " Number of personality functions in array: " 8062 << format("0x%" PRIx32, NumPersonalities) << '\n'; 8063 8064 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 8065 outs() << " Index array section offset: " 8066 << format("0x%" PRIx32, IndicesStart) << '\n'; 8067 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 8068 outs() << " Number of indices in array: " 8069 << format("0x%" PRIx32, NumIndices) << '\n'; 8070 8071 //===---------------------------------- 8072 // A shared list of common encodings 8073 //===---------------------------------- 8074 8075 // These occupy indices in the range [0, N] whenever an encoding is referenced 8076 // from a compressed 2nd level index table. In practice the linker only 8077 // creates ~128 of these, so that indices are available to embed encodings in 8078 // the 2nd level index. 8079 8080 SmallVector<uint32_t, 64> CommonEncodings; 8081 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 8082 Pos = CommonEncodingsStart; 8083 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 8084 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 8085 CommonEncodings.push_back(Encoding); 8086 8087 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 8088 << '\n'; 8089 } 8090 8091 //===---------------------------------- 8092 // Personality functions used in this executable 8093 //===---------------------------------- 8094 8095 // There should be only a handful of these (one per source language, 8096 // roughly). Particularly since they only get 2 bits in the compact encoding. 8097 8098 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 8099 Pos = PersonalitiesStart; 8100 for (unsigned i = 0; i < NumPersonalities; ++i) { 8101 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 8102 outs() << " personality[" << i + 1 8103 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 8104 } 8105 8106 //===---------------------------------- 8107 // The level 1 index entries 8108 //===---------------------------------- 8109 8110 // These specify an approximate place to start searching for the more detailed 8111 // information, sorted by PC. 8112 8113 struct IndexEntry { 8114 uint32_t FunctionOffset; 8115 uint32_t SecondLevelPageStart; 8116 uint32_t LSDAStart; 8117 }; 8118 8119 SmallVector<IndexEntry, 4> IndexEntries; 8120 8121 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 8122 Pos = IndicesStart; 8123 for (unsigned i = 0; i < NumIndices; ++i) { 8124 IndexEntry Entry; 8125 8126 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 8127 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 8128 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 8129 IndexEntries.push_back(Entry); 8130 8131 outs() << " [" << i << "]: " 8132 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 8133 << ", " 8134 << "2nd level page offset=" 8135 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 8136 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 8137 } 8138 8139 //===---------------------------------- 8140 // Next come the LSDA tables 8141 //===---------------------------------- 8142 8143 // The LSDA layout is rather implicit: it's a contiguous array of entries from 8144 // the first top-level index's LSDAOffset to the last (sentinel). 8145 8146 outs() << " LSDA descriptors:\n"; 8147 Pos = IndexEntries[0].LSDAStart; 8148 const uint32_t LSDASize = 2 * sizeof(uint32_t); 8149 int NumLSDAs = 8150 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 8151 8152 for (int i = 0; i < NumLSDAs; ++i) { 8153 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 8154 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 8155 outs() << " [" << i << "]: " 8156 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8157 << ", " 8158 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 8159 } 8160 8161 //===---------------------------------- 8162 // Finally, the 2nd level indices 8163 //===---------------------------------- 8164 8165 // Generally these are 4K in size, and have 2 possible forms: 8166 // + Regular stores up to 511 entries with disparate encodings 8167 // + Compressed stores up to 1021 entries if few enough compact encoding 8168 // values are used. 8169 outs() << " Second level indices:\n"; 8170 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 8171 // The final sentinel top-level index has no associated 2nd level page 8172 if (IndexEntries[i].SecondLevelPageStart == 0) 8173 break; 8174 8175 outs() << " Second level index[" << i << "]: " 8176 << "offset in section=" 8177 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 8178 << ", " 8179 << "base function offset=" 8180 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 8181 8182 Pos = IndexEntries[i].SecondLevelPageStart; 8183 if (Pos + sizeof(uint32_t) > Contents.size()) { 8184 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 8185 continue; 8186 } 8187 8188 uint32_t Kind = 8189 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 8190 if (Kind == 2) 8191 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 8192 else if (Kind == 3) 8193 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 8194 IndexEntries[i].FunctionOffset, 8195 CommonEncodings); 8196 else 8197 outs() << " Skipping 2nd level page with unknown kind " << Kind 8198 << '\n'; 8199 } 8200 } 8201 8202 void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) { 8203 std::map<uint64_t, SymbolRef> Symbols; 8204 for (const SymbolRef &SymRef : Obj->symbols()) { 8205 // Discard any undefined or absolute symbols. They're not going to take part 8206 // in the convenience lookup for unwind info and just take up resources. 8207 auto SectOrErr = SymRef.getSection(); 8208 if (!SectOrErr) { 8209 // TODO: Actually report errors helpfully. 8210 consumeError(SectOrErr.takeError()); 8211 continue; 8212 } 8213 section_iterator Section = *SectOrErr; 8214 if (Section == Obj->section_end()) 8215 continue; 8216 8217 uint64_t Addr = cantFail(SymRef.getValue()); 8218 Symbols.insert(std::make_pair(Addr, SymRef)); 8219 } 8220 8221 for (const SectionRef &Section : Obj->sections()) { 8222 StringRef SectName; 8223 if (Expected<StringRef> NameOrErr = Section.getName()) 8224 SectName = *NameOrErr; 8225 else 8226 consumeError(NameOrErr.takeError()); 8227 8228 if (SectName == "__compact_unwind") 8229 printMachOCompactUnwindSection(Obj, Symbols, Section); 8230 else if (SectName == "__unwind_info") 8231 printMachOUnwindInfoSection(Obj, Symbols, Section); 8232 } 8233 } 8234 8235 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 8236 uint32_t cpusubtype, uint32_t filetype, 8237 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 8238 bool verbose) { 8239 outs() << "Mach header\n"; 8240 outs() << " magic cputype cpusubtype caps filetype ncmds " 8241 "sizeofcmds flags\n"; 8242 if (verbose) { 8243 if (magic == MachO::MH_MAGIC) 8244 outs() << " MH_MAGIC"; 8245 else if (magic == MachO::MH_MAGIC_64) 8246 outs() << "MH_MAGIC_64"; 8247 else 8248 outs() << format(" 0x%08" PRIx32, magic); 8249 switch (cputype) { 8250 case MachO::CPU_TYPE_I386: 8251 outs() << " I386"; 8252 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8253 case MachO::CPU_SUBTYPE_I386_ALL: 8254 outs() << " ALL"; 8255 break; 8256 default: 8257 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8258 break; 8259 } 8260 break; 8261 case MachO::CPU_TYPE_X86_64: 8262 outs() << " X86_64"; 8263 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8264 case MachO::CPU_SUBTYPE_X86_64_ALL: 8265 outs() << " ALL"; 8266 break; 8267 case MachO::CPU_SUBTYPE_X86_64_H: 8268 outs() << " Haswell"; 8269 break; 8270 default: 8271 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8272 break; 8273 } 8274 break; 8275 case MachO::CPU_TYPE_ARM: 8276 outs() << " ARM"; 8277 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8278 case MachO::CPU_SUBTYPE_ARM_ALL: 8279 outs() << " ALL"; 8280 break; 8281 case MachO::CPU_SUBTYPE_ARM_V4T: 8282 outs() << " V4T"; 8283 break; 8284 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 8285 outs() << " V5TEJ"; 8286 break; 8287 case MachO::CPU_SUBTYPE_ARM_XSCALE: 8288 outs() << " XSCALE"; 8289 break; 8290 case MachO::CPU_SUBTYPE_ARM_V6: 8291 outs() << " V6"; 8292 break; 8293 case MachO::CPU_SUBTYPE_ARM_V6M: 8294 outs() << " V6M"; 8295 break; 8296 case MachO::CPU_SUBTYPE_ARM_V7: 8297 outs() << " V7"; 8298 break; 8299 case MachO::CPU_SUBTYPE_ARM_V7EM: 8300 outs() << " V7EM"; 8301 break; 8302 case MachO::CPU_SUBTYPE_ARM_V7K: 8303 outs() << " V7K"; 8304 break; 8305 case MachO::CPU_SUBTYPE_ARM_V7M: 8306 outs() << " V7M"; 8307 break; 8308 case MachO::CPU_SUBTYPE_ARM_V7S: 8309 outs() << " V7S"; 8310 break; 8311 default: 8312 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8313 break; 8314 } 8315 break; 8316 case MachO::CPU_TYPE_ARM64: 8317 outs() << " ARM64"; 8318 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8319 case MachO::CPU_SUBTYPE_ARM64_ALL: 8320 outs() << " ALL"; 8321 break; 8322 case MachO::CPU_SUBTYPE_ARM64_V8: 8323 outs() << " V8"; 8324 break; 8325 case MachO::CPU_SUBTYPE_ARM64E: 8326 outs() << " E"; 8327 break; 8328 default: 8329 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8330 break; 8331 } 8332 break; 8333 case MachO::CPU_TYPE_ARM64_32: 8334 outs() << " ARM64_32"; 8335 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8336 case MachO::CPU_SUBTYPE_ARM64_32_V8: 8337 outs() << " V8"; 8338 break; 8339 default: 8340 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8341 break; 8342 } 8343 break; 8344 case MachO::CPU_TYPE_POWERPC: 8345 outs() << " PPC"; 8346 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8347 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8348 outs() << " ALL"; 8349 break; 8350 default: 8351 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8352 break; 8353 } 8354 break; 8355 case MachO::CPU_TYPE_POWERPC64: 8356 outs() << " PPC64"; 8357 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8358 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8359 outs() << " ALL"; 8360 break; 8361 default: 8362 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8363 break; 8364 } 8365 break; 8366 default: 8367 outs() << format(" %7d", cputype); 8368 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8369 break; 8370 } 8371 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 8372 outs() << " LIB64"; 8373 } else { 8374 outs() << format(" 0x%02" PRIx32, 8375 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8376 } 8377 switch (filetype) { 8378 case MachO::MH_OBJECT: 8379 outs() << " OBJECT"; 8380 break; 8381 case MachO::MH_EXECUTE: 8382 outs() << " EXECUTE"; 8383 break; 8384 case MachO::MH_FVMLIB: 8385 outs() << " FVMLIB"; 8386 break; 8387 case MachO::MH_CORE: 8388 outs() << " CORE"; 8389 break; 8390 case MachO::MH_PRELOAD: 8391 outs() << " PRELOAD"; 8392 break; 8393 case MachO::MH_DYLIB: 8394 outs() << " DYLIB"; 8395 break; 8396 case MachO::MH_DYLIB_STUB: 8397 outs() << " DYLIB_STUB"; 8398 break; 8399 case MachO::MH_DYLINKER: 8400 outs() << " DYLINKER"; 8401 break; 8402 case MachO::MH_BUNDLE: 8403 outs() << " BUNDLE"; 8404 break; 8405 case MachO::MH_DSYM: 8406 outs() << " DSYM"; 8407 break; 8408 case MachO::MH_KEXT_BUNDLE: 8409 outs() << " KEXTBUNDLE"; 8410 break; 8411 case MachO::MH_FILESET: 8412 outs() << " FILESET"; 8413 break; 8414 default: 8415 outs() << format(" %10u", filetype); 8416 break; 8417 } 8418 outs() << format(" %5u", ncmds); 8419 outs() << format(" %10u", sizeofcmds); 8420 uint32_t f = flags; 8421 if (f & MachO::MH_NOUNDEFS) { 8422 outs() << " NOUNDEFS"; 8423 f &= ~MachO::MH_NOUNDEFS; 8424 } 8425 if (f & MachO::MH_INCRLINK) { 8426 outs() << " INCRLINK"; 8427 f &= ~MachO::MH_INCRLINK; 8428 } 8429 if (f & MachO::MH_DYLDLINK) { 8430 outs() << " DYLDLINK"; 8431 f &= ~MachO::MH_DYLDLINK; 8432 } 8433 if (f & MachO::MH_BINDATLOAD) { 8434 outs() << " BINDATLOAD"; 8435 f &= ~MachO::MH_BINDATLOAD; 8436 } 8437 if (f & MachO::MH_PREBOUND) { 8438 outs() << " PREBOUND"; 8439 f &= ~MachO::MH_PREBOUND; 8440 } 8441 if (f & MachO::MH_SPLIT_SEGS) { 8442 outs() << " SPLIT_SEGS"; 8443 f &= ~MachO::MH_SPLIT_SEGS; 8444 } 8445 if (f & MachO::MH_LAZY_INIT) { 8446 outs() << " LAZY_INIT"; 8447 f &= ~MachO::MH_LAZY_INIT; 8448 } 8449 if (f & MachO::MH_TWOLEVEL) { 8450 outs() << " TWOLEVEL"; 8451 f &= ~MachO::MH_TWOLEVEL; 8452 } 8453 if (f & MachO::MH_FORCE_FLAT) { 8454 outs() << " FORCE_FLAT"; 8455 f &= ~MachO::MH_FORCE_FLAT; 8456 } 8457 if (f & MachO::MH_NOMULTIDEFS) { 8458 outs() << " NOMULTIDEFS"; 8459 f &= ~MachO::MH_NOMULTIDEFS; 8460 } 8461 if (f & MachO::MH_NOFIXPREBINDING) { 8462 outs() << " NOFIXPREBINDING"; 8463 f &= ~MachO::MH_NOFIXPREBINDING; 8464 } 8465 if (f & MachO::MH_PREBINDABLE) { 8466 outs() << " PREBINDABLE"; 8467 f &= ~MachO::MH_PREBINDABLE; 8468 } 8469 if (f & MachO::MH_ALLMODSBOUND) { 8470 outs() << " ALLMODSBOUND"; 8471 f &= ~MachO::MH_ALLMODSBOUND; 8472 } 8473 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8474 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8475 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8476 } 8477 if (f & MachO::MH_CANONICAL) { 8478 outs() << " CANONICAL"; 8479 f &= ~MachO::MH_CANONICAL; 8480 } 8481 if (f & MachO::MH_WEAK_DEFINES) { 8482 outs() << " WEAK_DEFINES"; 8483 f &= ~MachO::MH_WEAK_DEFINES; 8484 } 8485 if (f & MachO::MH_BINDS_TO_WEAK) { 8486 outs() << " BINDS_TO_WEAK"; 8487 f &= ~MachO::MH_BINDS_TO_WEAK; 8488 } 8489 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8490 outs() << " ALLOW_STACK_EXECUTION"; 8491 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8492 } 8493 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8494 outs() << " DEAD_STRIPPABLE_DYLIB"; 8495 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8496 } 8497 if (f & MachO::MH_PIE) { 8498 outs() << " PIE"; 8499 f &= ~MachO::MH_PIE; 8500 } 8501 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8502 outs() << " NO_REEXPORTED_DYLIBS"; 8503 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8504 } 8505 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8506 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8507 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8508 } 8509 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8510 outs() << " MH_NO_HEAP_EXECUTION"; 8511 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8512 } 8513 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8514 outs() << " APP_EXTENSION_SAFE"; 8515 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8516 } 8517 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8518 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8519 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8520 } 8521 if (f != 0 || flags == 0) 8522 outs() << format(" 0x%08" PRIx32, f); 8523 } else { 8524 outs() << format(" 0x%08" PRIx32, magic); 8525 outs() << format(" %7d", cputype); 8526 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8527 outs() << format(" 0x%02" PRIx32, 8528 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8529 outs() << format(" %10u", filetype); 8530 outs() << format(" %5u", ncmds); 8531 outs() << format(" %10u", sizeofcmds); 8532 outs() << format(" 0x%08" PRIx32, flags); 8533 } 8534 outs() << "\n"; 8535 } 8536 8537 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8538 StringRef SegName, uint64_t vmaddr, 8539 uint64_t vmsize, uint64_t fileoff, 8540 uint64_t filesize, uint32_t maxprot, 8541 uint32_t initprot, uint32_t nsects, 8542 uint32_t flags, uint32_t object_size, 8543 bool verbose) { 8544 uint64_t expected_cmdsize; 8545 if (cmd == MachO::LC_SEGMENT) { 8546 outs() << " cmd LC_SEGMENT\n"; 8547 expected_cmdsize = nsects; 8548 expected_cmdsize *= sizeof(struct MachO::section); 8549 expected_cmdsize += sizeof(struct MachO::segment_command); 8550 } else { 8551 outs() << " cmd LC_SEGMENT_64\n"; 8552 expected_cmdsize = nsects; 8553 expected_cmdsize *= sizeof(struct MachO::section_64); 8554 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8555 } 8556 outs() << " cmdsize " << cmdsize; 8557 if (cmdsize != expected_cmdsize) 8558 outs() << " Inconsistent size\n"; 8559 else 8560 outs() << "\n"; 8561 outs() << " segname " << SegName << "\n"; 8562 if (cmd == MachO::LC_SEGMENT_64) { 8563 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8564 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8565 } else { 8566 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8567 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8568 } 8569 outs() << " fileoff " << fileoff; 8570 if (fileoff > object_size) 8571 outs() << " (past end of file)\n"; 8572 else 8573 outs() << "\n"; 8574 outs() << " filesize " << filesize; 8575 if (fileoff + filesize > object_size) 8576 outs() << " (past end of file)\n"; 8577 else 8578 outs() << "\n"; 8579 if (verbose) { 8580 if ((maxprot & 8581 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8582 MachO::VM_PROT_EXECUTE)) != 0) 8583 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8584 else { 8585 outs() << " maxprot "; 8586 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8587 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8588 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8589 } 8590 if ((initprot & 8591 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8592 MachO::VM_PROT_EXECUTE)) != 0) 8593 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8594 else { 8595 outs() << " initprot "; 8596 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8597 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8598 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8599 } 8600 } else { 8601 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8602 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8603 } 8604 outs() << " nsects " << nsects << "\n"; 8605 if (verbose) { 8606 outs() << " flags"; 8607 if (flags == 0) 8608 outs() << " (none)\n"; 8609 else { 8610 if (flags & MachO::SG_HIGHVM) { 8611 outs() << " HIGHVM"; 8612 flags &= ~MachO::SG_HIGHVM; 8613 } 8614 if (flags & MachO::SG_FVMLIB) { 8615 outs() << " FVMLIB"; 8616 flags &= ~MachO::SG_FVMLIB; 8617 } 8618 if (flags & MachO::SG_NORELOC) { 8619 outs() << " NORELOC"; 8620 flags &= ~MachO::SG_NORELOC; 8621 } 8622 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8623 outs() << " PROTECTED_VERSION_1"; 8624 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8625 } 8626 if (flags & MachO::SG_READ_ONLY) { 8627 // Apple's otool prints the SG_ prefix for this flag, but not for the 8628 // others. 8629 outs() << " SG_READ_ONLY"; 8630 flags &= ~MachO::SG_READ_ONLY; 8631 } 8632 if (flags) 8633 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8634 else 8635 outs() << "\n"; 8636 } 8637 } else { 8638 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8639 } 8640 } 8641 8642 static void PrintSection(const char *sectname, const char *segname, 8643 uint64_t addr, uint64_t size, uint32_t offset, 8644 uint32_t align, uint32_t reloff, uint32_t nreloc, 8645 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8646 uint32_t cmd, const char *sg_segname, 8647 uint32_t filetype, uint32_t object_size, 8648 bool verbose) { 8649 outs() << "Section\n"; 8650 outs() << " sectname " << format("%.16s\n", sectname); 8651 outs() << " segname " << format("%.16s", segname); 8652 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8653 outs() << " (does not match segment)\n"; 8654 else 8655 outs() << "\n"; 8656 if (cmd == MachO::LC_SEGMENT_64) { 8657 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8658 outs() << " size " << format("0x%016" PRIx64, size); 8659 } else { 8660 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8661 outs() << " size " << format("0x%08" PRIx64, size); 8662 } 8663 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8664 outs() << " (past end of file)\n"; 8665 else 8666 outs() << "\n"; 8667 outs() << " offset " << offset; 8668 if (offset > object_size) 8669 outs() << " (past end of file)\n"; 8670 else 8671 outs() << "\n"; 8672 uint32_t align_shifted = 1 << align; 8673 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8674 outs() << " reloff " << reloff; 8675 if (reloff > object_size) 8676 outs() << " (past end of file)\n"; 8677 else 8678 outs() << "\n"; 8679 outs() << " nreloc " << nreloc; 8680 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8681 outs() << " (past end of file)\n"; 8682 else 8683 outs() << "\n"; 8684 uint32_t section_type = flags & MachO::SECTION_TYPE; 8685 if (verbose) { 8686 outs() << " type"; 8687 if (section_type == MachO::S_REGULAR) 8688 outs() << " S_REGULAR\n"; 8689 else if (section_type == MachO::S_ZEROFILL) 8690 outs() << " S_ZEROFILL\n"; 8691 else if (section_type == MachO::S_CSTRING_LITERALS) 8692 outs() << " S_CSTRING_LITERALS\n"; 8693 else if (section_type == MachO::S_4BYTE_LITERALS) 8694 outs() << " S_4BYTE_LITERALS\n"; 8695 else if (section_type == MachO::S_8BYTE_LITERALS) 8696 outs() << " S_8BYTE_LITERALS\n"; 8697 else if (section_type == MachO::S_16BYTE_LITERALS) 8698 outs() << " S_16BYTE_LITERALS\n"; 8699 else if (section_type == MachO::S_LITERAL_POINTERS) 8700 outs() << " S_LITERAL_POINTERS\n"; 8701 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8702 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8703 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8704 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8705 else if (section_type == MachO::S_SYMBOL_STUBS) 8706 outs() << " S_SYMBOL_STUBS\n"; 8707 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8708 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8709 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8710 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8711 else if (section_type == MachO::S_COALESCED) 8712 outs() << " S_COALESCED\n"; 8713 else if (section_type == MachO::S_INTERPOSING) 8714 outs() << " S_INTERPOSING\n"; 8715 else if (section_type == MachO::S_DTRACE_DOF) 8716 outs() << " S_DTRACE_DOF\n"; 8717 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8718 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8719 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8720 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8721 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8722 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8723 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8724 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8725 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8726 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8727 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8728 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8729 else if (section_type == MachO::S_INIT_FUNC_OFFSETS) 8730 outs() << " S_INIT_FUNC_OFFSETS\n"; 8731 else 8732 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8733 outs() << "attributes"; 8734 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8735 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8736 outs() << " PURE_INSTRUCTIONS"; 8737 if (section_attributes & MachO::S_ATTR_NO_TOC) 8738 outs() << " NO_TOC"; 8739 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8740 outs() << " STRIP_STATIC_SYMS"; 8741 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8742 outs() << " NO_DEAD_STRIP"; 8743 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8744 outs() << " LIVE_SUPPORT"; 8745 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8746 outs() << " SELF_MODIFYING_CODE"; 8747 if (section_attributes & MachO::S_ATTR_DEBUG) 8748 outs() << " DEBUG"; 8749 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8750 outs() << " SOME_INSTRUCTIONS"; 8751 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8752 outs() << " EXT_RELOC"; 8753 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8754 outs() << " LOC_RELOC"; 8755 if (section_attributes == 0) 8756 outs() << " (none)"; 8757 outs() << "\n"; 8758 } else 8759 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8760 outs() << " reserved1 " << reserved1; 8761 if (section_type == MachO::S_SYMBOL_STUBS || 8762 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8763 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8764 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8765 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8766 outs() << " (index into indirect symbol table)\n"; 8767 else 8768 outs() << "\n"; 8769 outs() << " reserved2 " << reserved2; 8770 if (section_type == MachO::S_SYMBOL_STUBS) 8771 outs() << " (size of stubs)\n"; 8772 else 8773 outs() << "\n"; 8774 } 8775 8776 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8777 uint32_t object_size) { 8778 outs() << " cmd LC_SYMTAB\n"; 8779 outs() << " cmdsize " << st.cmdsize; 8780 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8781 outs() << " Incorrect size\n"; 8782 else 8783 outs() << "\n"; 8784 outs() << " symoff " << st.symoff; 8785 if (st.symoff > object_size) 8786 outs() << " (past end of file)\n"; 8787 else 8788 outs() << "\n"; 8789 outs() << " nsyms " << st.nsyms; 8790 uint64_t big_size; 8791 if (Is64Bit) { 8792 big_size = st.nsyms; 8793 big_size *= sizeof(struct MachO::nlist_64); 8794 big_size += st.symoff; 8795 if (big_size > object_size) 8796 outs() << " (past end of file)\n"; 8797 else 8798 outs() << "\n"; 8799 } else { 8800 big_size = st.nsyms; 8801 big_size *= sizeof(struct MachO::nlist); 8802 big_size += st.symoff; 8803 if (big_size > object_size) 8804 outs() << " (past end of file)\n"; 8805 else 8806 outs() << "\n"; 8807 } 8808 outs() << " stroff " << st.stroff; 8809 if (st.stroff > object_size) 8810 outs() << " (past end of file)\n"; 8811 else 8812 outs() << "\n"; 8813 outs() << " strsize " << st.strsize; 8814 big_size = st.stroff; 8815 big_size += st.strsize; 8816 if (big_size > object_size) 8817 outs() << " (past end of file)\n"; 8818 else 8819 outs() << "\n"; 8820 } 8821 8822 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8823 uint32_t nsyms, uint32_t object_size, 8824 bool Is64Bit) { 8825 outs() << " cmd LC_DYSYMTAB\n"; 8826 outs() << " cmdsize " << dyst.cmdsize; 8827 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8828 outs() << " Incorrect size\n"; 8829 else 8830 outs() << "\n"; 8831 outs() << " ilocalsym " << dyst.ilocalsym; 8832 if (dyst.ilocalsym > nsyms) 8833 outs() << " (greater than the number of symbols)\n"; 8834 else 8835 outs() << "\n"; 8836 outs() << " nlocalsym " << dyst.nlocalsym; 8837 uint64_t big_size; 8838 big_size = dyst.ilocalsym; 8839 big_size += dyst.nlocalsym; 8840 if (big_size > nsyms) 8841 outs() << " (past the end of the symbol table)\n"; 8842 else 8843 outs() << "\n"; 8844 outs() << " iextdefsym " << dyst.iextdefsym; 8845 if (dyst.iextdefsym > nsyms) 8846 outs() << " (greater than the number of symbols)\n"; 8847 else 8848 outs() << "\n"; 8849 outs() << " nextdefsym " << dyst.nextdefsym; 8850 big_size = dyst.iextdefsym; 8851 big_size += dyst.nextdefsym; 8852 if (big_size > nsyms) 8853 outs() << " (past the end of the symbol table)\n"; 8854 else 8855 outs() << "\n"; 8856 outs() << " iundefsym " << dyst.iundefsym; 8857 if (dyst.iundefsym > nsyms) 8858 outs() << " (greater than the number of symbols)\n"; 8859 else 8860 outs() << "\n"; 8861 outs() << " nundefsym " << dyst.nundefsym; 8862 big_size = dyst.iundefsym; 8863 big_size += dyst.nundefsym; 8864 if (big_size > nsyms) 8865 outs() << " (past the end of the symbol table)\n"; 8866 else 8867 outs() << "\n"; 8868 outs() << " tocoff " << dyst.tocoff; 8869 if (dyst.tocoff > object_size) 8870 outs() << " (past end of file)\n"; 8871 else 8872 outs() << "\n"; 8873 outs() << " ntoc " << dyst.ntoc; 8874 big_size = dyst.ntoc; 8875 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8876 big_size += dyst.tocoff; 8877 if (big_size > object_size) 8878 outs() << " (past end of file)\n"; 8879 else 8880 outs() << "\n"; 8881 outs() << " modtaboff " << dyst.modtaboff; 8882 if (dyst.modtaboff > object_size) 8883 outs() << " (past end of file)\n"; 8884 else 8885 outs() << "\n"; 8886 outs() << " nmodtab " << dyst.nmodtab; 8887 uint64_t modtabend; 8888 if (Is64Bit) { 8889 modtabend = dyst.nmodtab; 8890 modtabend *= sizeof(struct MachO::dylib_module_64); 8891 modtabend += dyst.modtaboff; 8892 } else { 8893 modtabend = dyst.nmodtab; 8894 modtabend *= sizeof(struct MachO::dylib_module); 8895 modtabend += dyst.modtaboff; 8896 } 8897 if (modtabend > object_size) 8898 outs() << " (past end of file)\n"; 8899 else 8900 outs() << "\n"; 8901 outs() << " extrefsymoff " << dyst.extrefsymoff; 8902 if (dyst.extrefsymoff > object_size) 8903 outs() << " (past end of file)\n"; 8904 else 8905 outs() << "\n"; 8906 outs() << " nextrefsyms " << dyst.nextrefsyms; 8907 big_size = dyst.nextrefsyms; 8908 big_size *= sizeof(struct MachO::dylib_reference); 8909 big_size += dyst.extrefsymoff; 8910 if (big_size > object_size) 8911 outs() << " (past end of file)\n"; 8912 else 8913 outs() << "\n"; 8914 outs() << " indirectsymoff " << dyst.indirectsymoff; 8915 if (dyst.indirectsymoff > object_size) 8916 outs() << " (past end of file)\n"; 8917 else 8918 outs() << "\n"; 8919 outs() << " nindirectsyms " << dyst.nindirectsyms; 8920 big_size = dyst.nindirectsyms; 8921 big_size *= sizeof(uint32_t); 8922 big_size += dyst.indirectsymoff; 8923 if (big_size > object_size) 8924 outs() << " (past end of file)\n"; 8925 else 8926 outs() << "\n"; 8927 outs() << " extreloff " << dyst.extreloff; 8928 if (dyst.extreloff > object_size) 8929 outs() << " (past end of file)\n"; 8930 else 8931 outs() << "\n"; 8932 outs() << " nextrel " << dyst.nextrel; 8933 big_size = dyst.nextrel; 8934 big_size *= sizeof(struct MachO::relocation_info); 8935 big_size += dyst.extreloff; 8936 if (big_size > object_size) 8937 outs() << " (past end of file)\n"; 8938 else 8939 outs() << "\n"; 8940 outs() << " locreloff " << dyst.locreloff; 8941 if (dyst.locreloff > object_size) 8942 outs() << " (past end of file)\n"; 8943 else 8944 outs() << "\n"; 8945 outs() << " nlocrel " << dyst.nlocrel; 8946 big_size = dyst.nlocrel; 8947 big_size *= sizeof(struct MachO::relocation_info); 8948 big_size += dyst.locreloff; 8949 if (big_size > object_size) 8950 outs() << " (past end of file)\n"; 8951 else 8952 outs() << "\n"; 8953 } 8954 8955 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8956 uint32_t object_size) { 8957 if (dc.cmd == MachO::LC_DYLD_INFO) 8958 outs() << " cmd LC_DYLD_INFO\n"; 8959 else 8960 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8961 outs() << " cmdsize " << dc.cmdsize; 8962 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8963 outs() << " Incorrect size\n"; 8964 else 8965 outs() << "\n"; 8966 outs() << " rebase_off " << dc.rebase_off; 8967 if (dc.rebase_off > object_size) 8968 outs() << " (past end of file)\n"; 8969 else 8970 outs() << "\n"; 8971 outs() << " rebase_size " << dc.rebase_size; 8972 uint64_t big_size; 8973 big_size = dc.rebase_off; 8974 big_size += dc.rebase_size; 8975 if (big_size > object_size) 8976 outs() << " (past end of file)\n"; 8977 else 8978 outs() << "\n"; 8979 outs() << " bind_off " << dc.bind_off; 8980 if (dc.bind_off > object_size) 8981 outs() << " (past end of file)\n"; 8982 else 8983 outs() << "\n"; 8984 outs() << " bind_size " << dc.bind_size; 8985 big_size = dc.bind_off; 8986 big_size += dc.bind_size; 8987 if (big_size > object_size) 8988 outs() << " (past end of file)\n"; 8989 else 8990 outs() << "\n"; 8991 outs() << " weak_bind_off " << dc.weak_bind_off; 8992 if (dc.weak_bind_off > object_size) 8993 outs() << " (past end of file)\n"; 8994 else 8995 outs() << "\n"; 8996 outs() << " weak_bind_size " << dc.weak_bind_size; 8997 big_size = dc.weak_bind_off; 8998 big_size += dc.weak_bind_size; 8999 if (big_size > object_size) 9000 outs() << " (past end of file)\n"; 9001 else 9002 outs() << "\n"; 9003 outs() << " lazy_bind_off " << dc.lazy_bind_off; 9004 if (dc.lazy_bind_off > object_size) 9005 outs() << " (past end of file)\n"; 9006 else 9007 outs() << "\n"; 9008 outs() << " lazy_bind_size " << dc.lazy_bind_size; 9009 big_size = dc.lazy_bind_off; 9010 big_size += dc.lazy_bind_size; 9011 if (big_size > object_size) 9012 outs() << " (past end of file)\n"; 9013 else 9014 outs() << "\n"; 9015 outs() << " export_off " << dc.export_off; 9016 if (dc.export_off > object_size) 9017 outs() << " (past end of file)\n"; 9018 else 9019 outs() << "\n"; 9020 outs() << " export_size " << dc.export_size; 9021 big_size = dc.export_off; 9022 big_size += dc.export_size; 9023 if (big_size > object_size) 9024 outs() << " (past end of file)\n"; 9025 else 9026 outs() << "\n"; 9027 } 9028 9029 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 9030 const char *Ptr) { 9031 if (dyld.cmd == MachO::LC_ID_DYLINKER) 9032 outs() << " cmd LC_ID_DYLINKER\n"; 9033 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 9034 outs() << " cmd LC_LOAD_DYLINKER\n"; 9035 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 9036 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 9037 else 9038 outs() << " cmd ?(" << dyld.cmd << ")\n"; 9039 outs() << " cmdsize " << dyld.cmdsize; 9040 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 9041 outs() << " Incorrect size\n"; 9042 else 9043 outs() << "\n"; 9044 if (dyld.name >= dyld.cmdsize) 9045 outs() << " name ?(bad offset " << dyld.name << ")\n"; 9046 else { 9047 const char *P = (const char *)(Ptr) + dyld.name; 9048 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 9049 } 9050 } 9051 9052 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 9053 outs() << " cmd LC_UUID\n"; 9054 outs() << " cmdsize " << uuid.cmdsize; 9055 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 9056 outs() << " Incorrect size\n"; 9057 else 9058 outs() << "\n"; 9059 outs() << " uuid "; 9060 for (int i = 0; i < 16; ++i) { 9061 outs() << format("%02" PRIX32, uuid.uuid[i]); 9062 if (i == 3 || i == 5 || i == 7 || i == 9) 9063 outs() << "-"; 9064 } 9065 outs() << "\n"; 9066 } 9067 9068 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 9069 outs() << " cmd LC_RPATH\n"; 9070 outs() << " cmdsize " << rpath.cmdsize; 9071 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 9072 outs() << " Incorrect size\n"; 9073 else 9074 outs() << "\n"; 9075 if (rpath.path >= rpath.cmdsize) 9076 outs() << " path ?(bad offset " << rpath.path << ")\n"; 9077 else { 9078 const char *P = (const char *)(Ptr) + rpath.path; 9079 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 9080 } 9081 } 9082 9083 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 9084 StringRef LoadCmdName; 9085 switch (vd.cmd) { 9086 case MachO::LC_VERSION_MIN_MACOSX: 9087 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 9088 break; 9089 case MachO::LC_VERSION_MIN_IPHONEOS: 9090 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 9091 break; 9092 case MachO::LC_VERSION_MIN_TVOS: 9093 LoadCmdName = "LC_VERSION_MIN_TVOS"; 9094 break; 9095 case MachO::LC_VERSION_MIN_WATCHOS: 9096 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 9097 break; 9098 default: 9099 llvm_unreachable("Unknown version min load command"); 9100 } 9101 9102 outs() << " cmd " << LoadCmdName << '\n'; 9103 outs() << " cmdsize " << vd.cmdsize; 9104 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 9105 outs() << " Incorrect size\n"; 9106 else 9107 outs() << "\n"; 9108 outs() << " version " 9109 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 9110 << MachOObjectFile::getVersionMinMinor(vd, false); 9111 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 9112 if (Update != 0) 9113 outs() << "." << Update; 9114 outs() << "\n"; 9115 if (vd.sdk == 0) 9116 outs() << " sdk n/a"; 9117 else { 9118 outs() << " sdk " 9119 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 9120 << MachOObjectFile::getVersionMinMinor(vd, true); 9121 } 9122 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 9123 if (Update != 0) 9124 outs() << "." << Update; 9125 outs() << "\n"; 9126 } 9127 9128 static void PrintNoteLoadCommand(MachO::note_command Nt) { 9129 outs() << " cmd LC_NOTE\n"; 9130 outs() << " cmdsize " << Nt.cmdsize; 9131 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 9132 outs() << " Incorrect size\n"; 9133 else 9134 outs() << "\n"; 9135 const char *d = Nt.data_owner; 9136 outs() << "data_owner " << format("%.16s\n", d); 9137 outs() << " offset " << Nt.offset << "\n"; 9138 outs() << " size " << Nt.size << "\n"; 9139 } 9140 9141 static void PrintBuildToolVersion(MachO::build_tool_version bv, bool verbose) { 9142 outs() << " tool "; 9143 if (verbose) 9144 outs() << MachOObjectFile::getBuildTool(bv.tool); 9145 else 9146 outs() << bv.tool; 9147 outs() << "\n"; 9148 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 9149 << "\n"; 9150 } 9151 9152 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 9153 MachO::build_version_command bd, 9154 bool verbose) { 9155 outs() << " cmd LC_BUILD_VERSION\n"; 9156 outs() << " cmdsize " << bd.cmdsize; 9157 if (bd.cmdsize != 9158 sizeof(struct MachO::build_version_command) + 9159 bd.ntools * sizeof(struct MachO::build_tool_version)) 9160 outs() << " Incorrect size\n"; 9161 else 9162 outs() << "\n"; 9163 outs() << " platform "; 9164 if (verbose) 9165 outs() << MachOObjectFile::getBuildPlatform(bd.platform); 9166 else 9167 outs() << bd.platform; 9168 outs() << "\n"; 9169 if (bd.sdk) 9170 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 9171 << "\n"; 9172 else 9173 outs() << " sdk n/a\n"; 9174 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 9175 << "\n"; 9176 outs() << " ntools " << bd.ntools << "\n"; 9177 for (unsigned i = 0; i < bd.ntools; ++i) { 9178 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 9179 PrintBuildToolVersion(bv, verbose); 9180 } 9181 } 9182 9183 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 9184 outs() << " cmd LC_SOURCE_VERSION\n"; 9185 outs() << " cmdsize " << sd.cmdsize; 9186 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 9187 outs() << " Incorrect size\n"; 9188 else 9189 outs() << "\n"; 9190 uint64_t a = (sd.version >> 40) & 0xffffff; 9191 uint64_t b = (sd.version >> 30) & 0x3ff; 9192 uint64_t c = (sd.version >> 20) & 0x3ff; 9193 uint64_t d = (sd.version >> 10) & 0x3ff; 9194 uint64_t e = sd.version & 0x3ff; 9195 outs() << " version " << a << "." << b; 9196 if (e != 0) 9197 outs() << "." << c << "." << d << "." << e; 9198 else if (d != 0) 9199 outs() << "." << c << "." << d; 9200 else if (c != 0) 9201 outs() << "." << c; 9202 outs() << "\n"; 9203 } 9204 9205 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 9206 outs() << " cmd LC_MAIN\n"; 9207 outs() << " cmdsize " << ep.cmdsize; 9208 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 9209 outs() << " Incorrect size\n"; 9210 else 9211 outs() << "\n"; 9212 outs() << " entryoff " << ep.entryoff << "\n"; 9213 outs() << " stacksize " << ep.stacksize << "\n"; 9214 } 9215 9216 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 9217 uint32_t object_size) { 9218 outs() << " cmd LC_ENCRYPTION_INFO\n"; 9219 outs() << " cmdsize " << ec.cmdsize; 9220 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 9221 outs() << " Incorrect size\n"; 9222 else 9223 outs() << "\n"; 9224 outs() << " cryptoff " << ec.cryptoff; 9225 if (ec.cryptoff > object_size) 9226 outs() << " (past end of file)\n"; 9227 else 9228 outs() << "\n"; 9229 outs() << " cryptsize " << ec.cryptsize; 9230 if (ec.cryptsize > object_size) 9231 outs() << " (past end of file)\n"; 9232 else 9233 outs() << "\n"; 9234 outs() << " cryptid " << ec.cryptid << "\n"; 9235 } 9236 9237 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 9238 uint32_t object_size) { 9239 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 9240 outs() << " cmdsize " << ec.cmdsize; 9241 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 9242 outs() << " Incorrect size\n"; 9243 else 9244 outs() << "\n"; 9245 outs() << " cryptoff " << ec.cryptoff; 9246 if (ec.cryptoff > object_size) 9247 outs() << " (past end of file)\n"; 9248 else 9249 outs() << "\n"; 9250 outs() << " cryptsize " << ec.cryptsize; 9251 if (ec.cryptsize > object_size) 9252 outs() << " (past end of file)\n"; 9253 else 9254 outs() << "\n"; 9255 outs() << " cryptid " << ec.cryptid << "\n"; 9256 outs() << " pad " << ec.pad << "\n"; 9257 } 9258 9259 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 9260 const char *Ptr) { 9261 outs() << " cmd LC_LINKER_OPTION\n"; 9262 outs() << " cmdsize " << lo.cmdsize; 9263 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 9264 outs() << " Incorrect size\n"; 9265 else 9266 outs() << "\n"; 9267 outs() << " count " << lo.count << "\n"; 9268 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 9269 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 9270 uint32_t i = 0; 9271 while (left > 0) { 9272 while (*string == '\0' && left > 0) { 9273 string++; 9274 left--; 9275 } 9276 if (left > 0) { 9277 i++; 9278 outs() << " string #" << i << " " << format("%.*s\n", left, string); 9279 uint32_t NullPos = StringRef(string, left).find('\0'); 9280 uint32_t len = std::min(NullPos, left) + 1; 9281 string += len; 9282 left -= len; 9283 } 9284 } 9285 if (lo.count != i) 9286 outs() << " count " << lo.count << " does not match number of strings " 9287 << i << "\n"; 9288 } 9289 9290 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 9291 const char *Ptr) { 9292 outs() << " cmd LC_SUB_FRAMEWORK\n"; 9293 outs() << " cmdsize " << sub.cmdsize; 9294 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 9295 outs() << " Incorrect size\n"; 9296 else 9297 outs() << "\n"; 9298 if (sub.umbrella < sub.cmdsize) { 9299 const char *P = Ptr + sub.umbrella; 9300 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 9301 } else { 9302 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 9303 } 9304 } 9305 9306 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 9307 const char *Ptr) { 9308 outs() << " cmd LC_SUB_UMBRELLA\n"; 9309 outs() << " cmdsize " << sub.cmdsize; 9310 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 9311 outs() << " Incorrect size\n"; 9312 else 9313 outs() << "\n"; 9314 if (sub.sub_umbrella < sub.cmdsize) { 9315 const char *P = Ptr + sub.sub_umbrella; 9316 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 9317 } else { 9318 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 9319 } 9320 } 9321 9322 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 9323 const char *Ptr) { 9324 outs() << " cmd LC_SUB_LIBRARY\n"; 9325 outs() << " cmdsize " << sub.cmdsize; 9326 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 9327 outs() << " Incorrect size\n"; 9328 else 9329 outs() << "\n"; 9330 if (sub.sub_library < sub.cmdsize) { 9331 const char *P = Ptr + sub.sub_library; 9332 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 9333 } else { 9334 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 9335 } 9336 } 9337 9338 static void PrintSubClientCommand(MachO::sub_client_command sub, 9339 const char *Ptr) { 9340 outs() << " cmd LC_SUB_CLIENT\n"; 9341 outs() << " cmdsize " << sub.cmdsize; 9342 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 9343 outs() << " Incorrect size\n"; 9344 else 9345 outs() << "\n"; 9346 if (sub.client < sub.cmdsize) { 9347 const char *P = Ptr + sub.client; 9348 outs() << " client " << P << " (offset " << sub.client << ")\n"; 9349 } else { 9350 outs() << " client ?(bad offset " << sub.client << ")\n"; 9351 } 9352 } 9353 9354 static void PrintRoutinesCommand(MachO::routines_command r) { 9355 outs() << " cmd LC_ROUTINES\n"; 9356 outs() << " cmdsize " << r.cmdsize; 9357 if (r.cmdsize != sizeof(struct MachO::routines_command)) 9358 outs() << " Incorrect size\n"; 9359 else 9360 outs() << "\n"; 9361 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 9362 outs() << " init_module " << r.init_module << "\n"; 9363 outs() << " reserved1 " << r.reserved1 << "\n"; 9364 outs() << " reserved2 " << r.reserved2 << "\n"; 9365 outs() << " reserved3 " << r.reserved3 << "\n"; 9366 outs() << " reserved4 " << r.reserved4 << "\n"; 9367 outs() << " reserved5 " << r.reserved5 << "\n"; 9368 outs() << " reserved6 " << r.reserved6 << "\n"; 9369 } 9370 9371 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 9372 outs() << " cmd LC_ROUTINES_64\n"; 9373 outs() << " cmdsize " << r.cmdsize; 9374 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 9375 outs() << " Incorrect size\n"; 9376 else 9377 outs() << "\n"; 9378 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 9379 outs() << " init_module " << r.init_module << "\n"; 9380 outs() << " reserved1 " << r.reserved1 << "\n"; 9381 outs() << " reserved2 " << r.reserved2 << "\n"; 9382 outs() << " reserved3 " << r.reserved3 << "\n"; 9383 outs() << " reserved4 " << r.reserved4 << "\n"; 9384 outs() << " reserved5 " << r.reserved5 << "\n"; 9385 outs() << " reserved6 " << r.reserved6 << "\n"; 9386 } 9387 9388 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 9389 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 9390 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 9391 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 9392 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 9393 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 9394 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 9395 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 9396 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 9397 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 9398 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 9399 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 9400 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 9401 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 9402 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 9403 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 9404 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 9405 } 9406 9407 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 9408 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 9409 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 9410 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 9411 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 9412 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 9413 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 9414 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 9415 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 9416 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 9417 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 9418 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 9419 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 9420 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 9421 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 9422 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 9423 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 9424 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 9425 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 9426 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 9427 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 9428 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 9429 } 9430 9431 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 9432 uint32_t f; 9433 outs() << "\t mmst_reg "; 9434 for (f = 0; f < 10; f++) 9435 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 9436 outs() << "\n"; 9437 outs() << "\t mmst_rsrv "; 9438 for (f = 0; f < 6; f++) 9439 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 9440 outs() << "\n"; 9441 } 9442 9443 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 9444 uint32_t f; 9445 outs() << "\t xmm_reg "; 9446 for (f = 0; f < 16; f++) 9447 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 9448 outs() << "\n"; 9449 } 9450 9451 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 9452 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 9453 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 9454 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 9455 outs() << " denorm " << fpu.fpu_fcw.denorm; 9456 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 9457 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 9458 outs() << " undfl " << fpu.fpu_fcw.undfl; 9459 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 9460 outs() << "\t\t pc "; 9461 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 9462 outs() << "FP_PREC_24B "; 9463 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 9464 outs() << "FP_PREC_53B "; 9465 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 9466 outs() << "FP_PREC_64B "; 9467 else 9468 outs() << fpu.fpu_fcw.pc << " "; 9469 outs() << "rc "; 9470 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 9471 outs() << "FP_RND_NEAR "; 9472 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 9473 outs() << "FP_RND_DOWN "; 9474 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 9475 outs() << "FP_RND_UP "; 9476 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 9477 outs() << "FP_CHOP "; 9478 outs() << "\n"; 9479 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 9480 outs() << " denorm " << fpu.fpu_fsw.denorm; 9481 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 9482 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 9483 outs() << " undfl " << fpu.fpu_fsw.undfl; 9484 outs() << " precis " << fpu.fpu_fsw.precis; 9485 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 9486 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9487 outs() << " c0 " << fpu.fpu_fsw.c0; 9488 outs() << " c1 " << fpu.fpu_fsw.c1; 9489 outs() << " c2 " << fpu.fpu_fsw.c2; 9490 outs() << " tos " << fpu.fpu_fsw.tos; 9491 outs() << " c3 " << fpu.fpu_fsw.c3; 9492 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9493 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9494 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9495 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9496 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9497 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9498 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9499 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9500 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9501 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9502 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9503 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9504 outs() << "\n"; 9505 outs() << "\t fpu_stmm0:\n"; 9506 Print_mmst_reg(fpu.fpu_stmm0); 9507 outs() << "\t fpu_stmm1:\n"; 9508 Print_mmst_reg(fpu.fpu_stmm1); 9509 outs() << "\t fpu_stmm2:\n"; 9510 Print_mmst_reg(fpu.fpu_stmm2); 9511 outs() << "\t fpu_stmm3:\n"; 9512 Print_mmst_reg(fpu.fpu_stmm3); 9513 outs() << "\t fpu_stmm4:\n"; 9514 Print_mmst_reg(fpu.fpu_stmm4); 9515 outs() << "\t fpu_stmm5:\n"; 9516 Print_mmst_reg(fpu.fpu_stmm5); 9517 outs() << "\t fpu_stmm6:\n"; 9518 Print_mmst_reg(fpu.fpu_stmm6); 9519 outs() << "\t fpu_stmm7:\n"; 9520 Print_mmst_reg(fpu.fpu_stmm7); 9521 outs() << "\t fpu_xmm0:\n"; 9522 Print_xmm_reg(fpu.fpu_xmm0); 9523 outs() << "\t fpu_xmm1:\n"; 9524 Print_xmm_reg(fpu.fpu_xmm1); 9525 outs() << "\t fpu_xmm2:\n"; 9526 Print_xmm_reg(fpu.fpu_xmm2); 9527 outs() << "\t fpu_xmm3:\n"; 9528 Print_xmm_reg(fpu.fpu_xmm3); 9529 outs() << "\t fpu_xmm4:\n"; 9530 Print_xmm_reg(fpu.fpu_xmm4); 9531 outs() << "\t fpu_xmm5:\n"; 9532 Print_xmm_reg(fpu.fpu_xmm5); 9533 outs() << "\t fpu_xmm6:\n"; 9534 Print_xmm_reg(fpu.fpu_xmm6); 9535 outs() << "\t fpu_xmm7:\n"; 9536 Print_xmm_reg(fpu.fpu_xmm7); 9537 outs() << "\t fpu_xmm8:\n"; 9538 Print_xmm_reg(fpu.fpu_xmm8); 9539 outs() << "\t fpu_xmm9:\n"; 9540 Print_xmm_reg(fpu.fpu_xmm9); 9541 outs() << "\t fpu_xmm10:\n"; 9542 Print_xmm_reg(fpu.fpu_xmm10); 9543 outs() << "\t fpu_xmm11:\n"; 9544 Print_xmm_reg(fpu.fpu_xmm11); 9545 outs() << "\t fpu_xmm12:\n"; 9546 Print_xmm_reg(fpu.fpu_xmm12); 9547 outs() << "\t fpu_xmm13:\n"; 9548 Print_xmm_reg(fpu.fpu_xmm13); 9549 outs() << "\t fpu_xmm14:\n"; 9550 Print_xmm_reg(fpu.fpu_xmm14); 9551 outs() << "\t fpu_xmm15:\n"; 9552 Print_xmm_reg(fpu.fpu_xmm15); 9553 outs() << "\t fpu_rsrv4:\n"; 9554 for (uint32_t f = 0; f < 6; f++) { 9555 outs() << "\t "; 9556 for (uint32_t g = 0; g < 16; g++) 9557 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9558 outs() << "\n"; 9559 } 9560 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9561 outs() << "\n"; 9562 } 9563 9564 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9565 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9566 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9567 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9568 } 9569 9570 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9571 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9572 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9573 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9574 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9575 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9576 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9577 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9578 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9579 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9580 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9581 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9582 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9583 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9584 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9585 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9586 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9587 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9588 } 9589 9590 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9591 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9592 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9593 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9594 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9595 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9596 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9597 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9598 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9599 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9600 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9601 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9602 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9603 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9604 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9605 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9606 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9607 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9608 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9609 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9610 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9611 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9612 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9613 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9614 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9615 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9616 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9617 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9618 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9619 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9620 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9621 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9622 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9623 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9624 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9625 } 9626 9627 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9628 bool isLittleEndian, uint32_t cputype) { 9629 if (t.cmd == MachO::LC_THREAD) 9630 outs() << " cmd LC_THREAD\n"; 9631 else if (t.cmd == MachO::LC_UNIXTHREAD) 9632 outs() << " cmd LC_UNIXTHREAD\n"; 9633 else 9634 outs() << " cmd " << t.cmd << " (unknown)\n"; 9635 outs() << " cmdsize " << t.cmdsize; 9636 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9637 outs() << " Incorrect size\n"; 9638 else 9639 outs() << "\n"; 9640 9641 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9642 const char *end = Ptr + t.cmdsize; 9643 uint32_t flavor, count, left; 9644 if (cputype == MachO::CPU_TYPE_I386) { 9645 while (begin < end) { 9646 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9647 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9648 begin += sizeof(uint32_t); 9649 } else { 9650 flavor = 0; 9651 begin = end; 9652 } 9653 if (isLittleEndian != sys::IsLittleEndianHost) 9654 sys::swapByteOrder(flavor); 9655 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9656 memcpy((char *)&count, begin, sizeof(uint32_t)); 9657 begin += sizeof(uint32_t); 9658 } else { 9659 count = 0; 9660 begin = end; 9661 } 9662 if (isLittleEndian != sys::IsLittleEndianHost) 9663 sys::swapByteOrder(count); 9664 if (flavor == MachO::x86_THREAD_STATE32) { 9665 outs() << " flavor i386_THREAD_STATE\n"; 9666 if (count == MachO::x86_THREAD_STATE32_COUNT) 9667 outs() << " count i386_THREAD_STATE_COUNT\n"; 9668 else 9669 outs() << " count " << count 9670 << " (not x86_THREAD_STATE32_COUNT)\n"; 9671 MachO::x86_thread_state32_t cpu32; 9672 left = end - begin; 9673 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9674 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9675 begin += sizeof(MachO::x86_thread_state32_t); 9676 } else { 9677 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9678 memcpy(&cpu32, begin, left); 9679 begin += left; 9680 } 9681 if (isLittleEndian != sys::IsLittleEndianHost) 9682 swapStruct(cpu32); 9683 Print_x86_thread_state32_t(cpu32); 9684 } else if (flavor == MachO::x86_THREAD_STATE) { 9685 outs() << " flavor x86_THREAD_STATE\n"; 9686 if (count == MachO::x86_THREAD_STATE_COUNT) 9687 outs() << " count x86_THREAD_STATE_COUNT\n"; 9688 else 9689 outs() << " count " << count 9690 << " (not x86_THREAD_STATE_COUNT)\n"; 9691 struct MachO::x86_thread_state_t ts; 9692 left = end - begin; 9693 if (left >= sizeof(MachO::x86_thread_state_t)) { 9694 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9695 begin += sizeof(MachO::x86_thread_state_t); 9696 } else { 9697 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9698 memcpy(&ts, begin, left); 9699 begin += left; 9700 } 9701 if (isLittleEndian != sys::IsLittleEndianHost) 9702 swapStruct(ts); 9703 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9704 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9705 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9706 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9707 else 9708 outs() << "tsh.count " << ts.tsh.count 9709 << " (not x86_THREAD_STATE32_COUNT\n"; 9710 Print_x86_thread_state32_t(ts.uts.ts32); 9711 } else { 9712 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9713 << ts.tsh.count << "\n"; 9714 } 9715 } else { 9716 outs() << " flavor " << flavor << " (unknown)\n"; 9717 outs() << " count " << count << "\n"; 9718 outs() << " state (unknown)\n"; 9719 begin += count * sizeof(uint32_t); 9720 } 9721 } 9722 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9723 while (begin < end) { 9724 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9725 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9726 begin += sizeof(uint32_t); 9727 } else { 9728 flavor = 0; 9729 begin = end; 9730 } 9731 if (isLittleEndian != sys::IsLittleEndianHost) 9732 sys::swapByteOrder(flavor); 9733 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9734 memcpy((char *)&count, begin, sizeof(uint32_t)); 9735 begin += sizeof(uint32_t); 9736 } else { 9737 count = 0; 9738 begin = end; 9739 } 9740 if (isLittleEndian != sys::IsLittleEndianHost) 9741 sys::swapByteOrder(count); 9742 if (flavor == MachO::x86_THREAD_STATE64) { 9743 outs() << " flavor x86_THREAD_STATE64\n"; 9744 if (count == MachO::x86_THREAD_STATE64_COUNT) 9745 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9746 else 9747 outs() << " count " << count 9748 << " (not x86_THREAD_STATE64_COUNT)\n"; 9749 MachO::x86_thread_state64_t cpu64; 9750 left = end - begin; 9751 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9752 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9753 begin += sizeof(MachO::x86_thread_state64_t); 9754 } else { 9755 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9756 memcpy(&cpu64, begin, left); 9757 begin += left; 9758 } 9759 if (isLittleEndian != sys::IsLittleEndianHost) 9760 swapStruct(cpu64); 9761 Print_x86_thread_state64_t(cpu64); 9762 } else if (flavor == MachO::x86_THREAD_STATE) { 9763 outs() << " flavor x86_THREAD_STATE\n"; 9764 if (count == MachO::x86_THREAD_STATE_COUNT) 9765 outs() << " count x86_THREAD_STATE_COUNT\n"; 9766 else 9767 outs() << " count " << count 9768 << " (not x86_THREAD_STATE_COUNT)\n"; 9769 struct MachO::x86_thread_state_t ts; 9770 left = end - begin; 9771 if (left >= sizeof(MachO::x86_thread_state_t)) { 9772 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9773 begin += sizeof(MachO::x86_thread_state_t); 9774 } else { 9775 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9776 memcpy(&ts, begin, left); 9777 begin += left; 9778 } 9779 if (isLittleEndian != sys::IsLittleEndianHost) 9780 swapStruct(ts); 9781 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9782 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9783 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9784 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9785 else 9786 outs() << "tsh.count " << ts.tsh.count 9787 << " (not x86_THREAD_STATE64_COUNT\n"; 9788 Print_x86_thread_state64_t(ts.uts.ts64); 9789 } else { 9790 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9791 << ts.tsh.count << "\n"; 9792 } 9793 } else if (flavor == MachO::x86_FLOAT_STATE) { 9794 outs() << " flavor x86_FLOAT_STATE\n"; 9795 if (count == MachO::x86_FLOAT_STATE_COUNT) 9796 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9797 else 9798 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9799 struct MachO::x86_float_state_t fs; 9800 left = end - begin; 9801 if (left >= sizeof(MachO::x86_float_state_t)) { 9802 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9803 begin += sizeof(MachO::x86_float_state_t); 9804 } else { 9805 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9806 memcpy(&fs, begin, left); 9807 begin += left; 9808 } 9809 if (isLittleEndian != sys::IsLittleEndianHost) 9810 swapStruct(fs); 9811 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9812 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9813 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9814 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9815 else 9816 outs() << "fsh.count " << fs.fsh.count 9817 << " (not x86_FLOAT_STATE64_COUNT\n"; 9818 Print_x86_float_state_t(fs.ufs.fs64); 9819 } else { 9820 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9821 << fs.fsh.count << "\n"; 9822 } 9823 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9824 outs() << " flavor x86_EXCEPTION_STATE\n"; 9825 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9826 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9827 else 9828 outs() << " count " << count 9829 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9830 struct MachO::x86_exception_state_t es; 9831 left = end - begin; 9832 if (left >= sizeof(MachO::x86_exception_state_t)) { 9833 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9834 begin += sizeof(MachO::x86_exception_state_t); 9835 } else { 9836 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9837 memcpy(&es, begin, left); 9838 begin += left; 9839 } 9840 if (isLittleEndian != sys::IsLittleEndianHost) 9841 swapStruct(es); 9842 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9843 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9844 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9845 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9846 else 9847 outs() << "\t esh.count " << es.esh.count 9848 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9849 Print_x86_exception_state_t(es.ues.es64); 9850 } else { 9851 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9852 << es.esh.count << "\n"; 9853 } 9854 } else if (flavor == MachO::x86_EXCEPTION_STATE64) { 9855 outs() << " flavor x86_EXCEPTION_STATE64\n"; 9856 if (count == MachO::x86_EXCEPTION_STATE64_COUNT) 9857 outs() << " count x86_EXCEPTION_STATE64_COUNT\n"; 9858 else 9859 outs() << " count " << count 9860 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; 9861 struct MachO::x86_exception_state64_t es64; 9862 left = end - begin; 9863 if (left >= sizeof(MachO::x86_exception_state64_t)) { 9864 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); 9865 begin += sizeof(MachO::x86_exception_state64_t); 9866 } else { 9867 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); 9868 memcpy(&es64, begin, left); 9869 begin += left; 9870 } 9871 if (isLittleEndian != sys::IsLittleEndianHost) 9872 swapStruct(es64); 9873 Print_x86_exception_state_t(es64); 9874 } else { 9875 outs() << " flavor " << flavor << " (unknown)\n"; 9876 outs() << " count " << count << "\n"; 9877 outs() << " state (unknown)\n"; 9878 begin += count * sizeof(uint32_t); 9879 } 9880 } 9881 } else if (cputype == MachO::CPU_TYPE_ARM) { 9882 while (begin < end) { 9883 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9884 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9885 begin += sizeof(uint32_t); 9886 } else { 9887 flavor = 0; 9888 begin = end; 9889 } 9890 if (isLittleEndian != sys::IsLittleEndianHost) 9891 sys::swapByteOrder(flavor); 9892 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9893 memcpy((char *)&count, begin, sizeof(uint32_t)); 9894 begin += sizeof(uint32_t); 9895 } else { 9896 count = 0; 9897 begin = end; 9898 } 9899 if (isLittleEndian != sys::IsLittleEndianHost) 9900 sys::swapByteOrder(count); 9901 if (flavor == MachO::ARM_THREAD_STATE) { 9902 outs() << " flavor ARM_THREAD_STATE\n"; 9903 if (count == MachO::ARM_THREAD_STATE_COUNT) 9904 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9905 else 9906 outs() << " count " << count 9907 << " (not ARM_THREAD_STATE_COUNT)\n"; 9908 MachO::arm_thread_state32_t cpu32; 9909 left = end - begin; 9910 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9911 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9912 begin += sizeof(MachO::arm_thread_state32_t); 9913 } else { 9914 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9915 memcpy(&cpu32, begin, left); 9916 begin += left; 9917 } 9918 if (isLittleEndian != sys::IsLittleEndianHost) 9919 swapStruct(cpu32); 9920 Print_arm_thread_state32_t(cpu32); 9921 } else { 9922 outs() << " flavor " << flavor << " (unknown)\n"; 9923 outs() << " count " << count << "\n"; 9924 outs() << " state (unknown)\n"; 9925 begin += count * sizeof(uint32_t); 9926 } 9927 } 9928 } else if (cputype == MachO::CPU_TYPE_ARM64 || 9929 cputype == MachO::CPU_TYPE_ARM64_32) { 9930 while (begin < end) { 9931 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9932 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9933 begin += sizeof(uint32_t); 9934 } else { 9935 flavor = 0; 9936 begin = end; 9937 } 9938 if (isLittleEndian != sys::IsLittleEndianHost) 9939 sys::swapByteOrder(flavor); 9940 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9941 memcpy((char *)&count, begin, sizeof(uint32_t)); 9942 begin += sizeof(uint32_t); 9943 } else { 9944 count = 0; 9945 begin = end; 9946 } 9947 if (isLittleEndian != sys::IsLittleEndianHost) 9948 sys::swapByteOrder(count); 9949 if (flavor == MachO::ARM_THREAD_STATE64) { 9950 outs() << " flavor ARM_THREAD_STATE64\n"; 9951 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9952 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9953 else 9954 outs() << " count " << count 9955 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9956 MachO::arm_thread_state64_t cpu64; 9957 left = end - begin; 9958 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9959 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9960 begin += sizeof(MachO::arm_thread_state64_t); 9961 } else { 9962 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9963 memcpy(&cpu64, begin, left); 9964 begin += left; 9965 } 9966 if (isLittleEndian != sys::IsLittleEndianHost) 9967 swapStruct(cpu64); 9968 Print_arm_thread_state64_t(cpu64); 9969 } else { 9970 outs() << " flavor " << flavor << " (unknown)\n"; 9971 outs() << " count " << count << "\n"; 9972 outs() << " state (unknown)\n"; 9973 begin += count * sizeof(uint32_t); 9974 } 9975 } 9976 } else { 9977 while (begin < end) { 9978 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9979 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9980 begin += sizeof(uint32_t); 9981 } else { 9982 flavor = 0; 9983 begin = end; 9984 } 9985 if (isLittleEndian != sys::IsLittleEndianHost) 9986 sys::swapByteOrder(flavor); 9987 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9988 memcpy((char *)&count, begin, sizeof(uint32_t)); 9989 begin += sizeof(uint32_t); 9990 } else { 9991 count = 0; 9992 begin = end; 9993 } 9994 if (isLittleEndian != sys::IsLittleEndianHost) 9995 sys::swapByteOrder(count); 9996 outs() << " flavor " << flavor << "\n"; 9997 outs() << " count " << count << "\n"; 9998 outs() << " state (Unknown cputype/cpusubtype)\n"; 9999 begin += count * sizeof(uint32_t); 10000 } 10001 } 10002 } 10003 10004 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 10005 if (dl.cmd == MachO::LC_ID_DYLIB) 10006 outs() << " cmd LC_ID_DYLIB\n"; 10007 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 10008 outs() << " cmd LC_LOAD_DYLIB\n"; 10009 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 10010 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 10011 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 10012 outs() << " cmd LC_REEXPORT_DYLIB\n"; 10013 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 10014 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 10015 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 10016 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 10017 else 10018 outs() << " cmd " << dl.cmd << " (unknown)\n"; 10019 outs() << " cmdsize " << dl.cmdsize; 10020 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 10021 outs() << " Incorrect size\n"; 10022 else 10023 outs() << "\n"; 10024 if (dl.dylib.name < dl.cmdsize) { 10025 const char *P = (const char *)(Ptr) + dl.dylib.name; 10026 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 10027 } else { 10028 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 10029 } 10030 outs() << " time stamp " << dl.dylib.timestamp << " "; 10031 time_t t = dl.dylib.timestamp; 10032 outs() << ctime(&t); 10033 outs() << " current version "; 10034 if (dl.dylib.current_version == 0xffffffff) 10035 outs() << "n/a\n"; 10036 else 10037 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 10038 << ((dl.dylib.current_version >> 8) & 0xff) << "." 10039 << (dl.dylib.current_version & 0xff) << "\n"; 10040 outs() << "compatibility version "; 10041 if (dl.dylib.compatibility_version == 0xffffffff) 10042 outs() << "n/a\n"; 10043 else 10044 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 10045 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 10046 << (dl.dylib.compatibility_version & 0xff) << "\n"; 10047 } 10048 10049 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 10050 uint32_t object_size) { 10051 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 10052 outs() << " cmd LC_CODE_SIGNATURE\n"; 10053 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 10054 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 10055 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 10056 outs() << " cmd LC_FUNCTION_STARTS\n"; 10057 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 10058 outs() << " cmd LC_DATA_IN_CODE\n"; 10059 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 10060 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 10061 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 10062 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 10063 else if (ld.cmd == MachO::LC_DYLD_EXPORTS_TRIE) 10064 outs() << " cmd LC_DYLD_EXPORTS_TRIE\n"; 10065 else if (ld.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) 10066 outs() << " cmd LC_DYLD_CHAINED_FIXUPS\n"; 10067 else if (ld.cmd == MachO::LC_ATOM_INFO) 10068 outs() << " cmd LC_ATOM_INFO\n"; 10069 else 10070 outs() << " cmd " << ld.cmd << " (?)\n"; 10071 outs() << " cmdsize " << ld.cmdsize; 10072 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 10073 outs() << " Incorrect size\n"; 10074 else 10075 outs() << "\n"; 10076 outs() << " dataoff " << ld.dataoff; 10077 if (ld.dataoff > object_size) 10078 outs() << " (past end of file)\n"; 10079 else 10080 outs() << "\n"; 10081 outs() << " datasize " << ld.datasize; 10082 uint64_t big_size = ld.dataoff; 10083 big_size += ld.datasize; 10084 if (big_size > object_size) 10085 outs() << " (past end of file)\n"; 10086 else 10087 outs() << "\n"; 10088 } 10089 10090 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 10091 uint32_t cputype, bool verbose) { 10092 StringRef Buf = Obj->getData(); 10093 unsigned Index = 0; 10094 for (const auto &Command : Obj->load_commands()) { 10095 outs() << "Load command " << Index++ << "\n"; 10096 if (Command.C.cmd == MachO::LC_SEGMENT) { 10097 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 10098 const char *sg_segname = SLC.segname; 10099 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 10100 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 10101 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 10102 verbose); 10103 for (unsigned j = 0; j < SLC.nsects; j++) { 10104 MachO::section S = Obj->getSection(Command, j); 10105 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 10106 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 10107 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 10108 } 10109 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10110 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 10111 const char *sg_segname = SLC_64.segname; 10112 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 10113 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 10114 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 10115 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 10116 for (unsigned j = 0; j < SLC_64.nsects; j++) { 10117 MachO::section_64 S_64 = Obj->getSection64(Command, j); 10118 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 10119 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 10120 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 10121 sg_segname, filetype, Buf.size(), verbose); 10122 } 10123 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 10124 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10125 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 10126 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 10127 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 10128 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10129 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 10130 Obj->is64Bit()); 10131 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 10132 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 10133 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 10134 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 10135 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 10136 Command.C.cmd == MachO::LC_ID_DYLINKER || 10137 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 10138 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 10139 PrintDyldLoadCommand(Dyld, Command.Ptr); 10140 } else if (Command.C.cmd == MachO::LC_UUID) { 10141 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 10142 PrintUuidLoadCommand(Uuid); 10143 } else if (Command.C.cmd == MachO::LC_RPATH) { 10144 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 10145 PrintRpathLoadCommand(Rpath, Command.Ptr); 10146 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 10147 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 10148 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 10149 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 10150 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 10151 PrintVersionMinLoadCommand(Vd); 10152 } else if (Command.C.cmd == MachO::LC_NOTE) { 10153 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 10154 PrintNoteLoadCommand(Nt); 10155 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 10156 MachO::build_version_command Bv = 10157 Obj->getBuildVersionLoadCommand(Command); 10158 PrintBuildVersionLoadCommand(Obj, Bv, verbose); 10159 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 10160 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 10161 PrintSourceVersionCommand(Sd); 10162 } else if (Command.C.cmd == MachO::LC_MAIN) { 10163 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 10164 PrintEntryPointCommand(Ep); 10165 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 10166 MachO::encryption_info_command Ei = 10167 Obj->getEncryptionInfoCommand(Command); 10168 PrintEncryptionInfoCommand(Ei, Buf.size()); 10169 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 10170 MachO::encryption_info_command_64 Ei = 10171 Obj->getEncryptionInfoCommand64(Command); 10172 PrintEncryptionInfoCommand64(Ei, Buf.size()); 10173 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 10174 MachO::linker_option_command Lo = 10175 Obj->getLinkerOptionLoadCommand(Command); 10176 PrintLinkerOptionCommand(Lo, Command.Ptr); 10177 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 10178 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 10179 PrintSubFrameworkCommand(Sf, Command.Ptr); 10180 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 10181 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 10182 PrintSubUmbrellaCommand(Sf, Command.Ptr); 10183 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 10184 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 10185 PrintSubLibraryCommand(Sl, Command.Ptr); 10186 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 10187 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 10188 PrintSubClientCommand(Sc, Command.Ptr); 10189 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 10190 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 10191 PrintRoutinesCommand(Rc); 10192 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 10193 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 10194 PrintRoutinesCommand64(Rc); 10195 } else if (Command.C.cmd == MachO::LC_THREAD || 10196 Command.C.cmd == MachO::LC_UNIXTHREAD) { 10197 MachO::thread_command Tc = Obj->getThreadCommand(Command); 10198 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 10199 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 10200 Command.C.cmd == MachO::LC_ID_DYLIB || 10201 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 10202 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 10203 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 10204 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 10205 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 10206 PrintDylibCommand(Dl, Command.Ptr); 10207 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 10208 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 10209 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 10210 Command.C.cmd == MachO::LC_DATA_IN_CODE || 10211 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 10212 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT || 10213 Command.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE || 10214 Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS || 10215 Command.C.cmd == MachO::LC_ATOM_INFO) { 10216 MachO::linkedit_data_command Ld = 10217 Obj->getLinkeditDataLoadCommand(Command); 10218 PrintLinkEditDataCommand(Ld, Buf.size()); 10219 } else { 10220 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 10221 << ")\n"; 10222 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 10223 // TODO: get and print the raw bytes of the load command. 10224 } 10225 // TODO: print all the other kinds of load commands. 10226 } 10227 } 10228 10229 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 10230 if (Obj->is64Bit()) { 10231 MachO::mach_header_64 H_64; 10232 H_64 = Obj->getHeader64(); 10233 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 10234 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 10235 } else { 10236 MachO::mach_header H; 10237 H = Obj->getHeader(); 10238 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 10239 H.sizeofcmds, H.flags, verbose); 10240 } 10241 } 10242 10243 void objdump::printMachOFileHeader(const object::ObjectFile *Obj) { 10244 const MachOObjectFile *file = cast<const MachOObjectFile>(Obj); 10245 PrintMachHeader(file, Verbose); 10246 } 10247 10248 void MachODumper::printPrivateHeaders() { 10249 printMachOFileHeader(&Obj); 10250 if (!FirstPrivateHeader) 10251 printMachOLoadCommands(&Obj); 10252 } 10253 10254 void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) { 10255 const MachOObjectFile *file = cast<const MachOObjectFile>(Obj); 10256 uint32_t filetype = 0; 10257 uint32_t cputype = 0; 10258 if (file->is64Bit()) { 10259 MachO::mach_header_64 H_64; 10260 H_64 = file->getHeader64(); 10261 filetype = H_64.filetype; 10262 cputype = H_64.cputype; 10263 } else { 10264 MachO::mach_header H; 10265 H = file->getHeader(); 10266 filetype = H.filetype; 10267 cputype = H.cputype; 10268 } 10269 PrintLoadCommands(file, filetype, cputype, Verbose); 10270 } 10271 10272 //===----------------------------------------------------------------------===// 10273 // export trie dumping 10274 //===----------------------------------------------------------------------===// 10275 10276 static void printMachOExportsTrie(const object::MachOObjectFile *Obj) { 10277 uint64_t BaseSegmentAddress = 0; 10278 for (const auto &Command : Obj->load_commands()) { 10279 if (Command.C.cmd == MachO::LC_SEGMENT) { 10280 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 10281 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10282 BaseSegmentAddress = Seg.vmaddr; 10283 break; 10284 } 10285 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10286 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 10287 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10288 BaseSegmentAddress = Seg.vmaddr; 10289 break; 10290 } 10291 } 10292 } 10293 Error Err = Error::success(); 10294 for (const object::ExportEntry &Entry : Obj->exports(Err)) { 10295 uint64_t Flags = Entry.flags(); 10296 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 10297 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 10298 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10299 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 10300 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10301 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 10302 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 10303 if (ReExport) 10304 outs() << "[re-export] "; 10305 else 10306 outs() << format("0x%08llX ", 10307 Entry.address() + BaseSegmentAddress); 10308 outs() << Entry.name(); 10309 if (WeakDef || ThreadLocal || Resolver || Abs) { 10310 ListSeparator LS; 10311 outs() << " ["; 10312 if (WeakDef) 10313 outs() << LS << "weak_def"; 10314 if (ThreadLocal) 10315 outs() << LS << "per-thread"; 10316 if (Abs) 10317 outs() << LS << "absolute"; 10318 if (Resolver) 10319 outs() << LS << format("resolver=0x%08llX", Entry.other()); 10320 outs() << "]"; 10321 } 10322 if (ReExport) { 10323 StringRef DylibName = "unknown"; 10324 int Ordinal = Entry.other() - 1; 10325 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 10326 if (Entry.otherName().empty()) 10327 outs() << " (from " << DylibName << ")"; 10328 else 10329 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 10330 } 10331 outs() << "\n"; 10332 } 10333 if (Err) 10334 reportError(std::move(Err), Obj->getFileName()); 10335 } 10336 10337 //===----------------------------------------------------------------------===// 10338 // rebase table dumping 10339 //===----------------------------------------------------------------------===// 10340 10341 static void printMachORebaseTable(object::MachOObjectFile *Obj) { 10342 outs() << "segment section address type\n"; 10343 Error Err = Error::success(); 10344 for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 10345 StringRef SegmentName = Entry.segmentName(); 10346 StringRef SectionName = Entry.sectionName(); 10347 uint64_t Address = Entry.address(); 10348 10349 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 10350 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 10351 SegmentName.str().c_str(), SectionName.str().c_str(), 10352 Address, Entry.typeName().str().c_str()); 10353 } 10354 if (Err) 10355 reportError(std::move(Err), Obj->getFileName()); 10356 } 10357 10358 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 10359 StringRef DylibName; 10360 switch (Ordinal) { 10361 case MachO::BIND_SPECIAL_DYLIB_SELF: 10362 return "this-image"; 10363 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 10364 return "main-executable"; 10365 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 10366 return "flat-namespace"; 10367 case MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP: 10368 return "weak"; 10369 default: 10370 if (Ordinal > 0) { 10371 std::error_code EC = 10372 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 10373 if (EC) 10374 return "<<bad library ordinal>>"; 10375 return DylibName; 10376 } 10377 } 10378 return "<<unknown special ordinal>>"; 10379 } 10380 10381 //===----------------------------------------------------------------------===// 10382 // bind table dumping 10383 //===----------------------------------------------------------------------===// 10384 10385 static void printMachOBindTable(object::MachOObjectFile *Obj) { 10386 // Build table of sections so names can used in final output. 10387 outs() << "segment section address type " 10388 "addend dylib symbol\n"; 10389 Error Err = Error::success(); 10390 for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 10391 StringRef SegmentName = Entry.segmentName(); 10392 StringRef SectionName = Entry.sectionName(); 10393 uint64_t Address = Entry.address(); 10394 10395 // Table lines look like: 10396 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 10397 StringRef Attr; 10398 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 10399 Attr = " (weak_import)"; 10400 outs() << left_justify(SegmentName, 8) << " " 10401 << left_justify(SectionName, 18) << " " 10402 << format_hex(Address, 10, true) << " " 10403 << left_justify(Entry.typeName(), 8) << " " 10404 << format_decimal(Entry.addend(), 8) << " " 10405 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10406 << Entry.symbolName() << Attr << "\n"; 10407 } 10408 if (Err) 10409 reportError(std::move(Err), Obj->getFileName()); 10410 } 10411 10412 //===----------------------------------------------------------------------===// 10413 // lazy bind table dumping 10414 //===----------------------------------------------------------------------===// 10415 10416 static void printMachOLazyBindTable(object::MachOObjectFile *Obj) { 10417 outs() << "segment section address " 10418 "dylib symbol\n"; 10419 Error Err = Error::success(); 10420 for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 10421 StringRef SegmentName = Entry.segmentName(); 10422 StringRef SectionName = Entry.sectionName(); 10423 uint64_t Address = Entry.address(); 10424 10425 // Table lines look like: 10426 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 10427 outs() << left_justify(SegmentName, 8) << " " 10428 << left_justify(SectionName, 18) << " " 10429 << format_hex(Address, 10, true) << " " 10430 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10431 << Entry.symbolName() << "\n"; 10432 } 10433 if (Err) 10434 reportError(std::move(Err), Obj->getFileName()); 10435 } 10436 10437 //===----------------------------------------------------------------------===// 10438 // weak bind table dumping 10439 //===----------------------------------------------------------------------===// 10440 10441 static void printMachOWeakBindTable(object::MachOObjectFile *Obj) { 10442 outs() << "segment section address " 10443 "type addend symbol\n"; 10444 Error Err = Error::success(); 10445 for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 10446 // Strong symbols don't have a location to update. 10447 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 10448 outs() << " strong " 10449 << Entry.symbolName() << "\n"; 10450 continue; 10451 } 10452 StringRef SegmentName = Entry.segmentName(); 10453 StringRef SectionName = Entry.sectionName(); 10454 uint64_t Address = Entry.address(); 10455 10456 // Table lines look like: 10457 // __DATA __data 0x00001000 pointer 0 _foo 10458 outs() << left_justify(SegmentName, 8) << " " 10459 << left_justify(SectionName, 18) << " " 10460 << format_hex(Address, 10, true) << " " 10461 << left_justify(Entry.typeName(), 8) << " " 10462 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 10463 << "\n"; 10464 } 10465 if (Err) 10466 reportError(std::move(Err), Obj->getFileName()); 10467 } 10468 10469 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 10470 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 10471 // information for that address. If the address is found its binding symbol 10472 // name is returned. If not nullptr is returned. 10473 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 10474 struct DisassembleInfo *info) { 10475 if (info->bindtable == nullptr) { 10476 info->bindtable = std::make_unique<SymbolAddressMap>(); 10477 Error Err = Error::success(); 10478 for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 10479 uint64_t Address = Entry.address(); 10480 StringRef name = Entry.symbolName(); 10481 if (!name.empty()) 10482 (*info->bindtable)[Address] = name; 10483 } 10484 if (Err) 10485 reportError(std::move(Err), info->O->getFileName()); 10486 } 10487 auto name = info->bindtable->lookup(ReferenceValue); 10488 return !name.empty() ? name.data() : nullptr; 10489 } 10490 10491 void objdump::printLazyBindTable(ObjectFile *o) { 10492 outs() << "\nLazy bind table:\n"; 10493 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10494 printMachOLazyBindTable(MachO); 10495 else 10496 WithColor::error() 10497 << "This operation is only currently supported " 10498 "for Mach-O executable files.\n"; 10499 } 10500 10501 void objdump::printWeakBindTable(ObjectFile *o) { 10502 outs() << "\nWeak bind table:\n"; 10503 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10504 printMachOWeakBindTable(MachO); 10505 else 10506 WithColor::error() 10507 << "This operation is only currently supported " 10508 "for Mach-O executable files.\n"; 10509 } 10510 10511 void objdump::printExportsTrie(const ObjectFile *o) { 10512 outs() << "\nExports trie:\n"; 10513 if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10514 printMachOExportsTrie(MachO); 10515 else 10516 WithColor::error() 10517 << "This operation is only currently supported " 10518 "for Mach-O executable files.\n"; 10519 } 10520 10521 void objdump::printRebaseTable(ObjectFile *o) { 10522 outs() << "\nRebase table:\n"; 10523 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10524 printMachORebaseTable(MachO); 10525 else 10526 WithColor::error() 10527 << "This operation is only currently supported " 10528 "for Mach-O executable files.\n"; 10529 } 10530 10531 void objdump::printBindTable(ObjectFile *o) { 10532 outs() << "\nBind table:\n"; 10533 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10534 printMachOBindTable(MachO); 10535 else 10536 WithColor::error() 10537 << "This operation is only currently supported " 10538 "for Mach-O executable files.\n"; 10539 } 10540