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/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/GraphWriter.h" 38 #include "llvm/Support/MachO.h" 39 #include "llvm/Support/MemoryBuffer.h" 40 #include "llvm/Support/FormattedStream.h" 41 #include "llvm/Support/TargetRegistry.h" 42 #include "llvm/Support/TargetSelect.h" 43 #include "llvm/Support/raw_ostream.h" 44 #include <algorithm> 45 #include <cstring> 46 #include <system_error> 47 48 #if HAVE_CXXABI_H 49 #include <cxxabi.h> 50 #endif 51 52 using namespace llvm; 53 using namespace object; 54 55 static cl::opt<bool> 56 UseDbg("g", 57 cl::desc("Print line information from debug info if available")); 58 59 static cl::opt<std::string> DSYMFile("dsym", 60 cl::desc("Use .dSYM file for debug info")); 61 62 static cl::opt<bool> FullLeadingAddr("full-leading-addr", 63 cl::desc("Print full leading address")); 64 65 static cl::opt<bool> 66 PrintImmHex("print-imm-hex", 67 cl::desc("Use hex format for immediate values")); 68 69 static cl::list<std::string> 70 ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 71 cl::ZeroOrMore); 72 bool ArchAll = false; 73 74 static std::string ThumbTripleName; 75 76 static const Target *GetTarget(const MachOObjectFile *MachOObj, 77 const char **McpuDefault, 78 const Target **ThumbTarget) { 79 // Figure out the target triple. 80 if (TripleName.empty()) { 81 llvm::Triple TT("unknown-unknown-unknown"); 82 llvm::Triple ThumbTriple = Triple(); 83 TT = MachOObj->getArch(McpuDefault, &ThumbTriple); 84 TripleName = TT.str(); 85 ThumbTripleName = ThumbTriple.str(); 86 } 87 88 // Get the target specific parser. 89 std::string Error; 90 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 91 if (TheTarget && ThumbTripleName.empty()) 92 return TheTarget; 93 94 *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); 95 if (*ThumbTarget) 96 return TheTarget; 97 98 errs() << "llvm-objdump: error: unable to get target for '"; 99 if (!TheTarget) 100 errs() << TripleName; 101 else 102 errs() << ThumbTripleName; 103 errs() << "', see --version and --triple.\n"; 104 return nullptr; 105 } 106 107 struct SymbolSorter { 108 bool operator()(const SymbolRef &A, const SymbolRef &B) { 109 SymbolRef::Type AType, BType; 110 A.getType(AType); 111 B.getType(BType); 112 113 uint64_t AAddr, BAddr; 114 if (AType != SymbolRef::ST_Function) 115 AAddr = 0; 116 else 117 A.getAddress(AAddr); 118 if (BType != SymbolRef::ST_Function) 119 BAddr = 0; 120 else 121 B.getAddress(BAddr); 122 return AAddr < BAddr; 123 } 124 }; 125 126 // Types for the storted data in code table that is built before disassembly 127 // and the predicate function to sort them. 128 typedef std::pair<uint64_t, DiceRef> DiceTableEntry; 129 typedef std::vector<DiceTableEntry> DiceTable; 130 typedef DiceTable::iterator dice_table_iterator; 131 132 // This is used to search for a data in code table entry for the PC being 133 // disassembled. The j parameter has the PC in j.first. A single data in code 134 // table entry can cover many bytes for each of its Kind's. So if the offset, 135 // aka the i.first value, of the data in code table entry plus its Length 136 // covers the PC being searched for this will return true. If not it will 137 // return false. 138 static bool compareDiceTableEntries(const DiceTableEntry &i, 139 const DiceTableEntry &j) { 140 uint16_t Length; 141 i.second.getLength(Length); 142 143 return j.first >= i.first && j.first < i.first + Length; 144 } 145 146 static uint64_t DumpDataInCode(const char *bytes, uint64_t Length, 147 unsigned short Kind) { 148 uint32_t Value, Size = 1; 149 150 switch (Kind) { 151 default: 152 case MachO::DICE_KIND_DATA: 153 if (Length >= 4) { 154 if (!NoShowRawInsn) 155 DumpBytes(StringRef(bytes, 4)); 156 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 157 outs() << "\t.long " << Value; 158 Size = 4; 159 } else if (Length >= 2) { 160 if (!NoShowRawInsn) 161 DumpBytes(StringRef(bytes, 2)); 162 Value = bytes[1] << 8 | bytes[0]; 163 outs() << "\t.short " << Value; 164 Size = 2; 165 } else { 166 if (!NoShowRawInsn) 167 DumpBytes(StringRef(bytes, 2)); 168 Value = bytes[0]; 169 outs() << "\t.byte " << Value; 170 Size = 1; 171 } 172 if (Kind == MachO::DICE_KIND_DATA) 173 outs() << "\t@ KIND_DATA\n"; 174 else 175 outs() << "\t@ data in code kind = " << Kind << "\n"; 176 break; 177 case MachO::DICE_KIND_JUMP_TABLE8: 178 if (!NoShowRawInsn) 179 DumpBytes(StringRef(bytes, 1)); 180 Value = bytes[0]; 181 outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n"; 182 Size = 1; 183 break; 184 case MachO::DICE_KIND_JUMP_TABLE16: 185 if (!NoShowRawInsn) 186 DumpBytes(StringRef(bytes, 2)); 187 Value = bytes[1] << 8 | bytes[0]; 188 outs() << "\t.short " << format("%5u", Value & 0xffff) 189 << "\t@ KIND_JUMP_TABLE16\n"; 190 Size = 2; 191 break; 192 case MachO::DICE_KIND_JUMP_TABLE32: 193 case MachO::DICE_KIND_ABS_JUMP_TABLE32: 194 if (!NoShowRawInsn) 195 DumpBytes(StringRef(bytes, 4)); 196 Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; 197 outs() << "\t.long " << Value; 198 if (Kind == MachO::DICE_KIND_JUMP_TABLE32) 199 outs() << "\t@ KIND_JUMP_TABLE32\n"; 200 else 201 outs() << "\t@ KIND_ABS_JUMP_TABLE32\n"; 202 Size = 4; 203 break; 204 } 205 return Size; 206 } 207 208 static void getSectionsAndSymbols(const MachO::mach_header Header, 209 MachOObjectFile *MachOObj, 210 std::vector<SectionRef> &Sections, 211 std::vector<SymbolRef> &Symbols, 212 SmallVectorImpl<uint64_t> &FoundFns, 213 uint64_t &BaseSegmentAddress) { 214 for (const SymbolRef &Symbol : MachOObj->symbols()) { 215 StringRef SymName; 216 Symbol.getName(SymName); 217 if (!SymName.startswith("ltmp")) 218 Symbols.push_back(Symbol); 219 } 220 221 for (const SectionRef &Section : MachOObj->sections()) { 222 StringRef SectName; 223 Section.getName(SectName); 224 Sections.push_back(Section); 225 } 226 227 MachOObjectFile::LoadCommandInfo Command = 228 MachOObj->getFirstLoadCommandInfo(); 229 bool BaseSegmentAddressSet = false; 230 for (unsigned i = 0;; ++i) { 231 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 232 // We found a function starts segment, parse the addresses for later 233 // consumption. 234 MachO::linkedit_data_command LLC = 235 MachOObj->getLinkeditDataLoadCommand(Command); 236 237 MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); 238 } else if (Command.C.cmd == MachO::LC_SEGMENT) { 239 MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command); 240 StringRef SegName = SLC.segname; 241 if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") { 242 BaseSegmentAddressSet = true; 243 BaseSegmentAddress = SLC.vmaddr; 244 } 245 } 246 247 if (i == Header.ncmds - 1) 248 break; 249 else 250 Command = MachOObj->getNextLoadCommandInfo(Command); 251 } 252 } 253 254 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file 255 // and if it is and there is a list of architecture flags is specified then 256 // check to make sure this Mach-O file is one of those architectures or all 257 // architectures were specified. If not then an error is generated and this 258 // routine returns false. Else it returns true. 259 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { 260 if (isa<MachOObjectFile>(O) && !ArchAll && ArchFlags.size() != 0) { 261 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O); 262 bool ArchFound = false; 263 MachO::mach_header H; 264 MachO::mach_header_64 H_64; 265 Triple T; 266 if (MachO->is64Bit()) { 267 H_64 = MachO->MachOObjectFile::getHeader64(); 268 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype); 269 } else { 270 H = MachO->MachOObjectFile::getHeader(); 271 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype); 272 } 273 unsigned i; 274 for (i = 0; i < ArchFlags.size(); ++i) { 275 if (ArchFlags[i] == T.getArchName()) 276 ArchFound = true; 277 break; 278 } 279 if (!ArchFound) { 280 errs() << "llvm-objdump: file: " + Filename + " does not contain " 281 << "architecture: " + ArchFlags[i] + "\n"; 282 return false; 283 } 284 } 285 return true; 286 } 287 288 static void DisassembleInputMachO2(StringRef Filename, MachOObjectFile *MachOOF, 289 StringRef ArchiveMemberName = StringRef(), 290 StringRef ArchitectureName = StringRef()); 291 292 void llvm::DisassembleInputMachO(StringRef Filename) { 293 // Check for -arch all and verifiy the -arch flags are valid. 294 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 295 if (ArchFlags[i] == "all") { 296 ArchAll = true; 297 } else { 298 if (!MachOObjectFile::isValidArch(ArchFlags[i])) { 299 errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] + 300 "'for the -arch option\n"; 301 return; 302 } 303 } 304 } 305 306 // Attempt to open the binary. 307 ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename); 308 if (std::error_code EC = BinaryOrErr.getError()) { 309 errs() << "llvm-objdump: '" << Filename << "': " << EC.message() << ".\n"; 310 return; 311 } 312 Binary &Bin = *BinaryOrErr.get().getBinary(); 313 314 if (Archive *A = dyn_cast<Archive>(&Bin)) { 315 outs() << "Archive : " << Filename << "\n"; 316 for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); 317 I != E; ++I) { 318 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = I->getAsBinary(); 319 if (ChildOrErr.getError()) 320 continue; 321 if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 322 if (!checkMachOAndArchFlags(O, Filename)) 323 return; 324 DisassembleInputMachO2(Filename, O, O->getFileName()); 325 } 326 } 327 return; 328 } 329 if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 330 // If we have a list of architecture flags specified dump only those. 331 if (!ArchAll && ArchFlags.size() != 0) { 332 // Look for a slice in the universal binary that matches each ArchFlag. 333 bool ArchFound; 334 for (unsigned i = 0; i < ArchFlags.size(); ++i) { 335 ArchFound = false; 336 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 337 E = UB->end_objects(); 338 I != E; ++I) { 339 if (ArchFlags[i] == I->getArchTypeName()) { 340 ArchFound = true; 341 ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = 342 I->getAsObjectFile(); 343 std::string ArchitectureName = ""; 344 if (ArchFlags.size() > 1) 345 ArchitectureName = I->getArchTypeName(); 346 if (ObjOrErr) { 347 ObjectFile &O = *ObjOrErr.get(); 348 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 349 DisassembleInputMachO2(Filename, MachOOF, "", ArchitectureName); 350 } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = 351 I->getAsArchive()) { 352 std::unique_ptr<Archive> &A = *AOrErr; 353 outs() << "Archive : " << Filename; 354 if (!ArchitectureName.empty()) 355 outs() << " (architecture " << ArchitectureName << ")"; 356 outs() << "\n"; 357 for (Archive::child_iterator AI = A->child_begin(), 358 AE = A->child_end(); 359 AI != AE; ++AI) { 360 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary(); 361 if (ChildOrErr.getError()) 362 continue; 363 if (MachOObjectFile *O = 364 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 365 DisassembleInputMachO2(Filename, O, O->getFileName(), 366 ArchitectureName); 367 } 368 } 369 } 370 } 371 if (!ArchFound) { 372 errs() << "llvm-objdump: file: " + Filename + " does not contain " 373 << "architecture: " + ArchFlags[i] + "\n"; 374 return; 375 } 376 } 377 return; 378 } 379 // No architecture flags were specified so if this contains a slice that 380 // matches the host architecture dump only that. 381 if (!ArchAll) { 382 StringRef HostArchName = MachOObjectFile::getHostArch().getArchName(); 383 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 384 E = UB->end_objects(); 385 I != E; ++I) { 386 if (HostArchName == I->getArchTypeName()) { 387 ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 388 std::string ArchiveName; 389 ArchiveName.clear(); 390 if (ObjOrErr) { 391 ObjectFile &O = *ObjOrErr.get(); 392 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) 393 DisassembleInputMachO2(Filename, MachOOF); 394 } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = 395 I->getAsArchive()) { 396 std::unique_ptr<Archive> &A = *AOrErr; 397 outs() << "Archive : " << Filename << "\n"; 398 for (Archive::child_iterator AI = A->child_begin(), 399 AE = A->child_end(); 400 AI != AE; ++AI) { 401 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary(); 402 if (ChildOrErr.getError()) 403 continue; 404 if (MachOObjectFile *O = 405 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) 406 DisassembleInputMachO2(Filename, O, O->getFileName()); 407 } 408 } 409 return; 410 } 411 } 412 } 413 // Either all architectures have been specified or none have been specified 414 // and this does not contain the host architecture so dump all the slices. 415 bool moreThanOneArch = UB->getNumberOfObjects() > 1; 416 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 417 E = UB->end_objects(); 418 I != E; ++I) { 419 ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 420 std::string ArchitectureName = ""; 421 if (moreThanOneArch) 422 ArchitectureName = I->getArchTypeName(); 423 if (ObjOrErr) { 424 ObjectFile &Obj = *ObjOrErr.get(); 425 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) 426 DisassembleInputMachO2(Filename, MachOOF, "", ArchitectureName); 427 } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { 428 std::unique_ptr<Archive> &A = *AOrErr; 429 outs() << "Archive : " << Filename; 430 if (!ArchitectureName.empty()) 431 outs() << " (architecture " << ArchitectureName << ")"; 432 outs() << "\n"; 433 for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); 434 AI != AE; ++AI) { 435 ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary(); 436 if (ChildOrErr.getError()) 437 continue; 438 if (MachOObjectFile *O = 439 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) { 440 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O)) 441 DisassembleInputMachO2(Filename, MachOOF, MachOOF->getFileName(), 442 ArchitectureName); 443 } 444 } 445 } 446 } 447 return; 448 } 449 if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) { 450 if (!checkMachOAndArchFlags(O, Filename)) 451 return; 452 if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) { 453 DisassembleInputMachO2(Filename, MachOOF); 454 } else 455 errs() << "llvm-objdump: '" << Filename << "': " 456 << "Object is not a Mach-O file type.\n"; 457 } else 458 errs() << "llvm-objdump: '" << Filename << "': " 459 << "Unrecognized file type.\n"; 460 } 461 462 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap; 463 typedef std::pair<uint64_t, const char *> BindInfoEntry; 464 typedef std::vector<BindInfoEntry> BindTable; 465 typedef BindTable::iterator bind_table_iterator; 466 467 // The block of info used by the Symbolizer call backs. 468 struct DisassembleInfo { 469 bool verbose; 470 MachOObjectFile *O; 471 SectionRef S; 472 SymbolAddressMap *AddrMap; 473 std::vector<SectionRef> *Sections; 474 const char *class_name; 475 const char *selector_name; 476 char *method; 477 char *demangled_name; 478 uint64_t adrp_addr; 479 uint32_t adrp_inst; 480 BindTable *bindtable; 481 }; 482 483 // GuessSymbolName is passed the address of what might be a symbol and a 484 // pointer to the DisassembleInfo struct. It returns the name of a symbol 485 // with that address or nullptr if no symbol is found with that address. 486 static const char *GuessSymbolName(uint64_t value, 487 struct DisassembleInfo *info) { 488 const char *SymbolName = nullptr; 489 // A DenseMap can't lookup up some values. 490 if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) { 491 StringRef name = info->AddrMap->lookup(value); 492 if (!name.empty()) 493 SymbolName = name.data(); 494 } 495 return SymbolName; 496 } 497 498 // SymbolizerGetOpInfo() is the operand information call back function. 499 // This is called to get the symbolic information for operand(s) of an 500 // instruction when it is being done. This routine does this from 501 // the relocation information, symbol table, etc. That block of information 502 // is a pointer to the struct DisassembleInfo that was passed when the 503 // disassembler context was created and passed to back to here when 504 // called back by the disassembler for instruction operands that could have 505 // relocation information. The address of the instruction containing operand is 506 // at the Pc parameter. The immediate value the operand has is passed in 507 // op_info->Value and is at Offset past the start of the instruction and has a 508 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the 509 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol 510 // names and addends of the symbolic expression to add for the operand. The 511 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic 512 // information is returned then this function returns 1 else it returns 0. 513 int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, 514 uint64_t Size, int TagType, void *TagBuf) { 515 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 516 struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf; 517 uint64_t value = op_info->Value; 518 519 // Make sure all fields returned are zero if we don't set them. 520 memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1)); 521 op_info->Value = value; 522 523 // If the TagType is not the value 1 which it code knows about or if no 524 // verbose symbolic information is wanted then just return 0, indicating no 525 // information is being returned. 526 if (TagType != 1 || info->verbose == false) 527 return 0; 528 529 unsigned int Arch = info->O->getArch(); 530 if (Arch == Triple::x86) { 531 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 532 return 0; 533 // First search the section's relocation entries (if any) for an entry 534 // for this section offset. 535 uint32_t sect_addr = info->S.getAddress(); 536 uint32_t sect_offset = (Pc + Offset) - sect_addr; 537 bool reloc_found = false; 538 DataRefImpl Rel; 539 MachO::any_relocation_info RE; 540 bool isExtern = false; 541 SymbolRef Symbol; 542 bool r_scattered = false; 543 uint32_t r_value, pair_r_value, r_type; 544 for (const RelocationRef &Reloc : info->S.relocations()) { 545 uint64_t RelocOffset; 546 Reloc.getOffset(RelocOffset); 547 if (RelocOffset == sect_offset) { 548 Rel = Reloc.getRawDataRefImpl(); 549 RE = info->O->getRelocation(Rel); 550 r_type = info->O->getAnyRelocationType(RE); 551 r_scattered = info->O->isRelocationScattered(RE); 552 if (r_scattered) { 553 r_value = info->O->getScatteredRelocationValue(RE); 554 if (r_type == MachO::GENERIC_RELOC_SECTDIFF || 555 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 556 DataRefImpl RelNext = Rel; 557 info->O->moveRelocationNext(RelNext); 558 MachO::any_relocation_info RENext; 559 RENext = info->O->getRelocation(RelNext); 560 if (info->O->isRelocationScattered(RENext)) 561 pair_r_value = info->O->getScatteredRelocationValue(RENext); 562 else 563 return 0; 564 } 565 } else { 566 isExtern = info->O->getPlainRelocationExternal(RE); 567 if (isExtern) { 568 symbol_iterator RelocSym = Reloc.getSymbol(); 569 Symbol = *RelocSym; 570 } 571 } 572 reloc_found = true; 573 break; 574 } 575 } 576 if (reloc_found && isExtern) { 577 StringRef SymName; 578 Symbol.getName(SymName); 579 const char *name = SymName.data(); 580 op_info->AddSymbol.Present = 1; 581 op_info->AddSymbol.Name = name; 582 // For i386 extern relocation entries the value in the instruction is 583 // the offset from the symbol, and value is already set in op_info->Value. 584 return 1; 585 } 586 if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF || 587 r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) { 588 const char *add = GuessSymbolName(r_value, info); 589 const char *sub = GuessSymbolName(pair_r_value, info); 590 uint32_t offset = value - (r_value - pair_r_value); 591 op_info->AddSymbol.Present = 1; 592 if (add != nullptr) 593 op_info->AddSymbol.Name = add; 594 else 595 op_info->AddSymbol.Value = r_value; 596 op_info->SubtractSymbol.Present = 1; 597 if (sub != nullptr) 598 op_info->SubtractSymbol.Name = sub; 599 else 600 op_info->SubtractSymbol.Value = pair_r_value; 601 op_info->Value = offset; 602 return 1; 603 } 604 // TODO: 605 // Second search the external relocation entries of a fully linked image 606 // (if any) for an entry that matches this segment offset. 607 // uint32_t seg_offset = (Pc + Offset); 608 return 0; 609 } else if (Arch == Triple::x86_64) { 610 if (Size != 1 && Size != 2 && Size != 4 && Size != 0) 611 return 0; 612 // First search the section's relocation entries (if any) for an entry 613 // for this section offset. 614 uint64_t sect_addr = info->S.getAddress(); 615 uint64_t sect_offset = (Pc + Offset) - sect_addr; 616 bool reloc_found = false; 617 DataRefImpl Rel; 618 MachO::any_relocation_info RE; 619 bool isExtern = false; 620 SymbolRef Symbol; 621 for (const RelocationRef &Reloc : info->S.relocations()) { 622 uint64_t RelocOffset; 623 Reloc.getOffset(RelocOffset); 624 if (RelocOffset == sect_offset) { 625 Rel = Reloc.getRawDataRefImpl(); 626 RE = info->O->getRelocation(Rel); 627 // NOTE: Scattered relocations don't exist on x86_64. 628 isExtern = info->O->getPlainRelocationExternal(RE); 629 if (isExtern) { 630 symbol_iterator RelocSym = Reloc.getSymbol(); 631 Symbol = *RelocSym; 632 } 633 reloc_found = true; 634 break; 635 } 636 } 637 if (reloc_found && isExtern) { 638 // The Value passed in will be adjusted by the Pc if the instruction 639 // adds the Pc. But for x86_64 external relocation entries the Value 640 // is the offset from the external symbol. 641 if (info->O->getAnyRelocationPCRel(RE)) 642 op_info->Value -= Pc + Offset + Size; 643 StringRef SymName; 644 Symbol.getName(SymName); 645 const char *name = SymName.data(); 646 unsigned Type = info->O->getAnyRelocationType(RE); 647 if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { 648 DataRefImpl RelNext = Rel; 649 info->O->moveRelocationNext(RelNext); 650 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 651 unsigned TypeNext = info->O->getAnyRelocationType(RENext); 652 bool isExternNext = info->O->getPlainRelocationExternal(RENext); 653 unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext); 654 if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) { 655 op_info->SubtractSymbol.Present = 1; 656 op_info->SubtractSymbol.Name = name; 657 symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); 658 Symbol = *RelocSymNext; 659 StringRef SymNameNext; 660 Symbol.getName(SymNameNext); 661 name = SymNameNext.data(); 662 } 663 } 664 // TODO: add the VariantKinds to op_info->VariantKind for relocation types 665 // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT. 666 op_info->AddSymbol.Present = 1; 667 op_info->AddSymbol.Name = name; 668 return 1; 669 } 670 // TODO: 671 // Second search the external relocation entries of a fully linked image 672 // (if any) for an entry that matches this segment offset. 673 // uint64_t seg_offset = (Pc + Offset); 674 return 0; 675 } else if (Arch == Triple::arm) { 676 if (Offset != 0 || (Size != 4 && Size != 2)) 677 return 0; 678 // First search the section's relocation entries (if any) for an entry 679 // for this section offset. 680 uint32_t sect_addr = info->S.getAddress(); 681 uint32_t sect_offset = (Pc + Offset) - sect_addr; 682 bool reloc_found = false; 683 DataRefImpl Rel; 684 MachO::any_relocation_info RE; 685 bool isExtern = false; 686 SymbolRef Symbol; 687 bool r_scattered = false; 688 uint32_t r_value, pair_r_value, r_type, r_length, other_half; 689 for (const RelocationRef &Reloc : info->S.relocations()) { 690 uint64_t RelocOffset; 691 Reloc.getOffset(RelocOffset); 692 if (RelocOffset == sect_offset) { 693 Rel = Reloc.getRawDataRefImpl(); 694 RE = info->O->getRelocation(Rel); 695 r_length = info->O->getAnyRelocationLength(RE); 696 r_scattered = info->O->isRelocationScattered(RE); 697 if (r_scattered) { 698 r_value = info->O->getScatteredRelocationValue(RE); 699 r_type = info->O->getScatteredRelocationType(RE); 700 } else { 701 r_type = info->O->getAnyRelocationType(RE); 702 isExtern = info->O->getPlainRelocationExternal(RE); 703 if (isExtern) { 704 symbol_iterator RelocSym = Reloc.getSymbol(); 705 Symbol = *RelocSym; 706 } 707 } 708 if (r_type == MachO::ARM_RELOC_HALF || 709 r_type == MachO::ARM_RELOC_SECTDIFF || 710 r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF || 711 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 712 DataRefImpl RelNext = Rel; 713 info->O->moveRelocationNext(RelNext); 714 MachO::any_relocation_info RENext; 715 RENext = info->O->getRelocation(RelNext); 716 other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff; 717 if (info->O->isRelocationScattered(RENext)) 718 pair_r_value = info->O->getScatteredRelocationValue(RENext); 719 } 720 reloc_found = true; 721 break; 722 } 723 } 724 if (reloc_found && isExtern) { 725 StringRef SymName; 726 Symbol.getName(SymName); 727 const char *name = SymName.data(); 728 op_info->AddSymbol.Present = 1; 729 op_info->AddSymbol.Name = name; 730 if (value != 0) { 731 switch (r_type) { 732 case MachO::ARM_RELOC_HALF: 733 if ((r_length & 0x1) == 1) { 734 op_info->Value = value << 16 | other_half; 735 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 736 } else { 737 op_info->Value = other_half << 16 | value; 738 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 739 } 740 break; 741 default: 742 break; 743 } 744 } else { 745 switch (r_type) { 746 case MachO::ARM_RELOC_HALF: 747 if ((r_length & 0x1) == 1) { 748 op_info->Value = value << 16 | other_half; 749 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 750 } else { 751 op_info->Value = other_half << 16 | value; 752 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 753 } 754 break; 755 default: 756 break; 757 } 758 } 759 return 1; 760 } 761 // If we have a branch that is not an external relocation entry then 762 // return 0 so the code in tryAddingSymbolicOperand() can use the 763 // SymbolLookUp call back with the branch target address to look up the 764 // symbol and possiblity add an annotation for a symbol stub. 765 if (reloc_found && isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || 766 r_type == MachO::ARM_THUMB_RELOC_BR22)) 767 return 0; 768 769 uint32_t offset = 0; 770 if (reloc_found) { 771 if (r_type == MachO::ARM_RELOC_HALF || 772 r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 773 if ((r_length & 0x1) == 1) 774 value = value << 16 | other_half; 775 else 776 value = other_half << 16 | value; 777 } 778 if (r_scattered && (r_type != MachO::ARM_RELOC_HALF && 779 r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) { 780 offset = value - r_value; 781 value = r_value; 782 } 783 } 784 785 if (reloc_found && r_type == MachO::ARM_RELOC_HALF_SECTDIFF) { 786 if ((r_length & 0x1) == 1) 787 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 788 else 789 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 790 const char *add = GuessSymbolName(r_value, info); 791 const char *sub = GuessSymbolName(pair_r_value, info); 792 int32_t offset = value - (r_value - pair_r_value); 793 op_info->AddSymbol.Present = 1; 794 if (add != nullptr) 795 op_info->AddSymbol.Name = add; 796 else 797 op_info->AddSymbol.Value = r_value; 798 op_info->SubtractSymbol.Present = 1; 799 if (sub != nullptr) 800 op_info->SubtractSymbol.Name = sub; 801 else 802 op_info->SubtractSymbol.Value = pair_r_value; 803 op_info->Value = offset; 804 return 1; 805 } 806 807 if (reloc_found == false) 808 return 0; 809 810 op_info->AddSymbol.Present = 1; 811 op_info->Value = offset; 812 if (reloc_found) { 813 if (r_type == MachO::ARM_RELOC_HALF) { 814 if ((r_length & 0x1) == 1) 815 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16; 816 else 817 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16; 818 } 819 } 820 const char *add = GuessSymbolName(value, info); 821 if (add != nullptr) { 822 op_info->AddSymbol.Name = add; 823 return 1; 824 } 825 op_info->AddSymbol.Value = value; 826 return 1; 827 } else if (Arch == Triple::aarch64) { 828 if (Offset != 0 || Size != 4) 829 return 0; 830 // First search the section's relocation entries (if any) for an entry 831 // for this section offset. 832 uint64_t sect_addr = info->S.getAddress(); 833 uint64_t sect_offset = (Pc + Offset) - sect_addr; 834 bool reloc_found = false; 835 DataRefImpl Rel; 836 MachO::any_relocation_info RE; 837 bool isExtern = false; 838 SymbolRef Symbol; 839 uint32_t r_type = 0; 840 for (const RelocationRef &Reloc : info->S.relocations()) { 841 uint64_t RelocOffset; 842 Reloc.getOffset(RelocOffset); 843 if (RelocOffset == sect_offset) { 844 Rel = Reloc.getRawDataRefImpl(); 845 RE = info->O->getRelocation(Rel); 846 r_type = info->O->getAnyRelocationType(RE); 847 if (r_type == MachO::ARM64_RELOC_ADDEND) { 848 DataRefImpl RelNext = Rel; 849 info->O->moveRelocationNext(RelNext); 850 MachO::any_relocation_info RENext = info->O->getRelocation(RelNext); 851 if (value == 0) { 852 value = info->O->getPlainRelocationSymbolNum(RENext); 853 op_info->Value = value; 854 } 855 } 856 // NOTE: Scattered relocations don't exist on arm64. 857 isExtern = info->O->getPlainRelocationExternal(RE); 858 if (isExtern) { 859 symbol_iterator RelocSym = Reloc.getSymbol(); 860 Symbol = *RelocSym; 861 } 862 reloc_found = true; 863 break; 864 } 865 } 866 if (reloc_found && isExtern) { 867 StringRef SymName; 868 Symbol.getName(SymName); 869 const char *name = SymName.data(); 870 op_info->AddSymbol.Present = 1; 871 op_info->AddSymbol.Name = name; 872 873 switch (r_type) { 874 case MachO::ARM64_RELOC_PAGE21: 875 /* @page */ 876 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE; 877 break; 878 case MachO::ARM64_RELOC_PAGEOFF12: 879 /* @pageoff */ 880 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF; 881 break; 882 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 883 /* @gotpage */ 884 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE; 885 break; 886 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 887 /* @gotpageoff */ 888 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF; 889 break; 890 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 891 /* @tvlppage is not implemented in llvm-mc */ 892 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP; 893 break; 894 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 895 /* @tvlppageoff is not implemented in llvm-mc */ 896 op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF; 897 break; 898 default: 899 case MachO::ARM64_RELOC_BRANCH26: 900 op_info->VariantKind = LLVMDisassembler_VariantKind_None; 901 break; 902 } 903 return 1; 904 } 905 return 0; 906 } else { 907 return 0; 908 } 909 } 910 911 // GuessCstringPointer is passed the address of what might be a pointer to a 912 // literal string in a cstring section. If that address is in a cstring section 913 // it returns a pointer to that string. Else it returns nullptr. 914 const char *GuessCstringPointer(uint64_t ReferenceValue, 915 struct DisassembleInfo *info) { 916 uint32_t LoadCommandCount = info->O->getHeader().ncmds; 917 MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); 918 for (unsigned I = 0;; ++I) { 919 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 920 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 921 for (unsigned J = 0; J < Seg.nsects; ++J) { 922 MachO::section_64 Sec = info->O->getSection64(Load, J); 923 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 924 if (section_type == MachO::S_CSTRING_LITERALS && 925 ReferenceValue >= Sec.addr && 926 ReferenceValue < Sec.addr + Sec.size) { 927 uint64_t sect_offset = ReferenceValue - Sec.addr; 928 uint64_t object_offset = Sec.offset + sect_offset; 929 StringRef MachOContents = info->O->getData(); 930 uint64_t object_size = MachOContents.size(); 931 const char *object_addr = (const char *)MachOContents.data(); 932 if (object_offset < object_size) { 933 const char *name = object_addr + object_offset; 934 return name; 935 } else { 936 return nullptr; 937 } 938 } 939 } 940 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 941 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 942 for (unsigned J = 0; J < Seg.nsects; ++J) { 943 MachO::section Sec = info->O->getSection(Load, J); 944 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 945 if (section_type == MachO::S_CSTRING_LITERALS && 946 ReferenceValue >= Sec.addr && 947 ReferenceValue < Sec.addr + Sec.size) { 948 uint64_t sect_offset = ReferenceValue - Sec.addr; 949 uint64_t object_offset = Sec.offset + sect_offset; 950 StringRef MachOContents = info->O->getData(); 951 uint64_t object_size = MachOContents.size(); 952 const char *object_addr = (const char *)MachOContents.data(); 953 if (object_offset < object_size) { 954 const char *name = object_addr + object_offset; 955 return name; 956 } else { 957 return nullptr; 958 } 959 } 960 } 961 } 962 if (I == LoadCommandCount - 1) 963 break; 964 else 965 Load = info->O->getNextLoadCommandInfo(Load); 966 } 967 return nullptr; 968 } 969 970 // GuessIndirectSymbol returns the name of the indirect symbol for the 971 // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe 972 // an address of a symbol stub or a lazy or non-lazy pointer to associate the 973 // symbol name being referenced by the stub or pointer. 974 static const char *GuessIndirectSymbol(uint64_t ReferenceValue, 975 struct DisassembleInfo *info) { 976 uint32_t LoadCommandCount = info->O->getHeader().ncmds; 977 MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); 978 MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand(); 979 MachO::symtab_command Symtab = info->O->getSymtabLoadCommand(); 980 for (unsigned I = 0;; ++I) { 981 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 982 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 983 for (unsigned J = 0; J < Seg.nsects; ++J) { 984 MachO::section_64 Sec = info->O->getSection64(Load, J); 985 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 986 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 987 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 988 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 989 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 990 section_type == MachO::S_SYMBOL_STUBS) && 991 ReferenceValue >= Sec.addr && 992 ReferenceValue < Sec.addr + Sec.size) { 993 uint32_t stride; 994 if (section_type == MachO::S_SYMBOL_STUBS) 995 stride = Sec.reserved2; 996 else 997 stride = 8; 998 if (stride == 0) 999 return nullptr; 1000 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 1001 if (index < Dysymtab.nindirectsyms) { 1002 uint32_t indirect_symbol = 1003 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 1004 if (indirect_symbol < Symtab.nsyms) { 1005 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 1006 SymbolRef Symbol = *Sym; 1007 StringRef SymName; 1008 Symbol.getName(SymName); 1009 const char *name = SymName.data(); 1010 return name; 1011 } 1012 } 1013 } 1014 } 1015 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1016 MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load); 1017 for (unsigned J = 0; J < Seg.nsects; ++J) { 1018 MachO::section Sec = info->O->getSection(Load, J); 1019 uint32_t section_type = Sec.flags & MachO::SECTION_TYPE; 1020 if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 1021 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 1022 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 1023 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS || 1024 section_type == MachO::S_SYMBOL_STUBS) && 1025 ReferenceValue >= Sec.addr && 1026 ReferenceValue < Sec.addr + Sec.size) { 1027 uint32_t stride; 1028 if (section_type == MachO::S_SYMBOL_STUBS) 1029 stride = Sec.reserved2; 1030 else 1031 stride = 4; 1032 if (stride == 0) 1033 return nullptr; 1034 uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride; 1035 if (index < Dysymtab.nindirectsyms) { 1036 uint32_t indirect_symbol = 1037 info->O->getIndirectSymbolTableEntry(Dysymtab, index); 1038 if (indirect_symbol < Symtab.nsyms) { 1039 symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); 1040 SymbolRef Symbol = *Sym; 1041 StringRef SymName; 1042 Symbol.getName(SymName); 1043 const char *name = SymName.data(); 1044 return name; 1045 } 1046 } 1047 } 1048 } 1049 } 1050 if (I == LoadCommandCount - 1) 1051 break; 1052 else 1053 Load = info->O->getNextLoadCommandInfo(Load); 1054 } 1055 return nullptr; 1056 } 1057 1058 // method_reference() is called passing it the ReferenceName that might be 1059 // a reference it to an Objective-C method call. If so then it allocates and 1060 // assembles a method call string with the values last seen and saved in 1061 // the DisassembleInfo's class_name and selector_name fields. This is saved 1062 // into the method field of the info and any previous string is free'ed. 1063 // Then the class_name field in the info is set to nullptr. The method call 1064 // string is set into ReferenceName and ReferenceType is set to 1065 // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call 1066 // then both ReferenceType and ReferenceName are left unchanged. 1067 static void method_reference(struct DisassembleInfo *info, 1068 uint64_t *ReferenceType, 1069 const char **ReferenceName) { 1070 unsigned int Arch = info->O->getArch(); 1071 if (*ReferenceName != nullptr) { 1072 if (strcmp(*ReferenceName, "_objc_msgSend") == 0) { 1073 if (info->selector_name != nullptr) { 1074 if (info->method != nullptr) 1075 free(info->method); 1076 if (info->class_name != nullptr) { 1077 info->method = (char *)malloc(5 + strlen(info->class_name) + 1078 strlen(info->selector_name)); 1079 if (info->method != nullptr) { 1080 strcpy(info->method, "+["); 1081 strcat(info->method, info->class_name); 1082 strcat(info->method, " "); 1083 strcat(info->method, info->selector_name); 1084 strcat(info->method, "]"); 1085 *ReferenceName = info->method; 1086 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 1087 } 1088 } else { 1089 info->method = (char *)malloc(9 + strlen(info->selector_name)); 1090 if (info->method != nullptr) { 1091 if (Arch == Triple::x86_64) 1092 strcpy(info->method, "-[%rdi "); 1093 else if (Arch == Triple::aarch64) 1094 strcpy(info->method, "-[x0 "); 1095 else 1096 strcpy(info->method, "-[r? "); 1097 strcat(info->method, info->selector_name); 1098 strcat(info->method, "]"); 1099 *ReferenceName = info->method; 1100 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 1101 } 1102 } 1103 info->class_name = nullptr; 1104 } 1105 } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) { 1106 if (info->selector_name != nullptr) { 1107 if (info->method != nullptr) 1108 free(info->method); 1109 info->method = (char *)malloc(17 + strlen(info->selector_name)); 1110 if (info->method != nullptr) { 1111 if (Arch == Triple::x86_64) 1112 strcpy(info->method, "-[[%rdi super] "); 1113 else if (Arch == Triple::aarch64) 1114 strcpy(info->method, "-[[x0 super] "); 1115 else 1116 strcpy(info->method, "-[[r? super] "); 1117 strcat(info->method, info->selector_name); 1118 strcat(info->method, "]"); 1119 *ReferenceName = info->method; 1120 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message; 1121 } 1122 info->class_name = nullptr; 1123 } 1124 } 1125 } 1126 } 1127 1128 // GuessPointerPointer() is passed the address of what might be a pointer to 1129 // a reference to an Objective-C class, selector, message ref or cfstring. 1130 // If so the value of the pointer is returned and one of the booleans are set 1131 // to true. If not zero is returned and all the booleans are set to false. 1132 static uint64_t GuessPointerPointer(uint64_t ReferenceValue, 1133 struct DisassembleInfo *info, 1134 bool &classref, bool &selref, bool &msgref, 1135 bool &cfstring) { 1136 classref = false; 1137 selref = false; 1138 msgref = false; 1139 cfstring = false; 1140 uint32_t LoadCommandCount = info->O->getHeader().ncmds; 1141 MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo(); 1142 for (unsigned I = 0;; ++I) { 1143 if (Load.C.cmd == MachO::LC_SEGMENT_64) { 1144 MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load); 1145 for (unsigned J = 0; J < Seg.nsects; ++J) { 1146 MachO::section_64 Sec = info->O->getSection64(Load, J); 1147 if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 || 1148 strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 1149 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 || 1150 strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 || 1151 strncmp(Sec.sectname, "__cfstring", 16) == 0) && 1152 ReferenceValue >= Sec.addr && 1153 ReferenceValue < Sec.addr + Sec.size) { 1154 uint64_t sect_offset = ReferenceValue - Sec.addr; 1155 uint64_t object_offset = Sec.offset + sect_offset; 1156 StringRef MachOContents = info->O->getData(); 1157 uint64_t object_size = MachOContents.size(); 1158 const char *object_addr = (const char *)MachOContents.data(); 1159 if (object_offset < object_size) { 1160 uint64_t pointer_value; 1161 memcpy(&pointer_value, object_addr + object_offset, 1162 sizeof(uint64_t)); 1163 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 1164 sys::swapByteOrder(pointer_value); 1165 if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0) 1166 selref = true; 1167 else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 || 1168 strncmp(Sec.sectname, "__objc_superrefs", 16) == 0) 1169 classref = true; 1170 else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 && 1171 ReferenceValue + 8 < Sec.addr + Sec.size) { 1172 msgref = true; 1173 memcpy(&pointer_value, object_addr + object_offset + 8, 1174 sizeof(uint64_t)); 1175 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 1176 sys::swapByteOrder(pointer_value); 1177 } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0) 1178 cfstring = true; 1179 return pointer_value; 1180 } else { 1181 return 0; 1182 } 1183 } 1184 } 1185 } 1186 // TODO: Look for LC_SEGMENT for 32-bit Mach-O files. 1187 if (I == LoadCommandCount - 1) 1188 break; 1189 else 1190 Load = info->O->getNextLoadCommandInfo(Load); 1191 } 1192 return 0; 1193 } 1194 1195 // get_pointer_64 returns a pointer to the bytes in the object file at the 1196 // Address from a section in the Mach-O file. And indirectly returns the 1197 // offset into the section, number of bytes left in the section past the offset 1198 // and which section is was being referenced. If the Address is not in a 1199 // section nullptr is returned. 1200 const char *get_pointer_64(uint64_t Address, uint32_t &offset, uint32_t &left, 1201 SectionRef &S, DisassembleInfo *info) { 1202 offset = 0; 1203 left = 0; 1204 S = SectionRef(); 1205 for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) { 1206 uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress(); 1207 uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize(); 1208 if (Address >= SectAddress && Address < SectAddress + SectSize) { 1209 S = (*(info->Sections))[SectIdx]; 1210 offset = Address - SectAddress; 1211 left = SectSize - offset; 1212 StringRef SectContents; 1213 ((*(info->Sections))[SectIdx]).getContents(SectContents); 1214 return SectContents.data() + offset; 1215 } 1216 } 1217 return nullptr; 1218 } 1219 1220 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of 1221 // the symbol indirectly through n_value. Based on the relocation information 1222 // for the specified section offset in the specified section reference. 1223 const char *get_symbol_64(uint32_t sect_offset, SectionRef S, 1224 DisassembleInfo *info, uint64_t &n_value) { 1225 n_value = 0; 1226 if (info->verbose == false) 1227 return nullptr; 1228 1229 // See if there is an external relocation entry at the sect_offset. 1230 bool reloc_found = false; 1231 DataRefImpl Rel; 1232 MachO::any_relocation_info RE; 1233 bool isExtern = false; 1234 SymbolRef Symbol; 1235 for (const RelocationRef &Reloc : S.relocations()) { 1236 uint64_t RelocOffset; 1237 Reloc.getOffset(RelocOffset); 1238 if (RelocOffset == sect_offset) { 1239 Rel = Reloc.getRawDataRefImpl(); 1240 RE = info->O->getRelocation(Rel); 1241 if (info->O->isRelocationScattered(RE)) 1242 continue; 1243 isExtern = info->O->getPlainRelocationExternal(RE); 1244 if (isExtern) { 1245 symbol_iterator RelocSym = Reloc.getSymbol(); 1246 Symbol = *RelocSym; 1247 } 1248 reloc_found = true; 1249 break; 1250 } 1251 } 1252 // If there is an external relocation entry for a symbol in this section 1253 // at this section_offset then use that symbol's value for the n_value 1254 // and return its name. 1255 const char *SymbolName = nullptr; 1256 if (reloc_found && isExtern) { 1257 Symbol.getAddress(n_value); 1258 StringRef name; 1259 Symbol.getName(name); 1260 if (!name.empty()) { 1261 SymbolName = name.data(); 1262 return SymbolName; 1263 } 1264 } 1265 1266 // TODO: For fully linked images, look through the external relocation 1267 // entries off the dynamic symtab command. For these the r_offset is from the 1268 // start of the first writeable segment in the Mach-O file. So the offset 1269 // to this section from that segment is passed to this routine by the caller, 1270 // as the database_offset. Which is the difference of the section's starting 1271 // address and the first writable segment. 1272 // 1273 // NOTE: need add passing the database_offset to this routine. 1274 1275 // TODO: We did not find an external relocation entry so look up the 1276 // ReferenceValue as an address of a symbol and if found return that symbol's 1277 // name. 1278 // 1279 // NOTE: need add passing the ReferenceValue to this routine. Then that code 1280 // would simply be this: 1281 // SymbolName = GuessSymbolName(ReferenceValue, info); 1282 1283 return SymbolName; 1284 } 1285 1286 // These are structs in the Objective-C meta data and read to produce the 1287 // comments for disassembly. While these are part of the ABI they are no 1288 // public defintions. So the are here not in include/llvm/Support/MachO.h . 1289 1290 // The cfstring object in a 64-bit Mach-O file. 1291 struct cfstring64_t { 1292 uint64_t isa; // class64_t * (64-bit pointer) 1293 uint64_t flags; // flag bits 1294 uint64_t characters; // char * (64-bit pointer) 1295 uint64_t length; // number of non-NULL characters in above 1296 }; 1297 1298 // The class object in a 64-bit Mach-O file. 1299 struct class64_t { 1300 uint64_t isa; // class64_t * (64-bit pointer) 1301 uint64_t superclass; // class64_t * (64-bit pointer) 1302 uint64_t cache; // Cache (64-bit pointer) 1303 uint64_t vtable; // IMP * (64-bit pointer) 1304 uint64_t data; // class_ro64_t * (64-bit pointer) 1305 }; 1306 1307 struct class_ro64_t { 1308 uint32_t flags; 1309 uint32_t instanceStart; 1310 uint32_t instanceSize; 1311 uint32_t reserved; 1312 uint64_t ivarLayout; // const uint8_t * (64-bit pointer) 1313 uint64_t name; // const char * (64-bit pointer) 1314 uint64_t baseMethods; // const method_list_t * (64-bit pointer) 1315 uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer) 1316 uint64_t ivars; // const ivar_list_t * (64-bit pointer) 1317 uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer) 1318 uint64_t baseProperties; // const struct objc_property_list (64-bit pointer) 1319 }; 1320 1321 inline void swapStruct(struct cfstring64_t &cfs) { 1322 sys::swapByteOrder(cfs.isa); 1323 sys::swapByteOrder(cfs.flags); 1324 sys::swapByteOrder(cfs.characters); 1325 sys::swapByteOrder(cfs.length); 1326 } 1327 1328 inline void swapStruct(struct class64_t &c) { 1329 sys::swapByteOrder(c.isa); 1330 sys::swapByteOrder(c.superclass); 1331 sys::swapByteOrder(c.cache); 1332 sys::swapByteOrder(c.vtable); 1333 sys::swapByteOrder(c.data); 1334 } 1335 1336 inline void swapStruct(struct class_ro64_t &cro) { 1337 sys::swapByteOrder(cro.flags); 1338 sys::swapByteOrder(cro.instanceStart); 1339 sys::swapByteOrder(cro.instanceSize); 1340 sys::swapByteOrder(cro.reserved); 1341 sys::swapByteOrder(cro.ivarLayout); 1342 sys::swapByteOrder(cro.name); 1343 sys::swapByteOrder(cro.baseMethods); 1344 sys::swapByteOrder(cro.baseProtocols); 1345 sys::swapByteOrder(cro.ivars); 1346 sys::swapByteOrder(cro.weakIvarLayout); 1347 sys::swapByteOrder(cro.baseProperties); 1348 } 1349 1350 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 1351 struct DisassembleInfo *info); 1352 1353 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer 1354 // to an Objective-C class and returns the class name. It is also passed the 1355 // address of the pointer, so when the pointer is zero as it can be in an .o 1356 // file, that is used to look for an external relocation entry with a symbol 1357 // name. 1358 const char *get_objc2_64bit_class_name(uint64_t pointer_value, 1359 uint64_t ReferenceValue, 1360 struct DisassembleInfo *info) { 1361 const char *r; 1362 uint32_t offset, left; 1363 SectionRef S; 1364 1365 // The pointer_value can be 0 in an object file and have a relocation 1366 // entry for the class symbol at the ReferenceValue (the address of the 1367 // pointer). 1368 if (pointer_value == 0) { 1369 r = get_pointer_64(ReferenceValue, offset, left, S, info); 1370 if (r == nullptr || left < sizeof(uint64_t)) 1371 return nullptr; 1372 uint64_t n_value; 1373 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 1374 if (symbol_name == nullptr) 1375 return nullptr; 1376 const char *class_name = strrchr(symbol_name, '$'); 1377 if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0') 1378 return class_name + 2; 1379 else 1380 return nullptr; 1381 } 1382 1383 // The case were the pointer_value is non-zero and points to a class defined 1384 // in this Mach-O file. 1385 r = get_pointer_64(pointer_value, offset, left, S, info); 1386 if (r == nullptr || left < sizeof(struct class64_t)) 1387 return nullptr; 1388 struct class64_t c; 1389 memcpy(&c, r, sizeof(struct class64_t)); 1390 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 1391 swapStruct(c); 1392 if (c.data == 0) 1393 return nullptr; 1394 r = get_pointer_64(c.data, offset, left, S, info); 1395 if (r == nullptr || left < sizeof(struct class_ro64_t)) 1396 return nullptr; 1397 struct class_ro64_t cro; 1398 memcpy(&cro, r, sizeof(struct class_ro64_t)); 1399 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 1400 swapStruct(cro); 1401 if (cro.name == 0) 1402 return nullptr; 1403 const char *name = get_pointer_64(cro.name, offset, left, S, info); 1404 return name; 1405 } 1406 1407 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a 1408 // pointer to a cfstring and returns its name or nullptr. 1409 const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue, 1410 struct DisassembleInfo *info) { 1411 const char *r, *name; 1412 uint32_t offset, left; 1413 SectionRef S; 1414 struct cfstring64_t cfs; 1415 uint64_t cfs_characters; 1416 1417 r = get_pointer_64(ReferenceValue, offset, left, S, info); 1418 if (r == nullptr || left < sizeof(struct cfstring64_t)) 1419 return nullptr; 1420 memcpy(&cfs, r, sizeof(struct cfstring64_t)); 1421 if (info->O->isLittleEndian() != sys::IsLittleEndianHost) 1422 swapStruct(cfs); 1423 if (cfs.characters == 0) { 1424 uint64_t n_value; 1425 const char *symbol_name = get_symbol_64( 1426 offset + offsetof(struct cfstring64_t, characters), S, info, n_value); 1427 if (symbol_name == nullptr) 1428 return nullptr; 1429 cfs_characters = n_value; 1430 } else 1431 cfs_characters = cfs.characters; 1432 name = get_pointer_64(cfs_characters, offset, left, S, info); 1433 1434 return name; 1435 } 1436 1437 // get_objc2_64bit_selref() is used for disassembly and is passed a the address 1438 // of a pointer to an Objective-C selector reference when the pointer value is 1439 // zero as in a .o file and is likely to have a external relocation entry with 1440 // who's symbol's n_value is the real pointer to the selector name. If that is 1441 // the case the real pointer to the selector name is returned else 0 is 1442 // returned 1443 uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue, 1444 struct DisassembleInfo *info) { 1445 uint32_t offset, left; 1446 SectionRef S; 1447 1448 const char *r = get_pointer_64(ReferenceValue, offset, left, S, info); 1449 if (r == nullptr || left < sizeof(uint64_t)) 1450 return 0; 1451 uint64_t n_value; 1452 const char *symbol_name = get_symbol_64(offset, S, info, n_value); 1453 if (symbol_name == nullptr) 1454 return 0; 1455 return n_value; 1456 } 1457 1458 // GuessLiteralPointer returns a string which for the item in the Mach-O file 1459 // for the address passed in as ReferenceValue for printing as a comment with 1460 // the instruction and also returns the corresponding type of that item 1461 // indirectly through ReferenceType. 1462 // 1463 // If ReferenceValue is an address of literal cstring then a pointer to the 1464 // cstring is returned and ReferenceType is set to 1465 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr . 1466 // 1467 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or 1468 // Class ref that name is returned and the ReferenceType is set accordingly. 1469 // 1470 // Lastly, literals which are Symbol address in a literal pool are looked for 1471 // and if found the symbol name is returned and ReferenceType is set to 1472 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr . 1473 // 1474 // If there is no item in the Mach-O file for the address passed in as 1475 // ReferenceValue nullptr is returned and ReferenceType is unchanged. 1476 const char *GuessLiteralPointer(uint64_t ReferenceValue, uint64_t ReferencePC, 1477 uint64_t *ReferenceType, 1478 struct DisassembleInfo *info) { 1479 // First see if there is an external relocation entry at the ReferencePC. 1480 uint64_t sect_addr = info->S.getAddress(); 1481 uint64_t sect_offset = ReferencePC - sect_addr; 1482 bool reloc_found = false; 1483 DataRefImpl Rel; 1484 MachO::any_relocation_info RE; 1485 bool isExtern = false; 1486 SymbolRef Symbol; 1487 for (const RelocationRef &Reloc : info->S.relocations()) { 1488 uint64_t RelocOffset; 1489 Reloc.getOffset(RelocOffset); 1490 if (RelocOffset == sect_offset) { 1491 Rel = Reloc.getRawDataRefImpl(); 1492 RE = info->O->getRelocation(Rel); 1493 if (info->O->isRelocationScattered(RE)) 1494 continue; 1495 isExtern = info->O->getPlainRelocationExternal(RE); 1496 if (isExtern) { 1497 symbol_iterator RelocSym = Reloc.getSymbol(); 1498 Symbol = *RelocSym; 1499 } 1500 reloc_found = true; 1501 break; 1502 } 1503 } 1504 // If there is an external relocation entry for a symbol in a section 1505 // then used that symbol's value for the value of the reference. 1506 if (reloc_found && isExtern) { 1507 if (info->O->getAnyRelocationPCRel(RE)) { 1508 unsigned Type = info->O->getAnyRelocationType(RE); 1509 if (Type == MachO::X86_64_RELOC_SIGNED) { 1510 Symbol.getAddress(ReferenceValue); 1511 } 1512 } 1513 } 1514 1515 // Look for literals such as Objective-C CFStrings refs, Selector refs, 1516 // Message refs and Class refs. 1517 bool classref, selref, msgref, cfstring; 1518 uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref, 1519 selref, msgref, cfstring); 1520 if (classref == true && pointer_value == 0) { 1521 // Note the ReferenceValue is a pointer into the __objc_classrefs section. 1522 // And the pointer_value in that section is typically zero as it will be 1523 // set by dyld as part of the "bind information". 1524 const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info); 1525 if (name != nullptr) { 1526 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 1527 const char *class_name = strrchr(name, '$'); 1528 if (class_name != nullptr && class_name[1] == '_' && 1529 class_name[2] != '\0') { 1530 info->class_name = class_name + 2; 1531 return name; 1532 } 1533 } 1534 } 1535 1536 if (classref == true) { 1537 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref; 1538 const char *name = 1539 get_objc2_64bit_class_name(pointer_value, ReferenceValue, info); 1540 if (name != nullptr) 1541 info->class_name = name; 1542 else 1543 name = "bad class ref"; 1544 return name; 1545 } 1546 1547 if (cfstring == true) { 1548 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref; 1549 const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info); 1550 return name; 1551 } 1552 1553 if (selref == true && pointer_value == 0) 1554 pointer_value = get_objc2_64bit_selref(ReferenceValue, info); 1555 1556 if (pointer_value != 0) 1557 ReferenceValue = pointer_value; 1558 1559 const char *name = GuessCstringPointer(ReferenceValue, info); 1560 if (name) { 1561 if (pointer_value != 0 && selref == true) { 1562 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref; 1563 info->selector_name = name; 1564 } else if (pointer_value != 0 && msgref == true) { 1565 info->class_name = nullptr; 1566 *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref; 1567 info->selector_name = name; 1568 } else 1569 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr; 1570 return name; 1571 } 1572 1573 // Lastly look for an indirect symbol with this ReferenceValue which is in 1574 // a literal pool. If found return that symbol name. 1575 name = GuessIndirectSymbol(ReferenceValue, info); 1576 if (name) { 1577 *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr; 1578 return name; 1579 } 1580 1581 return nullptr; 1582 } 1583 1584 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating 1585 // the Symbolizer. It looks up the ReferenceValue using the info passed via the 1586 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer 1587 // is created and returns the symbol name that matches the ReferenceValue or 1588 // nullptr if none. The ReferenceType is passed in for the IN type of 1589 // reference the instruction is making from the values in defined in the header 1590 // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific 1591 // Out type and the ReferenceName will also be set which is added as a comment 1592 // to the disassembled instruction. 1593 // 1594 #if HAVE_CXXABI_H 1595 // If the symbol name is a C++ mangled name then the demangled name is 1596 // returned through ReferenceName and ReferenceType is set to 1597 // LLVMDisassembler_ReferenceType_DeMangled_Name . 1598 #endif 1599 // 1600 // When this is called to get a symbol name for a branch target then the 1601 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then 1602 // SymbolValue will be looked for in the indirect symbol table to determine if 1603 // it is an address for a symbol stub. If so then the symbol name for that 1604 // stub is returned indirectly through ReferenceName and then ReferenceType is 1605 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub. 1606 // 1607 // When this is called with an value loaded via a PC relative load then 1608 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the 1609 // SymbolValue is checked to be an address of literal pointer, symbol pointer, 1610 // or an Objective-C meta data reference. If so the output ReferenceType is 1611 // set to correspond to that as well as setting the ReferenceName. 1612 const char *SymbolizerSymbolLookUp(void *DisInfo, uint64_t ReferenceValue, 1613 uint64_t *ReferenceType, 1614 uint64_t ReferencePC, 1615 const char **ReferenceName) { 1616 struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo; 1617 // If no verbose symbolic information is wanted then just return nullptr. 1618 if (info->verbose == false) { 1619 *ReferenceName = nullptr; 1620 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 1621 return nullptr; 1622 } 1623 1624 const char *SymbolName = GuessSymbolName(ReferenceValue, info); 1625 1626 if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) { 1627 *ReferenceName = GuessIndirectSymbol(ReferenceValue, info); 1628 if (*ReferenceName != nullptr) { 1629 method_reference(info, ReferenceType, ReferenceName); 1630 if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) 1631 *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; 1632 } else 1633 #if HAVE_CXXABI_H 1634 if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 1635 if (info->demangled_name != nullptr) 1636 free(info->demangled_name); 1637 int status; 1638 info->demangled_name = 1639 abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status); 1640 if (info->demangled_name != nullptr) { 1641 *ReferenceName = info->demangled_name; 1642 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 1643 } else 1644 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 1645 } else 1646 #endif 1647 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 1648 } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { 1649 *ReferenceName = 1650 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 1651 if (*ReferenceName) 1652 method_reference(info, ReferenceType, ReferenceName); 1653 else 1654 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 1655 // If this is arm64 and the reference is an adrp instruction save the 1656 // instruction, passed in ReferenceValue and the address of the instruction 1657 // for use later if we see and add immediate instruction. 1658 } else if (info->O->getArch() == Triple::aarch64 && 1659 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 1660 info->adrp_inst = ReferenceValue; 1661 info->adrp_addr = ReferencePC; 1662 SymbolName = nullptr; 1663 *ReferenceName = nullptr; 1664 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 1665 // If this is arm64 and reference is an add immediate instruction and we 1666 // have 1667 // seen an adrp instruction just before it and the adrp's Xd register 1668 // matches 1669 // this add's Xn register reconstruct the value being referenced and look to 1670 // see if it is a literal pointer. Note the add immediate instruction is 1671 // passed in ReferenceValue. 1672 } else if (info->O->getArch() == Triple::aarch64 && 1673 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 1674 ReferencePC - 4 == info->adrp_addr && 1675 (info->adrp_inst & 0x9f000000) == 0x90000000 && 1676 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 1677 uint32_t addxri_inst; 1678 uint64_t adrp_imm, addxri_imm; 1679 1680 adrp_imm = 1681 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 1682 if (info->adrp_inst & 0x0200000) 1683 adrp_imm |= 0xfffffffffc000000LL; 1684 1685 addxri_inst = ReferenceValue; 1686 addxri_imm = (addxri_inst >> 10) & 0xfff; 1687 if (((addxri_inst >> 22) & 0x3) == 1) 1688 addxri_imm <<= 12; 1689 1690 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 1691 (adrp_imm << 12) + addxri_imm; 1692 1693 *ReferenceName = 1694 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 1695 if (*ReferenceName == nullptr) 1696 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 1697 // If this is arm64 and the reference is a load register instruction and we 1698 // have seen an adrp instruction just before it and the adrp's Xd register 1699 // matches this add's Xn register reconstruct the value being referenced and 1700 // look to see if it is a literal pointer. Note the load register 1701 // instruction is passed in ReferenceValue. 1702 } else if (info->O->getArch() == Triple::aarch64 && 1703 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui && 1704 ReferencePC - 4 == info->adrp_addr && 1705 (info->adrp_inst & 0x9f000000) == 0x90000000 && 1706 (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) { 1707 uint32_t ldrxui_inst; 1708 uint64_t adrp_imm, ldrxui_imm; 1709 1710 adrp_imm = 1711 ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3); 1712 if (info->adrp_inst & 0x0200000) 1713 adrp_imm |= 0xfffffffffc000000LL; 1714 1715 ldrxui_inst = ReferenceValue; 1716 ldrxui_imm = (ldrxui_inst >> 10) & 0xfff; 1717 1718 ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) + 1719 (adrp_imm << 12) + (ldrxui_imm << 3); 1720 1721 *ReferenceName = 1722 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 1723 if (*ReferenceName == nullptr) 1724 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 1725 } 1726 // If this arm64 and is an load register (PC-relative) instruction the 1727 // ReferenceValue is the PC plus the immediate value. 1728 else if (info->O->getArch() == Triple::aarch64 && 1729 (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl || 1730 *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) { 1731 *ReferenceName = 1732 GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); 1733 if (*ReferenceName == nullptr) 1734 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 1735 } 1736 #if HAVE_CXXABI_H 1737 else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { 1738 if (info->demangled_name != nullptr) 1739 free(info->demangled_name); 1740 int status; 1741 info->demangled_name = 1742 abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status); 1743 if (info->demangled_name != nullptr) { 1744 *ReferenceName = info->demangled_name; 1745 *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; 1746 } 1747 } 1748 #endif 1749 else { 1750 *ReferenceName = nullptr; 1751 *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 1752 } 1753 1754 return SymbolName; 1755 } 1756 1757 /// \brief Emits the comments that are stored in the CommentStream. 1758 /// Each comment in the CommentStream must end with a newline. 1759 static void emitComments(raw_svector_ostream &CommentStream, 1760 SmallString<128> &CommentsToEmit, 1761 formatted_raw_ostream &FormattedOS, 1762 const MCAsmInfo &MAI) { 1763 // Flush the stream before taking its content. 1764 CommentStream.flush(); 1765 StringRef Comments = CommentsToEmit.str(); 1766 // Get the default information for printing a comment. 1767 const char *CommentBegin = MAI.getCommentString(); 1768 unsigned CommentColumn = MAI.getCommentColumn(); 1769 bool IsFirst = true; 1770 while (!Comments.empty()) { 1771 if (!IsFirst) 1772 FormattedOS << '\n'; 1773 // Emit a line of comments. 1774 FormattedOS.PadToColumn(CommentColumn); 1775 size_t Position = Comments.find('\n'); 1776 FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 1777 // Move after the newline character. 1778 Comments = Comments.substr(Position + 1); 1779 IsFirst = false; 1780 } 1781 FormattedOS.flush(); 1782 1783 // Tell the comment stream that the vector changed underneath it. 1784 CommentsToEmit.clear(); 1785 CommentStream.resync(); 1786 } 1787 1788 static void DisassembleInputMachO2(StringRef Filename, MachOObjectFile *MachOOF, 1789 StringRef ArchiveMemberName, 1790 StringRef ArchitectureName) { 1791 const char *McpuDefault = nullptr; 1792 const Target *ThumbTarget = nullptr; 1793 const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); 1794 if (!TheTarget) { 1795 // GetTarget prints out stuff. 1796 return; 1797 } 1798 if (MCPU.empty() && McpuDefault) 1799 MCPU = McpuDefault; 1800 1801 std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); 1802 std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; 1803 if (ThumbTarget) 1804 ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); 1805 1806 // Package up features to be passed to target/subtarget 1807 std::string FeaturesStr; 1808 if (MAttrs.size()) { 1809 SubtargetFeatures Features; 1810 for (unsigned i = 0; i != MAttrs.size(); ++i) 1811 Features.AddFeature(MAttrs[i]); 1812 FeaturesStr = Features.getString(); 1813 } 1814 1815 // Set up disassembler. 1816 std::unique_ptr<const MCRegisterInfo> MRI( 1817 TheTarget->createMCRegInfo(TripleName)); 1818 std::unique_ptr<const MCAsmInfo> AsmInfo( 1819 TheTarget->createMCAsmInfo(*MRI, TripleName)); 1820 std::unique_ptr<const MCSubtargetInfo> STI( 1821 TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); 1822 MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); 1823 std::unique_ptr<MCDisassembler> DisAsm( 1824 TheTarget->createMCDisassembler(*STI, Ctx)); 1825 std::unique_ptr<MCSymbolizer> Symbolizer; 1826 struct DisassembleInfo SymbolizerInfo; 1827 std::unique_ptr<MCRelocationInfo> RelInfo( 1828 TheTarget->createMCRelocationInfo(TripleName, Ctx)); 1829 if (RelInfo) { 1830 Symbolizer.reset(TheTarget->createMCSymbolizer( 1831 TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 1832 &SymbolizerInfo, &Ctx, RelInfo.release())); 1833 DisAsm->setSymbolizer(std::move(Symbolizer)); 1834 } 1835 int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); 1836 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 1837 AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI, *STI)); 1838 // Set the display preference for hex vs. decimal immediates. 1839 IP->setPrintImmHex(PrintImmHex); 1840 // Comment stream and backing vector. 1841 SmallString<128> CommentsToEmit; 1842 raw_svector_ostream CommentStream(CommentsToEmit); 1843 // FIXME: Setting the CommentStream in the InstPrinter is problematic in that 1844 // if it is done then arm64 comments for string literals don't get printed 1845 // and some constant get printed instead and not setting it causes intel 1846 // (32-bit and 64-bit) comments printed with different spacing before the 1847 // comment causing different diffs with the 'C' disassembler library API. 1848 // IP->setCommentStream(CommentStream); 1849 1850 if (!AsmInfo || !STI || !DisAsm || !IP) { 1851 errs() << "error: couldn't initialize disassembler for target " 1852 << TripleName << '\n'; 1853 return; 1854 } 1855 1856 // Set up thumb disassembler. 1857 std::unique_ptr<const MCRegisterInfo> ThumbMRI; 1858 std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; 1859 std::unique_ptr<const MCSubtargetInfo> ThumbSTI; 1860 std::unique_ptr<MCDisassembler> ThumbDisAsm; 1861 std::unique_ptr<MCInstPrinter> ThumbIP; 1862 std::unique_ptr<MCContext> ThumbCtx; 1863 std::unique_ptr<MCSymbolizer> ThumbSymbolizer; 1864 struct DisassembleInfo ThumbSymbolizerInfo; 1865 std::unique_ptr<MCRelocationInfo> ThumbRelInfo; 1866 if (ThumbTarget) { 1867 ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); 1868 ThumbAsmInfo.reset( 1869 ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName)); 1870 ThumbSTI.reset( 1871 ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MCPU, FeaturesStr)); 1872 ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); 1873 ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); 1874 MCContext *PtrThumbCtx = ThumbCtx.get(); 1875 ThumbRelInfo.reset( 1876 ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx)); 1877 if (ThumbRelInfo) { 1878 ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer( 1879 ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp, 1880 &ThumbSymbolizerInfo, PtrThumbCtx, ThumbRelInfo.release())); 1881 ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer)); 1882 } 1883 int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); 1884 ThumbIP.reset(ThumbTarget->createMCInstPrinter( 1885 ThumbAsmPrinterVariant, *ThumbAsmInfo, *ThumbInstrInfo, *ThumbMRI, 1886 *ThumbSTI)); 1887 // Set the display preference for hex vs. decimal immediates. 1888 ThumbIP->setPrintImmHex(PrintImmHex); 1889 } 1890 1891 if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) { 1892 errs() << "error: couldn't initialize disassembler for target " 1893 << ThumbTripleName << '\n'; 1894 return; 1895 } 1896 1897 outs() << Filename; 1898 if (!ArchiveMemberName.empty()) 1899 outs() << '(' << ArchiveMemberName << ')'; 1900 if (!ArchitectureName.empty()) 1901 outs() << " (architecture " << ArchitectureName << ")"; 1902 outs() << ":\n"; 1903 1904 MachO::mach_header Header = MachOOF->getHeader(); 1905 1906 // FIXME: Using the -cfg command line option, this code used to be able to 1907 // annotate relocations with the referenced symbol's name, and if this was 1908 // inside a __[cf]string section, the data it points to. This is now replaced 1909 // by the upcoming MCSymbolizer, which needs the appropriate setup done above. 1910 std::vector<SectionRef> Sections; 1911 std::vector<SymbolRef> Symbols; 1912 SmallVector<uint64_t, 8> FoundFns; 1913 uint64_t BaseSegmentAddress; 1914 1915 getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns, 1916 BaseSegmentAddress); 1917 1918 // Sort the symbols by address, just in case they didn't come in that way. 1919 std::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); 1920 1921 // Build a data in code table that is sorted on by the address of each entry. 1922 uint64_t BaseAddress = 0; 1923 if (Header.filetype == MachO::MH_OBJECT) 1924 BaseAddress = Sections[0].getAddress(); 1925 else 1926 BaseAddress = BaseSegmentAddress; 1927 DiceTable Dices; 1928 for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); 1929 DI != DE; ++DI) { 1930 uint32_t Offset; 1931 DI->getOffset(Offset); 1932 Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); 1933 } 1934 array_pod_sort(Dices.begin(), Dices.end()); 1935 1936 #ifndef NDEBUG 1937 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); 1938 #else 1939 raw_ostream &DebugOut = nulls(); 1940 #endif 1941 1942 std::unique_ptr<DIContext> diContext; 1943 ObjectFile *DbgObj = MachOOF; 1944 // Try to find debug info and set up the DIContext for it. 1945 if (UseDbg) { 1946 // A separate DSym file path was specified, parse it as a macho file, 1947 // get the sections and supply it to the section name parsing machinery. 1948 if (!DSYMFile.empty()) { 1949 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 1950 MemoryBuffer::getFileOrSTDIN(DSYMFile); 1951 if (std::error_code EC = BufOrErr.getError()) { 1952 errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n'; 1953 return; 1954 } 1955 DbgObj = 1956 ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()) 1957 .get() 1958 .release(); 1959 } 1960 1961 // Setup the DIContext 1962 diContext.reset(DIContext::getDWARFContext(*DbgObj)); 1963 } 1964 1965 // TODO: For now this only disassembles the (__TEXT,__text) section (see the 1966 // checks in the code below at the top of this loop). It should allow a 1967 // darwin otool(1) like -s option to disassemble any named segment & section 1968 // that is marked as containing instructions with the attributes 1969 // S_ATTR_PURE_INSTRUCTIONS or S_ATTR_SOME_INSTRUCTIONS in the flags field of 1970 // the section structure. 1971 outs() << "(__TEXT,__text) section\n"; 1972 1973 for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { 1974 1975 bool SectIsText = Sections[SectIdx].isText(); 1976 if (SectIsText == false) 1977 continue; 1978 1979 StringRef SectName; 1980 if (Sections[SectIdx].getName(SectName) || SectName != "__text") 1981 continue; // Skip non-text sections 1982 1983 DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); 1984 1985 StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); 1986 if (SegmentName != "__TEXT") 1987 continue; 1988 1989 StringRef BytesStr; 1990 Sections[SectIdx].getContents(BytesStr); 1991 ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()), 1992 BytesStr.size()); 1993 uint64_t SectAddress = Sections[SectIdx].getAddress(); 1994 1995 bool symbolTableWorked = false; 1996 1997 // Parse relocations. 1998 std::vector<std::pair<uint64_t, SymbolRef>> Relocs; 1999 for (const RelocationRef &Reloc : Sections[SectIdx].relocations()) { 2000 uint64_t RelocOffset; 2001 Reloc.getOffset(RelocOffset); 2002 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 2003 RelocOffset -= SectionAddress; 2004 2005 symbol_iterator RelocSym = Reloc.getSymbol(); 2006 2007 Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); 2008 } 2009 array_pod_sort(Relocs.begin(), Relocs.end()); 2010 2011 // Create a map of symbol addresses to symbol names for use by 2012 // the SymbolizerSymbolLookUp() routine. 2013 SymbolAddressMap AddrMap; 2014 for (const SymbolRef &Symbol : MachOOF->symbols()) { 2015 SymbolRef::Type ST; 2016 Symbol.getType(ST); 2017 if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || 2018 ST == SymbolRef::ST_Other) { 2019 uint64_t Address; 2020 Symbol.getAddress(Address); 2021 StringRef SymName; 2022 Symbol.getName(SymName); 2023 AddrMap[Address] = SymName; 2024 } 2025 } 2026 // Set up the block of info used by the Symbolizer call backs. 2027 SymbolizerInfo.verbose = true; 2028 SymbolizerInfo.O = MachOOF; 2029 SymbolizerInfo.S = Sections[SectIdx]; 2030 SymbolizerInfo.AddrMap = &AddrMap; 2031 SymbolizerInfo.Sections = &Sections; 2032 SymbolizerInfo.class_name = nullptr; 2033 SymbolizerInfo.selector_name = nullptr; 2034 SymbolizerInfo.method = nullptr; 2035 SymbolizerInfo.demangled_name = nullptr; 2036 SymbolizerInfo.bindtable = nullptr; 2037 SymbolizerInfo.adrp_addr = 0; 2038 SymbolizerInfo.adrp_inst = 0; 2039 // Same for the ThumbSymbolizer 2040 ThumbSymbolizerInfo.verbose = true; 2041 ThumbSymbolizerInfo.O = MachOOF; 2042 ThumbSymbolizerInfo.S = Sections[SectIdx]; 2043 ThumbSymbolizerInfo.AddrMap = &AddrMap; 2044 ThumbSymbolizerInfo.Sections = &Sections; 2045 ThumbSymbolizerInfo.class_name = nullptr; 2046 ThumbSymbolizerInfo.selector_name = nullptr; 2047 ThumbSymbolizerInfo.method = nullptr; 2048 ThumbSymbolizerInfo.demangled_name = nullptr; 2049 ThumbSymbolizerInfo.bindtable = nullptr; 2050 ThumbSymbolizerInfo.adrp_addr = 0; 2051 ThumbSymbolizerInfo.adrp_inst = 0; 2052 2053 // Disassemble symbol by symbol. 2054 for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { 2055 StringRef SymName; 2056 Symbols[SymIdx].getName(SymName); 2057 2058 SymbolRef::Type ST; 2059 Symbols[SymIdx].getType(ST); 2060 if (ST != SymbolRef::ST_Function) 2061 continue; 2062 2063 // Make sure the symbol is defined in this section. 2064 bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]); 2065 if (!containsSym) 2066 continue; 2067 2068 // Start at the address of the symbol relative to the section's address. 2069 uint64_t Start = 0; 2070 uint64_t SectionAddress = Sections[SectIdx].getAddress(); 2071 Symbols[SymIdx].getAddress(Start); 2072 Start -= SectionAddress; 2073 2074 // Stop disassembling either at the beginning of the next symbol or at 2075 // the end of the section. 2076 bool containsNextSym = false; 2077 uint64_t NextSym = 0; 2078 uint64_t NextSymIdx = SymIdx + 1; 2079 while (Symbols.size() > NextSymIdx) { 2080 SymbolRef::Type NextSymType; 2081 Symbols[NextSymIdx].getType(NextSymType); 2082 if (NextSymType == SymbolRef::ST_Function) { 2083 containsNextSym = 2084 Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]); 2085 Symbols[NextSymIdx].getAddress(NextSym); 2086 NextSym -= SectionAddress; 2087 break; 2088 } 2089 ++NextSymIdx; 2090 } 2091 2092 uint64_t SectSize = Sections[SectIdx].getSize(); 2093 uint64_t End = containsNextSym ? NextSym : SectSize; 2094 uint64_t Size; 2095 2096 symbolTableWorked = true; 2097 2098 DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); 2099 bool isThumb = 2100 (MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb) && ThumbTarget; 2101 2102 outs() << SymName << ":\n"; 2103 DILineInfo lastLine; 2104 for (uint64_t Index = Start; Index < End; Index += Size) { 2105 MCInst Inst; 2106 2107 uint64_t PC = SectAddress + Index; 2108 if (FullLeadingAddr) { 2109 if (MachOOF->is64Bit()) 2110 outs() << format("%016" PRIx64, PC); 2111 else 2112 outs() << format("%08" PRIx64, PC); 2113 } else { 2114 outs() << format("%8" PRIx64 ":", PC); 2115 } 2116 if (!NoShowRawInsn) 2117 outs() << "\t"; 2118 2119 // Check the data in code table here to see if this is data not an 2120 // instruction to be disassembled. 2121 DiceTable Dice; 2122 Dice.push_back(std::make_pair(PC, DiceRef())); 2123 dice_table_iterator DTI = 2124 std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(), 2125 compareDiceTableEntries); 2126 if (DTI != Dices.end()) { 2127 uint16_t Length; 2128 DTI->second.getLength(Length); 2129 uint16_t Kind; 2130 DTI->second.getKind(Kind); 2131 Size = DumpDataInCode(reinterpret_cast<const char *>(Bytes.data()) + 2132 Index, 2133 Length, Kind); 2134 if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) && 2135 (PC == (DTI->first + Length - 1)) && (Length & 1)) 2136 Size++; 2137 continue; 2138 } 2139 2140 SmallVector<char, 64> AnnotationsBytes; 2141 raw_svector_ostream Annotations(AnnotationsBytes); 2142 2143 bool gotInst; 2144 if (isThumb) 2145 gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index), 2146 PC, DebugOut, Annotations); 2147 else 2148 gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC, 2149 DebugOut, Annotations); 2150 if (gotInst) { 2151 if (!NoShowRawInsn) { 2152 DumpBytes(StringRef( 2153 reinterpret_cast<const char *>(Bytes.data()) + Index, Size)); 2154 } 2155 formatted_raw_ostream FormattedOS(outs()); 2156 Annotations.flush(); 2157 StringRef AnnotationsStr = Annotations.str(); 2158 if (isThumb) 2159 ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr); 2160 else 2161 IP->printInst(&Inst, FormattedOS, AnnotationsStr); 2162 emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo); 2163 2164 // Print debug info. 2165 if (diContext) { 2166 DILineInfo dli = diContext->getLineInfoForAddress(PC); 2167 // Print valid line info if it changed. 2168 if (dli != lastLine && dli.Line != 0) 2169 outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' 2170 << dli.Column; 2171 lastLine = dli; 2172 } 2173 outs() << "\n"; 2174 } else { 2175 unsigned int Arch = MachOOF->getArch(); 2176 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 2177 outs() << format("\t.byte 0x%02x #bad opcode\n", 2178 *(Bytes.data() + Index) & 0xff); 2179 Size = 1; // skip exactly one illegible byte and move on. 2180 } else if (Arch == Triple::aarch64) { 2181 uint32_t opcode = (*(Bytes.data() + Index) & 0xff) | 2182 (*(Bytes.data() + Index + 1) & 0xff) << 8 | 2183 (*(Bytes.data() + Index + 2) & 0xff) << 16 | 2184 (*(Bytes.data() + Index + 3) & 0xff) << 24; 2185 outs() << format("\t.long\t0x%08x\n", opcode); 2186 Size = 4; 2187 } else { 2188 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 2189 if (Size == 0) 2190 Size = 1; // skip illegible bytes 2191 } 2192 } 2193 } 2194 } 2195 if (!symbolTableWorked) { 2196 // Reading the symbol table didn't work, disassemble the whole section. 2197 uint64_t SectAddress = Sections[SectIdx].getAddress(); 2198 uint64_t SectSize = Sections[SectIdx].getSize(); 2199 uint64_t InstSize; 2200 for (uint64_t Index = 0; Index < SectSize; Index += InstSize) { 2201 MCInst Inst; 2202 2203 uint64_t PC = SectAddress + Index; 2204 if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC, 2205 DebugOut, nulls())) { 2206 if (FullLeadingAddr) { 2207 if (MachOOF->is64Bit()) 2208 outs() << format("%016" PRIx64, PC); 2209 else 2210 outs() << format("%08" PRIx64, PC); 2211 } else { 2212 outs() << format("%8" PRIx64 ":", PC); 2213 } 2214 if (!NoShowRawInsn) { 2215 outs() << "\t"; 2216 DumpBytes( 2217 StringRef(reinterpret_cast<const char *>(Bytes.data()) + Index, 2218 InstSize)); 2219 } 2220 IP->printInst(&Inst, outs(), ""); 2221 outs() << "\n"; 2222 } else { 2223 unsigned int Arch = MachOOF->getArch(); 2224 if (Arch == Triple::x86_64 || Arch == Triple::x86) { 2225 outs() << format("\t.byte 0x%02x #bad opcode\n", 2226 *(Bytes.data() + Index) & 0xff); 2227 InstSize = 1; // skip exactly one illegible byte and move on. 2228 } else { 2229 errs() << "llvm-objdump: warning: invalid instruction encoding\n"; 2230 if (InstSize == 0) 2231 InstSize = 1; // skip illegible bytes 2232 } 2233 } 2234 } 2235 } 2236 // The TripleName's need to be reset if we are called again for a different 2237 // archtecture. 2238 TripleName = ""; 2239 ThumbTripleName = ""; 2240 2241 if (SymbolizerInfo.method != nullptr) 2242 free(SymbolizerInfo.method); 2243 if (SymbolizerInfo.demangled_name != nullptr) 2244 free(SymbolizerInfo.demangled_name); 2245 if (SymbolizerInfo.bindtable != nullptr) 2246 delete SymbolizerInfo.bindtable; 2247 if (ThumbSymbolizerInfo.method != nullptr) 2248 free(ThumbSymbolizerInfo.method); 2249 if (ThumbSymbolizerInfo.demangled_name != nullptr) 2250 free(ThumbSymbolizerInfo.demangled_name); 2251 if (ThumbSymbolizerInfo.bindtable != nullptr) 2252 delete ThumbSymbolizerInfo.bindtable; 2253 } 2254 } 2255 2256 //===----------------------------------------------------------------------===// 2257 // __compact_unwind section dumping 2258 //===----------------------------------------------------------------------===// 2259 2260 namespace { 2261 2262 template <typename T> static uint64_t readNext(const char *&Buf) { 2263 using llvm::support::little; 2264 using llvm::support::unaligned; 2265 2266 uint64_t Val = support::endian::read<T, little, unaligned>(Buf); 2267 Buf += sizeof(T); 2268 return Val; 2269 } 2270 2271 struct CompactUnwindEntry { 2272 uint32_t OffsetInSection; 2273 2274 uint64_t FunctionAddr; 2275 uint32_t Length; 2276 uint32_t CompactEncoding; 2277 uint64_t PersonalityAddr; 2278 uint64_t LSDAAddr; 2279 2280 RelocationRef FunctionReloc; 2281 RelocationRef PersonalityReloc; 2282 RelocationRef LSDAReloc; 2283 2284 CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64) 2285 : OffsetInSection(Offset) { 2286 if (Is64) 2287 read<uint64_t>(Contents.data() + Offset); 2288 else 2289 read<uint32_t>(Contents.data() + Offset); 2290 } 2291 2292 private: 2293 template <typename UIntPtr> void read(const char *Buf) { 2294 FunctionAddr = readNext<UIntPtr>(Buf); 2295 Length = readNext<uint32_t>(Buf); 2296 CompactEncoding = readNext<uint32_t>(Buf); 2297 PersonalityAddr = readNext<UIntPtr>(Buf); 2298 LSDAAddr = readNext<UIntPtr>(Buf); 2299 } 2300 }; 2301 } 2302 2303 /// Given a relocation from __compact_unwind, consisting of the RelocationRef 2304 /// and data being relocated, determine the best base Name and Addend to use for 2305 /// display purposes. 2306 /// 2307 /// 1. An Extern relocation will directly reference a symbol (and the data is 2308 /// then already an addend), so use that. 2309 /// 2. Otherwise the data is an offset in the object file's layout; try to find 2310 // a symbol before it in the same section, and use the offset from there. 2311 /// 3. Finally, if all that fails, fall back to an offset from the start of the 2312 /// referenced section. 2313 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, 2314 std::map<uint64_t, SymbolRef> &Symbols, 2315 const RelocationRef &Reloc, uint64_t Addr, 2316 StringRef &Name, uint64_t &Addend) { 2317 if (Reloc.getSymbol() != Obj->symbol_end()) { 2318 Reloc.getSymbol()->getName(Name); 2319 Addend = Addr; 2320 return; 2321 } 2322 2323 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl()); 2324 SectionRef RelocSection = Obj->getRelocationSection(RE); 2325 2326 uint64_t SectionAddr = RelocSection.getAddress(); 2327 2328 auto Sym = Symbols.upper_bound(Addr); 2329 if (Sym == Symbols.begin()) { 2330 // The first symbol in the object is after this reference, the best we can 2331 // do is section-relative notation. 2332 RelocSection.getName(Name); 2333 Addend = Addr - SectionAddr; 2334 return; 2335 } 2336 2337 // Go back one so that SymbolAddress <= Addr. 2338 --Sym; 2339 2340 section_iterator SymSection = Obj->section_end(); 2341 Sym->second.getSection(SymSection); 2342 if (RelocSection == *SymSection) { 2343 // There's a valid symbol in the same section before this reference. 2344 Sym->second.getName(Name); 2345 Addend = Addr - Sym->first; 2346 return; 2347 } 2348 2349 // There is a symbol before this reference, but it's in a different 2350 // section. Probably not helpful to mention it, so use the section name. 2351 RelocSection.getName(Name); 2352 Addend = Addr - SectionAddr; 2353 } 2354 2355 static void printUnwindRelocDest(const MachOObjectFile *Obj, 2356 std::map<uint64_t, SymbolRef> &Symbols, 2357 const RelocationRef &Reloc, uint64_t Addr) { 2358 StringRef Name; 2359 uint64_t Addend; 2360 2361 if (!Reloc.getObjectFile()) 2362 return; 2363 2364 findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend); 2365 2366 outs() << Name; 2367 if (Addend) 2368 outs() << " + " << format("0x%" PRIx64, Addend); 2369 } 2370 2371 static void 2372 printMachOCompactUnwindSection(const MachOObjectFile *Obj, 2373 std::map<uint64_t, SymbolRef> &Symbols, 2374 const SectionRef &CompactUnwind) { 2375 2376 assert(Obj->isLittleEndian() && 2377 "There should not be a big-endian .o with __compact_unwind"); 2378 2379 bool Is64 = Obj->is64Bit(); 2380 uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); 2381 uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t); 2382 2383 StringRef Contents; 2384 CompactUnwind.getContents(Contents); 2385 2386 SmallVector<CompactUnwindEntry, 4> CompactUnwinds; 2387 2388 // First populate the initial raw offsets, encodings and so on from the entry. 2389 for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { 2390 CompactUnwindEntry Entry(Contents.data(), Offset, Is64); 2391 CompactUnwinds.push_back(Entry); 2392 } 2393 2394 // Next we need to look at the relocations to find out what objects are 2395 // actually being referred to. 2396 for (const RelocationRef &Reloc : CompactUnwind.relocations()) { 2397 uint64_t RelocAddress; 2398 Reloc.getOffset(RelocAddress); 2399 2400 uint32_t EntryIdx = RelocAddress / EntrySize; 2401 uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize; 2402 CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx]; 2403 2404 if (OffsetInEntry == 0) 2405 Entry.FunctionReloc = Reloc; 2406 else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t)) 2407 Entry.PersonalityReloc = Reloc; 2408 else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) 2409 Entry.LSDAReloc = Reloc; 2410 else 2411 llvm_unreachable("Unexpected relocation in __compact_unwind section"); 2412 } 2413 2414 // Finally, we're ready to print the data we've gathered. 2415 outs() << "Contents of __compact_unwind section:\n"; 2416 for (auto &Entry : CompactUnwinds) { 2417 outs() << " Entry at offset " 2418 << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n"; 2419 2420 // 1. Start of the region this entry applies to. 2421 outs() << " start: " << format("0x%" PRIx64, 2422 Entry.FunctionAddr) << ' '; 2423 printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr); 2424 outs() << '\n'; 2425 2426 // 2. Length of the region this entry applies to. 2427 outs() << " length: " << format("0x%" PRIx32, Entry.Length) 2428 << '\n'; 2429 // 3. The 32-bit compact encoding. 2430 outs() << " compact encoding: " 2431 << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n'; 2432 2433 // 4. The personality function, if present. 2434 if (Entry.PersonalityReloc.getObjectFile()) { 2435 outs() << " personality function: " 2436 << format("0x%" PRIx64, Entry.PersonalityAddr) << ' '; 2437 printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc, 2438 Entry.PersonalityAddr); 2439 outs() << '\n'; 2440 } 2441 2442 // 5. This entry's language-specific data area. 2443 if (Entry.LSDAReloc.getObjectFile()) { 2444 outs() << " LSDA: " << format("0x%" PRIx64, 2445 Entry.LSDAAddr) << ' '; 2446 printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr); 2447 outs() << '\n'; 2448 } 2449 } 2450 } 2451 2452 //===----------------------------------------------------------------------===// 2453 // __unwind_info section dumping 2454 //===----------------------------------------------------------------------===// 2455 2456 static void printRegularSecondLevelUnwindPage(const char *PageStart) { 2457 const char *Pos = PageStart; 2458 uint32_t Kind = readNext<uint32_t>(Pos); 2459 (void)Kind; 2460 assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); 2461 2462 uint16_t EntriesStart = readNext<uint16_t>(Pos); 2463 uint16_t NumEntries = readNext<uint16_t>(Pos); 2464 2465 Pos = PageStart + EntriesStart; 2466 for (unsigned i = 0; i < NumEntries; ++i) { 2467 uint32_t FunctionOffset = readNext<uint32_t>(Pos); 2468 uint32_t Encoding = readNext<uint32_t>(Pos); 2469 2470 outs() << " [" << i << "]: " 2471 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 2472 << ", " 2473 << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n'; 2474 } 2475 } 2476 2477 static void printCompressedSecondLevelUnwindPage( 2478 const char *PageStart, uint32_t FunctionBase, 2479 const SmallVectorImpl<uint32_t> &CommonEncodings) { 2480 const char *Pos = PageStart; 2481 uint32_t Kind = readNext<uint32_t>(Pos); 2482 (void)Kind; 2483 assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); 2484 2485 uint16_t EntriesStart = readNext<uint16_t>(Pos); 2486 uint16_t NumEntries = readNext<uint16_t>(Pos); 2487 2488 uint16_t EncodingsStart = readNext<uint16_t>(Pos); 2489 readNext<uint16_t>(Pos); 2490 const auto *PageEncodings = reinterpret_cast<const support::ulittle32_t *>( 2491 PageStart + EncodingsStart); 2492 2493 Pos = PageStart + EntriesStart; 2494 for (unsigned i = 0; i < NumEntries; ++i) { 2495 uint32_t Entry = readNext<uint32_t>(Pos); 2496 uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff); 2497 uint32_t EncodingIdx = Entry >> 24; 2498 2499 uint32_t Encoding; 2500 if (EncodingIdx < CommonEncodings.size()) 2501 Encoding = CommonEncodings[EncodingIdx]; 2502 else 2503 Encoding = PageEncodings[EncodingIdx - CommonEncodings.size()]; 2504 2505 outs() << " [" << i << "]: " 2506 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 2507 << ", " 2508 << "encoding[" << EncodingIdx 2509 << "]=" << format("0x%08" PRIx32, Encoding) << '\n'; 2510 } 2511 } 2512 2513 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, 2514 std::map<uint64_t, SymbolRef> &Symbols, 2515 const SectionRef &UnwindInfo) { 2516 2517 assert(Obj->isLittleEndian() && 2518 "There should not be a big-endian .o with __unwind_info"); 2519 2520 outs() << "Contents of __unwind_info section:\n"; 2521 2522 StringRef Contents; 2523 UnwindInfo.getContents(Contents); 2524 const char *Pos = Contents.data(); 2525 2526 //===---------------------------------- 2527 // Section header 2528 //===---------------------------------- 2529 2530 uint32_t Version = readNext<uint32_t>(Pos); 2531 outs() << " Version: " 2532 << format("0x%" PRIx32, Version) << '\n'; 2533 assert(Version == 1 && "only understand version 1"); 2534 2535 uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos); 2536 outs() << " Common encodings array section offset: " 2537 << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; 2538 uint32_t NumCommonEncodings = readNext<uint32_t>(Pos); 2539 outs() << " Number of common encodings in array: " 2540 << format("0x%" PRIx32, NumCommonEncodings) << '\n'; 2541 2542 uint32_t PersonalitiesStart = readNext<uint32_t>(Pos); 2543 outs() << " Personality function array section offset: " 2544 << format("0x%" PRIx32, PersonalitiesStart) << '\n'; 2545 uint32_t NumPersonalities = readNext<uint32_t>(Pos); 2546 outs() << " Number of personality functions in array: " 2547 << format("0x%" PRIx32, NumPersonalities) << '\n'; 2548 2549 uint32_t IndicesStart = readNext<uint32_t>(Pos); 2550 outs() << " Index array section offset: " 2551 << format("0x%" PRIx32, IndicesStart) << '\n'; 2552 uint32_t NumIndices = readNext<uint32_t>(Pos); 2553 outs() << " Number of indices in array: " 2554 << format("0x%" PRIx32, NumIndices) << '\n'; 2555 2556 //===---------------------------------- 2557 // A shared list of common encodings 2558 //===---------------------------------- 2559 2560 // These occupy indices in the range [0, N] whenever an encoding is referenced 2561 // from a compressed 2nd level index table. In practice the linker only 2562 // creates ~128 of these, so that indices are available to embed encodings in 2563 // the 2nd level index. 2564 2565 SmallVector<uint32_t, 64> CommonEncodings; 2566 outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n"; 2567 Pos = Contents.data() + CommonEncodingsStart; 2568 for (unsigned i = 0; i < NumCommonEncodings; ++i) { 2569 uint32_t Encoding = readNext<uint32_t>(Pos); 2570 CommonEncodings.push_back(Encoding); 2571 2572 outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) 2573 << '\n'; 2574 } 2575 2576 //===---------------------------------- 2577 // Personality functions used in this executable 2578 //===---------------------------------- 2579 2580 // There should be only a handful of these (one per source language, 2581 // roughly). Particularly since they only get 2 bits in the compact encoding. 2582 2583 outs() << " Personality functions: (count = " << NumPersonalities << ")\n"; 2584 Pos = Contents.data() + PersonalitiesStart; 2585 for (unsigned i = 0; i < NumPersonalities; ++i) { 2586 uint32_t PersonalityFn = readNext<uint32_t>(Pos); 2587 outs() << " personality[" << i + 1 2588 << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n'; 2589 } 2590 2591 //===---------------------------------- 2592 // The level 1 index entries 2593 //===---------------------------------- 2594 2595 // These specify an approximate place to start searching for the more detailed 2596 // information, sorted by PC. 2597 2598 struct IndexEntry { 2599 uint32_t FunctionOffset; 2600 uint32_t SecondLevelPageStart; 2601 uint32_t LSDAStart; 2602 }; 2603 2604 SmallVector<IndexEntry, 4> IndexEntries; 2605 2606 outs() << " Top level indices: (count = " << NumIndices << ")\n"; 2607 Pos = Contents.data() + IndicesStart; 2608 for (unsigned i = 0; i < NumIndices; ++i) { 2609 IndexEntry Entry; 2610 2611 Entry.FunctionOffset = readNext<uint32_t>(Pos); 2612 Entry.SecondLevelPageStart = readNext<uint32_t>(Pos); 2613 Entry.LSDAStart = readNext<uint32_t>(Pos); 2614 IndexEntries.push_back(Entry); 2615 2616 outs() << " [" << i << "]: " 2617 << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset) 2618 << ", " 2619 << "2nd level page offset=" 2620 << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", " 2621 << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n'; 2622 } 2623 2624 //===---------------------------------- 2625 // Next come the LSDA tables 2626 //===---------------------------------- 2627 2628 // The LSDA layout is rather implicit: it's a contiguous array of entries from 2629 // the first top-level index's LSDAOffset to the last (sentinel). 2630 2631 outs() << " LSDA descriptors:\n"; 2632 Pos = Contents.data() + IndexEntries[0].LSDAStart; 2633 int NumLSDAs = (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / 2634 (2 * sizeof(uint32_t)); 2635 for (int i = 0; i < NumLSDAs; ++i) { 2636 uint32_t FunctionOffset = readNext<uint32_t>(Pos); 2637 uint32_t LSDAOffset = readNext<uint32_t>(Pos); 2638 outs() << " [" << i << "]: " 2639 << "function offset=" << format("0x%08" PRIx32, FunctionOffset) 2640 << ", " 2641 << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n'; 2642 } 2643 2644 //===---------------------------------- 2645 // Finally, the 2nd level indices 2646 //===---------------------------------- 2647 2648 // Generally these are 4K in size, and have 2 possible forms: 2649 // + Regular stores up to 511 entries with disparate encodings 2650 // + Compressed stores up to 1021 entries if few enough compact encoding 2651 // values are used. 2652 outs() << " Second level indices:\n"; 2653 for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) { 2654 // The final sentinel top-level index has no associated 2nd level page 2655 if (IndexEntries[i].SecondLevelPageStart == 0) 2656 break; 2657 2658 outs() << " Second level index[" << i << "]: " 2659 << "offset in section=" 2660 << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart) 2661 << ", " 2662 << "base function offset=" 2663 << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; 2664 2665 Pos = Contents.data() + IndexEntries[i].SecondLevelPageStart; 2666 uint32_t Kind = *reinterpret_cast<const support::ulittle32_t *>(Pos); 2667 if (Kind == 2) 2668 printRegularSecondLevelUnwindPage(Pos); 2669 else if (Kind == 3) 2670 printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset, 2671 CommonEncodings); 2672 else 2673 llvm_unreachable("Do not know how to print this kind of 2nd level page"); 2674 } 2675 } 2676 2677 void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { 2678 std::map<uint64_t, SymbolRef> Symbols; 2679 for (const SymbolRef &SymRef : Obj->symbols()) { 2680 // Discard any undefined or absolute symbols. They're not going to take part 2681 // in the convenience lookup for unwind info and just take up resources. 2682 section_iterator Section = Obj->section_end(); 2683 SymRef.getSection(Section); 2684 if (Section == Obj->section_end()) 2685 continue; 2686 2687 uint64_t Addr; 2688 SymRef.getAddress(Addr); 2689 Symbols.insert(std::make_pair(Addr, SymRef)); 2690 } 2691 2692 for (const SectionRef &Section : Obj->sections()) { 2693 StringRef SectName; 2694 Section.getName(SectName); 2695 if (SectName == "__compact_unwind") 2696 printMachOCompactUnwindSection(Obj, Symbols, Section); 2697 else if (SectName == "__unwind_info") 2698 printMachOUnwindInfoSection(Obj, Symbols, Section); 2699 else if (SectName == "__eh_frame") 2700 outs() << "llvm-objdump: warning: unhandled __eh_frame section\n"; 2701 } 2702 } 2703 2704 static void PrintMachHeader(uint32_t magic, uint32_t cputype, 2705 uint32_t cpusubtype, uint32_t filetype, 2706 uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags, 2707 bool verbose) { 2708 outs() << "Mach header\n"; 2709 outs() << " magic cputype cpusubtype caps filetype ncmds " 2710 "sizeofcmds flags\n"; 2711 if (verbose) { 2712 if (magic == MachO::MH_MAGIC) 2713 outs() << " MH_MAGIC"; 2714 else if (magic == MachO::MH_MAGIC_64) 2715 outs() << "MH_MAGIC_64"; 2716 else 2717 outs() << format(" 0x%08" PRIx32, magic); 2718 switch (cputype) { 2719 case MachO::CPU_TYPE_I386: 2720 outs() << " I386"; 2721 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2722 case MachO::CPU_SUBTYPE_I386_ALL: 2723 outs() << " ALL"; 2724 break; 2725 default: 2726 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2727 break; 2728 } 2729 break; 2730 case MachO::CPU_TYPE_X86_64: 2731 outs() << " X86_64"; 2732 case MachO::CPU_SUBTYPE_X86_64_ALL: 2733 outs() << " ALL"; 2734 break; 2735 case MachO::CPU_SUBTYPE_X86_64_H: 2736 outs() << " Haswell"; 2737 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2738 break; 2739 case MachO::CPU_TYPE_ARM: 2740 outs() << " ARM"; 2741 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2742 case MachO::CPU_SUBTYPE_ARM_ALL: 2743 outs() << " ALL"; 2744 break; 2745 case MachO::CPU_SUBTYPE_ARM_V4T: 2746 outs() << " V4T"; 2747 break; 2748 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2749 outs() << " V5TEJ"; 2750 break; 2751 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2752 outs() << " XSCALE"; 2753 break; 2754 case MachO::CPU_SUBTYPE_ARM_V6: 2755 outs() << " V6"; 2756 break; 2757 case MachO::CPU_SUBTYPE_ARM_V6M: 2758 outs() << " V6M"; 2759 break; 2760 case MachO::CPU_SUBTYPE_ARM_V7: 2761 outs() << " V7"; 2762 break; 2763 case MachO::CPU_SUBTYPE_ARM_V7EM: 2764 outs() << " V7EM"; 2765 break; 2766 case MachO::CPU_SUBTYPE_ARM_V7K: 2767 outs() << " V7K"; 2768 break; 2769 case MachO::CPU_SUBTYPE_ARM_V7M: 2770 outs() << " V7M"; 2771 break; 2772 case MachO::CPU_SUBTYPE_ARM_V7S: 2773 outs() << " V7S"; 2774 break; 2775 default: 2776 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2777 break; 2778 } 2779 break; 2780 case MachO::CPU_TYPE_ARM64: 2781 outs() << " ARM64"; 2782 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2783 case MachO::CPU_SUBTYPE_ARM64_ALL: 2784 outs() << " ALL"; 2785 break; 2786 default: 2787 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2788 break; 2789 } 2790 break; 2791 case MachO::CPU_TYPE_POWERPC: 2792 outs() << " PPC"; 2793 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2794 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2795 outs() << " ALL"; 2796 break; 2797 default: 2798 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2799 break; 2800 } 2801 break; 2802 case MachO::CPU_TYPE_POWERPC64: 2803 outs() << " PPC64"; 2804 switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) { 2805 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2806 outs() << " ALL"; 2807 break; 2808 default: 2809 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2810 break; 2811 } 2812 break; 2813 } 2814 if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) { 2815 outs() << " LIB64"; 2816 } else { 2817 outs() << format(" 0x%02" PRIx32, 2818 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 2819 } 2820 switch (filetype) { 2821 case MachO::MH_OBJECT: 2822 outs() << " OBJECT"; 2823 break; 2824 case MachO::MH_EXECUTE: 2825 outs() << " EXECUTE"; 2826 break; 2827 case MachO::MH_FVMLIB: 2828 outs() << " FVMLIB"; 2829 break; 2830 case MachO::MH_CORE: 2831 outs() << " CORE"; 2832 break; 2833 case MachO::MH_PRELOAD: 2834 outs() << " PRELOAD"; 2835 break; 2836 case MachO::MH_DYLIB: 2837 outs() << " DYLIB"; 2838 break; 2839 case MachO::MH_DYLIB_STUB: 2840 outs() << " DYLIB_STUB"; 2841 break; 2842 case MachO::MH_DYLINKER: 2843 outs() << " DYLINKER"; 2844 break; 2845 case MachO::MH_BUNDLE: 2846 outs() << " BUNDLE"; 2847 break; 2848 case MachO::MH_DSYM: 2849 outs() << " DSYM"; 2850 break; 2851 case MachO::MH_KEXT_BUNDLE: 2852 outs() << " KEXTBUNDLE"; 2853 break; 2854 default: 2855 outs() << format(" %10u", filetype); 2856 break; 2857 } 2858 outs() << format(" %5u", ncmds); 2859 outs() << format(" %10u", sizeofcmds); 2860 uint32_t f = flags; 2861 if (f & MachO::MH_NOUNDEFS) { 2862 outs() << " NOUNDEFS"; 2863 f &= ~MachO::MH_NOUNDEFS; 2864 } 2865 if (f & MachO::MH_INCRLINK) { 2866 outs() << " INCRLINK"; 2867 f &= ~MachO::MH_INCRLINK; 2868 } 2869 if (f & MachO::MH_DYLDLINK) { 2870 outs() << " DYLDLINK"; 2871 f &= ~MachO::MH_DYLDLINK; 2872 } 2873 if (f & MachO::MH_BINDATLOAD) { 2874 outs() << " BINDATLOAD"; 2875 f &= ~MachO::MH_BINDATLOAD; 2876 } 2877 if (f & MachO::MH_PREBOUND) { 2878 outs() << " PREBOUND"; 2879 f &= ~MachO::MH_PREBOUND; 2880 } 2881 if (f & MachO::MH_SPLIT_SEGS) { 2882 outs() << " SPLIT_SEGS"; 2883 f &= ~MachO::MH_SPLIT_SEGS; 2884 } 2885 if (f & MachO::MH_LAZY_INIT) { 2886 outs() << " LAZY_INIT"; 2887 f &= ~MachO::MH_LAZY_INIT; 2888 } 2889 if (f & MachO::MH_TWOLEVEL) { 2890 outs() << " TWOLEVEL"; 2891 f &= ~MachO::MH_TWOLEVEL; 2892 } 2893 if (f & MachO::MH_FORCE_FLAT) { 2894 outs() << " FORCE_FLAT"; 2895 f &= ~MachO::MH_FORCE_FLAT; 2896 } 2897 if (f & MachO::MH_NOMULTIDEFS) { 2898 outs() << " NOMULTIDEFS"; 2899 f &= ~MachO::MH_NOMULTIDEFS; 2900 } 2901 if (f & MachO::MH_NOFIXPREBINDING) { 2902 outs() << " NOFIXPREBINDING"; 2903 f &= ~MachO::MH_NOFIXPREBINDING; 2904 } 2905 if (f & MachO::MH_PREBINDABLE) { 2906 outs() << " PREBINDABLE"; 2907 f &= ~MachO::MH_PREBINDABLE; 2908 } 2909 if (f & MachO::MH_ALLMODSBOUND) { 2910 outs() << " ALLMODSBOUND"; 2911 f &= ~MachO::MH_ALLMODSBOUND; 2912 } 2913 if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) { 2914 outs() << " SUBSECTIONS_VIA_SYMBOLS"; 2915 f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS; 2916 } 2917 if (f & MachO::MH_CANONICAL) { 2918 outs() << " CANONICAL"; 2919 f &= ~MachO::MH_CANONICAL; 2920 } 2921 if (f & MachO::MH_WEAK_DEFINES) { 2922 outs() << " WEAK_DEFINES"; 2923 f &= ~MachO::MH_WEAK_DEFINES; 2924 } 2925 if (f & MachO::MH_BINDS_TO_WEAK) { 2926 outs() << " BINDS_TO_WEAK"; 2927 f &= ~MachO::MH_BINDS_TO_WEAK; 2928 } 2929 if (f & MachO::MH_ALLOW_STACK_EXECUTION) { 2930 outs() << " ALLOW_STACK_EXECUTION"; 2931 f &= ~MachO::MH_ALLOW_STACK_EXECUTION; 2932 } 2933 if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) { 2934 outs() << " DEAD_STRIPPABLE_DYLIB"; 2935 f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB; 2936 } 2937 if (f & MachO::MH_PIE) { 2938 outs() << " PIE"; 2939 f &= ~MachO::MH_PIE; 2940 } 2941 if (f & MachO::MH_NO_REEXPORTED_DYLIBS) { 2942 outs() << " NO_REEXPORTED_DYLIBS"; 2943 f &= ~MachO::MH_NO_REEXPORTED_DYLIBS; 2944 } 2945 if (f & MachO::MH_HAS_TLV_DESCRIPTORS) { 2946 outs() << " MH_HAS_TLV_DESCRIPTORS"; 2947 f &= ~MachO::MH_HAS_TLV_DESCRIPTORS; 2948 } 2949 if (f & MachO::MH_NO_HEAP_EXECUTION) { 2950 outs() << " MH_NO_HEAP_EXECUTION"; 2951 f &= ~MachO::MH_NO_HEAP_EXECUTION; 2952 } 2953 if (f & MachO::MH_APP_EXTENSION_SAFE) { 2954 outs() << " APP_EXTENSION_SAFE"; 2955 f &= ~MachO::MH_APP_EXTENSION_SAFE; 2956 } 2957 if (f != 0 || flags == 0) 2958 outs() << format(" 0x%08" PRIx32, f); 2959 } else { 2960 outs() << format(" 0x%08" PRIx32, magic); 2961 outs() << format(" %7d", cputype); 2962 outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK); 2963 outs() << format(" 0x%02" PRIx32, 2964 (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24); 2965 outs() << format(" %10u", filetype); 2966 outs() << format(" %5u", ncmds); 2967 outs() << format(" %10u", sizeofcmds); 2968 outs() << format(" 0x%08" PRIx32, flags); 2969 } 2970 outs() << "\n"; 2971 } 2972 2973 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, 2974 StringRef SegName, uint64_t vmaddr, 2975 uint64_t vmsize, uint64_t fileoff, 2976 uint64_t filesize, uint32_t maxprot, 2977 uint32_t initprot, uint32_t nsects, 2978 uint32_t flags, uint32_t object_size, 2979 bool verbose) { 2980 uint64_t expected_cmdsize; 2981 if (cmd == MachO::LC_SEGMENT) { 2982 outs() << " cmd LC_SEGMENT\n"; 2983 expected_cmdsize = nsects; 2984 expected_cmdsize *= sizeof(struct MachO::section); 2985 expected_cmdsize += sizeof(struct MachO::segment_command); 2986 } else { 2987 outs() << " cmd LC_SEGMENT_64\n"; 2988 expected_cmdsize = nsects; 2989 expected_cmdsize *= sizeof(struct MachO::section_64); 2990 expected_cmdsize += sizeof(struct MachO::segment_command_64); 2991 } 2992 outs() << " cmdsize " << cmdsize; 2993 if (cmdsize != expected_cmdsize) 2994 outs() << " Inconsistent size\n"; 2995 else 2996 outs() << "\n"; 2997 outs() << " segname " << SegName << "\n"; 2998 if (cmd == MachO::LC_SEGMENT_64) { 2999 outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n"; 3000 outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n"; 3001 } else { 3002 outs() << " vmaddr " << format("0x%08" PRIx32, vmaddr) << "\n"; 3003 outs() << " vmsize " << format("0x%08" PRIx32, vmsize) << "\n"; 3004 } 3005 outs() << " fileoff " << fileoff; 3006 if (fileoff > object_size) 3007 outs() << " (past end of file)\n"; 3008 else 3009 outs() << "\n"; 3010 outs() << " filesize " << filesize; 3011 if (fileoff + filesize > object_size) 3012 outs() << " (past end of file)\n"; 3013 else 3014 outs() << "\n"; 3015 if (verbose) { 3016 if ((maxprot & 3017 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 3018 MachO::VM_PROT_EXECUTE)) != 0) 3019 outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n"; 3020 else { 3021 if (maxprot & MachO::VM_PROT_READ) 3022 outs() << " maxprot r"; 3023 else 3024 outs() << " maxprot -"; 3025 if (maxprot & MachO::VM_PROT_WRITE) 3026 outs() << "w"; 3027 else 3028 outs() << "-"; 3029 if (maxprot & MachO::VM_PROT_EXECUTE) 3030 outs() << "x\n"; 3031 else 3032 outs() << "-\n"; 3033 } 3034 if ((initprot & 3035 ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | 3036 MachO::VM_PROT_EXECUTE)) != 0) 3037 outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; 3038 else { 3039 if (initprot & MachO::VM_PROT_READ) 3040 outs() << " initprot r"; 3041 else 3042 outs() << " initprot -"; 3043 if (initprot & MachO::VM_PROT_WRITE) 3044 outs() << "w"; 3045 else 3046 outs() << "-"; 3047 if (initprot & MachO::VM_PROT_EXECUTE) 3048 outs() << "x\n"; 3049 else 3050 outs() << "-\n"; 3051 } 3052 } else { 3053 outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n"; 3054 outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n"; 3055 } 3056 outs() << " nsects " << nsects << "\n"; 3057 if (verbose) { 3058 outs() << " flags"; 3059 if (flags == 0) 3060 outs() << " (none)\n"; 3061 else { 3062 if (flags & MachO::SG_HIGHVM) { 3063 outs() << " HIGHVM"; 3064 flags &= ~MachO::SG_HIGHVM; 3065 } 3066 if (flags & MachO::SG_FVMLIB) { 3067 outs() << " FVMLIB"; 3068 flags &= ~MachO::SG_FVMLIB; 3069 } 3070 if (flags & MachO::SG_NORELOC) { 3071 outs() << " NORELOC"; 3072 flags &= ~MachO::SG_NORELOC; 3073 } 3074 if (flags & MachO::SG_PROTECTED_VERSION_1) { 3075 outs() << " PROTECTED_VERSION_1"; 3076 flags &= ~MachO::SG_PROTECTED_VERSION_1; 3077 } 3078 if (flags) 3079 outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n"; 3080 else 3081 outs() << "\n"; 3082 } 3083 } else { 3084 outs() << " flags " << format("0x%" PRIx32, flags) << "\n"; 3085 } 3086 } 3087 3088 static void PrintSection(const char *sectname, const char *segname, 3089 uint64_t addr, uint64_t size, uint32_t offset, 3090 uint32_t align, uint32_t reloff, uint32_t nreloc, 3091 uint32_t flags, uint32_t reserved1, uint32_t reserved2, 3092 uint32_t cmd, const char *sg_segname, 3093 uint32_t filetype, uint32_t object_size, 3094 bool verbose) { 3095 outs() << "Section\n"; 3096 outs() << " sectname " << format("%.16s\n", sectname); 3097 outs() << " segname " << format("%.16s", segname); 3098 if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0) 3099 outs() << " (does not match segment)\n"; 3100 else 3101 outs() << "\n"; 3102 if (cmd == MachO::LC_SEGMENT_64) { 3103 outs() << " addr " << format("0x%016" PRIx64, addr) << "\n"; 3104 outs() << " size " << format("0x%016" PRIx64, size); 3105 } else { 3106 outs() << " addr " << format("0x%08" PRIx32, addr) << "\n"; 3107 outs() << " size " << format("0x%08" PRIx32, size); 3108 } 3109 if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size) 3110 outs() << " (past end of file)\n"; 3111 else 3112 outs() << "\n"; 3113 outs() << " offset " << offset; 3114 if (offset > object_size) 3115 outs() << " (past end of file)\n"; 3116 else 3117 outs() << "\n"; 3118 uint32_t align_shifted = 1 << align; 3119 outs() << " align 2^" << align << " (" << align_shifted << ")\n"; 3120 outs() << " reloff " << reloff; 3121 if (reloff > object_size) 3122 outs() << " (past end of file)\n"; 3123 else 3124 outs() << "\n"; 3125 outs() << " nreloc " << nreloc; 3126 if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size) 3127 outs() << " (past end of file)\n"; 3128 else 3129 outs() << "\n"; 3130 uint32_t section_type = flags & MachO::SECTION_TYPE; 3131 if (verbose) { 3132 outs() << " type"; 3133 if (section_type == MachO::S_REGULAR) 3134 outs() << " S_REGULAR\n"; 3135 else if (section_type == MachO::S_ZEROFILL) 3136 outs() << " S_ZEROFILL\n"; 3137 else if (section_type == MachO::S_CSTRING_LITERALS) 3138 outs() << " S_CSTRING_LITERALS\n"; 3139 else if (section_type == MachO::S_4BYTE_LITERALS) 3140 outs() << " S_4BYTE_LITERALS\n"; 3141 else if (section_type == MachO::S_8BYTE_LITERALS) 3142 outs() << " S_8BYTE_LITERALS\n"; 3143 else if (section_type == MachO::S_16BYTE_LITERALS) 3144 outs() << " S_16BYTE_LITERALS\n"; 3145 else if (section_type == MachO::S_LITERAL_POINTERS) 3146 outs() << " S_LITERAL_POINTERS\n"; 3147 else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS) 3148 outs() << " S_NON_LAZY_SYMBOL_POINTERS\n"; 3149 else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS) 3150 outs() << " S_LAZY_SYMBOL_POINTERS\n"; 3151 else if (section_type == MachO::S_SYMBOL_STUBS) 3152 outs() << " S_SYMBOL_STUBS\n"; 3153 else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS) 3154 outs() << " S_MOD_INIT_FUNC_POINTERS\n"; 3155 else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS) 3156 outs() << " S_MOD_TERM_FUNC_POINTERS\n"; 3157 else if (section_type == MachO::S_COALESCED) 3158 outs() << " S_COALESCED\n"; 3159 else if (section_type == MachO::S_INTERPOSING) 3160 outs() << " S_INTERPOSING\n"; 3161 else if (section_type == MachO::S_DTRACE_DOF) 3162 outs() << " S_DTRACE_DOF\n"; 3163 else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS) 3164 outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n"; 3165 else if (section_type == MachO::S_THREAD_LOCAL_REGULAR) 3166 outs() << " S_THREAD_LOCAL_REGULAR\n"; 3167 else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL) 3168 outs() << " S_THREAD_LOCAL_ZEROFILL\n"; 3169 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES) 3170 outs() << " S_THREAD_LOCAL_VARIABLES\n"; 3171 else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 3172 outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n"; 3173 else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS) 3174 outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n"; 3175 else 3176 outs() << format("0x%08" PRIx32, section_type) << "\n"; 3177 outs() << "attributes"; 3178 uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES; 3179 if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS) 3180 outs() << " PURE_INSTRUCTIONS"; 3181 if (section_attributes & MachO::S_ATTR_NO_TOC) 3182 outs() << " NO_TOC"; 3183 if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS) 3184 outs() << " STRIP_STATIC_SYMS"; 3185 if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP) 3186 outs() << " NO_DEAD_STRIP"; 3187 if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT) 3188 outs() << " LIVE_SUPPORT"; 3189 if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE) 3190 outs() << " SELF_MODIFYING_CODE"; 3191 if (section_attributes & MachO::S_ATTR_DEBUG) 3192 outs() << " DEBUG"; 3193 if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS) 3194 outs() << " SOME_INSTRUCTIONS"; 3195 if (section_attributes & MachO::S_ATTR_EXT_RELOC) 3196 outs() << " EXT_RELOC"; 3197 if (section_attributes & MachO::S_ATTR_LOC_RELOC) 3198 outs() << " LOC_RELOC"; 3199 if (section_attributes == 0) 3200 outs() << " (none)"; 3201 outs() << "\n"; 3202 } else 3203 outs() << " flags " << format("0x%08" PRIx32, flags) << "\n"; 3204 outs() << " reserved1 " << reserved1; 3205 if (section_type == MachO::S_SYMBOL_STUBS || 3206 section_type == MachO::S_LAZY_SYMBOL_POINTERS || 3207 section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS || 3208 section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS || 3209 section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS) 3210 outs() << " (index into indirect symbol table)\n"; 3211 else 3212 outs() << "\n"; 3213 outs() << " reserved2 " << reserved2; 3214 if (section_type == MachO::S_SYMBOL_STUBS) 3215 outs() << " (size of stubs)\n"; 3216 else 3217 outs() << "\n"; 3218 } 3219 3220 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit, 3221 uint32_t object_size) { 3222 outs() << " cmd LC_SYMTAB\n"; 3223 outs() << " cmdsize " << st.cmdsize; 3224 if (st.cmdsize != sizeof(struct MachO::symtab_command)) 3225 outs() << " Incorrect size\n"; 3226 else 3227 outs() << "\n"; 3228 outs() << " symoff " << st.symoff; 3229 if (st.symoff > object_size) 3230 outs() << " (past end of file)\n"; 3231 else 3232 outs() << "\n"; 3233 outs() << " nsyms " << st.nsyms; 3234 uint64_t big_size; 3235 if (Is64Bit) { 3236 big_size = st.nsyms; 3237 big_size *= sizeof(struct MachO::nlist_64); 3238 big_size += st.symoff; 3239 if (big_size > object_size) 3240 outs() << " (past end of file)\n"; 3241 else 3242 outs() << "\n"; 3243 } else { 3244 big_size = st.nsyms; 3245 big_size *= sizeof(struct MachO::nlist); 3246 big_size += st.symoff; 3247 if (big_size > object_size) 3248 outs() << " (past end of file)\n"; 3249 else 3250 outs() << "\n"; 3251 } 3252 outs() << " stroff " << st.stroff; 3253 if (st.stroff > object_size) 3254 outs() << " (past end of file)\n"; 3255 else 3256 outs() << "\n"; 3257 outs() << " strsize " << st.strsize; 3258 big_size = st.stroff; 3259 big_size += st.strsize; 3260 if (big_size > object_size) 3261 outs() << " (past end of file)\n"; 3262 else 3263 outs() << "\n"; 3264 } 3265 3266 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst, 3267 uint32_t nsyms, uint32_t object_size, 3268 bool Is64Bit) { 3269 outs() << " cmd LC_DYSYMTAB\n"; 3270 outs() << " cmdsize " << dyst.cmdsize; 3271 if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command)) 3272 outs() << " Incorrect size\n"; 3273 else 3274 outs() << "\n"; 3275 outs() << " ilocalsym " << dyst.ilocalsym; 3276 if (dyst.ilocalsym > nsyms) 3277 outs() << " (greater than the number of symbols)\n"; 3278 else 3279 outs() << "\n"; 3280 outs() << " nlocalsym " << dyst.nlocalsym; 3281 uint64_t big_size; 3282 big_size = dyst.ilocalsym; 3283 big_size += dyst.nlocalsym; 3284 if (big_size > nsyms) 3285 outs() << " (past the end of the symbol table)\n"; 3286 else 3287 outs() << "\n"; 3288 outs() << " iextdefsym " << dyst.iextdefsym; 3289 if (dyst.iextdefsym > nsyms) 3290 outs() << " (greater than the number of symbols)\n"; 3291 else 3292 outs() << "\n"; 3293 outs() << " nextdefsym " << dyst.nextdefsym; 3294 big_size = dyst.iextdefsym; 3295 big_size += dyst.nextdefsym; 3296 if (big_size > nsyms) 3297 outs() << " (past the end of the symbol table)\n"; 3298 else 3299 outs() << "\n"; 3300 outs() << " iundefsym " << dyst.iundefsym; 3301 if (dyst.iundefsym > nsyms) 3302 outs() << " (greater than the number of symbols)\n"; 3303 else 3304 outs() << "\n"; 3305 outs() << " nundefsym " << dyst.nundefsym; 3306 big_size = dyst.iundefsym; 3307 big_size += dyst.nundefsym; 3308 if (big_size > nsyms) 3309 outs() << " (past the end of the symbol table)\n"; 3310 else 3311 outs() << "\n"; 3312 outs() << " tocoff " << dyst.tocoff; 3313 if (dyst.tocoff > object_size) 3314 outs() << " (past end of file)\n"; 3315 else 3316 outs() << "\n"; 3317 outs() << " ntoc " << dyst.ntoc; 3318 big_size = dyst.ntoc; 3319 big_size *= sizeof(struct MachO::dylib_table_of_contents); 3320 big_size += dyst.tocoff; 3321 if (big_size > object_size) 3322 outs() << " (past end of file)\n"; 3323 else 3324 outs() << "\n"; 3325 outs() << " modtaboff " << dyst.modtaboff; 3326 if (dyst.modtaboff > object_size) 3327 outs() << " (past end of file)\n"; 3328 else 3329 outs() << "\n"; 3330 outs() << " nmodtab " << dyst.nmodtab; 3331 uint64_t modtabend; 3332 if (Is64Bit) { 3333 modtabend = dyst.nmodtab; 3334 modtabend *= sizeof(struct MachO::dylib_module_64); 3335 modtabend += dyst.modtaboff; 3336 } else { 3337 modtabend = dyst.nmodtab; 3338 modtabend *= sizeof(struct MachO::dylib_module); 3339 modtabend += dyst.modtaboff; 3340 } 3341 if (modtabend > object_size) 3342 outs() << " (past end of file)\n"; 3343 else 3344 outs() << "\n"; 3345 outs() << " extrefsymoff " << dyst.extrefsymoff; 3346 if (dyst.extrefsymoff > object_size) 3347 outs() << " (past end of file)\n"; 3348 else 3349 outs() << "\n"; 3350 outs() << " nextrefsyms " << dyst.nextrefsyms; 3351 big_size = dyst.nextrefsyms; 3352 big_size *= sizeof(struct MachO::dylib_reference); 3353 big_size += dyst.extrefsymoff; 3354 if (big_size > object_size) 3355 outs() << " (past end of file)\n"; 3356 else 3357 outs() << "\n"; 3358 outs() << " indirectsymoff " << dyst.indirectsymoff; 3359 if (dyst.indirectsymoff > object_size) 3360 outs() << " (past end of file)\n"; 3361 else 3362 outs() << "\n"; 3363 outs() << " nindirectsyms " << dyst.nindirectsyms; 3364 big_size = dyst.nindirectsyms; 3365 big_size *= sizeof(uint32_t); 3366 big_size += dyst.indirectsymoff; 3367 if (big_size > object_size) 3368 outs() << " (past end of file)\n"; 3369 else 3370 outs() << "\n"; 3371 outs() << " extreloff " << dyst.extreloff; 3372 if (dyst.extreloff > object_size) 3373 outs() << " (past end of file)\n"; 3374 else 3375 outs() << "\n"; 3376 outs() << " nextrel " << dyst.nextrel; 3377 big_size = dyst.nextrel; 3378 big_size *= sizeof(struct MachO::relocation_info); 3379 big_size += dyst.extreloff; 3380 if (big_size > object_size) 3381 outs() << " (past end of file)\n"; 3382 else 3383 outs() << "\n"; 3384 outs() << " locreloff " << dyst.locreloff; 3385 if (dyst.locreloff > object_size) 3386 outs() << " (past end of file)\n"; 3387 else 3388 outs() << "\n"; 3389 outs() << " nlocrel " << dyst.nlocrel; 3390 big_size = dyst.nlocrel; 3391 big_size *= sizeof(struct MachO::relocation_info); 3392 big_size += dyst.locreloff; 3393 if (big_size > object_size) 3394 outs() << " (past end of file)\n"; 3395 else 3396 outs() << "\n"; 3397 } 3398 3399 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc, 3400 uint32_t object_size) { 3401 if (dc.cmd == MachO::LC_DYLD_INFO) 3402 outs() << " cmd LC_DYLD_INFO\n"; 3403 else 3404 outs() << " cmd LC_DYLD_INFO_ONLY\n"; 3405 outs() << " cmdsize " << dc.cmdsize; 3406 if (dc.cmdsize != sizeof(struct MachO::dyld_info_command)) 3407 outs() << " Incorrect size\n"; 3408 else 3409 outs() << "\n"; 3410 outs() << " rebase_off " << dc.rebase_off; 3411 if (dc.rebase_off > object_size) 3412 outs() << " (past end of file)\n"; 3413 else 3414 outs() << "\n"; 3415 outs() << " rebase_size " << dc.rebase_size; 3416 uint64_t big_size; 3417 big_size = dc.rebase_off; 3418 big_size += dc.rebase_size; 3419 if (big_size > object_size) 3420 outs() << " (past end of file)\n"; 3421 else 3422 outs() << "\n"; 3423 outs() << " bind_off " << dc.bind_off; 3424 if (dc.bind_off > object_size) 3425 outs() << " (past end of file)\n"; 3426 else 3427 outs() << "\n"; 3428 outs() << " bind_size " << dc.bind_size; 3429 big_size = dc.bind_off; 3430 big_size += dc.bind_size; 3431 if (big_size > object_size) 3432 outs() << " (past end of file)\n"; 3433 else 3434 outs() << "\n"; 3435 outs() << " weak_bind_off " << dc.weak_bind_off; 3436 if (dc.weak_bind_off > object_size) 3437 outs() << " (past end of file)\n"; 3438 else 3439 outs() << "\n"; 3440 outs() << " weak_bind_size " << dc.weak_bind_size; 3441 big_size = dc.weak_bind_off; 3442 big_size += dc.weak_bind_size; 3443 if (big_size > object_size) 3444 outs() << " (past end of file)\n"; 3445 else 3446 outs() << "\n"; 3447 outs() << " lazy_bind_off " << dc.lazy_bind_off; 3448 if (dc.lazy_bind_off > object_size) 3449 outs() << " (past end of file)\n"; 3450 else 3451 outs() << "\n"; 3452 outs() << " lazy_bind_size " << dc.lazy_bind_size; 3453 big_size = dc.lazy_bind_off; 3454 big_size += dc.lazy_bind_size; 3455 if (big_size > object_size) 3456 outs() << " (past end of file)\n"; 3457 else 3458 outs() << "\n"; 3459 outs() << " export_off " << dc.export_off; 3460 if (dc.export_off > object_size) 3461 outs() << " (past end of file)\n"; 3462 else 3463 outs() << "\n"; 3464 outs() << " export_size " << dc.export_size; 3465 big_size = dc.export_off; 3466 big_size += dc.export_size; 3467 if (big_size > object_size) 3468 outs() << " (past end of file)\n"; 3469 else 3470 outs() << "\n"; 3471 } 3472 3473 static void PrintDyldLoadCommand(MachO::dylinker_command dyld, 3474 const char *Ptr) { 3475 if (dyld.cmd == MachO::LC_ID_DYLINKER) 3476 outs() << " cmd LC_ID_DYLINKER\n"; 3477 else if (dyld.cmd == MachO::LC_LOAD_DYLINKER) 3478 outs() << " cmd LC_LOAD_DYLINKER\n"; 3479 else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT) 3480 outs() << " cmd LC_DYLD_ENVIRONMENT\n"; 3481 else 3482 outs() << " cmd ?(" << dyld.cmd << ")\n"; 3483 outs() << " cmdsize " << dyld.cmdsize; 3484 if (dyld.cmdsize < sizeof(struct MachO::dylinker_command)) 3485 outs() << " Incorrect size\n"; 3486 else 3487 outs() << "\n"; 3488 if (dyld.name >= dyld.cmdsize) 3489 outs() << " name ?(bad offset " << dyld.name << ")\n"; 3490 else { 3491 const char *P = (const char *)(Ptr) + dyld.name; 3492 outs() << " name " << P << " (offset " << dyld.name << ")\n"; 3493 } 3494 } 3495 3496 static void PrintUuidLoadCommand(MachO::uuid_command uuid) { 3497 outs() << " cmd LC_UUID\n"; 3498 outs() << " cmdsize " << uuid.cmdsize; 3499 if (uuid.cmdsize != sizeof(struct MachO::uuid_command)) 3500 outs() << " Incorrect size\n"; 3501 else 3502 outs() << "\n"; 3503 outs() << " uuid "; 3504 outs() << format("%02" PRIX32, uuid.uuid[0]); 3505 outs() << format("%02" PRIX32, uuid.uuid[1]); 3506 outs() << format("%02" PRIX32, uuid.uuid[2]); 3507 outs() << format("%02" PRIX32, uuid.uuid[3]); 3508 outs() << "-"; 3509 outs() << format("%02" PRIX32, uuid.uuid[4]); 3510 outs() << format("%02" PRIX32, uuid.uuid[5]); 3511 outs() << "-"; 3512 outs() << format("%02" PRIX32, uuid.uuid[6]); 3513 outs() << format("%02" PRIX32, uuid.uuid[7]); 3514 outs() << "-"; 3515 outs() << format("%02" PRIX32, uuid.uuid[8]); 3516 outs() << format("%02" PRIX32, uuid.uuid[9]); 3517 outs() << "-"; 3518 outs() << format("%02" PRIX32, uuid.uuid[10]); 3519 outs() << format("%02" PRIX32, uuid.uuid[11]); 3520 outs() << format("%02" PRIX32, uuid.uuid[12]); 3521 outs() << format("%02" PRIX32, uuid.uuid[13]); 3522 outs() << format("%02" PRIX32, uuid.uuid[14]); 3523 outs() << format("%02" PRIX32, uuid.uuid[15]); 3524 outs() << "\n"; 3525 } 3526 3527 static void PrintRpathLoadCommand(MachO::rpath_command rpath, 3528 const char *Ptr) { 3529 outs() << " cmd LC_RPATH\n"; 3530 outs() << " cmdsize " << rpath.cmdsize; 3531 if (rpath.cmdsize < sizeof(struct MachO::rpath_command)) 3532 outs() << " Incorrect size\n"; 3533 else 3534 outs() << "\n"; 3535 if (rpath.path >= rpath.cmdsize) 3536 outs() << " path ?(bad offset " << rpath.path << ")\n"; 3537 else { 3538 const char *P = (const char *)(Ptr) + rpath.path; 3539 outs() << " path " << P << " (offset " << rpath.path << ")\n"; 3540 } 3541 } 3542 3543 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) { 3544 if (vd.cmd == MachO::LC_VERSION_MIN_MACOSX) 3545 outs() << " cmd LC_VERSION_MIN_MACOSX\n"; 3546 else if (vd.cmd == MachO::LC_VERSION_MIN_IPHONEOS) 3547 outs() << " cmd LC_VERSION_MIN_IPHONEOS\n"; 3548 else 3549 outs() << " cmd " << vd.cmd << " (?)\n"; 3550 outs() << " cmdsize " << vd.cmdsize; 3551 if (vd.cmdsize != sizeof(struct MachO::version_min_command)) 3552 outs() << " Incorrect size\n"; 3553 else 3554 outs() << "\n"; 3555 outs() << " version " << ((vd.version >> 16) & 0xffff) << "." 3556 << ((vd.version >> 8) & 0xff); 3557 if ((vd.version & 0xff) != 0) 3558 outs() << "." << (vd.version & 0xff); 3559 outs() << "\n"; 3560 if (vd.sdk == 0) 3561 outs() << " sdk n/a\n"; 3562 else { 3563 outs() << " sdk " << ((vd.sdk >> 16) & 0xffff) << "." 3564 << ((vd.sdk >> 8) & 0xff); 3565 } 3566 if ((vd.sdk & 0xff) != 0) 3567 outs() << "." << (vd.sdk & 0xff); 3568 outs() << "\n"; 3569 } 3570 3571 static void PrintSourceVersionCommand(MachO::source_version_command sd) { 3572 outs() << " cmd LC_SOURCE_VERSION\n"; 3573 outs() << " cmdsize " << sd.cmdsize; 3574 if (sd.cmdsize != sizeof(struct MachO::source_version_command)) 3575 outs() << " Incorrect size\n"; 3576 else 3577 outs() << "\n"; 3578 uint64_t a = (sd.version >> 40) & 0xffffff; 3579 uint64_t b = (sd.version >> 30) & 0x3ff; 3580 uint64_t c = (sd.version >> 20) & 0x3ff; 3581 uint64_t d = (sd.version >> 10) & 0x3ff; 3582 uint64_t e = sd.version & 0x3ff; 3583 outs() << " version " << a << "." << b; 3584 if (e != 0) 3585 outs() << "." << c << "." << d << "." << e; 3586 else if (d != 0) 3587 outs() << "." << c << "." << d; 3588 else if (c != 0) 3589 outs() << "." << c; 3590 outs() << "\n"; 3591 } 3592 3593 static void PrintEntryPointCommand(MachO::entry_point_command ep) { 3594 outs() << " cmd LC_MAIN\n"; 3595 outs() << " cmdsize " << ep.cmdsize; 3596 if (ep.cmdsize != sizeof(struct MachO::entry_point_command)) 3597 outs() << " Incorrect size\n"; 3598 else 3599 outs() << "\n"; 3600 outs() << " entryoff " << ep.entryoff << "\n"; 3601 outs() << " stacksize " << ep.stacksize << "\n"; 3602 } 3603 3604 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) { 3605 if (dl.cmd == MachO::LC_ID_DYLIB) 3606 outs() << " cmd LC_ID_DYLIB\n"; 3607 else if (dl.cmd == MachO::LC_LOAD_DYLIB) 3608 outs() << " cmd LC_LOAD_DYLIB\n"; 3609 else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB) 3610 outs() << " cmd LC_LOAD_WEAK_DYLIB\n"; 3611 else if (dl.cmd == MachO::LC_REEXPORT_DYLIB) 3612 outs() << " cmd LC_REEXPORT_DYLIB\n"; 3613 else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB) 3614 outs() << " cmd LC_LAZY_LOAD_DYLIB\n"; 3615 else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB) 3616 outs() << " cmd LC_LOAD_UPWARD_DYLIB\n"; 3617 else 3618 outs() << " cmd " << dl.cmd << " (unknown)\n"; 3619 outs() << " cmdsize " << dl.cmdsize; 3620 if (dl.cmdsize < sizeof(struct MachO::dylib_command)) 3621 outs() << " Incorrect size\n"; 3622 else 3623 outs() << "\n"; 3624 if (dl.dylib.name < dl.cmdsize) { 3625 const char *P = (const char *)(Ptr) + dl.dylib.name; 3626 outs() << " name " << P << " (offset " << dl.dylib.name << ")\n"; 3627 } else { 3628 outs() << " name ?(bad offset " << dl.dylib.name << ")\n"; 3629 } 3630 outs() << " time stamp " << dl.dylib.timestamp << " "; 3631 time_t t = dl.dylib.timestamp; 3632 outs() << ctime(&t); 3633 outs() << " current version "; 3634 if (dl.dylib.current_version == 0xffffffff) 3635 outs() << "n/a\n"; 3636 else 3637 outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "." 3638 << ((dl.dylib.current_version >> 8) & 0xff) << "." 3639 << (dl.dylib.current_version & 0xff) << "\n"; 3640 outs() << "compatibility version "; 3641 if (dl.dylib.compatibility_version == 0xffffffff) 3642 outs() << "n/a\n"; 3643 else 3644 outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "." 3645 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "." 3646 << (dl.dylib.compatibility_version & 0xff) << "\n"; 3647 } 3648 3649 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld, 3650 uint32_t object_size) { 3651 if (ld.cmd == MachO::LC_CODE_SIGNATURE) 3652 outs() << " cmd LC_FUNCTION_STARTS\n"; 3653 else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO) 3654 outs() << " cmd LC_SEGMENT_SPLIT_INFO\n"; 3655 else if (ld.cmd == MachO::LC_FUNCTION_STARTS) 3656 outs() << " cmd LC_FUNCTION_STARTS\n"; 3657 else if (ld.cmd == MachO::LC_DATA_IN_CODE) 3658 outs() << " cmd LC_DATA_IN_CODE\n"; 3659 else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) 3660 outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n"; 3661 else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) 3662 outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n"; 3663 else 3664 outs() << " cmd " << ld.cmd << " (?)\n"; 3665 outs() << " cmdsize " << ld.cmdsize; 3666 if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command)) 3667 outs() << " Incorrect size\n"; 3668 else 3669 outs() << "\n"; 3670 outs() << " dataoff " << ld.dataoff; 3671 if (ld.dataoff > object_size) 3672 outs() << " (past end of file)\n"; 3673 else 3674 outs() << "\n"; 3675 outs() << " datasize " << ld.datasize; 3676 uint64_t big_size = ld.dataoff; 3677 big_size += ld.datasize; 3678 if (big_size > object_size) 3679 outs() << " (past end of file)\n"; 3680 else 3681 outs() << "\n"; 3682 } 3683 3684 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t ncmds, 3685 uint32_t filetype, uint32_t cputype, 3686 bool verbose) { 3687 StringRef Buf = Obj->getData(); 3688 MachOObjectFile::LoadCommandInfo Command = Obj->getFirstLoadCommandInfo(); 3689 for (unsigned i = 0;; ++i) { 3690 outs() << "Load command " << i << "\n"; 3691 if (Command.C.cmd == MachO::LC_SEGMENT) { 3692 MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command); 3693 const char *sg_segname = SLC.segname; 3694 PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr, 3695 SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot, 3696 SLC.initprot, SLC.nsects, SLC.flags, Buf.size(), 3697 verbose); 3698 for (unsigned j = 0; j < SLC.nsects; j++) { 3699 MachO::section_64 S = Obj->getSection64(Command, j); 3700 PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align, 3701 S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2, 3702 SLC.cmd, sg_segname, filetype, Buf.size(), verbose); 3703 } 3704 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 3705 MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command); 3706 const char *sg_segname = SLC_64.segname; 3707 PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname, 3708 SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff, 3709 SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot, 3710 SLC_64.nsects, SLC_64.flags, Buf.size(), verbose); 3711 for (unsigned j = 0; j < SLC_64.nsects; j++) { 3712 MachO::section_64 S_64 = Obj->getSection64(Command, j); 3713 PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size, 3714 S_64.offset, S_64.align, S_64.reloff, S_64.nreloc, 3715 S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd, 3716 sg_segname, filetype, Buf.size(), verbose); 3717 } 3718 } else if (Command.C.cmd == MachO::LC_SYMTAB) { 3719 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 3720 PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size()); 3721 } else if (Command.C.cmd == MachO::LC_DYSYMTAB) { 3722 MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand(); 3723 MachO::symtab_command Symtab = Obj->getSymtabLoadCommand(); 3724 PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(), 3725 Obj->is64Bit()); 3726 } else if (Command.C.cmd == MachO::LC_DYLD_INFO || 3727 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 3728 MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command); 3729 PrintDyldInfoLoadCommand(DyldInfo, Buf.size()); 3730 } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER || 3731 Command.C.cmd == MachO::LC_ID_DYLINKER || 3732 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 3733 MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command); 3734 PrintDyldLoadCommand(Dyld, Command.Ptr); 3735 } else if (Command.C.cmd == MachO::LC_UUID) { 3736 MachO::uuid_command Uuid = Obj->getUuidCommand(Command); 3737 PrintUuidLoadCommand(Uuid); 3738 } else if (Command.C.cmd == MachO::LC_RPATH) { 3739 MachO::rpath_command Rpath = Obj->getRpathCommand(Command); 3740 PrintRpathLoadCommand(Rpath, Command.Ptr); 3741 } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX) { 3742 MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command); 3743 PrintVersionMinLoadCommand(Vd); 3744 } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) { 3745 MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command); 3746 PrintSourceVersionCommand(Sd); 3747 } else if (Command.C.cmd == MachO::LC_MAIN) { 3748 MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command); 3749 PrintEntryPointCommand(Ep); 3750 } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 3751 Command.C.cmd == MachO::LC_ID_DYLIB || 3752 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 3753 Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 3754 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 3755 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 3756 MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 3757 PrintDylibCommand(Dl, Command.Ptr); 3758 } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE || 3759 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO || 3760 Command.C.cmd == MachO::LC_FUNCTION_STARTS || 3761 Command.C.cmd == MachO::LC_DATA_IN_CODE || 3762 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS || 3763 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 3764 MachO::linkedit_data_command Ld = 3765 Obj->getLinkeditDataLoadCommand(Command); 3766 PrintLinkEditDataCommand(Ld, Buf.size()); 3767 } else { 3768 outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd) 3769 << ")\n"; 3770 outs() << " cmdsize " << Command.C.cmdsize << "\n"; 3771 // TODO: get and print the raw bytes of the load command. 3772 } 3773 // TODO: print all the other kinds of load commands. 3774 if (i == ncmds - 1) 3775 break; 3776 else 3777 Command = Obj->getNextLoadCommandInfo(Command); 3778 } 3779 } 3780 3781 static void getAndPrintMachHeader(const MachOObjectFile *Obj, uint32_t &ncmds, 3782 uint32_t &filetype, uint32_t &cputype, 3783 bool verbose) { 3784 if (Obj->is64Bit()) { 3785 MachO::mach_header_64 H_64; 3786 H_64 = Obj->getHeader64(); 3787 PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype, 3788 H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose); 3789 ncmds = H_64.ncmds; 3790 filetype = H_64.filetype; 3791 cputype = H_64.cputype; 3792 } else { 3793 MachO::mach_header H; 3794 H = Obj->getHeader(); 3795 PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds, 3796 H.sizeofcmds, H.flags, verbose); 3797 ncmds = H.ncmds; 3798 filetype = H.filetype; 3799 cputype = H.cputype; 3800 } 3801 } 3802 3803 void llvm::printMachOFileHeader(const object::ObjectFile *Obj) { 3804 const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj); 3805 uint32_t ncmds = 0; 3806 uint32_t filetype = 0; 3807 uint32_t cputype = 0; 3808 getAndPrintMachHeader(file, ncmds, filetype, cputype, true); 3809 PrintLoadCommands(file, ncmds, filetype, cputype, true); 3810 } 3811 3812 //===----------------------------------------------------------------------===// 3813 // export trie dumping 3814 //===----------------------------------------------------------------------===// 3815 3816 void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) { 3817 for (const llvm::object::ExportEntry &Entry : Obj->exports()) { 3818 uint64_t Flags = Entry.flags(); 3819 bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 3820 bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 3821 bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 3822 MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); 3823 bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 3824 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 3825 bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 3826 if (ReExport) 3827 outs() << "[re-export] "; 3828 else 3829 outs() << format("0x%08llX ", 3830 Entry.address()); // FIXME:add in base address 3831 outs() << Entry.name(); 3832 if (WeakDef || ThreadLocal || Resolver || Abs) { 3833 bool NeedsComma = false; 3834 outs() << " ["; 3835 if (WeakDef) { 3836 outs() << "weak_def"; 3837 NeedsComma = true; 3838 } 3839 if (ThreadLocal) { 3840 if (NeedsComma) 3841 outs() << ", "; 3842 outs() << "per-thread"; 3843 NeedsComma = true; 3844 } 3845 if (Abs) { 3846 if (NeedsComma) 3847 outs() << ", "; 3848 outs() << "absolute"; 3849 NeedsComma = true; 3850 } 3851 if (Resolver) { 3852 if (NeedsComma) 3853 outs() << ", "; 3854 outs() << format("resolver=0x%08llX", Entry.other()); 3855 NeedsComma = true; 3856 } 3857 outs() << "]"; 3858 } 3859 if (ReExport) { 3860 StringRef DylibName = "unknown"; 3861 int Ordinal = Entry.other() - 1; 3862 Obj->getLibraryShortNameByIndex(Ordinal, DylibName); 3863 if (Entry.otherName().empty()) 3864 outs() << " (from " << DylibName << ")"; 3865 else 3866 outs() << " (" << Entry.otherName() << " from " << DylibName << ")"; 3867 } 3868 outs() << "\n"; 3869 } 3870 } 3871 3872 //===----------------------------------------------------------------------===// 3873 // rebase table dumping 3874 //===----------------------------------------------------------------------===// 3875 3876 namespace { 3877 class SegInfo { 3878 public: 3879 SegInfo(const object::MachOObjectFile *Obj); 3880 3881 StringRef segmentName(uint32_t SegIndex); 3882 StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset); 3883 uint64_t address(uint32_t SegIndex, uint64_t SegOffset); 3884 3885 private: 3886 struct SectionInfo { 3887 uint64_t Address; 3888 uint64_t Size; 3889 StringRef SectionName; 3890 StringRef SegmentName; 3891 uint64_t OffsetInSegment; 3892 uint64_t SegmentStartAddress; 3893 uint32_t SegmentIndex; 3894 }; 3895 const SectionInfo &findSection(uint32_t SegIndex, uint64_t SegOffset); 3896 SmallVector<SectionInfo, 32> Sections; 3897 }; 3898 } 3899 3900 SegInfo::SegInfo(const object::MachOObjectFile *Obj) { 3901 // Build table of sections so segIndex/offset pairs can be translated. 3902 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0; 3903 StringRef CurSegName; 3904 uint64_t CurSegAddress; 3905 for (const SectionRef &Section : Obj->sections()) { 3906 SectionInfo Info; 3907 if (error(Section.getName(Info.SectionName))) 3908 return; 3909 Info.Address = Section.getAddress(); 3910 Info.Size = Section.getSize(); 3911 Info.SegmentName = 3912 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl()); 3913 if (!Info.SegmentName.equals(CurSegName)) { 3914 ++CurSegIndex; 3915 CurSegName = Info.SegmentName; 3916 CurSegAddress = Info.Address; 3917 } 3918 Info.SegmentIndex = CurSegIndex - 1; 3919 Info.OffsetInSegment = Info.Address - CurSegAddress; 3920 Info.SegmentStartAddress = CurSegAddress; 3921 Sections.push_back(Info); 3922 } 3923 } 3924 3925 StringRef SegInfo::segmentName(uint32_t SegIndex) { 3926 for (const SectionInfo &SI : Sections) { 3927 if (SI.SegmentIndex == SegIndex) 3928 return SI.SegmentName; 3929 } 3930 llvm_unreachable("invalid segIndex"); 3931 } 3932 3933 const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex, 3934 uint64_t OffsetInSeg) { 3935 for (const SectionInfo &SI : Sections) { 3936 if (SI.SegmentIndex != SegIndex) 3937 continue; 3938 if (SI.OffsetInSegment > OffsetInSeg) 3939 continue; 3940 if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size)) 3941 continue; 3942 return SI; 3943 } 3944 llvm_unreachable("segIndex and offset not in any section"); 3945 } 3946 3947 StringRef SegInfo::sectionName(uint32_t SegIndex, uint64_t OffsetInSeg) { 3948 return findSection(SegIndex, OffsetInSeg).SectionName; 3949 } 3950 3951 uint64_t SegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) { 3952 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg); 3953 return SI.SegmentStartAddress + OffsetInSeg; 3954 } 3955 3956 void llvm::printMachORebaseTable(const object::MachOObjectFile *Obj) { 3957 // Build table of sections so names can used in final output. 3958 SegInfo sectionTable(Obj); 3959 3960 outs() << "segment section address type\n"; 3961 for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) { 3962 uint32_t SegIndex = Entry.segmentIndex(); 3963 uint64_t OffsetInSeg = Entry.segmentOffset(); 3964 StringRef SegmentName = sectionTable.segmentName(SegIndex); 3965 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 3966 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 3967 3968 // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer 3969 outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n", 3970 SegmentName.str().c_str(), SectionName.str().c_str(), 3971 Address, Entry.typeName().str().c_str()); 3972 } 3973 } 3974 3975 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) { 3976 StringRef DylibName; 3977 switch (Ordinal) { 3978 case MachO::BIND_SPECIAL_DYLIB_SELF: 3979 return "this-image"; 3980 case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: 3981 return "main-executable"; 3982 case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP: 3983 return "flat-namespace"; 3984 default: 3985 if (Ordinal > 0) { 3986 std::error_code EC = 3987 Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName); 3988 if (EC) 3989 return "<<bad library ordinal>>"; 3990 return DylibName; 3991 } 3992 } 3993 return "<<unknown special ordinal>>"; 3994 } 3995 3996 //===----------------------------------------------------------------------===// 3997 // bind table dumping 3998 //===----------------------------------------------------------------------===// 3999 4000 void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) { 4001 // Build table of sections so names can used in final output. 4002 SegInfo sectionTable(Obj); 4003 4004 outs() << "segment section address type " 4005 "addend dylib symbol\n"; 4006 for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) { 4007 uint32_t SegIndex = Entry.segmentIndex(); 4008 uint64_t OffsetInSeg = Entry.segmentOffset(); 4009 StringRef SegmentName = sectionTable.segmentName(SegIndex); 4010 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 4011 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 4012 4013 // Table lines look like: 4014 // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard 4015 StringRef Attr; 4016 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT) 4017 Attr = " (weak_import)"; 4018 outs() << left_justify(SegmentName, 8) << " " 4019 << left_justify(SectionName, 18) << " " 4020 << format_hex(Address, 10, true) << " " 4021 << left_justify(Entry.typeName(), 8) << " " 4022 << format_decimal(Entry.addend(), 8) << " " 4023 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 4024 << Entry.symbolName() << Attr << "\n"; 4025 } 4026 } 4027 4028 //===----------------------------------------------------------------------===// 4029 // lazy bind table dumping 4030 //===----------------------------------------------------------------------===// 4031 4032 void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) { 4033 // Build table of sections so names can used in final output. 4034 SegInfo sectionTable(Obj); 4035 4036 outs() << "segment section address " 4037 "dylib symbol\n"; 4038 for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable()) { 4039 uint32_t SegIndex = Entry.segmentIndex(); 4040 uint64_t OffsetInSeg = Entry.segmentOffset(); 4041 StringRef SegmentName = sectionTable.segmentName(SegIndex); 4042 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 4043 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 4044 4045 // Table lines look like: 4046 // __DATA __got 0x00012010 libSystem ___stack_chk_guard 4047 outs() << left_justify(SegmentName, 8) << " " 4048 << left_justify(SectionName, 18) << " " 4049 << format_hex(Address, 10, true) << " " 4050 << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " " 4051 << Entry.symbolName() << "\n"; 4052 } 4053 } 4054 4055 //===----------------------------------------------------------------------===// 4056 // weak bind table dumping 4057 //===----------------------------------------------------------------------===// 4058 4059 void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) { 4060 // Build table of sections so names can used in final output. 4061 SegInfo sectionTable(Obj); 4062 4063 outs() << "segment section address " 4064 "type addend symbol\n"; 4065 for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable()) { 4066 // Strong symbols don't have a location to update. 4067 if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 4068 outs() << " strong " 4069 << Entry.symbolName() << "\n"; 4070 continue; 4071 } 4072 uint32_t SegIndex = Entry.segmentIndex(); 4073 uint64_t OffsetInSeg = Entry.segmentOffset(); 4074 StringRef SegmentName = sectionTable.segmentName(SegIndex); 4075 StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg); 4076 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 4077 4078 // Table lines look like: 4079 // __DATA __data 0x00001000 pointer 0 _foo 4080 outs() << left_justify(SegmentName, 8) << " " 4081 << left_justify(SectionName, 18) << " " 4082 << format_hex(Address, 10, true) << " " 4083 << left_justify(Entry.typeName(), 8) << " " 4084 << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName() 4085 << "\n"; 4086 } 4087 } 4088 4089 // get_dyld_bind_info_symbolname() is used for disassembly and passed an 4090 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind 4091 // information for that address. If the address is found its binding symbol 4092 // name is returned. If not nullptr is returned. 4093 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, 4094 struct DisassembleInfo *info) { 4095 if (info->bindtable == nullptr) { 4096 info->bindtable = new (BindTable); 4097 SegInfo sectionTable(info->O); 4098 for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) { 4099 uint32_t SegIndex = Entry.segmentIndex(); 4100 uint64_t OffsetInSeg = Entry.segmentOffset(); 4101 uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); 4102 const char *SymbolName = nullptr; 4103 StringRef name = Entry.symbolName(); 4104 if (!name.empty()) 4105 SymbolName = name.data(); 4106 info->bindtable->push_back(std::make_pair(Address, SymbolName)); 4107 } 4108 } 4109 for (bind_table_iterator BI = info->bindtable->begin(), 4110 BE = info->bindtable->end(); 4111 BI != BE; ++BI) { 4112 uint64_t Address = BI->first; 4113 if (ReferenceValue == Address) { 4114 const char *SymbolName = BI->second; 4115 return SymbolName; 4116 } 4117 } 4118 return nullptr; 4119 } 4120