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