MachODump.cpp revision 4c5e43da7792f75567b693105cc53e3f1992ad98
1//===-- MachODump.cpp - Object file dumping utility for llvm --------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the MachO-specific dumper for llvm-objdump. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm-objdump.h" 15#include "llvm-c/Disassembler.h" 16#include "llvm/ADT/STLExtras.h" 17#include "llvm/ADT/StringExtras.h" 18#include "llvm/ADT/Triple.h" 19#include "llvm/Config/config.h" 20#include "llvm/DebugInfo/DWARF/DIContext.h" 21#include "llvm/MC/MCAsmInfo.h" 22#include "llvm/MC/MCContext.h" 23#include "llvm/MC/MCDisassembler.h" 24#include "llvm/MC/MCInst.h" 25#include "llvm/MC/MCInstPrinter.h" 26#include "llvm/MC/MCInstrDesc.h" 27#include "llvm/MC/MCInstrInfo.h" 28#include "llvm/MC/MCRegisterInfo.h" 29#include "llvm/MC/MCSubtargetInfo.h" 30#include "llvm/Object/MachO.h" 31#include "llvm/Object/MachOUniversal.h" 32#include "llvm/Support/Casting.h" 33#include "llvm/Support/CommandLine.h" 34#include "llvm/Support/Debug.h" 35#include "llvm/Support/Endian.h" 36#include "llvm/Support/Format.h" 37#include "llvm/Support/FormattedStream.h" 38#include "llvm/Support/GraphWriter.h" 39#include "llvm/Support/LEB128.h" 40#include "llvm/Support/MachO.h" 41#include "llvm/Support/MemoryBuffer.h" 42#include "llvm/Support/TargetRegistry.h" 43#include "llvm/Support/TargetSelect.h" 44#include "llvm/Support/raw_ostream.h" 45#include <algorithm> 46#include <cstring> 47#include <system_error> 48 49#if HAVE_CXXABI_H 50#include <cxxabi.h> 51#endif 52 53using namespace llvm; 54using namespace object; 55 56static cl::opt<bool> 57 UseDbg("g", 58 cl::desc("Print line information from debug info if available")); 59 60static cl::opt<std::string> DSYMFile("dsym", 61 cl::desc("Use .dSYM file for debug info")); 62 63static cl::opt<bool> FullLeadingAddr("full-leading-addr", 64 cl::desc("Print full leading address")); 65 66static cl::opt<bool> NoLeadingAddr("no-leading-addr", 67 cl::desc("Print no leading address")); 68 69static cl::opt<bool> 70 PrintImmHex("print-imm-hex", 71 cl::desc("Use hex format for immediate values")); 72 73cl::opt<bool> llvm::UniversalHeaders("universal-headers", 74 cl::desc("Print Mach-O universal headers " 75 "(requires -macho)")); 76 77cl::opt<bool> 78 llvm::ArchiveHeaders("archive-headers", 79 cl::desc("Print archive headers for Mach-O archives " 80 "(requires -macho)")); 81 82cl::opt<bool> 83 llvm::IndirectSymbols("indirect-symbols", 84 cl::desc("Print indirect symbol table for Mach-O " 85 "objects (requires -macho)")); 86 87cl::opt<bool> 88 llvm::DataInCode("data-in-code", 89 cl::desc("Print the data in code table for Mach-O objects " 90 "(requires -macho)")); 91 92cl::opt<bool> 93 llvm::LinkOptHints("link-opt-hints", 94 cl::desc("Print the linker optimization hints for " 95 "Mach-O objects (requires -macho)")); 96 97cl::list<std::string> 98 llvm::DumpSections("section", 99 cl::desc("Prints the specified segment,section for " 100 "Mach-O objects (requires -macho)")); 101 102cl::opt<bool> 103 llvm::InfoPlist("info-plist", 104 cl::desc("Print the info plist section as strings for " 105 "Mach-O objects (requires -macho)")); 106 107cl::opt<bool> 108 llvm::DylibsUsed("dylibs-used", 109 cl::desc("Print the shared libraries used for linked " 110 "Mach-O files (requires -macho)")); 111 112cl::opt<bool> 113 llvm::DylibId("dylib-id", 114 cl::desc("Print the shared library's id for the dylib Mach-O " 115 "file (requires -macho)")); 116 117cl::opt<bool> 118 llvm::NonVerbose("non-verbose", 119 cl::desc("Print the info for Mach-O objects in " 120 "non-verbose or numeric form (requires -macho)")); 121 122cl::opt<std::string> llvm::DisSymName( 123 "dis-symname", 124 cl::desc("disassemble just this symbol's instructions (requires -macho")); 125 126static cl::opt<bool> NoSymbolicOperands( 127 "no-symbolic-operands", 128 cl::desc("do not symbolic operands when disassembling (requires -macho)")); 129 130 131static cl::list<std::string> 132 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 133 cl::ZeroOrMore); 134bool ArchAll = false; 135 136static std::string ThumbTripleName; 137 138static const Target *GetTarget(const MachOObjectFile *MachOObj, 139 const char **McpuDefault, 140 const Target **ThumbTarget) { 141 // Figure out the target triple. 142 if (TripleName.empty()) { 143 llvm::Triple TT("unknown-unknown-unknown"); 144 llvm::Triple ThumbTriple = Triple(); 145 TT = MachOObj->getArch(McpuDefault, &ThumbTriple); 146 TripleName = TT.str(); 147 ThumbTripleName = ThumbTriple.str(); 148 } 149 150 // Get the target specific parser. 151 std::string Error; 152 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 153 if (TheTarget && ThumbTripleName.empty()) 154 return TheTarget; 155 156 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 157 if (*ThumbTarget) 158 return TheTarget; 159 160 errs() << "llvm-objdump: error: unable to get target for '"; 161 if (!TheTarget) 162 errs() << TripleName; 163 else 164 errs() << ThumbTripleName; 165 errs() << "', see --version and --triple.\n"; 166 return nullptr; 167} 168 169struct SymbolSorter { 170 bool operator()(const SymbolRef &A, const SymbolRef &B) { 171 SymbolRef::Type AType, BType; 172 A.getType(AType); 173 B.getType(BType); 174 175 uint64_t AAddr, BAddr; 176 if (AType != SymbolRef::ST_Function) 177 AAddr = 0; 178 else 179 A.getAddress(AAddr); 180 if (BType != SymbolRef::ST_Function) 181 BAddr = 0; 182 else 183 B.getAddress(BAddr); 184 return AAddr < BAddr; 185 } 186}; 187 188// Types for the storted data in code table that is built before disassembly 189// and the predicate function to sort them. 190typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 191typedef std::vector<DiceTableEntry> DiceTable; 192typedef DiceTable::iterator dice_table_iterator; 193 194// This is used to search for a data in code table entry for the PC being 195// disassembled. The j parameter has the PC in j.first. A single data in code 196// table entry can cover many bytes for each of its Kind's. So if the offset, 197// aka the i.first value, of the data in code table entry plus its Length 198// covers the PC being searched for this will return true. If not it will 199// return false. 200static bool compareDiceTableEntries(const DiceTableEntry &i, 201 const DiceTableEntry &j) { 202 uint16_t Length; 203 i.second.getLength(Length); 204 205 return j.first >= i.first && j.first < i.first + Length; 206} 207 208static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length, 209 unsigned short Kind) { 210 uint32_t Value, Size = 1; 211 212 switch (Kind) { 213 default: 214 case MachO::DICE_KIND_DATA: 215 if (Length >= 4) { 216 if (!NoShowRawInsn) 217 DumpBytes(ArrayRef<uint8_t>(bytes, 4)); 218 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 219 outs() << "\t.long " << Value; 220 Size = 4; 221 } else if (Length >= 2) { 222 if (!NoShowRawInsn) 223 DumpBytes(ArrayRef<uint8_t>(bytes, 2)); 224 Value = bytes[1] << 8 | bytes[0]; 225 outs() << "\t.short " << Value; 226 Size = 2; 227 } else { 228 if (!NoShowRawInsn) 229 DumpBytes(ArrayRef<uint8_t>(bytes, 2)); 230 Value = bytes[0]; 231 outs() << "\t.byte " << Value; 232 Size = 1; 233 } 234 if (Kind == MachO::DICE_KIND_DATA) 235 outs() << "\t@ KIND_DATA\n"; 236 else 237 outs() << "\t@ data in code kind = " << Kind << "\n"; 238 break; 239 case MachO::DICE_KIND_JUMP_TABLE8: 240 if (!NoShowRawInsn) 241 DumpBytes(ArrayRef<uint8_t>(bytes, 1)); 242 Value = bytes[0]; 243 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 244 Size = 1; 245 break; 246 case MachO::DICE_KIND_JUMP_TABLE16: 247 if (!NoShowRawInsn) 248 DumpBytes(ArrayRef<uint8_t>(bytes, 2)); 249 Value = bytes[1] << 8 | bytes[0]; 250 outs() << "\t.short " << format("%5u", Value & 0xffff) 251 << "\t@ KIND_JUMP_TABLE16\n"; 252 Size = 2; 253 break; 254 case MachO::DICE_KIND_JUMP_TABLE32: 255 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 256 if (!NoShowRawInsn) 257 DumpBytes(ArrayRef<uint8_t>(bytes, 4)); 258 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 259 outs() << "\t.long " << Value; 260 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 261 outs() << "\t@ KIND_JUMP_TABLE32\n"; 262 else 263 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 264 Size = 4; 265 break; 266 } 267 return Size; 268} 269 270static void getSectionsAndSymbols(const MachO::mach_header Header, 271 MachOObjectFile *MachOObj, 272 std::vector<SectionRef> &Sections, 273 std::vector<SymbolRef> &Symbols, 274 SmallVectorImpl<uint64_t> &FoundFns, 275 uint64_t &BaseSegmentAddress) { 276 for (const SymbolRef &Symbol : MachOObj->symbols()) { 277 StringRef SymName; 278 Symbol.getName(SymName); 279 if (!SymName.startswith("ltmp")) 280 Symbols.push_back(Symbol); 281 } 282 283 for (const SectionRef &Section : MachOObj->sections()) { 284 StringRef SectName; 285 Section.getName(SectName); 286 Sections.push_back(Section); 287 } 288 289 MachOObjectFile::LoadCommandInfo Command = 290 MachOObj->getFirstLoadCommandInfo(); 291 bool BaseSegmentAddressSet = false; 292 for (unsigned i = 0;; ++i) { 293 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 294 // We found a function starts segment, parse the addresses for later 295 // consumption. 296 MachO::linkedit_data_command LLC = 297 MachOObj->getLinkeditDataLoadCommand(Command); 298 299 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 300 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 301 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 302 StringRef SegName = SLC.segname; 303 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 304 BaseSegmentAddressSet = true; 305 BaseSegmentAddress = SLC.vmaddr; 306 } 307 } 308 309 if (i == Header.ncmds - 1) 310 break; 311 else 312 Command = MachOObj->getNextLoadCommandInfo(Command); 313 } 314} 315 316static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, 317 uint32_t n, uint32_t count, 318 uint32_t stride, uint64_t addr) { 319 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 320 uint32_t nindirectsyms = Dysymtab.nindirectsyms; 321 if (n > nindirectsyms) 322 outs() << " (entries start past the end of the indirect symbol " 323 "table) (reserved1 field greater than the table size)"; 324 else if (n + count > nindirectsyms) 325 outs() << " (entries extends past the end of the indirect symbol " 326 "table)"; 327 outs() << "\n"; 328 uint32_t cputype = O->getHeader().cputype; 329 if (cputype & MachO::CPU_ARCH_ABI64) 330 outs() << "address index"; 331 else 332 outs() << "address index"; 333 if (verbose) 334 outs() << " name\n"; 335 else 336 outs() << "\n"; 337 for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) { 338 if (cputype & MachO::CPU_ARCH_ABI64) 339 outs() << format("0x%016" PRIx64, addr + j * stride) << " "; 340 else 341 outs() << format("0x%08" PRIx32, addr + j * stride) << " "; 342 MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand(); 343 uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j); 344 if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) { 345 outs() << "LOCAL\n"; 346 continue; 347 } 348 if (indirect_symbol == 349 (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) { 350 outs() << "LOCAL ABSOLUTE\n"; 351 continue; 352 } 353 if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) { 354 outs() << "ABSOLUTE\n"; 355 continue; 356 } 357 outs() << format("%5u ", indirect_symbol); 358 if (verbose) { 359 MachO::symtab_command Symtab = O->getSymtabLoadCommand(); 360 if (indirect_symbol < Symtab.nsyms) { 361 symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); 362 SymbolRef Symbol = *Sym; 363 StringRef SymName; 364 Symbol.getName(SymName); 365 outs() << SymName; 366 } else { 367 outs() << "?"; 368 } 369 } 370 outs() << "\n"; 371 } 372} 373 374static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) { 375 uint32_t LoadCommandCount = O->getHeader().ncmds; 376 MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo(); 377 for (unsigned I = 0;; ++I) { 378 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 379 MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load); 380 for (unsigned J = 0; J < Seg.nsects; ++J) { 381 MachO::section_64 Sec = O->getSection64(Load, J); 382 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 383 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 384 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 385 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 386 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 387 section_type == MachO::S_SYMBOL_STUBS) { 388 uint32_t stride; 389 if (section_type == MachO::S_SYMBOL_STUBS) 390 stride = Sec.reserved2; 391 else 392 stride = 8; 393 if (stride == 0) { 394 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 395 << Sec.sectname << ") " 396 << "(size of stubs in reserved2 field is zero)\n"; 397 continue; 398 } 399 uint32_t count = Sec.size / stride; 400 outs() << "Indirect symbols for (" << Sec.segname << "," 401 << Sec.sectname << ") " << count << " entries"; 402 uint32_t n = Sec.reserved1; 403 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 404 } 405 } 406 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 407 MachO::segment_command Seg = O->getSegmentLoadCommand(Load); 408 for (unsigned J = 0; J < Seg.nsects; ++J) { 409 MachO::section Sec = O->getSection(Load, J); 410 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 411 if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 412 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 413 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 414 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 415 section_type == MachO::S_SYMBOL_STUBS) { 416 uint32_t stride; 417 if (section_type == MachO::S_SYMBOL_STUBS) 418 stride = Sec.reserved2; 419 else 420 stride = 4; 421 if (stride == 0) { 422 outs() << "Can't print indirect symbols for (" << Sec.segname << "," 423 << Sec.sectname << ") " 424 << "(size of stubs in reserved2 field is zero)\n"; 425 continue; 426 } 427 uint32_t count = Sec.size / stride; 428 outs() << "Indirect symbols for (" << Sec.segname << "," 429 << Sec.sectname << ") " << count << " entries"; 430 uint32_t n = Sec.reserved1; 431 PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr); 432 } 433 } 434 } 435 if (I == LoadCommandCount - 1) 436 break; 437 else 438 Load = O->getNextLoadCommandInfo(Load); 439 } 440} 441 442static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) { 443 MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand(); 444 uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry); 445 outs() << "Data in code table (" << nentries << " entries)\n"; 446 outs() << "offset length kind\n"; 447 for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE; 448 ++DI) { 449 uint32_t Offset; 450 DI->getOffset(Offset); 451 outs() << format("0x%08" PRIx32, Offset) << " "; 452 uint16_t Length; 453 DI->getLength(Length); 454 outs() << format("%6u", Length) << " "; 455 uint16_t Kind; 456 DI->getKind(Kind); 457 if (verbose) { 458 switch (Kind) { 459 case MachO::DICE_KIND_DATA: 460 outs() << "DATA"; 461 break; 462 case MachO::DICE_KIND_JUMP_TABLE8: 463 outs() << "JUMP_TABLE8"; 464 break; 465 case MachO::DICE_KIND_JUMP_TABLE16: 466 outs() << "JUMP_TABLE16"; 467 break; 468 case MachO::DICE_KIND_JUMP_TABLE32: 469 outs() << "JUMP_TABLE32"; 470 break; 471 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 472 outs() << "ABS_JUMP_TABLE32"; 473 break; 474 default: 475 outs() << format("0x%04" PRIx32, Kind); 476 break; 477 } 478 } else 479 outs() << format("0x%04" PRIx32, Kind); 480 outs() << "\n"; 481 } 482} 483 484static void PrintLinkOptHints(MachOObjectFile *O) { 485 MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand(); 486 const char *loh = O->getData().substr(LohLC.dataoff, 1).data(); 487 uint32_t nloh = LohLC.datasize; 488 outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n"; 489 for (uint32_t i = 0; i < nloh;) { 490 unsigned n; 491 uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n); 492 i += n; 493 outs() << " identifier " << identifier << " "; 494 if (i >= nloh) 495 return; 496 switch (identifier) { 497 case 1: 498 outs() << "AdrpAdrp\n"; 499 break; 500 case 2: 501 outs() << "AdrpLdr\n"; 502 break; 503 case 3: 504 outs() << "AdrpAddLdr\n"; 505 break; 506 case 4: 507 outs() << "AdrpLdrGotLdr\n"; 508 break; 509 case 5: 510 outs() << "AdrpAddStr\n"; 511 break; 512 case 6: 513 outs() << "AdrpLdrGotStr\n"; 514 break; 515 case 7: 516 outs() << "AdrpAdd\n"; 517 break; 518 case 8: 519 outs() << "AdrpLdrGot\n"; 520 break; 521 default: 522 outs() << "Unknown identifier value\n"; 523 break; 524 } 525 uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n); 526 i += n; 527 outs() << " narguments " << narguments << "\n"; 528 if (i >= nloh) 529 return; 530 531 for (uint32_t j = 0; j < narguments; j++) { 532 uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n); 533 i += n; 534 outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n"; 535 if (i >= nloh) 536 return; 537 } 538 } 539} 540 541static void PrintDylibs(MachOObjectFile *O, bool JustId) { 542 uint32_t LoadCommandCount = O->getHeader().ncmds; 543 MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo(); 544 for (unsigned I = 0;; ++I) { 545 if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) || 546 (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB || 547 Load.C.cmd == MachO::LC_LOAD_DYLIB || 548 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 549 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 550 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 551 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) { 552 MachO::dylib_command dl = O->getDylibIDLoadCommand(Load); 553 if (dl.dylib.name < dl.cmdsize) { 554 const char *p = (const char *)(Load.Ptr) + dl.dylib.name; 555 if (JustId) 556 outs() << p << "\n"; 557 else { 558 outs() << "\t" << p; 559 outs() << " (compatibility version " 560 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 561 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 562 << (dl.dylib.compatibility_version & 0xff) << ","; 563 outs() << " current version " 564 << ((dl.dylib.current_version >> 16) & 0xffff) << "." 565 << ((dl.dylib.current_version >> 8) & 0xff) << "." 566 << (dl.dylib.current_version & 0xff) << ")\n"; 567 } 568 } else { 569 outs() << "\tBad offset (" << dl.dylib.name << ") for name of "; 570 if (Load.C.cmd == MachO::LC_ID_DYLIB) 571 outs() << "LC_ID_DYLIB "; 572 else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) 573 outs() << "LC_LOAD_DYLIB "; 574 else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) 575 outs() << "LC_LOAD_WEAK_DYLIB "; 576 else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) 577 outs() << "LC_LAZY_LOAD_DYLIB "; 578 else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) 579 outs() << "LC_REEXPORT_DYLIB "; 580 else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 581 outs() << "LC_LOAD_UPWARD_DYLIB "; 582 else 583 outs() << "LC_??? "; 584 outs() << "command " << I << "\n"; 585 } 586 } 587 if (I == LoadCommandCount - 1) 588 break; 589 else 590 Load = O->getNextLoadCommandInfo(Load); 591 } 592} 593 594typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 595 596static void CreateSymbolAddressMap(MachOObjectFile *O, 597 SymbolAddressMap *AddrMap) { 598 // Create a map of symbol addresses to symbol names. 599 for (const SymbolRef &Symbol : O->symbols()) { 600 SymbolRef::Type ST; 601 Symbol.getType(ST); 602 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 603 ST == SymbolRef::ST_Other) { 604 uint64_t Address; 605 Symbol.getAddress(Address); 606 StringRef SymName; 607 Symbol.getName(SymName); 608 (*AddrMap)[Address] = SymName; 609 } 610 } 611} 612 613// GuessSymbolName is passed the address of what might be a symbol and a 614// pointer to the SymbolAddressMap. It returns the name of a symbol 615// with that address or nullptr if no symbol is found with that address. 616static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { 617 const char *SymbolName = nullptr; 618 // A DenseMap can't lookup up some values. 619 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 620 StringRef name = AddrMap->lookup(value); 621 if (!name.empty()) 622 SymbolName = name.data(); 623 } 624 return SymbolName; 625} 626 627static void DumpCstringChar(const char c) { 628 char p[2]; 629 p[0] = c; 630 p[1] = '\0'; 631 outs().write_escaped(p); 632} 633 634static void DumpCstringSection(MachOObjectFile *O, const char *sect, 635 uint32_t sect_size, uint64_t sect_addr, 636 bool print_addresses) { 637 for (uint32_t i = 0; i < sect_size; i++) { 638 if (print_addresses) { 639 if (O->is64Bit()) 640 outs() << format("%016" PRIx64, sect_addr + i) << " "; 641 else 642 outs() << format("%08" PRIx64, sect_addr + i) << " "; 643 } 644 for (; i < sect_size && sect[i] != '\0'; i++) 645 DumpCstringChar(sect[i]); 646 if (i < sect_size && sect[i] == '\0') 647 outs() << "\n"; 648 } 649} 650 651static void DumpLiteral4(uint32_t l, float f) { 652 outs() << format("0x%08" PRIx32, l); 653 if ((l & 0x7f800000) != 0x7f800000) 654 outs() << format(" (%.16e)\n", f); 655 else { 656 if (l == 0x7f800000) 657 outs() << " (+Infinity)\n"; 658 else if (l == 0xff800000) 659 outs() << " (-Infinity)\n"; 660 else if ((l & 0x00400000) == 0x00400000) 661 outs() << " (non-signaling Not-a-Number)\n"; 662 else 663 outs() << " (signaling Not-a-Number)\n"; 664 } 665} 666 667static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, 668 uint32_t sect_size, uint64_t sect_addr, 669 bool print_addresses) { 670 for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { 671 if (print_addresses) { 672 if (O->is64Bit()) 673 outs() << format("%016" PRIx64, sect_addr + i) << " "; 674 else 675 outs() << format("%08" PRIx64, sect_addr + i) << " "; 676 } 677 float f; 678 memcpy(&f, sect + i, sizeof(float)); 679 if (O->isLittleEndian() != sys::IsLittleEndianHost) 680 sys::swapByteOrder(f); 681 uint32_t l; 682 memcpy(&l, sect + i, sizeof(uint32_t)); 683 if (O->isLittleEndian() != sys::IsLittleEndianHost) 684 sys::swapByteOrder(l); 685 DumpLiteral4(l, f); 686 } 687} 688 689static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, 690 double d) { 691 outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); 692 uint32_t Hi, Lo; 693 if (O->isLittleEndian()) { 694 Hi = l1; 695 Lo = l0; 696 } else { 697 Hi = l0; 698 Lo = l1; 699 } 700 // Hi is the high word, so this is equivalent to if(isfinite(d)) 701 if ((Hi & 0x7ff00000) != 0x7ff00000) 702 outs() << format(" (%.16e)\n", d); 703 else { 704 if (Hi == 0x7ff00000 && Lo == 0) 705 outs() << " (+Infinity)\n"; 706 else if (Hi == 0xfff00000 && Lo == 0) 707 outs() << " (-Infinity)\n"; 708 else if ((Hi & 0x00080000) == 0x00080000) 709 outs() << " (non-signaling Not-a-Number)\n"; 710 else 711 outs() << " (signaling Not-a-Number)\n"; 712 } 713} 714 715static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, 716 uint32_t sect_size, uint64_t sect_addr, 717 bool print_addresses) { 718 for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { 719 if (print_addresses) { 720 if (O->is64Bit()) 721 outs() << format("%016" PRIx64, sect_addr + i) << " "; 722 else 723 outs() << format("%08" PRIx64, sect_addr + i) << " "; 724 } 725 double d; 726 memcpy(&d, sect + i, sizeof(double)); 727 if (O->isLittleEndian() != sys::IsLittleEndianHost) 728 sys::swapByteOrder(d); 729 uint32_t l0, l1; 730 memcpy(&l0, sect + i, sizeof(uint32_t)); 731 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 732 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 733 sys::swapByteOrder(l0); 734 sys::swapByteOrder(l1); 735 } 736 DumpLiteral8(O, l0, l1, d); 737 } 738} 739 740static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { 741 outs() << format("0x%08" PRIx32, l0) << " "; 742 outs() << format("0x%08" PRIx32, l1) << " "; 743 outs() << format("0x%08" PRIx32, l2) << " "; 744 outs() << format("0x%08" PRIx32, l3) << "\n"; 745} 746 747static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, 748 uint32_t sect_size, uint64_t sect_addr, 749 bool print_addresses) { 750 for (uint32_t i = 0; i < sect_size; i += 16) { 751 if (print_addresses) { 752 if (O->is64Bit()) 753 outs() << format("%016" PRIx64, sect_addr + i) << " "; 754 else 755 outs() << format("%08" PRIx64, sect_addr + i) << " "; 756 } 757 uint32_t l0, l1, l2, l3; 758 memcpy(&l0, sect + i, sizeof(uint32_t)); 759 memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); 760 memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); 761 memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); 762 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 763 sys::swapByteOrder(l0); 764 sys::swapByteOrder(l1); 765 sys::swapByteOrder(l2); 766 sys::swapByteOrder(l3); 767 } 768 DumpLiteral16(l0, l1, l2, l3); 769 } 770} 771 772static void DumpLiteralPointerSection(MachOObjectFile *O, 773 const SectionRef &Section, 774 const char *sect, uint32_t sect_size, 775 uint64_t sect_addr, 776 bool print_addresses) { 777 // Collect the literal sections in this Mach-O file. 778 std::vector<SectionRef> LiteralSections; 779 for (const SectionRef &Section : O->sections()) { 780 DataRefImpl Ref = Section.getRawDataRefImpl(); 781 uint32_t section_type; 782 if (O->is64Bit()) { 783 const MachO::section_64 Sec = O->getSection64(Ref); 784 section_type = Sec.flags & MachO::SECTION_TYPE; 785 } else { 786 const MachO::section Sec = O->getSection(Ref); 787 section_type = Sec.flags & MachO::SECTION_TYPE; 788 } 789 if (section_type == MachO::S_CSTRING_LITERALS || 790 section_type == MachO::S_4BYTE_LITERALS || 791 section_type == MachO::S_8BYTE_LITERALS || 792 section_type == MachO::S_16BYTE_LITERALS) 793 LiteralSections.push_back(Section); 794 } 795 796 // Set the size of the literal pointer. 797 uint32_t lp_size = O->is64Bit() ? 8 : 4; 798 799 // Collect the external relocation symbols for the the literal pointers. 800 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 801 for (const RelocationRef &Reloc : Section.relocations()) { 802 DataRefImpl Rel; 803 MachO::any_relocation_info RE; 804 bool isExtern = false; 805 Rel = Reloc.getRawDataRefImpl(); 806 RE = O->getRelocation(Rel); 807 isExtern = O->getPlainRelocationExternal(RE); 808 if (isExtern) { 809 uint64_t RelocOffset; 810 Reloc.getOffset(RelocOffset); 811 symbol_iterator RelocSym = Reloc.getSymbol(); 812 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 813 } 814 } 815 array_pod_sort(Relocs.begin(), Relocs.end()); 816 817 // Dump each literal pointer. 818 for (uint32_t i = 0; i < sect_size; i += lp_size) { 819 if (print_addresses) { 820 if (O->is64Bit()) 821 outs() << format("%016" PRIx64, sect_addr + i) << " "; 822 else 823 outs() << format("%08" PRIx64, sect_addr + i) << " "; 824 } 825 uint64_t lp; 826 if (O->is64Bit()) { 827 memcpy(&lp, sect + i, sizeof(uint64_t)); 828 if (O->isLittleEndian() != sys::IsLittleEndianHost) 829 sys::swapByteOrder(lp); 830 } else { 831 uint32_t li; 832 memcpy(&li, sect + i, sizeof(uint32_t)); 833 if (O->isLittleEndian() != sys::IsLittleEndianHost) 834 sys::swapByteOrder(li); 835 lp = li; 836 } 837 838 // First look for an external relocation entry for this literal pointer. 839 auto Reloc = std::find_if( 840 Relocs.begin(), Relocs.end(), 841 [&](const std::pair<uint64_t, SymbolRef> &P) { return P.first == i; }); 842 if (Reloc != Relocs.end()) { 843 symbol_iterator RelocSym = Reloc->second; 844 StringRef SymName; 845 RelocSym->getName(SymName); 846 outs() << "external relocation entry for symbol:" << SymName << "\n"; 847 continue; 848 } 849 850 // For local references see what the section the literal pointer points to. 851 auto Sect = std::find_if(LiteralSections.begin(), LiteralSections.end(), 852 [&](const SectionRef &R) { 853 return lp >= R.getAddress() && 854 lp < R.getAddress() + R.getSize(); 855 }); 856 if (Sect == LiteralSections.end()) { 857 outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; 858 continue; 859 } 860 861 uint64_t SectAddress = Sect->getAddress(); 862 uint64_t SectSize = Sect->getSize(); 863 864 StringRef SectName; 865 Sect->getName(SectName); 866 DataRefImpl Ref = Sect->getRawDataRefImpl(); 867 StringRef SegmentName = O->getSectionFinalSegmentName(Ref); 868 outs() << SegmentName << ":" << SectName << ":"; 869 870 uint32_t section_type; 871 if (O->is64Bit()) { 872 const MachO::section_64 Sec = O->getSection64(Ref); 873 section_type = Sec.flags & MachO::SECTION_TYPE; 874 } else { 875 const MachO::section Sec = O->getSection(Ref); 876 section_type = Sec.flags & MachO::SECTION_TYPE; 877 } 878 879 StringRef BytesStr; 880 Sect->getContents(BytesStr); 881 const char *Contents = reinterpret_cast<const char *>(BytesStr.data()); 882 883 switch (section_type) { 884 case MachO::S_CSTRING_LITERALS: 885 for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0'; 886 i++) { 887 DumpCstringChar(Contents[i]); 888 } 889 outs() << "\n"; 890 break; 891 case MachO::S_4BYTE_LITERALS: 892 float f; 893 memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); 894 uint32_t l; 895 memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); 896 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 897 sys::swapByteOrder(f); 898 sys::swapByteOrder(l); 899 } 900 DumpLiteral4(l, f); 901 break; 902 case MachO::S_8BYTE_LITERALS: { 903 double d; 904 memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); 905 uint32_t l0, l1; 906 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 907 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 908 sizeof(uint32_t)); 909 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 910 sys::swapByteOrder(f); 911 sys::swapByteOrder(l0); 912 sys::swapByteOrder(l1); 913 } 914 DumpLiteral8(O, l0, l1, d); 915 break; 916 } 917 case MachO::S_16BYTE_LITERALS: { 918 uint32_t l0, l1, l2, l3; 919 memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); 920 memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), 921 sizeof(uint32_t)); 922 memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), 923 sizeof(uint32_t)); 924 memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), 925 sizeof(uint32_t)); 926 if (O->isLittleEndian() != sys::IsLittleEndianHost) { 927 sys::swapByteOrder(l0); 928 sys::swapByteOrder(l1); 929 sys::swapByteOrder(l2); 930 sys::swapByteOrder(l3); 931 } 932 DumpLiteral16(l0, l1, l2, l3); 933 break; 934 } 935 } 936 } 937} 938 939static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect, 940 uint32_t sect_size, uint64_t sect_addr, 941 SymbolAddressMap *AddrMap, 942 bool verbose) { 943 uint32_t stride; 944 if (O->is64Bit()) 945 stride = sizeof(uint64_t); 946 else 947 stride = sizeof(uint32_t); 948 for (uint32_t i = 0; i < sect_size; i += stride) { 949 const char *SymbolName = nullptr; 950 if (O->is64Bit()) { 951 outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " "; 952 uint64_t pointer_value; 953 memcpy(&pointer_value, sect + i, stride); 954 if (O->isLittleEndian() != sys::IsLittleEndianHost) 955 sys::swapByteOrder(pointer_value); 956 outs() << format("0x%016" PRIx64, pointer_value); 957 if (verbose) 958 SymbolName = GuessSymbolName(pointer_value, AddrMap); 959 } else { 960 outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " "; 961 uint32_t pointer_value; 962 memcpy(&pointer_value, sect + i, stride); 963 if (O->isLittleEndian() != sys::IsLittleEndianHost) 964 sys::swapByteOrder(pointer_value); 965 outs() << format("0x%08" PRIx32, pointer_value); 966 if (verbose) 967 SymbolName = GuessSymbolName(pointer_value, AddrMap); 968 } 969 if (SymbolName) 970 outs() << " " << SymbolName; 971 outs() << "\n"; 972 } 973} 974 975static void DumpRawSectionContents(MachOObjectFile *O, const char *sect, 976 uint32_t size, uint64_t addr) { 977 uint32_t cputype = O->getHeader().cputype; 978 if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) { 979 uint32_t j; 980 for (uint32_t i = 0; i < size; i += j, addr += j) { 981 if (O->is64Bit()) 982 outs() << format("%016" PRIx64, addr) << "\t"; 983 else 984 outs() << format("%08" PRIx64, addr) << "\t"; 985 for (j = 0; j < 16 && i + j < size; j++) { 986 uint8_t byte_word = *(sect + i + j); 987 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 988 } 989 outs() << "\n"; 990 } 991 } else { 992 uint32_t j; 993 for (uint32_t i = 0; i < size; i += j, addr += j) { 994 if (O->is64Bit()) 995 outs() << format("%016" PRIx64, addr) << "\t"; 996 else 997 outs() << format("%08" PRIx64, sect) << "\t"; 998 for (j = 0; j < 4 * sizeof(int32_t) && i + j < size; 999 j += sizeof(int32_t)) { 1000 if (i + j + sizeof(int32_t) < size) { 1001 uint32_t long_word; 1002 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 1003 if (O->isLittleEndian() != sys::IsLittleEndianHost) 1004 sys::swapByteOrder(long_word); 1005 outs() << format("%08" PRIx32, long_word) << " "; 1006 } else { 1007 for (uint32_t k = 0; i + j + k < size; k++) { 1008 uint8_t byte_word = *(sect + i + j); 1009 outs() << format("%02" PRIx32, (uint32_t)byte_word) << " "; 1010 } 1011 } 1012 } 1013 outs() << "\n"; 1014 } 1015 } 1016} 1017 1018static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 1019 StringRef DisSegName, StringRef DisSectName); 1020 1021static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, 1022 bool verbose) { 1023 SymbolAddressMap AddrMap; 1024 if (verbose) 1025 CreateSymbolAddressMap(O, &AddrMap); 1026 1027 for (unsigned i = 0; i < DumpSections.size(); ++i) { 1028 StringRef DumpSection = DumpSections[i]; 1029 std::pair<StringRef, StringRef> DumpSegSectName; 1030 DumpSegSectName = DumpSection.split(','); 1031 StringRef DumpSegName, DumpSectName; 1032 if (DumpSegSectName.second.size()) { 1033 DumpSegName = DumpSegSectName.first; 1034 DumpSectName = DumpSegSectName.second; 1035 } else { 1036 DumpSegName = ""; 1037 DumpSectName = DumpSegSectName.first; 1038 } 1039 for (const SectionRef &Section : O->sections()) { 1040 StringRef SectName; 1041 Section.getName(SectName); 1042 DataRefImpl Ref = Section.getRawDataRefImpl(); 1043 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1044 if ((DumpSegName.empty() || SegName == DumpSegName) && 1045 (SectName == DumpSectName)) { 1046 outs() << "Contents of (" << SegName << "," << SectName 1047 << ") section\n"; 1048 uint32_t section_flags; 1049 if (O->is64Bit()) { 1050 const MachO::section_64 Sec = O->getSection64(Ref); 1051 section_flags = Sec.flags; 1052 1053 } else { 1054 const MachO::section Sec = O->getSection(Ref); 1055 section_flags = Sec.flags; 1056 } 1057 uint32_t section_type = section_flags & MachO::SECTION_TYPE; 1058 1059 StringRef BytesStr; 1060 Section.getContents(BytesStr); 1061 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1062 uint32_t sect_size = BytesStr.size(); 1063 uint64_t sect_addr = Section.getAddress(); 1064 1065 if (verbose) { 1066 if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) || 1067 (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) { 1068 DisassembleMachO(Filename, O, SegName, SectName); 1069 continue; 1070 } 1071 if (SegName == "__TEXT" && SectName == "__info_plist") { 1072 outs() << sect; 1073 continue; 1074 } 1075 switch (section_type) { 1076 case MachO::S_REGULAR: 1077 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1078 break; 1079 case MachO::S_ZEROFILL: 1080 outs() << "zerofill section and has no contents in the file\n"; 1081 break; 1082 case MachO::S_CSTRING_LITERALS: 1083 DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1084 break; 1085 case MachO::S_4BYTE_LITERALS: 1086 DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1087 break; 1088 case MachO::S_8BYTE_LITERALS: 1089 DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1090 break; 1091 case MachO::S_16BYTE_LITERALS: 1092 DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr); 1093 break; 1094 case MachO::S_LITERAL_POINTERS: 1095 DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, 1096 !NoLeadingAddr); 1097 break; 1098 case MachO::S_MOD_INIT_FUNC_POINTERS: 1099 case MachO::S_MOD_TERM_FUNC_POINTERS: 1100 DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap, 1101 verbose); 1102 break; 1103 default: 1104 outs() << "Unknown section type (" 1105 << format("0x%08" PRIx32, section_type) << ")\n"; 1106 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1107 break; 1108 } 1109 } else { 1110 if (section_type == MachO::S_ZEROFILL) 1111 outs() << "zerofill section and has no contents in the file\n"; 1112 else 1113 DumpRawSectionContents(O, sect, sect_size, sect_addr); 1114 } 1115 } 1116 } 1117 } 1118} 1119 1120static void DumpInfoPlistSectionContents(StringRef Filename, 1121 MachOObjectFile *O) { 1122 for (const SectionRef &Section : O->sections()) { 1123 StringRef SectName; 1124 Section.getName(SectName); 1125 DataRefImpl Ref = Section.getRawDataRefImpl(); 1126 StringRef SegName = O->getSectionFinalSegmentName(Ref); 1127 if (SegName == "__TEXT" && SectName == "__info_plist") { 1128 outs() << "Contents of (" << SegName << "," << SectName << ") section\n"; 1129 StringRef BytesStr; 1130 Section.getContents(BytesStr); 1131 const char *sect = reinterpret_cast<const char *>(BytesStr.data()); 1132 outs() << sect; 1133 return; 1134 } 1135 } 1136} 1137 1138// checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 1139// and if it is and there is a list of architecture flags is specified then 1140// check to make sure this Mach-O file is one of those architectures or all 1141// architectures were specified. If not then an error is generated and this 1142// routine returns false. Else it returns true. 1143static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 1144 if (isa<MachOObjectFile>(O) && !ArchAll && ArchFlags.size() != 0) { 1145 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O); 1146 bool ArchFound = false; 1147 MachO::mach_header H; 1148 MachO::mach_header_64 H_64; 1149 Triple T; 1150 if (MachO->is64Bit()) { 1151 H_64 = MachO->MachOObjectFile::getHeader64(); 1152 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype); 1153 } else { 1154 H = MachO->MachOObjectFile::getHeader(); 1155 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype); 1156 } 1157 unsigned i; 1158 for (i = 0; i < ArchFlags.size(); ++i) { 1159 if (ArchFlags[i] == T.getArchName()) 1160 ArchFound = true; 1161 break; 1162 } 1163 if (!ArchFound) { 1164 errs() << "llvm-objdump: file: " + Filename + " does not contain " 1165 << "architecture: " + ArchFlags[i] + "\n"; 1166 return false; 1167 } 1168 } 1169 return true; 1170} 1171 1172// ProcessMachO() is passed a single opened Mach-O file, which may be an 1173// archive member and or in a slice of a universal file. It prints the 1174// the file name and header info and then processes it according to the 1175// command line options. 1176static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, 1177 StringRef ArchiveMemberName = StringRef(), 1178 StringRef ArchitectureName = StringRef()) { 1179 // If we are doing some processing here on the Mach-O file print the header 1180 // info. And don't print it otherwise like in the case of printing the 1181 // UniversalHeaders or ArchiveHeaders. 1182 if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || 1183 LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints || 1184 DylibsUsed || DylibId || DumpSections.size() != 0) { 1185 outs() << Filename; 1186 if (!ArchiveMemberName.empty()) 1187 outs() << '(' << ArchiveMemberName << ')'; 1188 if (!ArchitectureName.empty()) 1189 outs() << " (architecture " << ArchitectureName << ")"; 1190 outs() << ":\n"; 1191 } 1192 1193 if (Disassemble) 1194 DisassembleMachO(Filename, MachOOF, "__TEXT", "__text"); 1195 if (IndirectSymbols) 1196 PrintIndirectSymbols(MachOOF, !NonVerbose); 1197 if (DataInCode) 1198 PrintDataInCodeTable(MachOOF, !NonVerbose); 1199 if (LinkOptHints) 1200 PrintLinkOptHints(MachOOF); 1201 if (Relocations) 1202 PrintRelocations(MachOOF); 1203 if (SectionHeaders) 1204 PrintSectionHeaders(MachOOF); 1205 if (SectionContents) 1206 PrintSectionContents(MachOOF); 1207 if (DumpSections.size() != 0) 1208 DumpSectionContents(Filename, MachOOF, !NonVerbose); 1209 if (InfoPlist) 1210 DumpInfoPlistSectionContents(Filename, MachOOF); 1211 if (DylibsUsed) 1212 PrintDylibs(MachOOF, false); 1213 if (DylibId) 1214 PrintDylibs(MachOOF, true); 1215 if (SymbolTable) 1216 PrintSymbolTable(MachOOF); 1217 if (UnwindInfo) 1218 printMachOUnwindInfo(MachOOF); 1219 if (PrivateHeaders) 1220 printMachOFileHeader(MachOOF); 1221 if (ExportsTrie) 1222 printExportsTrie(MachOOF); 1223 if (Rebase) 1224 printRebaseTable(MachOOF); 1225 if (Bind) 1226 printBindTable(MachOOF); 1227 if (LazyBind) 1228 printLazyBindTable(MachOOF); 1229 if (WeakBind) 1230 printWeakBindTable(MachOOF); 1231} 1232 1233// printUnknownCPUType() helps print_fat_headers for unknown CPU's. 1234static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) { 1235 outs() << " cputype (" << cputype << ")\n"; 1236 outs() << " cpusubtype (" << cpusubtype << ")\n"; 1237} 1238 1239// printCPUType() helps print_fat_headers by printing the cputype and 1240// pusubtype (symbolically for the one's it knows about). 1241static void printCPUType(uint32_t cputype, uint32_t cpusubtype) { 1242 switch (cputype) { 1243 case MachO::CPU_TYPE_I386: 1244 switch (cpusubtype) { 1245 case MachO::CPU_SUBTYPE_I386_ALL: 1246 outs() << " cputype CPU_TYPE_I386\n"; 1247 outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n"; 1248 break; 1249 default: 1250 printUnknownCPUType(cputype, cpusubtype); 1251 break; 1252 } 1253 break; 1254 case MachO::CPU_TYPE_X86_64: 1255 switch (cpusubtype) { 1256 case MachO::CPU_SUBTYPE_X86_64_ALL: 1257 outs() << " cputype CPU_TYPE_X86_64\n"; 1258 outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n"; 1259 break; 1260 case MachO::CPU_SUBTYPE_X86_64_H: 1261 outs() << " cputype CPU_TYPE_X86_64\n"; 1262 outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n"; 1263 break; 1264 default: 1265 printUnknownCPUType(cputype, cpusubtype); 1266 break; 1267 } 1268 break; 1269 case MachO::CPU_TYPE_ARM: 1270 switch (cpusubtype) { 1271 case MachO::CPU_SUBTYPE_ARM_ALL: 1272 outs() << " cputype CPU_TYPE_ARM\n"; 1273 outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n"; 1274 break; 1275 case MachO::CPU_SUBTYPE_ARM_V4T: 1276 outs() << " cputype CPU_TYPE_ARM\n"; 1277 outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n"; 1278 break; 1279 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1280 outs() << " cputype CPU_TYPE_ARM\n"; 1281 outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n"; 1282 break; 1283 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1284 outs() << " cputype CPU_TYPE_ARM\n"; 1285 outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n"; 1286 break; 1287 case MachO::CPU_SUBTYPE_ARM_V6: 1288 outs() << " cputype CPU_TYPE_ARM\n"; 1289 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n"; 1290 break; 1291 case MachO::CPU_SUBTYPE_ARM_V6M: 1292 outs() << " cputype CPU_TYPE_ARM\n"; 1293 outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n"; 1294 break; 1295 case MachO::CPU_SUBTYPE_ARM_V7: 1296 outs() << " cputype CPU_TYPE_ARM\n"; 1297 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n"; 1298 break; 1299 case MachO::CPU_SUBTYPE_ARM_V7EM: 1300 outs() << " cputype CPU_TYPE_ARM\n"; 1301 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n"; 1302 break; 1303 case MachO::CPU_SUBTYPE_ARM_V7K: 1304 outs() << " cputype CPU_TYPE_ARM\n"; 1305 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n"; 1306 break; 1307 case MachO::CPU_SUBTYPE_ARM_V7M: 1308 outs() << " cputype CPU_TYPE_ARM\n"; 1309 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n"; 1310 break; 1311 case MachO::CPU_SUBTYPE_ARM_V7S: 1312 outs() << " cputype CPU_TYPE_ARM\n"; 1313 outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n"; 1314 break; 1315 default: 1316 printUnknownCPUType(cputype, cpusubtype); 1317 break; 1318 } 1319 break; 1320 case MachO::CPU_TYPE_ARM64: 1321 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 1322 case MachO::CPU_SUBTYPE_ARM64_ALL: 1323 outs() << " cputype CPU_TYPE_ARM64\n"; 1324 outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n"; 1325 break; 1326 default: 1327 printUnknownCPUType(cputype, cpusubtype); 1328 break; 1329 } 1330 break; 1331 default: 1332 printUnknownCPUType(cputype, cpusubtype); 1333 break; 1334 } 1335} 1336 1337static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, 1338 bool verbose) { 1339 outs() << "Fat headers\n"; 1340 if (verbose) 1341 outs() << "fat_magic FAT_MAGIC\n"; 1342 else 1343 outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n"; 1344 1345 uint32_t nfat_arch = UB->getNumberOfObjects(); 1346 StringRef Buf = UB->getData(); 1347 uint64_t size = Buf.size(); 1348 uint64_t big_size = sizeof(struct MachO::fat_header) + 1349 nfat_arch * sizeof(struct MachO::fat_arch); 1350 outs() << "nfat_arch " << UB->getNumberOfObjects(); 1351 if (nfat_arch == 0) 1352 outs() << " (malformed, contains zero architecture types)\n"; 1353 else if (big_size > size) 1354 outs() << " (malformed, architectures past end of file)\n"; 1355 else 1356 outs() << "\n"; 1357 1358 for (uint32_t i = 0; i < nfat_arch; ++i) { 1359 MachOUniversalBinary::ObjectForArch OFA(UB, i); 1360 uint32_t cputype = OFA.getCPUType(); 1361 uint32_t cpusubtype = OFA.getCPUSubType(); 1362 outs() << "architecture "; 1363 for (uint32_t j = 0; i != 0 && j <= i - 1; j++) { 1364 MachOUniversalBinary::ObjectForArch other_OFA(UB, j); 1365 uint32_t other_cputype = other_OFA.getCPUType(); 1366 uint32_t other_cpusubtype = other_OFA.getCPUSubType(); 1367 if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype && 1368 (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) == 1369 (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) { 1370 outs() << "(illegal duplicate architecture) "; 1371 break; 1372 } 1373 } 1374 if (verbose) { 1375 outs() << OFA.getArchTypeName() << "\n"; 1376 printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 1377 } else { 1378 outs() << i << "\n"; 1379 outs() << " cputype " << cputype << "\n"; 1380 outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) 1381 << "\n"; 1382 } 1383 if (verbose && 1384 (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) 1385 outs() << " capabilities CPU_SUBTYPE_LIB64\n"; 1386 else 1387 outs() << " capabilities " 1388 << format("0x%" PRIx32, 1389 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n"; 1390 outs() << " offset " << OFA.getOffset(); 1391 if (OFA.getOffset() > size) 1392 outs() << " (past end of file)"; 1393 if (OFA.getOffset() % (1 << OFA.getAlign()) != 0) 1394 outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")"; 1395 outs() << "\n"; 1396 outs() << " size " << OFA.getSize(); 1397 big_size = OFA.getOffset() + OFA.getSize(); 1398 if (big_size > size) 1399 outs() << " (past end of file)"; 1400 outs() << "\n"; 1401 outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign()) 1402 << ")\n"; 1403 } 1404} 1405 1406static void printArchiveChild(Archive::Child &C, bool verbose, 1407 bool print_offset) { 1408 if (print_offset) 1409 outs() << C.getChildOffset() << "\t"; 1410 sys::fs::perms Mode = C.getAccessMode(); 1411 if (verbose) { 1412 // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. 1413 // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. 1414 outs() << "-"; 1415 if (Mode & sys::fs::owner_read) 1416 outs() << "r"; 1417 else 1418 outs() << "-"; 1419 if (Mode & sys::fs::owner_write) 1420 outs() << "w"; 1421 else 1422 outs() << "-"; 1423 if (Mode & sys::fs::owner_exe) 1424 outs() << "x"; 1425 else 1426 outs() << "-"; 1427 if (Mode & sys::fs::group_read) 1428 outs() << "r"; 1429 else 1430 outs() << "-"; 1431 if (Mode & sys::fs::group_write) 1432 outs() << "w"; 1433 else 1434 outs() << "-"; 1435 if (Mode & sys::fs::group_exe) 1436 outs() << "x"; 1437 else 1438 outs() << "-"; 1439 if (Mode & sys::fs::others_read) 1440 outs() << "r"; 1441 else 1442 outs() << "-"; 1443 if (Mode & sys::fs::others_write) 1444 outs() << "w"; 1445 else 1446 outs() << "-"; 1447 if (Mode & sys::fs::others_exe) 1448 outs() << "x"; 1449 else 1450 outs() << "-"; 1451 } else { 1452 outs() << format("0%o ", Mode); 1453 } 1454 1455 unsigned UID = C.getUID(); 1456 outs() << format("%3d/", UID); 1457 unsigned GID = C.getGID(); 1458 outs() << format("%-3d ", GID); 1459 uint64_t Size = C.getRawSize(); 1460 outs() << format("%5" PRId64, Size) << " "; 1461 1462 StringRef RawLastModified = C.getRawLastModified(); 1463 if (verbose) { 1464 unsigned Seconds; 1465 if (RawLastModified.getAsInteger(10, Seconds)) 1466 outs() << "(date: \"%s\" contains non-decimal chars) " << RawLastModified; 1467 else { 1468 // Since cime(3) returns a 26 character string of the form: 1469 // "Sun Sep 16 01:03:52 1973\n\0" 1470 // just print 24 characters. 1471 time_t t = Seconds; 1472 outs() << format("%.24s ", ctime(&t)); 1473 } 1474 } else { 1475 outs() << RawLastModified << " "; 1476 } 1477 1478 if (verbose) { 1479 ErrorOr<StringRef> NameOrErr = C.getName(); 1480 if (NameOrErr.getError()) { 1481 StringRef RawName = C.getRawName(); 1482 outs() << RawName << "\n"; 1483 } else { 1484 StringRef Name = NameOrErr.get(); 1485 outs() << Name << "\n"; 1486 } 1487 } else { 1488 StringRef RawName = C.getRawName(); 1489 outs() << RawName << "\n"; 1490 } 1491} 1492 1493static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) { 1494 if (A->hasSymbolTable()) { 1495 Archive::child_iterator S = A->getSymbolTableChild(); 1496 Archive::Child C = *S; 1497 printArchiveChild(C, verbose, print_offset); 1498 } 1499 for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E; 1500 ++I) { 1501 Archive::Child C = *I; 1502 printArchiveChild(C, verbose, print_offset); 1503 } 1504} 1505 1506// ParseInputMachO() parses the named Mach-O file in Filename and handles the 1507// -arch flags selecting just those slices as specified by them and also parses 1508// archive files. Then for each individual Mach-O file ProcessMachO() is 1509// called to process the file based on the command line options. 1510void llvm::ParseInputMachO(StringRef Filename) { 1511 // Check for -arch all and verifiy the -arch flags are valid. 1512 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 1513 if (ArchFlags[i] == "all") { 1514 ArchAll = true; 1515 } else { 1516 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 1517 errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] + 1518 "'for the -arch option\n"; 1519 return; 1520 } 1521 } 1522 } 1523 1524 // Attempt to open the binary. 1525 ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 1526 if (std::error_code EC = BinaryOrErr.getError()) { 1527 errs() << "llvm-objdump: '" << Filename << "': " << EC.message() << ".\n"; 1528 return; 1529 } 1530 Binary &Bin = *BinaryOrErr.get().getBinary(); 1531 1532 if (Archive *A = dyn_cast<Archive>(&Bin)) { 1533 outs() << "Archive : " << Filename << "\n"; 1534 if (ArchiveHeaders) 1535 printArchiveHeaders(A, true, false); 1536 for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); 1537 I != E; ++I) { 1538 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = I->getAsBinary(); 1539 if (ChildOrErr.getError()) 1540 continue; 1541 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 1542 if (!checkMachOAndArchFlags(O, Filename)) 1543 return; 1544 ProcessMachO(Filename, O, O->getFileName()); 1545 } 1546 } 1547 return; 1548 } 1549 if (UniversalHeaders) { 1550 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) 1551 printMachOUniversalHeaders(UB, !NonVerbose); 1552 } 1553 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 1554 // If we have a list of architecture flags specified dump only those. 1555 if (!ArchAll && ArchFlags.size() != 0) { 1556 // Look for a slice in the universal binary that matches each ArchFlag. 1557 bool ArchFound; 1558 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 1559 ArchFound = false; 1560 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 1561 E = UB->end_objects(); 1562 I != E; ++I) { 1563 if (ArchFlags[i] == I->getArchTypeName()) { 1564 ArchFound = true; 1565 ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = 1566 I->getAsObjectFile(); 1567 std::string ArchitectureName = ""; 1568 if (ArchFlags.size() > 1) 1569 ArchitectureName = I->getArchTypeName(); 1570 if (ObjOrErr) { 1571 ObjectFile &O = *ObjOrErr.get(); 1572 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 1573 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 1574 } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = 1575 I->getAsArchive()) { 1576 std::unique_ptr<Archive> &A = *AOrErr; 1577 outs() << "Archive : " << Filename; 1578 if (!ArchitectureName.empty()) 1579 outs() << " (architecture " << ArchitectureName << ")"; 1580 outs() << "\n"; 1581 if (ArchiveHeaders) 1582 printArchiveHeaders(A.get(), true, false); 1583 for (Archive::child_iterator AI = A->child_begin(), 1584 AE = A->child_end(); 1585 AI != AE; ++AI) { 1586 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary(); 1587 if (ChildOrErr.getError()) 1588 continue; 1589 if (MachOObjectFile *O = 1590 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 1591 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName); 1592 } 1593 } 1594 } 1595 } 1596 if (!ArchFound) { 1597 errs() << "llvm-objdump: file: " + Filename + " does not contain " 1598 << "architecture: " + ArchFlags[i] + "\n"; 1599 return; 1600 } 1601 } 1602 return; 1603 } 1604 // No architecture flags were specified so if this contains a slice that 1605 // matches the host architecture dump only that. 1606 if (!ArchAll) { 1607 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 1608 E = UB->end_objects(); 1609 I != E; ++I) { 1610 if (MachOObjectFile::getHostArch().getArchName() == 1611 I->getArchTypeName()) { 1612 ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 1613 std::string ArchiveName; 1614 ArchiveName.clear(); 1615 if (ObjOrErr) { 1616 ObjectFile &O = *ObjOrErr.get(); 1617 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 1618 ProcessMachO(Filename, MachOOF); 1619 } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = 1620 I->getAsArchive()) { 1621 std::unique_ptr<Archive> &A = *AOrErr; 1622 outs() << "Archive : " << Filename << "\n"; 1623 if (ArchiveHeaders) 1624 printArchiveHeaders(A.get(), true, false); 1625 for (Archive::child_iterator AI = A->child_begin(), 1626 AE = A->child_end(); 1627 AI != AE; ++AI) { 1628 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary(); 1629 if (ChildOrErr.getError()) 1630 continue; 1631 if (MachOObjectFile *O = 1632 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 1633 ProcessMachO(Filename, O, O->getFileName()); 1634 } 1635 } 1636 return; 1637 } 1638 } 1639 } 1640 // Either all architectures have been specified or none have been specified 1641 // and this does not contain the host architecture so dump all the slices. 1642 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 1643 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 1644 E = UB->end_objects(); 1645 I != E; ++I) { 1646 ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 1647 std::string ArchitectureName = ""; 1648 if (moreThanOneArch) 1649 ArchitectureName = I->getArchTypeName(); 1650 if (ObjOrErr) { 1651 ObjectFile &Obj = *ObjOrErr.get(); 1652 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 1653 ProcessMachO(Filename, MachOOF, "", ArchitectureName); 1654 } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { 1655 std::unique_ptr<Archive> &A = *AOrErr; 1656 outs() << "Archive : " << Filename; 1657 if (!ArchitectureName.empty()) 1658 outs() << " (architecture " << ArchitectureName << ")"; 1659 outs() << "\n"; 1660 if (ArchiveHeaders) 1661 printArchiveHeaders(A.get(), true, false); 1662 for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); 1663 AI != AE; ++AI) { 1664 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary(); 1665 if (ChildOrErr.getError()) 1666 continue; 1667 if (MachOObjectFile *O = 1668 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 1669 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 1670 ProcessMachO(Filename, MachOOF, MachOOF->getFileName(), 1671 ArchitectureName); 1672 } 1673 } 1674 } 1675 } 1676 return; 1677 } 1678 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 1679 if (!checkMachOAndArchFlags(O, Filename)) 1680 return; 1681 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) { 1682 ProcessMachO(Filename, MachOOF); 1683 } else 1684 errs() << "llvm-objdump: '" << Filename << "': " 1685 << "Object is not a Mach-O file type.\n"; 1686 } else 1687 errs() << "llvm-objdump: '" << Filename << "': " 1688 << "Unrecognized file type.\n"; 1689} 1690 1691typedef std::pair<uint64_t, const char *> BindInfoEntry; 1692typedef std::vector<BindInfoEntry> BindTable; 1693typedef BindTable::iterator bind_table_iterator; 1694 1695// The block of info used by the Symbolizer call backs. 1696struct DisassembleInfo { 1697 bool verbose; 1698 MachOObjectFile *O; 1699 SectionRef S; 1700 SymbolAddressMap *AddrMap; 1701 std::vector<SectionRef> *Sections; 1702 const char *class_name; 1703 const char *selector_name; 1704 char *method; 1705 char *demangled_name; 1706 uint64_t adrp_addr; 1707 uint32_t adrp_inst; 1708 BindTable *bindtable; 1709}; 1710 1711// SymbolizerGetOpInfo() is the operand information call back function. 1712// This is called to get the symbolic information for operand(s) of an 1713// instruction when it is being done. This routine does this from 1714// the relocation information, symbol table, etc. That block of information 1715// is a pointer to the struct DisassembleInfo that was passed when the 1716// disassembler context was created and passed to back to here when 1717// called back by the disassembler for instruction operands that could have 1718// relocation information. The address of the instruction containing operand is 1719// at the Pc parameter. The immediate value the operand has is passed in 1720// op_info->Value and is at Offset past the start of the instruction and has a 1721// byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 1722// LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 1723// names and addends of the symbolic expression to add for the operand. The 1724// value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 1725// information is returned then this function returns 1 else it returns 0. 1726static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 1727 uint64_t Size, int TagType, void *TagBuf) { 1728 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 1729 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 1730 uint64_t value = op_info->Value; 1731 1732 // Make sure all fields returned are zero if we don't set them. 1733 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 1734 op_info->Value = value; 1735 1736 // If the TagType is not the value 1 which it code knows about or if no 1737 // verbose symbolic information is wanted then just return 0, indicating no 1738 // information is being returned. 1739 if (TagType != 1 || !info->verbose) 1740 return 0; 1741 1742 unsigned int Arch = info->O->getArch(); 1743 if (Arch == Triple::x86) { 1744 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 1745 return 0; 1746 // First search the section's relocation entries (if any) for an entry 1747 // for this section offset. 1748 uint32_t sect_addr = info->S.getAddress(); 1749 uint32_t sect_offset = (Pc + Offset) - sect_addr; 1750 bool reloc_found = false; 1751 DataRefImpl Rel; 1752 MachO::any_relocation_info RE; 1753 bool isExtern = false; 1754 SymbolRef Symbol; 1755 bool r_scattered = false; 1756 uint32_t r_value, pair_r_value, r_type; 1757 for (const RelocationRef &Reloc : info->S.relocations()) { 1758 uint64_t RelocOffset; 1759 Reloc.getOffset(RelocOffset); 1760 if (RelocOffset == sect_offset) { 1761 Rel = Reloc.getRawDataRefImpl(); 1762 RE = info->O->getRelocation(Rel); 1763 r_type = info->O->getAnyRelocationType(RE); 1764 r_scattered = info->O->isRelocationScattered(RE); 1765 if (r_scattered) { 1766 r_value = info->O->getScatteredRelocationValue(RE); 1767 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 1768 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 1769 DataRefImpl RelNext = Rel; 1770 info->O->moveRelocationNext(RelNext); 1771 MachO::any_relocation_info RENext; 1772 RENext = info->O->getRelocation(RelNext); 1773 if (info->O->isRelocationScattered(RENext)) 1774 pair_r_value = info->O->getScatteredRelocationValue(RENext); 1775 else 1776 return 0; 1777 } 1778 } else { 1779 isExtern = info->O->getPlainRelocationExternal(RE); 1780 if (isExtern) { 1781 symbol_iterator RelocSym = Reloc.getSymbol(); 1782 Symbol = *RelocSym; 1783 } 1784 } 1785 reloc_found = true; 1786 break; 1787 } 1788 } 1789 if (reloc_found && isExtern) { 1790 StringRef SymName; 1791 Symbol.getName(SymName); 1792 const char *name = SymName.data(); 1793 op_info->AddSymbol.Present = 1; 1794 op_info->AddSymbol.Name = name; 1795 // For i386 extern relocation entries the value in the instruction is 1796 // the offset from the symbol, and value is already set in op_info->Value. 1797 return 1; 1798 } 1799 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 1800 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 1801 const char *add = GuessSymbolName(r_value, info->AddrMap); 1802 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 1803 uint32_t offset = value - (r_value - pair_r_value); 1804 op_info->AddSymbol.Present = 1; 1805 if (add != nullptr) 1806 op_info->AddSymbol.Name = add; 1807 else 1808 op_info->AddSymbol.Value = r_value; 1809 op_info->SubtractSymbol.Present = 1; 1810 if (sub != nullptr) 1811 op_info->SubtractSymbol.Name = sub; 1812 else 1813 op_info->SubtractSymbol.Value = pair_r_value; 1814 op_info->Value = offset; 1815 return 1; 1816 } 1817 // TODO: 1818 // Second search the external relocation entries of a fully linked image 1819 // (if any) for an entry that matches this segment offset. 1820 // uint32_t seg_offset = (Pc + Offset); 1821 return 0; 1822 } 1823 if (Arch == Triple::x86_64) { 1824 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 1825 return 0; 1826 // First search the section's relocation entries (if any) for an entry 1827 // for this section offset. 1828 uint64_t sect_addr = info->S.getAddress(); 1829 uint64_t sect_offset = (Pc + Offset) - sect_addr; 1830 bool reloc_found = false; 1831 DataRefImpl Rel; 1832 MachO::any_relocation_info RE; 1833 bool isExtern = false; 1834 SymbolRef Symbol; 1835 for (const RelocationRef &Reloc : info->S.relocations()) { 1836 uint64_t RelocOffset; 1837 Reloc.getOffset(RelocOffset); 1838 if (RelocOffset == sect_offset) { 1839 Rel = Reloc.getRawDataRefImpl(); 1840 RE = info->O->getRelocation(Rel); 1841 // NOTE: Scattered relocations don't exist on x86_64. 1842 isExtern = info->O->getPlainRelocationExternal(RE); 1843 if (isExtern) { 1844 symbol_iterator RelocSym = Reloc.getSymbol(); 1845 Symbol = *RelocSym; 1846 } 1847 reloc_found = true; 1848 break; 1849 } 1850 } 1851 if (reloc_found && isExtern) { 1852 // The Value passed in will be adjusted by the Pc if the instruction 1853 // adds the Pc. But for x86_64 external relocation entries the Value 1854 // is the offset from the external symbol. 1855 if (info->O->getAnyRelocationPCRel(RE)) 1856 op_info->Value -= Pc + Offset + Size; 1857 StringRef SymName; 1858 Symbol.getName(SymName); 1859 const char *name = SymName.data(); 1860 unsigned Type = info->O->getAnyRelocationType(RE); 1861 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 1862 DataRefImpl RelNext = Rel; 1863 info->O->moveRelocationNext(RelNext); 1864 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 1865 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 1866 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 1867 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 1868 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 1869 op_info->SubtractSymbol.Present = 1; 1870 op_info->SubtractSymbol.Name = name; 1871 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 1872 Symbol = *RelocSymNext; 1873 StringRef SymNameNext; 1874 Symbol.getName(SymNameNext); 1875 name = SymNameNext.data(); 1876 } 1877 } 1878 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 1879 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 1880 op_info->AddSymbol.Present = 1; 1881 op_info->AddSymbol.Name = name; 1882 return 1; 1883 } 1884 // TODO: 1885 // Second search the external relocation entries of a fully linked image 1886 // (if any) for an entry that matches this segment offset. 1887 // uint64_t seg_offset = (Pc + Offset); 1888 return 0; 1889 } 1890 if (Arch == Triple::arm) { 1891 if (Offset != 0 || (Size != 4 && Size != 2)) 1892 return 0; 1893 // First search the section's relocation entries (if any) for an entry 1894 // for this section offset. 1895 uint32_t sect_addr = info->S.getAddress(); 1896 uint32_t sect_offset = (Pc + Offset) - sect_addr; 1897 DataRefImpl Rel; 1898 MachO::any_relocation_info RE; 1899 bool isExtern = false; 1900 SymbolRef Symbol; 1901 bool r_scattered = false; 1902 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 1903 auto Reloc = 1904 std::find_if(info->S.relocations().begin(), info->S.relocations().end(), 1905 [&](const RelocationRef &Reloc) { 1906 uint64_t RelocOffset; 1907 Reloc.getOffset(RelocOffset); 1908 return RelocOffset == sect_offset; 1909 }); 1910 1911 if (Reloc == info->S.relocations().end()) 1912 return 0; 1913 1914 Rel = Reloc->getRawDataRefImpl(); 1915 RE = info->O->getRelocation(Rel); 1916 r_length = info->O->getAnyRelocationLength(RE); 1917 r_scattered = info->O->isRelocationScattered(RE); 1918 if (r_scattered) { 1919 r_value = info->O->getScatteredRelocationValue(RE); 1920 r_type = info->O->getScatteredRelocationType(RE); 1921 } else { 1922 r_type = info->O->getAnyRelocationType(RE); 1923 isExtern = info->O->getPlainRelocationExternal(RE); 1924 if (isExtern) { 1925 symbol_iterator RelocSym = Reloc->getSymbol(); 1926 Symbol = *RelocSym; 1927 } 1928 } 1929 if (r_type == MachO::ARM_RELOC_HALF || 1930 r_type == MachO::ARM_RELOC_SECTDIFF || 1931 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 1932 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 1933 DataRefImpl RelNext = Rel; 1934 info->O->moveRelocationNext(RelNext); 1935 MachO::any_relocation_info RENext; 1936 RENext = info->O->getRelocation(RelNext); 1937 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 1938 if (info->O->isRelocationScattered(RENext)) 1939 pair_r_value = info->O->getScatteredRelocationValue(RENext); 1940 } 1941 1942 if (isExtern) { 1943 StringRef SymName; 1944 Symbol.getName(SymName); 1945 const char *name = SymName.data(); 1946 op_info->AddSymbol.Present = 1; 1947 op_info->AddSymbol.Name = name; 1948 switch (r_type) { 1949 case MachO::ARM_RELOC_HALF: 1950 if ((r_length & 0x1) == 1) { 1951 op_info->Value = value << 16 | other_half; 1952 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 1953 } else { 1954 op_info->Value = other_half << 16 | value; 1955 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 1956 } 1957 break; 1958 default: 1959 break; 1960 } 1961 return 1; 1962 } 1963 // If we have a branch that is not an external relocation entry then 1964 // return 0 so the code in tryAddingSymbolicOperand() can use the 1965 // SymbolLookUp call back with the branch target address to look up the 1966 // symbol and possiblity add an annotation for a symbol stub. 1967 if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 1968 r_type == MachO::ARM_THUMB_RELOC_BR22)) 1969 return 0; 1970 1971 uint32_t offset = 0; 1972 if (r_type == MachO::ARM_RELOC_HALF || 1973 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 1974 if ((r_length & 0x1) == 1) 1975 value = value << 16 | other_half; 1976 else 1977 value = other_half << 16 | value; 1978 } 1979 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 1980 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 1981 offset = value - r_value; 1982 value = r_value; 1983 } 1984 1985 if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 1986 if ((r_length & 0x1) == 1) 1987 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 1988 else 1989 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 1990 const char *add = GuessSymbolName(r_value, info->AddrMap); 1991 const char *sub = GuessSymbolName(pair_r_value, info->AddrMap); 1992 int32_t offset = value - (r_value - pair_r_value); 1993 op_info->AddSymbol.Present = 1; 1994 if (add != nullptr) 1995 op_info->AddSymbol.Name = add; 1996 else 1997 op_info->AddSymbol.Value = r_value; 1998 op_info->SubtractSymbol.Present = 1; 1999 if (sub != nullptr) 2000 op_info->SubtractSymbol.Name = sub; 2001 else 2002 op_info->SubtractSymbol.Value = pair_r_value; 2003 op_info->Value = offset; 2004 return 1; 2005 } 2006 2007 op_info->AddSymbol.Present = 1; 2008 op_info->Value = offset; 2009 if (r_type == MachO::ARM_RELOC_HALF) { 2010 if ((r_length & 0x1) == 1) 2011 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 2012 else 2013 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 2014 } 2015 const char *add = GuessSymbolName(value, info->AddrMap); 2016 if (add != nullptr) { 2017 op_info->AddSymbol.Name = add; 2018 return 1; 2019 } 2020 op_info->AddSymbol.Value = value; 2021 return 1; 2022 } 2023 if (Arch == Triple::aarch64) { 2024 if (Offset != 0 || Size != 4) 2025 return 0; 2026 // First search the section's relocation entries (if any) for an entry 2027 // for this section offset. 2028 uint64_t sect_addr = info->S.getAddress(); 2029 uint64_t sect_offset = (Pc + Offset) - sect_addr; 2030 auto Reloc = 2031 std::find_if(info->S.relocations().begin(), info->S.relocations().end(), 2032 [&](const RelocationRef &Reloc) { 2033 uint64_t RelocOffset; 2034 Reloc.getOffset(RelocOffset); 2035 return RelocOffset == sect_offset; 2036 }); 2037 2038 if (Reloc == info->S.relocations().end()) 2039 return 0; 2040 2041 DataRefImpl Rel = Reloc->getRawDataRefImpl(); 2042 MachO::any_relocation_info RE = info->O->getRelocation(Rel); 2043 uint32_t r_type = info->O->getAnyRelocationType(RE); 2044 if (r_type == MachO::ARM64_RELOC_ADDEND) { 2045 DataRefImpl RelNext = Rel; 2046 info->O->moveRelocationNext(RelNext); 2047 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 2048 if (value == 0) { 2049 value = info->O->getPlainRelocationSymbolNum(RENext); 2050 op_info->Value = value; 2051 } 2052 } 2053 // NOTE: Scattered relocations don't exist on arm64. 2054 if (!info->O->getPlainRelocationExternal(RE)) 2055 return 0; 2056 StringRef SymName; 2057 Reloc->getSymbol()->getName(SymName); 2058 const char *name = SymName.data(); 2059 op_info->AddSymbol.Present = 1; 2060 op_info->AddSymbol.Name = name; 2061 2062 switch (r_type) { 2063 case MachO::ARM64_RELOC_PAGE21: 2064 /* @page */ 2065 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 2066 break; 2067 case MachO::ARM64_RELOC_PAGEOFF12: 2068 /* @pageoff */ 2069 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 2070 break; 2071 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 2072 /* @gotpage */ 2073 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 2074 break; 2075 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 2076 /* @gotpageoff */ 2077 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 2078 break; 2079 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 2080 /* @tvlppage is not implemented in llvm-mc */ 2081 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 2082 break; 2083 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 2084 /* @tvlppageoff is not implemented in llvm-mc */ 2085 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 2086 break; 2087 default: 2088 case MachO::ARM64_RELOC_BRANCH26: 2089 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 2090 break; 2091 } 2092 return 1; 2093 } 2094 return 0; 2095} 2096 2097// GuessCstringPointer is passed the address of what might be a pointer to a 2098// literal string in a cstring section. If that address is in a cstring section 2099// it returns a pointer to that string. Else it returns nullptr. 2100static const char *GuessCstringPointer(uint64_t ReferenceValue, 2101 struct DisassembleInfo *info) { 2102 uint32_t LoadCommandCount = info->O->getHeader().ncmds; 2103 MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); 2104 for (unsigned I = 0;; ++I) { 2105 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2106 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2107 for (unsigned J = 0; J < Seg.nsects; ++J) { 2108 MachO::section_64 Sec = info->O->getSection64(Load, J); 2109 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2110 if (section_type == MachO::S_CSTRING_LITERALS && 2111 ReferenceValue >= Sec.addr && 2112 ReferenceValue < Sec.addr + Sec.size) { 2113 uint64_t sect_offset = ReferenceValue - Sec.addr; 2114 uint64_t object_offset = Sec.offset + sect_offset; 2115 StringRef MachOContents = info->O->getData(); 2116 uint64_t object_size = MachOContents.size(); 2117 const char *object_addr = (const char *)MachOContents.data(); 2118 if (object_offset < object_size) { 2119 const char *name = object_addr + object_offset; 2120 return name; 2121 } else { 2122 return nullptr; 2123 } 2124 } 2125 } 2126 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2127 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2128 for (unsigned J = 0; J < Seg.nsects; ++J) { 2129 MachO::section Sec = info->O->getSection(Load, J); 2130 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2131 if (section_type == MachO::S_CSTRING_LITERALS && 2132 ReferenceValue >= Sec.addr && 2133 ReferenceValue < Sec.addr + Sec.size) { 2134 uint64_t sect_offset = ReferenceValue - Sec.addr; 2135 uint64_t object_offset = Sec.offset + sect_offset; 2136 StringRef MachOContents = info->O->getData(); 2137 uint64_t object_size = MachOContents.size(); 2138 const char *object_addr = (const char *)MachOContents.data(); 2139 if (object_offset < object_size) { 2140 const char *name = object_addr + object_offset; 2141 return name; 2142 } else { 2143 return nullptr; 2144 } 2145 } 2146 } 2147 } 2148 if (I == LoadCommandCount - 1) 2149 break; 2150 else 2151 Load = info->O->getNextLoadCommandInfo(Load); 2152 } 2153 return nullptr; 2154} 2155 2156// GuessIndirectSymbol returns the name of the indirect symbol for the 2157// ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 2158// an address of a symbol stub or a lazy or non-lazy pointer to associate the 2159// symbol name being referenced by the stub or pointer. 2160static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 2161 struct DisassembleInfo *info) { 2162 uint32_t LoadCommandCount = info->O->getHeader().ncmds; 2163 MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); 2164 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 2165 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 2166 for (unsigned I = 0;; ++I) { 2167 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2168 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2169 for (unsigned J = 0; J < Seg.nsects; ++J) { 2170 MachO::section_64 Sec = info->O->getSection64(Load, J); 2171 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2172 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2173 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2174 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2175 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2176 section_type == MachO::S_SYMBOL_STUBS) && 2177 ReferenceValue >= Sec.addr && 2178 ReferenceValue < Sec.addr + Sec.size) { 2179 uint32_t stride; 2180 if (section_type == MachO::S_SYMBOL_STUBS) 2181 stride = Sec.reserved2; 2182 else 2183 stride = 8; 2184 if (stride == 0) 2185 return nullptr; 2186 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2187 if (index < Dysymtab.nindirectsyms) { 2188 uint32_t indirect_symbol = 2189 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2190 if (indirect_symbol < Symtab.nsyms) { 2191 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2192 SymbolRef Symbol = *Sym; 2193 StringRef SymName; 2194 Symbol.getName(SymName); 2195 const char *name = SymName.data(); 2196 return name; 2197 } 2198 } 2199 } 2200 } 2201 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 2202 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 2203 for (unsigned J = 0; J < Seg.nsects; ++J) { 2204 MachO::section Sec = info->O->getSection(Load, J); 2205 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 2206 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 2207 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 2208 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 2209 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 2210 section_type == MachO::S_SYMBOL_STUBS) && 2211 ReferenceValue >= Sec.addr && 2212 ReferenceValue < Sec.addr + Sec.size) { 2213 uint32_t stride; 2214 if (section_type == MachO::S_SYMBOL_STUBS) 2215 stride = Sec.reserved2; 2216 else 2217 stride = 4; 2218 if (stride == 0) 2219 return nullptr; 2220 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 2221 if (index < Dysymtab.nindirectsyms) { 2222 uint32_t indirect_symbol = 2223 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 2224 if (indirect_symbol < Symtab.nsyms) { 2225 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 2226 SymbolRef Symbol = *Sym; 2227 StringRef SymName; 2228 Symbol.getName(SymName); 2229 const char *name = SymName.data(); 2230 return name; 2231 } 2232 } 2233 } 2234 } 2235 } 2236 if (I == LoadCommandCount - 1) 2237 break; 2238 else 2239 Load = info->O->getNextLoadCommandInfo(Load); 2240 } 2241 return nullptr; 2242} 2243 2244// method_reference() is called passing it the ReferenceName that might be 2245// a reference it to an Objective-C method call. If so then it allocates and 2246// assembles a method call string with the values last seen and saved in 2247// the DisassembleInfo's class_name and selector_name fields. This is saved 2248// into the method field of the info and any previous string is free'ed. 2249// Then the class_name field in the info is set to nullptr. The method call 2250// string is set into ReferenceName and ReferenceType is set to 2251// LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 2252// then both ReferenceType and ReferenceName are left unchanged. 2253static void method_reference(struct DisassembleInfo *info, 2254 uint64_t *ReferenceType, 2255 const char **ReferenceName) { 2256 unsigned int Arch = info->O->getArch(); 2257 if (*ReferenceName != nullptr) { 2258 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 2259 if (info->selector_name != nullptr) { 2260 if (info->method != nullptr) 2261 free(info->method); 2262 if (info->class_name != nullptr) { 2263 info->method = (char *)malloc(5 + strlen(info->class_name) + 2264 strlen(info->selector_name)); 2265 if (info->method != nullptr) { 2266 strcpy(info->method, "+["); 2267 strcat(info->method, info->class_name); 2268 strcat(info->method, " "); 2269 strcat(info->method, info->selector_name); 2270 strcat(info->method, "]"); 2271 *ReferenceName = info->method; 2272 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2273 } 2274 } else { 2275 info->method = (char *)malloc(9 + strlen(info->selector_name)); 2276 if (info->method != nullptr) { 2277 if (Arch == Triple::x86_64) 2278 strcpy(info->method, "-[%rdi "); 2279 else if (Arch == Triple::aarch64) 2280 strcpy(info->method, "-[x0 "); 2281 else 2282 strcpy(info->method, "-[r? "); 2283 strcat(info->method, info->selector_name); 2284 strcat(info->method, "]"); 2285 *ReferenceName = info->method; 2286 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2287 } 2288 } 2289 info->class_name = nullptr; 2290 } 2291 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 2292 if (info->selector_name != nullptr) { 2293 if (info->method != nullptr) 2294 free(info->method); 2295 info->method = (char *)malloc(17 + strlen(info->selector_name)); 2296 if (info->method != nullptr) { 2297 if (Arch == Triple::x86_64) 2298 strcpy(info->method, "-[[%rdi super] "); 2299 else if (Arch == Triple::aarch64) 2300 strcpy(info->method, "-[[x0 super] "); 2301 else 2302 strcpy(info->method, "-[[r? super] "); 2303 strcat(info->method, info->selector_name); 2304 strcat(info->method, "]"); 2305 *ReferenceName = info->method; 2306 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 2307 } 2308 info->class_name = nullptr; 2309 } 2310 } 2311 } 2312} 2313 2314// GuessPointerPointer() is passed the address of what might be a pointer to 2315// a reference to an Objective-C class, selector, message ref or cfstring. 2316// If so the value of the pointer is returned and one of the booleans are set 2317// to true. If not zero is returned and all the booleans are set to false. 2318static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 2319 struct DisassembleInfo *info, 2320 bool &classref, bool &selref, bool &msgref, 2321 bool &cfstring) { 2322 classref = false; 2323 selref = false; 2324 msgref = false; 2325 cfstring = false; 2326 uint32_t LoadCommandCount = info->O->getHeader().ncmds; 2327 MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); 2328 for (unsigned I = 0;; ++I) { 2329 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 2330 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 2331 for (unsigned J = 0; J < Seg.nsects; ++J) { 2332 MachO::section_64 Sec = info->O->getSection64(Load, J); 2333 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 2334 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2335 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 2336 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 2337 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 2338 ReferenceValue >= Sec.addr && 2339 ReferenceValue < Sec.addr + Sec.size) { 2340 uint64_t sect_offset = ReferenceValue - Sec.addr; 2341 uint64_t object_offset = Sec.offset + sect_offset; 2342 StringRef MachOContents = info->O->getData(); 2343 uint64_t object_size = MachOContents.size(); 2344 const char *object_addr = (const char *)MachOContents.data(); 2345 if (object_offset < object_size) { 2346 uint64_t pointer_value; 2347 memcpy(&pointer_value, object_addr + object_offset, 2348 sizeof(uint64_t)); 2349 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2350 sys::swapByteOrder(pointer_value); 2351 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 2352 selref = true; 2353 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 2354 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 2355 classref = true; 2356 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 2357 ReferenceValue + 8 < Sec.addr + Sec.size) { 2358 msgref = true; 2359 memcpy(&pointer_value, object_addr + object_offset + 8, 2360 sizeof(uint64_t)); 2361 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2362 sys::swapByteOrder(pointer_value); 2363 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 2364 cfstring = true; 2365 return pointer_value; 2366 } else { 2367 return 0; 2368 } 2369 } 2370 } 2371 } 2372 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 2373 if (I == LoadCommandCount - 1) 2374 break; 2375 else 2376 Load = info->O->getNextLoadCommandInfo(Load); 2377 } 2378 return 0; 2379} 2380 2381// get_pointer_64 returns a pointer to the bytes in the object file at the 2382// Address from a section in the Mach-O file. And indirectly returns the 2383// offset into the section, number of bytes left in the section past the offset 2384// and which section is was being referenced. If the Address is not in a 2385// section nullptr is returned. 2386static const char *get_pointer_64(uint64_t Address, uint32_t &offset, 2387 uint32_t &left, SectionRef &S, 2388 DisassembleInfo *info) { 2389 offset = 0; 2390 left = 0; 2391 S = SectionRef(); 2392 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 2393 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 2394 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 2395 if (Address >= SectAddress && Address < SectAddress + SectSize) { 2396 S = (*(info->Sections))[SectIdx]; 2397 offset = Address - SectAddress; 2398 left = SectSize - offset; 2399 StringRef SectContents; 2400 ((*(info->Sections))[SectIdx]).getContents(SectContents); 2401 return SectContents.data() + offset; 2402 } 2403 } 2404 return nullptr; 2405} 2406 2407// get_symbol_64() returns the name of a symbol (or nullptr) and the address of 2408// the symbol indirectly through n_value. Based on the relocation information 2409// for the specified section offset in the specified section reference. 2410static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 2411 DisassembleInfo *info, uint64_t &n_value) { 2412 n_value = 0; 2413 if (!info->verbose) 2414 return nullptr; 2415 2416 // See if there is an external relocation entry at the sect_offset. 2417 bool reloc_found = false; 2418 DataRefImpl Rel; 2419 MachO::any_relocation_info RE; 2420 bool isExtern = false; 2421 SymbolRef Symbol; 2422 for (const RelocationRef &Reloc : S.relocations()) { 2423 uint64_t RelocOffset; 2424 Reloc.getOffset(RelocOffset); 2425 if (RelocOffset == sect_offset) { 2426 Rel = Reloc.getRawDataRefImpl(); 2427 RE = info->O->getRelocation(Rel); 2428 if (info->O->isRelocationScattered(RE)) 2429 continue; 2430 isExtern = info->O->getPlainRelocationExternal(RE); 2431 if (isExtern) { 2432 symbol_iterator RelocSym = Reloc.getSymbol(); 2433 Symbol = *RelocSym; 2434 } 2435 reloc_found = true; 2436 break; 2437 } 2438 } 2439 // If there is an external relocation entry for a symbol in this section 2440 // at this section_offset then use that symbol's value for the n_value 2441 // and return its name. 2442 const char *SymbolName = nullptr; 2443 if (reloc_found && isExtern) { 2444 Symbol.getAddress(n_value); 2445 StringRef name; 2446 Symbol.getName(name); 2447 if (!name.empty()) { 2448 SymbolName = name.data(); 2449 return SymbolName; 2450 } 2451 } 2452 2453 // TODO: For fully linked images, look through the external relocation 2454 // entries off the dynamic symtab command. For these the r_offset is from the 2455 // start of the first writeable segment in the Mach-O file. So the offset 2456 // to this section from that segment is passed to this routine by the caller, 2457 // as the database_offset. Which is the difference of the section's starting 2458 // address and the first writable segment. 2459 // 2460 // NOTE: need add passing the database_offset to this routine. 2461 2462 // TODO: We did not find an external relocation entry so look up the 2463 // ReferenceValue as an address of a symbol and if found return that symbol's 2464 // name. 2465 // 2466 // NOTE: need add passing the ReferenceValue to this routine. Then that code 2467 // would simply be this: 2468 // SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 2469 2470 return SymbolName; 2471} 2472 2473// These are structs in the Objective-C meta data and read to produce the 2474// comments for disassembly. While these are part of the ABI they are no 2475// public defintions. So the are here not in include/llvm/Support/MachO.h . 2476 2477// The cfstring object in a 64-bit Mach-O file. 2478struct cfstring64_t { 2479 uint64_t isa; // class64_t * (64-bit pointer) 2480 uint64_t flags; // flag bits 2481 uint64_t characters; // char * (64-bit pointer) 2482 uint64_t length; // number of non-NULL characters in above 2483}; 2484 2485// The class object in a 64-bit Mach-O file. 2486struct class64_t { 2487 uint64_t isa; // class64_t * (64-bit pointer) 2488 uint64_t superclass; // class64_t * (64-bit pointer) 2489 uint64_t cache; // Cache (64-bit pointer) 2490 uint64_t vtable; // IMP * (64-bit pointer) 2491 uint64_t data; // class_ro64_t * (64-bit pointer) 2492}; 2493 2494struct class_ro64_t { 2495 uint32_t flags; 2496 uint32_t instanceStart; 2497 uint32_t instanceSize; 2498 uint32_t reserved; 2499 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 2500 uint64_t name; // const char * (64-bit pointer) 2501 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 2502 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 2503 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 2504 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 2505 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 2506}; 2507 2508inline void swapStruct(struct cfstring64_t &cfs) { 2509 sys::swapByteOrder(cfs.isa); 2510 sys::swapByteOrder(cfs.flags); 2511 sys::swapByteOrder(cfs.characters); 2512 sys::swapByteOrder(cfs.length); 2513} 2514 2515inline void swapStruct(struct class64_t &c) { 2516 sys::swapByteOrder(c.isa); 2517 sys::swapByteOrder(c.superclass); 2518 sys::swapByteOrder(c.cache); 2519 sys::swapByteOrder(c.vtable); 2520 sys::swapByteOrder(c.data); 2521} 2522 2523inline void swapStruct(struct class_ro64_t &cro) { 2524 sys::swapByteOrder(cro.flags); 2525 sys::swapByteOrder(cro.instanceStart); 2526 sys::swapByteOrder(cro.instanceSize); 2527 sys::swapByteOrder(cro.reserved); 2528 sys::swapByteOrder(cro.ivarLayout); 2529 sys::swapByteOrder(cro.name); 2530 sys::swapByteOrder(cro.baseMethods); 2531 sys::swapByteOrder(cro.baseProtocols); 2532 sys::swapByteOrder(cro.ivars); 2533 sys::swapByteOrder(cro.weakIvarLayout); 2534 sys::swapByteOrder(cro.baseProperties); 2535} 2536 2537static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 2538 struct DisassembleInfo *info); 2539 2540// get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 2541// to an Objective-C class and returns the class name. It is also passed the 2542// address of the pointer, so when the pointer is zero as it can be in an .o 2543// file, that is used to look for an external relocation entry with a symbol 2544// name. 2545static const char *get_objc2_64bit_class_name(uint64_t pointer_value, 2546 uint64_t ReferenceValue, 2547 struct DisassembleInfo *info) { 2548 const char *r; 2549 uint32_t offset, left; 2550 SectionRef S; 2551 2552 // The pointer_value can be 0 in an object file and have a relocation 2553 // entry for the class symbol at the ReferenceValue (the address of the 2554 // pointer). 2555 if (pointer_value == 0) { 2556 r = get_pointer_64(ReferenceValue, offset, left, S, info); 2557 if (r == nullptr || left < sizeof(uint64_t)) 2558 return nullptr; 2559 uint64_t n_value; 2560 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 2561 if (symbol_name == nullptr) 2562 return nullptr; 2563 const char *class_name = strrchr(symbol_name, '$'); 2564 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 2565 return class_name + 2; 2566 else 2567 return nullptr; 2568 } 2569 2570 // The case were the pointer_value is non-zero and points to a class defined 2571 // in this Mach-O file. 2572 r = get_pointer_64(pointer_value, offset, left, S, info); 2573 if (r == nullptr || left < sizeof(struct class64_t)) 2574 return nullptr; 2575 struct class64_t c; 2576 memcpy(&c, r, sizeof(struct class64_t)); 2577 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2578 swapStruct(c); 2579 if (c.data == 0) 2580 return nullptr; 2581 r = get_pointer_64(c.data, offset, left, S, info); 2582 if (r == nullptr || left < sizeof(struct class_ro64_t)) 2583 return nullptr; 2584 struct class_ro64_t cro; 2585 memcpy(&cro, r, sizeof(struct class_ro64_t)); 2586 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2587 swapStruct(cro); 2588 if (cro.name == 0) 2589 return nullptr; 2590 const char *name = get_pointer_64(cro.name, offset, left, S, info); 2591 return name; 2592} 2593 2594// get_objc2_64bit_cfstring_name is used for disassembly and is passed a 2595// pointer to a cfstring and returns its name or nullptr. 2596static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 2597 struct DisassembleInfo *info) { 2598 const char *r, *name; 2599 uint32_t offset, left; 2600 SectionRef S; 2601 struct cfstring64_t cfs; 2602 uint64_t cfs_characters; 2603 2604 r = get_pointer_64(ReferenceValue, offset, left, S, info); 2605 if (r == nullptr || left < sizeof(struct cfstring64_t)) 2606 return nullptr; 2607 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 2608 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 2609 swapStruct(cfs); 2610 if (cfs.characters == 0) { 2611 uint64_t n_value; 2612 const char *symbol_name = get_symbol_64( 2613 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 2614 if (symbol_name == nullptr) 2615 return nullptr; 2616 cfs_characters = n_value; 2617 } else 2618 cfs_characters = cfs.characters; 2619 name = get_pointer_64(cfs_characters, offset, left, S, info); 2620 2621 return name; 2622} 2623 2624// get_objc2_64bit_selref() is used for disassembly and is passed a the address 2625// of a pointer to an Objective-C selector reference when the pointer value is 2626// zero as in a .o file and is likely to have a external relocation entry with 2627// who's symbol's n_value is the real pointer to the selector name. If that is 2628// the case the real pointer to the selector name is returned else 0 is 2629// returned 2630static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 2631 struct DisassembleInfo *info) { 2632 uint32_t offset, left; 2633 SectionRef S; 2634 2635 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 2636 if (r == nullptr || left < sizeof(uint64_t)) 2637 return 0; 2638 uint64_t n_value; 2639 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 2640 if (symbol_name == nullptr) 2641 return 0; 2642 return n_value; 2643} 2644 2645// GuessLiteralPointer returns a string which for the item in the Mach-O file 2646// for the address passed in as ReferenceValue for printing as a comment with 2647// the instruction and also returns the corresponding type of that item 2648// indirectly through ReferenceType. 2649// 2650// If ReferenceValue is an address of literal cstring then a pointer to the 2651// cstring is returned and ReferenceType is set to 2652// LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 2653// 2654// If ReferenceValue is an address of an Objective-C CFString, Selector ref or 2655// Class ref that name is returned and the ReferenceType is set accordingly. 2656// 2657// Lastly, literals which are Symbol address in a literal pool are looked for 2658// and if found the symbol name is returned and ReferenceType is set to 2659// LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 2660// 2661// If there is no item in the Mach-O file for the address passed in as 2662// ReferenceValue nullptr is returned and ReferenceType is unchanged. 2663static const char *GuessLiteralPointer(uint64_t ReferenceValue, 2664 uint64_t ReferencePC, 2665 uint64_t *ReferenceType, 2666 struct DisassembleInfo *info) { 2667 // First see if there is an external relocation entry at the ReferencePC. 2668 uint64_t sect_addr = info->S.getAddress(); 2669 uint64_t sect_offset = ReferencePC - sect_addr; 2670 bool reloc_found = false; 2671 DataRefImpl Rel; 2672 MachO::any_relocation_info RE; 2673 bool isExtern = false; 2674 SymbolRef Symbol; 2675 for (const RelocationRef &Reloc : info->S.relocations()) { 2676 uint64_t RelocOffset; 2677 Reloc.getOffset(RelocOffset); 2678 if (RelocOffset == sect_offset) { 2679 Rel = Reloc.getRawDataRefImpl(); 2680 RE = info->O->getRelocation(Rel); 2681 if (info->O->isRelocationScattered(RE)) 2682 continue; 2683 isExtern = info->O->getPlainRelocationExternal(RE); 2684 if (isExtern) { 2685 symbol_iterator RelocSym = Reloc.getSymbol(); 2686 Symbol = *RelocSym; 2687 } 2688 reloc_found = true; 2689 break; 2690 } 2691 } 2692 // If there is an external relocation entry for a symbol in a section 2693 // then used that symbol's value for the value of the reference. 2694 if (reloc_found && isExtern) { 2695 if (info->O->getAnyRelocationPCRel(RE)) { 2696 unsigned Type = info->O->getAnyRelocationType(RE); 2697 if (Type == MachO::X86_64_RELOC_SIGNED) { 2698 Symbol.getAddress(ReferenceValue); 2699 } 2700 } 2701 } 2702 2703 // Look for literals such as Objective-C CFStrings refs, Selector refs, 2704 // Message refs and Class refs. 2705 bool classref, selref, msgref, cfstring; 2706 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 2707 selref, msgref, cfstring); 2708 if (classref && pointer_value == 0) { 2709 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 2710 // And the pointer_value in that section is typically zero as it will be 2711 // set by dyld as part of the "bind information". 2712 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 2713 if (name != nullptr) { 2714 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 2715 const char *class_name = strrchr(name, '$'); 2716 if (class_name != nullptr && class_name[1] == '_' && 2717 class_name[2] != '\0') { 2718 info->class_name = class_name + 2; 2719 return name; 2720 } 2721 } 2722 } 2723 2724 if (classref) { 2725 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 2726 const char *name = 2727 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 2728 if (name != nullptr) 2729 info->class_name = name; 2730 else 2731 name = "bad class ref"; 2732 return name; 2733 } 2734 2735 if (cfstring) { 2736 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 2737 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 2738 return name; 2739 } 2740 2741 if (selref && pointer_value == 0) 2742 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 2743 2744 if (pointer_value != 0) 2745 ReferenceValue = pointer_value; 2746 2747 const char *name = GuessCstringPointer(ReferenceValue, info); 2748 if (name) { 2749 if (pointer_value != 0 && selref) { 2750 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 2751 info->selector_name = name; 2752 } else if (pointer_value != 0 && msgref) { 2753 info->class_name = nullptr; 2754 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 2755 info->selector_name = name; 2756 } else 2757 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 2758 return name; 2759 } 2760 2761 // Lastly look for an indirect symbol with this ReferenceValue which is in 2762 // a literal pool. If found return that symbol name. 2763 name = GuessIndirectSymbol(ReferenceValue, info); 2764 if (name) { 2765 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 2766 return name; 2767 } 2768 2769 return nullptr; 2770} 2771 2772// SymbolizerSymbolLookUp is the symbol lookup function passed when creating 2773// the Symbolizer. It looks up the ReferenceValue using the info passed via the 2774// pointer to the struct DisassembleInfo that was passed when MCSymbolizer 2775// is created and returns the symbol name that matches the ReferenceValue or 2776// nullptr if none. The ReferenceType is passed in for the IN type of 2777// reference the instruction is making from the values in defined in the header 2778// "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 2779// Out type and the ReferenceName will also be set which is added as a comment 2780// to the disassembled instruction. 2781// 2782#if HAVE_CXXABI_H 2783// If the symbol name is a C++ mangled name then the demangled name is 2784// returned through ReferenceName and ReferenceType is set to 2785// LLVMDisassembler_ReferenceType_DeMangled_Name . 2786#endif 2787// 2788// When this is called to get a symbol name for a branch target then the 2789// ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 2790// SymbolValue will be looked for in the indirect symbol table to determine if 2791// it is an address for a symbol stub. If so then the symbol name for that 2792// stub is returned indirectly through ReferenceName and then ReferenceType is 2793// set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 2794// 2795// When this is called with an value loaded via a PC relative load then 2796// ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 2797// SymbolValue is checked to be an address of literal pointer, symbol pointer, 2798// or an Objective-C meta data reference. If so the output ReferenceType is 2799// set to correspond to that as well as setting the ReferenceName. 2800static const char *SymbolizerSymbolLookUp(void *DisInfo, 2801 uint64_t ReferenceValue, 2802 uint64_t *ReferenceType, 2803 uint64_t ReferencePC, 2804 const char **ReferenceName) { 2805 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 2806 // If no verbose symbolic information is wanted then just return nullptr. 2807 if (!info->verbose) { 2808 *ReferenceName = nullptr; 2809 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 2810 return nullptr; 2811 } 2812 2813 const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap); 2814 2815 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 2816 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 2817 if (*ReferenceName != nullptr) { 2818 method_reference(info, ReferenceType, ReferenceName); 2819 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 2820 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 2821 } else 2822#if HAVE_CXXABI_H 2823 if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 2824 if (info->demangled_name != nullptr) 2825 free(info->demangled_name); 2826 int status; 2827 info->demangled_name = 2828 abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status); 2829 if (info->demangled_name != nullptr) { 2830 *ReferenceName = info->demangled_name; 2831 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 2832 } else 2833 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 2834 } else 2835#endif 2836 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 2837 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 2838 *ReferenceName = 2839 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 2840 if (*ReferenceName) 2841 method_reference(info, ReferenceType, ReferenceName); 2842 else 2843 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 2844 // If this is arm64 and the reference is an adrp instruction save the 2845 // instruction, passed in ReferenceValue and the address of the instruction 2846 // for use later if we see and add immediate instruction. 2847 } else if (info->O->getArch() == Triple::aarch64 && 2848 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 2849 info->adrp_inst = ReferenceValue; 2850 info->adrp_addr = ReferencePC; 2851 SymbolName = nullptr; 2852 *ReferenceName = nullptr; 2853 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 2854 // If this is arm64 and reference is an add immediate instruction and we 2855 // have 2856 // seen an adrp instruction just before it and the adrp's Xd register 2857 // matches 2858 // this add's Xn register reconstruct the value being referenced and look to 2859 // see if it is a literal pointer. Note the add immediate instruction is 2860 // passed in ReferenceValue. 2861 } else if (info->O->getArch() == Triple::aarch64 && 2862 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 2863 ReferencePC - 4 == info->adrp_addr && 2864 (info->adrp_inst & 0x9f000000) == 0x90000000 && 2865 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 2866 uint32_t addxri_inst; 2867 uint64_t adrp_imm, addxri_imm; 2868 2869 adrp_imm = 2870 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 2871 if (info->adrp_inst & 0x0200000) 2872 adrp_imm |= 0xfffffffffc000000LL; 2873 2874 addxri_inst = ReferenceValue; 2875 addxri_imm = (addxri_inst >> 10) & 0xfff; 2876 if (((addxri_inst >> 22) & 0x3) == 1) 2877 addxri_imm <<= 12; 2878 2879 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 2880 (adrp_imm << 12) + addxri_imm; 2881 2882 *ReferenceName = 2883 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 2884 if (*ReferenceName == nullptr) 2885 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 2886 // If this is arm64 and the reference is a load register instruction and we 2887 // have seen an adrp instruction just before it and the adrp's Xd register 2888 // matches this add's Xn register reconstruct the value being referenced and 2889 // look to see if it is a literal pointer. Note the load register 2890 // instruction is passed in ReferenceValue. 2891 } else if (info->O->getArch() == Triple::aarch64 && 2892 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 2893 ReferencePC - 4 == info->adrp_addr && 2894 (info->adrp_inst & 0x9f000000) == 0x90000000 && 2895 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 2896 uint32_t ldrxui_inst; 2897 uint64_t adrp_imm, ldrxui_imm; 2898 2899 adrp_imm = 2900 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 2901 if (info->adrp_inst & 0x0200000) 2902 adrp_imm |= 0xfffffffffc000000LL; 2903 2904 ldrxui_inst = ReferenceValue; 2905 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 2906 2907 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 2908 (adrp_imm << 12) + (ldrxui_imm << 3); 2909 2910 *ReferenceName = 2911 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 2912 if (*ReferenceName == nullptr) 2913 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 2914 } 2915 // If this arm64 and is an load register (PC-relative) instruction the 2916 // ReferenceValue is the PC plus the immediate value. 2917 else if (info->O->getArch() == Triple::aarch64 && 2918 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 2919 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 2920 *ReferenceName = 2921 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 2922 if (*ReferenceName == nullptr) 2923 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 2924 } 2925#if HAVE_CXXABI_H 2926 else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 2927 if (info->demangled_name != nullptr) 2928 free(info->demangled_name); 2929 int status; 2930 info->demangled_name = 2931 abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status); 2932 if (info->demangled_name != nullptr) { 2933 *ReferenceName = info->demangled_name; 2934 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 2935 } 2936 } 2937#endif 2938 else { 2939 *ReferenceName = nullptr; 2940 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 2941 } 2942 2943 return SymbolName; 2944} 2945 2946/// \brief Emits the comments that are stored in the CommentStream. 2947/// Each comment in the CommentStream must end with a newline. 2948static void emitComments(raw_svector_ostream &CommentStream, 2949 SmallString<128> &CommentsToEmit, 2950 formatted_raw_ostream &FormattedOS, 2951 const MCAsmInfo &MAI) { 2952 // Flush the stream before taking its content. 2953 CommentStream.flush(); 2954 StringRef Comments = CommentsToEmit.str(); 2955 // Get the default information for printing a comment. 2956 const char *CommentBegin = MAI.getCommentString(); 2957 unsigned CommentColumn = MAI.getCommentColumn(); 2958 bool IsFirst = true; 2959 while (!Comments.empty()) { 2960 if (!IsFirst) 2961 FormattedOS << '\n'; 2962 // Emit a line of comments. 2963 FormattedOS.PadToColumn(CommentColumn); 2964 size_t Position = Comments.find('\n'); 2965 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 2966 // Move after the newline character. 2967 Comments = Comments.substr(Position + 1); 2968 IsFirst = false; 2969 } 2970 FormattedOS.flush(); 2971 2972 // Tell the comment stream that the vector changed underneath it. 2973 CommentsToEmit.clear(); 2974 CommentStream.resync(); 2975} 2976 2977static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, 2978 StringRef DisSegName, StringRef DisSectName) { 2979 const char *McpuDefault = nullptr; 2980 const Target *ThumbTarget = nullptr; 2981 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 2982 if (!TheTarget) { 2983 // GetTarget prints out stuff. 2984 return; 2985 } 2986 if (MCPU.empty() && McpuDefault) 2987 MCPU = McpuDefault; 2988 2989 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 2990 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 2991 if (ThumbTarget) 2992 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 2993 2994 // Package up features to be passed to target/subtarget 2995 std::string FeaturesStr; 2996 if (MAttrs.size()) { 2997 SubtargetFeatures Features; 2998 for (unsigned i = 0; i != MAttrs.size(); ++i) 2999 Features.AddFeature(MAttrs[i]); 3000 FeaturesStr = Features.getString(); 3001 } 3002 3003 // Set up disassembler. 3004 std::unique_ptr<const MCRegisterInfo> MRI( 3005 TheTarget->createMCRegInfo(TripleName)); 3006 std::unique_ptr<const MCAsmInfo> AsmInfo( 3007 TheTarget->createMCAsmInfo(*MRI, TripleName)); 3008 std::unique_ptr<const MCSubtargetInfo> STI( 3009 TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); 3010 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 3011 std::unique_ptr<MCDisassembler> DisAsm( 3012 TheTarget->createMCDisassembler(*STI, Ctx)); 3013 std::unique_ptr<MCSymbolizer> Symbolizer; 3014 struct DisassembleInfo SymbolizerInfo; 3015 std::unique_ptr<MCRelocationInfo> RelInfo( 3016 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 3017 if (RelInfo) { 3018 Symbolizer.reset(TheTarget->createMCSymbolizer( 3019 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 3020 &SymbolizerInfo, &Ctx, std::move(RelInfo))); 3021 DisAsm->setSymbolizer(std::move(Symbolizer)); 3022 } 3023 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 3024 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 3025 AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI, *STI)); 3026 // Set the display preference for hex vs. decimal immediates. 3027 IP->setPrintImmHex(PrintImmHex); 3028 // Comment stream and backing vector. 3029 SmallString<128> CommentsToEmit; 3030 raw_svector_ostream CommentStream(CommentsToEmit); 3031 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 3032 // if it is done then arm64 comments for string literals don't get printed 3033 // and some constant get printed instead and not setting it causes intel 3034 // (32-bit and 64-bit) comments printed with different spacing before the 3035 // comment causing different diffs with the 'C' disassembler library API. 3036 // IP->setCommentStream(CommentStream); 3037 3038 if (!AsmInfo || !STI || !DisAsm || !IP) { 3039 errs() << "error: couldn't initialize disassembler for target " 3040 << TripleName << '\n'; 3041 return; 3042 } 3043 3044 // Set up thumb disassembler. 3045 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 3046 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 3047 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 3048 std::unique_ptr<MCDisassembler> ThumbDisAsm; 3049 std::unique_ptr<MCInstPrinter> ThumbIP; 3050 std::unique_ptr<MCContext> ThumbCtx; 3051 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 3052 struct DisassembleInfo ThumbSymbolizerInfo; 3053 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 3054 if (ThumbTarget) { 3055 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 3056 ThumbAsmInfo.reset( 3057 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName)); 3058 ThumbSTI.reset( 3059 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MCPU, FeaturesStr)); 3060 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 3061 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 3062 MCContext *PtrThumbCtx = ThumbCtx.get(); 3063 ThumbRelInfo.reset( 3064 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 3065 if (ThumbRelInfo) { 3066 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 3067 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 3068 &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo))); 3069 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 3070 } 3071 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 3072 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 3073 ThumbAsmPrinterVariant, *ThumbAsmInfo, *ThumbInstrInfo, *ThumbMRI, 3074 *ThumbSTI)); 3075 // Set the display preference for hex vs. decimal immediates. 3076 ThumbIP->setPrintImmHex(PrintImmHex); 3077 } 3078 3079 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) { 3080 errs() << "error: couldn't initialize disassembler for target " 3081 << ThumbTripleName << '\n'; 3082 return; 3083 } 3084 3085 MachO::mach_header Header = MachOOF->getHeader(); 3086 3087 // FIXME: Using the -cfg command line option, this code used to be able to 3088 // annotate relocations with the referenced symbol's name, and if this was 3089 // inside a __[cf]string section, the data it points to. This is now replaced 3090 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 3091 std::vector<SectionRef> Sections; 3092 std::vector<SymbolRef> Symbols; 3093 SmallVector<uint64_t, 8> FoundFns; 3094 uint64_t BaseSegmentAddress; 3095 3096 getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns, 3097 BaseSegmentAddress); 3098 3099 // Sort the symbols by address, just in case they didn't come in that way. 3100 std::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); 3101 3102 // Build a data in code table that is sorted on by the address of each entry. 3103 uint64_t BaseAddress = 0; 3104 if (Header.filetype == MachO::MH_OBJECT) 3105 BaseAddress = Sections[0].getAddress(); 3106 else 3107 BaseAddress = BaseSegmentAddress; 3108 DiceTable Dices; 3109 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 3110 DI != DE; ++DI) { 3111 uint32_t Offset; 3112 DI->getOffset(Offset); 3113 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 3114 } 3115 array_pod_sort(Dices.begin(), Dices.end()); 3116 3117#ifndef NDEBUG 3118 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); 3119#else 3120 raw_ostream &DebugOut = nulls(); 3121#endif 3122 3123 std::unique_ptr<DIContext> diContext; 3124 ObjectFile *DbgObj = MachOOF; 3125 // Try to find debug info and set up the DIContext for it. 3126 if (UseDbg) { 3127 // A separate DSym file path was specified, parse it as a macho file, 3128 // get the sections and supply it to the section name parsing machinery. 3129 if (!DSYMFile.empty()) { 3130 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 3131 MemoryBuffer::getFileOrSTDIN(DSYMFile); 3132 if (std::error_code EC = BufOrErr.getError()) { 3133 errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n'; 3134 return; 3135 } 3136 DbgObj = 3137 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()) 3138 .get() 3139 .release(); 3140 } 3141 3142 // Setup the DIContext 3143 diContext.reset(DIContext::getDWARFContext(*DbgObj)); 3144 } 3145 3146 if (DumpSections.size() == 0) 3147 outs() << "(" << DisSegName << "," << DisSectName << ") section\n"; 3148 3149 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 3150 StringRef SectName; 3151 if (Sections[SectIdx].getName(SectName) || SectName != DisSectName) 3152 continue; 3153 3154 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 3155 3156 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 3157 if (SegmentName != DisSegName) 3158 continue; 3159 3160 StringRef BytesStr; 3161 Sections[SectIdx].getContents(BytesStr); 3162 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()), 3163 BytesStr.size()); 3164 uint64_t SectAddress = Sections[SectIdx].getAddress(); 3165 3166 bool symbolTableWorked = false; 3167 3168 // Parse relocations. 3169 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 3170 for (const RelocationRef &Reloc : Sections[SectIdx].relocations()) { 3171 uint64_t RelocOffset; 3172 Reloc.getOffset(RelocOffset); 3173 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 3174 RelocOffset -= SectionAddress; 3175 3176 symbol_iterator RelocSym = Reloc.getSymbol(); 3177 3178 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 3179 } 3180 array_pod_sort(Relocs.begin(), Relocs.end()); 3181 3182 // Create a map of symbol addresses to symbol names for use by 3183 // the SymbolizerSymbolLookUp() routine. 3184 SymbolAddressMap AddrMap; 3185 bool DisSymNameFound = false; 3186 for (const SymbolRef &Symbol : MachOOF->symbols()) { 3187 SymbolRef::Type ST; 3188 Symbol.getType(ST); 3189 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 3190 ST == SymbolRef::ST_Other) { 3191 uint64_t Address; 3192 Symbol.getAddress(Address); 3193 StringRef SymName; 3194 Symbol.getName(SymName); 3195 AddrMap[Address] = SymName; 3196 if (!DisSymName.empty() && DisSymName == SymName) 3197 DisSymNameFound = true; 3198 } 3199 } 3200 if (!DisSymName.empty() && !DisSymNameFound) { 3201 outs() << "Can't find -dis-symname: " << DisSymName << "\n"; 3202 return; 3203 } 3204 // Set up the block of info used by the Symbolizer call backs. 3205 SymbolizerInfo.verbose = !NoSymbolicOperands; 3206 SymbolizerInfo.O = MachOOF; 3207 SymbolizerInfo.S = Sections[SectIdx]; 3208 SymbolizerInfo.AddrMap = &AddrMap; 3209 SymbolizerInfo.Sections = &Sections; 3210 SymbolizerInfo.class_name = nullptr; 3211 SymbolizerInfo.selector_name = nullptr; 3212 SymbolizerInfo.method = nullptr; 3213 SymbolizerInfo.demangled_name = nullptr; 3214 SymbolizerInfo.bindtable = nullptr; 3215 SymbolizerInfo.adrp_addr = 0; 3216 SymbolizerInfo.adrp_inst = 0; 3217 // Same for the ThumbSymbolizer 3218 ThumbSymbolizerInfo.verbose = !NoSymbolicOperands; 3219 ThumbSymbolizerInfo.O = MachOOF; 3220 ThumbSymbolizerInfo.S = Sections[SectIdx]; 3221 ThumbSymbolizerInfo.AddrMap = &AddrMap; 3222 ThumbSymbolizerInfo.Sections = &Sections; 3223 ThumbSymbolizerInfo.class_name = nullptr; 3224 ThumbSymbolizerInfo.selector_name = nullptr; 3225 ThumbSymbolizerInfo.method = nullptr; 3226 ThumbSymbolizerInfo.demangled_name = nullptr; 3227 ThumbSymbolizerInfo.bindtable = nullptr; 3228 ThumbSymbolizerInfo.adrp_addr = 0; 3229 ThumbSymbolizerInfo.adrp_inst = 0; 3230 3231 // Disassemble symbol by symbol. 3232 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 3233 StringRef SymName; 3234 Symbols[SymIdx].getName(SymName); 3235 3236 SymbolRef::Type ST; 3237 Symbols[SymIdx].getType(ST); 3238 if (ST != SymbolRef::ST_Function) 3239 continue; 3240 3241 // Make sure the symbol is defined in this section. 3242 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 3243 if (!containsSym) 3244 continue; 3245 3246 // If we are only disassembling one symbol see if this is that symbol. 3247 if (!DisSymName.empty() && DisSymName != SymName) 3248 continue; 3249 3250 // Start at the address of the symbol relative to the section's address. 3251 uint64_t Start = 0; 3252 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 3253 Symbols[SymIdx].getAddress(Start); 3254 Start -= SectionAddress; 3255 3256 // Stop disassembling either at the beginning of the next symbol or at 3257 // the end of the section. 3258 bool containsNextSym = false; 3259 uint64_t NextSym = 0; 3260 uint64_t NextSymIdx = SymIdx + 1; 3261 while (Symbols.size() > NextSymIdx) { 3262 SymbolRef::Type NextSymType; 3263 Symbols[NextSymIdx].getType(NextSymType); 3264 if (NextSymType == SymbolRef::ST_Function) { 3265 containsNextSym = 3266 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 3267 Symbols[NextSymIdx].getAddress(NextSym); 3268 NextSym -= SectionAddress; 3269 break; 3270 } 3271 ++NextSymIdx; 3272 } 3273 3274 uint64_t SectSize = Sections[SectIdx].getSize(); 3275 uint64_t End = containsNextSym ? NextSym : SectSize; 3276 uint64_t Size; 3277 3278 symbolTableWorked = true; 3279 3280 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 3281 bool isThumb = 3282 (MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb) && ThumbTarget; 3283 3284 outs() << SymName << ":\n"; 3285 DILineInfo lastLine; 3286 for (uint64_t Index = Start; Index < End; Index += Size) { 3287 MCInst Inst; 3288 3289 uint64_t PC = SectAddress + Index; 3290 if (!NoLeadingAddr) { 3291 if (FullLeadingAddr) { 3292 if (MachOOF->is64Bit()) 3293 outs() << format("%016" PRIx64, PC); 3294 else 3295 outs() << format("%08" PRIx64, PC); 3296 } else { 3297 outs() << format("%8" PRIx64 ":", PC); 3298 } 3299 } 3300 if (!NoShowRawInsn) 3301 outs() << "\t"; 3302 3303 // Check the data in code table here to see if this is data not an 3304 // instruction to be disassembled. 3305 DiceTable Dice; 3306 Dice.push_back(std::make_pair(PC, DiceRef())); 3307 dice_table_iterator DTI = 3308 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 3309 compareDiceTableEntries); 3310 if (DTI != Dices.end()) { 3311 uint16_t Length; 3312 DTI->second.getLength(Length); 3313 uint16_t Kind; 3314 DTI->second.getKind(Kind); 3315 Size = DumpDataInCode(Bytes.data() + Index, Length, Kind); 3316 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 3317 (PC == (DTI->first + Length - 1)) && (Length & 1)) 3318 Size++; 3319 continue; 3320 } 3321 3322 SmallVector<char, 64> AnnotationsBytes; 3323 raw_svector_ostream Annotations(AnnotationsBytes); 3324 3325 bool gotInst; 3326 if (isThumb) 3327 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 3328 PC, DebugOut, Annotations); 3329 else 3330 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 3331 DebugOut, Annotations); 3332 if (gotInst) { 3333 if (!NoShowRawInsn) { 3334 DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size)); 3335 } 3336 formatted_raw_ostream FormattedOS(outs()); 3337 Annotations.flush(); 3338 StringRef AnnotationsStr = Annotations.str(); 3339 if (isThumb) 3340 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr); 3341 else 3342 IP->printInst(&Inst, FormattedOS, AnnotationsStr); 3343 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 3344 3345 // Print debug info. 3346 if (diContext) { 3347 DILineInfo dli = diContext->getLineInfoForAddress(PC); 3348 // Print valid line info if it changed. 3349 if (dli != lastLine && dli.Line != 0) 3350 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 3351 << dli.Column; 3352 lastLine = dli; 3353 } 3354 outs() << "\n"; 3355 } else { 3356 unsigned int Arch = MachOOF->getArch(); 3357 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 3358 outs() << format("\t.byte 0x%02x #bad opcode\n", 3359 *(Bytes.data() + Index) & 0xff); 3360 Size = 1; // skip exactly one illegible byte and move on. 3361 } else if (Arch == Triple::aarch64) { 3362 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 3363 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 3364 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 3365 (*(Bytes.data() + Index + 3) & 0xff) << 24; 3366 outs() << format("\t.long\t0x%08x\n", opcode); 3367 Size = 4; 3368 } else { 3369 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 3370 if (Size == 0) 3371 Size = 1; // skip illegible bytes 3372 } 3373 } 3374 } 3375 } 3376 if (!symbolTableWorked) { 3377 // Reading the symbol table didn't work, disassemble the whole section. 3378 uint64_t SectAddress = Sections[SectIdx].getAddress(); 3379 uint64_t SectSize = Sections[SectIdx].getSize(); 3380 uint64_t InstSize; 3381 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 3382 MCInst Inst; 3383 3384 uint64_t PC = SectAddress + Index; 3385 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 3386 DebugOut, nulls())) { 3387 if (!NoLeadingAddr) { 3388 if (FullLeadingAddr) { 3389 if (MachOOF->is64Bit()) 3390 outs() << format("%016" PRIx64, PC); 3391 else 3392 outs() << format("%08" PRIx64, PC); 3393 } else { 3394 outs() << format("%8" PRIx64 ":", PC); 3395 } 3396 } 3397 if (!NoShowRawInsn) { 3398 outs() << "\t"; 3399 DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, InstSize)); 3400 } 3401 IP->printInst(&Inst, outs(), ""); 3402 outs() << "\n"; 3403 } else { 3404 unsigned int Arch = MachOOF->getArch(); 3405 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 3406 outs() << format("\t.byte 0x%02x #bad opcode\n", 3407 *(Bytes.data() + Index) & 0xff); 3408 InstSize = 1; // skip exactly one illegible byte and move on. 3409 } else { 3410 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 3411 if (InstSize == 0) 3412 InstSize = 1; // skip illegible bytes 3413 } 3414 } 3415 } 3416 } 3417 // The TripleName's need to be reset if we are called again for a different 3418 // archtecture. 3419 TripleName = ""; 3420 ThumbTripleName = ""; 3421 3422 if (SymbolizerInfo.method != nullptr) 3423 free(SymbolizerInfo.method); 3424 if (SymbolizerInfo.demangled_name != nullptr) 3425 free(SymbolizerInfo.demangled_name); 3426 if (SymbolizerInfo.bindtable != nullptr) 3427 delete SymbolizerInfo.bindtable; 3428 if (ThumbSymbolizerInfo.method != nullptr) 3429 free(ThumbSymbolizerInfo.method); 3430 if (ThumbSymbolizerInfo.demangled_name != nullptr) 3431 free(ThumbSymbolizerInfo.demangled_name); 3432 if (ThumbSymbolizerInfo.bindtable != nullptr) 3433 delete ThumbSymbolizerInfo.bindtable; 3434 } 3435} 3436 3437//===----------------------------------------------------------------------===// 3438// __compact_unwind section dumping 3439//===----------------------------------------------------------------------===// 3440 3441namespace { 3442 3443template <typename T> static uint64_t readNext(const char *&Buf) { 3444 using llvm::support::little; 3445 using llvm::support::unaligned; 3446 3447 uint64_t Val = support::endian::read<T, little, unaligned>(Buf); 3448 Buf += sizeof(T); 3449 return Val; 3450} 3451 3452struct CompactUnwindEntry { 3453 uint32_t OffsetInSection; 3454 3455 uint64_t FunctionAddr; 3456 uint32_t Length; 3457 uint32_t CompactEncoding; 3458 uint64_t PersonalityAddr; 3459 uint64_t LSDAAddr; 3460 3461 RelocationRef FunctionReloc; 3462 RelocationRef PersonalityReloc; 3463 RelocationRef LSDAReloc; 3464 3465 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 3466 : OffsetInSection(Offset) { 3467 if (Is64) 3468 read<uint64_t>(Contents.data() + Offset); 3469 else 3470 read<uint32_t>(Contents.data() + Offset); 3471 } 3472 3473private: 3474 template <typename UIntPtr> void read(const char *Buf) { 3475 FunctionAddr = readNext<UIntPtr>(Buf); 3476 Length = readNext<uint32_t>(Buf); 3477 CompactEncoding = readNext<uint32_t>(Buf); 3478 PersonalityAddr = readNext<UIntPtr>(Buf); 3479 LSDAAddr = readNext<UIntPtr>(Buf); 3480 } 3481}; 3482} 3483 3484/// Given a relocation from __compact_unwind, consisting of the RelocationRef 3485/// and data being relocated, determine the best base Name and Addend to use for 3486/// display purposes. 3487/// 3488/// 1. An Extern relocation will directly reference a symbol (and the data is 3489/// then already an addend), so use that. 3490/// 2. Otherwise the data is an offset in the object file's layout; try to find 3491// a symbol before it in the same section, and use the offset from there. 3492/// 3. Finally, if all that fails, fall back to an offset from the start of the 3493/// referenced section. 3494static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 3495 std::map<uint64_t, SymbolRef> &Symbols, 3496 const RelocationRef &Reloc, uint64_t Addr, 3497 StringRef &Name, uint64_t &Addend) { 3498 if (Reloc.getSymbol() != Obj->symbol_end()) { 3499 Reloc.getSymbol()->getName(Name); 3500 Addend = Addr; 3501 return; 3502 } 3503 3504 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 3505 SectionRef RelocSection = Obj->getRelocationSection(RE); 3506 3507 uint64_t SectionAddr = RelocSection.getAddress(); 3508 3509 auto Sym = Symbols.upper_bound(Addr); 3510 if (Sym == Symbols.begin()) { 3511 // The first symbol in the object is after this reference, the best we can 3512 // do is section-relative notation. 3513 RelocSection.getName(Name); 3514 Addend = Addr - SectionAddr; 3515 return; 3516 } 3517 3518 // Go back one so that SymbolAddress <= Addr. 3519 --Sym; 3520 3521 section_iterator SymSection = Obj->section_end(); 3522 Sym->second.getSection(SymSection); 3523 if (RelocSection == *SymSection) { 3524 // There's a valid symbol in the same section before this reference. 3525 Sym->second.getName(Name); 3526 Addend = Addr - Sym->first; 3527 return; 3528 } 3529 3530 // There is a symbol before this reference, but it's in a different 3531 // section. Probably not helpful to mention it, so use the section name. 3532 RelocSection.getName(Name); 3533 Addend = Addr - SectionAddr; 3534} 3535 3536static void printUnwindRelocDest(const MachOObjectFile *Obj, 3537 std::map<uint64_t, SymbolRef> &Symbols, 3538 const RelocationRef &Reloc, uint64_t Addr) { 3539 StringRef Name; 3540 uint64_t Addend; 3541 3542 if (!Reloc.getObjectFile()) 3543 return; 3544 3545 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 3546 3547 outs() << Name; 3548 if (Addend) 3549 outs() << " + " << format("0x%" PRIx64, Addend); 3550} 3551 3552static void 3553printMachOCompactUnwindSection(const MachOObjectFile *Obj, 3554 std::map<uint64_t, SymbolRef> &Symbols, 3555 const SectionRef &CompactUnwind) { 3556 3557 assert(Obj->isLittleEndian() && 3558 "There should not be a big-endian .o with __compact_unwind"); 3559 3560 bool Is64 = Obj->is64Bit(); 3561 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 3562 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 3563 3564 StringRef Contents; 3565 CompactUnwind.getContents(Contents); 3566 3567 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 3568 3569 // First populate the initial raw offsets, encodings and so on from the entry. 3570 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 3571 CompactUnwindEntry Entry(Contents.data(), Offset, Is64); 3572 CompactUnwinds.push_back(Entry); 3573 } 3574 3575 // Next we need to look at the relocations to find out what objects are 3576 // actually being referred to. 3577 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 3578 uint64_t RelocAddress; 3579 Reloc.getOffset(RelocAddress); 3580 3581 uint32_t EntryIdx = RelocAddress / EntrySize; 3582 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 3583 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 3584 3585 if (OffsetInEntry == 0) 3586 Entry.FunctionReloc = Reloc; 3587 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 3588 Entry.PersonalityReloc = Reloc; 3589 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 3590 Entry.LSDAReloc = Reloc; 3591 else 3592 llvm_unreachable("Unexpected relocation in __compact_unwind section"); 3593 } 3594 3595 // Finally, we're ready to print the data we've gathered. 3596 outs() << "Contents of __compact_unwind section:\n"; 3597 for (auto &Entry : CompactUnwinds) { 3598 outs() << " Entry at offset " 3599 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 3600 3601 // 1. Start of the region this entry applies to. 3602 outs() << " start: " << format("0x%" PRIx64, 3603 Entry.FunctionAddr) << ' '; 3604 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 3605 outs() << '\n'; 3606 3607 // 2. Length of the region this entry applies to. 3608 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 3609 << '\n'; 3610 // 3. The 32-bit compact encoding. 3611 outs() << " compact encoding: " 3612 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 3613 3614 // 4. The personality function, if present. 3615 if (Entry.PersonalityReloc.getObjectFile()) { 3616 outs() << " personality function: " 3617 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 3618 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 3619 Entry.PersonalityAddr); 3620 outs() << '\n'; 3621 } 3622 3623 // 5. This entry's language-specific data area. 3624 if (Entry.LSDAReloc.getObjectFile()) { 3625 outs() << " LSDA: " << format("0x%" PRIx64, 3626 Entry.LSDAAddr) << ' '; 3627 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 3628 outs() << '\n'; 3629 } 3630 } 3631} 3632 3633//===----------------------------------------------------------------------===// 3634// __unwind_info section dumping 3635//===----------------------------------------------------------------------===// 3636 3637static void printRegularSecondLevelUnwindPage(const char *PageStart) { 3638 const char *Pos = PageStart; 3639 uint32_t Kind = readNext<uint32_t>(Pos); 3640 (void)Kind; 3641 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 3642 3643 uint16_t EntriesStart = readNext<uint16_t>(Pos); 3644 uint16_t NumEntries = readNext<uint16_t>(Pos); 3645 3646 Pos = PageStart + EntriesStart; 3647 for (unsigned i = 0; i < NumEntries; ++i) { 3648 uint32_t FunctionOffset = readNext<uint32_t>(Pos); 3649 uint32_t Encoding = readNext<uint32_t>(Pos); 3650 3651 outs() << " [" << i << "]: " 3652 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 3653 << ", " 3654 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 3655 } 3656} 3657 3658static void printCompressedSecondLevelUnwindPage( 3659 const char *PageStart, uint32_t FunctionBase, 3660 const SmallVectorImpl<uint32_t> &CommonEncodings) { 3661 const char *Pos = PageStart; 3662 uint32_t Kind = readNext<uint32_t>(Pos); 3663 (void)Kind; 3664 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 3665 3666 uint16_t EntriesStart = readNext<uint16_t>(Pos); 3667 uint16_t NumEntries = readNext<uint16_t>(Pos); 3668 3669 uint16_t EncodingsStart = readNext<uint16_t>(Pos); 3670 readNext<uint16_t>(Pos); 3671 const auto *PageEncodings = reinterpret_cast<const support::ulittle32_t *>( 3672 PageStart + EncodingsStart); 3673 3674 Pos = PageStart + EntriesStart; 3675 for (unsigned i = 0; i < NumEntries; ++i) { 3676 uint32_t Entry = readNext<uint32_t>(Pos); 3677 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 3678 uint32_t EncodingIdx = Entry >> 24; 3679 3680 uint32_t Encoding; 3681 if (EncodingIdx < CommonEncodings.size()) 3682 Encoding = CommonEncodings[EncodingIdx]; 3683 else 3684 Encoding = PageEncodings[EncodingIdx - CommonEncodings.size()]; 3685 3686 outs() << " [" << i << "]: " 3687 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 3688 << ", " 3689 << "encoding[" << EncodingIdx 3690 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 3691 } 3692} 3693 3694static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 3695 std::map<uint64_t, SymbolRef> &Symbols, 3696 const SectionRef &UnwindInfo) { 3697 3698 assert(Obj->isLittleEndian() && 3699 "There should not be a big-endian .o with __unwind_info"); 3700 3701 outs() << "Contents of __unwind_info section:\n"; 3702 3703 StringRef Contents; 3704 UnwindInfo.getContents(Contents); 3705 const char *Pos = Contents.data(); 3706 3707 //===---------------------------------- 3708 // Section header 3709 //===---------------------------------- 3710 3711 uint32_t Version = readNext<uint32_t>(Pos); 3712 outs() << " Version: " 3713 << format("0x%" PRIx32, Version) << '\n'; 3714 assert(Version == 1 && "only understand version 1"); 3715 3716 uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos); 3717 outs() << " Common encodings array section offset: " 3718 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 3719 uint32_t NumCommonEncodings = readNext<uint32_t>(Pos); 3720 outs() << " Number of common encodings in array: " 3721 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 3722 3723 uint32_t PersonalitiesStart = readNext<uint32_t>(Pos); 3724 outs() << " Personality function array section offset: " 3725 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 3726 uint32_t NumPersonalities = readNext<uint32_t>(Pos); 3727 outs() << " Number of personality functions in array: " 3728 << format("0x%" PRIx32, NumPersonalities) << '\n'; 3729 3730 uint32_t IndicesStart = readNext<uint32_t>(Pos); 3731 outs() << " Index array section offset: " 3732 << format("0x%" PRIx32, IndicesStart) << '\n'; 3733 uint32_t NumIndices = readNext<uint32_t>(Pos); 3734 outs() << " Number of indices in array: " 3735 << format("0x%" PRIx32, NumIndices) << '\n'; 3736 3737 //===---------------------------------- 3738 // A shared list of common encodings 3739 //===---------------------------------- 3740 3741 // These occupy indices in the range [0, N] whenever an encoding is referenced 3742 // from a compressed 2nd level index table. In practice the linker only 3743 // creates ~128 of these, so that indices are available to embed encodings in 3744 // the 2nd level index. 3745 3746 SmallVector<uint32_t, 64> CommonEncodings; 3747 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 3748 Pos = Contents.data() + CommonEncodingsStart; 3749 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 3750 uint32_t Encoding = readNext<uint32_t>(Pos); 3751 CommonEncodings.push_back(Encoding); 3752 3753 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 3754 << '\n'; 3755 } 3756 3757 //===---------------------------------- 3758 // Personality functions used in this executable 3759 //===---------------------------------- 3760 3761 // There should be only a handful of these (one per source language, 3762 // roughly). Particularly since they only get 2 bits in the compact encoding. 3763 3764 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 3765 Pos = Contents.data() + PersonalitiesStart; 3766 for (unsigned i = 0; i < NumPersonalities; ++i) { 3767 uint32_t PersonalityFn = readNext<uint32_t>(Pos); 3768 outs() << " personality[" << i + 1 3769 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 3770 } 3771 3772 //===---------------------------------- 3773 // The level 1 index entries 3774 //===---------------------------------- 3775 3776 // These specify an approximate place to start searching for the more detailed 3777 // information, sorted by PC. 3778 3779 struct IndexEntry { 3780 uint32_t FunctionOffset; 3781 uint32_t SecondLevelPageStart; 3782 uint32_t LSDAStart; 3783 }; 3784 3785 SmallVector<IndexEntry, 4> IndexEntries; 3786 3787 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 3788 Pos = Contents.data() + IndicesStart; 3789 for (unsigned i = 0; i < NumIndices; ++i) { 3790 IndexEntry Entry; 3791 3792 Entry.FunctionOffset = readNext<uint32_t>(Pos); 3793 Entry.SecondLevelPageStart = readNext<uint32_t>(Pos); 3794 Entry.LSDAStart = readNext<uint32_t>(Pos); 3795 IndexEntries.push_back(Entry); 3796 3797 outs() << " [" << i << "]: " 3798 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 3799 << ", " 3800 << "2nd level page offset=" 3801 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 3802 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 3803 } 3804 3805 //===---------------------------------- 3806 // Next come the LSDA tables 3807 //===---------------------------------- 3808 3809 // The LSDA layout is rather implicit: it's a contiguous array of entries from 3810 // the first top-level index's LSDAOffset to the last (sentinel). 3811 3812 outs() << " LSDA descriptors:\n"; 3813 Pos = Contents.data() + IndexEntries[0].LSDAStart; 3814 int NumLSDAs = (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / 3815 (2 * sizeof(uint32_t)); 3816 for (int i = 0; i < NumLSDAs; ++i) { 3817 uint32_t FunctionOffset = readNext<uint32_t>(Pos); 3818 uint32_t LSDAOffset = readNext<uint32_t>(Pos); 3819 outs() << " [" << i << "]: " 3820 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 3821 << ", " 3822 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 3823 } 3824 3825 //===---------------------------------- 3826 // Finally, the 2nd level indices 3827 //===---------------------------------- 3828 3829 // Generally these are 4K in size, and have 2 possible forms: 3830 // + Regular stores up to 511 entries with disparate encodings 3831 // + Compressed stores up to 1021 entries if few enough compact encoding 3832 // values are used. 3833 outs() << " Second level indices:\n"; 3834 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 3835 // The final sentinel top-level index has no associated 2nd level page 3836 if (IndexEntries[i].SecondLevelPageStart == 0) 3837 break; 3838 3839 outs() << " Second level index[" << i << "]: " 3840 << "offset in section=" 3841 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 3842 << ", " 3843 << "base function offset=" 3844 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 3845 3846 Pos = Contents.data() + IndexEntries[i].SecondLevelPageStart; 3847 uint32_t Kind = *reinterpret_cast<const support::ulittle32_t *>(Pos); 3848 if (Kind == 2) 3849 printRegularSecondLevelUnwindPage(Pos); 3850 else if (Kind == 3) 3851 printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset, 3852 CommonEncodings); 3853 else 3854 llvm_unreachable("Do not know how to print this kind of 2nd level page"); 3855 } 3856} 3857 3858void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { 3859 std::map<uint64_t, SymbolRef> Symbols; 3860 for (const SymbolRef &SymRef : Obj->symbols()) { 3861 // Discard any undefined or absolute symbols. They're not going to take part 3862 // in the convenience lookup for unwind info and just take up resources. 3863 section_iterator Section = Obj->section_end(); 3864 SymRef.getSection(Section); 3865 if (Section == Obj->section_end()) 3866 continue; 3867 3868 uint64_t Addr; 3869 SymRef.getAddress(Addr); 3870 Symbols.insert(std::make_pair(Addr, SymRef)); 3871 } 3872 3873 for (const SectionRef &Section : Obj->sections()) { 3874 StringRef SectName; 3875 Section.getName(SectName); 3876 if (SectName == "__compact_unwind") 3877 printMachOCompactUnwindSection(Obj, Symbols, Section); 3878 else if (SectName == "__unwind_info") 3879 printMachOUnwindInfoSection(Obj, Symbols, Section); 3880 else if (SectName == "__eh_frame") 3881 outs() << "llvm-objdump: warning: unhandled __eh_frame section\n"; 3882 } 3883} 3884 3885static void PrintMachHeader(uint32_t magic, uint32_t cputype, 3886 uint32_t cpusubtype, uint32_t filetype, 3887 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 3888 bool verbose) { 3889 outs() << "Mach header\n"; 3890 outs() << " magic cputype cpusubtype caps filetype ncmds " 3891 "sizeofcmds flags\n"; 3892 if (verbose) { 3893 if (magic == MachO::MH_MAGIC) 3894 outs() << " MH_MAGIC"; 3895 else if (magic == MachO::MH_MAGIC_64) 3896 outs() << "MH_MAGIC_64"; 3897 else 3898 outs() << format(" 0x%08" PRIx32, magic); 3899 switch (cputype) { 3900 case MachO::CPU_TYPE_I386: 3901 outs() << " I386"; 3902 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 3903 case MachO::CPU_SUBTYPE_I386_ALL: 3904 outs() << " ALL"; 3905 break; 3906 default: 3907 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 3908 break; 3909 } 3910 break; 3911 case MachO::CPU_TYPE_X86_64: 3912 outs() << " X86_64"; 3913 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 3914 case MachO::CPU_SUBTYPE_X86_64_ALL: 3915 outs() << " ALL"; 3916 break; 3917 case MachO::CPU_SUBTYPE_X86_64_H: 3918 outs() << " Haswell"; 3919 break; 3920 default: 3921 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 3922 break; 3923 } 3924 break; 3925 case MachO::CPU_TYPE_ARM: 3926 outs() << " ARM"; 3927 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 3928 case MachO::CPU_SUBTYPE_ARM_ALL: 3929 outs() << " ALL"; 3930 break; 3931 case MachO::CPU_SUBTYPE_ARM_V4T: 3932 outs() << " V4T"; 3933 break; 3934 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 3935 outs() << " V5TEJ"; 3936 break; 3937 case MachO::CPU_SUBTYPE_ARM_XSCALE: 3938 outs() << " XSCALE"; 3939 break; 3940 case MachO::CPU_SUBTYPE_ARM_V6: 3941 outs() << " V6"; 3942 break; 3943 case MachO::CPU_SUBTYPE_ARM_V6M: 3944 outs() << " V6M"; 3945 break; 3946 case MachO::CPU_SUBTYPE_ARM_V7: 3947 outs() << " V7"; 3948 break; 3949 case MachO::CPU_SUBTYPE_ARM_V7EM: 3950 outs() << " V7EM"; 3951 break; 3952 case MachO::CPU_SUBTYPE_ARM_V7K: 3953 outs() << " V7K"; 3954 break; 3955 case MachO::CPU_SUBTYPE_ARM_V7M: 3956 outs() << " V7M"; 3957 break; 3958 case MachO::CPU_SUBTYPE_ARM_V7S: 3959 outs() << " V7S"; 3960 break; 3961 default: 3962 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 3963 break; 3964 } 3965 break; 3966 case MachO::CPU_TYPE_ARM64: 3967 outs() << " ARM64"; 3968 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 3969 case MachO::CPU_SUBTYPE_ARM64_ALL: 3970 outs() << " ALL"; 3971 break; 3972 default: 3973 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 3974 break; 3975 } 3976 break; 3977 case MachO::CPU_TYPE_POWERPC: 3978 outs() << " PPC"; 3979 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 3980 case MachO::CPU_SUBTYPE_POWERPC_ALL: 3981 outs() << " ALL"; 3982 break; 3983 default: 3984 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 3985 break; 3986 } 3987 break; 3988 case MachO::CPU_TYPE_POWERPC64: 3989 outs() << " PPC64"; 3990 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 3991 case MachO::CPU_SUBTYPE_POWERPC_ALL: 3992 outs() << " ALL"; 3993 break; 3994 default: 3995 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 3996 break; 3997 } 3998 break; 3999 } 4000 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 4001 outs() << " LIB64"; 4002 } else { 4003 outs() << format(" 0x%02" PRIx32, 4004 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 4005 } 4006 switch (filetype) { 4007 case MachO::MH_OBJECT: 4008 outs() << " OBJECT"; 4009 break; 4010 case MachO::MH_EXECUTE: 4011 outs() << " EXECUTE"; 4012 break; 4013 case MachO::MH_FVMLIB: 4014 outs() << " FVMLIB"; 4015 break; 4016 case MachO::MH_CORE: 4017 outs() << " CORE"; 4018 break; 4019 case MachO::MH_PRELOAD: 4020 outs() << " PRELOAD"; 4021 break; 4022 case MachO::MH_DYLIB: 4023 outs() << " DYLIB"; 4024 break; 4025 case MachO::MH_DYLIB_STUB: 4026 outs() << " DYLIB_STUB"; 4027 break; 4028 case MachO::MH_DYLINKER: 4029 outs() << " DYLINKER"; 4030 break; 4031 case MachO::MH_BUNDLE: 4032 outs() << " BUNDLE"; 4033 break; 4034 case MachO::MH_DSYM: 4035 outs() << " DSYM"; 4036 break; 4037 case MachO::MH_KEXT_BUNDLE: 4038 outs() << " KEXTBUNDLE"; 4039 break; 4040 default: 4041 outs() << format(" %10u", filetype); 4042 break; 4043 } 4044 outs() << format(" %5u", ncmds); 4045 outs() << format(" %10u", sizeofcmds); 4046 uint32_t f = flags; 4047 if (f & MachO::MH_NOUNDEFS) { 4048 outs() << " NOUNDEFS"; 4049 f &= ~MachO::MH_NOUNDEFS; 4050 } 4051 if (f & MachO::MH_INCRLINK) { 4052 outs() << " INCRLINK"; 4053 f &= ~MachO::MH_INCRLINK; 4054 } 4055 if (f & MachO::MH_DYLDLINK) { 4056 outs() << " DYLDLINK"; 4057 f &= ~MachO::MH_DYLDLINK; 4058 } 4059 if (f & MachO::MH_BINDATLOAD) { 4060 outs() << " BINDATLOAD"; 4061 f &= ~MachO::MH_BINDATLOAD; 4062 } 4063 if (f & MachO::MH_PREBOUND) { 4064 outs() << " PREBOUND"; 4065 f &= ~MachO::MH_PREBOUND; 4066 } 4067 if (f & MachO::MH_SPLIT_SEGS) { 4068 outs() << " SPLIT_SEGS"; 4069 f &= ~MachO::MH_SPLIT_SEGS; 4070 } 4071 if (f & MachO::MH_LAZY_INIT) { 4072 outs() << " LAZY_INIT"; 4073 f &= ~MachO::MH_LAZY_INIT; 4074 } 4075 if (f & MachO::MH_TWOLEVEL) { 4076 outs() << " TWOLEVEL"; 4077 f &= ~MachO::MH_TWOLEVEL; 4078 } 4079 if (f & MachO::MH_FORCE_FLAT) { 4080 outs() << " FORCE_FLAT"; 4081 f &= ~MachO::MH_FORCE_FLAT; 4082 } 4083 if (f & MachO::MH_NOMULTIDEFS) { 4084 outs() << " NOMULTIDEFS"; 4085 f &= ~MachO::MH_NOMULTIDEFS; 4086 } 4087 if (f & MachO::MH_NOFIXPREBINDING) { 4088 outs() << " NOFIXPREBINDING"; 4089 f &= ~MachO::MH_NOFIXPREBINDING; 4090 } 4091 if (f & MachO::MH_PREBINDABLE) { 4092 outs() << " PREBINDABLE"; 4093 f &= ~MachO::MH_PREBINDABLE; 4094 } 4095 if (f & MachO::MH_ALLMODSBOUND) { 4096 outs() << " ALLMODSBOUND"; 4097 f &= ~MachO::MH_ALLMODSBOUND; 4098 } 4099 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 4100 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 4101 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 4102 } 4103 if (f & MachO::MH_CANONICAL) { 4104 outs() << " CANONICAL"; 4105 f &= ~MachO::MH_CANONICAL; 4106 } 4107 if (f & MachO::MH_WEAK_DEFINES) { 4108 outs() << " WEAK_DEFINES"; 4109 f &= ~MachO::MH_WEAK_DEFINES; 4110 } 4111 if (f & MachO::MH_BINDS_TO_WEAK) { 4112 outs() << " BINDS_TO_WEAK"; 4113 f &= ~MachO::MH_BINDS_TO_WEAK; 4114 } 4115 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 4116 outs() << " ALLOW_STACK_EXECUTION"; 4117 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 4118 } 4119 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 4120 outs() << " DEAD_STRIPPABLE_DYLIB"; 4121 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 4122 } 4123 if (f & MachO::MH_PIE) { 4124 outs() << " PIE"; 4125 f &= ~MachO::MH_PIE; 4126 } 4127 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 4128 outs() << " NO_REEXPORTED_DYLIBS"; 4129 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 4130 } 4131 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 4132 outs() << " MH_HAS_TLV_DESCRIPTORS"; 4133 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 4134 } 4135 if (f & MachO::MH_NO_HEAP_EXECUTION) { 4136 outs() << " MH_NO_HEAP_EXECUTION"; 4137 f &= ~MachO::MH_NO_HEAP_EXECUTION; 4138 } 4139 if (f & MachO::MH_APP_EXTENSION_SAFE) { 4140 outs() << " APP_EXTENSION_SAFE"; 4141 f &= ~MachO::MH_APP_EXTENSION_SAFE; 4142 } 4143 if (f != 0 || flags == 0) 4144 outs() << format(" 0x%08" PRIx32, f); 4145 } else { 4146 outs() << format(" 0x%08" PRIx32, magic); 4147 outs() << format(" %7d", cputype); 4148 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 4149 outs() << format(" 0x%02" PRIx32, 4150 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 4151 outs() << format(" %10u", filetype); 4152 outs() << format(" %5u", ncmds); 4153 outs() << format(" %10u", sizeofcmds); 4154 outs() << format(" 0x%08" PRIx32, flags); 4155 } 4156 outs() << "\n"; 4157} 4158 4159static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 4160 StringRef SegName, uint64_t vmaddr, 4161 uint64_t vmsize, uint64_t fileoff, 4162 uint64_t filesize, uint32_t maxprot, 4163 uint32_t initprot, uint32_t nsects, 4164 uint32_t flags, uint32_t object_size, 4165 bool verbose) { 4166 uint64_t expected_cmdsize; 4167 if (cmd == MachO::LC_SEGMENT) { 4168 outs() << " cmd LC_SEGMENT\n"; 4169 expected_cmdsize = nsects; 4170 expected_cmdsize *= sizeof(struct MachO::section); 4171 expected_cmdsize += sizeof(struct MachO::segment_command); 4172 } else { 4173 outs() << " cmd LC_SEGMENT_64\n"; 4174 expected_cmdsize = nsects; 4175 expected_cmdsize *= sizeof(struct MachO::section_64); 4176 expected_cmdsize += sizeof(struct MachO::segment_command_64); 4177 } 4178 outs() << " cmdsize " << cmdsize; 4179 if (cmdsize != expected_cmdsize) 4180 outs() << " Inconsistent size\n"; 4181 else 4182 outs() << "\n"; 4183 outs() << " segname " << SegName << "\n"; 4184 if (cmd == MachO::LC_SEGMENT_64) { 4185 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 4186 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 4187 } else { 4188 outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n"; 4189 outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n"; 4190 } 4191 outs() << " fileoff " << fileoff; 4192 if (fileoff > object_size) 4193 outs() << " (past end of file)\n"; 4194 else 4195 outs() << "\n"; 4196 outs() << " filesize " << filesize; 4197 if (fileoff + filesize > object_size) 4198 outs() << " (past end of file)\n"; 4199 else 4200 outs() << "\n"; 4201 if (verbose) { 4202 if ((maxprot & 4203 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 4204 MachO::VM_PROT_EXECUTE)) != 0) 4205 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 4206 else { 4207 if (maxprot & MachO::VM_PROT_READ) 4208 outs() << " maxprot r"; 4209 else 4210 outs() << " maxprot -"; 4211 if (maxprot & MachO::VM_PROT_WRITE) 4212 outs() << "w"; 4213 else 4214 outs() << "-"; 4215 if (maxprot & MachO::VM_PROT_EXECUTE) 4216 outs() << "x\n"; 4217 else 4218 outs() << "-\n"; 4219 } 4220 if ((initprot & 4221 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 4222 MachO::VM_PROT_EXECUTE)) != 0) 4223 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 4224 else { 4225 if (initprot & MachO::VM_PROT_READ) 4226 outs() << " initprot r"; 4227 else 4228 outs() << " initprot -"; 4229 if (initprot & MachO::VM_PROT_WRITE) 4230 outs() << "w"; 4231 else 4232 outs() << "-"; 4233 if (initprot & MachO::VM_PROT_EXECUTE) 4234 outs() << "x\n"; 4235 else 4236 outs() << "-\n"; 4237 } 4238 } else { 4239 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 4240 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 4241 } 4242 outs() << " nsects " << nsects << "\n"; 4243 if (verbose) { 4244 outs() << " flags"; 4245 if (flags == 0) 4246 outs() << " (none)\n"; 4247 else { 4248 if (flags & MachO::SG_HIGHVM) { 4249 outs() << " HIGHVM"; 4250 flags &= ~MachO::SG_HIGHVM; 4251 } 4252 if (flags & MachO::SG_FVMLIB) { 4253 outs() << " FVMLIB"; 4254 flags &= ~MachO::SG_FVMLIB; 4255 } 4256 if (flags & MachO::SG_NORELOC) { 4257 outs() << " NORELOC"; 4258 flags &= ~MachO::SG_NORELOC; 4259 } 4260 if (flags & MachO::SG_PROTECTED_VERSION_1) { 4261 outs() << " PROTECTED_VERSION_1"; 4262 flags &= ~MachO::SG_PROTECTED_VERSION_1; 4263 } 4264 if (flags) 4265 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 4266 else 4267 outs() << "\n"; 4268 } 4269 } else { 4270 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 4271 } 4272} 4273 4274static void PrintSection(const char *sectname, const char *segname, 4275 uint64_t addr, uint64_t size, uint32_t offset, 4276 uint32_t align, uint32_t reloff, uint32_t nreloc, 4277 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 4278 uint32_t cmd, const char *sg_segname, 4279 uint32_t filetype, uint32_t object_size, 4280 bool verbose) { 4281 outs() << "Section\n"; 4282 outs() << " sectname " << format("%.16s\n", sectname); 4283 outs() << " segname " << format("%.16s", segname); 4284 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 4285 outs() << " (does not match segment)\n"; 4286 else 4287 outs() << "\n"; 4288 if (cmd == MachO::LC_SEGMENT_64) { 4289 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 4290 outs() << " size " << format("0x%016" PRIx64, size); 4291 } else { 4292 outs() << " addr " << format("0x%08" PRIx64, addr) << "\n"; 4293 outs() << " size " << format("0x%08" PRIx64, size); 4294 } 4295 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 4296 outs() << " (past end of file)\n"; 4297 else 4298 outs() << "\n"; 4299 outs() << " offset " << offset; 4300 if (offset > object_size) 4301 outs() << " (past end of file)\n"; 4302 else 4303 outs() << "\n"; 4304 uint32_t align_shifted = 1 << align; 4305 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 4306 outs() << " reloff " << reloff; 4307 if (reloff > object_size) 4308 outs() << " (past end of file)\n"; 4309 else 4310 outs() << "\n"; 4311 outs() << " nreloc " << nreloc; 4312 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 4313 outs() << " (past end of file)\n"; 4314 else 4315 outs() << "\n"; 4316 uint32_t section_type = flags & MachO::SECTION_TYPE; 4317 if (verbose) { 4318 outs() << " type"; 4319 if (section_type == MachO::S_REGULAR) 4320 outs() << " S_REGULAR\n"; 4321 else if (section_type == MachO::S_ZEROFILL) 4322 outs() << " S_ZEROFILL\n"; 4323 else if (section_type == MachO::S_CSTRING_LITERALS) 4324 outs() << " S_CSTRING_LITERALS\n"; 4325 else if (section_type == MachO::S_4BYTE_LITERALS) 4326 outs() << " S_4BYTE_LITERALS\n"; 4327 else if (section_type == MachO::S_8BYTE_LITERALS) 4328 outs() << " S_8BYTE_LITERALS\n"; 4329 else if (section_type == MachO::S_16BYTE_LITERALS) 4330 outs() << " S_16BYTE_LITERALS\n"; 4331 else if (section_type == MachO::S_LITERAL_POINTERS) 4332 outs() << " S_LITERAL_POINTERS\n"; 4333 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 4334 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 4335 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 4336 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 4337 else if (section_type == MachO::S_SYMBOL_STUBS) 4338 outs() << " S_SYMBOL_STUBS\n"; 4339 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 4340 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 4341 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 4342 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 4343 else if (section_type == MachO::S_COALESCED) 4344 outs() << " S_COALESCED\n"; 4345 else if (section_type == MachO::S_INTERPOSING) 4346 outs() << " S_INTERPOSING\n"; 4347 else if (section_type == MachO::S_DTRACE_DOF) 4348 outs() << " S_DTRACE_DOF\n"; 4349 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 4350 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 4351 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 4352 outs() << " S_THREAD_LOCAL_REGULAR\n"; 4353 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 4354 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 4355 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 4356 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 4357 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 4358 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 4359 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 4360 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 4361 else 4362 outs() << format("0x%08" PRIx32, section_type) << "\n"; 4363 outs() << "attributes"; 4364 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 4365 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 4366 outs() << " PURE_INSTRUCTIONS"; 4367 if (section_attributes & MachO::S_ATTR_NO_TOC) 4368 outs() << " NO_TOC"; 4369 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 4370 outs() << " STRIP_STATIC_SYMS"; 4371 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 4372 outs() << " NO_DEAD_STRIP"; 4373 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 4374 outs() << " LIVE_SUPPORT"; 4375 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 4376 outs() << " SELF_MODIFYING_CODE"; 4377 if (section_attributes & MachO::S_ATTR_DEBUG) 4378 outs() << " DEBUG"; 4379 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 4380 outs() << " SOME_INSTRUCTIONS"; 4381 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 4382 outs() << " EXT_RELOC"; 4383 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 4384 outs() << " LOC_RELOC"; 4385 if (section_attributes == 0) 4386 outs() << " (none)"; 4387 outs() << "\n"; 4388 } else 4389 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 4390 outs() << " reserved1 " << reserved1; 4391 if (section_type == MachO::S_SYMBOL_STUBS || 4392 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 4393 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 4394 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 4395 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 4396 outs() << " (index into indirect symbol table)\n"; 4397 else 4398 outs() << "\n"; 4399 outs() << " reserved2 " << reserved2; 4400 if (section_type == MachO::S_SYMBOL_STUBS) 4401 outs() << " (size of stubs)\n"; 4402 else 4403 outs() << "\n"; 4404} 4405 4406static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 4407 uint32_t object_size) { 4408 outs() << " cmd LC_SYMTAB\n"; 4409 outs() << " cmdsize " << st.cmdsize; 4410 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 4411 outs() << " Incorrect size\n"; 4412 else 4413 outs() << "\n"; 4414 outs() << " symoff " << st.symoff; 4415 if (st.symoff > object_size) 4416 outs() << " (past end of file)\n"; 4417 else 4418 outs() << "\n"; 4419 outs() << " nsyms " << st.nsyms; 4420 uint64_t big_size; 4421 if (Is64Bit) { 4422 big_size = st.nsyms; 4423 big_size *= sizeof(struct MachO::nlist_64); 4424 big_size += st.symoff; 4425 if (big_size > object_size) 4426 outs() << " (past end of file)\n"; 4427 else 4428 outs() << "\n"; 4429 } else { 4430 big_size = st.nsyms; 4431 big_size *= sizeof(struct MachO::nlist); 4432 big_size += st.symoff; 4433 if (big_size > object_size) 4434 outs() << " (past end of file)\n"; 4435 else 4436 outs() << "\n"; 4437 } 4438 outs() << " stroff " << st.stroff; 4439 if (st.stroff > object_size) 4440 outs() << " (past end of file)\n"; 4441 else 4442 outs() << "\n"; 4443 outs() << " strsize " << st.strsize; 4444 big_size = st.stroff; 4445 big_size += st.strsize; 4446 if (big_size > object_size) 4447 outs() << " (past end of file)\n"; 4448 else 4449 outs() << "\n"; 4450} 4451 4452static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 4453 uint32_t nsyms, uint32_t object_size, 4454 bool Is64Bit) { 4455 outs() << " cmd LC_DYSYMTAB\n"; 4456 outs() << " cmdsize " << dyst.cmdsize; 4457 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 4458 outs() << " Incorrect size\n"; 4459 else 4460 outs() << "\n"; 4461 outs() << " ilocalsym " << dyst.ilocalsym; 4462 if (dyst.ilocalsym > nsyms) 4463 outs() << " (greater than the number of symbols)\n"; 4464 else 4465 outs() << "\n"; 4466 outs() << " nlocalsym " << dyst.nlocalsym; 4467 uint64_t big_size; 4468 big_size = dyst.ilocalsym; 4469 big_size += dyst.nlocalsym; 4470 if (big_size > nsyms) 4471 outs() << " (past the end of the symbol table)\n"; 4472 else 4473 outs() << "\n"; 4474 outs() << " iextdefsym " << dyst.iextdefsym; 4475 if (dyst.iextdefsym > nsyms) 4476 outs() << " (greater than the number of symbols)\n"; 4477 else 4478 outs() << "\n"; 4479 outs() << " nextdefsym " << dyst.nextdefsym; 4480 big_size = dyst.iextdefsym; 4481 big_size += dyst.nextdefsym; 4482 if (big_size > nsyms) 4483 outs() << " (past the end of the symbol table)\n"; 4484 else 4485 outs() << "\n"; 4486 outs() << " iundefsym " << dyst.iundefsym; 4487 if (dyst.iundefsym > nsyms) 4488 outs() << " (greater than the number of symbols)\n"; 4489 else 4490 outs() << "\n"; 4491 outs() << " nundefsym " << dyst.nundefsym; 4492 big_size = dyst.iundefsym; 4493 big_size += dyst.nundefsym; 4494 if (big_size > nsyms) 4495 outs() << " (past the end of the symbol table)\n"; 4496 else 4497 outs() << "\n"; 4498 outs() << " tocoff " << dyst.tocoff; 4499 if (dyst.tocoff > object_size) 4500 outs() << " (past end of file)\n"; 4501 else 4502 outs() << "\n"; 4503 outs() << " ntoc " << dyst.ntoc; 4504 big_size = dyst.ntoc; 4505 big_size *= sizeof(struct MachO::dylib_table_of_contents); 4506 big_size += dyst.tocoff; 4507 if (big_size > object_size) 4508 outs() << " (past end of file)\n"; 4509 else 4510 outs() << "\n"; 4511 outs() << " modtaboff " << dyst.modtaboff; 4512 if (dyst.modtaboff > object_size) 4513 outs() << " (past end of file)\n"; 4514 else 4515 outs() << "\n"; 4516 outs() << " nmodtab " << dyst.nmodtab; 4517 uint64_t modtabend; 4518 if (Is64Bit) { 4519 modtabend = dyst.nmodtab; 4520 modtabend *= sizeof(struct MachO::dylib_module_64); 4521 modtabend += dyst.modtaboff; 4522 } else { 4523 modtabend = dyst.nmodtab; 4524 modtabend *= sizeof(struct MachO::dylib_module); 4525 modtabend += dyst.modtaboff; 4526 } 4527 if (modtabend > object_size) 4528 outs() << " (past end of file)\n"; 4529 else 4530 outs() << "\n"; 4531 outs() << " extrefsymoff " << dyst.extrefsymoff; 4532 if (dyst.extrefsymoff > object_size) 4533 outs() << " (past end of file)\n"; 4534 else 4535 outs() << "\n"; 4536 outs() << " nextrefsyms " << dyst.nextrefsyms; 4537 big_size = dyst.nextrefsyms; 4538 big_size *= sizeof(struct MachO::dylib_reference); 4539 big_size += dyst.extrefsymoff; 4540 if (big_size > object_size) 4541 outs() << " (past end of file)\n"; 4542 else 4543 outs() << "\n"; 4544 outs() << " indirectsymoff " << dyst.indirectsymoff; 4545 if (dyst.indirectsymoff > object_size) 4546 outs() << " (past end of file)\n"; 4547 else 4548 outs() << "\n"; 4549 outs() << " nindirectsyms " << dyst.nindirectsyms; 4550 big_size = dyst.nindirectsyms; 4551 big_size *= sizeof(uint32_t); 4552 big_size += dyst.indirectsymoff; 4553 if (big_size > object_size) 4554 outs() << " (past end of file)\n"; 4555 else 4556 outs() << "\n"; 4557 outs() << " extreloff " << dyst.extreloff; 4558 if (dyst.extreloff > object_size) 4559 outs() << " (past end of file)\n"; 4560 else 4561 outs() << "\n"; 4562 outs() << " nextrel " << dyst.nextrel; 4563 big_size = dyst.nextrel; 4564 big_size *= sizeof(struct MachO::relocation_info); 4565 big_size += dyst.extreloff; 4566 if (big_size > object_size) 4567 outs() << " (past end of file)\n"; 4568 else 4569 outs() << "\n"; 4570 outs() << " locreloff " << dyst.locreloff; 4571 if (dyst.locreloff > object_size) 4572 outs() << " (past end of file)\n"; 4573 else 4574 outs() << "\n"; 4575 outs() << " nlocrel " << dyst.nlocrel; 4576 big_size = dyst.nlocrel; 4577 big_size *= sizeof(struct MachO::relocation_info); 4578 big_size += dyst.locreloff; 4579 if (big_size > object_size) 4580 outs() << " (past end of file)\n"; 4581 else 4582 outs() << "\n"; 4583} 4584 4585static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 4586 uint32_t object_size) { 4587 if (dc.cmd == MachO::LC_DYLD_INFO) 4588 outs() << " cmd LC_DYLD_INFO\n"; 4589 else 4590 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 4591 outs() << " cmdsize " << dc.cmdsize; 4592 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 4593 outs() << " Incorrect size\n"; 4594 else 4595 outs() << "\n"; 4596 outs() << " rebase_off " << dc.rebase_off; 4597 if (dc.rebase_off > object_size) 4598 outs() << " (past end of file)\n"; 4599 else 4600 outs() << "\n"; 4601 outs() << " rebase_size " << dc.rebase_size; 4602 uint64_t big_size; 4603 big_size = dc.rebase_off; 4604 big_size += dc.rebase_size; 4605 if (big_size > object_size) 4606 outs() << " (past end of file)\n"; 4607 else 4608 outs() << "\n"; 4609 outs() << " bind_off " << dc.bind_off; 4610 if (dc.bind_off > object_size) 4611 outs() << " (past end of file)\n"; 4612 else 4613 outs() << "\n"; 4614 outs() << " bind_size " << dc.bind_size; 4615 big_size = dc.bind_off; 4616 big_size += dc.bind_size; 4617 if (big_size > object_size) 4618 outs() << " (past end of file)\n"; 4619 else 4620 outs() << "\n"; 4621 outs() << " weak_bind_off " << dc.weak_bind_off; 4622 if (dc.weak_bind_off > object_size) 4623 outs() << " (past end of file)\n"; 4624 else 4625 outs() << "\n"; 4626 outs() << " weak_bind_size " << dc.weak_bind_size; 4627 big_size = dc.weak_bind_off; 4628 big_size += dc.weak_bind_size; 4629 if (big_size > object_size) 4630 outs() << " (past end of file)\n"; 4631 else 4632 outs() << "\n"; 4633 outs() << " lazy_bind_off " << dc.lazy_bind_off; 4634 if (dc.lazy_bind_off > object_size) 4635 outs() << " (past end of file)\n"; 4636 else 4637 outs() << "\n"; 4638 outs() << " lazy_bind_size " << dc.lazy_bind_size; 4639 big_size = dc.lazy_bind_off; 4640 big_size += dc.lazy_bind_size; 4641 if (big_size > object_size) 4642 outs() << " (past end of file)\n"; 4643 else 4644 outs() << "\n"; 4645 outs() << " export_off " << dc.export_off; 4646 if (dc.export_off > object_size) 4647 outs() << " (past end of file)\n"; 4648 else 4649 outs() << "\n"; 4650 outs() << " export_size " << dc.export_size; 4651 big_size = dc.export_off; 4652 big_size += dc.export_size; 4653 if (big_size > object_size) 4654 outs() << " (past end of file)\n"; 4655 else 4656 outs() << "\n"; 4657} 4658 4659static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 4660 const char *Ptr) { 4661 if (dyld.cmd == MachO::LC_ID_DYLINKER) 4662 outs() << " cmd LC_ID_DYLINKER\n"; 4663 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 4664 outs() << " cmd LC_LOAD_DYLINKER\n"; 4665 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 4666 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 4667 else 4668 outs() << " cmd ?(" << dyld.cmd << ")\n"; 4669 outs() << " cmdsize " << dyld.cmdsize; 4670 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 4671 outs() << " Incorrect size\n"; 4672 else 4673 outs() << "\n"; 4674 if (dyld.name >= dyld.cmdsize) 4675 outs() << " name ?(bad offset " << dyld.name << ")\n"; 4676 else { 4677 const char *P = (const char *)(Ptr) + dyld.name; 4678 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 4679 } 4680} 4681 4682static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 4683 outs() << " cmd LC_UUID\n"; 4684 outs() << " cmdsize " << uuid.cmdsize; 4685 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 4686 outs() << " Incorrect size\n"; 4687 else 4688 outs() << "\n"; 4689 outs() << " uuid "; 4690 outs() << format("%02" PRIX32, uuid.uuid[0]); 4691 outs() << format("%02" PRIX32, uuid.uuid[1]); 4692 outs() << format("%02" PRIX32, uuid.uuid[2]); 4693 outs() << format("%02" PRIX32, uuid.uuid[3]); 4694 outs() << "-"; 4695 outs() << format("%02" PRIX32, uuid.uuid[4]); 4696 outs() << format("%02" PRIX32, uuid.uuid[5]); 4697 outs() << "-"; 4698 outs() << format("%02" PRIX32, uuid.uuid[6]); 4699 outs() << format("%02" PRIX32, uuid.uuid[7]); 4700 outs() << "-"; 4701 outs() << format("%02" PRIX32, uuid.uuid[8]); 4702 outs() << format("%02" PRIX32, uuid.uuid[9]); 4703 outs() << "-"; 4704 outs() << format("%02" PRIX32, uuid.uuid[10]); 4705 outs() << format("%02" PRIX32, uuid.uuid[11]); 4706 outs() << format("%02" PRIX32, uuid.uuid[12]); 4707 outs() << format("%02" PRIX32, uuid.uuid[13]); 4708 outs() << format("%02" PRIX32, uuid.uuid[14]); 4709 outs() << format("%02" PRIX32, uuid.uuid[15]); 4710 outs() << "\n"; 4711} 4712 4713static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) { 4714 outs() << " cmd LC_RPATH\n"; 4715 outs() << " cmdsize " << rpath.cmdsize; 4716 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 4717 outs() << " Incorrect size\n"; 4718 else 4719 outs() << "\n"; 4720 if (rpath.path >= rpath.cmdsize) 4721 outs() << " path ?(bad offset " << rpath.path << ")\n"; 4722 else { 4723 const char *P = (const char *)(Ptr) + rpath.path; 4724 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 4725 } 4726} 4727 4728static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 4729 if (vd.cmd == MachO::LC_VERSION_MIN_MACOSX) 4730 outs() << " cmd LC_VERSION_MIN_MACOSX\n"; 4731 else if (vd.cmd == MachO::LC_VERSION_MIN_IPHONEOS) 4732 outs() << " cmd LC_VERSION_MIN_IPHONEOS\n"; 4733 else 4734 outs() << " cmd " << vd.cmd << " (?)\n"; 4735 outs() << " cmdsize " << vd.cmdsize; 4736 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 4737 outs() << " Incorrect size\n"; 4738 else 4739 outs() << "\n"; 4740 outs() << " version " << ((vd.version >> 16) & 0xffff) << "." 4741 << ((vd.version >> 8) & 0xff); 4742 if ((vd.version & 0xff) != 0) 4743 outs() << "." << (vd.version & 0xff); 4744 outs() << "\n"; 4745 if (vd.sdk == 0) 4746 outs() << " sdk n/a"; 4747 else { 4748 outs() << " sdk " << ((vd.sdk >> 16) & 0xffff) << "." 4749 << ((vd.sdk >> 8) & 0xff); 4750 } 4751 if ((vd.sdk & 0xff) != 0) 4752 outs() << "." << (vd.sdk & 0xff); 4753 outs() << "\n"; 4754} 4755 4756static void PrintSourceVersionCommand(MachO::source_version_command sd) { 4757 outs() << " cmd LC_SOURCE_VERSION\n"; 4758 outs() << " cmdsize " << sd.cmdsize; 4759 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 4760 outs() << " Incorrect size\n"; 4761 else 4762 outs() << "\n"; 4763 uint64_t a = (sd.version >> 40) & 0xffffff; 4764 uint64_t b = (sd.version >> 30) & 0x3ff; 4765 uint64_t c = (sd.version >> 20) & 0x3ff; 4766 uint64_t d = (sd.version >> 10) & 0x3ff; 4767 uint64_t e = sd.version & 0x3ff; 4768 outs() << " version " << a << "." << b; 4769 if (e != 0) 4770 outs() << "." << c << "." << d << "." << e; 4771 else if (d != 0) 4772 outs() << "." << c << "." << d; 4773 else if (c != 0) 4774 outs() << "." << c; 4775 outs() << "\n"; 4776} 4777 4778static void PrintEntryPointCommand(MachO::entry_point_command ep) { 4779 outs() << " cmd LC_MAIN\n"; 4780 outs() << " cmdsize " << ep.cmdsize; 4781 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 4782 outs() << " Incorrect size\n"; 4783 else 4784 outs() << "\n"; 4785 outs() << " entryoff " << ep.entryoff << "\n"; 4786 outs() << " stacksize " << ep.stacksize << "\n"; 4787} 4788 4789static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec, 4790 uint32_t object_size) { 4791 outs() << " cmd LC_ENCRYPTION_INFO\n"; 4792 outs() << " cmdsize " << ec.cmdsize; 4793 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command)) 4794 outs() << " Incorrect size\n"; 4795 else 4796 outs() << "\n"; 4797 outs() << " cryptoff " << ec.cryptoff; 4798 if (ec.cryptoff > object_size) 4799 outs() << " (past end of file)\n"; 4800 else 4801 outs() << "\n"; 4802 outs() << " cryptsize " << ec.cryptsize; 4803 if (ec.cryptsize > object_size) 4804 outs() << " (past end of file)\n"; 4805 else 4806 outs() << "\n"; 4807 outs() << " cryptid " << ec.cryptid << "\n"; 4808} 4809 4810static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec, 4811 uint32_t object_size) { 4812 outs() << " cmd LC_ENCRYPTION_INFO_64\n"; 4813 outs() << " cmdsize " << ec.cmdsize; 4814 if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64)) 4815 outs() << " Incorrect size\n"; 4816 else 4817 outs() << "\n"; 4818 outs() << " cryptoff " << ec.cryptoff; 4819 if (ec.cryptoff > object_size) 4820 outs() << " (past end of file)\n"; 4821 else 4822 outs() << "\n"; 4823 outs() << " cryptsize " << ec.cryptsize; 4824 if (ec.cryptsize > object_size) 4825 outs() << " (past end of file)\n"; 4826 else 4827 outs() << "\n"; 4828 outs() << " cryptid " << ec.cryptid << "\n"; 4829 outs() << " pad " << ec.pad << "\n"; 4830} 4831 4832static void PrintLinkerOptionCommand(MachO::linker_option_command lo, 4833 const char *Ptr) { 4834 outs() << " cmd LC_LINKER_OPTION\n"; 4835 outs() << " cmdsize " << lo.cmdsize; 4836 if (lo.cmdsize < sizeof(struct MachO::linker_option_command)) 4837 outs() << " Incorrect size\n"; 4838 else 4839 outs() << "\n"; 4840 outs() << " count " << lo.count << "\n"; 4841 const char *string = Ptr + sizeof(struct MachO::linker_option_command); 4842 uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command); 4843 uint32_t i = 0; 4844 while (left > 0) { 4845 while (*string == '\0' && left > 0) { 4846 string++; 4847 left--; 4848 } 4849 if (left > 0) { 4850 i++; 4851 outs() << " string #" << i << " " << format("%.*s\n", left, string); 4852 uint32_t NullPos = StringRef(string, left).find('\0'); 4853 uint32_t len = std::min(NullPos, left) + 1; 4854 string += len; 4855 left -= len; 4856 } 4857 } 4858 if (lo.count != i) 4859 outs() << " count " << lo.count << " does not match number of strings " 4860 << i << "\n"; 4861} 4862 4863static void PrintSubFrameworkCommand(MachO::sub_framework_command sub, 4864 const char *Ptr) { 4865 outs() << " cmd LC_SUB_FRAMEWORK\n"; 4866 outs() << " cmdsize " << sub.cmdsize; 4867 if (sub.cmdsize < sizeof(struct MachO::sub_framework_command)) 4868 outs() << " Incorrect size\n"; 4869 else 4870 outs() << "\n"; 4871 if (sub.umbrella < sub.cmdsize) { 4872 const char *P = Ptr + sub.umbrella; 4873 outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n"; 4874 } else { 4875 outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n"; 4876 } 4877} 4878 4879static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub, 4880 const char *Ptr) { 4881 outs() << " cmd LC_SUB_UMBRELLA\n"; 4882 outs() << " cmdsize " << sub.cmdsize; 4883 if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command)) 4884 outs() << " Incorrect size\n"; 4885 else 4886 outs() << "\n"; 4887 if (sub.sub_umbrella < sub.cmdsize) { 4888 const char *P = Ptr + sub.sub_umbrella; 4889 outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n"; 4890 } else { 4891 outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n"; 4892 } 4893} 4894 4895static void PrintSubLibraryCommand(MachO::sub_library_command sub, 4896 const char *Ptr) { 4897 outs() << " cmd LC_SUB_LIBRARY\n"; 4898 outs() << " cmdsize " << sub.cmdsize; 4899 if (sub.cmdsize < sizeof(struct MachO::sub_library_command)) 4900 outs() << " Incorrect size\n"; 4901 else 4902 outs() << "\n"; 4903 if (sub.sub_library < sub.cmdsize) { 4904 const char *P = Ptr + sub.sub_library; 4905 outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n"; 4906 } else { 4907 outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n"; 4908 } 4909} 4910 4911static void PrintSubClientCommand(MachO::sub_client_command sub, 4912 const char *Ptr) { 4913 outs() << " cmd LC_SUB_CLIENT\n"; 4914 outs() << " cmdsize " << sub.cmdsize; 4915 if (sub.cmdsize < sizeof(struct MachO::sub_client_command)) 4916 outs() << " Incorrect size\n"; 4917 else 4918 outs() << "\n"; 4919 if (sub.client < sub.cmdsize) { 4920 const char *P = Ptr + sub.client; 4921 outs() << " client " << P << " (offset " << sub.client << ")\n"; 4922 } else { 4923 outs() << " client ?(bad offset " << sub.client << ")\n"; 4924 } 4925} 4926 4927static void PrintRoutinesCommand(MachO::routines_command r) { 4928 outs() << " cmd LC_ROUTINES\n"; 4929 outs() << " cmdsize " << r.cmdsize; 4930 if (r.cmdsize != sizeof(struct MachO::routines_command)) 4931 outs() << " Incorrect size\n"; 4932 else 4933 outs() << "\n"; 4934 outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n"; 4935 outs() << " init_module " << r.init_module << "\n"; 4936 outs() << " reserved1 " << r.reserved1 << "\n"; 4937 outs() << " reserved2 " << r.reserved2 << "\n"; 4938 outs() << " reserved3 " << r.reserved3 << "\n"; 4939 outs() << " reserved4 " << r.reserved4 << "\n"; 4940 outs() << " reserved5 " << r.reserved5 << "\n"; 4941 outs() << " reserved6 " << r.reserved6 << "\n"; 4942} 4943 4944static void PrintRoutinesCommand64(MachO::routines_command_64 r) { 4945 outs() << " cmd LC_ROUTINES_64\n"; 4946 outs() << " cmdsize " << r.cmdsize; 4947 if (r.cmdsize != sizeof(struct MachO::routines_command_64)) 4948 outs() << " Incorrect size\n"; 4949 else 4950 outs() << "\n"; 4951 outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n"; 4952 outs() << " init_module " << r.init_module << "\n"; 4953 outs() << " reserved1 " << r.reserved1 << "\n"; 4954 outs() << " reserved2 " << r.reserved2 << "\n"; 4955 outs() << " reserved3 " << r.reserved3 << "\n"; 4956 outs() << " reserved4 " << r.reserved4 << "\n"; 4957 outs() << " reserved5 " << r.reserved5 << "\n"; 4958 outs() << " reserved6 " << r.reserved6 << "\n"; 4959} 4960 4961static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) { 4962 outs() << " rax " << format("0x%016" PRIx64, cpu64.rax); 4963 outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx); 4964 outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n"; 4965 outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx); 4966 outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi); 4967 outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n"; 4968 outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp); 4969 outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp); 4970 outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n"; 4971 outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9); 4972 outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10); 4973 outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n"; 4974 outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12); 4975 outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13); 4976 outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n"; 4977 outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15); 4978 outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n"; 4979 outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags); 4980 outs() << " cs " << format("0x%016" PRIx64, cpu64.cs); 4981 outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n"; 4982 outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n"; 4983} 4984 4985static void Print_mmst_reg(MachO::mmst_reg_t &r) { 4986 uint32_t f; 4987 outs() << "\t mmst_reg "; 4988 for (f = 0; f < 10; f++) 4989 outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " "; 4990 outs() << "\n"; 4991 outs() << "\t mmst_rsrv "; 4992 for (f = 0; f < 6; f++) 4993 outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " "; 4994 outs() << "\n"; 4995} 4996 4997static void Print_xmm_reg(MachO::xmm_reg_t &r) { 4998 uint32_t f; 4999 outs() << "\t xmm_reg "; 5000 for (f = 0; f < 16; f++) 5001 outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " "; 5002 outs() << "\n"; 5003} 5004 5005static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) { 5006 outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0]; 5007 outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n"; 5008 outs() << "\t control: invalid " << fpu.fpu_fcw.invalid; 5009 outs() << " denorm " << fpu.fpu_fcw.denorm; 5010 outs() << " zdiv " << fpu.fpu_fcw.zdiv; 5011 outs() << " ovrfl " << fpu.fpu_fcw.ovrfl; 5012 outs() << " undfl " << fpu.fpu_fcw.undfl; 5013 outs() << " precis " << fpu.fpu_fcw.precis << "\n"; 5014 outs() << "\t\t pc "; 5015 if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B) 5016 outs() << "FP_PREC_24B "; 5017 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B) 5018 outs() << "FP_PREC_53B "; 5019 else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B) 5020 outs() << "FP_PREC_64B "; 5021 else 5022 outs() << fpu.fpu_fcw.pc << " "; 5023 outs() << "rc "; 5024 if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR) 5025 outs() << "FP_RND_NEAR "; 5026 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN) 5027 outs() << "FP_RND_DOWN "; 5028 else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP) 5029 outs() << "FP_RND_UP "; 5030 else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP) 5031 outs() << "FP_CHOP "; 5032 outs() << "\n"; 5033 outs() << "\t status: invalid " << fpu.fpu_fsw.invalid; 5034 outs() << " denorm " << fpu.fpu_fsw.denorm; 5035 outs() << " zdiv " << fpu.fpu_fsw.zdiv; 5036 outs() << " ovrfl " << fpu.fpu_fsw.ovrfl; 5037 outs() << " undfl " << fpu.fpu_fsw.undfl; 5038 outs() << " precis " << fpu.fpu_fsw.precis; 5039 outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n"; 5040 outs() << "\t errsumm " << fpu.fpu_fsw.errsumm; 5041 outs() << " c0 " << fpu.fpu_fsw.c0; 5042 outs() << " c1 " << fpu.fpu_fsw.c1; 5043 outs() << " c2 " << fpu.fpu_fsw.c2; 5044 outs() << " tos " << fpu.fpu_fsw.tos; 5045 outs() << " c3 " << fpu.fpu_fsw.c3; 5046 outs() << " busy " << fpu.fpu_fsw.busy << "\n"; 5047 outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw); 5048 outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1); 5049 outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop); 5050 outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n"; 5051 outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs); 5052 outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2); 5053 outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp); 5054 outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n"; 5055 outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3); 5056 outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr); 5057 outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask); 5058 outs() << "\n"; 5059 outs() << "\t fpu_stmm0:\n"; 5060 Print_mmst_reg(fpu.fpu_stmm0); 5061 outs() << "\t fpu_stmm1:\n"; 5062 Print_mmst_reg(fpu.fpu_stmm1); 5063 outs() << "\t fpu_stmm2:\n"; 5064 Print_mmst_reg(fpu.fpu_stmm2); 5065 outs() << "\t fpu_stmm3:\n"; 5066 Print_mmst_reg(fpu.fpu_stmm3); 5067 outs() << "\t fpu_stmm4:\n"; 5068 Print_mmst_reg(fpu.fpu_stmm4); 5069 outs() << "\t fpu_stmm5:\n"; 5070 Print_mmst_reg(fpu.fpu_stmm5); 5071 outs() << "\t fpu_stmm6:\n"; 5072 Print_mmst_reg(fpu.fpu_stmm6); 5073 outs() << "\t fpu_stmm7:\n"; 5074 Print_mmst_reg(fpu.fpu_stmm7); 5075 outs() << "\t fpu_xmm0:\n"; 5076 Print_xmm_reg(fpu.fpu_xmm0); 5077 outs() << "\t fpu_xmm1:\n"; 5078 Print_xmm_reg(fpu.fpu_xmm1); 5079 outs() << "\t fpu_xmm2:\n"; 5080 Print_xmm_reg(fpu.fpu_xmm2); 5081 outs() << "\t fpu_xmm3:\n"; 5082 Print_xmm_reg(fpu.fpu_xmm3); 5083 outs() << "\t fpu_xmm4:\n"; 5084 Print_xmm_reg(fpu.fpu_xmm4); 5085 outs() << "\t fpu_xmm5:\n"; 5086 Print_xmm_reg(fpu.fpu_xmm5); 5087 outs() << "\t fpu_xmm6:\n"; 5088 Print_xmm_reg(fpu.fpu_xmm6); 5089 outs() << "\t fpu_xmm7:\n"; 5090 Print_xmm_reg(fpu.fpu_xmm7); 5091 outs() << "\t fpu_xmm8:\n"; 5092 Print_xmm_reg(fpu.fpu_xmm8); 5093 outs() << "\t fpu_xmm9:\n"; 5094 Print_xmm_reg(fpu.fpu_xmm9); 5095 outs() << "\t fpu_xmm10:\n"; 5096 Print_xmm_reg(fpu.fpu_xmm10); 5097 outs() << "\t fpu_xmm11:\n"; 5098 Print_xmm_reg(fpu.fpu_xmm11); 5099 outs() << "\t fpu_xmm12:\n"; 5100 Print_xmm_reg(fpu.fpu_xmm12); 5101 outs() << "\t fpu_xmm13:\n"; 5102 Print_xmm_reg(fpu.fpu_xmm13); 5103 outs() << "\t fpu_xmm14:\n"; 5104 Print_xmm_reg(fpu.fpu_xmm14); 5105 outs() << "\t fpu_xmm15:\n"; 5106 Print_xmm_reg(fpu.fpu_xmm15); 5107 outs() << "\t fpu_rsrv4:\n"; 5108 for (uint32_t f = 0; f < 6; f++) { 5109 outs() << "\t "; 5110 for (uint32_t g = 0; g < 16; g++) 5111 outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " "; 5112 outs() << "\n"; 5113 } 5114 outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1); 5115 outs() << "\n"; 5116} 5117 5118static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { 5119 outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno); 5120 outs() << " err " << format("0x%08" PRIx32, exc64.err); 5121 outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; 5122} 5123 5124static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, 5125 bool isLittleEndian, uint32_t cputype) { 5126 if (t.cmd == MachO::LC_THREAD) 5127 outs() << " cmd LC_THREAD\n"; 5128 else if (t.cmd == MachO::LC_UNIXTHREAD) 5129 outs() << " cmd LC_UNIXTHREAD\n"; 5130 else 5131 outs() << " cmd " << t.cmd << " (unknown)\n"; 5132 outs() << " cmdsize " << t.cmdsize; 5133 if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t)) 5134 outs() << " Incorrect size\n"; 5135 else 5136 outs() << "\n"; 5137 5138 const char *begin = Ptr + sizeof(struct MachO::thread_command); 5139 const char *end = Ptr + t.cmdsize; 5140 uint32_t flavor, count, left; 5141 if (cputype == MachO::CPU_TYPE_X86_64) { 5142 while (begin < end) { 5143 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 5144 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 5145 begin += sizeof(uint32_t); 5146 } else { 5147 flavor = 0; 5148 begin = end; 5149 } 5150 if (isLittleEndian != sys::IsLittleEndianHost) 5151 sys::swapByteOrder(flavor); 5152 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 5153 memcpy((char *)&count, begin, sizeof(uint32_t)); 5154 begin += sizeof(uint32_t); 5155 } else { 5156 count = 0; 5157 begin = end; 5158 } 5159 if (isLittleEndian != sys::IsLittleEndianHost) 5160 sys::swapByteOrder(count); 5161 if (flavor == MachO::x86_THREAD_STATE64) { 5162 outs() << " flavor x86_THREAD_STATE64\n"; 5163 if (count == MachO::x86_THREAD_STATE64_COUNT) 5164 outs() << " count x86_THREAD_STATE64_COUNT\n"; 5165 else 5166 outs() << " count " << count 5167 << " (not x86_THREAD_STATE64_COUNT)\n"; 5168 MachO::x86_thread_state64_t cpu64; 5169 left = end - begin; 5170 if (left >= sizeof(MachO::x86_thread_state64_t)) { 5171 memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t)); 5172 begin += sizeof(MachO::x86_thread_state64_t); 5173 } else { 5174 memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t)); 5175 memcpy(&cpu64, begin, left); 5176 begin += left; 5177 } 5178 if (isLittleEndian != sys::IsLittleEndianHost) 5179 swapStruct(cpu64); 5180 Print_x86_thread_state64_t(cpu64); 5181 } else if (flavor == MachO::x86_THREAD_STATE) { 5182 outs() << " flavor x86_THREAD_STATE\n"; 5183 if (count == MachO::x86_THREAD_STATE_COUNT) 5184 outs() << " count x86_THREAD_STATE_COUNT\n"; 5185 else 5186 outs() << " count " << count 5187 << " (not x86_THREAD_STATE_COUNT)\n"; 5188 struct MachO::x86_thread_state_t ts; 5189 left = end - begin; 5190 if (left >= sizeof(MachO::x86_thread_state_t)) { 5191 memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t)); 5192 begin += sizeof(MachO::x86_thread_state_t); 5193 } else { 5194 memset(&ts, '\0', sizeof(MachO::x86_thread_state_t)); 5195 memcpy(&ts, begin, left); 5196 begin += left; 5197 } 5198 if (isLittleEndian != sys::IsLittleEndianHost) 5199 swapStruct(ts); 5200 if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) { 5201 outs() << "\t tsh.flavor x86_THREAD_STATE64 "; 5202 if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT) 5203 outs() << "tsh.count x86_THREAD_STATE64_COUNT\n"; 5204 else 5205 outs() << "tsh.count " << ts.tsh.count 5206 << " (not x86_THREAD_STATE64_COUNT\n"; 5207 Print_x86_thread_state64_t(ts.uts.ts64); 5208 } else { 5209 outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count " 5210 << ts.tsh.count << "\n"; 5211 } 5212 } else if (flavor == MachO::x86_FLOAT_STATE) { 5213 outs() << " flavor x86_FLOAT_STATE\n"; 5214 if (count == MachO::x86_FLOAT_STATE_COUNT) 5215 outs() << " count x86_FLOAT_STATE_COUNT\n"; 5216 else 5217 outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n"; 5218 struct MachO::x86_float_state_t fs; 5219 left = end - begin; 5220 if (left >= sizeof(MachO::x86_float_state_t)) { 5221 memcpy(&fs, begin, sizeof(MachO::x86_float_state_t)); 5222 begin += sizeof(MachO::x86_float_state_t); 5223 } else { 5224 memset(&fs, '\0', sizeof(MachO::x86_float_state_t)); 5225 memcpy(&fs, begin, left); 5226 begin += left; 5227 } 5228 if (isLittleEndian != sys::IsLittleEndianHost) 5229 swapStruct(fs); 5230 if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) { 5231 outs() << "\t fsh.flavor x86_FLOAT_STATE64 "; 5232 if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT) 5233 outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n"; 5234 else 5235 outs() << "fsh.count " << fs.fsh.count 5236 << " (not x86_FLOAT_STATE64_COUNT\n"; 5237 Print_x86_float_state_t(fs.ufs.fs64); 5238 } else { 5239 outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count " 5240 << fs.fsh.count << "\n"; 5241 } 5242 } else if (flavor == MachO::x86_EXCEPTION_STATE) { 5243 outs() << " flavor x86_EXCEPTION_STATE\n"; 5244 if (count == MachO::x86_EXCEPTION_STATE_COUNT) 5245 outs() << " count x86_EXCEPTION_STATE_COUNT\n"; 5246 else 5247 outs() << " count " << count 5248 << " (not x86_EXCEPTION_STATE_COUNT)\n"; 5249 struct MachO::x86_exception_state_t es; 5250 left = end - begin; 5251 if (left >= sizeof(MachO::x86_exception_state_t)) { 5252 memcpy(&es, begin, sizeof(MachO::x86_exception_state_t)); 5253 begin += sizeof(MachO::x86_exception_state_t); 5254 } else { 5255 memset(&es, '\0', sizeof(MachO::x86_exception_state_t)); 5256 memcpy(&es, begin, left); 5257 begin += left; 5258 } 5259 if (isLittleEndian != sys::IsLittleEndianHost) 5260 swapStruct(es); 5261 if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) { 5262 outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n"; 5263 if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT) 5264 outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n"; 5265 else 5266 outs() << "\t esh.count " << es.esh.count 5267 << " (not x86_EXCEPTION_STATE64_COUNT\n"; 5268 Print_x86_exception_state_t(es.ues.es64); 5269 } else { 5270 outs() << "\t esh.flavor " << es.esh.flavor << " esh.count " 5271 << es.esh.count << "\n"; 5272 } 5273 } else { 5274 outs() << " flavor " << flavor << " (unknown)\n"; 5275 outs() << " count " << count << "\n"; 5276 outs() << " state (unknown)\n"; 5277 begin += count * sizeof(uint32_t); 5278 } 5279 } 5280 } else { 5281 while (begin < end) { 5282 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 5283 memcpy((char *)&flavor, begin, sizeof(uint32_t)); 5284 begin += sizeof(uint32_t); 5285 } else { 5286 flavor = 0; 5287 begin = end; 5288 } 5289 if (isLittleEndian != sys::IsLittleEndianHost) 5290 sys::swapByteOrder(flavor); 5291 if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { 5292 memcpy((char *)&count, begin, sizeof(uint32_t)); 5293 begin += sizeof(uint32_t); 5294 } else { 5295 count = 0; 5296 begin = end; 5297 } 5298 if (isLittleEndian != sys::IsLittleEndianHost) 5299 sys::swapByteOrder(count); 5300 outs() << " flavor " << flavor << "\n"; 5301 outs() << " count " << count << "\n"; 5302 outs() << " state (Unknown cputype/cpusubtype)\n"; 5303 begin += count * sizeof(uint32_t); 5304 } 5305 } 5306} 5307 5308static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 5309 if (dl.cmd == MachO::LC_ID_DYLIB) 5310 outs() << " cmd LC_ID_DYLIB\n"; 5311 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 5312 outs() << " cmd LC_LOAD_DYLIB\n"; 5313 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 5314 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 5315 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 5316 outs() << " cmd LC_REEXPORT_DYLIB\n"; 5317 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 5318 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 5319 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 5320 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 5321 else 5322 outs() << " cmd " << dl.cmd << " (unknown)\n"; 5323 outs() << " cmdsize " << dl.cmdsize; 5324 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 5325 outs() << " Incorrect size\n"; 5326 else 5327 outs() << "\n"; 5328 if (dl.dylib.name < dl.cmdsize) { 5329 const char *P = (const char *)(Ptr) + dl.dylib.name; 5330 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 5331 } else { 5332 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 5333 } 5334 outs() << " time stamp " << dl.dylib.timestamp << " "; 5335 time_t t = dl.dylib.timestamp; 5336 outs() << ctime(&t); 5337 outs() << " current version "; 5338 if (dl.dylib.current_version == 0xffffffff) 5339 outs() << "n/a\n"; 5340 else 5341 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 5342 << ((dl.dylib.current_version >> 8) & 0xff) << "." 5343 << (dl.dylib.current_version & 0xff) << "\n"; 5344 outs() << "compatibility version "; 5345 if (dl.dylib.compatibility_version == 0xffffffff) 5346 outs() << "n/a\n"; 5347 else 5348 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 5349 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 5350 << (dl.dylib.compatibility_version & 0xff) << "\n"; 5351} 5352 5353static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 5354 uint32_t object_size) { 5355 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 5356 outs() << " cmd LC_FUNCTION_STARTS\n"; 5357 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 5358 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 5359 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 5360 outs() << " cmd LC_FUNCTION_STARTS\n"; 5361 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 5362 outs() << " cmd LC_DATA_IN_CODE\n"; 5363 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 5364 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 5365 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 5366 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 5367 else 5368 outs() << " cmd " << ld.cmd << " (?)\n"; 5369 outs() << " cmdsize " << ld.cmdsize; 5370 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 5371 outs() << " Incorrect size\n"; 5372 else 5373 outs() << "\n"; 5374 outs() << " dataoff " << ld.dataoff; 5375 if (ld.dataoff > object_size) 5376 outs() << " (past end of file)\n"; 5377 else 5378 outs() << "\n"; 5379 outs() << " datasize " << ld.datasize; 5380 uint64_t big_size = ld.dataoff; 5381 big_size += ld.datasize; 5382 if (big_size > object_size) 5383 outs() << " (past end of file)\n"; 5384 else 5385 outs() << "\n"; 5386} 5387 5388static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t ncmds, 5389 uint32_t filetype, uint32_t cputype, 5390 bool verbose) { 5391 if (ncmds == 0) 5392 return; 5393 StringRef Buf = Obj->getData(); 5394 MachOObjectFile::LoadCommandInfo Command = Obj->getFirstLoadCommandInfo(); 5395 for (unsigned i = 0;; ++i) { 5396 outs() << "Load command " << i << "\n"; 5397 if (Command.C.cmd == MachO::LC_SEGMENT) { 5398 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 5399 const char *sg_segname = SLC.segname; 5400 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 5401 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 5402 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 5403 verbose); 5404 for (unsigned j = 0; j < SLC.nsects; j++) { 5405 MachO::section S = Obj->getSection(Command, j); 5406 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 5407 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 5408 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 5409 } 5410 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 5411 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 5412 const char *sg_segname = SLC_64.segname; 5413 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 5414 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 5415 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 5416 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 5417 for (unsigned j = 0; j < SLC_64.nsects; j++) { 5418 MachO::section_64 S_64 = Obj->getSection64(Command, j); 5419 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 5420 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 5421 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 5422 sg_segname, filetype, Buf.size(), verbose); 5423 } 5424 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 5425 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 5426 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 5427 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 5428 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 5429 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 5430 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 5431 Obj->is64Bit()); 5432 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 5433 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 5434 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 5435 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 5436 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 5437 Command.C.cmd == MachO::LC_ID_DYLINKER || 5438 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 5439 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 5440 PrintDyldLoadCommand(Dyld, Command.Ptr); 5441 } else if (Command.C.cmd == MachO::LC_UUID) { 5442 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 5443 PrintUuidLoadCommand(Uuid); 5444 } else if (Command.C.cmd == MachO::LC_RPATH) { 5445 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 5446 PrintRpathLoadCommand(Rpath, Command.Ptr); 5447 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX || 5448 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) { 5449 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 5450 PrintVersionMinLoadCommand(Vd); 5451 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 5452 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 5453 PrintSourceVersionCommand(Sd); 5454 } else if (Command.C.cmd == MachO::LC_MAIN) { 5455 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 5456 PrintEntryPointCommand(Ep); 5457 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) { 5458 MachO::encryption_info_command Ei = 5459 Obj->getEncryptionInfoCommand(Command); 5460 PrintEncryptionInfoCommand(Ei, Buf.size()); 5461 } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 5462 MachO::encryption_info_command_64 Ei = 5463 Obj->getEncryptionInfoCommand64(Command); 5464 PrintEncryptionInfoCommand64(Ei, Buf.size()); 5465 } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) { 5466 MachO::linker_option_command Lo = 5467 Obj->getLinkerOptionLoadCommand(Command); 5468 PrintLinkerOptionCommand(Lo, Command.Ptr); 5469 } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) { 5470 MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command); 5471 PrintSubFrameworkCommand(Sf, Command.Ptr); 5472 } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) { 5473 MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command); 5474 PrintSubUmbrellaCommand(Sf, Command.Ptr); 5475 } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) { 5476 MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command); 5477 PrintSubLibraryCommand(Sl, Command.Ptr); 5478 } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) { 5479 MachO::sub_client_command Sc = Obj->getSubClientCommand(Command); 5480 PrintSubClientCommand(Sc, Command.Ptr); 5481 } else if (Command.C.cmd == MachO::LC_ROUTINES) { 5482 MachO::routines_command Rc = Obj->getRoutinesCommand(Command); 5483 PrintRoutinesCommand(Rc); 5484 } else if (Command.C.cmd == MachO::LC_ROUTINES_64) { 5485 MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command); 5486 PrintRoutinesCommand64(Rc); 5487 } else if (Command.C.cmd == MachO::LC_THREAD || 5488 Command.C.cmd == MachO::LC_UNIXTHREAD) { 5489 MachO::thread_command Tc = Obj->getThreadCommand(Command); 5490 PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype); 5491 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 5492 Command.C.cmd == MachO::LC_ID_DYLIB || 5493 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 5494 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 5495 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 5496 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 5497 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 5498 PrintDylibCommand(Dl, Command.Ptr); 5499 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 5500 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 5501 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 5502 Command.C.cmd == MachO::LC_DATA_IN_CODE || 5503 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 5504 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 5505 MachO::linkedit_data_command Ld = 5506 Obj->getLinkeditDataLoadCommand(Command); 5507 PrintLinkEditDataCommand(Ld, Buf.size()); 5508 } else { 5509 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 5510 << ")\n"; 5511 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 5512 // TODO: get and print the raw bytes of the load command. 5513 } 5514 // TODO: print all the other kinds of load commands. 5515 if (i == ncmds - 1) 5516 break; 5517 else 5518 Command = Obj->getNextLoadCommandInfo(Command); 5519 } 5520} 5521 5522static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds, 5523 uint32_t &filetype, uint32_t &cputype, 5524 bool verbose) { 5525 if (Obj->is64Bit()) { 5526 MachO::mach_header_64 H_64; 5527 H_64 = Obj->getHeader64(); 5528 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 5529 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 5530 ncmds = H_64.ncmds; 5531 filetype = H_64.filetype; 5532 cputype = H_64.cputype; 5533 } else { 5534 MachO::mach_header H; 5535 H = Obj->getHeader(); 5536 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 5537 H.sizeofcmds, H.flags, verbose); 5538 ncmds = H.ncmds; 5539 filetype = H.filetype; 5540 cputype = H.cputype; 5541 } 5542} 5543 5544void llvm::printMachOFileHeader(const object::ObjectFile *Obj) { 5545 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 5546 uint32_t ncmds = 0; 5547 uint32_t filetype = 0; 5548 uint32_t cputype = 0; 5549 getAndPrintMachHeader(file, ncmds, filetype, cputype, !NonVerbose); 5550 PrintLoadCommands(file, ncmds, filetype, cputype, !NonVerbose); 5551} 5552 5553//===----------------------------------------------------------------------===// 5554// export trie dumping 5555//===----------------------------------------------------------------------===// 5556 5557void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) { 5558 for (const llvm::object::ExportEntry &Entry : Obj->exports()) { 5559 uint64_t Flags = Entry.flags(); 5560 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 5561 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 5562 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 5563 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 5564 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 5565 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 5566 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 5567 if (ReExport) 5568 outs() << "[re-export] "; 5569 else 5570 outs() << format("0x%08llX ", 5571 Entry.address()); // FIXME:add in base address 5572 outs() << Entry.name(); 5573 if (WeakDef || ThreadLocal || Resolver || Abs) { 5574 bool NeedsComma = false; 5575 outs() << " ["; 5576 if (WeakDef) { 5577 outs() << "weak_def"; 5578 NeedsComma = true; 5579 } 5580 if (ThreadLocal) { 5581 if (NeedsComma) 5582 outs() << ", "; 5583 outs() << "per-thread"; 5584 NeedsComma = true; 5585 } 5586 if (Abs) { 5587 if (NeedsComma) 5588 outs() << ", "; 5589 outs() << "absolute"; 5590 NeedsComma = true; 5591 } 5592 if (Resolver) { 5593 if (NeedsComma) 5594 outs() << ", "; 5595 outs() << format("resolver=0x%08llX", Entry.other()); 5596 NeedsComma = true; 5597 } 5598 outs() << "]"; 5599 } 5600 if (ReExport) { 5601 StringRef DylibName = "unknown"; 5602 int Ordinal = Entry.other() - 1; 5603 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 5604 if (Entry.otherName().empty()) 5605 outs() << " (from " << DylibName << ")"; 5606 else 5607 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 5608 } 5609 outs() << "\n"; 5610 } 5611} 5612 5613//===----------------------------------------------------------------------===// 5614// rebase table dumping 5615//===----------------------------------------------------------------------===// 5616 5617namespace { 5618class SegInfo { 5619public: 5620 SegInfo(const object::MachOObjectFile *Obj); 5621 5622 StringRef segmentName(uint32_t SegIndex); 5623 StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset); 5624 uint64_t address(uint32_t SegIndex, uint64_t SegOffset); 5625 5626private: 5627 struct SectionInfo { 5628 uint64_t Address; 5629 uint64_t Size; 5630 StringRef SectionName; 5631 StringRef SegmentName; 5632 uint64_t OffsetInSegment; 5633 uint64_t SegmentStartAddress; 5634 uint32_t SegmentIndex; 5635 }; 5636 const SectionInfo &findSection(uint32_t SegIndex, uint64_t SegOffset); 5637 SmallVector<SectionInfo, 32> Sections; 5638}; 5639} 5640 5641SegInfo::SegInfo(const object::MachOObjectFile *Obj) { 5642 // Build table of sections so segIndex/offset pairs can be translated. 5643 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0; 5644 StringRef CurSegName; 5645 uint64_t CurSegAddress; 5646 for (const SectionRef &Section : Obj->sections()) { 5647 SectionInfo Info; 5648 if (error(Section.getName(Info.SectionName))) 5649 return; 5650 Info.Address = Section.getAddress(); 5651 Info.Size = Section.getSize(); 5652 Info.SegmentName = 5653 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl()); 5654 if (!Info.SegmentName.equals(CurSegName)) { 5655 ++CurSegIndex; 5656 CurSegName = Info.SegmentName; 5657 CurSegAddress = Info.Address; 5658 } 5659 Info.SegmentIndex = CurSegIndex - 1; 5660 Info.OffsetInSegment = Info.Address - CurSegAddress; 5661 Info.SegmentStartAddress = CurSegAddress; 5662 Sections.push_back(Info); 5663 } 5664} 5665 5666StringRef SegInfo::segmentName(uint32_t SegIndex) { 5667 for (const SectionInfo &SI : Sections) { 5668 if (SI.SegmentIndex == SegIndex) 5669 return SI.SegmentName; 5670 } 5671 llvm_unreachable("invalid segIndex"); 5672} 5673 5674const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex, 5675 uint64_t OffsetInSeg) { 5676 for (const SectionInfo &SI : Sections) { 5677 if (SI.SegmentIndex != SegIndex) 5678 continue; 5679 if (SI.OffsetInSegment > OffsetInSeg) 5680 continue; 5681 if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size)) 5682 continue; 5683 return SI; 5684 } 5685 llvm_unreachable("segIndex and offset not in any section"); 5686} 5687 5688StringRef SegInfo::sectionName(uint32_t SegIndex, uint64_t OffsetInSeg) { 5689 return findSection(SegIndex, OffsetInSeg).SectionName; 5690} 5691 5692uint64_t SegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) { 5693 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg); 5694 return SI.SegmentStartAddress + OffsetInSeg; 5695} 5696 5697void llvm::printMachORebaseTable(const object::MachOObjectFile *Obj) { 5698 // Build table of sections so names can used in final output. 5699 SegInfo sectionTable(Obj); 5700 5701 outs() << "segment section address type\n"; 5702 for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) { 5703 uint32_t SegIndex = Entry.segmentIndex(); 5704 uint64_t OffsetInSeg = Entry.segmentOffset(); 5705 StringRef SegmentName = sectionTable.segmentName(SegIndex); 5706 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 5707 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 5708 5709 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 5710 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 5711 SegmentName.str().c_str(), SectionName.str().c_str(), 5712 Address, Entry.typeName().str().c_str()); 5713 } 5714} 5715 5716static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 5717 StringRef DylibName; 5718 switch (Ordinal) { 5719 case MachO::BIND_SPECIAL_DYLIB_SELF: 5720 return "this-image"; 5721 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 5722 return "main-executable"; 5723 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 5724 return "flat-namespace"; 5725 default: 5726 if (Ordinal > 0) { 5727 std::error_code EC = 5728 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 5729 if (EC) 5730 return "<<bad library ordinal>>"; 5731 return DylibName; 5732 } 5733 } 5734 return "<<unknown special ordinal>>"; 5735} 5736 5737//===----------------------------------------------------------------------===// 5738// bind table dumping 5739//===----------------------------------------------------------------------===// 5740 5741void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) { 5742 // Build table of sections so names can used in final output. 5743 SegInfo sectionTable(Obj); 5744 5745 outs() << "segment section address type " 5746 "addend dylib symbol\n"; 5747 for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) { 5748 uint32_t SegIndex = Entry.segmentIndex(); 5749 uint64_t OffsetInSeg = Entry.segmentOffset(); 5750 StringRef SegmentName = sectionTable.segmentName(SegIndex); 5751 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 5752 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 5753 5754 // Table lines look like: 5755 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 5756 StringRef Attr; 5757 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 5758 Attr = " (weak_import)"; 5759 outs() << left_justify(SegmentName, 8) << " " 5760 << left_justify(SectionName, 18) << " " 5761 << format_hex(Address, 10, true) << " " 5762 << left_justify(Entry.typeName(), 8) << " " 5763 << format_decimal(Entry.addend(), 8) << " " 5764 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 5765 << Entry.symbolName() << Attr << "\n"; 5766 } 5767} 5768 5769//===----------------------------------------------------------------------===// 5770// lazy bind table dumping 5771//===----------------------------------------------------------------------===// 5772 5773void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) { 5774 // Build table of sections so names can used in final output. 5775 SegInfo sectionTable(Obj); 5776 5777 outs() << "segment section address " 5778 "dylib symbol\n"; 5779 for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable()) { 5780 uint32_t SegIndex = Entry.segmentIndex(); 5781 uint64_t OffsetInSeg = Entry.segmentOffset(); 5782 StringRef SegmentName = sectionTable.segmentName(SegIndex); 5783 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 5784 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 5785 5786 // Table lines look like: 5787 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 5788 outs() << left_justify(SegmentName, 8) << " " 5789 << left_justify(SectionName, 18) << " " 5790 << format_hex(Address, 10, true) << " " 5791 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 5792 << Entry.symbolName() << "\n"; 5793 } 5794} 5795 5796//===----------------------------------------------------------------------===// 5797// weak bind table dumping 5798//===----------------------------------------------------------------------===// 5799 5800void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) { 5801 // Build table of sections so names can used in final output. 5802 SegInfo sectionTable(Obj); 5803 5804 outs() << "segment section address " 5805 "type addend symbol\n"; 5806 for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable()) { 5807 // Strong symbols don't have a location to update. 5808 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 5809 outs() << " strong " 5810 << Entry.symbolName() << "\n"; 5811 continue; 5812 } 5813 uint32_t SegIndex = Entry.segmentIndex(); 5814 uint64_t OffsetInSeg = Entry.segmentOffset(); 5815 StringRef SegmentName = sectionTable.segmentName(SegIndex); 5816 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 5817 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 5818 5819 // Table lines look like: 5820 // __DATA __data 0x00001000 pointer 0 _foo 5821 outs() << left_justify(SegmentName, 8) << " " 5822 << left_justify(SectionName, 18) << " " 5823 << format_hex(Address, 10, true) << " " 5824 << left_justify(Entry.typeName(), 8) << " " 5825 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 5826 << "\n"; 5827 } 5828} 5829 5830// get_dyld_bind_info_symbolname() is used for disassembly and passed an 5831// address, ReferenceValue, in the Mach-O file and looks in the dyld bind 5832// information for that address. If the address is found its binding symbol 5833// name is returned. If not nullptr is returned. 5834static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 5835 struct DisassembleInfo *info) { 5836 if (info->bindtable == nullptr) { 5837 info->bindtable = new (BindTable); 5838 SegInfo sectionTable(info->O); 5839 for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) { 5840 uint32_t SegIndex = Entry.segmentIndex(); 5841 uint64_t OffsetInSeg = Entry.segmentOffset(); 5842 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 5843 const char *SymbolName = nullptr; 5844 StringRef name = Entry.symbolName(); 5845 if (!name.empty()) 5846 SymbolName = name.data(); 5847 info->bindtable->push_back(std::make_pair(Address, SymbolName)); 5848 } 5849 } 5850 for (bind_table_iterator BI = info->bindtable->begin(), 5851 BE = info->bindtable->end(); 5852 BI != BE; ++BI) { 5853 uint64_t Address = BI->first; 5854 if (ReferenceValue == Address) { 5855 const char *SymbolName = BI->second; 5856 return SymbolName; 5857 } 5858 } 5859 return nullptr; 5860} 5861