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 && cputype == MachO::CPU_TYPE_ARM64 && 2398 MachO::CPU_SUBTYPE_ARM64E_IS_VERSIONED_PTRAUTH_ABI(cpusubtype)) { 2399 outs() << " capabilities CPU_SUBTYPE_ARM64E_"; 2400 if (MachO::CPU_SUBTYPE_ARM64E_IS_KERNEL_PTRAUTH_ABI(cpusubtype)) 2401 outs() << "KERNEL_"; 2402 outs() << format("PTRAUTH_VERSION %d", 2403 MachO::CPU_SUBTYPE_ARM64E_PTRAUTH_VERSION(cpusubtype)) 2404 << "\n"; 2405 } else if (verbose && (cpusubtype & MachO::CPU_SUBTYPE_MASK) == 2406 MachO::CPU_SUBTYPE_LIB64) 2407 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 2408 else 2409 outs() << " capabilities " 2410 << format("0x%" PRIx32, 2411 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 2412 outs() << " offset " << OFA.getOffset(); 2413 if (OFA.getOffset() > size) 2414 outs() << " (past end of file)"; 2415 if (OFA.getOffset() % (1ull << OFA.getAlign()) != 0) 2416 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 2417 outs() << "\n"; 2418 outs() << " size " << OFA.getSize(); 2419 big_size = OFA.getOffset() + OFA.getSize(); 2420 if (big_size > size) 2421 outs() << " (past end of file)"; 2422 outs() << "\n"; 2423 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 2424 << ")\n"; 2425 } 2426 } 2427 2428 static void printArchiveChild(StringRef Filename, const Archive::Child &C, 2429 size_t ChildIndex, bool verbose, 2430 bool print_offset, 2431 StringRef ArchitectureName = StringRef()) { 2432 if (print_offset) 2433 outs() << C.getChildOffset() << "\t"; 2434 sys::fs::perms Mode = 2435 unwrapOrError(C.getAccessMode(), getFileNameForError(C, ChildIndex), 2436 Filename, ArchitectureName); 2437 if (verbose) { 2438 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 2439 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 2440 outs() << "-"; 2441 outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); 2442 outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); 2443 outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); 2444 outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); 2445 outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); 2446 outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); 2447 outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); 2448 outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); 2449 outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); 2450 } else { 2451 outs() << format("0%o ", Mode); 2452 } 2453 2454 outs() << format("%3d/%-3d %5" PRId64 " ", 2455 unwrapOrError(C.getUID(), getFileNameForError(C, ChildIndex), 2456 Filename, ArchitectureName), 2457 unwrapOrError(C.getGID(), getFileNameForError(C, ChildIndex), 2458 Filename, ArchitectureName), 2459 unwrapOrError(C.getRawSize(), 2460 getFileNameForError(C, ChildIndex), Filename, 2461 ArchitectureName)); 2462 2463 StringRef RawLastModified = C.getRawLastModified(); 2464 if (verbose) { 2465 unsigned Seconds; 2466 if (RawLastModified.getAsInteger(10, Seconds)) 2467 outs() << "(date: \"" << RawLastModified 2468 << "\" contains non-decimal chars) "; 2469 else { 2470 // Since cime(3) returns a 26 character string of the form: 2471 // "Sun Sep 16 01:03:52 1973\n\0" 2472 // just print 24 characters. 2473 time_t t = Seconds; 2474 outs() << format("%.24s ", ctime(&t)); 2475 } 2476 } else { 2477 outs() << RawLastModified << " "; 2478 } 2479 2480 if (verbose) { 2481 Expected<StringRef> NameOrErr = C.getName(); 2482 if (!NameOrErr) { 2483 consumeError(NameOrErr.takeError()); 2484 outs() << unwrapOrError(C.getRawName(), 2485 getFileNameForError(C, ChildIndex), Filename, 2486 ArchitectureName) 2487 << "\n"; 2488 } else { 2489 StringRef Name = NameOrErr.get(); 2490 outs() << Name << "\n"; 2491 } 2492 } else { 2493 outs() << unwrapOrError(C.getRawName(), getFileNameForError(C, ChildIndex), 2494 Filename, ArchitectureName) 2495 << "\n"; 2496 } 2497 } 2498 2499 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, 2500 bool print_offset, 2501 StringRef ArchitectureName = StringRef()) { 2502 Error Err = Error::success(); 2503 size_t I = 0; 2504 for (const auto &C : A->children(Err, false)) 2505 printArchiveChild(Filename, C, I++, verbose, print_offset, 2506 ArchitectureName); 2507 2508 if (Err) 2509 reportError(std::move(Err), Filename, "", ArchitectureName); 2510 } 2511 2512 static bool ValidateArchFlags() { 2513 // Check for -arch all and verifiy the -arch flags are valid. 2514 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2515 if (ArchFlags[i] == "all") { 2516 ArchAll = true; 2517 } else { 2518 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 2519 WithColor::error(errs(), "llvm-objdump") 2520 << "unknown architecture named '" + ArchFlags[i] + 2521 "'for the -arch option\n"; 2522 return false; 2523 } 2524 } 2525 } 2526 return true; 2527 } 2528 2529 // ParseInputMachO() parses the named Mach-O file in Filename and handles the 2530 // -arch flags selecting just those slices as specified by them and also parses 2531 // archive files. Then for each individual Mach-O file ProcessMachO() is 2532 // called to process the file based on the command line options. 2533 void objdump::parseInputMachO(StringRef Filename) { 2534 if (!ValidateArchFlags()) 2535 return; 2536 2537 // Attempt to open the binary. 2538 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 2539 if (!BinaryOrErr) { 2540 if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError())) 2541 reportError(std::move(E), Filename); 2542 else 2543 outs() << Filename << ": is not an object file\n"; 2544 return; 2545 } 2546 Binary &Bin = *BinaryOrErr.get().getBinary(); 2547 2548 if (Archive *A = dyn_cast<Archive>(&Bin)) { 2549 outs() << "Archive : " << Filename << "\n"; 2550 if (ArchiveHeaders) 2551 printArchiveHeaders(Filename, A, Verbose, ArchiveMemberOffsets); 2552 2553 Error Err = Error::success(); 2554 unsigned I = -1; 2555 for (auto &C : A->children(Err)) { 2556 ++I; 2557 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2558 if (!ChildOrErr) { 2559 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2560 reportError(std::move(E), getFileNameForError(C, I), Filename); 2561 continue; 2562 } 2563 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2564 if (!checkMachOAndArchFlags(O, Filename)) 2565 return; 2566 ProcessMachO(Filename, O, O->getFileName()); 2567 } 2568 } 2569 if (Err) 2570 reportError(std::move(Err), Filename); 2571 return; 2572 } 2573 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 2574 parseInputMachO(UB); 2575 return; 2576 } 2577 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 2578 if (!checkMachOAndArchFlags(O, Filename)) 2579 return; 2580 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) 2581 ProcessMachO(Filename, MachOOF); 2582 else 2583 WithColor::error(errs(), "llvm-objdump") 2584 << Filename << "': " 2585 << "object is not a Mach-O file type.\n"; 2586 return; 2587 } 2588 llvm_unreachable("Input object can't be invalid at this point"); 2589 } 2590 2591 void objdump::parseInputMachO(MachOUniversalBinary *UB) { 2592 if (!ValidateArchFlags()) 2593 return; 2594 2595 auto Filename = UB->getFileName(); 2596 2597 if (UniversalHeaders) 2598 printMachOUniversalHeaders(UB, Verbose); 2599 2600 // If we have a list of architecture flags specified dump only those. 2601 if (!ArchAll && !ArchFlags.empty()) { 2602 // Look for a slice in the universal binary that matches each ArchFlag. 2603 bool ArchFound; 2604 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 2605 ArchFound = false; 2606 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2607 E = UB->end_objects(); 2608 I != E; ++I) { 2609 if (ArchFlags[i] == I->getArchFlagName()) { 2610 ArchFound = true; 2611 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 2612 I->getAsObjectFile(); 2613 std::string ArchitectureName; 2614 if (ArchFlags.size() > 1) 2615 ArchitectureName = I->getArchFlagName(); 2616 if (ObjOrErr) { 2617 ObjectFile &O = *ObjOrErr.get(); 2618 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2619 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2620 } else if (Error E = isNotObjectErrorInvalidFileType( 2621 ObjOrErr.takeError())) { 2622 reportError(std::move(E), "", Filename, ArchitectureName); 2623 continue; 2624 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2625 I->getAsArchive()) { 2626 std::unique_ptr<Archive> &A = *AOrErr; 2627 outs() << "Archive : " << Filename; 2628 if (!ArchitectureName.empty()) 2629 outs() << " (architecture " << ArchitectureName << ")"; 2630 outs() << "\n"; 2631 if (ArchiveHeaders) 2632 printArchiveHeaders(Filename, A.get(), Verbose, 2633 ArchiveMemberOffsets, ArchitectureName); 2634 Error Err = Error::success(); 2635 unsigned I = -1; 2636 for (auto &C : A->children(Err)) { 2637 ++I; 2638 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2639 if (!ChildOrErr) { 2640 if (Error E = 2641 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2642 reportError(std::move(E), getFileNameForError(C, I), Filename, 2643 ArchitectureName); 2644 continue; 2645 } 2646 if (MachOObjectFile *O = 2647 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2648 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 2649 } 2650 if (Err) 2651 reportError(std::move(Err), Filename); 2652 } else { 2653 consumeError(AOrErr.takeError()); 2654 reportError(Filename, 2655 "Mach-O universal file for architecture " + 2656 StringRef(I->getArchFlagName()) + 2657 " is not a Mach-O file or an archive file"); 2658 } 2659 } 2660 } 2661 if (!ArchFound) { 2662 WithColor::error(errs(), "llvm-objdump") 2663 << "file: " + Filename + " does not contain " 2664 << "architecture: " + ArchFlags[i] + "\n"; 2665 return; 2666 } 2667 } 2668 return; 2669 } 2670 // No architecture flags were specified so if this contains a slice that 2671 // matches the host architecture dump only that. 2672 if (!ArchAll) { 2673 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2674 E = UB->end_objects(); 2675 I != E; ++I) { 2676 if (MachOObjectFile::getHostArch().getArchName() == 2677 I->getArchFlagName()) { 2678 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2679 std::string ArchiveName; 2680 ArchiveName.clear(); 2681 if (ObjOrErr) { 2682 ObjectFile &O = *ObjOrErr.get(); 2683 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 2684 ProcessMachO(Filename, MachOOF); 2685 } else if (Error E = 2686 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2687 reportError(std::move(E), Filename); 2688 } else if (Expected<std::unique_ptr<Archive>> AOrErr = 2689 I->getAsArchive()) { 2690 std::unique_ptr<Archive> &A = *AOrErr; 2691 outs() << "Archive : " << Filename << "\n"; 2692 if (ArchiveHeaders) 2693 printArchiveHeaders(Filename, A.get(), Verbose, 2694 ArchiveMemberOffsets); 2695 Error Err = Error::success(); 2696 unsigned I = -1; 2697 for (auto &C : A->children(Err)) { 2698 ++I; 2699 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2700 if (!ChildOrErr) { 2701 if (Error E = 2702 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2703 reportError(std::move(E), getFileNameForError(C, I), Filename); 2704 continue; 2705 } 2706 if (MachOObjectFile *O = 2707 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 2708 ProcessMachO(Filename, O, O->getFileName()); 2709 } 2710 if (Err) 2711 reportError(std::move(Err), Filename); 2712 } else { 2713 consumeError(AOrErr.takeError()); 2714 reportError(Filename, "Mach-O universal file for architecture " + 2715 StringRef(I->getArchFlagName()) + 2716 " is not a Mach-O file or an archive file"); 2717 } 2718 return; 2719 } 2720 } 2721 } 2722 // Either all architectures have been specified or none have been specified 2723 // and this does not contain the host architecture so dump all the slices. 2724 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 2725 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 2726 E = UB->end_objects(); 2727 I != E; ++I) { 2728 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 2729 std::string ArchitectureName; 2730 if (moreThanOneArch) 2731 ArchitectureName = I->getArchFlagName(); 2732 if (ObjOrErr) { 2733 ObjectFile &Obj = *ObjOrErr.get(); 2734 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 2735 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 2736 } else if (Error E = 2737 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 2738 reportError(std::move(E), Filename, "", ArchitectureName); 2739 } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { 2740 std::unique_ptr<Archive> &A = *AOrErr; 2741 outs() << "Archive : " << Filename; 2742 if (!ArchitectureName.empty()) 2743 outs() << " (architecture " << ArchitectureName << ")"; 2744 outs() << "\n"; 2745 if (ArchiveHeaders) 2746 printArchiveHeaders(Filename, A.get(), Verbose, ArchiveMemberOffsets, 2747 ArchitectureName); 2748 Error Err = Error::success(); 2749 unsigned I = -1; 2750 for (auto &C : A->children(Err)) { 2751 ++I; 2752 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); 2753 if (!ChildOrErr) { 2754 if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 2755 reportError(std::move(E), getFileNameForError(C, I), Filename, 2756 ArchitectureName); 2757 continue; 2758 } 2759 if (MachOObjectFile *O = 2760 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 2761 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 2762 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 2763 ArchitectureName); 2764 } 2765 } 2766 if (Err) 2767 reportError(std::move(Err), Filename); 2768 } else { 2769 consumeError(AOrErr.takeError()); 2770 reportError(Filename, "Mach-O universal file for architecture " + 2771 StringRef(I->getArchFlagName()) + 2772 " is not a Mach-O file or an archive file"); 2773 } 2774 } 2775 } 2776 2777 namespace { 2778 // The block of info used by the Symbolizer call backs. 2779 struct DisassembleInfo { 2780 DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, 2781 std::vector<SectionRef> *Sections, bool verbose) 2782 : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {} 2783 bool verbose; 2784 MachOObjectFile *O; 2785 SectionRef S; 2786 SymbolAddressMap *AddrMap; 2787 std::vector<SectionRef> *Sections; 2788 const char *class_name = nullptr; 2789 const char *selector_name = nullptr; 2790 std::unique_ptr<char[]> method = nullptr; 2791 char *demangled_name = nullptr; 2792 uint64_t adrp_addr = 0; 2793 uint32_t adrp_inst = 0; 2794 std::unique_ptr<SymbolAddressMap> bindtable; 2795 uint32_t depth = 0; 2796 }; 2797 } // namespace 2798 2799 // SymbolizerGetOpInfo() is the operand information call back function. 2800 // This is called to get the symbolic information for operand(s) of an 2801 // instruction when it is being done. This routine does this from 2802 // the relocation information, symbol table, etc. That block of information 2803 // is a pointer to the struct DisassembleInfo that was passed when the 2804 // disassembler context was created and passed to back to here when 2805 // called back by the disassembler for instruction operands that could have 2806 // relocation information. The address of the instruction containing operand is 2807 // at the Pc parameter. The immediate value the operand has is passed in 2808 // op_info->Value and is at Offset past the start of the instruction and has a 2809 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 2810 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 2811 // names and addends of the symbolic expression to add for the operand. The 2812 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 2813 // information is returned then this function returns 1 else it returns 0. 2814 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 2815 uint64_t OpSize, uint64_t InstSize, int TagType, 2816 void *TagBuf) { 2817 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2818 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 2819 uint64_t value = op_info->Value; 2820 2821 // Make sure all fields returned are zero if we don't set them. 2822 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 2823 op_info->Value = value; 2824 2825 // If the TagType is not the value 1 which it code knows about or if no 2826 // verbose symbolic information is wanted then just return 0, indicating no 2827 // information is being returned. 2828 if (TagType != 1 || !info->verbose) 2829 return 0; 2830 2831 unsigned int Arch = info->O->getArch(); 2832 if (Arch == Triple::x86) { 2833 if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0) 2834 return 0; 2835 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2836 // TODO: 2837 // Search the external relocation entries of a fully linked image 2838 // (if any) for an entry that matches this segment offset. 2839 // uint32_t seg_offset = (Pc + Offset); 2840 return 0; 2841 } 2842 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2843 // for an entry for this section offset. 2844 uint32_t sect_addr = info->S.getAddress(); 2845 uint32_t sect_offset = (Pc + Offset) - sect_addr; 2846 bool reloc_found = false; 2847 DataRefImpl Rel; 2848 MachO::any_relocation_info RE; 2849 bool isExtern = false; 2850 SymbolRef Symbol; 2851 bool r_scattered = false; 2852 uint32_t r_value, pair_r_value, r_type; 2853 for (const RelocationRef &Reloc : info->S.relocations()) { 2854 uint64_t RelocOffset = Reloc.getOffset(); 2855 if (RelocOffset == sect_offset) { 2856 Rel = Reloc.getRawDataRefImpl(); 2857 RE = info->O->getRelocation(Rel); 2858 r_type = info->O->getAnyRelocationType(RE); 2859 r_scattered = info->O->isRelocationScattered(RE); 2860 if (r_scattered) { 2861 r_value = info->O->getScatteredRelocationValue(RE); 2862 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2863 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 2864 DataRefImpl RelNext = Rel; 2865 info->O->moveRelocationNext(RelNext); 2866 MachO::any_relocation_info RENext; 2867 RENext = info->O->getRelocation(RelNext); 2868 if (info->O->isRelocationScattered(RENext)) 2869 pair_r_value = info->O->getScatteredRelocationValue(RENext); 2870 else 2871 return 0; 2872 } 2873 } else { 2874 isExtern = info->O->getPlainRelocationExternal(RE); 2875 if (isExtern) { 2876 symbol_iterator RelocSym = Reloc.getSymbol(); 2877 Symbol = *RelocSym; 2878 } 2879 } 2880 reloc_found = true; 2881 break; 2882 } 2883 } 2884 if (reloc_found && isExtern) { 2885 op_info->AddSymbol.Present = 1; 2886 op_info->AddSymbol.Name = 2887 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2888 // For i386 extern relocation entries the value in the instruction is 2889 // the offset from the symbol, and value is already set in op_info->Value. 2890 return 1; 2891 } 2892 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 2893 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 2894 const char *add = GuessSymbolName(r_value, info->AddrMap); 2895 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 2896 uint32_t offset = value - (r_value - pair_r_value); 2897 op_info->AddSymbol.Present = 1; 2898 if (add != nullptr) 2899 op_info->AddSymbol.Name = add; 2900 else 2901 op_info->AddSymbol.Value = r_value; 2902 op_info->SubtractSymbol.Present = 1; 2903 if (sub != nullptr) 2904 op_info->SubtractSymbol.Name = sub; 2905 else 2906 op_info->SubtractSymbol.Value = pair_r_value; 2907 op_info->Value = offset; 2908 return 1; 2909 } 2910 return 0; 2911 } 2912 if (Arch == Triple::x86_64) { 2913 if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0) 2914 return 0; 2915 // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external 2916 // relocation entries of a linked image (if any) for an entry that matches 2917 // this segment offset. 2918 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 2919 uint64_t seg_offset = Pc + Offset; 2920 bool reloc_found = false; 2921 DataRefImpl Rel; 2922 MachO::any_relocation_info RE; 2923 bool isExtern = false; 2924 SymbolRef Symbol; 2925 for (const RelocationRef &Reloc : info->O->external_relocations()) { 2926 uint64_t RelocOffset = Reloc.getOffset(); 2927 if (RelocOffset == seg_offset) { 2928 Rel = Reloc.getRawDataRefImpl(); 2929 RE = info->O->getRelocation(Rel); 2930 // external relocation entries should always be external. 2931 isExtern = info->O->getPlainRelocationExternal(RE); 2932 if (isExtern) { 2933 symbol_iterator RelocSym = Reloc.getSymbol(); 2934 Symbol = *RelocSym; 2935 } 2936 reloc_found = true; 2937 break; 2938 } 2939 } 2940 if (reloc_found && isExtern) { 2941 // The Value passed in will be adjusted by the Pc if the instruction 2942 // adds the Pc. But for x86_64 external relocation entries the Value 2943 // is the offset from the external symbol. 2944 if (info->O->getAnyRelocationPCRel(RE)) 2945 op_info->Value -= Pc + InstSize; 2946 const char *name = 2947 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2948 op_info->AddSymbol.Present = 1; 2949 op_info->AddSymbol.Name = name; 2950 return 1; 2951 } 2952 return 0; 2953 } 2954 // In MH_OBJECT filetypes search the section's relocation entries (if any) 2955 // for an entry for this section offset. 2956 uint64_t sect_addr = info->S.getAddress(); 2957 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2958 bool reloc_found = false; 2959 DataRefImpl Rel; 2960 MachO::any_relocation_info RE; 2961 bool isExtern = false; 2962 SymbolRef Symbol; 2963 for (const RelocationRef &Reloc : info->S.relocations()) { 2964 uint64_t RelocOffset = Reloc.getOffset(); 2965 if (RelocOffset == sect_offset) { 2966 Rel = Reloc.getRawDataRefImpl(); 2967 RE = info->O->getRelocation(Rel); 2968 // NOTE: Scattered relocations don't exist on x86_64. 2969 isExtern = info->O->getPlainRelocationExternal(RE); 2970 if (isExtern) { 2971 symbol_iterator RelocSym = Reloc.getSymbol(); 2972 Symbol = *RelocSym; 2973 } 2974 reloc_found = true; 2975 break; 2976 } 2977 } 2978 if (reloc_found && isExtern) { 2979 // The Value passed in will be adjusted by the Pc if the instruction 2980 // adds the Pc. But for x86_64 external relocation entries the Value 2981 // is the offset from the external symbol. 2982 if (info->O->getAnyRelocationPCRel(RE)) 2983 op_info->Value -= Pc + InstSize; 2984 const char *name = 2985 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 2986 unsigned Type = info->O->getAnyRelocationType(RE); 2987 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 2988 DataRefImpl RelNext = Rel; 2989 info->O->moveRelocationNext(RelNext); 2990 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2991 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 2992 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 2993 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 2994 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 2995 op_info->SubtractSymbol.Present = 1; 2996 op_info->SubtractSymbol.Name = name; 2997 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 2998 Symbol = *RelocSymNext; 2999 name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 3000 } 3001 } 3002 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 3003 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 3004 op_info->AddSymbol.Present = 1; 3005 op_info->AddSymbol.Name = name; 3006 return 1; 3007 } 3008 return 0; 3009 } 3010 if (Arch == Triple::arm) { 3011 if (Offset != 0 || (InstSize != 4 && InstSize != 2)) 3012 return 0; 3013 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 3014 // TODO: 3015 // Search the external relocation entries of a fully linked image 3016 // (if any) for an entry that matches this segment offset. 3017 // uint32_t seg_offset = (Pc + Offset); 3018 return 0; 3019 } 3020 // In MH_OBJECT filetypes search the section's relocation entries (if any) 3021 // for an entry for this section offset. 3022 uint32_t sect_addr = info->S.getAddress(); 3023 uint32_t sect_offset = (Pc + Offset) - sect_addr; 3024 DataRefImpl Rel; 3025 MachO::any_relocation_info RE; 3026 bool isExtern = false; 3027 SymbolRef Symbol; 3028 bool r_scattered = false; 3029 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 3030 auto Reloc = 3031 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 3032 uint64_t RelocOffset = Reloc.getOffset(); 3033 return RelocOffset == sect_offset; 3034 }); 3035 3036 if (Reloc == info->S.relocations().end()) 3037 return 0; 3038 3039 Rel = Reloc->getRawDataRefImpl(); 3040 RE = info->O->getRelocation(Rel); 3041 r_length = info->O->getAnyRelocationLength(RE); 3042 r_scattered = info->O->isRelocationScattered(RE); 3043 if (r_scattered) { 3044 r_value = info->O->getScatteredRelocationValue(RE); 3045 r_type = info->O->getScatteredRelocationType(RE); 3046 } else { 3047 r_type = info->O->getAnyRelocationType(RE); 3048 isExtern = info->O->getPlainRelocationExternal(RE); 3049 if (isExtern) { 3050 symbol_iterator RelocSym = Reloc->getSymbol(); 3051 Symbol = *RelocSym; 3052 } 3053 } 3054 if (r_type == MachO::ARM_RELOC_HALF || 3055 r_type == MachO::ARM_RELOC_SECTDIFF || 3056 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 3057 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 3058 DataRefImpl RelNext = Rel; 3059 info->O->moveRelocationNext(RelNext); 3060 MachO::any_relocation_info RENext; 3061 RENext = info->O->getRelocation(RelNext); 3062 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 3063 if (info->O->isRelocationScattered(RENext)) 3064 pair_r_value = info->O->getScatteredRelocationValue(RENext); 3065 } 3066 3067 if (isExtern) { 3068 const char *name = 3069 unwrapOrError(Symbol.getName(), info->O->getFileName()).data(); 3070 op_info->AddSymbol.Present = 1; 3071 op_info->AddSymbol.Name = name; 3072 switch (r_type) { 3073 case MachO::ARM_RELOC_HALF: 3074 if ((r_length & 0x1) == 1) { 3075 op_info->Value = value << 16 | other_half; 3076 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 3077 } else { 3078 op_info->Value = other_half << 16 | value; 3079 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 3080 } 3081 break; 3082 default: 3083 break; 3084 } 3085 return 1; 3086 } 3087 // If we have a branch that is not an external relocation entry then 3088 // return 0 so the code in tryAddingSymbolicOperand() can use the 3089 // SymbolLookUp call back with the branch target address to look up the 3090 // symbol and possibility add an annotation for a symbol stub. 3091 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 3092 r_type == MachO::ARM_THUMB_RELOC_BR22)) 3093 return 0; 3094 3095 uint32_t offset = 0; 3096 if (r_type == MachO::ARM_RELOC_HALF || 3097 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 3098 if ((r_length & 0x1) == 1) 3099 value = value << 16 | other_half; 3100 else 3101 value = other_half << 16 | value; 3102 } 3103 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 3104 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 3105 offset = value - r_value; 3106 value = r_value; 3107 } 3108 3109 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 3110 if ((r_length & 0x1) == 1) 3111 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 3112 else 3113 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 3114 const char *add = GuessSymbolName(r_value, info->AddrMap); 3115 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 3116 int32_t offset = value - (r_value - pair_r_value); 3117 op_info->AddSymbol.Present = 1; 3118 if (add != nullptr) 3119 op_info->AddSymbol.Name = add; 3120 else 3121 op_info->AddSymbol.Value = r_value; 3122 op_info->SubtractSymbol.Present = 1; 3123 if (sub != nullptr) 3124 op_info->SubtractSymbol.Name = sub; 3125 else 3126 op_info->SubtractSymbol.Value = pair_r_value; 3127 op_info->Value = offset; 3128 return 1; 3129 } 3130 3131 op_info->AddSymbol.Present = 1; 3132 op_info->Value = offset; 3133 if (r_type == MachO::ARM_RELOC_HALF) { 3134 if ((r_length & 0x1) == 1) 3135 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 3136 else 3137 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 3138 } 3139 const char *add = GuessSymbolName(value, info->AddrMap); 3140 if (add != nullptr) { 3141 op_info->AddSymbol.Name = add; 3142 return 1; 3143 } 3144 op_info->AddSymbol.Value = value; 3145 return 1; 3146 } 3147 if (Arch == Triple::aarch64) { 3148 if (Offset != 0 || InstSize != 4) 3149 return 0; 3150 if (info->O->getHeader().filetype != MachO::MH_OBJECT) { 3151 // TODO: 3152 // Search the external relocation entries of a fully linked image 3153 // (if any) for an entry that matches this segment offset. 3154 // uint64_t seg_offset = (Pc + Offset); 3155 return 0; 3156 } 3157 // In MH_OBJECT filetypes search the section's relocation entries (if any) 3158 // for an entry for this section offset. 3159 uint64_t sect_addr = info->S.getAddress(); 3160 uint64_t sect_offset = (Pc + Offset) - sect_addr; 3161 auto Reloc = 3162 find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { 3163 uint64_t RelocOffset = Reloc.getOffset(); 3164 return RelocOffset == sect_offset; 3165 }); 3166 3167 if (Reloc == info->S.relocations().end()) 3168 return 0; 3169 3170 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 3171 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 3172 uint32_t r_type = info->O->getAnyRelocationType(RE); 3173 if (r_type == MachO::ARM64_RELOC_ADDEND) { 3174 DataRefImpl RelNext = Rel; 3175 info->O->moveRelocationNext(RelNext); 3176 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 3177 if (value == 0) { 3178 value = info->O->getPlainRelocationSymbolNum(RENext); 3179 op_info->Value = value; 3180 } 3181 } 3182 // NOTE: Scattered relocations don't exist on arm64. 3183 if (!info->O->getPlainRelocationExternal(RE)) 3184 return 0; 3185 const char *name = 3186 unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName()) 3187 .data(); 3188 op_info->AddSymbol.Present = 1; 3189 op_info->AddSymbol.Name = name; 3190 3191 switch (r_type) { 3192 case MachO::ARM64_RELOC_PAGE21: 3193 /* @page */ 3194 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 3195 break; 3196 case MachO::ARM64_RELOC_PAGEOFF12: 3197 /* @pageoff */ 3198 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 3199 break; 3200 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 3201 /* @gotpage */ 3202 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 3203 break; 3204 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 3205 /* @gotpageoff */ 3206 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 3207 break; 3208 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 3209 /* @tvlppage is not implemented in llvm-mc */ 3210 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 3211 break; 3212 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 3213 /* @tvlppageoff is not implemented in llvm-mc */ 3214 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 3215 break; 3216 default: 3217 case MachO::ARM64_RELOC_BRANCH26: 3218 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 3219 break; 3220 } 3221 return 1; 3222 } 3223 return 0; 3224 } 3225 3226 // GuessCstringPointer is passed the address of what might be a pointer to a 3227 // literal string in a cstring section. If that address is in a cstring section 3228 // it returns a pointer to that string. Else it returns nullptr. 3229 static const char *GuessCstringPointer(uint64_t ReferenceValue, 3230 struct DisassembleInfo *info) { 3231 for (const auto &Load : info->O->load_commands()) { 3232 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3233 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3234 for (unsigned J = 0; J < Seg.nsects; ++J) { 3235 MachO::section_64 Sec = info->O->getSection64(Load, J); 3236 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3237 if (section_type == MachO::S_CSTRING_LITERALS && 3238 ReferenceValue >= Sec.addr && 3239 ReferenceValue < Sec.addr + Sec.size) { 3240 uint64_t sect_offset = ReferenceValue - Sec.addr; 3241 uint64_t object_offset = Sec.offset + sect_offset; 3242 StringRef MachOContents = info->O->getData(); 3243 uint64_t object_size = MachOContents.size(); 3244 const char *object_addr = (const char *)MachOContents.data(); 3245 if (object_offset < object_size) { 3246 const char *name = object_addr + object_offset; 3247 return name; 3248 } else { 3249 return nullptr; 3250 } 3251 } 3252 } 3253 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3254 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3255 for (unsigned J = 0; J < Seg.nsects; ++J) { 3256 MachO::section Sec = info->O->getSection(Load, J); 3257 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3258 if (section_type == MachO::S_CSTRING_LITERALS && 3259 ReferenceValue >= Sec.addr && 3260 ReferenceValue < Sec.addr + Sec.size) { 3261 uint64_t sect_offset = ReferenceValue - Sec.addr; 3262 uint64_t object_offset = Sec.offset + sect_offset; 3263 StringRef MachOContents = info->O->getData(); 3264 uint64_t object_size = MachOContents.size(); 3265 const char *object_addr = (const char *)MachOContents.data(); 3266 if (object_offset < object_size) { 3267 const char *name = object_addr + object_offset; 3268 return name; 3269 } else { 3270 return nullptr; 3271 } 3272 } 3273 } 3274 } 3275 } 3276 return nullptr; 3277 } 3278 3279 // GuessIndirectSymbol returns the name of the indirect symbol for the 3280 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 3281 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 3282 // symbol name being referenced by the stub or pointer. 3283 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 3284 struct DisassembleInfo *info) { 3285 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 3286 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 3287 for (const auto &Load : info->O->load_commands()) { 3288 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3289 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3290 for (unsigned J = 0; J < Seg.nsects; ++J) { 3291 MachO::section_64 Sec = info->O->getSection64(Load, J); 3292 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3293 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3294 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3295 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3296 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3297 section_type == MachO::S_SYMBOL_STUBS) && 3298 ReferenceValue >= Sec.addr && 3299 ReferenceValue < Sec.addr + Sec.size) { 3300 uint32_t stride; 3301 if (section_type == MachO::S_SYMBOL_STUBS) 3302 stride = Sec.reserved2; 3303 else 3304 stride = 8; 3305 if (stride == 0) 3306 return nullptr; 3307 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3308 if (index < Dysymtab.nindirectsyms) { 3309 uint32_t indirect_symbol = 3310 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3311 if (indirect_symbol < Symtab.nsyms) { 3312 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3313 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3314 .data(); 3315 } 3316 } 3317 } 3318 } 3319 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 3320 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 3321 for (unsigned J = 0; J < Seg.nsects; ++J) { 3322 MachO::section Sec = info->O->getSection(Load, J); 3323 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 3324 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3325 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3326 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3327 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 3328 section_type == MachO::S_SYMBOL_STUBS) && 3329 ReferenceValue >= Sec.addr && 3330 ReferenceValue < Sec.addr + Sec.size) { 3331 uint32_t stride; 3332 if (section_type == MachO::S_SYMBOL_STUBS) 3333 stride = Sec.reserved2; 3334 else 3335 stride = 4; 3336 if (stride == 0) 3337 return nullptr; 3338 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 3339 if (index < Dysymtab.nindirectsyms) { 3340 uint32_t indirect_symbol = 3341 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 3342 if (indirect_symbol < Symtab.nsyms) { 3343 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 3344 return unwrapOrError(Sym->getName(), info->O->getFileName()) 3345 .data(); 3346 } 3347 } 3348 } 3349 } 3350 } 3351 } 3352 return nullptr; 3353 } 3354 3355 // method_reference() is called passing it the ReferenceName that might be 3356 // a reference it to an Objective-C method call. If so then it allocates and 3357 // assembles a method call string with the values last seen and saved in 3358 // the DisassembleInfo's class_name and selector_name fields. This is saved 3359 // into the method field of the info and any previous string is free'ed. 3360 // Then the class_name field in the info is set to nullptr. The method call 3361 // string is set into ReferenceName and ReferenceType is set to 3362 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 3363 // then both ReferenceType and ReferenceName are left unchanged. 3364 static void method_reference(struct DisassembleInfo *info, 3365 uint64_t *ReferenceType, 3366 const char **ReferenceName) { 3367 unsigned int Arch = info->O->getArch(); 3368 if (*ReferenceName != nullptr) { 3369 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 3370 if (info->selector_name != nullptr) { 3371 if (info->class_name != nullptr) { 3372 info->method = std::make_unique<char[]>( 3373 5 + strlen(info->class_name) + strlen(info->selector_name)); 3374 char *method = info->method.get(); 3375 if (method != nullptr) { 3376 strcpy(method, "+["); 3377 strcat(method, info->class_name); 3378 strcat(method, " "); 3379 strcat(method, info->selector_name); 3380 strcat(method, "]"); 3381 *ReferenceName = method; 3382 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3383 } 3384 } else { 3385 info->method = 3386 std::make_unique<char[]>(9 + strlen(info->selector_name)); 3387 char *method = info->method.get(); 3388 if (method != nullptr) { 3389 if (Arch == Triple::x86_64) 3390 strcpy(method, "-[%rdi "); 3391 else if (Arch == Triple::aarch64) 3392 strcpy(method, "-[x0 "); 3393 else 3394 strcpy(method, "-[r? "); 3395 strcat(method, info->selector_name); 3396 strcat(method, "]"); 3397 *ReferenceName = method; 3398 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3399 } 3400 } 3401 info->class_name = nullptr; 3402 } 3403 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 3404 if (info->selector_name != nullptr) { 3405 info->method = 3406 std::make_unique<char[]>(17 + strlen(info->selector_name)); 3407 char *method = info->method.get(); 3408 if (method != nullptr) { 3409 if (Arch == Triple::x86_64) 3410 strcpy(method, "-[[%rdi super] "); 3411 else if (Arch == Triple::aarch64) 3412 strcpy(method, "-[[x0 super] "); 3413 else 3414 strcpy(method, "-[[r? super] "); 3415 strcat(method, info->selector_name); 3416 strcat(method, "]"); 3417 *ReferenceName = method; 3418 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 3419 } 3420 info->class_name = nullptr; 3421 } 3422 } 3423 } 3424 } 3425 3426 // GuessPointerPointer() is passed the address of what might be a pointer to 3427 // a reference to an Objective-C class, selector, message ref or cfstring. 3428 // If so the value of the pointer is returned and one of the booleans are set 3429 // to true. If not zero is returned and all the booleans are set to false. 3430 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 3431 struct DisassembleInfo *info, 3432 bool &classref, bool &selref, bool &msgref, 3433 bool &cfstring) { 3434 classref = false; 3435 selref = false; 3436 msgref = false; 3437 cfstring = false; 3438 for (const auto &Load : info->O->load_commands()) { 3439 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 3440 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 3441 for (unsigned J = 0; J < Seg.nsects; ++J) { 3442 MachO::section_64 Sec = info->O->getSection64(Load, J); 3443 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 3444 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3445 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 3446 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 3447 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 3448 ReferenceValue >= Sec.addr && 3449 ReferenceValue < Sec.addr + Sec.size) { 3450 uint64_t sect_offset = ReferenceValue - Sec.addr; 3451 uint64_t object_offset = Sec.offset + sect_offset; 3452 StringRef MachOContents = info->O->getData(); 3453 uint64_t object_size = MachOContents.size(); 3454 const char *object_addr = (const char *)MachOContents.data(); 3455 if (object_offset < object_size) { 3456 uint64_t pointer_value; 3457 memcpy(&pointer_value, object_addr + object_offset, 3458 sizeof(uint64_t)); 3459 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3460 sys::swapByteOrder(pointer_value); 3461 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 3462 selref = true; 3463 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 3464 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 3465 classref = true; 3466 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 3467 ReferenceValue + 8 < Sec.addr + Sec.size) { 3468 msgref = true; 3469 memcpy(&pointer_value, object_addr + object_offset + 8, 3470 sizeof(uint64_t)); 3471 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 3472 sys::swapByteOrder(pointer_value); 3473 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 3474 cfstring = true; 3475 return pointer_value; 3476 } else { 3477 return 0; 3478 } 3479 } 3480 } 3481 } 3482 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 3483 } 3484 return 0; 3485 } 3486 3487 // get_pointer_64 returns a pointer to the bytes in the object file at the 3488 // Address from a section in the Mach-O file. And indirectly returns the 3489 // offset into the section, number of bytes left in the section past the offset 3490 // and which section is was being referenced. If the Address is not in a 3491 // section nullptr is returned. 3492 static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 3493 uint32_t &left, SectionRef &S, 3494 DisassembleInfo *info, 3495 bool objc_only = false) { 3496 offset = 0; 3497 left = 0; 3498 S = SectionRef(); 3499 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 3500 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 3501 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 3502 if (SectSize == 0) 3503 continue; 3504 if (objc_only) { 3505 StringRef SectName; 3506 Expected<StringRef> SecNameOrErr = 3507 ((*(info->Sections))[SectIdx]).getName(); 3508 if (SecNameOrErr) 3509 SectName = *SecNameOrErr; 3510 else 3511 consumeError(SecNameOrErr.takeError()); 3512 3513 DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl(); 3514 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 3515 if (SegName != "__OBJC" && SectName != "__cstring") 3516 continue; 3517 } 3518 if (Address >= SectAddress && Address < SectAddress + SectSize) { 3519 S = (*(info->Sections))[SectIdx]; 3520 offset = Address - SectAddress; 3521 left = SectSize - offset; 3522 StringRef SectContents = unwrapOrError( 3523 ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName()); 3524 return SectContents.data() + offset; 3525 } 3526 } 3527 return nullptr; 3528 } 3529 3530 static const char *get_pointer_32(uint32_t Address, uint32_t &offset, 3531 uint32_t &left, SectionRef &S, 3532 DisassembleInfo *info, 3533 bool objc_only = false) { 3534 return get_pointer_64(Address, offset, left, S, info, objc_only); 3535 } 3536 3537 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 3538 // the symbol indirectly through n_value. Based on the relocation information 3539 // for the specified section offset in the specified section reference. 3540 // If no relocation information is found and a non-zero ReferenceValue for the 3541 // symbol is passed, look up that address in the info's AddrMap. 3542 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 3543 DisassembleInfo *info, uint64_t &n_value, 3544 uint64_t ReferenceValue = 0) { 3545 n_value = 0; 3546 if (!info->verbose) 3547 return nullptr; 3548 3549 // See if there is an external relocation entry at the sect_offset. 3550 bool reloc_found = false; 3551 DataRefImpl Rel; 3552 MachO::any_relocation_info RE; 3553 bool isExtern = false; 3554 SymbolRef Symbol; 3555 for (const RelocationRef &Reloc : S.relocations()) { 3556 uint64_t RelocOffset = Reloc.getOffset(); 3557 if (RelocOffset == sect_offset) { 3558 Rel = Reloc.getRawDataRefImpl(); 3559 RE = info->O->getRelocation(Rel); 3560 if (info->O->isRelocationScattered(RE)) 3561 continue; 3562 isExtern = info->O->getPlainRelocationExternal(RE); 3563 if (isExtern) { 3564 symbol_iterator RelocSym = Reloc.getSymbol(); 3565 Symbol = *RelocSym; 3566 } 3567 reloc_found = true; 3568 break; 3569 } 3570 } 3571 // If there is an external relocation entry for a symbol in this section 3572 // at this section_offset then use that symbol's value for the n_value 3573 // and return its name. 3574 const char *SymbolName = nullptr; 3575 if (reloc_found && isExtern) { 3576 n_value = cantFail(Symbol.getValue()); 3577 StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName()); 3578 if (!Name.empty()) { 3579 SymbolName = Name.data(); 3580 return SymbolName; 3581 } 3582 } 3583 3584 // TODO: For fully linked images, look through the external relocation 3585 // entries off the dynamic symtab command. For these the r_offset is from the 3586 // start of the first writeable segment in the Mach-O file. So the offset 3587 // to this section from that segment is passed to this routine by the caller, 3588 // as the database_offset. Which is the difference of the section's starting 3589 // address and the first writable segment. 3590 // 3591 // NOTE: need add passing the database_offset to this routine. 3592 3593 // We did not find an external relocation entry so look up the ReferenceValue 3594 // as an address of a symbol and if found return that symbol's name. 3595 SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 3596 3597 return SymbolName; 3598 } 3599 3600 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, 3601 DisassembleInfo *info, 3602 uint32_t ReferenceValue) { 3603 uint64_t n_value64; 3604 return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue); 3605 } 3606 3607 namespace { 3608 3609 // These are structs in the Objective-C meta data and read to produce the 3610 // comments for disassembly. While these are part of the ABI they are no 3611 // public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h 3612 // . 3613 3614 // The cfstring object in a 64-bit Mach-O file. 3615 struct cfstring64_t { 3616 uint64_t isa; // class64_t * (64-bit pointer) 3617 uint64_t flags; // flag bits 3618 uint64_t characters; // char * (64-bit pointer) 3619 uint64_t length; // number of non-NULL characters in above 3620 }; 3621 3622 // The class object in a 64-bit Mach-O file. 3623 struct class64_t { 3624 uint64_t isa; // class64_t * (64-bit pointer) 3625 uint64_t superclass; // class64_t * (64-bit pointer) 3626 uint64_t cache; // Cache (64-bit pointer) 3627 uint64_t vtable; // IMP * (64-bit pointer) 3628 uint64_t data; // class_ro64_t * (64-bit pointer) 3629 }; 3630 3631 struct class32_t { 3632 uint32_t isa; /* class32_t * (32-bit pointer) */ 3633 uint32_t superclass; /* class32_t * (32-bit pointer) */ 3634 uint32_t cache; /* Cache (32-bit pointer) */ 3635 uint32_t vtable; /* IMP * (32-bit pointer) */ 3636 uint32_t data; /* class_ro32_t * (32-bit pointer) */ 3637 }; 3638 3639 struct class_ro64_t { 3640 uint32_t flags; 3641 uint32_t instanceStart; 3642 uint32_t instanceSize; 3643 uint32_t reserved; 3644 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 3645 uint64_t name; // const char * (64-bit pointer) 3646 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 3647 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 3648 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 3649 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 3650 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 3651 }; 3652 3653 struct class_ro32_t { 3654 uint32_t flags; 3655 uint32_t instanceStart; 3656 uint32_t instanceSize; 3657 uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */ 3658 uint32_t name; /* const char * (32-bit pointer) */ 3659 uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */ 3660 uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */ 3661 uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */ 3662 uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */ 3663 uint32_t baseProperties; /* const struct objc_property_list * 3664 (32-bit pointer) */ 3665 }; 3666 3667 /* Values for class_ro{64,32}_t->flags */ 3668 #define RO_META (1 << 0) 3669 #define RO_ROOT (1 << 1) 3670 #define RO_HAS_CXX_STRUCTORS (1 << 2) 3671 3672 /* Values for method_list{64,32}_t->entsize */ 3673 #define ML_HAS_RELATIVE_PTRS (1 << 31) 3674 #define ML_ENTSIZE_MASK 0xFFFF 3675 3676 struct method_list64_t { 3677 uint32_t entsize; 3678 uint32_t count; 3679 /* struct method64_t first; These structures follow inline */ 3680 }; 3681 3682 struct method_list32_t { 3683 uint32_t entsize; 3684 uint32_t count; 3685 /* struct method32_t first; These structures follow inline */ 3686 }; 3687 3688 struct method64_t { 3689 uint64_t name; /* SEL (64-bit pointer) */ 3690 uint64_t types; /* const char * (64-bit pointer) */ 3691 uint64_t imp; /* IMP (64-bit pointer) */ 3692 }; 3693 3694 struct method32_t { 3695 uint32_t name; /* SEL (32-bit pointer) */ 3696 uint32_t types; /* const char * (32-bit pointer) */ 3697 uint32_t imp; /* IMP (32-bit pointer) */ 3698 }; 3699 3700 struct method_relative_t { 3701 int32_t name; /* SEL (32-bit relative) */ 3702 int32_t types; /* const char * (32-bit relative) */ 3703 int32_t imp; /* IMP (32-bit relative) */ 3704 }; 3705 3706 struct protocol_list64_t { 3707 uint64_t count; /* uintptr_t (a 64-bit value) */ 3708 /* struct protocol64_t * list[0]; These pointers follow inline */ 3709 }; 3710 3711 struct protocol_list32_t { 3712 uint32_t count; /* uintptr_t (a 32-bit value) */ 3713 /* struct protocol32_t * list[0]; These pointers follow inline */ 3714 }; 3715 3716 struct protocol64_t { 3717 uint64_t isa; /* id * (64-bit pointer) */ 3718 uint64_t name; /* const char * (64-bit pointer) */ 3719 uint64_t protocols; /* struct protocol_list64_t * 3720 (64-bit pointer) */ 3721 uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */ 3722 uint64_t classMethods; /* method_list_t * (64-bit pointer) */ 3723 uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */ 3724 uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */ 3725 uint64_t instanceProperties; /* struct objc_property_list * 3726 (64-bit pointer) */ 3727 }; 3728 3729 struct protocol32_t { 3730 uint32_t isa; /* id * (32-bit pointer) */ 3731 uint32_t name; /* const char * (32-bit pointer) */ 3732 uint32_t protocols; /* struct protocol_list_t * 3733 (32-bit pointer) */ 3734 uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */ 3735 uint32_t classMethods; /* method_list_t * (32-bit pointer) */ 3736 uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */ 3737 uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */ 3738 uint32_t instanceProperties; /* struct objc_property_list * 3739 (32-bit pointer) */ 3740 }; 3741 3742 struct ivar_list64_t { 3743 uint32_t entsize; 3744 uint32_t count; 3745 /* struct ivar64_t first; These structures follow inline */ 3746 }; 3747 3748 struct ivar_list32_t { 3749 uint32_t entsize; 3750 uint32_t count; 3751 /* struct ivar32_t first; These structures follow inline */ 3752 }; 3753 3754 struct ivar64_t { 3755 uint64_t offset; /* uintptr_t * (64-bit pointer) */ 3756 uint64_t name; /* const char * (64-bit pointer) */ 3757 uint64_t type; /* const char * (64-bit pointer) */ 3758 uint32_t alignment; 3759 uint32_t size; 3760 }; 3761 3762 struct ivar32_t { 3763 uint32_t offset; /* uintptr_t * (32-bit pointer) */ 3764 uint32_t name; /* const char * (32-bit pointer) */ 3765 uint32_t type; /* const char * (32-bit pointer) */ 3766 uint32_t alignment; 3767 uint32_t size; 3768 }; 3769 3770 struct objc_property_list64 { 3771 uint32_t entsize; 3772 uint32_t count; 3773 /* struct objc_property64 first; These structures follow inline */ 3774 }; 3775 3776 struct objc_property_list32 { 3777 uint32_t entsize; 3778 uint32_t count; 3779 /* struct objc_property32 first; These structures follow inline */ 3780 }; 3781 3782 struct objc_property64 { 3783 uint64_t name; /* const char * (64-bit pointer) */ 3784 uint64_t attributes; /* const char * (64-bit pointer) */ 3785 }; 3786 3787 struct objc_property32 { 3788 uint32_t name; /* const char * (32-bit pointer) */ 3789 uint32_t attributes; /* const char * (32-bit pointer) */ 3790 }; 3791 3792 struct category64_t { 3793 uint64_t name; /* const char * (64-bit pointer) */ 3794 uint64_t cls; /* struct class_t * (64-bit pointer) */ 3795 uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */ 3796 uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */ 3797 uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */ 3798 uint64_t instanceProperties; /* struct objc_property_list * 3799 (64-bit pointer) */ 3800 }; 3801 3802 struct category32_t { 3803 uint32_t name; /* const char * (32-bit pointer) */ 3804 uint32_t cls; /* struct class_t * (32-bit pointer) */ 3805 uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */ 3806 uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */ 3807 uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */ 3808 uint32_t instanceProperties; /* struct objc_property_list * 3809 (32-bit pointer) */ 3810 }; 3811 3812 struct objc_image_info64 { 3813 uint32_t version; 3814 uint32_t flags; 3815 }; 3816 struct objc_image_info32 { 3817 uint32_t version; 3818 uint32_t flags; 3819 }; 3820 struct imageInfo_t { 3821 uint32_t version; 3822 uint32_t flags; 3823 }; 3824 /* masks for objc_image_info.flags */ 3825 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0) 3826 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) 3827 #define OBJC_IMAGE_IS_SIMULATED (1 << 5) 3828 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6) 3829 3830 struct message_ref64 { 3831 uint64_t imp; /* IMP (64-bit pointer) */ 3832 uint64_t sel; /* SEL (64-bit pointer) */ 3833 }; 3834 3835 struct message_ref32 { 3836 uint32_t imp; /* IMP (32-bit pointer) */ 3837 uint32_t sel; /* SEL (32-bit pointer) */ 3838 }; 3839 3840 // Objective-C 1 (32-bit only) meta data structs. 3841 3842 struct objc_module_t { 3843 uint32_t version; 3844 uint32_t size; 3845 uint32_t name; /* char * (32-bit pointer) */ 3846 uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */ 3847 }; 3848 3849 struct objc_symtab_t { 3850 uint32_t sel_ref_cnt; 3851 uint32_t refs; /* SEL * (32-bit pointer) */ 3852 uint16_t cls_def_cnt; 3853 uint16_t cat_def_cnt; 3854 // uint32_t defs[1]; /* void * (32-bit pointer) variable size */ 3855 }; 3856 3857 struct objc_class_t { 3858 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3859 uint32_t super_class; /* struct objc_class * (32-bit pointer) */ 3860 uint32_t name; /* const char * (32-bit pointer) */ 3861 int32_t version; 3862 int32_t info; 3863 int32_t instance_size; 3864 uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */ 3865 uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */ 3866 uint32_t cache; /* struct objc_cache * (32-bit pointer) */ 3867 uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */ 3868 }; 3869 3870 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask)) 3871 // class is not a metaclass 3872 #define CLS_CLASS 0x1 3873 // class is a metaclass 3874 #define CLS_META 0x2 3875 3876 struct objc_category_t { 3877 uint32_t category_name; /* char * (32-bit pointer) */ 3878 uint32_t class_name; /* char * (32-bit pointer) */ 3879 uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */ 3880 uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */ 3881 uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */ 3882 }; 3883 3884 struct objc_ivar_t { 3885 uint32_t ivar_name; /* char * (32-bit pointer) */ 3886 uint32_t ivar_type; /* char * (32-bit pointer) */ 3887 int32_t ivar_offset; 3888 }; 3889 3890 struct objc_ivar_list_t { 3891 int32_t ivar_count; 3892 // struct objc_ivar_t ivar_list[1]; /* variable length structure */ 3893 }; 3894 3895 struct objc_method_list_t { 3896 uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */ 3897 int32_t method_count; 3898 // struct objc_method_t method_list[1]; /* variable length structure */ 3899 }; 3900 3901 struct objc_method_t { 3902 uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3903 uint32_t method_types; /* char * (32-bit pointer) */ 3904 uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...) 3905 (32-bit pointer) */ 3906 }; 3907 3908 struct objc_protocol_list_t { 3909 uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */ 3910 int32_t count; 3911 // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t * 3912 // (32-bit pointer) */ 3913 }; 3914 3915 struct objc_protocol_t { 3916 uint32_t isa; /* struct objc_class * (32-bit pointer) */ 3917 uint32_t protocol_name; /* char * (32-bit pointer) */ 3918 uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */ 3919 uint32_t instance_methods; /* struct objc_method_description_list * 3920 (32-bit pointer) */ 3921 uint32_t class_methods; /* struct objc_method_description_list * 3922 (32-bit pointer) */ 3923 }; 3924 3925 struct objc_method_description_list_t { 3926 int32_t count; 3927 // struct objc_method_description_t list[1]; 3928 }; 3929 3930 struct objc_method_description_t { 3931 uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */ 3932 uint32_t types; /* char * (32-bit pointer) */ 3933 }; 3934 3935 inline void swapStruct(struct cfstring64_t &cfs) { 3936 sys::swapByteOrder(cfs.isa); 3937 sys::swapByteOrder(cfs.flags); 3938 sys::swapByteOrder(cfs.characters); 3939 sys::swapByteOrder(cfs.length); 3940 } 3941 3942 inline void swapStruct(struct class64_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 class32_t &c) { 3951 sys::swapByteOrder(c.isa); 3952 sys::swapByteOrder(c.superclass); 3953 sys::swapByteOrder(c.cache); 3954 sys::swapByteOrder(c.vtable); 3955 sys::swapByteOrder(c.data); 3956 } 3957 3958 inline void swapStruct(struct class_ro64_t &cro) { 3959 sys::swapByteOrder(cro.flags); 3960 sys::swapByteOrder(cro.instanceStart); 3961 sys::swapByteOrder(cro.instanceSize); 3962 sys::swapByteOrder(cro.reserved); 3963 sys::swapByteOrder(cro.ivarLayout); 3964 sys::swapByteOrder(cro.name); 3965 sys::swapByteOrder(cro.baseMethods); 3966 sys::swapByteOrder(cro.baseProtocols); 3967 sys::swapByteOrder(cro.ivars); 3968 sys::swapByteOrder(cro.weakIvarLayout); 3969 sys::swapByteOrder(cro.baseProperties); 3970 } 3971 3972 inline void swapStruct(struct class_ro32_t &cro) { 3973 sys::swapByteOrder(cro.flags); 3974 sys::swapByteOrder(cro.instanceStart); 3975 sys::swapByteOrder(cro.instanceSize); 3976 sys::swapByteOrder(cro.ivarLayout); 3977 sys::swapByteOrder(cro.name); 3978 sys::swapByteOrder(cro.baseMethods); 3979 sys::swapByteOrder(cro.baseProtocols); 3980 sys::swapByteOrder(cro.ivars); 3981 sys::swapByteOrder(cro.weakIvarLayout); 3982 sys::swapByteOrder(cro.baseProperties); 3983 } 3984 3985 inline void swapStruct(struct method_list64_t &ml) { 3986 sys::swapByteOrder(ml.entsize); 3987 sys::swapByteOrder(ml.count); 3988 } 3989 3990 inline void swapStruct(struct method_list32_t &ml) { 3991 sys::swapByteOrder(ml.entsize); 3992 sys::swapByteOrder(ml.count); 3993 } 3994 3995 inline void swapStruct(struct method64_t &m) { 3996 sys::swapByteOrder(m.name); 3997 sys::swapByteOrder(m.types); 3998 sys::swapByteOrder(m.imp); 3999 } 4000 4001 inline void swapStruct(struct method32_t &m) { 4002 sys::swapByteOrder(m.name); 4003 sys::swapByteOrder(m.types); 4004 sys::swapByteOrder(m.imp); 4005 } 4006 4007 inline void swapStruct(struct method_relative_t &m) { 4008 sys::swapByteOrder(m.name); 4009 sys::swapByteOrder(m.types); 4010 sys::swapByteOrder(m.imp); 4011 } 4012 4013 inline void swapStruct(struct protocol_list64_t &pl) { 4014 sys::swapByteOrder(pl.count); 4015 } 4016 4017 inline void swapStruct(struct protocol_list32_t &pl) { 4018 sys::swapByteOrder(pl.count); 4019 } 4020 4021 inline void swapStruct(struct protocol64_t &p) { 4022 sys::swapByteOrder(p.isa); 4023 sys::swapByteOrder(p.name); 4024 sys::swapByteOrder(p.protocols); 4025 sys::swapByteOrder(p.instanceMethods); 4026 sys::swapByteOrder(p.classMethods); 4027 sys::swapByteOrder(p.optionalInstanceMethods); 4028 sys::swapByteOrder(p.optionalClassMethods); 4029 sys::swapByteOrder(p.instanceProperties); 4030 } 4031 4032 inline void swapStruct(struct protocol32_t &p) { 4033 sys::swapByteOrder(p.isa); 4034 sys::swapByteOrder(p.name); 4035 sys::swapByteOrder(p.protocols); 4036 sys::swapByteOrder(p.instanceMethods); 4037 sys::swapByteOrder(p.classMethods); 4038 sys::swapByteOrder(p.optionalInstanceMethods); 4039 sys::swapByteOrder(p.optionalClassMethods); 4040 sys::swapByteOrder(p.instanceProperties); 4041 } 4042 4043 inline void swapStruct(struct ivar_list64_t &il) { 4044 sys::swapByteOrder(il.entsize); 4045 sys::swapByteOrder(il.count); 4046 } 4047 4048 inline void swapStruct(struct ivar_list32_t &il) { 4049 sys::swapByteOrder(il.entsize); 4050 sys::swapByteOrder(il.count); 4051 } 4052 4053 inline void swapStruct(struct ivar64_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 ivar32_t &i) { 4062 sys::swapByteOrder(i.offset); 4063 sys::swapByteOrder(i.name); 4064 sys::swapByteOrder(i.type); 4065 sys::swapByteOrder(i.alignment); 4066 sys::swapByteOrder(i.size); 4067 } 4068 4069 inline void swapStruct(struct objc_property_list64 &pl) { 4070 sys::swapByteOrder(pl.entsize); 4071 sys::swapByteOrder(pl.count); 4072 } 4073 4074 inline void swapStruct(struct objc_property_list32 &pl) { 4075 sys::swapByteOrder(pl.entsize); 4076 sys::swapByteOrder(pl.count); 4077 } 4078 4079 inline void swapStruct(struct objc_property64 &op) { 4080 sys::swapByteOrder(op.name); 4081 sys::swapByteOrder(op.attributes); 4082 } 4083 4084 inline void swapStruct(struct objc_property32 &op) { 4085 sys::swapByteOrder(op.name); 4086 sys::swapByteOrder(op.attributes); 4087 } 4088 4089 inline void swapStruct(struct category64_t &c) { 4090 sys::swapByteOrder(c.name); 4091 sys::swapByteOrder(c.cls); 4092 sys::swapByteOrder(c.instanceMethods); 4093 sys::swapByteOrder(c.classMethods); 4094 sys::swapByteOrder(c.protocols); 4095 sys::swapByteOrder(c.instanceProperties); 4096 } 4097 4098 inline void swapStruct(struct category32_t &c) { 4099 sys::swapByteOrder(c.name); 4100 sys::swapByteOrder(c.cls); 4101 sys::swapByteOrder(c.instanceMethods); 4102 sys::swapByteOrder(c.classMethods); 4103 sys::swapByteOrder(c.protocols); 4104 sys::swapByteOrder(c.instanceProperties); 4105 } 4106 4107 inline void swapStruct(struct objc_image_info64 &o) { 4108 sys::swapByteOrder(o.version); 4109 sys::swapByteOrder(o.flags); 4110 } 4111 4112 inline void swapStruct(struct objc_image_info32 &o) { 4113 sys::swapByteOrder(o.version); 4114 sys::swapByteOrder(o.flags); 4115 } 4116 4117 inline void swapStruct(struct imageInfo_t &o) { 4118 sys::swapByteOrder(o.version); 4119 sys::swapByteOrder(o.flags); 4120 } 4121 4122 inline void swapStruct(struct message_ref64 &mr) { 4123 sys::swapByteOrder(mr.imp); 4124 sys::swapByteOrder(mr.sel); 4125 } 4126 4127 inline void swapStruct(struct message_ref32 &mr) { 4128 sys::swapByteOrder(mr.imp); 4129 sys::swapByteOrder(mr.sel); 4130 } 4131 4132 inline void swapStruct(struct objc_module_t &module) { 4133 sys::swapByteOrder(module.version); 4134 sys::swapByteOrder(module.size); 4135 sys::swapByteOrder(module.name); 4136 sys::swapByteOrder(module.symtab); 4137 } 4138 4139 inline void swapStruct(struct objc_symtab_t &symtab) { 4140 sys::swapByteOrder(symtab.sel_ref_cnt); 4141 sys::swapByteOrder(symtab.refs); 4142 sys::swapByteOrder(symtab.cls_def_cnt); 4143 sys::swapByteOrder(symtab.cat_def_cnt); 4144 } 4145 4146 inline void swapStruct(struct objc_class_t &objc_class) { 4147 sys::swapByteOrder(objc_class.isa); 4148 sys::swapByteOrder(objc_class.super_class); 4149 sys::swapByteOrder(objc_class.name); 4150 sys::swapByteOrder(objc_class.version); 4151 sys::swapByteOrder(objc_class.info); 4152 sys::swapByteOrder(objc_class.instance_size); 4153 sys::swapByteOrder(objc_class.ivars); 4154 sys::swapByteOrder(objc_class.methodLists); 4155 sys::swapByteOrder(objc_class.cache); 4156 sys::swapByteOrder(objc_class.protocols); 4157 } 4158 4159 inline void swapStruct(struct objc_category_t &objc_category) { 4160 sys::swapByteOrder(objc_category.category_name); 4161 sys::swapByteOrder(objc_category.class_name); 4162 sys::swapByteOrder(objc_category.instance_methods); 4163 sys::swapByteOrder(objc_category.class_methods); 4164 sys::swapByteOrder(objc_category.protocols); 4165 } 4166 4167 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) { 4168 sys::swapByteOrder(objc_ivar_list.ivar_count); 4169 } 4170 4171 inline void swapStruct(struct objc_ivar_t &objc_ivar) { 4172 sys::swapByteOrder(objc_ivar.ivar_name); 4173 sys::swapByteOrder(objc_ivar.ivar_type); 4174 sys::swapByteOrder(objc_ivar.ivar_offset); 4175 } 4176 4177 inline void swapStruct(struct objc_method_list_t &method_list) { 4178 sys::swapByteOrder(method_list.obsolete); 4179 sys::swapByteOrder(method_list.method_count); 4180 } 4181 4182 inline void swapStruct(struct objc_method_t &method) { 4183 sys::swapByteOrder(method.method_name); 4184 sys::swapByteOrder(method.method_types); 4185 sys::swapByteOrder(method.method_imp); 4186 } 4187 4188 inline void swapStruct(struct objc_protocol_list_t &protocol_list) { 4189 sys::swapByteOrder(protocol_list.next); 4190 sys::swapByteOrder(protocol_list.count); 4191 } 4192 4193 inline void swapStruct(struct objc_protocol_t &protocol) { 4194 sys::swapByteOrder(protocol.isa); 4195 sys::swapByteOrder(protocol.protocol_name); 4196 sys::swapByteOrder(protocol.protocol_list); 4197 sys::swapByteOrder(protocol.instance_methods); 4198 sys::swapByteOrder(protocol.class_methods); 4199 } 4200 4201 inline void swapStruct(struct objc_method_description_list_t &mdl) { 4202 sys::swapByteOrder(mdl.count); 4203 } 4204 4205 inline void swapStruct(struct objc_method_description_t &md) { 4206 sys::swapByteOrder(md.name); 4207 sys::swapByteOrder(md.types); 4208 } 4209 4210 } // namespace 4211 4212 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 4213 struct DisassembleInfo *info); 4214 4215 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 4216 // to an Objective-C class and returns the class name. It is also passed the 4217 // address of the pointer, so when the pointer is zero as it can be in an .o 4218 // file, that is used to look for an external relocation entry with a symbol 4219 // name. 4220 static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 4221 uint64_t ReferenceValue, 4222 struct DisassembleInfo *info) { 4223 const char *r; 4224 uint32_t offset, left; 4225 SectionRef S; 4226 4227 // The pointer_value can be 0 in an object file and have a relocation 4228 // entry for the class symbol at the ReferenceValue (the address of the 4229 // pointer). 4230 if (pointer_value == 0) { 4231 r = get_pointer_64(ReferenceValue, offset, left, S, info); 4232 if (r == nullptr || left < sizeof(uint64_t)) 4233 return nullptr; 4234 uint64_t n_value; 4235 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 4236 if (symbol_name == nullptr) 4237 return nullptr; 4238 const char *class_name = strrchr(symbol_name, '$'); 4239 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 4240 return class_name + 2; 4241 else 4242 return nullptr; 4243 } 4244 4245 // The case were the pointer_value is non-zero and points to a class defined 4246 // in this Mach-O file. 4247 r = get_pointer_64(pointer_value, offset, left, S, info); 4248 if (r == nullptr || left < sizeof(struct class64_t)) 4249 return nullptr; 4250 struct class64_t c; 4251 memcpy(&c, r, sizeof(struct class64_t)); 4252 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4253 swapStruct(c); 4254 if (c.data == 0) 4255 return nullptr; 4256 r = get_pointer_64(c.data, offset, left, S, info); 4257 if (r == nullptr || left < sizeof(struct class_ro64_t)) 4258 return nullptr; 4259 struct class_ro64_t cro; 4260 memcpy(&cro, r, sizeof(struct class_ro64_t)); 4261 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4262 swapStruct(cro); 4263 if (cro.name == 0) 4264 return nullptr; 4265 const char *name = get_pointer_64(cro.name, offset, left, S, info); 4266 return name; 4267 } 4268 4269 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 4270 // pointer to a cfstring and returns its name or nullptr. 4271 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 4272 struct DisassembleInfo *info) { 4273 const char *r, *name; 4274 uint32_t offset, left; 4275 SectionRef S; 4276 struct cfstring64_t cfs; 4277 uint64_t cfs_characters; 4278 4279 r = get_pointer_64(ReferenceValue, offset, left, S, info); 4280 if (r == nullptr || left < sizeof(struct cfstring64_t)) 4281 return nullptr; 4282 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 4283 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4284 swapStruct(cfs); 4285 if (cfs.characters == 0) { 4286 uint64_t n_value; 4287 const char *symbol_name = get_symbol_64( 4288 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 4289 if (symbol_name == nullptr) 4290 return nullptr; 4291 cfs_characters = n_value; 4292 } else 4293 cfs_characters = cfs.characters; 4294 name = get_pointer_64(cfs_characters, offset, left, S, info); 4295 4296 return name; 4297 } 4298 4299 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 4300 // of a pointer to an Objective-C selector reference when the pointer value is 4301 // zero as in a .o file and is likely to have a external relocation entry with 4302 // who's symbol's n_value is the real pointer to the selector name. If that is 4303 // the case the real pointer to the selector name is returned else 0 is 4304 // returned 4305 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 4306 struct DisassembleInfo *info) { 4307 uint32_t offset, left; 4308 SectionRef S; 4309 4310 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 4311 if (r == nullptr || left < sizeof(uint64_t)) 4312 return 0; 4313 uint64_t n_value; 4314 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 4315 if (symbol_name == nullptr) 4316 return 0; 4317 return n_value; 4318 } 4319 4320 static const SectionRef get_section(MachOObjectFile *O, const char *segname, 4321 const char *sectname) { 4322 for (const SectionRef &Section : O->sections()) { 4323 StringRef SectName; 4324 Expected<StringRef> SecNameOrErr = Section.getName(); 4325 if (SecNameOrErr) 4326 SectName = *SecNameOrErr; 4327 else 4328 consumeError(SecNameOrErr.takeError()); 4329 4330 DataRefImpl Ref = Section.getRawDataRefImpl(); 4331 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4332 if (SegName == segname && SectName == sectname) 4333 return Section; 4334 } 4335 return SectionRef(); 4336 } 4337 4338 static void 4339 walk_pointer_list_64(const char *listname, const SectionRef S, 4340 MachOObjectFile *O, struct DisassembleInfo *info, 4341 void (*func)(uint64_t, struct DisassembleInfo *info)) { 4342 if (S == SectionRef()) 4343 return; 4344 4345 StringRef SectName; 4346 Expected<StringRef> SecNameOrErr = S.getName(); 4347 if (SecNameOrErr) 4348 SectName = *SecNameOrErr; 4349 else 4350 consumeError(SecNameOrErr.takeError()); 4351 4352 DataRefImpl Ref = S.getRawDataRefImpl(); 4353 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4354 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4355 4356 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4357 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4358 4359 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) { 4360 uint32_t left = S.getSize() - i; 4361 uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t); 4362 uint64_t p = 0; 4363 memcpy(&p, Contents + i, size); 4364 if (i + sizeof(uint64_t) > S.getSize()) 4365 outs() << listname << " list pointer extends past end of (" << SegName 4366 << "," << SectName << ") section\n"; 4367 outs() << format("%016" PRIx64, S.getAddress() + i) << " "; 4368 4369 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4370 sys::swapByteOrder(p); 4371 4372 uint64_t n_value = 0; 4373 const char *name = get_symbol_64(i, S, info, n_value, p); 4374 if (name == nullptr) 4375 name = get_dyld_bind_info_symbolname(S.getAddress() + i, info); 4376 4377 if (n_value != 0) { 4378 outs() << format("0x%" PRIx64, n_value); 4379 if (p != 0) 4380 outs() << " + " << format("0x%" PRIx64, p); 4381 } else 4382 outs() << format("0x%" PRIx64, p); 4383 if (name != nullptr) 4384 outs() << " " << name; 4385 outs() << "\n"; 4386 4387 p += n_value; 4388 if (func) 4389 func(p, info); 4390 } 4391 } 4392 4393 static void 4394 walk_pointer_list_32(const char *listname, const SectionRef S, 4395 MachOObjectFile *O, struct DisassembleInfo *info, 4396 void (*func)(uint32_t, struct DisassembleInfo *info)) { 4397 if (S == SectionRef()) 4398 return; 4399 4400 StringRef SectName = unwrapOrError(S.getName(), O->getFileName()); 4401 DataRefImpl Ref = S.getRawDataRefImpl(); 4402 StringRef SegName = O->getSectionFinalSegmentName(Ref); 4403 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 4404 4405 StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName()); 4406 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 4407 4408 for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) { 4409 uint32_t left = S.getSize() - i; 4410 uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t); 4411 uint32_t p = 0; 4412 memcpy(&p, Contents + i, size); 4413 if (i + sizeof(uint32_t) > S.getSize()) 4414 outs() << listname << " list pointer extends past end of (" << SegName 4415 << "," << SectName << ") section\n"; 4416 uint32_t Address = S.getAddress() + i; 4417 outs() << format("%08" PRIx32, Address) << " "; 4418 4419 if (O->isLittleEndian() != sys::IsLittleEndianHost) 4420 sys::swapByteOrder(p); 4421 outs() << format("0x%" PRIx32, p); 4422 4423 const char *name = get_symbol_32(i, S, info, p); 4424 if (name != nullptr) 4425 outs() << " " << name; 4426 outs() << "\n"; 4427 4428 if (func) 4429 func(p, info); 4430 } 4431 } 4432 4433 static void print_layout_map(const char *layout_map, uint32_t left) { 4434 if (layout_map == nullptr) 4435 return; 4436 outs() << " layout map: "; 4437 do { 4438 outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " "; 4439 left--; 4440 layout_map++; 4441 } while (*layout_map != '\0' && left != 0); 4442 outs() << "\n"; 4443 } 4444 4445 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) { 4446 uint32_t offset, left; 4447 SectionRef S; 4448 const char *layout_map; 4449 4450 if (p == 0) 4451 return; 4452 layout_map = get_pointer_64(p, offset, left, S, info); 4453 print_layout_map(layout_map, left); 4454 } 4455 4456 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { 4457 uint32_t offset, left; 4458 SectionRef S; 4459 const char *layout_map; 4460 4461 if (p == 0) 4462 return; 4463 layout_map = get_pointer_32(p, offset, left, S, info); 4464 print_layout_map(layout_map, left); 4465 } 4466 4467 static void print_relative_method_list(uint32_t structSizeAndFlags, 4468 uint32_t structCount, uint64_t p, 4469 struct DisassembleInfo *info, 4470 const char *indent, 4471 uint32_t pointerBits) { 4472 struct method_relative_t m; 4473 const char *r, *name; 4474 uint32_t offset, xoffset, left, i; 4475 SectionRef S, xS; 4476 4477 assert(((structSizeAndFlags & ML_HAS_RELATIVE_PTRS) != 0) && 4478 "expected structSizeAndFlags to have ML_HAS_RELATIVE_PTRS flag"); 4479 4480 outs() << indent << "\t\t entsize " 4481 << (structSizeAndFlags & ML_ENTSIZE_MASK) << " (relative) \n"; 4482 outs() << indent << "\t\t count " << structCount << "\n"; 4483 4484 for (i = 0; i < structCount; i++) { 4485 r = get_pointer_64(p, offset, left, S, info); 4486 memset(&m, '\0', sizeof(struct method_relative_t)); 4487 if (left < sizeof(struct method_relative_t)) { 4488 memcpy(&m, r, left); 4489 outs() << indent << " (method_t extends past the end of the section)\n"; 4490 } else 4491 memcpy(&m, r, sizeof(struct method_relative_t)); 4492 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4493 swapStruct(m); 4494 4495 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 4496 uint64_t relNameRefVA = p + offsetof(struct method_relative_t, name); 4497 uint64_t absNameRefVA = relNameRefVA + m.name; 4498 outs() << " (" << format("0x%" PRIx32, absNameRefVA) << ")"; 4499 4500 // since this is a relative list, absNameRefVA is the address of the 4501 // __objc_selrefs entry, so a pointer, not the actual name 4502 const char *nameRefPtr = 4503 get_pointer_64(absNameRefVA, xoffset, left, xS, info); 4504 if (nameRefPtr) { 4505 uint32_t pointerSize = pointerBits / CHAR_BIT; 4506 if (left < pointerSize) 4507 outs() << indent << " (nameRefPtr extends past the end of the section)"; 4508 else { 4509 if (pointerSize == 64) { 4510 uint64_t nameOff_64 = *reinterpret_cast<const uint64_t *>(nameRefPtr); 4511 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4512 sys::swapByteOrder(nameOff_64); 4513 name = get_pointer_64(nameOff_64, xoffset, left, xS, info); 4514 } else { 4515 uint32_t nameOff_32 = *reinterpret_cast<const uint32_t *>(nameRefPtr); 4516 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4517 sys::swapByteOrder(nameOff_32); 4518 name = get_pointer_32(nameOff_32, xoffset, left, xS, info); 4519 } 4520 if (name != nullptr) 4521 outs() << format(" %.*s", left, name); 4522 } 4523 } 4524 outs() << "\n"; 4525 4526 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 4527 uint64_t relTypesVA = p + offsetof(struct method_relative_t, types); 4528 uint64_t absTypesVA = relTypesVA + m.types; 4529 outs() << " (" << format("0x%" PRIx32, absTypesVA) << ")"; 4530 name = get_pointer_32(absTypesVA, xoffset, left, xS, info); 4531 if (name != nullptr) 4532 outs() << format(" %.*s", left, name); 4533 outs() << "\n"; 4534 4535 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4536 uint64_t relImpVA = p + offsetof(struct method_relative_t, imp); 4537 uint64_t absImpVA = relImpVA + m.imp; 4538 outs() << " (" << format("0x%" PRIx32, absImpVA) << ")"; 4539 name = GuessSymbolName(absImpVA, info->AddrMap); 4540 if (name != nullptr) 4541 outs() << " " << name; 4542 outs() << "\n"; 4543 4544 p += sizeof(struct method_relative_t); 4545 offset += sizeof(struct method_relative_t); 4546 } 4547 } 4548 4549 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, 4550 const char *indent) { 4551 struct method_list64_t ml; 4552 struct method64_t m; 4553 const char *r; 4554 uint32_t offset, xoffset, left, i; 4555 SectionRef S, xS; 4556 const char *name, *sym_name; 4557 uint64_t n_value; 4558 4559 r = get_pointer_64(p, offset, left, S, info); 4560 if (r == nullptr) 4561 return; 4562 memset(&ml, '\0', sizeof(struct method_list64_t)); 4563 if (left < sizeof(struct method_list64_t)) { 4564 memcpy(&ml, r, left); 4565 outs() << " (method_list_t entends past the end of the section)\n"; 4566 } else 4567 memcpy(&ml, r, sizeof(struct method_list64_t)); 4568 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4569 swapStruct(ml); 4570 p += sizeof(struct method_list64_t); 4571 4572 if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) { 4573 print_relative_method_list(ml.entsize, ml.count, p, info, indent, 4574 /*pointerBits=*/64); 4575 return; 4576 } 4577 4578 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4579 outs() << indent << "\t\t count " << ml.count << "\n"; 4580 4581 offset += sizeof(struct method_list64_t); 4582 for (i = 0; i < ml.count; i++) { 4583 r = get_pointer_64(p, offset, left, S, info); 4584 if (r == nullptr) 4585 return; 4586 memset(&m, '\0', sizeof(struct method64_t)); 4587 if (left < sizeof(struct method64_t)) { 4588 memcpy(&m, r, left); 4589 outs() << indent << " (method_t extends past the end of the section)\n"; 4590 } else 4591 memcpy(&m, r, sizeof(struct method64_t)); 4592 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4593 swapStruct(m); 4594 4595 outs() << indent << "\t\t name "; 4596 sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S, 4597 info, n_value, m.name); 4598 if (n_value != 0) { 4599 if (info->verbose && sym_name != nullptr) 4600 outs() << sym_name; 4601 else 4602 outs() << format("0x%" PRIx64, n_value); 4603 if (m.name != 0) 4604 outs() << " + " << format("0x%" PRIx64, m.name); 4605 } else 4606 outs() << format("0x%" PRIx64, m.name); 4607 name = get_pointer_64(m.name + n_value, xoffset, left, xS, info); 4608 if (name != nullptr) 4609 outs() << format(" %.*s", left, name); 4610 outs() << "\n"; 4611 4612 outs() << indent << "\t\t types "; 4613 sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S, 4614 info, n_value, m.types); 4615 if (n_value != 0) { 4616 if (info->verbose && sym_name != nullptr) 4617 outs() << sym_name; 4618 else 4619 outs() << format("0x%" PRIx64, n_value); 4620 if (m.types != 0) 4621 outs() << " + " << format("0x%" PRIx64, m.types); 4622 } else 4623 outs() << format("0x%" PRIx64, m.types); 4624 name = get_pointer_64(m.types + n_value, xoffset, left, xS, info); 4625 if (name != nullptr) 4626 outs() << format(" %.*s", left, name); 4627 outs() << "\n"; 4628 4629 outs() << indent << "\t\t imp "; 4630 name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info, 4631 n_value, m.imp); 4632 if (info->verbose && name == nullptr) { 4633 if (n_value != 0) { 4634 outs() << format("0x%" PRIx64, n_value) << " "; 4635 if (m.imp != 0) 4636 outs() << "+ " << format("0x%" PRIx64, m.imp) << " "; 4637 } else 4638 outs() << format("0x%" PRIx64, m.imp) << " "; 4639 } 4640 if (name != nullptr) 4641 outs() << name; 4642 outs() << "\n"; 4643 4644 p += sizeof(struct method64_t); 4645 offset += sizeof(struct method64_t); 4646 } 4647 } 4648 4649 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, 4650 const char *indent) { 4651 struct method_list32_t ml; 4652 struct method32_t m; 4653 const char *r, *name; 4654 uint32_t offset, xoffset, left, i; 4655 SectionRef S, xS; 4656 4657 r = get_pointer_32(p, offset, left, S, info); 4658 if (r == nullptr) 4659 return; 4660 memset(&ml, '\0', sizeof(struct method_list32_t)); 4661 if (left < sizeof(struct method_list32_t)) { 4662 memcpy(&ml, r, left); 4663 outs() << " (method_list_t entends past the end of the section)\n"; 4664 } else 4665 memcpy(&ml, r, sizeof(struct method_list32_t)); 4666 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4667 swapStruct(ml); 4668 p += sizeof(struct method_list32_t); 4669 4670 if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) { 4671 print_relative_method_list(ml.entsize, ml.count, p, info, indent, 4672 /*pointerBits=*/32); 4673 return; 4674 } 4675 4676 outs() << indent << "\t\t entsize " << ml.entsize << "\n"; 4677 outs() << indent << "\t\t count " << ml.count << "\n"; 4678 4679 offset += sizeof(struct method_list32_t); 4680 for (i = 0; i < ml.count; i++) { 4681 r = get_pointer_32(p, offset, left, S, info); 4682 if (r == nullptr) 4683 return; 4684 memset(&m, '\0', sizeof(struct method32_t)); 4685 if (left < sizeof(struct method32_t)) { 4686 memcpy(&ml, r, left); 4687 outs() << indent << " (method_t entends past the end of the section)\n"; 4688 } else 4689 memcpy(&m, r, sizeof(struct method32_t)); 4690 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4691 swapStruct(m); 4692 4693 outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); 4694 name = get_pointer_32(m.name, xoffset, left, xS, info); 4695 if (name != nullptr) 4696 outs() << format(" %.*s", left, name); 4697 outs() << "\n"; 4698 4699 outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); 4700 name = get_pointer_32(m.types, xoffset, left, xS, info); 4701 if (name != nullptr) 4702 outs() << format(" %.*s", left, name); 4703 outs() << "\n"; 4704 4705 outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); 4706 name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info, 4707 m.imp); 4708 if (name != nullptr) 4709 outs() << " " << name; 4710 outs() << "\n"; 4711 4712 p += sizeof(struct method32_t); 4713 offset += sizeof(struct method32_t); 4714 } 4715 } 4716 4717 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) { 4718 uint32_t offset, left, xleft; 4719 SectionRef S; 4720 struct objc_method_list_t method_list; 4721 struct objc_method_t method; 4722 const char *r, *methods, *name, *SymbolName; 4723 int32_t i; 4724 4725 r = get_pointer_32(p, offset, left, S, info, true); 4726 if (r == nullptr) 4727 return true; 4728 4729 outs() << "\n"; 4730 if (left > sizeof(struct objc_method_list_t)) { 4731 memcpy(&method_list, r, sizeof(struct objc_method_list_t)); 4732 } else { 4733 outs() << "\t\t objc_method_list extends past end of the section\n"; 4734 memset(&method_list, '\0', sizeof(struct objc_method_list_t)); 4735 memcpy(&method_list, r, left); 4736 } 4737 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4738 swapStruct(method_list); 4739 4740 outs() << "\t\t obsolete " 4741 << format("0x%08" PRIx32, method_list.obsolete) << "\n"; 4742 outs() << "\t\t method_count " << method_list.method_count << "\n"; 4743 4744 methods = r + sizeof(struct objc_method_list_t); 4745 for (i = 0; i < method_list.method_count; i++) { 4746 if ((i + 1) * sizeof(struct objc_method_t) > left) { 4747 outs() << "\t\t remaining method's extend past the of the section\n"; 4748 break; 4749 } 4750 memcpy(&method, methods + i * sizeof(struct objc_method_t), 4751 sizeof(struct objc_method_t)); 4752 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4753 swapStruct(method); 4754 4755 outs() << "\t\t method_name " 4756 << format("0x%08" PRIx32, method.method_name); 4757 if (info->verbose) { 4758 name = get_pointer_32(method.method_name, offset, xleft, S, info, true); 4759 if (name != nullptr) 4760 outs() << format(" %.*s", xleft, name); 4761 else 4762 outs() << " (not in an __OBJC section)"; 4763 } 4764 outs() << "\n"; 4765 4766 outs() << "\t\t method_types " 4767 << format("0x%08" PRIx32, method.method_types); 4768 if (info->verbose) { 4769 name = get_pointer_32(method.method_types, offset, xleft, S, info, true); 4770 if (name != nullptr) 4771 outs() << format(" %.*s", xleft, name); 4772 else 4773 outs() << " (not in an __OBJC section)"; 4774 } 4775 outs() << "\n"; 4776 4777 outs() << "\t\t method_imp " 4778 << format("0x%08" PRIx32, method.method_imp) << " "; 4779 if (info->verbose) { 4780 SymbolName = GuessSymbolName(method.method_imp, info->AddrMap); 4781 if (SymbolName != nullptr) 4782 outs() << SymbolName; 4783 } 4784 outs() << "\n"; 4785 } 4786 return false; 4787 } 4788 4789 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) { 4790 struct protocol_list64_t pl; 4791 uint64_t q, n_value; 4792 struct protocol64_t pc; 4793 const char *r; 4794 uint32_t offset, xoffset, left, i; 4795 SectionRef S, xS; 4796 const char *name, *sym_name; 4797 4798 r = get_pointer_64(p, offset, left, S, info); 4799 if (r == nullptr) 4800 return; 4801 memset(&pl, '\0', sizeof(struct protocol_list64_t)); 4802 if (left < sizeof(struct protocol_list64_t)) { 4803 memcpy(&pl, r, left); 4804 outs() << " (protocol_list_t entends past the end of the section)\n"; 4805 } else 4806 memcpy(&pl, r, sizeof(struct protocol_list64_t)); 4807 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4808 swapStruct(pl); 4809 outs() << " count " << pl.count << "\n"; 4810 4811 p += sizeof(struct protocol_list64_t); 4812 offset += sizeof(struct protocol_list64_t); 4813 for (i = 0; i < pl.count; i++) { 4814 r = get_pointer_64(p, offset, left, S, info); 4815 if (r == nullptr) 4816 return; 4817 q = 0; 4818 if (left < sizeof(uint64_t)) { 4819 memcpy(&q, r, left); 4820 outs() << " (protocol_t * entends past the end of the section)\n"; 4821 } else 4822 memcpy(&q, r, sizeof(uint64_t)); 4823 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4824 sys::swapByteOrder(q); 4825 4826 outs() << "\t\t list[" << i << "] "; 4827 sym_name = get_symbol_64(offset, S, info, n_value, q); 4828 if (n_value != 0) { 4829 if (info->verbose && sym_name != nullptr) 4830 outs() << sym_name; 4831 else 4832 outs() << format("0x%" PRIx64, n_value); 4833 if (q != 0) 4834 outs() << " + " << format("0x%" PRIx64, q); 4835 } else 4836 outs() << format("0x%" PRIx64, q); 4837 outs() << " (struct protocol_t *)\n"; 4838 4839 r = get_pointer_64(q + n_value, offset, left, S, info); 4840 if (r == nullptr) 4841 return; 4842 memset(&pc, '\0', sizeof(struct protocol64_t)); 4843 if (left < sizeof(struct protocol64_t)) { 4844 memcpy(&pc, r, left); 4845 outs() << " (protocol_t entends past the end of the section)\n"; 4846 } else 4847 memcpy(&pc, r, sizeof(struct protocol64_t)); 4848 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4849 swapStruct(pc); 4850 4851 outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n"; 4852 4853 outs() << "\t\t\t name "; 4854 sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S, 4855 info, n_value, pc.name); 4856 if (n_value != 0) { 4857 if (info->verbose && sym_name != nullptr) 4858 outs() << sym_name; 4859 else 4860 outs() << format("0x%" PRIx64, n_value); 4861 if (pc.name != 0) 4862 outs() << " + " << format("0x%" PRIx64, pc.name); 4863 } else 4864 outs() << format("0x%" PRIx64, pc.name); 4865 name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info); 4866 if (name != nullptr) 4867 outs() << format(" %.*s", left, name); 4868 outs() << "\n"; 4869 4870 outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n"; 4871 4872 outs() << "\t\t instanceMethods "; 4873 sym_name = 4874 get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods), 4875 S, info, n_value, pc.instanceMethods); 4876 if (n_value != 0) { 4877 if (info->verbose && sym_name != nullptr) 4878 outs() << sym_name; 4879 else 4880 outs() << format("0x%" PRIx64, n_value); 4881 if (pc.instanceMethods != 0) 4882 outs() << " + " << format("0x%" PRIx64, pc.instanceMethods); 4883 } else 4884 outs() << format("0x%" PRIx64, pc.instanceMethods); 4885 outs() << " (struct method_list_t *)\n"; 4886 if (pc.instanceMethods + n_value != 0) 4887 print_method_list64_t(pc.instanceMethods + n_value, info, "\t"); 4888 4889 outs() << "\t\t classMethods "; 4890 sym_name = 4891 get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S, 4892 info, n_value, pc.classMethods); 4893 if (n_value != 0) { 4894 if (info->verbose && sym_name != nullptr) 4895 outs() << sym_name; 4896 else 4897 outs() << format("0x%" PRIx64, n_value); 4898 if (pc.classMethods != 0) 4899 outs() << " + " << format("0x%" PRIx64, pc.classMethods); 4900 } else 4901 outs() << format("0x%" PRIx64, pc.classMethods); 4902 outs() << " (struct method_list_t *)\n"; 4903 if (pc.classMethods + n_value != 0) 4904 print_method_list64_t(pc.classMethods + n_value, info, "\t"); 4905 4906 outs() << "\t optionalInstanceMethods " 4907 << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n"; 4908 outs() << "\t optionalClassMethods " 4909 << format("0x%" PRIx64, pc.optionalClassMethods) << "\n"; 4910 outs() << "\t instanceProperties " 4911 << format("0x%" PRIx64, pc.instanceProperties) << "\n"; 4912 4913 p += sizeof(uint64_t); 4914 offset += sizeof(uint64_t); 4915 } 4916 } 4917 4918 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) { 4919 struct protocol_list32_t pl; 4920 uint32_t q; 4921 struct protocol32_t pc; 4922 const char *r; 4923 uint32_t offset, xoffset, left, i; 4924 SectionRef S, xS; 4925 const char *name; 4926 4927 r = get_pointer_32(p, offset, left, S, info); 4928 if (r == nullptr) 4929 return; 4930 memset(&pl, '\0', sizeof(struct protocol_list32_t)); 4931 if (left < sizeof(struct protocol_list32_t)) { 4932 memcpy(&pl, r, left); 4933 outs() << " (protocol_list_t entends past the end of the section)\n"; 4934 } else 4935 memcpy(&pl, r, sizeof(struct protocol_list32_t)); 4936 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4937 swapStruct(pl); 4938 outs() << " count " << pl.count << "\n"; 4939 4940 p += sizeof(struct protocol_list32_t); 4941 offset += sizeof(struct protocol_list32_t); 4942 for (i = 0; i < pl.count; i++) { 4943 r = get_pointer_32(p, offset, left, S, info); 4944 if (r == nullptr) 4945 return; 4946 q = 0; 4947 if (left < sizeof(uint32_t)) { 4948 memcpy(&q, r, left); 4949 outs() << " (protocol_t * entends past the end of the section)\n"; 4950 } else 4951 memcpy(&q, r, sizeof(uint32_t)); 4952 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4953 sys::swapByteOrder(q); 4954 outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q) 4955 << " (struct protocol_t *)\n"; 4956 r = get_pointer_32(q, offset, left, S, info); 4957 if (r == nullptr) 4958 return; 4959 memset(&pc, '\0', sizeof(struct protocol32_t)); 4960 if (left < sizeof(struct protocol32_t)) { 4961 memcpy(&pc, r, left); 4962 outs() << " (protocol_t entends past the end of the section)\n"; 4963 } else 4964 memcpy(&pc, r, sizeof(struct protocol32_t)); 4965 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 4966 swapStruct(pc); 4967 outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n"; 4968 outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name); 4969 name = get_pointer_32(pc.name, xoffset, left, xS, info); 4970 if (name != nullptr) 4971 outs() << format(" %.*s", left, name); 4972 outs() << "\n"; 4973 outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n"; 4974 outs() << "\t\t instanceMethods " 4975 << format("0x%" PRIx32, pc.instanceMethods) 4976 << " (struct method_list_t *)\n"; 4977 if (pc.instanceMethods != 0) 4978 print_method_list32_t(pc.instanceMethods, info, "\t"); 4979 outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods) 4980 << " (struct method_list_t *)\n"; 4981 if (pc.classMethods != 0) 4982 print_method_list32_t(pc.classMethods, info, "\t"); 4983 outs() << "\t optionalInstanceMethods " 4984 << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n"; 4985 outs() << "\t optionalClassMethods " 4986 << format("0x%" PRIx32, pc.optionalClassMethods) << "\n"; 4987 outs() << "\t instanceProperties " 4988 << format("0x%" PRIx32, pc.instanceProperties) << "\n"; 4989 p += sizeof(uint32_t); 4990 offset += sizeof(uint32_t); 4991 } 4992 } 4993 4994 static void print_indent(uint32_t indent) { 4995 for (uint32_t i = 0; i < indent;) { 4996 if (indent - i >= 8) { 4997 outs() << "\t"; 4998 i += 8; 4999 } else { 5000 for (uint32_t j = i; j < indent; j++) 5001 outs() << " "; 5002 return; 5003 } 5004 } 5005 } 5006 5007 static bool print_method_description_list(uint32_t p, uint32_t indent, 5008 struct DisassembleInfo *info) { 5009 uint32_t offset, left, xleft; 5010 SectionRef S; 5011 struct objc_method_description_list_t mdl; 5012 struct objc_method_description_t md; 5013 const char *r, *list, *name; 5014 int32_t i; 5015 5016 r = get_pointer_32(p, offset, left, S, info, true); 5017 if (r == nullptr) 5018 return true; 5019 5020 outs() << "\n"; 5021 if (left > sizeof(struct objc_method_description_list_t)) { 5022 memcpy(&mdl, r, sizeof(struct objc_method_description_list_t)); 5023 } else { 5024 print_indent(indent); 5025 outs() << " objc_method_description_list extends past end of the section\n"; 5026 memset(&mdl, '\0', sizeof(struct objc_method_description_list_t)); 5027 memcpy(&mdl, r, left); 5028 } 5029 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5030 swapStruct(mdl); 5031 5032 print_indent(indent); 5033 outs() << " count " << mdl.count << "\n"; 5034 5035 list = r + sizeof(struct objc_method_description_list_t); 5036 for (i = 0; i < mdl.count; i++) { 5037 if ((i + 1) * sizeof(struct objc_method_description_t) > left) { 5038 print_indent(indent); 5039 outs() << " remaining list entries extend past the of the section\n"; 5040 break; 5041 } 5042 print_indent(indent); 5043 outs() << " list[" << i << "]\n"; 5044 memcpy(&md, list + i * sizeof(struct objc_method_description_t), 5045 sizeof(struct objc_method_description_t)); 5046 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5047 swapStruct(md); 5048 5049 print_indent(indent); 5050 outs() << " name " << format("0x%08" PRIx32, md.name); 5051 if (info->verbose) { 5052 name = get_pointer_32(md.name, offset, xleft, S, info, true); 5053 if (name != nullptr) 5054 outs() << format(" %.*s", xleft, name); 5055 else 5056 outs() << " (not in an __OBJC section)"; 5057 } 5058 outs() << "\n"; 5059 5060 print_indent(indent); 5061 outs() << " types " << format("0x%08" PRIx32, md.types); 5062 if (info->verbose) { 5063 name = get_pointer_32(md.types, offset, xleft, S, info, true); 5064 if (name != nullptr) 5065 outs() << format(" %.*s", xleft, name); 5066 else 5067 outs() << " (not in an __OBJC section)"; 5068 } 5069 outs() << "\n"; 5070 } 5071 return false; 5072 } 5073 5074 static bool print_protocol_list(uint32_t p, uint32_t indent, 5075 struct DisassembleInfo *info); 5076 5077 static bool print_protocol(uint32_t p, uint32_t indent, 5078 struct DisassembleInfo *info) { 5079 uint32_t offset, left; 5080 SectionRef S; 5081 struct objc_protocol_t protocol; 5082 const char *r, *name; 5083 5084 r = get_pointer_32(p, offset, left, S, info, true); 5085 if (r == nullptr) 5086 return true; 5087 5088 outs() << "\n"; 5089 if (left >= sizeof(struct objc_protocol_t)) { 5090 memcpy(&protocol, r, sizeof(struct objc_protocol_t)); 5091 } else { 5092 print_indent(indent); 5093 outs() << " Protocol extends past end of the section\n"; 5094 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 5095 memcpy(&protocol, r, left); 5096 } 5097 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5098 swapStruct(protocol); 5099 5100 print_indent(indent); 5101 outs() << " isa " << format("0x%08" PRIx32, protocol.isa) 5102 << "\n"; 5103 5104 print_indent(indent); 5105 outs() << " protocol_name " 5106 << format("0x%08" PRIx32, protocol.protocol_name); 5107 if (info->verbose) { 5108 name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true); 5109 if (name != nullptr) 5110 outs() << format(" %.*s", left, name); 5111 else 5112 outs() << " (not in an __OBJC section)"; 5113 } 5114 outs() << "\n"; 5115 5116 print_indent(indent); 5117 outs() << " protocol_list " 5118 << format("0x%08" PRIx32, protocol.protocol_list); 5119 if (print_protocol_list(protocol.protocol_list, indent + 4, info)) 5120 outs() << " (not in an __OBJC section)\n"; 5121 5122 print_indent(indent); 5123 outs() << " instance_methods " 5124 << format("0x%08" PRIx32, protocol.instance_methods); 5125 if (print_method_description_list(protocol.instance_methods, indent, info)) 5126 outs() << " (not in an __OBJC section)\n"; 5127 5128 print_indent(indent); 5129 outs() << " class_methods " 5130 << format("0x%08" PRIx32, protocol.class_methods); 5131 if (print_method_description_list(protocol.class_methods, indent, info)) 5132 outs() << " (not in an __OBJC section)\n"; 5133 5134 return false; 5135 } 5136 5137 static bool print_protocol_list(uint32_t p, uint32_t indent, 5138 struct DisassembleInfo *info) { 5139 uint32_t offset, left, l; 5140 SectionRef S; 5141 struct objc_protocol_list_t protocol_list; 5142 const char *r, *list; 5143 int32_t i; 5144 5145 r = get_pointer_32(p, offset, left, S, info, true); 5146 if (r == nullptr) 5147 return true; 5148 5149 outs() << "\n"; 5150 if (left > sizeof(struct objc_protocol_list_t)) { 5151 memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t)); 5152 } else { 5153 outs() << "\t\t objc_protocol_list_t extends past end of the section\n"; 5154 memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t)); 5155 memcpy(&protocol_list, r, left); 5156 } 5157 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5158 swapStruct(protocol_list); 5159 5160 print_indent(indent); 5161 outs() << " next " << format("0x%08" PRIx32, protocol_list.next) 5162 << "\n"; 5163 print_indent(indent); 5164 outs() << " count " << protocol_list.count << "\n"; 5165 5166 list = r + sizeof(struct objc_protocol_list_t); 5167 for (i = 0; i < protocol_list.count; i++) { 5168 if ((i + 1) * sizeof(uint32_t) > left) { 5169 outs() << "\t\t remaining list entries extend past the of the section\n"; 5170 break; 5171 } 5172 memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t)); 5173 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5174 sys::swapByteOrder(l); 5175 5176 print_indent(indent); 5177 outs() << " list[" << i << "] " << format("0x%08" PRIx32, l); 5178 if (print_protocol(l, indent, info)) 5179 outs() << "(not in an __OBJC section)\n"; 5180 } 5181 return false; 5182 } 5183 5184 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) { 5185 struct ivar_list64_t il; 5186 struct ivar64_t i; 5187 const char *r; 5188 uint32_t offset, xoffset, left, j; 5189 SectionRef S, xS; 5190 const char *name, *sym_name, *ivar_offset_p; 5191 uint64_t ivar_offset, n_value; 5192 5193 r = get_pointer_64(p, offset, left, S, info); 5194 if (r == nullptr) 5195 return; 5196 memset(&il, '\0', sizeof(struct ivar_list64_t)); 5197 if (left < sizeof(struct ivar_list64_t)) { 5198 memcpy(&il, r, left); 5199 outs() << " (ivar_list_t entends past the end of the section)\n"; 5200 } else 5201 memcpy(&il, r, sizeof(struct ivar_list64_t)); 5202 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5203 swapStruct(il); 5204 outs() << " entsize " << il.entsize << "\n"; 5205 outs() << " count " << il.count << "\n"; 5206 5207 p += sizeof(struct ivar_list64_t); 5208 offset += sizeof(struct ivar_list64_t); 5209 for (j = 0; j < il.count; j++) { 5210 r = get_pointer_64(p, offset, left, S, info); 5211 if (r == nullptr) 5212 return; 5213 memset(&i, '\0', sizeof(struct ivar64_t)); 5214 if (left < sizeof(struct ivar64_t)) { 5215 memcpy(&i, r, left); 5216 outs() << " (ivar_t entends past the end of the section)\n"; 5217 } else 5218 memcpy(&i, r, sizeof(struct ivar64_t)); 5219 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5220 swapStruct(i); 5221 5222 outs() << "\t\t\t offset "; 5223 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S, 5224 info, n_value, i.offset); 5225 if (n_value != 0) { 5226 if (info->verbose && sym_name != nullptr) 5227 outs() << sym_name; 5228 else 5229 outs() << format("0x%" PRIx64, n_value); 5230 if (i.offset != 0) 5231 outs() << " + " << format("0x%" PRIx64, i.offset); 5232 } else 5233 outs() << format("0x%" PRIx64, i.offset); 5234 ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info); 5235 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 5236 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 5237 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5238 sys::swapByteOrder(ivar_offset); 5239 outs() << " " << ivar_offset << "\n"; 5240 } else 5241 outs() << "\n"; 5242 5243 outs() << "\t\t\t name "; 5244 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info, 5245 n_value, i.name); 5246 if (n_value != 0) { 5247 if (info->verbose && sym_name != nullptr) 5248 outs() << sym_name; 5249 else 5250 outs() << format("0x%" PRIx64, n_value); 5251 if (i.name != 0) 5252 outs() << " + " << format("0x%" PRIx64, i.name); 5253 } else 5254 outs() << format("0x%" PRIx64, i.name); 5255 name = get_pointer_64(i.name + n_value, xoffset, left, xS, info); 5256 if (name != nullptr) 5257 outs() << format(" %.*s", left, name); 5258 outs() << "\n"; 5259 5260 outs() << "\t\t\t type "; 5261 sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info, 5262 n_value, i.name); 5263 name = get_pointer_64(i.type + n_value, xoffset, left, xS, info); 5264 if (n_value != 0) { 5265 if (info->verbose && sym_name != nullptr) 5266 outs() << sym_name; 5267 else 5268 outs() << format("0x%" PRIx64, n_value); 5269 if (i.type != 0) 5270 outs() << " + " << format("0x%" PRIx64, i.type); 5271 } else 5272 outs() << format("0x%" PRIx64, i.type); 5273 if (name != nullptr) 5274 outs() << format(" %.*s", left, name); 5275 outs() << "\n"; 5276 5277 outs() << "\t\t\talignment " << i.alignment << "\n"; 5278 outs() << "\t\t\t size " << i.size << "\n"; 5279 5280 p += sizeof(struct ivar64_t); 5281 offset += sizeof(struct ivar64_t); 5282 } 5283 } 5284 5285 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) { 5286 struct ivar_list32_t il; 5287 struct ivar32_t i; 5288 const char *r; 5289 uint32_t offset, xoffset, left, j; 5290 SectionRef S, xS; 5291 const char *name, *ivar_offset_p; 5292 uint32_t ivar_offset; 5293 5294 r = get_pointer_32(p, offset, left, S, info); 5295 if (r == nullptr) 5296 return; 5297 memset(&il, '\0', sizeof(struct ivar_list32_t)); 5298 if (left < sizeof(struct ivar_list32_t)) { 5299 memcpy(&il, r, left); 5300 outs() << " (ivar_list_t entends past the end of the section)\n"; 5301 } else 5302 memcpy(&il, r, sizeof(struct ivar_list32_t)); 5303 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5304 swapStruct(il); 5305 outs() << " entsize " << il.entsize << "\n"; 5306 outs() << " count " << il.count << "\n"; 5307 5308 p += sizeof(struct ivar_list32_t); 5309 offset += sizeof(struct ivar_list32_t); 5310 for (j = 0; j < il.count; j++) { 5311 r = get_pointer_32(p, offset, left, S, info); 5312 if (r == nullptr) 5313 return; 5314 memset(&i, '\0', sizeof(struct ivar32_t)); 5315 if (left < sizeof(struct ivar32_t)) { 5316 memcpy(&i, r, left); 5317 outs() << " (ivar_t entends past the end of the section)\n"; 5318 } else 5319 memcpy(&i, r, sizeof(struct ivar32_t)); 5320 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5321 swapStruct(i); 5322 5323 outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset); 5324 ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info); 5325 if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) { 5326 memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset)); 5327 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5328 sys::swapByteOrder(ivar_offset); 5329 outs() << " " << ivar_offset << "\n"; 5330 } else 5331 outs() << "\n"; 5332 5333 outs() << "\t\t\t name " << format("0x%" PRIx32, i.name); 5334 name = get_pointer_32(i.name, xoffset, left, xS, info); 5335 if (name != nullptr) 5336 outs() << format(" %.*s", left, name); 5337 outs() << "\n"; 5338 5339 outs() << "\t\t\t type " << format("0x%" PRIx32, i.type); 5340 name = get_pointer_32(i.type, xoffset, left, xS, info); 5341 if (name != nullptr) 5342 outs() << format(" %.*s", left, name); 5343 outs() << "\n"; 5344 5345 outs() << "\t\t\talignment " << i.alignment << "\n"; 5346 outs() << "\t\t\t size " << i.size << "\n"; 5347 5348 p += sizeof(struct ivar32_t); 5349 offset += sizeof(struct ivar32_t); 5350 } 5351 } 5352 5353 static void print_objc_property_list64(uint64_t p, 5354 struct DisassembleInfo *info) { 5355 struct objc_property_list64 opl; 5356 struct objc_property64 op; 5357 const char *r; 5358 uint32_t offset, xoffset, left, j; 5359 SectionRef S, xS; 5360 const char *name, *sym_name; 5361 uint64_t n_value; 5362 5363 r = get_pointer_64(p, offset, left, S, info); 5364 if (r == nullptr) 5365 return; 5366 memset(&opl, '\0', sizeof(struct objc_property_list64)); 5367 if (left < sizeof(struct objc_property_list64)) { 5368 memcpy(&opl, r, left); 5369 outs() << " (objc_property_list entends past the end of the section)\n"; 5370 } else 5371 memcpy(&opl, r, sizeof(struct objc_property_list64)); 5372 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5373 swapStruct(opl); 5374 outs() << " entsize " << opl.entsize << "\n"; 5375 outs() << " count " << opl.count << "\n"; 5376 5377 p += sizeof(struct objc_property_list64); 5378 offset += sizeof(struct objc_property_list64); 5379 for (j = 0; j < opl.count; j++) { 5380 r = get_pointer_64(p, offset, left, S, info); 5381 if (r == nullptr) 5382 return; 5383 memset(&op, '\0', sizeof(struct objc_property64)); 5384 if (left < sizeof(struct objc_property64)) { 5385 memcpy(&op, r, left); 5386 outs() << " (objc_property entends past the end of the section)\n"; 5387 } else 5388 memcpy(&op, r, sizeof(struct objc_property64)); 5389 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5390 swapStruct(op); 5391 5392 outs() << "\t\t\t name "; 5393 sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S, 5394 info, n_value, op.name); 5395 if (n_value != 0) { 5396 if (info->verbose && sym_name != nullptr) 5397 outs() << sym_name; 5398 else 5399 outs() << format("0x%" PRIx64, n_value); 5400 if (op.name != 0) 5401 outs() << " + " << format("0x%" PRIx64, op.name); 5402 } else 5403 outs() << format("0x%" PRIx64, op.name); 5404 name = get_pointer_64(op.name + n_value, xoffset, left, xS, info); 5405 if (name != nullptr) 5406 outs() << format(" %.*s", left, name); 5407 outs() << "\n"; 5408 5409 outs() << "\t\t\tattributes "; 5410 sym_name = 5411 get_symbol_64(offset + offsetof(struct objc_property64, attributes), S, 5412 info, n_value, op.attributes); 5413 if (n_value != 0) { 5414 if (info->verbose && sym_name != nullptr) 5415 outs() << sym_name; 5416 else 5417 outs() << format("0x%" PRIx64, n_value); 5418 if (op.attributes != 0) 5419 outs() << " + " << format("0x%" PRIx64, op.attributes); 5420 } else 5421 outs() << format("0x%" PRIx64, op.attributes); 5422 name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info); 5423 if (name != nullptr) 5424 outs() << format(" %.*s", left, name); 5425 outs() << "\n"; 5426 5427 p += sizeof(struct objc_property64); 5428 offset += sizeof(struct objc_property64); 5429 } 5430 } 5431 5432 static void print_objc_property_list32(uint32_t p, 5433 struct DisassembleInfo *info) { 5434 struct objc_property_list32 opl; 5435 struct objc_property32 op; 5436 const char *r; 5437 uint32_t offset, xoffset, left, j; 5438 SectionRef S, xS; 5439 const char *name; 5440 5441 r = get_pointer_32(p, offset, left, S, info); 5442 if (r == nullptr) 5443 return; 5444 memset(&opl, '\0', sizeof(struct objc_property_list32)); 5445 if (left < sizeof(struct objc_property_list32)) { 5446 memcpy(&opl, r, left); 5447 outs() << " (objc_property_list entends past the end of the section)\n"; 5448 } else 5449 memcpy(&opl, r, sizeof(struct objc_property_list32)); 5450 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5451 swapStruct(opl); 5452 outs() << " entsize " << opl.entsize << "\n"; 5453 outs() << " count " << opl.count << "\n"; 5454 5455 p += sizeof(struct objc_property_list32); 5456 offset += sizeof(struct objc_property_list32); 5457 for (j = 0; j < opl.count; j++) { 5458 r = get_pointer_32(p, offset, left, S, info); 5459 if (r == nullptr) 5460 return; 5461 memset(&op, '\0', sizeof(struct objc_property32)); 5462 if (left < sizeof(struct objc_property32)) { 5463 memcpy(&op, r, left); 5464 outs() << " (objc_property entends past the end of the section)\n"; 5465 } else 5466 memcpy(&op, r, sizeof(struct objc_property32)); 5467 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5468 swapStruct(op); 5469 5470 outs() << "\t\t\t name " << format("0x%" PRIx32, op.name); 5471 name = get_pointer_32(op.name, xoffset, left, xS, info); 5472 if (name != nullptr) 5473 outs() << format(" %.*s", left, name); 5474 outs() << "\n"; 5475 5476 outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes); 5477 name = get_pointer_32(op.attributes, xoffset, left, xS, info); 5478 if (name != nullptr) 5479 outs() << format(" %.*s", left, name); 5480 outs() << "\n"; 5481 5482 p += sizeof(struct objc_property32); 5483 offset += sizeof(struct objc_property32); 5484 } 5485 } 5486 5487 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, 5488 bool &is_meta_class) { 5489 struct class_ro64_t cro; 5490 const char *r; 5491 uint32_t offset, xoffset, left; 5492 SectionRef S, xS; 5493 const char *name, *sym_name; 5494 uint64_t n_value; 5495 5496 r = get_pointer_64(p, offset, left, S, info); 5497 if (r == nullptr || left < sizeof(struct class_ro64_t)) 5498 return false; 5499 memcpy(&cro, r, sizeof(struct class_ro64_t)); 5500 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5501 swapStruct(cro); 5502 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5503 if (cro.flags & RO_META) 5504 outs() << " RO_META"; 5505 if (cro.flags & RO_ROOT) 5506 outs() << " RO_ROOT"; 5507 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5508 outs() << " RO_HAS_CXX_STRUCTORS"; 5509 outs() << "\n"; 5510 outs() << " instanceStart " << cro.instanceStart << "\n"; 5511 outs() << " instanceSize " << cro.instanceSize << "\n"; 5512 outs() << " reserved " << format("0x%" PRIx32, cro.reserved) 5513 << "\n"; 5514 outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout) 5515 << "\n"; 5516 print_layout_map64(cro.ivarLayout, info); 5517 5518 outs() << " name "; 5519 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S, 5520 info, n_value, cro.name); 5521 if (n_value != 0) { 5522 if (info->verbose && sym_name != nullptr) 5523 outs() << sym_name; 5524 else 5525 outs() << format("0x%" PRIx64, n_value); 5526 if (cro.name != 0) 5527 outs() << " + " << format("0x%" PRIx64, cro.name); 5528 } else 5529 outs() << format("0x%" PRIx64, cro.name); 5530 name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info); 5531 if (name != nullptr) 5532 outs() << format(" %.*s", left, name); 5533 outs() << "\n"; 5534 5535 outs() << " baseMethods "; 5536 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods), 5537 S, info, n_value, cro.baseMethods); 5538 if (n_value != 0) { 5539 if (info->verbose && sym_name != nullptr) 5540 outs() << sym_name; 5541 else 5542 outs() << format("0x%" PRIx64, n_value); 5543 if (cro.baseMethods != 0) 5544 outs() << " + " << format("0x%" PRIx64, cro.baseMethods); 5545 } else 5546 outs() << format("0x%" PRIx64, cro.baseMethods); 5547 outs() << " (struct method_list_t *)\n"; 5548 if (cro.baseMethods + n_value != 0) 5549 print_method_list64_t(cro.baseMethods + n_value, info, ""); 5550 5551 outs() << " baseProtocols "; 5552 sym_name = 5553 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S, 5554 info, n_value, cro.baseProtocols); 5555 if (n_value != 0) { 5556 if (info->verbose && sym_name != nullptr) 5557 outs() << sym_name; 5558 else 5559 outs() << format("0x%" PRIx64, n_value); 5560 if (cro.baseProtocols != 0) 5561 outs() << " + " << format("0x%" PRIx64, cro.baseProtocols); 5562 } else 5563 outs() << format("0x%" PRIx64, cro.baseProtocols); 5564 outs() << "\n"; 5565 if (cro.baseProtocols + n_value != 0) 5566 print_protocol_list64_t(cro.baseProtocols + n_value, info); 5567 5568 outs() << " ivars "; 5569 sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S, 5570 info, n_value, cro.ivars); 5571 if (n_value != 0) { 5572 if (info->verbose && sym_name != nullptr) 5573 outs() << sym_name; 5574 else 5575 outs() << format("0x%" PRIx64, n_value); 5576 if (cro.ivars != 0) 5577 outs() << " + " << format("0x%" PRIx64, cro.ivars); 5578 } else 5579 outs() << format("0x%" PRIx64, cro.ivars); 5580 outs() << "\n"; 5581 if (cro.ivars + n_value != 0) 5582 print_ivar_list64_t(cro.ivars + n_value, info); 5583 5584 outs() << " weakIvarLayout "; 5585 sym_name = 5586 get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S, 5587 info, n_value, cro.weakIvarLayout); 5588 if (n_value != 0) { 5589 if (info->verbose && sym_name != nullptr) 5590 outs() << sym_name; 5591 else 5592 outs() << format("0x%" PRIx64, n_value); 5593 if (cro.weakIvarLayout != 0) 5594 outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout); 5595 } else 5596 outs() << format("0x%" PRIx64, cro.weakIvarLayout); 5597 outs() << "\n"; 5598 print_layout_map64(cro.weakIvarLayout + n_value, info); 5599 5600 outs() << " baseProperties "; 5601 sym_name = 5602 get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S, 5603 info, n_value, cro.baseProperties); 5604 if (n_value != 0) { 5605 if (info->verbose && sym_name != nullptr) 5606 outs() << sym_name; 5607 else 5608 outs() << format("0x%" PRIx64, n_value); 5609 if (cro.baseProperties != 0) 5610 outs() << " + " << format("0x%" PRIx64, cro.baseProperties); 5611 } else 5612 outs() << format("0x%" PRIx64, cro.baseProperties); 5613 outs() << "\n"; 5614 if (cro.baseProperties + n_value != 0) 5615 print_objc_property_list64(cro.baseProperties + n_value, info); 5616 5617 is_meta_class = (cro.flags & RO_META) != 0; 5618 return true; 5619 } 5620 5621 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info, 5622 bool &is_meta_class) { 5623 struct class_ro32_t cro; 5624 const char *r; 5625 uint32_t offset, xoffset, left; 5626 SectionRef S, xS; 5627 const char *name; 5628 5629 r = get_pointer_32(p, offset, left, S, info); 5630 if (r == nullptr) 5631 return false; 5632 memset(&cro, '\0', sizeof(struct class_ro32_t)); 5633 if (left < sizeof(struct class_ro32_t)) { 5634 memcpy(&cro, r, left); 5635 outs() << " (class_ro_t entends past the end of the section)\n"; 5636 } else 5637 memcpy(&cro, r, sizeof(struct class_ro32_t)); 5638 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5639 swapStruct(cro); 5640 outs() << " flags " << format("0x%" PRIx32, cro.flags); 5641 if (cro.flags & RO_META) 5642 outs() << " RO_META"; 5643 if (cro.flags & RO_ROOT) 5644 outs() << " RO_ROOT"; 5645 if (cro.flags & RO_HAS_CXX_STRUCTORS) 5646 outs() << " RO_HAS_CXX_STRUCTORS"; 5647 outs() << "\n"; 5648 outs() << " instanceStart " << cro.instanceStart << "\n"; 5649 outs() << " instanceSize " << cro.instanceSize << "\n"; 5650 outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout) 5651 << "\n"; 5652 print_layout_map32(cro.ivarLayout, info); 5653 5654 outs() << " name " << format("0x%" PRIx32, cro.name); 5655 name = get_pointer_32(cro.name, xoffset, left, xS, info); 5656 if (name != nullptr) 5657 outs() << format(" %.*s", left, name); 5658 outs() << "\n"; 5659 5660 outs() << " baseMethods " 5661 << format("0x%" PRIx32, cro.baseMethods) 5662 << " (struct method_list_t *)\n"; 5663 if (cro.baseMethods != 0) 5664 print_method_list32_t(cro.baseMethods, info, ""); 5665 5666 outs() << " baseProtocols " 5667 << format("0x%" PRIx32, cro.baseProtocols) << "\n"; 5668 if (cro.baseProtocols != 0) 5669 print_protocol_list32_t(cro.baseProtocols, info); 5670 outs() << " ivars " << format("0x%" PRIx32, cro.ivars) 5671 << "\n"; 5672 if (cro.ivars != 0) 5673 print_ivar_list32_t(cro.ivars, info); 5674 outs() << " weakIvarLayout " 5675 << format("0x%" PRIx32, cro.weakIvarLayout) << "\n"; 5676 print_layout_map32(cro.weakIvarLayout, info); 5677 outs() << " baseProperties " 5678 << format("0x%" PRIx32, cro.baseProperties) << "\n"; 5679 if (cro.baseProperties != 0) 5680 print_objc_property_list32(cro.baseProperties, info); 5681 is_meta_class = (cro.flags & RO_META) != 0; 5682 return true; 5683 } 5684 5685 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { 5686 struct class64_t c; 5687 const char *r; 5688 uint32_t offset, left; 5689 SectionRef S; 5690 const char *name; 5691 uint64_t isa_n_value, n_value; 5692 5693 r = get_pointer_64(p, offset, left, S, info); 5694 if (r == nullptr || left < sizeof(struct class64_t)) 5695 return; 5696 memcpy(&c, r, sizeof(struct class64_t)); 5697 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5698 swapStruct(c); 5699 5700 outs() << " isa " << format("0x%" PRIx64, c.isa); 5701 name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info, 5702 isa_n_value, c.isa); 5703 if (name != nullptr) 5704 outs() << " " << name; 5705 outs() << "\n"; 5706 5707 outs() << " superclass " << format("0x%" PRIx64, c.superclass); 5708 name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info, 5709 n_value, c.superclass); 5710 if (name != nullptr) 5711 outs() << " " << name; 5712 else { 5713 name = get_dyld_bind_info_symbolname(S.getAddress() + 5714 offset + offsetof(struct class64_t, superclass), info); 5715 if (name != nullptr) 5716 outs() << " " << name; 5717 } 5718 outs() << "\n"; 5719 5720 outs() << " cache " << format("0x%" PRIx64, c.cache); 5721 name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info, 5722 n_value, c.cache); 5723 if (name != nullptr) 5724 outs() << " " << name; 5725 outs() << "\n"; 5726 5727 outs() << " vtable " << format("0x%" PRIx64, c.vtable); 5728 name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info, 5729 n_value, c.vtable); 5730 if (name != nullptr) 5731 outs() << " " << name; 5732 outs() << "\n"; 5733 5734 name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info, 5735 n_value, c.data); 5736 outs() << " data "; 5737 if (n_value != 0) { 5738 if (info->verbose && name != nullptr) 5739 outs() << name; 5740 else 5741 outs() << format("0x%" PRIx64, n_value); 5742 if (c.data != 0) 5743 outs() << " + " << format("0x%" PRIx64, c.data); 5744 } else 5745 outs() << format("0x%" PRIx64, c.data); 5746 outs() << " (struct class_ro_t *)"; 5747 5748 // This is a Swift class if some of the low bits of the pointer are set. 5749 if ((c.data + n_value) & 0x7) 5750 outs() << " Swift class"; 5751 outs() << "\n"; 5752 bool is_meta_class; 5753 if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class)) 5754 return; 5755 5756 if (!is_meta_class && 5757 c.isa + isa_n_value != p && 5758 c.isa + isa_n_value != 0 && 5759 info->depth < 100) { 5760 info->depth++; 5761 outs() << "Meta Class\n"; 5762 print_class64_t(c.isa + isa_n_value, info); 5763 } 5764 } 5765 5766 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) { 5767 struct class32_t c; 5768 const char *r; 5769 uint32_t offset, left; 5770 SectionRef S; 5771 const char *name; 5772 5773 r = get_pointer_32(p, offset, left, S, info); 5774 if (r == nullptr) 5775 return; 5776 memset(&c, '\0', sizeof(struct class32_t)); 5777 if (left < sizeof(struct class32_t)) { 5778 memcpy(&c, r, left); 5779 outs() << " (class_t entends past the end of the section)\n"; 5780 } else 5781 memcpy(&c, r, sizeof(struct class32_t)); 5782 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5783 swapStruct(c); 5784 5785 outs() << " isa " << format("0x%" PRIx32, c.isa); 5786 name = 5787 get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa); 5788 if (name != nullptr) 5789 outs() << " " << name; 5790 outs() << "\n"; 5791 5792 outs() << " superclass " << format("0x%" PRIx32, c.superclass); 5793 name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info, 5794 c.superclass); 5795 if (name != nullptr) 5796 outs() << " " << name; 5797 outs() << "\n"; 5798 5799 outs() << " cache " << format("0x%" PRIx32, c.cache); 5800 name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info, 5801 c.cache); 5802 if (name != nullptr) 5803 outs() << " " << name; 5804 outs() << "\n"; 5805 5806 outs() << " vtable " << format("0x%" PRIx32, c.vtable); 5807 name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info, 5808 c.vtable); 5809 if (name != nullptr) 5810 outs() << " " << name; 5811 outs() << "\n"; 5812 5813 name = 5814 get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data); 5815 outs() << " data " << format("0x%" PRIx32, c.data) 5816 << " (struct class_ro_t *)"; 5817 5818 // This is a Swift class if some of the low bits of the pointer are set. 5819 if (c.data & 0x3) 5820 outs() << " Swift class"; 5821 outs() << "\n"; 5822 bool is_meta_class; 5823 if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class)) 5824 return; 5825 5826 if (!is_meta_class) { 5827 outs() << "Meta Class\n"; 5828 print_class32_t(c.isa, info); 5829 } 5830 } 5831 5832 static void print_objc_class_t(struct objc_class_t *objc_class, 5833 struct DisassembleInfo *info) { 5834 uint32_t offset, left, xleft; 5835 const char *name, *p, *ivar_list; 5836 SectionRef S; 5837 int32_t i; 5838 struct objc_ivar_list_t objc_ivar_list; 5839 struct objc_ivar_t ivar; 5840 5841 outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa); 5842 if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) { 5843 name = get_pointer_32(objc_class->isa, offset, left, S, info, true); 5844 if (name != nullptr) 5845 outs() << format(" %.*s", left, name); 5846 else 5847 outs() << " (not in an __OBJC section)"; 5848 } 5849 outs() << "\n"; 5850 5851 outs() << "\t super_class " 5852 << format("0x%08" PRIx32, objc_class->super_class); 5853 if (info->verbose) { 5854 name = get_pointer_32(objc_class->super_class, offset, left, S, info, true); 5855 if (name != nullptr) 5856 outs() << format(" %.*s", left, name); 5857 else 5858 outs() << " (not in an __OBJC section)"; 5859 } 5860 outs() << "\n"; 5861 5862 outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name); 5863 if (info->verbose) { 5864 name = get_pointer_32(objc_class->name, offset, left, S, info, true); 5865 if (name != nullptr) 5866 outs() << format(" %.*s", left, name); 5867 else 5868 outs() << " (not in an __OBJC section)"; 5869 } 5870 outs() << "\n"; 5871 5872 outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version) 5873 << "\n"; 5874 5875 outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info); 5876 if (info->verbose) { 5877 if (CLS_GETINFO(objc_class, CLS_CLASS)) 5878 outs() << " CLS_CLASS"; 5879 else if (CLS_GETINFO(objc_class, CLS_META)) 5880 outs() << " CLS_META"; 5881 } 5882 outs() << "\n"; 5883 5884 outs() << "\t instance_size " 5885 << format("0x%08" PRIx32, objc_class->instance_size) << "\n"; 5886 5887 p = get_pointer_32(objc_class->ivars, offset, left, S, info, true); 5888 outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars); 5889 if (p != nullptr) { 5890 if (left > sizeof(struct objc_ivar_list_t)) { 5891 outs() << "\n"; 5892 memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t)); 5893 } else { 5894 outs() << " (entends past the end of the section)\n"; 5895 memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t)); 5896 memcpy(&objc_ivar_list, p, left); 5897 } 5898 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5899 swapStruct(objc_ivar_list); 5900 outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n"; 5901 ivar_list = p + sizeof(struct objc_ivar_list_t); 5902 for (i = 0; i < objc_ivar_list.ivar_count; i++) { 5903 if ((i + 1) * sizeof(struct objc_ivar_t) > left) { 5904 outs() << "\t\t remaining ivar's extend past the of the section\n"; 5905 break; 5906 } 5907 memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t), 5908 sizeof(struct objc_ivar_t)); 5909 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 5910 swapStruct(ivar); 5911 5912 outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name); 5913 if (info->verbose) { 5914 name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true); 5915 if (name != nullptr) 5916 outs() << format(" %.*s", xleft, name); 5917 else 5918 outs() << " (not in an __OBJC section)"; 5919 } 5920 outs() << "\n"; 5921 5922 outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type); 5923 if (info->verbose) { 5924 name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true); 5925 if (name != nullptr) 5926 outs() << format(" %.*s", xleft, name); 5927 else 5928 outs() << " (not in an __OBJC section)"; 5929 } 5930 outs() << "\n"; 5931 5932 outs() << "\t\t ivar_offset " 5933 << format("0x%08" PRIx32, ivar.ivar_offset) << "\n"; 5934 } 5935 } else { 5936 outs() << " (not in an __OBJC section)\n"; 5937 } 5938 5939 outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists); 5940 if (print_method_list(objc_class->methodLists, info)) 5941 outs() << " (not in an __OBJC section)\n"; 5942 5943 outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache) 5944 << "\n"; 5945 5946 outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols); 5947 if (print_protocol_list(objc_class->protocols, 16, info)) 5948 outs() << " (not in an __OBJC section)\n"; 5949 } 5950 5951 static void print_objc_objc_category_t(struct objc_category_t *objc_category, 5952 struct DisassembleInfo *info) { 5953 uint32_t offset, left; 5954 const char *name; 5955 SectionRef S; 5956 5957 outs() << "\t category name " 5958 << format("0x%08" PRIx32, objc_category->category_name); 5959 if (info->verbose) { 5960 name = get_pointer_32(objc_category->category_name, offset, left, S, info, 5961 true); 5962 if (name != nullptr) 5963 outs() << format(" %.*s", left, name); 5964 else 5965 outs() << " (not in an __OBJC section)"; 5966 } 5967 outs() << "\n"; 5968 5969 outs() << "\t\t class name " 5970 << format("0x%08" PRIx32, objc_category->class_name); 5971 if (info->verbose) { 5972 name = 5973 get_pointer_32(objc_category->class_name, offset, left, S, info, true); 5974 if (name != nullptr) 5975 outs() << format(" %.*s", left, name); 5976 else 5977 outs() << " (not in an __OBJC section)"; 5978 } 5979 outs() << "\n"; 5980 5981 outs() << "\t instance methods " 5982 << format("0x%08" PRIx32, objc_category->instance_methods); 5983 if (print_method_list(objc_category->instance_methods, info)) 5984 outs() << " (not in an __OBJC section)\n"; 5985 5986 outs() << "\t class methods " 5987 << format("0x%08" PRIx32, objc_category->class_methods); 5988 if (print_method_list(objc_category->class_methods, info)) 5989 outs() << " (not in an __OBJC section)\n"; 5990 } 5991 5992 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) { 5993 struct category64_t c; 5994 const char *r; 5995 uint32_t offset, xoffset, left; 5996 SectionRef S, xS; 5997 const char *name, *sym_name; 5998 uint64_t n_value; 5999 6000 r = get_pointer_64(p, offset, left, S, info); 6001 if (r == nullptr) 6002 return; 6003 memset(&c, '\0', sizeof(struct category64_t)); 6004 if (left < sizeof(struct category64_t)) { 6005 memcpy(&c, r, left); 6006 outs() << " (category_t entends past the end of the section)\n"; 6007 } else 6008 memcpy(&c, r, sizeof(struct category64_t)); 6009 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6010 swapStruct(c); 6011 6012 outs() << " name "; 6013 sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S, 6014 info, n_value, c.name); 6015 if (n_value != 0) { 6016 if (info->verbose && sym_name != nullptr) 6017 outs() << sym_name; 6018 else 6019 outs() << format("0x%" PRIx64, n_value); 6020 if (c.name != 0) 6021 outs() << " + " << format("0x%" PRIx64, c.name); 6022 } else 6023 outs() << format("0x%" PRIx64, c.name); 6024 name = get_pointer_64(c.name + n_value, xoffset, left, xS, info); 6025 if (name != nullptr) 6026 outs() << format(" %.*s", left, name); 6027 outs() << "\n"; 6028 6029 outs() << " cls "; 6030 sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info, 6031 n_value, c.cls); 6032 if (n_value != 0) { 6033 if (info->verbose && sym_name != nullptr) 6034 outs() << sym_name; 6035 else 6036 outs() << format("0x%" PRIx64, n_value); 6037 if (c.cls != 0) 6038 outs() << " + " << format("0x%" PRIx64, c.cls); 6039 } else 6040 outs() << format("0x%" PRIx64, c.cls); 6041 outs() << "\n"; 6042 if (c.cls + n_value != 0) 6043 print_class64_t(c.cls + n_value, info); 6044 6045 outs() << " instanceMethods "; 6046 sym_name = 6047 get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S, 6048 info, n_value, c.instanceMethods); 6049 if (n_value != 0) { 6050 if (info->verbose && sym_name != nullptr) 6051 outs() << sym_name; 6052 else 6053 outs() << format("0x%" PRIx64, n_value); 6054 if (c.instanceMethods != 0) 6055 outs() << " + " << format("0x%" PRIx64, c.instanceMethods); 6056 } else 6057 outs() << format("0x%" PRIx64, c.instanceMethods); 6058 outs() << "\n"; 6059 if (c.instanceMethods + n_value != 0) 6060 print_method_list64_t(c.instanceMethods + n_value, info, ""); 6061 6062 outs() << " classMethods "; 6063 sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods), 6064 S, info, n_value, c.classMethods); 6065 if (n_value != 0) { 6066 if (info->verbose && sym_name != nullptr) 6067 outs() << sym_name; 6068 else 6069 outs() << format("0x%" PRIx64, n_value); 6070 if (c.classMethods != 0) 6071 outs() << " + " << format("0x%" PRIx64, c.classMethods); 6072 } else 6073 outs() << format("0x%" PRIx64, c.classMethods); 6074 outs() << "\n"; 6075 if (c.classMethods + n_value != 0) 6076 print_method_list64_t(c.classMethods + n_value, info, ""); 6077 6078 outs() << " protocols "; 6079 sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S, 6080 info, n_value, c.protocols); 6081 if (n_value != 0) { 6082 if (info->verbose && sym_name != nullptr) 6083 outs() << sym_name; 6084 else 6085 outs() << format("0x%" PRIx64, n_value); 6086 if (c.protocols != 0) 6087 outs() << " + " << format("0x%" PRIx64, c.protocols); 6088 } else 6089 outs() << format("0x%" PRIx64, c.protocols); 6090 outs() << "\n"; 6091 if (c.protocols + n_value != 0) 6092 print_protocol_list64_t(c.protocols + n_value, info); 6093 6094 outs() << "instanceProperties "; 6095 sym_name = 6096 get_symbol_64(offset + offsetof(struct category64_t, instanceProperties), 6097 S, info, n_value, c.instanceProperties); 6098 if (n_value != 0) { 6099 if (info->verbose && sym_name != nullptr) 6100 outs() << sym_name; 6101 else 6102 outs() << format("0x%" PRIx64, n_value); 6103 if (c.instanceProperties != 0) 6104 outs() << " + " << format("0x%" PRIx64, c.instanceProperties); 6105 } else 6106 outs() << format("0x%" PRIx64, c.instanceProperties); 6107 outs() << "\n"; 6108 if (c.instanceProperties + n_value != 0) 6109 print_objc_property_list64(c.instanceProperties + n_value, info); 6110 } 6111 6112 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) { 6113 struct category32_t c; 6114 const char *r; 6115 uint32_t offset, left; 6116 SectionRef S, xS; 6117 const char *name; 6118 6119 r = get_pointer_32(p, offset, left, S, info); 6120 if (r == nullptr) 6121 return; 6122 memset(&c, '\0', sizeof(struct category32_t)); 6123 if (left < sizeof(struct category32_t)) { 6124 memcpy(&c, r, left); 6125 outs() << " (category_t entends past the end of the section)\n"; 6126 } else 6127 memcpy(&c, r, sizeof(struct category32_t)); 6128 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6129 swapStruct(c); 6130 6131 outs() << " name " << format("0x%" PRIx32, c.name); 6132 name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info, 6133 c.name); 6134 if (name) 6135 outs() << " " << name; 6136 outs() << "\n"; 6137 6138 outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n"; 6139 if (c.cls != 0) 6140 print_class32_t(c.cls, info); 6141 outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods) 6142 << "\n"; 6143 if (c.instanceMethods != 0) 6144 print_method_list32_t(c.instanceMethods, info, ""); 6145 outs() << " classMethods " << format("0x%" PRIx32, c.classMethods) 6146 << "\n"; 6147 if (c.classMethods != 0) 6148 print_method_list32_t(c.classMethods, info, ""); 6149 outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n"; 6150 if (c.protocols != 0) 6151 print_protocol_list32_t(c.protocols, info); 6152 outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties) 6153 << "\n"; 6154 if (c.instanceProperties != 0) 6155 print_objc_property_list32(c.instanceProperties, info); 6156 } 6157 6158 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) { 6159 uint32_t i, left, offset, xoffset; 6160 uint64_t p, n_value; 6161 struct message_ref64 mr; 6162 const char *name, *sym_name; 6163 const char *r; 6164 SectionRef xS; 6165 6166 if (S == SectionRef()) 6167 return; 6168 6169 StringRef SectName; 6170 Expected<StringRef> SecNameOrErr = S.getName(); 6171 if (SecNameOrErr) 6172 SectName = *SecNameOrErr; 6173 else 6174 consumeError(SecNameOrErr.takeError()); 6175 6176 DataRefImpl Ref = S.getRawDataRefImpl(); 6177 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6178 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6179 offset = 0; 6180 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 6181 p = S.getAddress() + i; 6182 r = get_pointer_64(p, offset, left, S, info); 6183 if (r == nullptr) 6184 return; 6185 memset(&mr, '\0', sizeof(struct message_ref64)); 6186 if (left < sizeof(struct message_ref64)) { 6187 memcpy(&mr, r, left); 6188 outs() << " (message_ref entends past the end of the section)\n"; 6189 } else 6190 memcpy(&mr, r, sizeof(struct message_ref64)); 6191 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6192 swapStruct(mr); 6193 6194 outs() << " imp "; 6195 name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info, 6196 n_value, mr.imp); 6197 if (n_value != 0) { 6198 outs() << format("0x%" PRIx64, n_value) << " "; 6199 if (mr.imp != 0) 6200 outs() << "+ " << format("0x%" PRIx64, mr.imp) << " "; 6201 } else 6202 outs() << format("0x%" PRIx64, mr.imp) << " "; 6203 if (name != nullptr) 6204 outs() << " " << name; 6205 outs() << "\n"; 6206 6207 outs() << " sel "; 6208 sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S, 6209 info, n_value, mr.sel); 6210 if (n_value != 0) { 6211 if (info->verbose && sym_name != nullptr) 6212 outs() << sym_name; 6213 else 6214 outs() << format("0x%" PRIx64, n_value); 6215 if (mr.sel != 0) 6216 outs() << " + " << format("0x%" PRIx64, mr.sel); 6217 } else 6218 outs() << format("0x%" PRIx64, mr.sel); 6219 name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info); 6220 if (name != nullptr) 6221 outs() << format(" %.*s", left, name); 6222 outs() << "\n"; 6223 6224 offset += sizeof(struct message_ref64); 6225 } 6226 } 6227 6228 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) { 6229 uint32_t i, left, offset, xoffset, p; 6230 struct message_ref32 mr; 6231 const char *name, *r; 6232 SectionRef xS; 6233 6234 if (S == SectionRef()) 6235 return; 6236 6237 StringRef SectName; 6238 Expected<StringRef> SecNameOrErr = S.getName(); 6239 if (SecNameOrErr) 6240 SectName = *SecNameOrErr; 6241 else 6242 consumeError(SecNameOrErr.takeError()); 6243 6244 DataRefImpl Ref = S.getRawDataRefImpl(); 6245 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6246 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6247 offset = 0; 6248 for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) { 6249 p = S.getAddress() + i; 6250 r = get_pointer_32(p, offset, left, S, info); 6251 if (r == nullptr) 6252 return; 6253 memset(&mr, '\0', sizeof(struct message_ref32)); 6254 if (left < sizeof(struct message_ref32)) { 6255 memcpy(&mr, r, left); 6256 outs() << " (message_ref entends past the end of the section)\n"; 6257 } else 6258 memcpy(&mr, r, sizeof(struct message_ref32)); 6259 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6260 swapStruct(mr); 6261 6262 outs() << " imp " << format("0x%" PRIx32, mr.imp); 6263 name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info, 6264 mr.imp); 6265 if (name != nullptr) 6266 outs() << " " << name; 6267 outs() << "\n"; 6268 6269 outs() << " sel " << format("0x%" PRIx32, mr.sel); 6270 name = get_pointer_32(mr.sel, xoffset, left, xS, info); 6271 if (name != nullptr) 6272 outs() << " " << name; 6273 outs() << "\n"; 6274 6275 offset += sizeof(struct message_ref32); 6276 } 6277 } 6278 6279 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) { 6280 uint32_t left, offset, swift_version; 6281 uint64_t p; 6282 struct objc_image_info64 o; 6283 const char *r; 6284 6285 if (S == SectionRef()) 6286 return; 6287 6288 StringRef SectName; 6289 Expected<StringRef> SecNameOrErr = S.getName(); 6290 if (SecNameOrErr) 6291 SectName = *SecNameOrErr; 6292 else 6293 consumeError(SecNameOrErr.takeError()); 6294 6295 DataRefImpl Ref = S.getRawDataRefImpl(); 6296 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6297 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6298 p = S.getAddress(); 6299 r = get_pointer_64(p, offset, left, S, info); 6300 if (r == nullptr) 6301 return; 6302 memset(&o, '\0', sizeof(struct objc_image_info64)); 6303 if (left < sizeof(struct objc_image_info64)) { 6304 memcpy(&o, r, left); 6305 outs() << " (objc_image_info entends past the end of the section)\n"; 6306 } else 6307 memcpy(&o, r, sizeof(struct objc_image_info64)); 6308 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6309 swapStruct(o); 6310 outs() << " version " << o.version << "\n"; 6311 outs() << " flags " << format("0x%" PRIx32, o.flags); 6312 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 6313 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 6314 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 6315 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 6316 if (o.flags & OBJC_IMAGE_IS_SIMULATED) 6317 outs() << " OBJC_IMAGE_IS_SIMULATED"; 6318 if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES) 6319 outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES"; 6320 swift_version = (o.flags >> 8) & 0xff; 6321 if (swift_version != 0) { 6322 if (swift_version == 1) 6323 outs() << " Swift 1.0"; 6324 else if (swift_version == 2) 6325 outs() << " Swift 1.1"; 6326 else if(swift_version == 3) 6327 outs() << " Swift 2.0"; 6328 else if(swift_version == 4) 6329 outs() << " Swift 3.0"; 6330 else if(swift_version == 5) 6331 outs() << " Swift 4.0"; 6332 else if(swift_version == 6) 6333 outs() << " Swift 4.1/Swift 4.2"; 6334 else if(swift_version == 7) 6335 outs() << " Swift 5 or later"; 6336 else 6337 outs() << " unknown future Swift version (" << swift_version << ")"; 6338 } 6339 outs() << "\n"; 6340 } 6341 6342 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) { 6343 uint32_t left, offset, swift_version, p; 6344 struct objc_image_info32 o; 6345 const char *r; 6346 6347 if (S == SectionRef()) 6348 return; 6349 6350 StringRef SectName; 6351 Expected<StringRef> SecNameOrErr = S.getName(); 6352 if (SecNameOrErr) 6353 SectName = *SecNameOrErr; 6354 else 6355 consumeError(SecNameOrErr.takeError()); 6356 6357 DataRefImpl Ref = S.getRawDataRefImpl(); 6358 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6359 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6360 p = S.getAddress(); 6361 r = get_pointer_32(p, offset, left, S, info); 6362 if (r == nullptr) 6363 return; 6364 memset(&o, '\0', sizeof(struct objc_image_info32)); 6365 if (left < sizeof(struct objc_image_info32)) { 6366 memcpy(&o, r, left); 6367 outs() << " (objc_image_info entends past the end of the section)\n"; 6368 } else 6369 memcpy(&o, r, sizeof(struct objc_image_info32)); 6370 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6371 swapStruct(o); 6372 outs() << " version " << o.version << "\n"; 6373 outs() << " flags " << format("0x%" PRIx32, o.flags); 6374 if (o.flags & OBJC_IMAGE_IS_REPLACEMENT) 6375 outs() << " OBJC_IMAGE_IS_REPLACEMENT"; 6376 if (o.flags & OBJC_IMAGE_SUPPORTS_GC) 6377 outs() << " OBJC_IMAGE_SUPPORTS_GC"; 6378 swift_version = (o.flags >> 8) & 0xff; 6379 if (swift_version != 0) { 6380 if (swift_version == 1) 6381 outs() << " Swift 1.0"; 6382 else if (swift_version == 2) 6383 outs() << " Swift 1.1"; 6384 else if(swift_version == 3) 6385 outs() << " Swift 2.0"; 6386 else if(swift_version == 4) 6387 outs() << " Swift 3.0"; 6388 else if(swift_version == 5) 6389 outs() << " Swift 4.0"; 6390 else if(swift_version == 6) 6391 outs() << " Swift 4.1/Swift 4.2"; 6392 else if(swift_version == 7) 6393 outs() << " Swift 5 or later"; 6394 else 6395 outs() << " unknown future Swift version (" << swift_version << ")"; 6396 } 6397 outs() << "\n"; 6398 } 6399 6400 static void print_image_info(SectionRef S, struct DisassembleInfo *info) { 6401 uint32_t left, offset, p; 6402 struct imageInfo_t o; 6403 const char *r; 6404 6405 StringRef SectName; 6406 Expected<StringRef> SecNameOrErr = S.getName(); 6407 if (SecNameOrErr) 6408 SectName = *SecNameOrErr; 6409 else 6410 consumeError(SecNameOrErr.takeError()); 6411 6412 DataRefImpl Ref = S.getRawDataRefImpl(); 6413 StringRef SegName = info->O->getSectionFinalSegmentName(Ref); 6414 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 6415 p = S.getAddress(); 6416 r = get_pointer_32(p, offset, left, S, info); 6417 if (r == nullptr) 6418 return; 6419 memset(&o, '\0', sizeof(struct imageInfo_t)); 6420 if (left < sizeof(struct imageInfo_t)) { 6421 memcpy(&o, r, left); 6422 outs() << " (imageInfo entends past the end of the section)\n"; 6423 } else 6424 memcpy(&o, r, sizeof(struct imageInfo_t)); 6425 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 6426 swapStruct(o); 6427 outs() << " version " << o.version << "\n"; 6428 outs() << " flags " << format("0x%" PRIx32, o.flags); 6429 if (o.flags & 0x1) 6430 outs() << " F&C"; 6431 if (o.flags & 0x2) 6432 outs() << " GC"; 6433 if (o.flags & 0x4) 6434 outs() << " GC-only"; 6435 else 6436 outs() << " RR"; 6437 outs() << "\n"; 6438 } 6439 6440 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { 6441 SymbolAddressMap AddrMap; 6442 if (verbose) 6443 CreateSymbolAddressMap(O, &AddrMap); 6444 6445 std::vector<SectionRef> Sections; 6446 append_range(Sections, O->sections()); 6447 6448 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6449 6450 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6451 if (CL == SectionRef()) 6452 CL = get_section(O, "__DATA", "__objc_classlist"); 6453 if (CL == SectionRef()) 6454 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6455 if (CL == SectionRef()) 6456 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6457 info.S = CL; 6458 walk_pointer_list_64("class", CL, O, &info, print_class64_t); 6459 6460 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6461 if (CR == SectionRef()) 6462 CR = get_section(O, "__DATA", "__objc_classrefs"); 6463 if (CR == SectionRef()) 6464 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6465 if (CR == SectionRef()) 6466 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6467 info.S = CR; 6468 walk_pointer_list_64("class refs", CR, O, &info, nullptr); 6469 6470 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6471 if (SR == SectionRef()) 6472 SR = get_section(O, "__DATA", "__objc_superrefs"); 6473 if (SR == SectionRef()) 6474 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6475 if (SR == SectionRef()) 6476 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6477 info.S = SR; 6478 walk_pointer_list_64("super refs", SR, O, &info, nullptr); 6479 6480 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6481 if (CA == SectionRef()) 6482 CA = get_section(O, "__DATA", "__objc_catlist"); 6483 if (CA == SectionRef()) 6484 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6485 if (CA == SectionRef()) 6486 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6487 info.S = CA; 6488 walk_pointer_list_64("category", CA, O, &info, print_category64_t); 6489 6490 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6491 if (PL == SectionRef()) 6492 PL = get_section(O, "__DATA", "__objc_protolist"); 6493 if (PL == SectionRef()) 6494 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6495 if (PL == SectionRef()) 6496 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6497 info.S = PL; 6498 walk_pointer_list_64("protocol", PL, O, &info, nullptr); 6499 6500 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6501 if (MR == SectionRef()) 6502 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6503 if (MR == SectionRef()) 6504 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6505 if (MR == SectionRef()) 6506 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6507 info.S = MR; 6508 print_message_refs64(MR, &info); 6509 6510 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6511 if (II == SectionRef()) 6512 II = get_section(O, "__DATA", "__objc_imageinfo"); 6513 if (II == SectionRef()) 6514 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6515 if (II == SectionRef()) 6516 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6517 info.S = II; 6518 print_image_info64(II, &info); 6519 } 6520 6521 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6522 SymbolAddressMap AddrMap; 6523 if (verbose) 6524 CreateSymbolAddressMap(O, &AddrMap); 6525 6526 std::vector<SectionRef> Sections; 6527 append_range(Sections, O->sections()); 6528 6529 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6530 6531 SectionRef CL = get_section(O, "__OBJC2", "__class_list"); 6532 if (CL == SectionRef()) 6533 CL = get_section(O, "__DATA", "__objc_classlist"); 6534 if (CL == SectionRef()) 6535 CL = get_section(O, "__DATA_CONST", "__objc_classlist"); 6536 if (CL == SectionRef()) 6537 CL = get_section(O, "__DATA_DIRTY", "__objc_classlist"); 6538 info.S = CL; 6539 walk_pointer_list_32("class", CL, O, &info, print_class32_t); 6540 6541 SectionRef CR = get_section(O, "__OBJC2", "__class_refs"); 6542 if (CR == SectionRef()) 6543 CR = get_section(O, "__DATA", "__objc_classrefs"); 6544 if (CR == SectionRef()) 6545 CR = get_section(O, "__DATA_CONST", "__objc_classrefs"); 6546 if (CR == SectionRef()) 6547 CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs"); 6548 info.S = CR; 6549 walk_pointer_list_32("class refs", CR, O, &info, nullptr); 6550 6551 SectionRef SR = get_section(O, "__OBJC2", "__super_refs"); 6552 if (SR == SectionRef()) 6553 SR = get_section(O, "__DATA", "__objc_superrefs"); 6554 if (SR == SectionRef()) 6555 SR = get_section(O, "__DATA_CONST", "__objc_superrefs"); 6556 if (SR == SectionRef()) 6557 SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs"); 6558 info.S = SR; 6559 walk_pointer_list_32("super refs", SR, O, &info, nullptr); 6560 6561 SectionRef CA = get_section(O, "__OBJC2", "__category_list"); 6562 if (CA == SectionRef()) 6563 CA = get_section(O, "__DATA", "__objc_catlist"); 6564 if (CA == SectionRef()) 6565 CA = get_section(O, "__DATA_CONST", "__objc_catlist"); 6566 if (CA == SectionRef()) 6567 CA = get_section(O, "__DATA_DIRTY", "__objc_catlist"); 6568 info.S = CA; 6569 walk_pointer_list_32("category", CA, O, &info, print_category32_t); 6570 6571 SectionRef PL = get_section(O, "__OBJC2", "__protocol_list"); 6572 if (PL == SectionRef()) 6573 PL = get_section(O, "__DATA", "__objc_protolist"); 6574 if (PL == SectionRef()) 6575 PL = get_section(O, "__DATA_CONST", "__objc_protolist"); 6576 if (PL == SectionRef()) 6577 PL = get_section(O, "__DATA_DIRTY", "__objc_protolist"); 6578 info.S = PL; 6579 walk_pointer_list_32("protocol", PL, O, &info, nullptr); 6580 6581 SectionRef MR = get_section(O, "__OBJC2", "__message_refs"); 6582 if (MR == SectionRef()) 6583 MR = get_section(O, "__DATA", "__objc_msgrefs"); 6584 if (MR == SectionRef()) 6585 MR = get_section(O, "__DATA_CONST", "__objc_msgrefs"); 6586 if (MR == SectionRef()) 6587 MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs"); 6588 info.S = MR; 6589 print_message_refs32(MR, &info); 6590 6591 SectionRef II = get_section(O, "__OBJC2", "__image_info"); 6592 if (II == SectionRef()) 6593 II = get_section(O, "__DATA", "__objc_imageinfo"); 6594 if (II == SectionRef()) 6595 II = get_section(O, "__DATA_CONST", "__objc_imageinfo"); 6596 if (II == SectionRef()) 6597 II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo"); 6598 info.S = II; 6599 print_image_info32(II, &info); 6600 } 6601 6602 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) { 6603 uint32_t i, j, p, offset, xoffset, left, defs_left, def; 6604 const char *r, *name, *defs; 6605 struct objc_module_t module; 6606 SectionRef S, xS; 6607 struct objc_symtab_t symtab; 6608 struct objc_class_t objc_class; 6609 struct objc_category_t objc_category; 6610 6611 outs() << "Objective-C segment\n"; 6612 S = get_section(O, "__OBJC", "__module_info"); 6613 if (S == SectionRef()) 6614 return false; 6615 6616 SymbolAddressMap AddrMap; 6617 if (verbose) 6618 CreateSymbolAddressMap(O, &AddrMap); 6619 6620 std::vector<SectionRef> Sections; 6621 append_range(Sections, O->sections()); 6622 6623 struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); 6624 6625 for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) { 6626 p = S.getAddress() + i; 6627 r = get_pointer_32(p, offset, left, S, &info, true); 6628 if (r == nullptr) 6629 return true; 6630 memset(&module, '\0', sizeof(struct objc_module_t)); 6631 if (left < sizeof(struct objc_module_t)) { 6632 memcpy(&module, r, left); 6633 outs() << " (module extends past end of __module_info section)\n"; 6634 } else 6635 memcpy(&module, r, sizeof(struct objc_module_t)); 6636 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6637 swapStruct(module); 6638 6639 outs() << "Module " << format("0x%" PRIx32, p) << "\n"; 6640 outs() << " version " << module.version << "\n"; 6641 outs() << " size " << module.size << "\n"; 6642 outs() << " name "; 6643 name = get_pointer_32(module.name, xoffset, left, xS, &info, true); 6644 if (name != nullptr) 6645 outs() << format("%.*s", left, name); 6646 else 6647 outs() << format("0x%08" PRIx32, module.name) 6648 << "(not in an __OBJC section)"; 6649 outs() << "\n"; 6650 6651 r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true); 6652 if (module.symtab == 0 || r == nullptr) { 6653 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) 6654 << " (not in an __OBJC section)\n"; 6655 continue; 6656 } 6657 outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n"; 6658 memset(&symtab, '\0', sizeof(struct objc_symtab_t)); 6659 defs_left = 0; 6660 defs = nullptr; 6661 if (left < sizeof(struct objc_symtab_t)) { 6662 memcpy(&symtab, r, left); 6663 outs() << "\tsymtab extends past end of an __OBJC section)\n"; 6664 } else { 6665 memcpy(&symtab, r, sizeof(struct objc_symtab_t)); 6666 if (left > sizeof(struct objc_symtab_t)) { 6667 defs_left = left - sizeof(struct objc_symtab_t); 6668 defs = r + sizeof(struct objc_symtab_t); 6669 } 6670 } 6671 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6672 swapStruct(symtab); 6673 6674 outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n"; 6675 r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true); 6676 outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs); 6677 if (r == nullptr) 6678 outs() << " (not in an __OBJC section)"; 6679 outs() << "\n"; 6680 outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n"; 6681 outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n"; 6682 if (symtab.cls_def_cnt > 0) 6683 outs() << "\tClass Definitions\n"; 6684 for (j = 0; j < symtab.cls_def_cnt; j++) { 6685 if ((j + 1) * sizeof(uint32_t) > defs_left) { 6686 outs() << "\t(remaining class defs entries entends past the end of the " 6687 << "section)\n"; 6688 break; 6689 } 6690 memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t)); 6691 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6692 sys::swapByteOrder(def); 6693 6694 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6695 outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def); 6696 if (r != nullptr) { 6697 if (left > sizeof(struct objc_class_t)) { 6698 outs() << "\n"; 6699 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6700 } else { 6701 outs() << " (entends past the end of the section)\n"; 6702 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6703 memcpy(&objc_class, r, left); 6704 } 6705 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6706 swapStruct(objc_class); 6707 print_objc_class_t(&objc_class, &info); 6708 } else { 6709 outs() << "(not in an __OBJC section)\n"; 6710 } 6711 6712 if (CLS_GETINFO(&objc_class, CLS_CLASS)) { 6713 outs() << "\tMeta Class"; 6714 r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true); 6715 if (r != nullptr) { 6716 if (left > sizeof(struct objc_class_t)) { 6717 outs() << "\n"; 6718 memcpy(&objc_class, r, sizeof(struct objc_class_t)); 6719 } else { 6720 outs() << " (entends past the end of the section)\n"; 6721 memset(&objc_class, '\0', sizeof(struct objc_class_t)); 6722 memcpy(&objc_class, r, left); 6723 } 6724 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6725 swapStruct(objc_class); 6726 print_objc_class_t(&objc_class, &info); 6727 } else { 6728 outs() << "(not in an __OBJC section)\n"; 6729 } 6730 } 6731 } 6732 if (symtab.cat_def_cnt > 0) 6733 outs() << "\tCategory Definitions\n"; 6734 for (j = 0; j < symtab.cat_def_cnt; j++) { 6735 if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) { 6736 outs() << "\t(remaining category defs entries entends past the end of " 6737 << "the section)\n"; 6738 break; 6739 } 6740 memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t), 6741 sizeof(uint32_t)); 6742 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6743 sys::swapByteOrder(def); 6744 6745 r = get_pointer_32(def, xoffset, left, xS, &info, true); 6746 outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] " 6747 << format("0x%08" PRIx32, def); 6748 if (r != nullptr) { 6749 if (left > sizeof(struct objc_category_t)) { 6750 outs() << "\n"; 6751 memcpy(&objc_category, r, sizeof(struct objc_category_t)); 6752 } else { 6753 outs() << " (entends past the end of the section)\n"; 6754 memset(&objc_category, '\0', sizeof(struct objc_category_t)); 6755 memcpy(&objc_category, r, left); 6756 } 6757 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6758 swapStruct(objc_category); 6759 print_objc_objc_category_t(&objc_category, &info); 6760 } else { 6761 outs() << "(not in an __OBJC section)\n"; 6762 } 6763 } 6764 } 6765 const SectionRef II = get_section(O, "__OBJC", "__image_info"); 6766 if (II != SectionRef()) 6767 print_image_info(II, &info); 6768 6769 return true; 6770 } 6771 6772 static void DumpProtocolSection(MachOObjectFile *O, const char *sect, 6773 uint32_t size, uint32_t addr) { 6774 SymbolAddressMap AddrMap; 6775 CreateSymbolAddressMap(O, &AddrMap); 6776 6777 std::vector<SectionRef> Sections; 6778 append_range(Sections, O->sections()); 6779 6780 struct DisassembleInfo info(O, &AddrMap, &Sections, true); 6781 6782 const char *p; 6783 struct objc_protocol_t protocol; 6784 uint32_t left, paddr; 6785 for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) { 6786 memset(&protocol, '\0', sizeof(struct objc_protocol_t)); 6787 left = size - (p - sect); 6788 if (left < sizeof(struct objc_protocol_t)) { 6789 outs() << "Protocol extends past end of __protocol section\n"; 6790 memcpy(&protocol, p, left); 6791 } else 6792 memcpy(&protocol, p, sizeof(struct objc_protocol_t)); 6793 if (O->isLittleEndian() != sys::IsLittleEndianHost) 6794 swapStruct(protocol); 6795 paddr = addr + (p - sect); 6796 outs() << "Protocol " << format("0x%" PRIx32, paddr); 6797 if (print_protocol(paddr, 0, &info)) 6798 outs() << "(not in an __OBJC section)\n"; 6799 } 6800 } 6801 6802 static void printObjcMetaData(MachOObjectFile *O, bool verbose) { 6803 if (O->is64Bit()) 6804 printObjc2_64bit_MetaData(O, verbose); 6805 else { 6806 MachO::mach_header H; 6807 H = O->getHeader(); 6808 if (H.cputype == MachO::CPU_TYPE_ARM) 6809 printObjc2_32bit_MetaData(O, verbose); 6810 else { 6811 // This is the 32-bit non-arm cputype case. Which is normally 6812 // the first Objective-C ABI. But it may be the case of a 6813 // binary for the iOS simulator which is the second Objective-C 6814 // ABI. In that case printObjc1_32bit_MetaData() will determine that 6815 // and return false. 6816 if (!printObjc1_32bit_MetaData(O, verbose)) 6817 printObjc2_32bit_MetaData(O, verbose); 6818 } 6819 } 6820 } 6821 6822 // GuessLiteralPointer returns a string which for the item in the Mach-O file 6823 // for the address passed in as ReferenceValue for printing as a comment with 6824 // the instruction and also returns the corresponding type of that item 6825 // indirectly through ReferenceType. 6826 // 6827 // If ReferenceValue is an address of literal cstring then a pointer to the 6828 // cstring is returned and ReferenceType is set to 6829 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 6830 // 6831 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 6832 // Class ref that name is returned and the ReferenceType is set accordingly. 6833 // 6834 // Lastly, literals which are Symbol address in a literal pool are looked for 6835 // and if found the symbol name is returned and ReferenceType is set to 6836 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 6837 // 6838 // If there is no item in the Mach-O file for the address passed in as 6839 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 6840 static const char *GuessLiteralPointer(uint64_t ReferenceValue, 6841 uint64_t ReferencePC, 6842 uint64_t *ReferenceType, 6843 struct DisassembleInfo *info) { 6844 // First see if there is an external relocation entry at the ReferencePC. 6845 if (info->O->getHeader().filetype == MachO::MH_OBJECT) { 6846 uint64_t sect_addr = info->S.getAddress(); 6847 uint64_t sect_offset = ReferencePC - sect_addr; 6848 bool reloc_found = false; 6849 DataRefImpl Rel; 6850 MachO::any_relocation_info RE; 6851 bool isExtern = false; 6852 SymbolRef Symbol; 6853 for (const RelocationRef &Reloc : info->S.relocations()) { 6854 uint64_t RelocOffset = Reloc.getOffset(); 6855 if (RelocOffset == sect_offset) { 6856 Rel = Reloc.getRawDataRefImpl(); 6857 RE = info->O->getRelocation(Rel); 6858 if (info->O->isRelocationScattered(RE)) 6859 continue; 6860 isExtern = info->O->getPlainRelocationExternal(RE); 6861 if (isExtern) { 6862 symbol_iterator RelocSym = Reloc.getSymbol(); 6863 Symbol = *RelocSym; 6864 } 6865 reloc_found = true; 6866 break; 6867 } 6868 } 6869 // If there is an external relocation entry for a symbol in a section 6870 // then used that symbol's value for the value of the reference. 6871 if (reloc_found && isExtern) { 6872 if (info->O->getAnyRelocationPCRel(RE)) { 6873 unsigned Type = info->O->getAnyRelocationType(RE); 6874 if (Type == MachO::X86_64_RELOC_SIGNED) { 6875 ReferenceValue = cantFail(Symbol.getValue()); 6876 } 6877 } 6878 } 6879 } 6880 6881 // Look for literals such as Objective-C CFStrings refs, Selector refs, 6882 // Message refs and Class refs. 6883 bool classref, selref, msgref, cfstring; 6884 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 6885 selref, msgref, cfstring); 6886 if (classref && pointer_value == 0) { 6887 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 6888 // And the pointer_value in that section is typically zero as it will be 6889 // set by dyld as part of the "bind information". 6890 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 6891 if (name != nullptr) { 6892 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6893 const char *class_name = strrchr(name, '$'); 6894 if (class_name != nullptr && class_name[1] == '_' && 6895 class_name[2] != '\0') { 6896 info->class_name = class_name + 2; 6897 return name; 6898 } 6899 } 6900 } 6901 6902 if (classref) { 6903 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 6904 const char *name = 6905 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 6906 if (name != nullptr) 6907 info->class_name = name; 6908 else 6909 name = "bad class ref"; 6910 return name; 6911 } 6912 6913 if (cfstring) { 6914 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 6915 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 6916 return name; 6917 } 6918 6919 if (selref && pointer_value == 0) 6920 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 6921 6922 if (pointer_value != 0) 6923 ReferenceValue = pointer_value; 6924 6925 const char *name = GuessCstringPointer(ReferenceValue, info); 6926 if (name) { 6927 if (pointer_value != 0 && selref) { 6928 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 6929 info->selector_name = name; 6930 } else if (pointer_value != 0 && msgref) { 6931 info->class_name = nullptr; 6932 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 6933 info->selector_name = name; 6934 } else 6935 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 6936 return name; 6937 } 6938 6939 // Lastly look for an indirect symbol with this ReferenceValue which is in 6940 // a literal pool. If found return that symbol name. 6941 name = GuessIndirectSymbol(ReferenceValue, info); 6942 if (name) { 6943 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 6944 return name; 6945 } 6946 6947 return nullptr; 6948 } 6949 6950 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 6951 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 6952 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 6953 // is created and returns the symbol name that matches the ReferenceValue or 6954 // nullptr if none. The ReferenceType is passed in for the IN type of 6955 // reference the instruction is making from the values in defined in the header 6956 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 6957 // Out type and the ReferenceName will also be set which is added as a comment 6958 // to the disassembled instruction. 6959 // 6960 // If the symbol name is a C++ mangled name then the demangled name is 6961 // returned through ReferenceName and ReferenceType is set to 6962 // LLVMDisassembler_ReferenceType_DeMangled_Name . 6963 // 6964 // When this is called to get a symbol name for a branch target then the 6965 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 6966 // SymbolValue will be looked for in the indirect symbol table to determine if 6967 // it is an address for a symbol stub. If so then the symbol name for that 6968 // stub is returned indirectly through ReferenceName and then ReferenceType is 6969 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 6970 // 6971 // When this is called with an value loaded via a PC relative load then 6972 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 6973 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 6974 // or an Objective-C meta data reference. If so the output ReferenceType is 6975 // set to correspond to that as well as setting the ReferenceName. 6976 static const char *SymbolizerSymbolLookUp(void *DisInfo, 6977 uint64_t ReferenceValue, 6978 uint64_t *ReferenceType, 6979 uint64_t ReferencePC, 6980 const char **ReferenceName) { 6981 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 6982 // If no verbose symbolic information is wanted then just return nullptr. 6983 if (!info->verbose) { 6984 *ReferenceName = nullptr; 6985 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 6986 return nullptr; 6987 } 6988 6989 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 6990 6991 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 6992 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 6993 if (*ReferenceName != nullptr) { 6994 method_reference(info, ReferenceType, ReferenceName); 6995 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 6996 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 6997 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 6998 if (info->demangled_name != nullptr) 6999 free(info->demangled_name); 7000 info->demangled_name = itaniumDemangle(SymbolName + 1); 7001 if (info->demangled_name != nullptr) { 7002 *ReferenceName = info->demangled_name; 7003 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 7004 } else 7005 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7006 } else 7007 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7008 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 7009 *ReferenceName = 7010 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7011 if (*ReferenceName) 7012 method_reference(info, ReferenceType, ReferenceName); 7013 else 7014 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7015 // If this is arm64 and the reference is an adrp instruction save the 7016 // instruction, passed in ReferenceValue and the address of the instruction 7017 // for use later if we see and add immediate instruction. 7018 } else if (info->O->getArch() == Triple::aarch64 && 7019 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 7020 info->adrp_inst = ReferenceValue; 7021 info->adrp_addr = ReferencePC; 7022 SymbolName = nullptr; 7023 *ReferenceName = nullptr; 7024 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7025 // If this is arm64 and reference is an add immediate instruction and we 7026 // have 7027 // seen an adrp instruction just before it and the adrp's Xd register 7028 // matches 7029 // this add's Xn register reconstruct the value being referenced and look to 7030 // see if it is a literal pointer. Note the add immediate instruction is 7031 // passed in ReferenceValue. 7032 } else if (info->O->getArch() == Triple::aarch64 && 7033 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 7034 ReferencePC - 4 == info->adrp_addr && 7035 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7036 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7037 uint32_t addxri_inst; 7038 uint64_t adrp_imm, addxri_imm; 7039 7040 adrp_imm = 7041 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7042 if (info->adrp_inst & 0x0200000) 7043 adrp_imm |= 0xfffffffffc000000LL; 7044 7045 addxri_inst = ReferenceValue; 7046 addxri_imm = (addxri_inst >> 10) & 0xfff; 7047 if (((addxri_inst >> 22) & 0x3) == 1) 7048 addxri_imm <<= 12; 7049 7050 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7051 (adrp_imm << 12) + addxri_imm; 7052 7053 *ReferenceName = 7054 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7055 if (*ReferenceName == nullptr) 7056 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7057 // If this is arm64 and the reference is a load register instruction and we 7058 // have seen an adrp instruction just before it and the adrp's Xd register 7059 // matches this add's Xn register reconstruct the value being referenced and 7060 // look to see if it is a literal pointer. Note the load register 7061 // instruction is passed in ReferenceValue. 7062 } else if (info->O->getArch() == Triple::aarch64 && 7063 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 7064 ReferencePC - 4 == info->adrp_addr && 7065 (info->adrp_inst & 0x9f000000) == 0x90000000 && 7066 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 7067 uint32_t ldrxui_inst; 7068 uint64_t adrp_imm, ldrxui_imm; 7069 7070 adrp_imm = 7071 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 7072 if (info->adrp_inst & 0x0200000) 7073 adrp_imm |= 0xfffffffffc000000LL; 7074 7075 ldrxui_inst = ReferenceValue; 7076 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 7077 7078 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 7079 (adrp_imm << 12) + (ldrxui_imm << 3); 7080 7081 *ReferenceName = 7082 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7083 if (*ReferenceName == nullptr) 7084 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7085 } 7086 // If this arm64 and is an load register (PC-relative) instruction the 7087 // ReferenceValue is the PC plus the immediate value. 7088 else if (info->O->getArch() == Triple::aarch64 && 7089 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 7090 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 7091 *ReferenceName = 7092 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 7093 if (*ReferenceName == nullptr) 7094 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7095 } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 7096 if (info->demangled_name != nullptr) 7097 free(info->demangled_name); 7098 info->demangled_name = itaniumDemangle(SymbolName + 1); 7099 if (info->demangled_name != nullptr) { 7100 *ReferenceName = info->demangled_name; 7101 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 7102 } 7103 } 7104 else { 7105 *ReferenceName = nullptr; 7106 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 7107 } 7108 7109 return SymbolName; 7110 } 7111 7112 /// Emits the comments that are stored in the CommentStream. 7113 /// Each comment in the CommentStream must end with a newline. 7114 static void emitComments(raw_svector_ostream &CommentStream, 7115 SmallString<128> &CommentsToEmit, 7116 formatted_raw_ostream &FormattedOS, 7117 const MCAsmInfo &MAI) { 7118 // Flush the stream before taking its content. 7119 StringRef Comments = CommentsToEmit.str(); 7120 // Get the default information for printing a comment. 7121 StringRef CommentBegin = MAI.getCommentString(); 7122 unsigned CommentColumn = MAI.getCommentColumn(); 7123 ListSeparator LS("\n"); 7124 while (!Comments.empty()) { 7125 FormattedOS << LS; 7126 // Emit a line of comments. 7127 FormattedOS.PadToColumn(CommentColumn); 7128 size_t Position = Comments.find('\n'); 7129 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 7130 // Move after the newline character. 7131 Comments = Comments.substr(Position + 1); 7132 } 7133 FormattedOS.flush(); 7134 7135 // Tell the comment stream that the vector changed underneath it. 7136 CommentsToEmit.clear(); 7137 } 7138 7139 const MachOObjectFile * 7140 objdump::getMachODSymObject(const MachOObjectFile *MachOOF, StringRef Filename, 7141 std::unique_ptr<Binary> &DSYMBinary, 7142 std::unique_ptr<MemoryBuffer> &DSYMBuf) { 7143 const MachOObjectFile *DbgObj = MachOOF; 7144 std::string DSYMPath; 7145 7146 // Auto-detect w/o --dsym. 7147 if (DSYMFile.empty()) { 7148 sys::fs::file_status DSYMStatus; 7149 Twine FilenameDSYM = Filename + ".dSYM"; 7150 if (!status(FilenameDSYM, DSYMStatus)) { 7151 if (sys::fs::is_directory(DSYMStatus)) { 7152 SmallString<1024> Path; 7153 FilenameDSYM.toVector(Path); 7154 sys::path::append(Path, "Contents", "Resources", "DWARF", 7155 sys::path::filename(Filename)); 7156 DSYMPath = std::string(Path); 7157 } else if (sys::fs::is_regular_file(DSYMStatus)) { 7158 DSYMPath = FilenameDSYM.str(); 7159 } 7160 } 7161 } 7162 7163 if (DSYMPath.empty() && !DSYMFile.empty()) { 7164 // If DSYMPath is a .dSYM directory, append the Mach-O file. 7165 if (sys::fs::is_directory(DSYMFile) && 7166 sys::path::extension(DSYMFile) == ".dSYM") { 7167 SmallString<128> ShortName(sys::path::filename(DSYMFile)); 7168 sys::path::replace_extension(ShortName, ""); 7169 SmallString<1024> FullPath(DSYMFile); 7170 sys::path::append(FullPath, "Contents", "Resources", "DWARF", ShortName); 7171 DSYMPath = FullPath.str(); 7172 } else { 7173 DSYMPath = DSYMFile; 7174 } 7175 } 7176 7177 if (!DSYMPath.empty()) { 7178 // Load the file. 7179 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 7180 MemoryBuffer::getFileOrSTDIN(DSYMPath); 7181 if (std::error_code EC = BufOrErr.getError()) { 7182 reportError(errorCodeToError(EC), DSYMPath); 7183 return nullptr; 7184 } 7185 7186 // We need to keep the file alive, because we're replacing DbgObj with it. 7187 DSYMBuf = std::move(BufOrErr.get()); 7188 7189 Expected<std::unique_ptr<Binary>> BinaryOrErr = 7190 createBinary(DSYMBuf->getMemBufferRef()); 7191 if (!BinaryOrErr) { 7192 reportError(BinaryOrErr.takeError(), DSYMPath); 7193 return nullptr; 7194 } 7195 7196 // We need to keep the Binary alive with the buffer 7197 DSYMBinary = std::move(BinaryOrErr.get()); 7198 if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) { 7199 // this is a Mach-O object file, use it 7200 if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) { 7201 DbgObj = MachDSYM; 7202 } else { 7203 WithColor::error(errs(), "llvm-objdump") 7204 << DSYMPath << " is not a Mach-O file type.\n"; 7205 return nullptr; 7206 } 7207 } else if (auto *UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())) { 7208 // this is a Universal Binary, find a Mach-O for this architecture 7209 uint32_t CPUType, CPUSubType; 7210 const char *ArchFlag; 7211 if (MachOOF->is64Bit()) { 7212 const MachO::mach_header_64 H_64 = MachOOF->getHeader64(); 7213 CPUType = H_64.cputype; 7214 CPUSubType = H_64.cpusubtype; 7215 } else { 7216 const MachO::mach_header H = MachOOF->getHeader(); 7217 CPUType = H.cputype; 7218 CPUSubType = H.cpusubtype; 7219 } 7220 Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr, 7221 &ArchFlag); 7222 Expected<std::unique_ptr<MachOObjectFile>> MachDSYM = 7223 UB->getMachOObjectForArch(ArchFlag); 7224 if (!MachDSYM) { 7225 reportError(MachDSYM.takeError(), DSYMPath); 7226 return nullptr; 7227 } 7228 7229 // We need to keep the Binary alive with the buffer 7230 DbgObj = &*MachDSYM.get(); 7231 DSYMBinary = std::move(*MachDSYM); 7232 } else { 7233 WithColor::error(errs(), "llvm-objdump") 7234 << DSYMPath << " is not a Mach-O or Universal file type.\n"; 7235 return nullptr; 7236 } 7237 } 7238 return DbgObj; 7239 } 7240 7241 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 7242 StringRef DisSegName, StringRef DisSectName) { 7243 const char *McpuDefault = nullptr; 7244 const Target *ThumbTarget = nullptr; 7245 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 7246 if (!TheTarget) { 7247 // GetTarget prints out stuff. 7248 return; 7249 } 7250 std::string MachOMCPU; 7251 if (MCPU.empty() && McpuDefault) 7252 MachOMCPU = McpuDefault; 7253 else 7254 MachOMCPU = MCPU; 7255 7256 #define CHECK_TARGET_INFO_CREATION(NAME) \ 7257 do { \ 7258 if (!NAME) { \ 7259 WithColor::error(errs(), "llvm-objdump") \ 7260 << "couldn't initialize disassembler for target " << TripleName \ 7261 << '\n'; \ 7262 return; \ 7263 } \ 7264 } while (false) 7265 #define CHECK_THUMB_TARGET_INFO_CREATION(NAME) \ 7266 do { \ 7267 if (!NAME) { \ 7268 WithColor::error(errs(), "llvm-objdump") \ 7269 << "couldn't initialize disassembler for target " << ThumbTripleName \ 7270 << '\n'; \ 7271 return; \ 7272 } \ 7273 } while (false) 7274 7275 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 7276 CHECK_TARGET_INFO_CREATION(InstrInfo); 7277 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 7278 if (ThumbTarget) { 7279 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 7280 CHECK_THUMB_TARGET_INFO_CREATION(ThumbInstrInfo); 7281 } 7282 7283 // Package up features to be passed to target/subtarget 7284 std::string FeaturesStr; 7285 if (!MAttrs.empty()) { 7286 SubtargetFeatures Features; 7287 for (unsigned i = 0; i != MAttrs.size(); ++i) 7288 Features.AddFeature(MAttrs[i]); 7289 FeaturesStr = Features.getString(); 7290 } 7291 7292 MCTargetOptions MCOptions; 7293 // Set up disassembler. 7294 std::unique_ptr<const MCRegisterInfo> MRI( 7295 TheTarget->createMCRegInfo(TripleName)); 7296 CHECK_TARGET_INFO_CREATION(MRI); 7297 std::unique_ptr<const MCAsmInfo> AsmInfo( 7298 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 7299 CHECK_TARGET_INFO_CREATION(AsmInfo); 7300 std::unique_ptr<const MCSubtargetInfo> STI( 7301 TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr)); 7302 CHECK_TARGET_INFO_CREATION(STI); 7303 MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get()); 7304 std::unique_ptr<MCDisassembler> DisAsm( 7305 TheTarget->createMCDisassembler(*STI, Ctx)); 7306 CHECK_TARGET_INFO_CREATION(DisAsm); 7307 std::unique_ptr<MCSymbolizer> Symbolizer; 7308 struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false); 7309 std::unique_ptr<MCRelocationInfo> RelInfo( 7310 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 7311 if (RelInfo) { 7312 Symbolizer.reset(TheTarget->createMCSymbolizer( 7313 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7314 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 7315 DisAsm->setSymbolizer(std::move(Symbolizer)); 7316 } 7317 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 7318 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 7319 Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI)); 7320 CHECK_TARGET_INFO_CREATION(IP); 7321 // Set the display preference for hex vs. decimal immediates. 7322 IP->setPrintImmHex(PrintImmHex); 7323 // Comment stream and backing vector. 7324 SmallString<128> CommentsToEmit; 7325 raw_svector_ostream CommentStream(CommentsToEmit); 7326 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 7327 // if it is done then arm64 comments for string literals don't get printed 7328 // and some constant get printed instead and not setting it causes intel 7329 // (32-bit and 64-bit) comments printed with different spacing before the 7330 // comment causing different diffs with the 'C' disassembler library API. 7331 // IP->setCommentStream(CommentStream); 7332 7333 for (StringRef Opt : DisassemblerOptions) 7334 if (!IP->applyTargetSpecificCLOption(Opt)) 7335 reportError(Filename, "unrecognized disassembler option: " + Opt); 7336 7337 // Set up separate thumb disassembler if needed. 7338 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 7339 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 7340 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 7341 std::unique_ptr<MCDisassembler> ThumbDisAsm; 7342 std::unique_ptr<MCInstPrinter> ThumbIP; 7343 std::unique_ptr<MCContext> ThumbCtx; 7344 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 7345 struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false); 7346 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 7347 if (ThumbTarget) { 7348 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 7349 CHECK_THUMB_TARGET_INFO_CREATION(ThumbMRI); 7350 ThumbAsmInfo.reset( 7351 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions)); 7352 CHECK_THUMB_TARGET_INFO_CREATION(ThumbAsmInfo); 7353 ThumbSTI.reset( 7354 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU, 7355 FeaturesStr)); 7356 CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI); 7357 ThumbCtx.reset(new MCContext(Triple(ThumbTripleName), ThumbAsmInfo.get(), 7358 ThumbMRI.get(), ThumbSTI.get())); 7359 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 7360 CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm); 7361 MCContext *PtrThumbCtx = ThumbCtx.get(); 7362 ThumbRelInfo.reset( 7363 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 7364 if (ThumbRelInfo) { 7365 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 7366 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 7367 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 7368 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 7369 } 7370 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 7371 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 7372 Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo, 7373 *ThumbInstrInfo, *ThumbMRI)); 7374 CHECK_THUMB_TARGET_INFO_CREATION(ThumbIP); 7375 // Set the display preference for hex vs. decimal immediates. 7376 ThumbIP->setPrintImmHex(PrintImmHex); 7377 } 7378 7379 #undef CHECK_TARGET_INFO_CREATION 7380 #undef CHECK_THUMB_TARGET_INFO_CREATION 7381 7382 MachO::mach_header Header = MachOOF->getHeader(); 7383 7384 // FIXME: Using the -cfg command line option, this code used to be able to 7385 // annotate relocations with the referenced symbol's name, and if this was 7386 // inside a __[cf]string section, the data it points to. This is now replaced 7387 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 7388 std::vector<SectionRef> Sections; 7389 std::vector<SymbolRef> Symbols; 7390 SmallVector<uint64_t, 8> FoundFns; 7391 uint64_t BaseSegmentAddress = 0; 7392 7393 getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, 7394 BaseSegmentAddress); 7395 7396 // Sort the symbols by address, just in case they didn't come in that way. 7397 llvm::stable_sort(Symbols, SymbolSorter()); 7398 7399 // Build a data in code table that is sorted on by the address of each entry. 7400 uint64_t BaseAddress = 0; 7401 if (Header.filetype == MachO::MH_OBJECT) 7402 BaseAddress = Sections[0].getAddress(); 7403 else 7404 BaseAddress = BaseSegmentAddress; 7405 DiceTable Dices; 7406 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 7407 DI != DE; ++DI) { 7408 uint32_t Offset; 7409 DI->getOffset(Offset); 7410 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 7411 } 7412 array_pod_sort(Dices.begin(), Dices.end()); 7413 7414 // Try to find debug info and set up the DIContext for it. 7415 std::unique_ptr<DIContext> diContext; 7416 std::unique_ptr<Binary> DSYMBinary; 7417 std::unique_ptr<MemoryBuffer> DSYMBuf; 7418 if (UseDbg) { 7419 // If separate DSym file path was specified, parse it as a macho file, 7420 // get the sections and supply it to the section name parsing machinery. 7421 if (const ObjectFile *DbgObj = 7422 getMachODSymObject(MachOOF, Filename, DSYMBinary, DSYMBuf)) { 7423 // Setup the DIContext 7424 diContext = DWARFContext::create(*DbgObj); 7425 } else { 7426 return; 7427 } 7428 } 7429 7430 if (FilterSections.empty()) 7431 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 7432 7433 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 7434 Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName(); 7435 if (!SecNameOrErr) { 7436 consumeError(SecNameOrErr.takeError()); 7437 continue; 7438 } 7439 if (*SecNameOrErr != DisSectName) 7440 continue; 7441 7442 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 7443 7444 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 7445 if (SegmentName != DisSegName) 7446 continue; 7447 7448 StringRef BytesStr = 7449 unwrapOrError(Sections[SectIdx].getContents(), Filename); 7450 ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr); 7451 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7452 7453 bool symbolTableWorked = false; 7454 7455 // Create a map of symbol addresses to symbol names for use by 7456 // the SymbolizerSymbolLookUp() routine. 7457 SymbolAddressMap AddrMap; 7458 bool DisSymNameFound = false; 7459 for (const SymbolRef &Symbol : MachOOF->symbols()) { 7460 SymbolRef::Type ST = 7461 unwrapOrError(Symbol.getType(), MachOOF->getFileName()); 7462 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 7463 ST == SymbolRef::ST_Other) { 7464 uint64_t Address = cantFail(Symbol.getValue()); 7465 StringRef SymName = 7466 unwrapOrError(Symbol.getName(), MachOOF->getFileName()); 7467 AddrMap[Address] = SymName; 7468 if (!DisSymName.empty() && DisSymName == SymName) 7469 DisSymNameFound = true; 7470 } 7471 } 7472 if (!DisSymName.empty() && !DisSymNameFound) { 7473 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 7474 return; 7475 } 7476 // Set up the block of info used by the Symbolizer call backs. 7477 SymbolizerInfo.verbose = SymbolicOperands; 7478 SymbolizerInfo.O = MachOOF; 7479 SymbolizerInfo.S = Sections[SectIdx]; 7480 SymbolizerInfo.AddrMap = &AddrMap; 7481 SymbolizerInfo.Sections = &Sections; 7482 // Same for the ThumbSymbolizer 7483 ThumbSymbolizerInfo.verbose = SymbolicOperands; 7484 ThumbSymbolizerInfo.O = MachOOF; 7485 ThumbSymbolizerInfo.S = Sections[SectIdx]; 7486 ThumbSymbolizerInfo.AddrMap = &AddrMap; 7487 ThumbSymbolizerInfo.Sections = &Sections; 7488 7489 unsigned int Arch = MachOOF->getArch(); 7490 7491 // Skip all symbols if this is a stubs file. 7492 if (Bytes.empty()) 7493 return; 7494 7495 // If the section has symbols but no symbol at the start of the section 7496 // these are used to make sure the bytes before the first symbol are 7497 // disassembled. 7498 bool FirstSymbol = true; 7499 bool FirstSymbolAtSectionStart = true; 7500 7501 // Disassemble symbol by symbol. 7502 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 7503 StringRef SymName = 7504 unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName()); 7505 SymbolRef::Type ST = 7506 unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName()); 7507 if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) 7508 continue; 7509 7510 // Make sure the symbol is defined in this section. 7511 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 7512 if (!containsSym) { 7513 if (!DisSymName.empty() && DisSymName == SymName) { 7514 outs() << "-dis-symname: " << DisSymName << " not in the section\n"; 7515 return; 7516 } 7517 continue; 7518 } 7519 // The __mh_execute_header is special and we need to deal with that fact 7520 // this symbol is before the start of the (__TEXT,__text) section and at the 7521 // address of the start of the __TEXT segment. This is because this symbol 7522 // is an N_SECT symbol in the (__TEXT,__text) but its address is before the 7523 // start of the section in a standard MH_EXECUTE filetype. 7524 if (!DisSymName.empty() && DisSymName == "__mh_execute_header") { 7525 outs() << "-dis-symname: __mh_execute_header not in any section\n"; 7526 return; 7527 } 7528 // When this code is trying to disassemble a symbol at a time and in the 7529 // case there is only the __mh_execute_header symbol left as in a stripped 7530 // executable, we need to deal with this by ignoring this symbol so the 7531 // whole section is disassembled and this symbol is then not displayed. 7532 if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" || 7533 SymName == "__mh_bundle_header" || SymName == "__mh_object_header" || 7534 SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header") 7535 continue; 7536 7537 // If we are only disassembling one symbol see if this is that symbol. 7538 if (!DisSymName.empty() && DisSymName != SymName) 7539 continue; 7540 7541 // Start at the address of the symbol relative to the section's address. 7542 uint64_t SectSize = Sections[SectIdx].getSize(); 7543 uint64_t Start = cantFail(Symbols[SymIdx].getValue()); 7544 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 7545 Start -= SectionAddress; 7546 7547 if (Start > SectSize) { 7548 outs() << "section data ends, " << SymName 7549 << " lies outside valid range\n"; 7550 return; 7551 } 7552 7553 // Stop disassembling either at the beginning of the next symbol or at 7554 // the end of the section. 7555 bool containsNextSym = false; 7556 uint64_t NextSym = 0; 7557 uint64_t NextSymIdx = SymIdx + 1; 7558 while (Symbols.size() > NextSymIdx) { 7559 SymbolRef::Type NextSymType = unwrapOrError( 7560 Symbols[NextSymIdx].getType(), MachOOF->getFileName()); 7561 if (NextSymType == SymbolRef::ST_Function) { 7562 containsNextSym = 7563 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 7564 NextSym = cantFail(Symbols[NextSymIdx].getValue()); 7565 NextSym -= SectionAddress; 7566 break; 7567 } 7568 ++NextSymIdx; 7569 } 7570 7571 uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize; 7572 uint64_t Size; 7573 7574 symbolTableWorked = true; 7575 7576 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 7577 uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb)); 7578 bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb; 7579 7580 // We only need the dedicated Thumb target if there's a real choice 7581 // (i.e. we're not targeting M-class) and the function is Thumb. 7582 bool UseThumbTarget = IsThumb && ThumbTarget; 7583 7584 // If we are not specifying a symbol to start disassembly with and this 7585 // is the first symbol in the section but not at the start of the section 7586 // then move the disassembly index to the start of the section and 7587 // don't print the symbol name just yet. This is so the bytes before the 7588 // first symbol are disassembled. 7589 uint64_t SymbolStart = Start; 7590 if (DisSymName.empty() && FirstSymbol && Start != 0) { 7591 FirstSymbolAtSectionStart = false; 7592 Start = 0; 7593 } 7594 else 7595 outs() << SymName << ":\n"; 7596 7597 DILineInfo lastLine; 7598 for (uint64_t Index = Start; Index < End; Index += Size) { 7599 MCInst Inst; 7600 7601 // If this is the first symbol in the section and it was not at the 7602 // start of the section, see if we are at its Index now and if so print 7603 // the symbol name. 7604 if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart) 7605 outs() << SymName << ":\n"; 7606 7607 uint64_t PC = SectAddress + Index; 7608 if (LeadingAddr) { 7609 if (FullLeadingAddr) { 7610 if (MachOOF->is64Bit()) 7611 outs() << format("%016" PRIx64, PC); 7612 else 7613 outs() << format("%08" PRIx64, PC); 7614 } else { 7615 outs() << format("%8" PRIx64 ":", PC); 7616 } 7617 } 7618 if (ShowRawInsn || Arch == Triple::arm) 7619 outs() << "\t"; 7620 7621 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size)) 7622 continue; 7623 7624 SmallVector<char, 64> AnnotationsBytes; 7625 raw_svector_ostream Annotations(AnnotationsBytes); 7626 7627 bool gotInst; 7628 if (UseThumbTarget) 7629 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 7630 PC, Annotations); 7631 else 7632 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 7633 Annotations); 7634 if (gotInst) { 7635 if (ShowRawInsn || Arch == Triple::arm) { 7636 dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs()); 7637 } 7638 formatted_raw_ostream FormattedOS(outs()); 7639 StringRef AnnotationsStr = Annotations.str(); 7640 if (UseThumbTarget) 7641 ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI, 7642 FormattedOS); 7643 else 7644 IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS); 7645 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 7646 7647 // Print debug info. 7648 if (diContext) { 7649 DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx}); 7650 // Print valid line info if it changed. 7651 if (dli != lastLine && dli.Line != 0) 7652 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 7653 << dli.Column; 7654 lastLine = dli; 7655 } 7656 outs() << "\n"; 7657 } else { 7658 if (MachOOF->getArchTriple().isX86()) { 7659 outs() << format("\t.byte 0x%02x #bad opcode\n", 7660 *(Bytes.data() + Index) & 0xff); 7661 Size = 1; // skip exactly one illegible byte and move on. 7662 } else if (Arch == Triple::aarch64 || 7663 (Arch == Triple::arm && !IsThumb)) { 7664 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7665 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 7666 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 7667 (*(Bytes.data() + Index + 3) & 0xff) << 24; 7668 outs() << format("\t.long\t0x%08x\n", opcode); 7669 Size = 4; 7670 } else if (Arch == Triple::arm) { 7671 assert(IsThumb && "ARM mode should have been dealt with above"); 7672 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 7673 (*(Bytes.data() + Index + 1) & 0xff) << 8; 7674 outs() << format("\t.short\t0x%04x\n", opcode); 7675 Size = 2; 7676 } else{ 7677 WithColor::warning(errs(), "llvm-objdump") 7678 << "invalid instruction encoding\n"; 7679 if (Size == 0) 7680 Size = 1; // skip illegible bytes 7681 } 7682 } 7683 } 7684 // Now that we are done disassembled the first symbol set the bool that 7685 // were doing this to false. 7686 FirstSymbol = false; 7687 } 7688 if (!symbolTableWorked) { 7689 // Reading the symbol table didn't work, disassemble the whole section. 7690 uint64_t SectAddress = Sections[SectIdx].getAddress(); 7691 uint64_t SectSize = Sections[SectIdx].getSize(); 7692 uint64_t InstSize; 7693 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 7694 MCInst Inst; 7695 7696 uint64_t PC = SectAddress + Index; 7697 7698 if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize)) 7699 continue; 7700 7701 SmallVector<char, 64> AnnotationsBytes; 7702 raw_svector_ostream Annotations(AnnotationsBytes); 7703 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 7704 Annotations)) { 7705 if (LeadingAddr) { 7706 if (FullLeadingAddr) { 7707 if (MachOOF->is64Bit()) 7708 outs() << format("%016" PRIx64, PC); 7709 else 7710 outs() << format("%08" PRIx64, PC); 7711 } else { 7712 outs() << format("%8" PRIx64 ":", PC); 7713 } 7714 } 7715 if (ShowRawInsn || Arch == Triple::arm) { 7716 outs() << "\t"; 7717 dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs()); 7718 } 7719 StringRef AnnotationsStr = Annotations.str(); 7720 IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs()); 7721 outs() << "\n"; 7722 } else { 7723 if (MachOOF->getArchTriple().isX86()) { 7724 outs() << format("\t.byte 0x%02x #bad opcode\n", 7725 *(Bytes.data() + Index) & 0xff); 7726 InstSize = 1; // skip exactly one illegible byte and move on. 7727 } else { 7728 WithColor::warning(errs(), "llvm-objdump") 7729 << "invalid instruction encoding\n"; 7730 if (InstSize == 0) 7731 InstSize = 1; // skip illegible bytes 7732 } 7733 } 7734 } 7735 } 7736 // The TripleName's need to be reset if we are called again for a different 7737 // architecture. 7738 TripleName = ""; 7739 ThumbTripleName = ""; 7740 7741 if (SymbolizerInfo.demangled_name != nullptr) 7742 free(SymbolizerInfo.demangled_name); 7743 if (ThumbSymbolizerInfo.demangled_name != nullptr) 7744 free(ThumbSymbolizerInfo.demangled_name); 7745 } 7746 } 7747 7748 //===----------------------------------------------------------------------===// 7749 // __compact_unwind section dumping 7750 //===----------------------------------------------------------------------===// 7751 7752 namespace { 7753 7754 template <typename T> 7755 static uint64_t read(StringRef Contents, ptrdiff_t Offset) { 7756 if (Offset + sizeof(T) > Contents.size()) { 7757 outs() << "warning: attempt to read past end of buffer\n"; 7758 return T(); 7759 } 7760 7761 uint64_t Val = support::endian::read<T, llvm::endianness::little>( 7762 Contents.data() + Offset); 7763 return Val; 7764 } 7765 7766 template <typename T> 7767 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { 7768 T Val = read<T>(Contents, Offset); 7769 Offset += sizeof(T); 7770 return Val; 7771 } 7772 7773 struct CompactUnwindEntry { 7774 uint32_t OffsetInSection; 7775 7776 uint64_t FunctionAddr; 7777 uint32_t Length; 7778 uint32_t CompactEncoding; 7779 uint64_t PersonalityAddr; 7780 uint64_t LSDAAddr; 7781 7782 RelocationRef FunctionReloc; 7783 RelocationRef PersonalityReloc; 7784 RelocationRef LSDAReloc; 7785 7786 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 7787 : OffsetInSection(Offset) { 7788 if (Is64) 7789 read<uint64_t>(Contents, Offset); 7790 else 7791 read<uint32_t>(Contents, Offset); 7792 } 7793 7794 private: 7795 template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { 7796 FunctionAddr = readNext<UIntPtr>(Contents, Offset); 7797 Length = readNext<uint32_t>(Contents, Offset); 7798 CompactEncoding = readNext<uint32_t>(Contents, Offset); 7799 PersonalityAddr = readNext<UIntPtr>(Contents, Offset); 7800 LSDAAddr = readNext<UIntPtr>(Contents, Offset); 7801 } 7802 }; 7803 } 7804 7805 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 7806 /// and data being relocated, determine the best base Name and Addend to use for 7807 /// display purposes. 7808 /// 7809 /// 1. An Extern relocation will directly reference a symbol (and the data is 7810 /// then already an addend), so use that. 7811 /// 2. Otherwise the data is an offset in the object file's layout; try to find 7812 // a symbol before it in the same section, and use the offset from there. 7813 /// 3. Finally, if all that fails, fall back to an offset from the start of the 7814 /// referenced section. 7815 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 7816 std::map<uint64_t, SymbolRef> &Symbols, 7817 const RelocationRef &Reloc, uint64_t Addr, 7818 StringRef &Name, uint64_t &Addend) { 7819 if (Reloc.getSymbol() != Obj->symbol_end()) { 7820 Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName()); 7821 Addend = Addr; 7822 return; 7823 } 7824 7825 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 7826 SectionRef RelocSection = Obj->getAnyRelocationSection(RE); 7827 7828 uint64_t SectionAddr = RelocSection.getAddress(); 7829 7830 auto Sym = Symbols.upper_bound(Addr); 7831 if (Sym == Symbols.begin()) { 7832 // The first symbol in the object is after this reference, the best we can 7833 // do is section-relative notation. 7834 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7835 Name = *NameOrErr; 7836 else 7837 consumeError(NameOrErr.takeError()); 7838 7839 Addend = Addr - SectionAddr; 7840 return; 7841 } 7842 7843 // Go back one so that SymbolAddress <= Addr. 7844 --Sym; 7845 7846 section_iterator SymSection = 7847 unwrapOrError(Sym->second.getSection(), Obj->getFileName()); 7848 if (RelocSection == *SymSection) { 7849 // There's a valid symbol in the same section before this reference. 7850 Name = unwrapOrError(Sym->second.getName(), Obj->getFileName()); 7851 Addend = Addr - Sym->first; 7852 return; 7853 } 7854 7855 // There is a symbol before this reference, but it's in a different 7856 // section. Probably not helpful to mention it, so use the section name. 7857 if (Expected<StringRef> NameOrErr = RelocSection.getName()) 7858 Name = *NameOrErr; 7859 else 7860 consumeError(NameOrErr.takeError()); 7861 7862 Addend = Addr - SectionAddr; 7863 } 7864 7865 static void printUnwindRelocDest(const MachOObjectFile *Obj, 7866 std::map<uint64_t, SymbolRef> &Symbols, 7867 const RelocationRef &Reloc, uint64_t Addr) { 7868 StringRef Name; 7869 uint64_t Addend; 7870 7871 if (!Reloc.getObject()) 7872 return; 7873 7874 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 7875 7876 outs() << Name; 7877 if (Addend) 7878 outs() << " + " << format("0x%" PRIx64, Addend); 7879 } 7880 7881 static void 7882 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 7883 std::map<uint64_t, SymbolRef> &Symbols, 7884 const SectionRef &CompactUnwind) { 7885 7886 if (!Obj->isLittleEndian()) { 7887 outs() << "Skipping big-endian __compact_unwind section\n"; 7888 return; 7889 } 7890 7891 bool Is64 = Obj->is64Bit(); 7892 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 7893 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 7894 7895 StringRef Contents = 7896 unwrapOrError(CompactUnwind.getContents(), Obj->getFileName()); 7897 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 7898 7899 // First populate the initial raw offsets, encodings and so on from the entry. 7900 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 7901 CompactUnwindEntry Entry(Contents, Offset, Is64); 7902 CompactUnwinds.push_back(Entry); 7903 } 7904 7905 // Next we need to look at the relocations to find out what objects are 7906 // actually being referred to. 7907 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 7908 uint64_t RelocAddress = Reloc.getOffset(); 7909 7910 uint32_t EntryIdx = RelocAddress / EntrySize; 7911 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 7912 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 7913 7914 if (OffsetInEntry == 0) 7915 Entry.FunctionReloc = Reloc; 7916 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 7917 Entry.PersonalityReloc = Reloc; 7918 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 7919 Entry.LSDAReloc = Reloc; 7920 else { 7921 outs() << "Invalid relocation in __compact_unwind section\n"; 7922 return; 7923 } 7924 } 7925 7926 // Finally, we're ready to print the data we've gathered. 7927 outs() << "Contents of __compact_unwind section:\n"; 7928 for (auto &Entry : CompactUnwinds) { 7929 outs() << " Entry at offset " 7930 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 7931 7932 // 1. Start of the region this entry applies to. 7933 outs() << " start: " << format("0x%" PRIx64, 7934 Entry.FunctionAddr) << ' '; 7935 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 7936 outs() << '\n'; 7937 7938 // 2. Length of the region this entry applies to. 7939 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 7940 << '\n'; 7941 // 3. The 32-bit compact encoding. 7942 outs() << " compact encoding: " 7943 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 7944 7945 // 4. The personality function, if present. 7946 if (Entry.PersonalityReloc.getObject()) { 7947 outs() << " personality function: " 7948 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 7949 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 7950 Entry.PersonalityAddr); 7951 outs() << '\n'; 7952 } 7953 7954 // 5. This entry's language-specific data area. 7955 if (Entry.LSDAReloc.getObject()) { 7956 outs() << " LSDA: " << format("0x%" PRIx64, 7957 Entry.LSDAAddr) << ' '; 7958 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 7959 outs() << '\n'; 7960 } 7961 } 7962 } 7963 7964 //===----------------------------------------------------------------------===// 7965 // __unwind_info section dumping 7966 //===----------------------------------------------------------------------===// 7967 7968 static void printRegularSecondLevelUnwindPage(StringRef PageData) { 7969 ptrdiff_t Pos = 0; 7970 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7971 (void)Kind; 7972 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 7973 7974 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7975 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 7976 7977 Pos = EntriesStart; 7978 for (unsigned i = 0; i < NumEntries; ++i) { 7979 uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); 7980 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 7981 7982 outs() << " [" << i << "]: " 7983 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 7984 << ", " 7985 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 7986 } 7987 } 7988 7989 static void printCompressedSecondLevelUnwindPage( 7990 StringRef PageData, uint32_t FunctionBase, 7991 const SmallVectorImpl<uint32_t> &CommonEncodings) { 7992 ptrdiff_t Pos = 0; 7993 uint32_t Kind = readNext<uint32_t>(PageData, Pos); 7994 (void)Kind; 7995 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 7996 7997 uint32_t NumCommonEncodings = CommonEncodings.size(); 7998 uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); 7999 uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); 8000 8001 uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos); 8002 uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos); 8003 SmallVector<uint32_t, 64> PageEncodings; 8004 if (NumPageEncodings) { 8005 outs() << " Page encodings: (count = " << NumPageEncodings << ")\n"; 8006 Pos = PageEncodingsStart; 8007 for (unsigned i = 0; i < NumPageEncodings; ++i) { 8008 uint32_t Encoding = readNext<uint32_t>(PageData, Pos); 8009 PageEncodings.push_back(Encoding); 8010 outs() << " encoding[" << (i + NumCommonEncodings) 8011 << "]: " << format("0x%08" PRIx32, Encoding) << '\n'; 8012 } 8013 } 8014 8015 Pos = EntriesStart; 8016 for (unsigned i = 0; i < NumEntries; ++i) { 8017 uint32_t Entry = readNext<uint32_t>(PageData, Pos); 8018 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 8019 uint32_t EncodingIdx = Entry >> 24; 8020 8021 uint32_t Encoding; 8022 if (EncodingIdx < NumCommonEncodings) 8023 Encoding = CommonEncodings[EncodingIdx]; 8024 else 8025 Encoding = PageEncodings[EncodingIdx - NumCommonEncodings]; 8026 8027 outs() << " [" << i << "]: " 8028 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8029 << ", " 8030 << "encoding[" << EncodingIdx 8031 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 8032 } 8033 } 8034 8035 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 8036 std::map<uint64_t, SymbolRef> &Symbols, 8037 const SectionRef &UnwindInfo) { 8038 8039 if (!Obj->isLittleEndian()) { 8040 outs() << "Skipping big-endian __unwind_info section\n"; 8041 return; 8042 } 8043 8044 outs() << "Contents of __unwind_info section:\n"; 8045 8046 StringRef Contents = 8047 unwrapOrError(UnwindInfo.getContents(), Obj->getFileName()); 8048 ptrdiff_t Pos = 0; 8049 8050 //===---------------------------------- 8051 // Section header 8052 //===---------------------------------- 8053 8054 uint32_t Version = readNext<uint32_t>(Contents, Pos); 8055 outs() << " Version: " 8056 << format("0x%" PRIx32, Version) << '\n'; 8057 if (Version != 1) { 8058 outs() << " Skipping section with unknown version\n"; 8059 return; 8060 } 8061 8062 uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos); 8063 outs() << " Common encodings array section offset: " 8064 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 8065 uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos); 8066 outs() << " Number of common encodings in array: " 8067 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 8068 8069 uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos); 8070 outs() << " Personality function array section offset: " 8071 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 8072 uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos); 8073 outs() << " Number of personality functions in array: " 8074 << format("0x%" PRIx32, NumPersonalities) << '\n'; 8075 8076 uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos); 8077 outs() << " Index array section offset: " 8078 << format("0x%" PRIx32, IndicesStart) << '\n'; 8079 uint32_t NumIndices = readNext<uint32_t>(Contents, Pos); 8080 outs() << " Number of indices in array: " 8081 << format("0x%" PRIx32, NumIndices) << '\n'; 8082 8083 //===---------------------------------- 8084 // A shared list of common encodings 8085 //===---------------------------------- 8086 8087 // These occupy indices in the range [0, N] whenever an encoding is referenced 8088 // from a compressed 2nd level index table. In practice the linker only 8089 // creates ~128 of these, so that indices are available to embed encodings in 8090 // the 2nd level index. 8091 8092 SmallVector<uint32_t, 64> CommonEncodings; 8093 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 8094 Pos = CommonEncodingsStart; 8095 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 8096 uint32_t Encoding = readNext<uint32_t>(Contents, Pos); 8097 CommonEncodings.push_back(Encoding); 8098 8099 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 8100 << '\n'; 8101 } 8102 8103 //===---------------------------------- 8104 // Personality functions used in this executable 8105 //===---------------------------------- 8106 8107 // There should be only a handful of these (one per source language, 8108 // roughly). Particularly since they only get 2 bits in the compact encoding. 8109 8110 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 8111 Pos = PersonalitiesStart; 8112 for (unsigned i = 0; i < NumPersonalities; ++i) { 8113 uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos); 8114 outs() << " personality[" << i + 1 8115 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 8116 } 8117 8118 //===---------------------------------- 8119 // The level 1 index entries 8120 //===---------------------------------- 8121 8122 // These specify an approximate place to start searching for the more detailed 8123 // information, sorted by PC. 8124 8125 struct IndexEntry { 8126 uint32_t FunctionOffset; 8127 uint32_t SecondLevelPageStart; 8128 uint32_t LSDAStart; 8129 }; 8130 8131 SmallVector<IndexEntry, 4> IndexEntries; 8132 8133 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 8134 Pos = IndicesStart; 8135 for (unsigned i = 0; i < NumIndices; ++i) { 8136 IndexEntry Entry; 8137 8138 Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); 8139 Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); 8140 Entry.LSDAStart = readNext<uint32_t>(Contents, Pos); 8141 IndexEntries.push_back(Entry); 8142 8143 outs() << " [" << i << "]: " 8144 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 8145 << ", " 8146 << "2nd level page offset=" 8147 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 8148 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 8149 } 8150 8151 //===---------------------------------- 8152 // Next come the LSDA tables 8153 //===---------------------------------- 8154 8155 // The LSDA layout is rather implicit: it's a contiguous array of entries from 8156 // the first top-level index's LSDAOffset to the last (sentinel). 8157 8158 outs() << " LSDA descriptors:\n"; 8159 Pos = IndexEntries[0].LSDAStart; 8160 const uint32_t LSDASize = 2 * sizeof(uint32_t); 8161 int NumLSDAs = 8162 (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; 8163 8164 for (int i = 0; i < NumLSDAs; ++i) { 8165 uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); 8166 uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos); 8167 outs() << " [" << i << "]: " 8168 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 8169 << ", " 8170 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 8171 } 8172 8173 //===---------------------------------- 8174 // Finally, the 2nd level indices 8175 //===---------------------------------- 8176 8177 // Generally these are 4K in size, and have 2 possible forms: 8178 // + Regular stores up to 511 entries with disparate encodings 8179 // + Compressed stores up to 1021 entries if few enough compact encoding 8180 // values are used. 8181 outs() << " Second level indices:\n"; 8182 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 8183 // The final sentinel top-level index has no associated 2nd level page 8184 if (IndexEntries[i].SecondLevelPageStart == 0) 8185 break; 8186 8187 outs() << " Second level index[" << i << "]: " 8188 << "offset in section=" 8189 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 8190 << ", " 8191 << "base function offset=" 8192 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 8193 8194 Pos = IndexEntries[i].SecondLevelPageStart; 8195 if (Pos + sizeof(uint32_t) > Contents.size()) { 8196 outs() << "warning: invalid offset for second level page: " << Pos << '\n'; 8197 continue; 8198 } 8199 8200 uint32_t Kind = 8201 *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos); 8202 if (Kind == 2) 8203 printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096)); 8204 else if (Kind == 3) 8205 printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), 8206 IndexEntries[i].FunctionOffset, 8207 CommonEncodings); 8208 else 8209 outs() << " Skipping 2nd level page with unknown kind " << Kind 8210 << '\n'; 8211 } 8212 } 8213 8214 void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) { 8215 std::map<uint64_t, SymbolRef> Symbols; 8216 for (const SymbolRef &SymRef : Obj->symbols()) { 8217 // Discard any undefined or absolute symbols. They're not going to take part 8218 // in the convenience lookup for unwind info and just take up resources. 8219 auto SectOrErr = SymRef.getSection(); 8220 if (!SectOrErr) { 8221 // TODO: Actually report errors helpfully. 8222 consumeError(SectOrErr.takeError()); 8223 continue; 8224 } 8225 section_iterator Section = *SectOrErr; 8226 if (Section == Obj->section_end()) 8227 continue; 8228 8229 uint64_t Addr = cantFail(SymRef.getValue()); 8230 Symbols.insert(std::make_pair(Addr, SymRef)); 8231 } 8232 8233 for (const SectionRef &Section : Obj->sections()) { 8234 StringRef SectName; 8235 if (Expected<StringRef> NameOrErr = Section.getName()) 8236 SectName = *NameOrErr; 8237 else 8238 consumeError(NameOrErr.takeError()); 8239 8240 if (SectName == "__compact_unwind") 8241 printMachOCompactUnwindSection(Obj, Symbols, Section); 8242 else if (SectName == "__unwind_info") 8243 printMachOUnwindInfoSection(Obj, Symbols, Section); 8244 } 8245 } 8246 8247 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 8248 uint32_t cpusubtype, uint32_t filetype, 8249 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 8250 bool verbose) { 8251 outs() << "Mach header\n"; 8252 outs() << " magic cputype cpusubtype caps filetype ncmds " 8253 "sizeofcmds flags\n"; 8254 if (verbose) { 8255 if (magic == MachO::MH_MAGIC) 8256 outs() << " MH_MAGIC"; 8257 else if (magic == MachO::MH_MAGIC_64) 8258 outs() << "MH_MAGIC_64"; 8259 else 8260 outs() << format(" 0x%08" PRIx32, magic); 8261 switch (cputype) { 8262 case MachO::CPU_TYPE_I386: 8263 outs() << " I386"; 8264 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8265 case MachO::CPU_SUBTYPE_I386_ALL: 8266 outs() << " ALL"; 8267 break; 8268 default: 8269 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8270 break; 8271 } 8272 break; 8273 case MachO::CPU_TYPE_X86_64: 8274 outs() << " X86_64"; 8275 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8276 case MachO::CPU_SUBTYPE_X86_64_ALL: 8277 outs() << " ALL"; 8278 break; 8279 case MachO::CPU_SUBTYPE_X86_64_H: 8280 outs() << " Haswell"; 8281 break; 8282 default: 8283 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8284 break; 8285 } 8286 break; 8287 case MachO::CPU_TYPE_ARM: 8288 outs() << " ARM"; 8289 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8290 case MachO::CPU_SUBTYPE_ARM_ALL: 8291 outs() << " ALL"; 8292 break; 8293 case MachO::CPU_SUBTYPE_ARM_V4T: 8294 outs() << " V4T"; 8295 break; 8296 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 8297 outs() << " V5TEJ"; 8298 break; 8299 case MachO::CPU_SUBTYPE_ARM_XSCALE: 8300 outs() << " XSCALE"; 8301 break; 8302 case MachO::CPU_SUBTYPE_ARM_V6: 8303 outs() << " V6"; 8304 break; 8305 case MachO::CPU_SUBTYPE_ARM_V6M: 8306 outs() << " V6M"; 8307 break; 8308 case MachO::CPU_SUBTYPE_ARM_V7: 8309 outs() << " V7"; 8310 break; 8311 case MachO::CPU_SUBTYPE_ARM_V7EM: 8312 outs() << " V7EM"; 8313 break; 8314 case MachO::CPU_SUBTYPE_ARM_V7K: 8315 outs() << " V7K"; 8316 break; 8317 case MachO::CPU_SUBTYPE_ARM_V7M: 8318 outs() << " V7M"; 8319 break; 8320 case MachO::CPU_SUBTYPE_ARM_V7S: 8321 outs() << " V7S"; 8322 break; 8323 default: 8324 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8325 break; 8326 } 8327 break; 8328 case MachO::CPU_TYPE_ARM64: 8329 outs() << " ARM64"; 8330 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8331 case MachO::CPU_SUBTYPE_ARM64_ALL: 8332 outs() << " ALL"; 8333 break; 8334 case MachO::CPU_SUBTYPE_ARM64_V8: 8335 outs() << " V8"; 8336 break; 8337 case MachO::CPU_SUBTYPE_ARM64E: 8338 outs() << " E"; 8339 break; 8340 default: 8341 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8342 break; 8343 } 8344 break; 8345 case MachO::CPU_TYPE_ARM64_32: 8346 outs() << " ARM64_32"; 8347 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8348 case MachO::CPU_SUBTYPE_ARM64_32_V8: 8349 outs() << " V8"; 8350 break; 8351 default: 8352 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8353 break; 8354 } 8355 break; 8356 case MachO::CPU_TYPE_POWERPC: 8357 outs() << " PPC"; 8358 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8359 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8360 outs() << " ALL"; 8361 break; 8362 default: 8363 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8364 break; 8365 } 8366 break; 8367 case MachO::CPU_TYPE_POWERPC64: 8368 outs() << " PPC64"; 8369 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 8370 case MachO::CPU_SUBTYPE_POWERPC_ALL: 8371 outs() << " ALL"; 8372 break; 8373 default: 8374 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8375 break; 8376 } 8377 break; 8378 default: 8379 outs() << format(" %7d", cputype); 8380 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8381 break; 8382 } 8383 8384 if (cputype == MachO::CPU_TYPE_ARM64 && 8385 MachO::CPU_SUBTYPE_ARM64E_IS_VERSIONED_PTRAUTH_ABI(cpusubtype)) { 8386 const char *Format = 8387 MachO::CPU_SUBTYPE_ARM64E_IS_KERNEL_PTRAUTH_ABI(cpusubtype) 8388 ? " PAK%02d" 8389 : " PAC%02d"; 8390 outs() << format(Format, 8391 MachO::CPU_SUBTYPE_ARM64E_PTRAUTH_VERSION(cpusubtype)); 8392 } else if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == 8393 MachO::CPU_SUBTYPE_LIB64) { 8394 outs() << " LIB64"; 8395 } else { 8396 outs() << format(" 0x%02" PRIx32, 8397 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8398 } 8399 switch (filetype) { 8400 case MachO::MH_OBJECT: 8401 outs() << " OBJECT"; 8402 break; 8403 case MachO::MH_EXECUTE: 8404 outs() << " EXECUTE"; 8405 break; 8406 case MachO::MH_FVMLIB: 8407 outs() << " FVMLIB"; 8408 break; 8409 case MachO::MH_CORE: 8410 outs() << " CORE"; 8411 break; 8412 case MachO::MH_PRELOAD: 8413 outs() << " PRELOAD"; 8414 break; 8415 case MachO::MH_DYLIB: 8416 outs() << " DYLIB"; 8417 break; 8418 case MachO::MH_DYLIB_STUB: 8419 outs() << " DYLIB_STUB"; 8420 break; 8421 case MachO::MH_DYLINKER: 8422 outs() << " DYLINKER"; 8423 break; 8424 case MachO::MH_BUNDLE: 8425 outs() << " BUNDLE"; 8426 break; 8427 case MachO::MH_DSYM: 8428 outs() << " DSYM"; 8429 break; 8430 case MachO::MH_KEXT_BUNDLE: 8431 outs() << " KEXTBUNDLE"; 8432 break; 8433 case MachO::MH_FILESET: 8434 outs() << " FILESET"; 8435 break; 8436 default: 8437 outs() << format(" %10u", filetype); 8438 break; 8439 } 8440 outs() << format(" %5u", ncmds); 8441 outs() << format(" %10u", sizeofcmds); 8442 uint32_t f = flags; 8443 if (f & MachO::MH_NOUNDEFS) { 8444 outs() << " NOUNDEFS"; 8445 f &= ~MachO::MH_NOUNDEFS; 8446 } 8447 if (f & MachO::MH_INCRLINK) { 8448 outs() << " INCRLINK"; 8449 f &= ~MachO::MH_INCRLINK; 8450 } 8451 if (f & MachO::MH_DYLDLINK) { 8452 outs() << " DYLDLINK"; 8453 f &= ~MachO::MH_DYLDLINK; 8454 } 8455 if (f & MachO::MH_BINDATLOAD) { 8456 outs() << " BINDATLOAD"; 8457 f &= ~MachO::MH_BINDATLOAD; 8458 } 8459 if (f & MachO::MH_PREBOUND) { 8460 outs() << " PREBOUND"; 8461 f &= ~MachO::MH_PREBOUND; 8462 } 8463 if (f & MachO::MH_SPLIT_SEGS) { 8464 outs() << " SPLIT_SEGS"; 8465 f &= ~MachO::MH_SPLIT_SEGS; 8466 } 8467 if (f & MachO::MH_LAZY_INIT) { 8468 outs() << " LAZY_INIT"; 8469 f &= ~MachO::MH_LAZY_INIT; 8470 } 8471 if (f & MachO::MH_TWOLEVEL) { 8472 outs() << " TWOLEVEL"; 8473 f &= ~MachO::MH_TWOLEVEL; 8474 } 8475 if (f & MachO::MH_FORCE_FLAT) { 8476 outs() << " FORCE_FLAT"; 8477 f &= ~MachO::MH_FORCE_FLAT; 8478 } 8479 if (f & MachO::MH_NOMULTIDEFS) { 8480 outs() << " NOMULTIDEFS"; 8481 f &= ~MachO::MH_NOMULTIDEFS; 8482 } 8483 if (f & MachO::MH_NOFIXPREBINDING) { 8484 outs() << " NOFIXPREBINDING"; 8485 f &= ~MachO::MH_NOFIXPREBINDING; 8486 } 8487 if (f & MachO::MH_PREBINDABLE) { 8488 outs() << " PREBINDABLE"; 8489 f &= ~MachO::MH_PREBINDABLE; 8490 } 8491 if (f & MachO::MH_ALLMODSBOUND) { 8492 outs() << " ALLMODSBOUND"; 8493 f &= ~MachO::MH_ALLMODSBOUND; 8494 } 8495 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 8496 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 8497 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 8498 } 8499 if (f & MachO::MH_CANONICAL) { 8500 outs() << " CANONICAL"; 8501 f &= ~MachO::MH_CANONICAL; 8502 } 8503 if (f & MachO::MH_WEAK_DEFINES) { 8504 outs() << " WEAK_DEFINES"; 8505 f &= ~MachO::MH_WEAK_DEFINES; 8506 } 8507 if (f & MachO::MH_BINDS_TO_WEAK) { 8508 outs() << " BINDS_TO_WEAK"; 8509 f &= ~MachO::MH_BINDS_TO_WEAK; 8510 } 8511 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 8512 outs() << " ALLOW_STACK_EXECUTION"; 8513 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 8514 } 8515 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 8516 outs() << " DEAD_STRIPPABLE_DYLIB"; 8517 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 8518 } 8519 if (f & MachO::MH_PIE) { 8520 outs() << " PIE"; 8521 f &= ~MachO::MH_PIE; 8522 } 8523 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 8524 outs() << " NO_REEXPORTED_DYLIBS"; 8525 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 8526 } 8527 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 8528 outs() << " MH_HAS_TLV_DESCRIPTORS"; 8529 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 8530 } 8531 if (f & MachO::MH_NO_HEAP_EXECUTION) { 8532 outs() << " MH_NO_HEAP_EXECUTION"; 8533 f &= ~MachO::MH_NO_HEAP_EXECUTION; 8534 } 8535 if (f & MachO::MH_APP_EXTENSION_SAFE) { 8536 outs() << " APP_EXTENSION_SAFE"; 8537 f &= ~MachO::MH_APP_EXTENSION_SAFE; 8538 } 8539 if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 8540 outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO"; 8541 f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO; 8542 } 8543 if (f != 0 || flags == 0) 8544 outs() << format(" 0x%08" PRIx32, f); 8545 } else { 8546 outs() << format(" 0x%08" PRIx32, magic); 8547 outs() << format(" %7d", cputype); 8548 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 8549 outs() << format(" 0x%02" PRIx32, 8550 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 8551 outs() << format(" %10u", filetype); 8552 outs() << format(" %5u", ncmds); 8553 outs() << format(" %10u", sizeofcmds); 8554 outs() << format(" 0x%08" PRIx32, flags); 8555 } 8556 outs() << "\n"; 8557 } 8558 8559 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 8560 StringRef SegName, uint64_t vmaddr, 8561 uint64_t vmsize, uint64_t fileoff, 8562 uint64_t filesize, uint32_t maxprot, 8563 uint32_t initprot, uint32_t nsects, 8564 uint32_t flags, uint32_t object_size, 8565 bool verbose) { 8566 uint64_t expected_cmdsize; 8567 if (cmd == MachO::LC_SEGMENT) { 8568 outs() << " cmd LC_SEGMENT\n"; 8569 expected_cmdsize = nsects; 8570 expected_cmdsize *= sizeof(struct MachO::section); 8571 expected_cmdsize += sizeof(struct MachO::segment_command); 8572 } else { 8573 outs() << " cmd LC_SEGMENT_64\n"; 8574 expected_cmdsize = nsects; 8575 expected_cmdsize *= sizeof(struct MachO::section_64); 8576 expected_cmdsize += sizeof(struct MachO::segment_command_64); 8577 } 8578 outs() << " cmdsize " << cmdsize; 8579 if (cmdsize != expected_cmdsize) 8580 outs() << " Inconsistent size\n"; 8581 else 8582 outs() << "\n"; 8583 outs() << " segname " << SegName << "\n"; 8584 if (cmd == MachO::LC_SEGMENT_64) { 8585 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 8586 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 8587 } else { 8588 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 8589 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 8590 } 8591 outs() << " fileoff " << fileoff; 8592 if (fileoff > object_size) 8593 outs() << " (past end of file)\n"; 8594 else 8595 outs() << "\n"; 8596 outs() << " filesize " << filesize; 8597 if (fileoff + filesize > object_size) 8598 outs() << " (past end of file)\n"; 8599 else 8600 outs() << "\n"; 8601 if (verbose) { 8602 if ((maxprot & 8603 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8604 MachO::VM_PROT_EXECUTE)) != 0) 8605 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 8606 else { 8607 outs() << " maxprot "; 8608 outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-"); 8609 outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8610 outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8611 } 8612 if ((initprot & 8613 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 8614 MachO::VM_PROT_EXECUTE)) != 0) 8615 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 8616 else { 8617 outs() << " initprot "; 8618 outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); 8619 outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); 8620 outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); 8621 } 8622 } else { 8623 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 8624 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 8625 } 8626 outs() << " nsects " << nsects << "\n"; 8627 if (verbose) { 8628 outs() << " flags"; 8629 if (flags == 0) 8630 outs() << " (none)\n"; 8631 else { 8632 if (flags & MachO::SG_HIGHVM) { 8633 outs() << " HIGHVM"; 8634 flags &= ~MachO::SG_HIGHVM; 8635 } 8636 if (flags & MachO::SG_FVMLIB) { 8637 outs() << " FVMLIB"; 8638 flags &= ~MachO::SG_FVMLIB; 8639 } 8640 if (flags & MachO::SG_NORELOC) { 8641 outs() << " NORELOC"; 8642 flags &= ~MachO::SG_NORELOC; 8643 } 8644 if (flags & MachO::SG_PROTECTED_VERSION_1) { 8645 outs() << " PROTECTED_VERSION_1"; 8646 flags &= ~MachO::SG_PROTECTED_VERSION_1; 8647 } 8648 if (flags & MachO::SG_READ_ONLY) { 8649 // Apple's otool prints the SG_ prefix for this flag, but not for the 8650 // others. 8651 outs() << " SG_READ_ONLY"; 8652 flags &= ~MachO::SG_READ_ONLY; 8653 } 8654 if (flags) 8655 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 8656 else 8657 outs() << "\n"; 8658 } 8659 } else { 8660 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 8661 } 8662 } 8663 8664 static void PrintSection(const char *sectname, const char *segname, 8665 uint64_t addr, uint64_t size, uint32_t offset, 8666 uint32_t align, uint32_t reloff, uint32_t nreloc, 8667 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 8668 uint32_t cmd, const char *sg_segname, 8669 uint32_t filetype, uint32_t object_size, 8670 bool verbose) { 8671 outs() << "Section\n"; 8672 outs() << " sectname " << format("%.16s\n", sectname); 8673 outs() << " segname " << format("%.16s", segname); 8674 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 8675 outs() << " (does not match segment)\n"; 8676 else 8677 outs() << "\n"; 8678 if (cmd == MachO::LC_SEGMENT_64) { 8679 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 8680 outs() << " size " << format("0x%016" PRIx64, size); 8681 } else { 8682 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 8683 outs() << " size " << format("0x%08" PRIx64, size); 8684 } 8685 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 8686 outs() << " (past end of file)\n"; 8687 else 8688 outs() << "\n"; 8689 outs() << " offset " << offset; 8690 if (offset > object_size) 8691 outs() << " (past end of file)\n"; 8692 else 8693 outs() << "\n"; 8694 uint32_t align_shifted = 1 << align; 8695 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 8696 outs() << " reloff " << reloff; 8697 if (reloff > object_size) 8698 outs() << " (past end of file)\n"; 8699 else 8700 outs() << "\n"; 8701 outs() << " nreloc " << nreloc; 8702 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 8703 outs() << " (past end of file)\n"; 8704 else 8705 outs() << "\n"; 8706 uint32_t section_type = flags & MachO::SECTION_TYPE; 8707 if (verbose) { 8708 outs() << " type"; 8709 if (section_type == MachO::S_REGULAR) 8710 outs() << " S_REGULAR\n"; 8711 else if (section_type == MachO::S_ZEROFILL) 8712 outs() << " S_ZEROFILL\n"; 8713 else if (section_type == MachO::S_CSTRING_LITERALS) 8714 outs() << " S_CSTRING_LITERALS\n"; 8715 else if (section_type == MachO::S_4BYTE_LITERALS) 8716 outs() << " S_4BYTE_LITERALS\n"; 8717 else if (section_type == MachO::S_8BYTE_LITERALS) 8718 outs() << " S_8BYTE_LITERALS\n"; 8719 else if (section_type == MachO::S_16BYTE_LITERALS) 8720 outs() << " S_16BYTE_LITERALS\n"; 8721 else if (section_type == MachO::S_LITERAL_POINTERS) 8722 outs() << " S_LITERAL_POINTERS\n"; 8723 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 8724 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 8725 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 8726 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 8727 else if (section_type == MachO::S_SYMBOL_STUBS) 8728 outs() << " S_SYMBOL_STUBS\n"; 8729 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 8730 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 8731 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 8732 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 8733 else if (section_type == MachO::S_COALESCED) 8734 outs() << " S_COALESCED\n"; 8735 else if (section_type == MachO::S_INTERPOSING) 8736 outs() << " S_INTERPOSING\n"; 8737 else if (section_type == MachO::S_DTRACE_DOF) 8738 outs() << " S_DTRACE_DOF\n"; 8739 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 8740 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 8741 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 8742 outs() << " S_THREAD_LOCAL_REGULAR\n"; 8743 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 8744 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 8745 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 8746 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 8747 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8748 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 8749 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 8750 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 8751 else if (section_type == MachO::S_INIT_FUNC_OFFSETS) 8752 outs() << " S_INIT_FUNC_OFFSETS\n"; 8753 else 8754 outs() << format("0x%08" PRIx32, section_type) << "\n"; 8755 outs() << "attributes"; 8756 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 8757 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 8758 outs() << " PURE_INSTRUCTIONS"; 8759 if (section_attributes & MachO::S_ATTR_NO_TOC) 8760 outs() << " NO_TOC"; 8761 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 8762 outs() << " STRIP_STATIC_SYMS"; 8763 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 8764 outs() << " NO_DEAD_STRIP"; 8765 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 8766 outs() << " LIVE_SUPPORT"; 8767 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 8768 outs() << " SELF_MODIFYING_CODE"; 8769 if (section_attributes & MachO::S_ATTR_DEBUG) 8770 outs() << " DEBUG"; 8771 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 8772 outs() << " SOME_INSTRUCTIONS"; 8773 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 8774 outs() << " EXT_RELOC"; 8775 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 8776 outs() << " LOC_RELOC"; 8777 if (section_attributes == 0) 8778 outs() << " (none)"; 8779 outs() << "\n"; 8780 } else 8781 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 8782 outs() << " reserved1 " << reserved1; 8783 if (section_type == MachO::S_SYMBOL_STUBS || 8784 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 8785 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 8786 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 8787 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 8788 outs() << " (index into indirect symbol table)\n"; 8789 else 8790 outs() << "\n"; 8791 outs() << " reserved2 " << reserved2; 8792 if (section_type == MachO::S_SYMBOL_STUBS) 8793 outs() << " (size of stubs)\n"; 8794 else 8795 outs() << "\n"; 8796 } 8797 8798 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 8799 uint32_t object_size) { 8800 outs() << " cmd LC_SYMTAB\n"; 8801 outs() << " cmdsize " << st.cmdsize; 8802 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 8803 outs() << " Incorrect size\n"; 8804 else 8805 outs() << "\n"; 8806 outs() << " symoff " << st.symoff; 8807 if (st.symoff > object_size) 8808 outs() << " (past end of file)\n"; 8809 else 8810 outs() << "\n"; 8811 outs() << " nsyms " << st.nsyms; 8812 uint64_t big_size; 8813 if (Is64Bit) { 8814 big_size = st.nsyms; 8815 big_size *= sizeof(struct MachO::nlist_64); 8816 big_size += st.symoff; 8817 if (big_size > object_size) 8818 outs() << " (past end of file)\n"; 8819 else 8820 outs() << "\n"; 8821 } else { 8822 big_size = st.nsyms; 8823 big_size *= sizeof(struct MachO::nlist); 8824 big_size += st.symoff; 8825 if (big_size > object_size) 8826 outs() << " (past end of file)\n"; 8827 else 8828 outs() << "\n"; 8829 } 8830 outs() << " stroff " << st.stroff; 8831 if (st.stroff > object_size) 8832 outs() << " (past end of file)\n"; 8833 else 8834 outs() << "\n"; 8835 outs() << " strsize " << st.strsize; 8836 big_size = st.stroff; 8837 big_size += st.strsize; 8838 if (big_size > object_size) 8839 outs() << " (past end of file)\n"; 8840 else 8841 outs() << "\n"; 8842 } 8843 8844 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 8845 uint32_t nsyms, uint32_t object_size, 8846 bool Is64Bit) { 8847 outs() << " cmd LC_DYSYMTAB\n"; 8848 outs() << " cmdsize " << dyst.cmdsize; 8849 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 8850 outs() << " Incorrect size\n"; 8851 else 8852 outs() << "\n"; 8853 outs() << " ilocalsym " << dyst.ilocalsym; 8854 if (dyst.ilocalsym > nsyms) 8855 outs() << " (greater than the number of symbols)\n"; 8856 else 8857 outs() << "\n"; 8858 outs() << " nlocalsym " << dyst.nlocalsym; 8859 uint64_t big_size; 8860 big_size = dyst.ilocalsym; 8861 big_size += dyst.nlocalsym; 8862 if (big_size > nsyms) 8863 outs() << " (past the end of the symbol table)\n"; 8864 else 8865 outs() << "\n"; 8866 outs() << " iextdefsym " << dyst.iextdefsym; 8867 if (dyst.iextdefsym > nsyms) 8868 outs() << " (greater than the number of symbols)\n"; 8869 else 8870 outs() << "\n"; 8871 outs() << " nextdefsym " << dyst.nextdefsym; 8872 big_size = dyst.iextdefsym; 8873 big_size += dyst.nextdefsym; 8874 if (big_size > nsyms) 8875 outs() << " (past the end of the symbol table)\n"; 8876 else 8877 outs() << "\n"; 8878 outs() << " iundefsym " << dyst.iundefsym; 8879 if (dyst.iundefsym > nsyms) 8880 outs() << " (greater than the number of symbols)\n"; 8881 else 8882 outs() << "\n"; 8883 outs() << " nundefsym " << dyst.nundefsym; 8884 big_size = dyst.iundefsym; 8885 big_size += dyst.nundefsym; 8886 if (big_size > nsyms) 8887 outs() << " (past the end of the symbol table)\n"; 8888 else 8889 outs() << "\n"; 8890 outs() << " tocoff " << dyst.tocoff; 8891 if (dyst.tocoff > object_size) 8892 outs() << " (past end of file)\n"; 8893 else 8894 outs() << "\n"; 8895 outs() << " ntoc " << dyst.ntoc; 8896 big_size = dyst.ntoc; 8897 big_size *= sizeof(struct MachO::dylib_table_of_contents); 8898 big_size += dyst.tocoff; 8899 if (big_size > object_size) 8900 outs() << " (past end of file)\n"; 8901 else 8902 outs() << "\n"; 8903 outs() << " modtaboff " << dyst.modtaboff; 8904 if (dyst.modtaboff > object_size) 8905 outs() << " (past end of file)\n"; 8906 else 8907 outs() << "\n"; 8908 outs() << " nmodtab " << dyst.nmodtab; 8909 uint64_t modtabend; 8910 if (Is64Bit) { 8911 modtabend = dyst.nmodtab; 8912 modtabend *= sizeof(struct MachO::dylib_module_64); 8913 modtabend += dyst.modtaboff; 8914 } else { 8915 modtabend = dyst.nmodtab; 8916 modtabend *= sizeof(struct MachO::dylib_module); 8917 modtabend += dyst.modtaboff; 8918 } 8919 if (modtabend > object_size) 8920 outs() << " (past end of file)\n"; 8921 else 8922 outs() << "\n"; 8923 outs() << " extrefsymoff " << dyst.extrefsymoff; 8924 if (dyst.extrefsymoff > object_size) 8925 outs() << " (past end of file)\n"; 8926 else 8927 outs() << "\n"; 8928 outs() << " nextrefsyms " << dyst.nextrefsyms; 8929 big_size = dyst.nextrefsyms; 8930 big_size *= sizeof(struct MachO::dylib_reference); 8931 big_size += dyst.extrefsymoff; 8932 if (big_size > object_size) 8933 outs() << " (past end of file)\n"; 8934 else 8935 outs() << "\n"; 8936 outs() << " indirectsymoff " << dyst.indirectsymoff; 8937 if (dyst.indirectsymoff > object_size) 8938 outs() << " (past end of file)\n"; 8939 else 8940 outs() << "\n"; 8941 outs() << " nindirectsyms " << dyst.nindirectsyms; 8942 big_size = dyst.nindirectsyms; 8943 big_size *= sizeof(uint32_t); 8944 big_size += dyst.indirectsymoff; 8945 if (big_size > object_size) 8946 outs() << " (past end of file)\n"; 8947 else 8948 outs() << "\n"; 8949 outs() << " extreloff " << dyst.extreloff; 8950 if (dyst.extreloff > object_size) 8951 outs() << " (past end of file)\n"; 8952 else 8953 outs() << "\n"; 8954 outs() << " nextrel " << dyst.nextrel; 8955 big_size = dyst.nextrel; 8956 big_size *= sizeof(struct MachO::relocation_info); 8957 big_size += dyst.extreloff; 8958 if (big_size > object_size) 8959 outs() << " (past end of file)\n"; 8960 else 8961 outs() << "\n"; 8962 outs() << " locreloff " << dyst.locreloff; 8963 if (dyst.locreloff > object_size) 8964 outs() << " (past end of file)\n"; 8965 else 8966 outs() << "\n"; 8967 outs() << " nlocrel " << dyst.nlocrel; 8968 big_size = dyst.nlocrel; 8969 big_size *= sizeof(struct MachO::relocation_info); 8970 big_size += dyst.locreloff; 8971 if (big_size > object_size) 8972 outs() << " (past end of file)\n"; 8973 else 8974 outs() << "\n"; 8975 } 8976 8977 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 8978 uint32_t object_size) { 8979 if (dc.cmd == MachO::LC_DYLD_INFO) 8980 outs() << " cmd LC_DYLD_INFO\n"; 8981 else 8982 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 8983 outs() << " cmdsize " << dc.cmdsize; 8984 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 8985 outs() << " Incorrect size\n"; 8986 else 8987 outs() << "\n"; 8988 outs() << " rebase_off " << dc.rebase_off; 8989 if (dc.rebase_off > object_size) 8990 outs() << " (past end of file)\n"; 8991 else 8992 outs() << "\n"; 8993 outs() << " rebase_size " << dc.rebase_size; 8994 uint64_t big_size; 8995 big_size = dc.rebase_off; 8996 big_size += dc.rebase_size; 8997 if (big_size > object_size) 8998 outs() << " (past end of file)\n"; 8999 else 9000 outs() << "\n"; 9001 outs() << " bind_off " << dc.bind_off; 9002 if (dc.bind_off > object_size) 9003 outs() << " (past end of file)\n"; 9004 else 9005 outs() << "\n"; 9006 outs() << " bind_size " << dc.bind_size; 9007 big_size = dc.bind_off; 9008 big_size += dc.bind_size; 9009 if (big_size > object_size) 9010 outs() << " (past end of file)\n"; 9011 else 9012 outs() << "\n"; 9013 outs() << " weak_bind_off " << dc.weak_bind_off; 9014 if (dc.weak_bind_off > object_size) 9015 outs() << " (past end of file)\n"; 9016 else 9017 outs() << "\n"; 9018 outs() << " weak_bind_size " << dc.weak_bind_size; 9019 big_size = dc.weak_bind_off; 9020 big_size += dc.weak_bind_size; 9021 if (big_size > object_size) 9022 outs() << " (past end of file)\n"; 9023 else 9024 outs() << "\n"; 9025 outs() << " lazy_bind_off " << dc.lazy_bind_off; 9026 if (dc.lazy_bind_off > object_size) 9027 outs() << " (past end of file)\n"; 9028 else 9029 outs() << "\n"; 9030 outs() << " lazy_bind_size " << dc.lazy_bind_size; 9031 big_size = dc.lazy_bind_off; 9032 big_size += dc.lazy_bind_size; 9033 if (big_size > object_size) 9034 outs() << " (past end of file)\n"; 9035 else 9036 outs() << "\n"; 9037 outs() << " export_off " << dc.export_off; 9038 if (dc.export_off > object_size) 9039 outs() << " (past end of file)\n"; 9040 else 9041 outs() << "\n"; 9042 outs() << " export_size " << dc.export_size; 9043 big_size = dc.export_off; 9044 big_size += dc.export_size; 9045 if (big_size > object_size) 9046 outs() << " (past end of file)\n"; 9047 else 9048 outs() << "\n"; 9049 } 9050 9051 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 9052 const char *Ptr) { 9053 if (dyld.cmd == MachO::LC_ID_DYLINKER) 9054 outs() << " cmd LC_ID_DYLINKER\n"; 9055 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 9056 outs() << " cmd LC_LOAD_DYLINKER\n"; 9057 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 9058 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 9059 else 9060 outs() << " cmd ?(" << dyld.cmd << ")\n"; 9061 outs() << " cmdsize " << dyld.cmdsize; 9062 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 9063 outs() << " Incorrect size\n"; 9064 else 9065 outs() << "\n"; 9066 if (dyld.name >= dyld.cmdsize) 9067 outs() << " name ?(bad offset " << dyld.name << ")\n"; 9068 else { 9069 const char *P = (const char *)(Ptr) + dyld.name; 9070 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 9071 } 9072 } 9073 9074 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 9075 outs() << " cmd LC_UUID\n"; 9076 outs() << " cmdsize " << uuid.cmdsize; 9077 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 9078 outs() << " Incorrect size\n"; 9079 else 9080 outs() << "\n"; 9081 outs() << " uuid "; 9082 for (int i = 0; i < 16; ++i) { 9083 outs() << format("%02" PRIX32, uuid.uuid[i]); 9084 if (i == 3 || i == 5 || i == 7 || i == 9) 9085 outs() << "-"; 9086 } 9087 outs() << "\n"; 9088 } 9089 9090 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 9091 outs() << " cmd LC_RPATH\n"; 9092 outs() << " cmdsize " << rpath.cmdsize; 9093 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 9094 outs() << " Incorrect size\n"; 9095 else 9096 outs() << "\n"; 9097 if (rpath.path >= rpath.cmdsize) 9098 outs() << " path ?(bad offset " << rpath.path << ")\n"; 9099 else { 9100 const char *P = (const char *)(Ptr) + rpath.path; 9101 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 9102 } 9103 } 9104 9105 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 9106 StringRef LoadCmdName; 9107 switch (vd.cmd) { 9108 case MachO::LC_VERSION_MIN_MACOSX: 9109 LoadCmdName = "LC_VERSION_MIN_MACOSX"; 9110 break; 9111 case MachO::LC_VERSION_MIN_IPHONEOS: 9112 LoadCmdName = "LC_VERSION_MIN_IPHONEOS"; 9113 break; 9114 case MachO::LC_VERSION_MIN_TVOS: 9115 LoadCmdName = "LC_VERSION_MIN_TVOS"; 9116 break; 9117 case MachO::LC_VERSION_MIN_WATCHOS: 9118 LoadCmdName = "LC_VERSION_MIN_WATCHOS"; 9119 break; 9120 default: 9121 llvm_unreachable("Unknown version min load command"); 9122 } 9123 9124 outs() << " cmd " << LoadCmdName << '\n'; 9125 outs() << " cmdsize " << vd.cmdsize; 9126 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 9127 outs() << " Incorrect size\n"; 9128 else 9129 outs() << "\n"; 9130 outs() << " version " 9131 << MachOObjectFile::getVersionMinMajor(vd, false) << "." 9132 << MachOObjectFile::getVersionMinMinor(vd, false); 9133 uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false); 9134 if (Update != 0) 9135 outs() << "." << Update; 9136 outs() << "\n"; 9137 if (vd.sdk == 0) 9138 outs() << " sdk n/a"; 9139 else { 9140 outs() << " sdk " 9141 << MachOObjectFile::getVersionMinMajor(vd, true) << "." 9142 << MachOObjectFile::getVersionMinMinor(vd, true); 9143 } 9144 Update = MachOObjectFile::getVersionMinUpdate(vd, true); 9145 if (Update != 0) 9146 outs() << "." << Update; 9147 outs() << "\n"; 9148 } 9149 9150 static void PrintNoteLoadCommand(MachO::note_command Nt) { 9151 outs() << " cmd LC_NOTE\n"; 9152 outs() << " cmdsize " << Nt.cmdsize; 9153 if (Nt.cmdsize != sizeof(struct MachO::note_command)) 9154 outs() << " Incorrect size\n"; 9155 else 9156 outs() << "\n"; 9157 const char *d = Nt.data_owner; 9158 outs() << "data_owner " << format("%.16s\n", d); 9159 outs() << " offset " << Nt.offset << "\n"; 9160 outs() << " size " << Nt.size << "\n"; 9161 } 9162 9163 static void PrintBuildToolVersion(MachO::build_tool_version bv, bool verbose) { 9164 outs() << " tool "; 9165 if (verbose) 9166 outs() << MachOObjectFile::getBuildTool(bv.tool); 9167 else 9168 outs() << bv.tool; 9169 outs() << "\n"; 9170 outs() << " version " << MachOObjectFile::getVersionString(bv.version) 9171 << "\n"; 9172 } 9173 9174 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj, 9175 MachO::build_version_command bd, 9176 bool verbose) { 9177 outs() << " cmd LC_BUILD_VERSION\n"; 9178 outs() << " cmdsize " << bd.cmdsize; 9179 if (bd.cmdsize != 9180 sizeof(struct MachO::build_version_command) + 9181 bd.ntools * sizeof(struct MachO::build_tool_version)) 9182 outs() << " Incorrect size\n"; 9183 else 9184 outs() << "\n"; 9185 outs() << " platform "; 9186 if (verbose) 9187 outs() << MachOObjectFile::getBuildPlatform(bd.platform); 9188 else 9189 outs() << bd.platform; 9190 outs() << "\n"; 9191 if (bd.sdk) 9192 outs() << " sdk " << MachOObjectFile::getVersionString(bd.sdk) 9193 << "\n"; 9194 else 9195 outs() << " sdk n/a\n"; 9196 outs() << " minos " << MachOObjectFile::getVersionString(bd.minos) 9197 << "\n"; 9198 outs() << " ntools " << bd.ntools << "\n"; 9199 for (unsigned i = 0; i < bd.ntools; ++i) { 9200 MachO::build_tool_version bv = obj->getBuildToolVersion(i); 9201 PrintBuildToolVersion(bv, verbose); 9202 } 9203 } 9204 9205 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 9206 outs() << " cmd LC_SOURCE_VERSION\n"; 9207 outs() << " cmdsize " << sd.cmdsize; 9208 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 9209 outs() << " Incorrect size\n"; 9210 else 9211 outs() << "\n"; 9212 uint64_t a = (sd.version >> 40) & 0xffffff; 9213 uint64_t b = (sd.version >> 30) & 0x3ff; 9214 uint64_t c = (sd.version >> 20) & 0x3ff; 9215 uint64_t d = (sd.version >> 10) & 0x3ff; 9216 uint64_t e = sd.version & 0x3ff; 9217 outs() << " version " << a << "." << b; 9218 if (e != 0) 9219 outs() << "." << c << "." << d << "." << e; 9220 else if (d != 0) 9221 outs() << "." << c << "." << d; 9222 else if (c != 0) 9223 outs() << "." << c; 9224 outs() << "\n"; 9225 } 9226 9227 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 9228 outs() << " cmd LC_MAIN\n"; 9229 outs() << " cmdsize " << ep.cmdsize; 9230 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 9231 outs() << " Incorrect size\n"; 9232 else 9233 outs() << "\n"; 9234 outs() << " entryoff " << ep.entryoff << "\n"; 9235 outs() << " stacksize " << ep.stacksize << "\n"; 9236 } 9237 9238 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 9239 uint32_t object_size) { 9240 outs() << " cmd LC_ENCRYPTION_INFO\n"; 9241 outs() << " cmdsize " << ec.cmdsize; 9242 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 9243 outs() << " Incorrect size\n"; 9244 else 9245 outs() << "\n"; 9246 outs() << " cryptoff " << ec.cryptoff; 9247 if (ec.cryptoff > object_size) 9248 outs() << " (past end of file)\n"; 9249 else 9250 outs() << "\n"; 9251 outs() << " cryptsize " << ec.cryptsize; 9252 if (ec.cryptsize > object_size) 9253 outs() << " (past end of file)\n"; 9254 else 9255 outs() << "\n"; 9256 outs() << " cryptid " << ec.cryptid << "\n"; 9257 } 9258 9259 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 9260 uint32_t object_size) { 9261 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 9262 outs() << " cmdsize " << ec.cmdsize; 9263 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 9264 outs() << " Incorrect size\n"; 9265 else 9266 outs() << "\n"; 9267 outs() << " cryptoff " << ec.cryptoff; 9268 if (ec.cryptoff > object_size) 9269 outs() << " (past end of file)\n"; 9270 else 9271 outs() << "\n"; 9272 outs() << " cryptsize " << ec.cryptsize; 9273 if (ec.cryptsize > object_size) 9274 outs() << " (past end of file)\n"; 9275 else 9276 outs() << "\n"; 9277 outs() << " cryptid " << ec.cryptid << "\n"; 9278 outs() << " pad " << ec.pad << "\n"; 9279 } 9280 9281 static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 9282 const char *Ptr) { 9283 outs() << " cmd LC_LINKER_OPTION\n"; 9284 outs() << " cmdsize " << lo.cmdsize; 9285 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 9286 outs() << " Incorrect size\n"; 9287 else 9288 outs() << "\n"; 9289 outs() << " count " << lo.count << "\n"; 9290 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 9291 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 9292 uint32_t i = 0; 9293 while (left > 0) { 9294 while (*string == '\0' && left > 0) { 9295 string++; 9296 left--; 9297 } 9298 if (left > 0) { 9299 i++; 9300 outs() << " string #" << i << " " << format("%.*s\n", left, string); 9301 uint32_t NullPos = StringRef(string, left).find('\0'); 9302 uint32_t len = std::min(NullPos, left) + 1; 9303 string += len; 9304 left -= len; 9305 } 9306 } 9307 if (lo.count != i) 9308 outs() << " count " << lo.count << " does not match number of strings " 9309 << i << "\n"; 9310 } 9311 9312 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 9313 const char *Ptr) { 9314 outs() << " cmd LC_SUB_FRAMEWORK\n"; 9315 outs() << " cmdsize " << sub.cmdsize; 9316 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 9317 outs() << " Incorrect size\n"; 9318 else 9319 outs() << "\n"; 9320 if (sub.umbrella < sub.cmdsize) { 9321 const char *P = Ptr + sub.umbrella; 9322 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 9323 } else { 9324 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 9325 } 9326 } 9327 9328 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 9329 const char *Ptr) { 9330 outs() << " cmd LC_SUB_UMBRELLA\n"; 9331 outs() << " cmdsize " << sub.cmdsize; 9332 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 9333 outs() << " Incorrect size\n"; 9334 else 9335 outs() << "\n"; 9336 if (sub.sub_umbrella < sub.cmdsize) { 9337 const char *P = Ptr + sub.sub_umbrella; 9338 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 9339 } else { 9340 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 9341 } 9342 } 9343 9344 static void PrintSubLibraryCommand(MachO::sub_library_command sub, 9345 const char *Ptr) { 9346 outs() << " cmd LC_SUB_LIBRARY\n"; 9347 outs() << " cmdsize " << sub.cmdsize; 9348 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 9349 outs() << " Incorrect size\n"; 9350 else 9351 outs() << "\n"; 9352 if (sub.sub_library < sub.cmdsize) { 9353 const char *P = Ptr + sub.sub_library; 9354 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 9355 } else { 9356 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 9357 } 9358 } 9359 9360 static void PrintSubClientCommand(MachO::sub_client_command sub, 9361 const char *Ptr) { 9362 outs() << " cmd LC_SUB_CLIENT\n"; 9363 outs() << " cmdsize " << sub.cmdsize; 9364 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 9365 outs() << " Incorrect size\n"; 9366 else 9367 outs() << "\n"; 9368 if (sub.client < sub.cmdsize) { 9369 const char *P = Ptr + sub.client; 9370 outs() << " client " << P << " (offset " << sub.client << ")\n"; 9371 } else { 9372 outs() << " client ?(bad offset " << sub.client << ")\n"; 9373 } 9374 } 9375 9376 static void PrintRoutinesCommand(MachO::routines_command r) { 9377 outs() << " cmd LC_ROUTINES\n"; 9378 outs() << " cmdsize " << r.cmdsize; 9379 if (r.cmdsize != sizeof(struct MachO::routines_command)) 9380 outs() << " Incorrect size\n"; 9381 else 9382 outs() << "\n"; 9383 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 9384 outs() << " init_module " << r.init_module << "\n"; 9385 outs() << " reserved1 " << r.reserved1 << "\n"; 9386 outs() << " reserved2 " << r.reserved2 << "\n"; 9387 outs() << " reserved3 " << r.reserved3 << "\n"; 9388 outs() << " reserved4 " << r.reserved4 << "\n"; 9389 outs() << " reserved5 " << r.reserved5 << "\n"; 9390 outs() << " reserved6 " << r.reserved6 << "\n"; 9391 } 9392 9393 static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 9394 outs() << " cmd LC_ROUTINES_64\n"; 9395 outs() << " cmdsize " << r.cmdsize; 9396 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 9397 outs() << " Incorrect size\n"; 9398 else 9399 outs() << "\n"; 9400 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 9401 outs() << " init_module " << r.init_module << "\n"; 9402 outs() << " reserved1 " << r.reserved1 << "\n"; 9403 outs() << " reserved2 " << r.reserved2 << "\n"; 9404 outs() << " reserved3 " << r.reserved3 << "\n"; 9405 outs() << " reserved4 " << r.reserved4 << "\n"; 9406 outs() << " reserved5 " << r.reserved5 << "\n"; 9407 outs() << " reserved6 " << r.reserved6 << "\n"; 9408 } 9409 9410 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) { 9411 outs() << "\t eax " << format("0x%08" PRIx32, cpu32.eax); 9412 outs() << " ebx " << format("0x%08" PRIx32, cpu32.ebx); 9413 outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx); 9414 outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n"; 9415 outs() << "\t edi " << format("0x%08" PRIx32, cpu32.edi); 9416 outs() << " esi " << format("0x%08" PRIx32, cpu32.esi); 9417 outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp); 9418 outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n"; 9419 outs() << "\t ss " << format("0x%08" PRIx32, cpu32.ss); 9420 outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags); 9421 outs() << " eip " << format("0x%08" PRIx32, cpu32.eip); 9422 outs() << " cs " << format("0x%08" PRIx32, cpu32.cs) << "\n"; 9423 outs() << "\t ds " << format("0x%08" PRIx32, cpu32.ds); 9424 outs() << " es " << format("0x%08" PRIx32, cpu32.es); 9425 outs() << " fs " << format("0x%08" PRIx32, cpu32.fs); 9426 outs() << " gs " << format("0x%08" PRIx32, cpu32.gs) << "\n"; 9427 } 9428 9429 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 9430 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 9431 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 9432 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 9433 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 9434 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 9435 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 9436 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 9437 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 9438 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 9439 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 9440 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 9441 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 9442 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 9443 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 9444 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 9445 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 9446 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 9447 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 9448 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 9449 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 9450 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 9451 } 9452 9453 static void Print_mmst_reg(MachO::mmst_reg_t &r) { 9454 uint32_t f; 9455 outs() << "\t mmst_reg "; 9456 for (f = 0; f < 10; f++) 9457 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 9458 outs() << "\n"; 9459 outs() << "\t mmst_rsrv "; 9460 for (f = 0; f < 6; f++) 9461 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 9462 outs() << "\n"; 9463 } 9464 9465 static void Print_xmm_reg(MachO::xmm_reg_t &r) { 9466 uint32_t f; 9467 outs() << "\t xmm_reg "; 9468 for (f = 0; f < 16; f++) 9469 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 9470 outs() << "\n"; 9471 } 9472 9473 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 9474 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 9475 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 9476 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 9477 outs() << " denorm " << fpu.fpu_fcw.denorm; 9478 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 9479 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 9480 outs() << " undfl " << fpu.fpu_fcw.undfl; 9481 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 9482 outs() << "\t\t pc "; 9483 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 9484 outs() << "FP_PREC_24B "; 9485 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 9486 outs() << "FP_PREC_53B "; 9487 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 9488 outs() << "FP_PREC_64B "; 9489 else 9490 outs() << fpu.fpu_fcw.pc << " "; 9491 outs() << "rc "; 9492 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 9493 outs() << "FP_RND_NEAR "; 9494 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 9495 outs() << "FP_RND_DOWN "; 9496 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 9497 outs() << "FP_RND_UP "; 9498 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 9499 outs() << "FP_CHOP "; 9500 outs() << "\n"; 9501 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 9502 outs() << " denorm " << fpu.fpu_fsw.denorm; 9503 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 9504 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 9505 outs() << " undfl " << fpu.fpu_fsw.undfl; 9506 outs() << " precis " << fpu.fpu_fsw.precis; 9507 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 9508 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 9509 outs() << " c0 " << fpu.fpu_fsw.c0; 9510 outs() << " c1 " << fpu.fpu_fsw.c1; 9511 outs() << " c2 " << fpu.fpu_fsw.c2; 9512 outs() << " tos " << fpu.fpu_fsw.tos; 9513 outs() << " c3 " << fpu.fpu_fsw.c3; 9514 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 9515 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 9516 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 9517 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 9518 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 9519 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 9520 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 9521 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 9522 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 9523 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 9524 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 9525 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 9526 outs() << "\n"; 9527 outs() << "\t fpu_stmm0:\n"; 9528 Print_mmst_reg(fpu.fpu_stmm0); 9529 outs() << "\t fpu_stmm1:\n"; 9530 Print_mmst_reg(fpu.fpu_stmm1); 9531 outs() << "\t fpu_stmm2:\n"; 9532 Print_mmst_reg(fpu.fpu_stmm2); 9533 outs() << "\t fpu_stmm3:\n"; 9534 Print_mmst_reg(fpu.fpu_stmm3); 9535 outs() << "\t fpu_stmm4:\n"; 9536 Print_mmst_reg(fpu.fpu_stmm4); 9537 outs() << "\t fpu_stmm5:\n"; 9538 Print_mmst_reg(fpu.fpu_stmm5); 9539 outs() << "\t fpu_stmm6:\n"; 9540 Print_mmst_reg(fpu.fpu_stmm6); 9541 outs() << "\t fpu_stmm7:\n"; 9542 Print_mmst_reg(fpu.fpu_stmm7); 9543 outs() << "\t fpu_xmm0:\n"; 9544 Print_xmm_reg(fpu.fpu_xmm0); 9545 outs() << "\t fpu_xmm1:\n"; 9546 Print_xmm_reg(fpu.fpu_xmm1); 9547 outs() << "\t fpu_xmm2:\n"; 9548 Print_xmm_reg(fpu.fpu_xmm2); 9549 outs() << "\t fpu_xmm3:\n"; 9550 Print_xmm_reg(fpu.fpu_xmm3); 9551 outs() << "\t fpu_xmm4:\n"; 9552 Print_xmm_reg(fpu.fpu_xmm4); 9553 outs() << "\t fpu_xmm5:\n"; 9554 Print_xmm_reg(fpu.fpu_xmm5); 9555 outs() << "\t fpu_xmm6:\n"; 9556 Print_xmm_reg(fpu.fpu_xmm6); 9557 outs() << "\t fpu_xmm7:\n"; 9558 Print_xmm_reg(fpu.fpu_xmm7); 9559 outs() << "\t fpu_xmm8:\n"; 9560 Print_xmm_reg(fpu.fpu_xmm8); 9561 outs() << "\t fpu_xmm9:\n"; 9562 Print_xmm_reg(fpu.fpu_xmm9); 9563 outs() << "\t fpu_xmm10:\n"; 9564 Print_xmm_reg(fpu.fpu_xmm10); 9565 outs() << "\t fpu_xmm11:\n"; 9566 Print_xmm_reg(fpu.fpu_xmm11); 9567 outs() << "\t fpu_xmm12:\n"; 9568 Print_xmm_reg(fpu.fpu_xmm12); 9569 outs() << "\t fpu_xmm13:\n"; 9570 Print_xmm_reg(fpu.fpu_xmm13); 9571 outs() << "\t fpu_xmm14:\n"; 9572 Print_xmm_reg(fpu.fpu_xmm14); 9573 outs() << "\t fpu_xmm15:\n"; 9574 Print_xmm_reg(fpu.fpu_xmm15); 9575 outs() << "\t fpu_rsrv4:\n"; 9576 for (uint32_t f = 0; f < 6; f++) { 9577 outs() << "\t "; 9578 for (uint32_t g = 0; g < 16; g++) 9579 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 9580 outs() << "\n"; 9581 } 9582 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 9583 outs() << "\n"; 9584 } 9585 9586 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 9587 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 9588 outs() << " err " << format("0x%08" PRIx32, exc64.err); 9589 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 9590 } 9591 9592 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { 9593 outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); 9594 outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); 9595 outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); 9596 outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; 9597 outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); 9598 outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); 9599 outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); 9600 outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; 9601 outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); 9602 outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); 9603 outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); 9604 outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; 9605 outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); 9606 outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); 9607 outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); 9608 outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; 9609 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; 9610 } 9611 9612 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { 9613 outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); 9614 outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); 9615 outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; 9616 outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); 9617 outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); 9618 outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; 9619 outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); 9620 outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); 9621 outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; 9622 outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); 9623 outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); 9624 outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; 9625 outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); 9626 outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); 9627 outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; 9628 outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); 9629 outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); 9630 outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; 9631 outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); 9632 outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); 9633 outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; 9634 outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); 9635 outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); 9636 outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; 9637 outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); 9638 outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); 9639 outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; 9640 outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); 9641 outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); 9642 outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; 9643 outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); 9644 outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); 9645 outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; 9646 outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; 9647 } 9648 9649 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 9650 bool isLittleEndian, uint32_t cputype) { 9651 if (t.cmd == MachO::LC_THREAD) 9652 outs() << " cmd LC_THREAD\n"; 9653 else if (t.cmd == MachO::LC_UNIXTHREAD) 9654 outs() << " cmd LC_UNIXTHREAD\n"; 9655 else 9656 outs() << " cmd " << t.cmd << " (unknown)\n"; 9657 outs() << " cmdsize " << t.cmdsize; 9658 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 9659 outs() << " Incorrect size\n"; 9660 else 9661 outs() << "\n"; 9662 9663 const char *begin = Ptr + sizeof(struct MachO::thread_command); 9664 const char *end = Ptr + t.cmdsize; 9665 uint32_t flavor, count, left; 9666 if (cputype == MachO::CPU_TYPE_I386) { 9667 while (begin < end) { 9668 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9669 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9670 begin += sizeof(uint32_t); 9671 } else { 9672 flavor = 0; 9673 begin = end; 9674 } 9675 if (isLittleEndian != sys::IsLittleEndianHost) 9676 sys::swapByteOrder(flavor); 9677 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9678 memcpy((char *)&count, begin, sizeof(uint32_t)); 9679 begin += sizeof(uint32_t); 9680 } else { 9681 count = 0; 9682 begin = end; 9683 } 9684 if (isLittleEndian != sys::IsLittleEndianHost) 9685 sys::swapByteOrder(count); 9686 if (flavor == MachO::x86_THREAD_STATE32) { 9687 outs() << " flavor i386_THREAD_STATE\n"; 9688 if (count == MachO::x86_THREAD_STATE32_COUNT) 9689 outs() << " count i386_THREAD_STATE_COUNT\n"; 9690 else 9691 outs() << " count " << count 9692 << " (not x86_THREAD_STATE32_COUNT)\n"; 9693 MachO::x86_thread_state32_t cpu32; 9694 left = end - begin; 9695 if (left >= sizeof(MachO::x86_thread_state32_t)) { 9696 memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t)); 9697 begin += sizeof(MachO::x86_thread_state32_t); 9698 } else { 9699 memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t)); 9700 memcpy(&cpu32, begin, left); 9701 begin += left; 9702 } 9703 if (isLittleEndian != sys::IsLittleEndianHost) 9704 swapStruct(cpu32); 9705 Print_x86_thread_state32_t(cpu32); 9706 } else if (flavor == MachO::x86_THREAD_STATE) { 9707 outs() << " flavor x86_THREAD_STATE\n"; 9708 if (count == MachO::x86_THREAD_STATE_COUNT) 9709 outs() << " count x86_THREAD_STATE_COUNT\n"; 9710 else 9711 outs() << " count " << count 9712 << " (not x86_THREAD_STATE_COUNT)\n"; 9713 struct MachO::x86_thread_state_t ts; 9714 left = end - begin; 9715 if (left >= sizeof(MachO::x86_thread_state_t)) { 9716 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9717 begin += sizeof(MachO::x86_thread_state_t); 9718 } else { 9719 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9720 memcpy(&ts, begin, left); 9721 begin += left; 9722 } 9723 if (isLittleEndian != sys::IsLittleEndianHost) 9724 swapStruct(ts); 9725 if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) { 9726 outs() << "\t tsh.flavor x86_THREAD_STATE32 "; 9727 if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT) 9728 outs() << "tsh.count x86_THREAD_STATE32_COUNT\n"; 9729 else 9730 outs() << "tsh.count " << ts.tsh.count 9731 << " (not x86_THREAD_STATE32_COUNT\n"; 9732 Print_x86_thread_state32_t(ts.uts.ts32); 9733 } else { 9734 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9735 << ts.tsh.count << "\n"; 9736 } 9737 } else { 9738 outs() << " flavor " << flavor << " (unknown)\n"; 9739 outs() << " count " << count << "\n"; 9740 outs() << " state (unknown)\n"; 9741 begin += count * sizeof(uint32_t); 9742 } 9743 } 9744 } else if (cputype == MachO::CPU_TYPE_X86_64) { 9745 while (begin < end) { 9746 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9747 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9748 begin += sizeof(uint32_t); 9749 } else { 9750 flavor = 0; 9751 begin = end; 9752 } 9753 if (isLittleEndian != sys::IsLittleEndianHost) 9754 sys::swapByteOrder(flavor); 9755 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9756 memcpy((char *)&count, begin, sizeof(uint32_t)); 9757 begin += sizeof(uint32_t); 9758 } else { 9759 count = 0; 9760 begin = end; 9761 } 9762 if (isLittleEndian != sys::IsLittleEndianHost) 9763 sys::swapByteOrder(count); 9764 if (flavor == MachO::x86_THREAD_STATE64) { 9765 outs() << " flavor x86_THREAD_STATE64\n"; 9766 if (count == MachO::x86_THREAD_STATE64_COUNT) 9767 outs() << " count x86_THREAD_STATE64_COUNT\n"; 9768 else 9769 outs() << " count " << count 9770 << " (not x86_THREAD_STATE64_COUNT)\n"; 9771 MachO::x86_thread_state64_t cpu64; 9772 left = end - begin; 9773 if (left >= sizeof(MachO::x86_thread_state64_t)) { 9774 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 9775 begin += sizeof(MachO::x86_thread_state64_t); 9776 } else { 9777 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 9778 memcpy(&cpu64, begin, left); 9779 begin += left; 9780 } 9781 if (isLittleEndian != sys::IsLittleEndianHost) 9782 swapStruct(cpu64); 9783 Print_x86_thread_state64_t(cpu64); 9784 } else if (flavor == MachO::x86_THREAD_STATE) { 9785 outs() << " flavor x86_THREAD_STATE\n"; 9786 if (count == MachO::x86_THREAD_STATE_COUNT) 9787 outs() << " count x86_THREAD_STATE_COUNT\n"; 9788 else 9789 outs() << " count " << count 9790 << " (not x86_THREAD_STATE_COUNT)\n"; 9791 struct MachO::x86_thread_state_t ts; 9792 left = end - begin; 9793 if (left >= sizeof(MachO::x86_thread_state_t)) { 9794 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 9795 begin += sizeof(MachO::x86_thread_state_t); 9796 } else { 9797 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 9798 memcpy(&ts, begin, left); 9799 begin += left; 9800 } 9801 if (isLittleEndian != sys::IsLittleEndianHost) 9802 swapStruct(ts); 9803 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 9804 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 9805 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 9806 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 9807 else 9808 outs() << "tsh.count " << ts.tsh.count 9809 << " (not x86_THREAD_STATE64_COUNT\n"; 9810 Print_x86_thread_state64_t(ts.uts.ts64); 9811 } else { 9812 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 9813 << ts.tsh.count << "\n"; 9814 } 9815 } else if (flavor == MachO::x86_FLOAT_STATE) { 9816 outs() << " flavor x86_FLOAT_STATE\n"; 9817 if (count == MachO::x86_FLOAT_STATE_COUNT) 9818 outs() << " count x86_FLOAT_STATE_COUNT\n"; 9819 else 9820 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 9821 struct MachO::x86_float_state_t fs; 9822 left = end - begin; 9823 if (left >= sizeof(MachO::x86_float_state_t)) { 9824 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 9825 begin += sizeof(MachO::x86_float_state_t); 9826 } else { 9827 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 9828 memcpy(&fs, begin, left); 9829 begin += left; 9830 } 9831 if (isLittleEndian != sys::IsLittleEndianHost) 9832 swapStruct(fs); 9833 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 9834 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 9835 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 9836 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 9837 else 9838 outs() << "fsh.count " << fs.fsh.count 9839 << " (not x86_FLOAT_STATE64_COUNT\n"; 9840 Print_x86_float_state_t(fs.ufs.fs64); 9841 } else { 9842 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 9843 << fs.fsh.count << "\n"; 9844 } 9845 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 9846 outs() << " flavor x86_EXCEPTION_STATE\n"; 9847 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 9848 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 9849 else 9850 outs() << " count " << count 9851 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 9852 struct MachO::x86_exception_state_t es; 9853 left = end - begin; 9854 if (left >= sizeof(MachO::x86_exception_state_t)) { 9855 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 9856 begin += sizeof(MachO::x86_exception_state_t); 9857 } else { 9858 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 9859 memcpy(&es, begin, left); 9860 begin += left; 9861 } 9862 if (isLittleEndian != sys::IsLittleEndianHost) 9863 swapStruct(es); 9864 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 9865 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 9866 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 9867 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 9868 else 9869 outs() << "\t esh.count " << es.esh.count 9870 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 9871 Print_x86_exception_state_t(es.ues.es64); 9872 } else { 9873 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 9874 << es.esh.count << "\n"; 9875 } 9876 } else if (flavor == MachO::x86_EXCEPTION_STATE64) { 9877 outs() << " flavor x86_EXCEPTION_STATE64\n"; 9878 if (count == MachO::x86_EXCEPTION_STATE64_COUNT) 9879 outs() << " count x86_EXCEPTION_STATE64_COUNT\n"; 9880 else 9881 outs() << " count " << count 9882 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; 9883 struct MachO::x86_exception_state64_t es64; 9884 left = end - begin; 9885 if (left >= sizeof(MachO::x86_exception_state64_t)) { 9886 memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); 9887 begin += sizeof(MachO::x86_exception_state64_t); 9888 } else { 9889 memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); 9890 memcpy(&es64, begin, left); 9891 begin += left; 9892 } 9893 if (isLittleEndian != sys::IsLittleEndianHost) 9894 swapStruct(es64); 9895 Print_x86_exception_state_t(es64); 9896 } else { 9897 outs() << " flavor " << flavor << " (unknown)\n"; 9898 outs() << " count " << count << "\n"; 9899 outs() << " state (unknown)\n"; 9900 begin += count * sizeof(uint32_t); 9901 } 9902 } 9903 } else if (cputype == MachO::CPU_TYPE_ARM) { 9904 while (begin < end) { 9905 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9906 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9907 begin += sizeof(uint32_t); 9908 } else { 9909 flavor = 0; 9910 begin = end; 9911 } 9912 if (isLittleEndian != sys::IsLittleEndianHost) 9913 sys::swapByteOrder(flavor); 9914 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9915 memcpy((char *)&count, begin, sizeof(uint32_t)); 9916 begin += sizeof(uint32_t); 9917 } else { 9918 count = 0; 9919 begin = end; 9920 } 9921 if (isLittleEndian != sys::IsLittleEndianHost) 9922 sys::swapByteOrder(count); 9923 if (flavor == MachO::ARM_THREAD_STATE) { 9924 outs() << " flavor ARM_THREAD_STATE\n"; 9925 if (count == MachO::ARM_THREAD_STATE_COUNT) 9926 outs() << " count ARM_THREAD_STATE_COUNT\n"; 9927 else 9928 outs() << " count " << count 9929 << " (not ARM_THREAD_STATE_COUNT)\n"; 9930 MachO::arm_thread_state32_t cpu32; 9931 left = end - begin; 9932 if (left >= sizeof(MachO::arm_thread_state32_t)) { 9933 memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); 9934 begin += sizeof(MachO::arm_thread_state32_t); 9935 } else { 9936 memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); 9937 memcpy(&cpu32, begin, left); 9938 begin += left; 9939 } 9940 if (isLittleEndian != sys::IsLittleEndianHost) 9941 swapStruct(cpu32); 9942 Print_arm_thread_state32_t(cpu32); 9943 } else { 9944 outs() << " flavor " << flavor << " (unknown)\n"; 9945 outs() << " count " << count << "\n"; 9946 outs() << " state (unknown)\n"; 9947 begin += count * sizeof(uint32_t); 9948 } 9949 } 9950 } else if (cputype == MachO::CPU_TYPE_ARM64 || 9951 cputype == MachO::CPU_TYPE_ARM64_32) { 9952 while (begin < end) { 9953 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9954 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 9955 begin += sizeof(uint32_t); 9956 } else { 9957 flavor = 0; 9958 begin = end; 9959 } 9960 if (isLittleEndian != sys::IsLittleEndianHost) 9961 sys::swapByteOrder(flavor); 9962 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 9963 memcpy((char *)&count, begin, sizeof(uint32_t)); 9964 begin += sizeof(uint32_t); 9965 } else { 9966 count = 0; 9967 begin = end; 9968 } 9969 if (isLittleEndian != sys::IsLittleEndianHost) 9970 sys::swapByteOrder(count); 9971 if (flavor == MachO::ARM_THREAD_STATE64) { 9972 outs() << " flavor ARM_THREAD_STATE64\n"; 9973 if (count == MachO::ARM_THREAD_STATE64_COUNT) 9974 outs() << " count ARM_THREAD_STATE64_COUNT\n"; 9975 else 9976 outs() << " count " << count 9977 << " (not ARM_THREAD_STATE64_COUNT)\n"; 9978 MachO::arm_thread_state64_t cpu64; 9979 left = end - begin; 9980 if (left >= sizeof(MachO::arm_thread_state64_t)) { 9981 memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); 9982 begin += sizeof(MachO::arm_thread_state64_t); 9983 } else { 9984 memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); 9985 memcpy(&cpu64, begin, left); 9986 begin += left; 9987 } 9988 if (isLittleEndian != sys::IsLittleEndianHost) 9989 swapStruct(cpu64); 9990 Print_arm_thread_state64_t(cpu64); 9991 } else { 9992 outs() << " flavor " << flavor << " (unknown)\n"; 9993 outs() << " count " << count << "\n"; 9994 outs() << " state (unknown)\n"; 9995 begin += count * sizeof(uint32_t); 9996 } 9997 } 9998 } else { 9999 while (begin < end) { 10000 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 10001 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 10002 begin += sizeof(uint32_t); 10003 } else { 10004 flavor = 0; 10005 begin = end; 10006 } 10007 if (isLittleEndian != sys::IsLittleEndianHost) 10008 sys::swapByteOrder(flavor); 10009 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 10010 memcpy((char *)&count, begin, sizeof(uint32_t)); 10011 begin += sizeof(uint32_t); 10012 } else { 10013 count = 0; 10014 begin = end; 10015 } 10016 if (isLittleEndian != sys::IsLittleEndianHost) 10017 sys::swapByteOrder(count); 10018 outs() << " flavor " << flavor << "\n"; 10019 outs() << " count " << count << "\n"; 10020 outs() << " state (Unknown cputype/cpusubtype)\n"; 10021 begin += count * sizeof(uint32_t); 10022 } 10023 } 10024 } 10025 10026 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 10027 if (dl.cmd == MachO::LC_ID_DYLIB) 10028 outs() << " cmd LC_ID_DYLIB\n"; 10029 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 10030 outs() << " cmd LC_LOAD_DYLIB\n"; 10031 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 10032 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 10033 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 10034 outs() << " cmd LC_REEXPORT_DYLIB\n"; 10035 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 10036 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 10037 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 10038 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 10039 else 10040 outs() << " cmd " << dl.cmd << " (unknown)\n"; 10041 outs() << " cmdsize " << dl.cmdsize; 10042 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 10043 outs() << " Incorrect size\n"; 10044 else 10045 outs() << "\n"; 10046 if (dl.dylib.name < dl.cmdsize) { 10047 const char *P = (const char *)(Ptr) + dl.dylib.name; 10048 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 10049 } else { 10050 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 10051 } 10052 outs() << " time stamp " << dl.dylib.timestamp << " "; 10053 time_t t = dl.dylib.timestamp; 10054 outs() << ctime(&t); 10055 outs() << " current version "; 10056 if (dl.dylib.current_version == 0xffffffff) 10057 outs() << "n/a\n"; 10058 else 10059 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 10060 << ((dl.dylib.current_version >> 8) & 0xff) << "." 10061 << (dl.dylib.current_version & 0xff) << "\n"; 10062 outs() << "compatibility version "; 10063 if (dl.dylib.compatibility_version == 0xffffffff) 10064 outs() << "n/a\n"; 10065 else 10066 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 10067 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 10068 << (dl.dylib.compatibility_version & 0xff) << "\n"; 10069 } 10070 10071 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 10072 uint32_t object_size) { 10073 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 10074 outs() << " cmd LC_CODE_SIGNATURE\n"; 10075 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 10076 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 10077 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 10078 outs() << " cmd LC_FUNCTION_STARTS\n"; 10079 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 10080 outs() << " cmd LC_DATA_IN_CODE\n"; 10081 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 10082 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 10083 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 10084 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 10085 else if (ld.cmd == MachO::LC_DYLD_EXPORTS_TRIE) 10086 outs() << " cmd LC_DYLD_EXPORTS_TRIE\n"; 10087 else if (ld.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) 10088 outs() << " cmd LC_DYLD_CHAINED_FIXUPS\n"; 10089 else if (ld.cmd == MachO::LC_ATOM_INFO) 10090 outs() << " cmd LC_ATOM_INFO\n"; 10091 else 10092 outs() << " cmd " << ld.cmd << " (?)\n"; 10093 outs() << " cmdsize " << ld.cmdsize; 10094 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 10095 outs() << " Incorrect size\n"; 10096 else 10097 outs() << "\n"; 10098 outs() << " dataoff " << ld.dataoff; 10099 if (ld.dataoff > object_size) 10100 outs() << " (past end of file)\n"; 10101 else 10102 outs() << "\n"; 10103 outs() << " datasize " << ld.datasize; 10104 uint64_t big_size = ld.dataoff; 10105 big_size += ld.datasize; 10106 if (big_size > object_size) 10107 outs() << " (past end of file)\n"; 10108 else 10109 outs() << "\n"; 10110 } 10111 10112 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype, 10113 uint32_t cputype, bool verbose) { 10114 StringRef Buf = Obj->getData(); 10115 unsigned Index = 0; 10116 for (const auto &Command : Obj->load_commands()) { 10117 outs() << "Load command " << Index++ << "\n"; 10118 if (Command.C.cmd == MachO::LC_SEGMENT) { 10119 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 10120 const char *sg_segname = SLC.segname; 10121 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 10122 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 10123 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 10124 verbose); 10125 for (unsigned j = 0; j < SLC.nsects; j++) { 10126 MachO::section S = Obj->getSection(Command, j); 10127 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 10128 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 10129 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 10130 } 10131 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10132 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 10133 const char *sg_segname = SLC_64.segname; 10134 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 10135 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 10136 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 10137 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 10138 for (unsigned j = 0; j < SLC_64.nsects; j++) { 10139 MachO::section_64 S_64 = Obj->getSection64(Command, j); 10140 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 10141 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 10142 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 10143 sg_segname, filetype, Buf.size(), verbose); 10144 } 10145 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 10146 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10147 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 10148 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 10149 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 10150 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 10151 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 10152 Obj->is64Bit()); 10153 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 10154 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 10155 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 10156 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 10157 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 10158 Command.C.cmd == MachO::LC_ID_DYLINKER || 10159 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 10160 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 10161 PrintDyldLoadCommand(Dyld, Command.Ptr); 10162 } else if (Command.C.cmd == MachO::LC_UUID) { 10163 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 10164 PrintUuidLoadCommand(Uuid); 10165 } else if (Command.C.cmd == MachO::LC_RPATH) { 10166 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 10167 PrintRpathLoadCommand(Rpath, Command.Ptr); 10168 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 10169 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS || 10170 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS || 10171 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 10172 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 10173 PrintVersionMinLoadCommand(Vd); 10174 } else if (Command.C.cmd == MachO::LC_NOTE) { 10175 MachO::note_command Nt = Obj->getNoteLoadCommand(Command); 10176 PrintNoteLoadCommand(Nt); 10177 } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) { 10178 MachO::build_version_command Bv = 10179 Obj->getBuildVersionLoadCommand(Command); 10180 PrintBuildVersionLoadCommand(Obj, Bv, verbose); 10181 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 10182 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 10183 PrintSourceVersionCommand(Sd); 10184 } else if (Command.C.cmd == MachO::LC_MAIN) { 10185 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 10186 PrintEntryPointCommand(Ep); 10187 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 10188 MachO::encryption_info_command Ei = 10189 Obj->getEncryptionInfoCommand(Command); 10190 PrintEncryptionInfoCommand(Ei, Buf.size()); 10191 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 10192 MachO::encryption_info_command_64 Ei = 10193 Obj->getEncryptionInfoCommand64(Command); 10194 PrintEncryptionInfoCommand64(Ei, Buf.size()); 10195 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 10196 MachO::linker_option_command Lo = 10197 Obj->getLinkerOptionLoadCommand(Command); 10198 PrintLinkerOptionCommand(Lo, Command.Ptr); 10199 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 10200 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 10201 PrintSubFrameworkCommand(Sf, Command.Ptr); 10202 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 10203 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 10204 PrintSubUmbrellaCommand(Sf, Command.Ptr); 10205 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 10206 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 10207 PrintSubLibraryCommand(Sl, Command.Ptr); 10208 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 10209 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 10210 PrintSubClientCommand(Sc, Command.Ptr); 10211 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 10212 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 10213 PrintRoutinesCommand(Rc); 10214 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 10215 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 10216 PrintRoutinesCommand64(Rc); 10217 } else if (Command.C.cmd == MachO::LC_THREAD || 10218 Command.C.cmd == MachO::LC_UNIXTHREAD) { 10219 MachO::thread_command Tc = Obj->getThreadCommand(Command); 10220 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 10221 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 10222 Command.C.cmd == MachO::LC_ID_DYLIB || 10223 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 10224 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 10225 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 10226 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 10227 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 10228 PrintDylibCommand(Dl, Command.Ptr); 10229 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 10230 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 10231 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 10232 Command.C.cmd == MachO::LC_DATA_IN_CODE || 10233 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 10234 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT || 10235 Command.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE || 10236 Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS || 10237 Command.C.cmd == MachO::LC_ATOM_INFO) { 10238 MachO::linkedit_data_command Ld = 10239 Obj->getLinkeditDataLoadCommand(Command); 10240 PrintLinkEditDataCommand(Ld, Buf.size()); 10241 } else { 10242 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 10243 << ")\n"; 10244 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 10245 // TODO: get and print the raw bytes of the load command. 10246 } 10247 // TODO: print all the other kinds of load commands. 10248 } 10249 } 10250 10251 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) { 10252 if (Obj->is64Bit()) { 10253 MachO::mach_header_64 H_64; 10254 H_64 = Obj->getHeader64(); 10255 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 10256 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 10257 } else { 10258 MachO::mach_header H; 10259 H = Obj->getHeader(); 10260 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 10261 H.sizeofcmds, H.flags, verbose); 10262 } 10263 } 10264 10265 void objdump::printMachOFileHeader(const object::ObjectFile *Obj) { 10266 const MachOObjectFile *file = cast<const MachOObjectFile>(Obj); 10267 PrintMachHeader(file, Verbose); 10268 } 10269 10270 void MachODumper::printPrivateHeaders() { 10271 printMachOFileHeader(&Obj); 10272 if (!FirstPrivateHeader) 10273 printMachOLoadCommands(&Obj); 10274 } 10275 10276 void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) { 10277 const MachOObjectFile *file = cast<const MachOObjectFile>(Obj); 10278 uint32_t filetype = 0; 10279 uint32_t cputype = 0; 10280 if (file->is64Bit()) { 10281 MachO::mach_header_64 H_64; 10282 H_64 = file->getHeader64(); 10283 filetype = H_64.filetype; 10284 cputype = H_64.cputype; 10285 } else { 10286 MachO::mach_header H; 10287 H = file->getHeader(); 10288 filetype = H.filetype; 10289 cputype = H.cputype; 10290 } 10291 PrintLoadCommands(file, filetype, cputype, Verbose); 10292 } 10293 10294 //===----------------------------------------------------------------------===// 10295 // export trie dumping 10296 //===----------------------------------------------------------------------===// 10297 10298 static void printMachOExportsTrie(const object::MachOObjectFile *Obj) { 10299 uint64_t BaseSegmentAddress = 0; 10300 for (const auto &Command : Obj->load_commands()) { 10301 if (Command.C.cmd == MachO::LC_SEGMENT) { 10302 MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command); 10303 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10304 BaseSegmentAddress = Seg.vmaddr; 10305 break; 10306 } 10307 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 10308 MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command); 10309 if (Seg.fileoff == 0 && Seg.filesize != 0) { 10310 BaseSegmentAddress = Seg.vmaddr; 10311 break; 10312 } 10313 } 10314 } 10315 Error Err = Error::success(); 10316 for (const object::ExportEntry &Entry : Obj->exports(Err)) { 10317 uint64_t Flags = Entry.flags(); 10318 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 10319 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 10320 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10321 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 10322 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 10323 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 10324 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 10325 if (ReExport) 10326 outs() << "[re-export] "; 10327 else 10328 outs() << format("0x%08llX ", 10329 Entry.address() + BaseSegmentAddress); 10330 outs() << Entry.name(); 10331 if (WeakDef || ThreadLocal || Resolver || Abs) { 10332 ListSeparator LS; 10333 outs() << " ["; 10334 if (WeakDef) 10335 outs() << LS << "weak_def"; 10336 if (ThreadLocal) 10337 outs() << LS << "per-thread"; 10338 if (Abs) 10339 outs() << LS << "absolute"; 10340 if (Resolver) 10341 outs() << LS << format("resolver=0x%08llX", Entry.other()); 10342 outs() << "]"; 10343 } 10344 if (ReExport) { 10345 StringRef DylibName = "unknown"; 10346 int Ordinal = Entry.other() - 1; 10347 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 10348 if (Entry.otherName().empty()) 10349 outs() << " (from " << DylibName << ")"; 10350 else 10351 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 10352 } 10353 outs() << "\n"; 10354 } 10355 if (Err) 10356 reportError(std::move(Err), Obj->getFileName()); 10357 } 10358 10359 //===----------------------------------------------------------------------===// 10360 // rebase table dumping 10361 //===----------------------------------------------------------------------===// 10362 10363 static void printMachORebaseTable(object::MachOObjectFile *Obj) { 10364 outs() << "segment section address type\n"; 10365 Error Err = Error::success(); 10366 for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) { 10367 StringRef SegmentName = Entry.segmentName(); 10368 StringRef SectionName = Entry.sectionName(); 10369 uint64_t Address = Entry.address(); 10370 10371 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 10372 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 10373 SegmentName.str().c_str(), SectionName.str().c_str(), 10374 Address, Entry.typeName().str().c_str()); 10375 } 10376 if (Err) 10377 reportError(std::move(Err), Obj->getFileName()); 10378 } 10379 10380 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 10381 StringRef DylibName; 10382 switch (Ordinal) { 10383 case MachO::BIND_SPECIAL_DYLIB_SELF: 10384 return "this-image"; 10385 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 10386 return "main-executable"; 10387 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 10388 return "flat-namespace"; 10389 case MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP: 10390 return "weak"; 10391 default: 10392 if (Ordinal > 0) { 10393 std::error_code EC = 10394 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 10395 if (EC) 10396 return "<<bad library ordinal>>"; 10397 return DylibName; 10398 } 10399 } 10400 return "<<unknown special ordinal>>"; 10401 } 10402 10403 //===----------------------------------------------------------------------===// 10404 // bind table dumping 10405 //===----------------------------------------------------------------------===// 10406 10407 static void printMachOBindTable(object::MachOObjectFile *Obj) { 10408 // Build table of sections so names can used in final output. 10409 outs() << "segment section address type " 10410 "addend dylib symbol\n"; 10411 Error Err = Error::success(); 10412 for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) { 10413 StringRef SegmentName = Entry.segmentName(); 10414 StringRef SectionName = Entry.sectionName(); 10415 uint64_t Address = Entry.address(); 10416 10417 // Table lines look like: 10418 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 10419 StringRef Attr; 10420 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 10421 Attr = " (weak_import)"; 10422 outs() << left_justify(SegmentName, 8) << " " 10423 << left_justify(SectionName, 18) << " " 10424 << format_hex(Address, 10, true) << " " 10425 << left_justify(Entry.typeName(), 8) << " " 10426 << format_decimal(Entry.addend(), 8) << " " 10427 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10428 << Entry.symbolName() << Attr << "\n"; 10429 } 10430 if (Err) 10431 reportError(std::move(Err), Obj->getFileName()); 10432 } 10433 10434 //===----------------------------------------------------------------------===// 10435 // lazy bind table dumping 10436 //===----------------------------------------------------------------------===// 10437 10438 static void printMachOLazyBindTable(object::MachOObjectFile *Obj) { 10439 outs() << "segment section address " 10440 "dylib symbol\n"; 10441 Error Err = Error::success(); 10442 for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) { 10443 StringRef SegmentName = Entry.segmentName(); 10444 StringRef SectionName = Entry.sectionName(); 10445 uint64_t Address = Entry.address(); 10446 10447 // Table lines look like: 10448 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 10449 outs() << left_justify(SegmentName, 8) << " " 10450 << left_justify(SectionName, 18) << " " 10451 << format_hex(Address, 10, true) << " " 10452 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 10453 << Entry.symbolName() << "\n"; 10454 } 10455 if (Err) 10456 reportError(std::move(Err), Obj->getFileName()); 10457 } 10458 10459 //===----------------------------------------------------------------------===// 10460 // weak bind table dumping 10461 //===----------------------------------------------------------------------===// 10462 10463 static void printMachOWeakBindTable(object::MachOObjectFile *Obj) { 10464 outs() << "segment section address " 10465 "type addend symbol\n"; 10466 Error Err = Error::success(); 10467 for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) { 10468 // Strong symbols don't have a location to update. 10469 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 10470 outs() << " strong " 10471 << Entry.symbolName() << "\n"; 10472 continue; 10473 } 10474 StringRef SegmentName = Entry.segmentName(); 10475 StringRef SectionName = Entry.sectionName(); 10476 uint64_t Address = Entry.address(); 10477 10478 // Table lines look like: 10479 // __DATA __data 0x00001000 pointer 0 _foo 10480 outs() << left_justify(SegmentName, 8) << " " 10481 << left_justify(SectionName, 18) << " " 10482 << format_hex(Address, 10, true) << " " 10483 << left_justify(Entry.typeName(), 8) << " " 10484 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 10485 << "\n"; 10486 } 10487 if (Err) 10488 reportError(std::move(Err), Obj->getFileName()); 10489 } 10490 10491 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 10492 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 10493 // information for that address. If the address is found its binding symbol 10494 // name is returned. If not nullptr is returned. 10495 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 10496 struct DisassembleInfo *info) { 10497 if (info->bindtable == nullptr) { 10498 info->bindtable = std::make_unique<SymbolAddressMap>(); 10499 Error Err = Error::success(); 10500 for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) { 10501 uint64_t Address = Entry.address(); 10502 StringRef name = Entry.symbolName(); 10503 if (!name.empty()) 10504 (*info->bindtable)[Address] = name; 10505 } 10506 if (Err) 10507 reportError(std::move(Err), info->O->getFileName()); 10508 } 10509 auto name = info->bindtable->lookup(ReferenceValue); 10510 return !name.empty() ? name.data() : nullptr; 10511 } 10512 10513 void objdump::printLazyBindTable(ObjectFile *o) { 10514 outs() << "\nLazy bind table:\n"; 10515 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10516 printMachOLazyBindTable(MachO); 10517 else 10518 WithColor::error() 10519 << "This operation is only currently supported " 10520 "for Mach-O executable files.\n"; 10521 } 10522 10523 void objdump::printWeakBindTable(ObjectFile *o) { 10524 outs() << "\nWeak bind table:\n"; 10525 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10526 printMachOWeakBindTable(MachO); 10527 else 10528 WithColor::error() 10529 << "This operation is only currently supported " 10530 "for Mach-O executable files.\n"; 10531 } 10532 10533 void objdump::printExportsTrie(const ObjectFile *o) { 10534 outs() << "\nExports trie:\n"; 10535 if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10536 printMachOExportsTrie(MachO); 10537 else 10538 WithColor::error() 10539 << "This operation is only currently supported " 10540 "for Mach-O executable files.\n"; 10541 } 10542 10543 void objdump::printRebaseTable(ObjectFile *o) { 10544 outs() << "\nRebase table:\n"; 10545 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10546 printMachORebaseTable(MachO); 10547 else 10548 WithColor::error() 10549 << "This operation is only currently supported " 10550 "for Mach-O executable files.\n"; 10551 } 10552 10553 void objdump::printBindTable(ObjectFile *o) { 10554 outs() << "\nBind table:\n"; 10555 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) 10556 printMachOBindTable(MachO); 10557 else 10558 WithColor::error() 10559 << "This operation is only currently supported " 10560 "for Mach-O executable files.\n"; 10561 } 10562