10b57cec5SDimitry Andric //===- MachODumper.cpp - Object file dumping utility for llvm -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the MachO-specific dumper for llvm-readobj. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "ObjDumper.h" 140b57cec5SDimitry Andric #include "StackMapPrinter.h" 150b57cec5SDimitry Andric #include "llvm-readobj.h" 160b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 170b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 180b57cec5SDimitry Andric #include "llvm/Object/MachO.h" 1904eeddc0SDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 200b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 210b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric using namespace llvm; 240b57cec5SDimitry Andric using namespace object; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric namespace { 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric class MachODumper : public ObjDumper { 290b57cec5SDimitry Andric public: 300b57cec5SDimitry Andric MachODumper(const MachOObjectFile *Obj, ScopedPrinter &Writer) 31e8d8bef9SDimitry Andric : ObjDumper(Writer, Obj->getFileName()), Obj(Obj) {} 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric void printFileHeaders() override; 340b57cec5SDimitry Andric void printSectionHeaders() override; 350b57cec5SDimitry Andric void printRelocations() override; 360b57cec5SDimitry Andric void printUnwindInfo() override; 370b57cec5SDimitry Andric void printStackMap() const override; 3804eeddc0SDimitry Andric void printCGProfile() override; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric void printNeededLibraries() override; 410b57cec5SDimitry Andric 4281ad6265SDimitry Andric bool canCompareSymbols() const override { return true; } 4381ad6265SDimitry Andric bool compareSymbolsByName(object::SymbolRef LHS, 4481ad6265SDimitry Andric object::SymbolRef RHS) const override; 4581ad6265SDimitry Andric bool compareSymbolsByType(object::SymbolRef LHS, 4681ad6265SDimitry Andric object::SymbolRef RHS) const override; 470b57cec5SDimitry Andric // MachO-specific. 480b57cec5SDimitry Andric void printMachODataInCode() override; 490b57cec5SDimitry Andric void printMachOVersionMin() override; 500b57cec5SDimitry Andric void printMachODysymtab() override; 510b57cec5SDimitry Andric void printMachOSegment() override; 520b57cec5SDimitry Andric void printMachOIndirectSymbols() override; 530b57cec5SDimitry Andric void printMachOLinkerOptions () override; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric private: 560b57cec5SDimitry Andric template<class MachHeader> 570b57cec5SDimitry Andric void printFileHeaders(const MachHeader &Header); 580b57cec5SDimitry Andric 5981ad6265SDimitry Andric StringRef getSymbolName(const SymbolRef &Symbol) const; 6081ad6265SDimitry Andric uint8_t getSymbolType(const SymbolRef &Symbol) const; 6104eeddc0SDimitry Andric 62*5f757f3fSDimitry Andric void printSymbols(bool ExtraSymInfo) override; 63bdd1243dSDimitry Andric void printSymbols(std::optional<SymbolComparator> SymComp) override; 640b57cec5SDimitry Andric void printDynamicSymbols() override; 65bdd1243dSDimitry Andric void printDynamicSymbols(std::optional<SymbolComparator> SymComp) override; 6681ad6265SDimitry Andric void printSymbol(const SymbolRef &Symbol, ScopedPrinter &W); 670b57cec5SDimitry Andric void printSymbol(const SymbolRef &Symbol); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric void printRelocation(const RelocationRef &Reloc); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric void printRelocation(const MachOObjectFile *Obj, const RelocationRef &Reloc); 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric void printSectionHeaders(const MachOObjectFile *Obj); 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric const MachOObjectFile *Obj; 760b57cec5SDimitry Andric }; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric } // namespace 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric namespace llvm { 820b57cec5SDimitry Andric 83e8d8bef9SDimitry Andric std::unique_ptr<ObjDumper> createMachODumper(const object::MachOObjectFile &Obj, 84e8d8bef9SDimitry Andric ScopedPrinter &Writer) { 85e8d8bef9SDimitry Andric return std::make_unique<MachODumper>(&Obj, Writer); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric } // namespace llvm 890b57cec5SDimitry Andric 90349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOMagics[] = { 910b57cec5SDimitry Andric { "Magic", MachO::MH_MAGIC }, 920b57cec5SDimitry Andric { "Cigam", MachO::MH_CIGAM }, 930b57cec5SDimitry Andric { "Magic64", MachO::MH_MAGIC_64 }, 940b57cec5SDimitry Andric { "Cigam64", MachO::MH_CIGAM_64 }, 950b57cec5SDimitry Andric { "FatMagic", MachO::FAT_MAGIC }, 960b57cec5SDimitry Andric { "FatCigam", MachO::FAT_CIGAM }, 970b57cec5SDimitry Andric }; 980b57cec5SDimitry Andric 99349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOHeaderFileTypes[] = { 1000b57cec5SDimitry Andric { "Relocatable", MachO::MH_OBJECT }, 1010b57cec5SDimitry Andric { "Executable", MachO::MH_EXECUTE }, 1020b57cec5SDimitry Andric { "FixedVMLibrary", MachO::MH_FVMLIB }, 1030b57cec5SDimitry Andric { "Core", MachO::MH_CORE }, 1040b57cec5SDimitry Andric { "PreloadedExecutable", MachO::MH_PRELOAD }, 1050b57cec5SDimitry Andric { "DynamicLibrary", MachO::MH_DYLIB }, 1060b57cec5SDimitry Andric { "DynamicLinker", MachO::MH_DYLINKER }, 1070b57cec5SDimitry Andric { "Bundle", MachO::MH_BUNDLE }, 1080b57cec5SDimitry Andric { "DynamicLibraryStub", MachO::MH_DYLIB_STUB }, 1090b57cec5SDimitry Andric { "DWARFSymbol", MachO::MH_DSYM }, 1100b57cec5SDimitry Andric { "KextBundle", MachO::MH_KEXT_BUNDLE }, 1110b57cec5SDimitry Andric }; 1120b57cec5SDimitry Andric 113349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOHeaderCpuTypes[] = { 1140b57cec5SDimitry Andric { "Any" , static_cast<uint32_t>(MachO::CPU_TYPE_ANY) }, 1150b57cec5SDimitry Andric { "X86" , MachO::CPU_TYPE_X86 }, 1160b57cec5SDimitry Andric { "X86-64" , MachO::CPU_TYPE_X86_64 }, 1170b57cec5SDimitry Andric { "Mc98000" , MachO::CPU_TYPE_MC98000 }, 1180b57cec5SDimitry Andric { "Arm" , MachO::CPU_TYPE_ARM }, 1190b57cec5SDimitry Andric { "Arm64" , MachO::CPU_TYPE_ARM64 }, 1200b57cec5SDimitry Andric { "Sparc" , MachO::CPU_TYPE_SPARC }, 1210b57cec5SDimitry Andric { "PowerPC" , MachO::CPU_TYPE_POWERPC }, 1220b57cec5SDimitry Andric { "PowerPC64" , MachO::CPU_TYPE_POWERPC64 }, 1230b57cec5SDimitry Andric }; 1240b57cec5SDimitry Andric 125349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX86[] = { 1260b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_I386_ALL), 1270b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_386), 1280b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486), 1290b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486SX), 1300b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_586), 1310b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTPRO), 1320b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M3), 1330b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M5), 1340b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON), 1350b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON_MOBILE), 1360b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3), 1370b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_M), 1380b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_XEON), 1390b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_M), 1400b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4), 1410b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4_M), 1420b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM), 1430b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM_2), 1440b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON), 1450b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON_MP), 1460b57cec5SDimitry Andric }; 1470b57cec5SDimitry Andric 148349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX64[] = { 1490b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_ALL), 1500b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_ARCH1), 1510b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_H), 1520b57cec5SDimitry Andric }; 1530b57cec5SDimitry Andric 154349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM[] = { 1550b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_ALL), 1560b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V4T), 1570b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6), 1580b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5), 1590b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5TEJ), 1600b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_XSCALE), 1610b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7), 1620b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7S), 1630b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7K), 1640b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6M), 1650b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7M), 1660b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7EM), 1670b57cec5SDimitry Andric }; 1680b57cec5SDimitry Andric 169349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM64[] = { 1700b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_ALL), 171e8d8bef9SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_V8), 1720b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64E), 1730b57cec5SDimitry Andric }; 1740b57cec5SDimitry Andric 175349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOHeaderCpuSubtypesSPARC[] = { 1760b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_SPARC_ALL), 1770b57cec5SDimitry Andric }; 1780b57cec5SDimitry Andric 179349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOHeaderCpuSubtypesPPC[] = { 1800b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_ALL), 1810b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_601), 1820b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_602), 1830b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603), 1840b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603e), 1850b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603ev), 1860b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604), 1870b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604e), 1880b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_620), 1890b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_750), 1900b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7400), 1910b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7450), 1920b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_970), 1930b57cec5SDimitry Andric }; 1940b57cec5SDimitry Andric 195349cc55cSDimitry Andric const EnumEntry<uint32_t> MachOHeaderFlags[] = { 1960b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_NOUNDEFS), 1970b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_INCRLINK), 1980b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_DYLDLINK), 1990b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDATLOAD), 2000b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBOUND), 2010b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_SPLIT_SEGS), 2020b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_LAZY_INIT), 2030b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_TWOLEVEL), 2040b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_FORCE_FLAT), 2050b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_NOMULTIDEFS), 2060b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_NOFIXPREBINDING), 2070b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBINDABLE), 2080b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLMODSBOUND), 2090b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_SUBSECTIONS_VIA_SYMBOLS), 2100b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_CANONICAL), 2110b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_WEAK_DEFINES), 2120b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDS_TO_WEAK), 2130b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLOW_STACK_EXECUTION), 2140b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_ROOT_SAFE), 2150b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_SETUID_SAFE), 2160b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_REEXPORTED_DYLIBS), 2170b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_PIE), 2180b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_DEAD_STRIPPABLE_DYLIB), 2190b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_HAS_TLV_DESCRIPTORS), 2200b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_HEAP_EXECUTION), 2210b57cec5SDimitry Andric LLVM_READOBJ_ENUM_ENT(MachO, MH_APP_EXTENSION_SAFE), 2220b57cec5SDimitry Andric }; 2230b57cec5SDimitry Andric 224349cc55cSDimitry Andric const EnumEntry<unsigned> MachOSectionTypes[] = { 2258bcb0991SDimitry Andric { "Regular" , MachO::S_REGULAR }, 2268bcb0991SDimitry Andric { "ZeroFill" , MachO::S_ZEROFILL }, 2278bcb0991SDimitry Andric { "CStringLiterals" , MachO::S_CSTRING_LITERALS }, 2288bcb0991SDimitry Andric { "4ByteLiterals" , MachO::S_4BYTE_LITERALS }, 2298bcb0991SDimitry Andric { "8ByteLiterals" , MachO::S_8BYTE_LITERALS }, 2308bcb0991SDimitry Andric { "LiteralPointers" , MachO::S_LITERAL_POINTERS }, 2318bcb0991SDimitry Andric { "NonLazySymbolPointers" , MachO::S_NON_LAZY_SYMBOL_POINTERS }, 2328bcb0991SDimitry Andric { "LazySymbolPointers" , MachO::S_LAZY_SYMBOL_POINTERS }, 2338bcb0991SDimitry Andric { "SymbolStubs" , MachO::S_SYMBOL_STUBS }, 2348bcb0991SDimitry Andric { "ModInitFuncPointers" , MachO::S_MOD_INIT_FUNC_POINTERS }, 2358bcb0991SDimitry Andric { "ModTermFuncPointers" , MachO::S_MOD_TERM_FUNC_POINTERS }, 2368bcb0991SDimitry Andric { "Coalesced" , MachO::S_COALESCED }, 2378bcb0991SDimitry Andric { "GBZeroFill" , MachO::S_GB_ZEROFILL }, 2388bcb0991SDimitry Andric { "Interposing" , MachO::S_INTERPOSING }, 2398bcb0991SDimitry Andric { "16ByteLiterals" , MachO::S_16BYTE_LITERALS }, 2408bcb0991SDimitry Andric { "DTraceDOF" , MachO::S_DTRACE_DOF }, 2418bcb0991SDimitry Andric { "LazyDylibSymbolPointers" , MachO::S_LAZY_DYLIB_SYMBOL_POINTERS }, 2428bcb0991SDimitry Andric { "ThreadLocalRegular" , MachO::S_THREAD_LOCAL_REGULAR }, 2438bcb0991SDimitry Andric { "ThreadLocalZerofill" , MachO::S_THREAD_LOCAL_ZEROFILL }, 2448bcb0991SDimitry Andric { "ThreadLocalVariables" , MachO::S_THREAD_LOCAL_VARIABLES }, 2458bcb0991SDimitry Andric { "ThreadLocalVariablePointers" , MachO::S_THREAD_LOCAL_VARIABLE_POINTERS }, 2468bcb0991SDimitry Andric { "ThreadLocalInitFunctionPointers", MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS } 2478bcb0991SDimitry Andric }; 2488bcb0991SDimitry Andric 249349cc55cSDimitry Andric const EnumEntry<unsigned> MachOSectionAttributes[] = { 2500b57cec5SDimitry Andric { "LocReloc" , 1 << 0 /*S_ATTR_LOC_RELOC */ }, 2510b57cec5SDimitry Andric { "ExtReloc" , 1 << 1 /*S_ATTR_EXT_RELOC */ }, 2520b57cec5SDimitry Andric { "SomeInstructions" , 1 << 2 /*S_ATTR_SOME_INSTRUCTIONS */ }, 2530b57cec5SDimitry Andric { "Debug" , 1 << 17 /*S_ATTR_DEBUG */ }, 2540b57cec5SDimitry Andric { "SelfModifyingCode", 1 << 18 /*S_ATTR_SELF_MODIFYING_CODE*/ }, 2550b57cec5SDimitry Andric { "LiveSupport" , 1 << 19 /*S_ATTR_LIVE_SUPPORT */ }, 2560b57cec5SDimitry Andric { "NoDeadStrip" , 1 << 20 /*S_ATTR_NO_DEAD_STRIP */ }, 2570b57cec5SDimitry Andric { "StripStaticSyms" , 1 << 21 /*S_ATTR_STRIP_STATIC_SYMS */ }, 2580b57cec5SDimitry Andric { "NoTOC" , 1 << 22 /*S_ATTR_NO_TOC */ }, 2590b57cec5SDimitry Andric { "PureInstructions" , 1 << 23 /*S_ATTR_PURE_INSTRUCTIONS */ }, 2600b57cec5SDimitry Andric }; 2610b57cec5SDimitry Andric 262349cc55cSDimitry Andric const EnumEntry<unsigned> MachOSymbolRefTypes[] = { 2630b57cec5SDimitry Andric { "UndefinedNonLazy", 0 }, 2640b57cec5SDimitry Andric { "ReferenceFlagUndefinedLazy", 1 }, 2650b57cec5SDimitry Andric { "ReferenceFlagDefined", 2 }, 2660b57cec5SDimitry Andric { "ReferenceFlagPrivateDefined", 3 }, 2670b57cec5SDimitry Andric { "ReferenceFlagPrivateUndefinedNonLazy", 4 }, 2680b57cec5SDimitry Andric { "ReferenceFlagPrivateUndefinedLazy", 5 } 2690b57cec5SDimitry Andric }; 2700b57cec5SDimitry Andric 271349cc55cSDimitry Andric const EnumEntry<unsigned> MachOSymbolFlags[] = { 272fe6060f1SDimitry Andric { "ThumbDef", 0x8 }, 2730b57cec5SDimitry Andric { "ReferencedDynamically", 0x10 }, 2740b57cec5SDimitry Andric { "NoDeadStrip", 0x20 }, 2750b57cec5SDimitry Andric { "WeakRef", 0x40 }, 2760b57cec5SDimitry Andric { "WeakDef", 0x80 }, 277fe6060f1SDimitry Andric { "SymbolResolver", 0x100 }, 2780b57cec5SDimitry Andric { "AltEntry", 0x200 }, 279fe6060f1SDimitry Andric { "ColdFunc", 0x400 }, 2800b57cec5SDimitry Andric }; 2810b57cec5SDimitry Andric 282349cc55cSDimitry Andric const EnumEntry<unsigned> MachOSymbolTypes[] = { 2830b57cec5SDimitry Andric { "Undef", 0x0 }, 2840b57cec5SDimitry Andric { "Abs", 0x2 }, 2850b57cec5SDimitry Andric { "Indirect", 0xA }, 2860b57cec5SDimitry Andric { "PreboundUndef", 0xC }, 2870b57cec5SDimitry Andric { "Section", 0xE } 2880b57cec5SDimitry Andric }; 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric namespace { 2910b57cec5SDimitry Andric struct MachOSection { 2920b57cec5SDimitry Andric ArrayRef<char> Name; 2930b57cec5SDimitry Andric ArrayRef<char> SegmentName; 2940b57cec5SDimitry Andric uint64_t Address; 2950b57cec5SDimitry Andric uint64_t Size; 2960b57cec5SDimitry Andric uint32_t Offset; 2970b57cec5SDimitry Andric uint32_t Alignment; 2980b57cec5SDimitry Andric uint32_t RelocationTableOffset; 2990b57cec5SDimitry Andric uint32_t NumRelocationTableEntries; 3000b57cec5SDimitry Andric uint32_t Flags; 3010b57cec5SDimitry Andric uint32_t Reserved1; 3020b57cec5SDimitry Andric uint32_t Reserved2; 3030b57cec5SDimitry Andric uint32_t Reserved3; 3040b57cec5SDimitry Andric }; 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric struct MachOSegment { 3070b57cec5SDimitry Andric std::string CmdName; 3080b57cec5SDimitry Andric std::string SegName; 3090b57cec5SDimitry Andric uint64_t cmdsize; 3100b57cec5SDimitry Andric uint64_t vmaddr; 3110b57cec5SDimitry Andric uint64_t vmsize; 3120b57cec5SDimitry Andric uint64_t fileoff; 3130b57cec5SDimitry Andric uint64_t filesize; 3140b57cec5SDimitry Andric uint32_t maxprot; 3150b57cec5SDimitry Andric uint32_t initprot; 3160b57cec5SDimitry Andric uint32_t nsects; 3170b57cec5SDimitry Andric uint32_t flags; 3180b57cec5SDimitry Andric }; 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric struct MachOSymbol { 3210b57cec5SDimitry Andric uint32_t StringIndex; 3220b57cec5SDimitry Andric uint8_t Type; 3230b57cec5SDimitry Andric uint8_t SectionIndex; 3240b57cec5SDimitry Andric uint16_t Flags; 3250b57cec5SDimitry Andric uint64_t Value; 3260b57cec5SDimitry Andric }; 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric static std::string getMask(uint32_t prot) 3300b57cec5SDimitry Andric { 3310b57cec5SDimitry Andric // TODO (davide): This always assumes prot is valid. 3320b57cec5SDimitry Andric // Catch mistakes and report if needed. 3330b57cec5SDimitry Andric std::string Prot; 3340b57cec5SDimitry Andric Prot = ""; 3350b57cec5SDimitry Andric Prot += (prot & MachO::VM_PROT_READ) ? "r" : "-"; 3360b57cec5SDimitry Andric Prot += (prot & MachO::VM_PROT_WRITE) ? "w" : "-"; 3370b57cec5SDimitry Andric Prot += (prot & MachO::VM_PROT_EXECUTE) ? "x" : "-"; 3380b57cec5SDimitry Andric return Prot; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric static void getSection(const MachOObjectFile *Obj, 3420b57cec5SDimitry Andric DataRefImpl Sec, 3430b57cec5SDimitry Andric MachOSection &Section) { 3440b57cec5SDimitry Andric if (!Obj->is64Bit()) { 3450b57cec5SDimitry Andric MachO::section Sect = Obj->getSection(Sec); 3460b57cec5SDimitry Andric Section.Address = Sect.addr; 3470b57cec5SDimitry Andric Section.Size = Sect.size; 3480b57cec5SDimitry Andric Section.Offset = Sect.offset; 3490b57cec5SDimitry Andric Section.Alignment = Sect.align; 3500b57cec5SDimitry Andric Section.RelocationTableOffset = Sect.reloff; 3510b57cec5SDimitry Andric Section.NumRelocationTableEntries = Sect.nreloc; 3520b57cec5SDimitry Andric Section.Flags = Sect.flags; 3530b57cec5SDimitry Andric Section.Reserved1 = Sect.reserved1; 3540b57cec5SDimitry Andric Section.Reserved2 = Sect.reserved2; 3550b57cec5SDimitry Andric return; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric MachO::section_64 Sect = Obj->getSection64(Sec); 3580b57cec5SDimitry Andric Section.Address = Sect.addr; 3590b57cec5SDimitry Andric Section.Size = Sect.size; 3600b57cec5SDimitry Andric Section.Offset = Sect.offset; 3610b57cec5SDimitry Andric Section.Alignment = Sect.align; 3620b57cec5SDimitry Andric Section.RelocationTableOffset = Sect.reloff; 3630b57cec5SDimitry Andric Section.NumRelocationTableEntries = Sect.nreloc; 3640b57cec5SDimitry Andric Section.Flags = Sect.flags; 3650b57cec5SDimitry Andric Section.Reserved1 = Sect.reserved1; 3660b57cec5SDimitry Andric Section.Reserved2 = Sect.reserved2; 3670b57cec5SDimitry Andric Section.Reserved3 = Sect.reserved3; 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric static void getSegment(const MachOObjectFile *Obj, 3710b57cec5SDimitry Andric const MachOObjectFile::LoadCommandInfo &L, 3720b57cec5SDimitry Andric MachOSegment &Segment) { 3730b57cec5SDimitry Andric if (!Obj->is64Bit()) { 3740b57cec5SDimitry Andric MachO::segment_command SC = Obj->getSegmentLoadCommand(L); 3750b57cec5SDimitry Andric Segment.CmdName = "LC_SEGMENT"; 3760b57cec5SDimitry Andric Segment.SegName = SC.segname; 3770b57cec5SDimitry Andric Segment.cmdsize = SC.cmdsize; 3780b57cec5SDimitry Andric Segment.vmaddr = SC.vmaddr; 3790b57cec5SDimitry Andric Segment.vmsize = SC.vmsize; 3800b57cec5SDimitry Andric Segment.fileoff = SC.fileoff; 3810b57cec5SDimitry Andric Segment.filesize = SC.filesize; 3820b57cec5SDimitry Andric Segment.maxprot = SC.maxprot; 3830b57cec5SDimitry Andric Segment.initprot = SC.initprot; 3840b57cec5SDimitry Andric Segment.nsects = SC.nsects; 3850b57cec5SDimitry Andric Segment.flags = SC.flags; 3860b57cec5SDimitry Andric return; 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric MachO::segment_command_64 SC = Obj->getSegment64LoadCommand(L); 3890b57cec5SDimitry Andric Segment.CmdName = "LC_SEGMENT_64"; 3900b57cec5SDimitry Andric Segment.SegName = SC.segname; 3910b57cec5SDimitry Andric Segment.cmdsize = SC.cmdsize; 3920b57cec5SDimitry Andric Segment.vmaddr = SC.vmaddr; 3930b57cec5SDimitry Andric Segment.vmsize = SC.vmsize; 3940b57cec5SDimitry Andric Segment.fileoff = SC.fileoff; 3950b57cec5SDimitry Andric Segment.filesize = SC.filesize; 3960b57cec5SDimitry Andric Segment.maxprot = SC.maxprot; 3970b57cec5SDimitry Andric Segment.initprot = SC.initprot; 3980b57cec5SDimitry Andric Segment.nsects = SC.nsects; 3990b57cec5SDimitry Andric Segment.flags = SC.flags; 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric static void getSymbol(const MachOObjectFile *Obj, 4030b57cec5SDimitry Andric DataRefImpl DRI, 4040b57cec5SDimitry Andric MachOSymbol &Symbol) { 4050b57cec5SDimitry Andric if (!Obj->is64Bit()) { 4060b57cec5SDimitry Andric MachO::nlist Entry = Obj->getSymbolTableEntry(DRI); 4070b57cec5SDimitry Andric Symbol.StringIndex = Entry.n_strx; 4080b57cec5SDimitry Andric Symbol.Type = Entry.n_type; 4090b57cec5SDimitry Andric Symbol.SectionIndex = Entry.n_sect; 4100b57cec5SDimitry Andric Symbol.Flags = Entry.n_desc; 4110b57cec5SDimitry Andric Symbol.Value = Entry.n_value; 4120b57cec5SDimitry Andric return; 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric MachO::nlist_64 Entry = Obj->getSymbol64TableEntry(DRI); 4150b57cec5SDimitry Andric Symbol.StringIndex = Entry.n_strx; 4160b57cec5SDimitry Andric Symbol.Type = Entry.n_type; 4170b57cec5SDimitry Andric Symbol.SectionIndex = Entry.n_sect; 4180b57cec5SDimitry Andric Symbol.Flags = Entry.n_desc; 4190b57cec5SDimitry Andric Symbol.Value = Entry.n_value; 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric void MachODumper::printFileHeaders() { 4230b57cec5SDimitry Andric DictScope H(W, "MachHeader"); 4240b57cec5SDimitry Andric if (!Obj->is64Bit()) { 4250b57cec5SDimitry Andric printFileHeaders(Obj->getHeader()); 4260b57cec5SDimitry Andric } else { 4270b57cec5SDimitry Andric printFileHeaders(Obj->getHeader64()); 4280b57cec5SDimitry Andric W.printHex("Reserved", Obj->getHeader64().reserved); 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric template<class MachHeader> 4330b57cec5SDimitry Andric void MachODumper::printFileHeaders(const MachHeader &Header) { 434bdd1243dSDimitry Andric W.printEnum("Magic", Header.magic, ArrayRef(MachOMagics)); 435bdd1243dSDimitry Andric W.printEnum("CpuType", Header.cputype, ArrayRef(MachOHeaderCpuTypes)); 4360b57cec5SDimitry Andric uint32_t subtype = Header.cpusubtype & ~MachO::CPU_SUBTYPE_MASK; 4370b57cec5SDimitry Andric switch (Header.cputype) { 4380b57cec5SDimitry Andric case MachO::CPU_TYPE_X86: 439bdd1243dSDimitry Andric W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesX86)); 4400b57cec5SDimitry Andric break; 4410b57cec5SDimitry Andric case MachO::CPU_TYPE_X86_64: 442bdd1243dSDimitry Andric W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesX64)); 4430b57cec5SDimitry Andric break; 4440b57cec5SDimitry Andric case MachO::CPU_TYPE_ARM: 445bdd1243dSDimitry Andric W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesARM)); 4460b57cec5SDimitry Andric break; 4470b57cec5SDimitry Andric case MachO::CPU_TYPE_POWERPC: 448bdd1243dSDimitry Andric W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesPPC)); 4490b57cec5SDimitry Andric break; 4500b57cec5SDimitry Andric case MachO::CPU_TYPE_SPARC: 451bdd1243dSDimitry Andric W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesSPARC)); 4520b57cec5SDimitry Andric break; 4530b57cec5SDimitry Andric case MachO::CPU_TYPE_ARM64: 454bdd1243dSDimitry Andric W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesARM64)); 4550b57cec5SDimitry Andric break; 4560b57cec5SDimitry Andric case MachO::CPU_TYPE_POWERPC64: 4570b57cec5SDimitry Andric default: 4580b57cec5SDimitry Andric W.printHex("CpuSubtype", subtype); 4590b57cec5SDimitry Andric } 460bdd1243dSDimitry Andric W.printEnum("FileType", Header.filetype, ArrayRef(MachOHeaderFileTypes)); 4610b57cec5SDimitry Andric W.printNumber("NumOfLoadCommands", Header.ncmds); 4620b57cec5SDimitry Andric W.printNumber("SizeOfLoadCommands", Header.sizeofcmds); 463bdd1243dSDimitry Andric W.printFlags("Flags", Header.flags, ArrayRef(MachOHeaderFlags)); 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric void MachODumper::printSectionHeaders() { return printSectionHeaders(Obj); } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric void MachODumper::printSectionHeaders(const MachOObjectFile *Obj) { 4690b57cec5SDimitry Andric ListScope Group(W, "Sections"); 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric int SectionIndex = -1; 4720b57cec5SDimitry Andric for (const SectionRef &Section : Obj->sections()) { 4730b57cec5SDimitry Andric ++SectionIndex; 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric MachOSection MOSection; 4760b57cec5SDimitry Andric getSection(Obj, Section.getRawDataRefImpl(), MOSection); 4770b57cec5SDimitry Andric DataRefImpl DR = Section.getRawDataRefImpl(); 4788bcb0991SDimitry Andric StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName()); 4790b57cec5SDimitry Andric ArrayRef<char> RawName = Obj->getSectionRawName(DR); 4800b57cec5SDimitry Andric StringRef SegmentName = Obj->getSectionFinalSegmentName(DR); 4810b57cec5SDimitry Andric ArrayRef<char> RawSegmentName = Obj->getSectionRawFinalSegmentName(DR); 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric DictScope SectionD(W, "Section"); 4840b57cec5SDimitry Andric W.printNumber("Index", SectionIndex); 4850b57cec5SDimitry Andric W.printBinary("Name", Name, RawName); 4860b57cec5SDimitry Andric W.printBinary("Segment", SegmentName, RawSegmentName); 4870b57cec5SDimitry Andric W.printHex("Address", MOSection.Address); 4880b57cec5SDimitry Andric W.printHex("Size", MOSection.Size); 4890b57cec5SDimitry Andric W.printNumber("Offset", MOSection.Offset); 4900b57cec5SDimitry Andric W.printNumber("Alignment", MOSection.Alignment); 4910b57cec5SDimitry Andric W.printHex("RelocationOffset", MOSection.RelocationTableOffset); 4920b57cec5SDimitry Andric W.printNumber("RelocationCount", MOSection.NumRelocationTableEntries); 493bdd1243dSDimitry Andric W.printEnum("Type", MOSection.Flags & 0xFF, ArrayRef(MachOSectionTypes)); 4940b57cec5SDimitry Andric W.printFlags("Attributes", MOSection.Flags >> 8, 495bdd1243dSDimitry Andric ArrayRef(MachOSectionAttributes)); 4960b57cec5SDimitry Andric W.printHex("Reserved1", MOSection.Reserved1); 4970b57cec5SDimitry Andric W.printHex("Reserved2", MOSection.Reserved2); 4980b57cec5SDimitry Andric if (Obj->is64Bit()) 4990b57cec5SDimitry Andric W.printHex("Reserved3", MOSection.Reserved3); 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric if (opts::SectionRelocations) { 5020b57cec5SDimitry Andric ListScope D(W, "Relocations"); 5030b57cec5SDimitry Andric for (const RelocationRef &Reloc : Section.relocations()) 5040b57cec5SDimitry Andric printRelocation(Reloc); 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric if (opts::SectionSymbols) { 5080b57cec5SDimitry Andric ListScope D(W, "Symbols"); 5090b57cec5SDimitry Andric for (const SymbolRef &Symbol : Obj->symbols()) { 5100b57cec5SDimitry Andric if (!Section.containsSymbol(Symbol)) 5110b57cec5SDimitry Andric continue; 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric printSymbol(Symbol); 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric if (opts::SectionData && !Section.isBSS()) 5188bcb0991SDimitry Andric W.printBinaryBlock("SectionData", unwrapOrError(Obj->getFileName(), 5198bcb0991SDimitry Andric Section.getContents())); 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric void MachODumper::printRelocations() { 5240b57cec5SDimitry Andric ListScope D(W, "Relocations"); 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric std::error_code EC; 5270b57cec5SDimitry Andric for (const SectionRef &Section : Obj->sections()) { 5288bcb0991SDimitry Andric StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName()); 5290b57cec5SDimitry Andric bool PrintedGroup = false; 5300b57cec5SDimitry Andric for (const RelocationRef &Reloc : Section.relocations()) { 5310b57cec5SDimitry Andric if (!PrintedGroup) { 5320b57cec5SDimitry Andric W.startLine() << "Section " << Name << " {\n"; 5330b57cec5SDimitry Andric W.indent(); 5340b57cec5SDimitry Andric PrintedGroup = true; 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric printRelocation(Reloc); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric if (PrintedGroup) { 5410b57cec5SDimitry Andric W.unindent(); 5420b57cec5SDimitry Andric W.startLine() << "}\n"; 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric void MachODumper::printRelocation(const RelocationRef &Reloc) { 5480b57cec5SDimitry Andric return printRelocation(Obj, Reloc); 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric void MachODumper::printRelocation(const MachOObjectFile *Obj, 5520b57cec5SDimitry Andric const RelocationRef &Reloc) { 5530b57cec5SDimitry Andric uint64_t Offset = Reloc.getOffset(); 5540b57cec5SDimitry Andric SmallString<32> RelocName; 5550b57cec5SDimitry Andric Reloc.getTypeName(RelocName); 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric DataRefImpl DR = Reloc.getRawDataRefImpl(); 5580b57cec5SDimitry Andric MachO::any_relocation_info RE = Obj->getRelocation(DR); 5590b57cec5SDimitry Andric bool IsScattered = Obj->isRelocationScattered(RE); 5600b57cec5SDimitry Andric bool IsExtern = !IsScattered && Obj->getPlainRelocationExternal(RE); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric StringRef TargetName; 5630b57cec5SDimitry Andric if (IsExtern) { 5640b57cec5SDimitry Andric symbol_iterator Symbol = Reloc.getSymbol(); 5650b57cec5SDimitry Andric if (Symbol != Obj->symbol_end()) { 56604eeddc0SDimitry Andric TargetName = getSymbolName(*Symbol); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric } else if (!IsScattered) { 5690b57cec5SDimitry Andric section_iterator SecI = Obj->getRelocationSection(DR); 5708bcb0991SDimitry Andric if (SecI != Obj->section_end()) 5718bcb0991SDimitry Andric TargetName = unwrapOrError(Obj->getFileName(), SecI->getName()); 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric if (TargetName.empty()) 5740b57cec5SDimitry Andric TargetName = "-"; 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric if (opts::ExpandRelocs) { 5770b57cec5SDimitry Andric DictScope Group(W, "Relocation"); 5780b57cec5SDimitry Andric W.printHex("Offset", Offset); 5790b57cec5SDimitry Andric W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE)); 5800b57cec5SDimitry Andric W.printNumber("Length", Obj->getAnyRelocationLength(RE)); 5810b57cec5SDimitry Andric W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE)); 5820b57cec5SDimitry Andric if (IsScattered) { 5830b57cec5SDimitry Andric W.printHex("Value", Obj->getScatteredRelocationValue(RE)); 5840b57cec5SDimitry Andric } else { 5850b57cec5SDimitry Andric const char *Kind = IsExtern ? "Symbol" : "Section"; 5860b57cec5SDimitry Andric W.printNumber(Kind, TargetName, Obj->getPlainRelocationSymbolNum(RE)); 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric } else { 5890b57cec5SDimitry Andric SmallString<32> SymbolNameOrOffset("0x"); 5900b57cec5SDimitry Andric if (IsScattered) { 5910b57cec5SDimitry Andric // Scattered relocations don't really have an associated symbol for some 5920b57cec5SDimitry Andric // reason, even if one exists in the symtab at the correct address. 5930b57cec5SDimitry Andric SymbolNameOrOffset += utohexstr(Obj->getScatteredRelocationValue(RE)); 5940b57cec5SDimitry Andric } else { 5950b57cec5SDimitry Andric SymbolNameOrOffset = TargetName; 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric raw_ostream& OS = W.startLine(); 5990b57cec5SDimitry Andric OS << W.hex(Offset) 6000b57cec5SDimitry Andric << " " << Obj->getAnyRelocationPCRel(RE) 6010b57cec5SDimitry Andric << " " << Obj->getAnyRelocationLength(RE); 6020b57cec5SDimitry Andric if (IsScattered) 6030b57cec5SDimitry Andric OS << " n/a"; 6040b57cec5SDimitry Andric else 6050b57cec5SDimitry Andric OS << " " << Obj->getPlainRelocationExternal(RE); 6060b57cec5SDimitry Andric OS << " " << RelocName 6070b57cec5SDimitry Andric << " " << IsScattered 6080b57cec5SDimitry Andric << " " << SymbolNameOrOffset 6090b57cec5SDimitry Andric << "\n"; 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 61381ad6265SDimitry Andric StringRef MachODumper::getSymbolName(const SymbolRef &Symbol) const { 61404eeddc0SDimitry Andric Expected<StringRef> SymbolNameOrErr = Symbol.getName(); 61504eeddc0SDimitry Andric if (!SymbolNameOrErr) { 61604eeddc0SDimitry Andric reportError(SymbolNameOrErr.takeError(), Obj->getFileName()); 61704eeddc0SDimitry Andric } 61804eeddc0SDimitry Andric return *SymbolNameOrErr; 61904eeddc0SDimitry Andric } 62004eeddc0SDimitry Andric 62181ad6265SDimitry Andric uint8_t MachODumper::getSymbolType(const SymbolRef &Symbol) const { 62281ad6265SDimitry Andric return Obj->is64Bit() 62381ad6265SDimitry Andric ? Obj->getSymbol64TableEntry(Symbol.getRawDataRefImpl()).n_type 62481ad6265SDimitry Andric : Obj->getSymbolTableEntry(Symbol.getRawDataRefImpl()).n_type; 62581ad6265SDimitry Andric } 6260b57cec5SDimitry Andric 62781ad6265SDimitry Andric bool MachODumper::compareSymbolsByName(SymbolRef LHS, SymbolRef RHS) const { 62881ad6265SDimitry Andric return getSymbolName(LHS).str().compare(getSymbolName(RHS).str()) < 0; 62981ad6265SDimitry Andric } 63081ad6265SDimitry Andric 63181ad6265SDimitry Andric bool MachODumper::compareSymbolsByType(SymbolRef LHS, SymbolRef RHS) const { 63281ad6265SDimitry Andric return getSymbolType(LHS) < getSymbolType(RHS); 63381ad6265SDimitry Andric } 63481ad6265SDimitry Andric 635*5f757f3fSDimitry Andric void MachODumper::printSymbols(bool /*ExtraSymInfo*/) { 636*5f757f3fSDimitry Andric printSymbols(std::nullopt); 637*5f757f3fSDimitry Andric } 63881ad6265SDimitry Andric 639bdd1243dSDimitry Andric void MachODumper::printSymbols(std::optional<SymbolComparator> SymComp) { 64081ad6265SDimitry Andric ListScope Group(W, "Symbols"); 64181ad6265SDimitry Andric if (SymComp) { 64281ad6265SDimitry Andric auto SymbolRange = Obj->symbols(); 64381ad6265SDimitry Andric std::vector<SymbolRef> SortedSymbols(SymbolRange.begin(), 64481ad6265SDimitry Andric SymbolRange.end()); 64581ad6265SDimitry Andric llvm::stable_sort(SortedSymbols, *SymComp); 64681ad6265SDimitry Andric for (SymbolRef Symbol : SortedSymbols) 64781ad6265SDimitry Andric printSymbol(Symbol); 64881ad6265SDimitry Andric } else { 6490b57cec5SDimitry Andric for (const SymbolRef &Symbol : Obj->symbols()) { 6500b57cec5SDimitry Andric printSymbol(Symbol); 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric } 65381ad6265SDimitry Andric } 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric void MachODumper::printDynamicSymbols() { 6560b57cec5SDimitry Andric ListScope Group(W, "DynamicSymbols"); 6570b57cec5SDimitry Andric } 658bdd1243dSDimitry Andric void MachODumper::printDynamicSymbols(std::optional<SymbolComparator> SymComp) { 65981ad6265SDimitry Andric ListScope Group(W, "DynamicSymbols"); 66081ad6265SDimitry Andric } 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric void MachODumper::printSymbol(const SymbolRef &Symbol) { 66381ad6265SDimitry Andric printSymbol(Symbol, W); 66481ad6265SDimitry Andric } 66581ad6265SDimitry Andric 66681ad6265SDimitry Andric void MachODumper::printSymbol(const SymbolRef &Symbol, ScopedPrinter &W) { 66704eeddc0SDimitry Andric StringRef SymbolName = getSymbolName(Symbol); 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric MachOSymbol MOSymbol; 6700b57cec5SDimitry Andric getSymbol(Obj, Symbol.getRawDataRefImpl(), MOSymbol); 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric StringRef SectionName = ""; 673e8d8bef9SDimitry Andric // Don't ask a Mach-O STABS symbol for its section unless we know that 674e8d8bef9SDimitry Andric // STAB symbol's section field refers to a valid section index. Otherwise 675e8d8bef9SDimitry Andric // the symbol may error trying to load a section that does not exist. 676e8d8bef9SDimitry Andric // TODO: Add a whitelist of STABS symbol types that contain valid section 677e8d8bef9SDimitry Andric // indices. 678e8d8bef9SDimitry Andric if (!(MOSymbol.Type & MachO::N_STAB)) { 6790b57cec5SDimitry Andric Expected<section_iterator> SecIOrErr = Symbol.getSection(); 6808bcb0991SDimitry Andric if (!SecIOrErr) 6818bcb0991SDimitry Andric reportError(SecIOrErr.takeError(), Obj->getFileName()); 6828bcb0991SDimitry Andric 6830b57cec5SDimitry Andric section_iterator SecI = *SecIOrErr; 6840b57cec5SDimitry Andric if (SecI != Obj->section_end()) 6858bcb0991SDimitry Andric SectionName = unwrapOrError(Obj->getFileName(), SecI->getName()); 686e8d8bef9SDimitry Andric } 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric DictScope D(W, "Symbol"); 6890b57cec5SDimitry Andric W.printNumber("Name", SymbolName, MOSymbol.StringIndex); 6900b57cec5SDimitry Andric if (MOSymbol.Type & MachO::N_STAB) { 6910b57cec5SDimitry Andric W.printHex("Type", "SymDebugTable", MOSymbol.Type); 6920b57cec5SDimitry Andric } else { 6930b57cec5SDimitry Andric if (MOSymbol.Type & MachO::N_PEXT) 6940b57cec5SDimitry Andric W.startLine() << "PrivateExtern\n"; 6950b57cec5SDimitry Andric if (MOSymbol.Type & MachO::N_EXT) 6960b57cec5SDimitry Andric W.startLine() << "Extern\n"; 6970b57cec5SDimitry Andric W.printEnum("Type", uint8_t(MOSymbol.Type & MachO::N_TYPE), 698bdd1243dSDimitry Andric ArrayRef(MachOSymbolTypes)); 6990b57cec5SDimitry Andric } 7000b57cec5SDimitry Andric W.printHex("Section", SectionName, MOSymbol.SectionIndex); 701fe6060f1SDimitry Andric W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0x7), 702bdd1243dSDimitry Andric ArrayRef(MachOSymbolRefTypes)); 703fe6060f1SDimitry Andric W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0x7), 704bdd1243dSDimitry Andric ArrayRef(MachOSymbolFlags)); 7050b57cec5SDimitry Andric W.printHex("Value", MOSymbol.Value); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric void MachODumper::printUnwindInfo() { 7090b57cec5SDimitry Andric W.startLine() << "UnwindInfo not implemented.\n"; 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric void MachODumper::printStackMap() const { 7130b57cec5SDimitry Andric object::SectionRef StackMapSection; 7140b57cec5SDimitry Andric for (auto Sec : Obj->sections()) { 7150b57cec5SDimitry Andric StringRef Name; 7168bcb0991SDimitry Andric if (Expected<StringRef> NameOrErr = Sec.getName()) 7178bcb0991SDimitry Andric Name = *NameOrErr; 7188bcb0991SDimitry Andric else 7198bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 7208bcb0991SDimitry Andric 7210b57cec5SDimitry Andric if (Name == "__llvm_stackmaps") { 7220b57cec5SDimitry Andric StackMapSection = Sec; 7230b57cec5SDimitry Andric break; 7240b57cec5SDimitry Andric } 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric if (StackMapSection == object::SectionRef()) 7280b57cec5SDimitry Andric return; 7290b57cec5SDimitry Andric 7308bcb0991SDimitry Andric StringRef StackMapContents = 7318bcb0991SDimitry Andric unwrapOrError(Obj->getFileName(), StackMapSection.getContents()); 7320b57cec5SDimitry Andric ArrayRef<uint8_t> StackMapContentsArray = 7330b57cec5SDimitry Andric arrayRefFromStringRef(StackMapContents); 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric if (Obj->isLittleEndian()) 7360b57cec5SDimitry Andric prettyPrintStackMap( 737*5f757f3fSDimitry Andric W, StackMapParser<llvm::endianness::little>(StackMapContentsArray)); 7380b57cec5SDimitry Andric else 7390b57cec5SDimitry Andric prettyPrintStackMap( 740*5f757f3fSDimitry Andric W, StackMapParser<llvm::endianness::big>(StackMapContentsArray)); 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric 74304eeddc0SDimitry Andric void MachODumper::printCGProfile() { 74404eeddc0SDimitry Andric object::SectionRef CGProfileSection; 74504eeddc0SDimitry Andric for (auto Sec : Obj->sections()) { 74604eeddc0SDimitry Andric StringRef Name; 74704eeddc0SDimitry Andric if (Expected<StringRef> NameOrErr = Sec.getName()) 74804eeddc0SDimitry Andric Name = *NameOrErr; 74904eeddc0SDimitry Andric else 75004eeddc0SDimitry Andric consumeError(NameOrErr.takeError()); 75104eeddc0SDimitry Andric 75204eeddc0SDimitry Andric if (Name == "__cg_profile") { 75304eeddc0SDimitry Andric CGProfileSection = Sec; 75404eeddc0SDimitry Andric break; 75504eeddc0SDimitry Andric } 75604eeddc0SDimitry Andric } 75704eeddc0SDimitry Andric if (CGProfileSection == object::SectionRef()) 75804eeddc0SDimitry Andric return; 75904eeddc0SDimitry Andric 76004eeddc0SDimitry Andric StringRef CGProfileContents = 76104eeddc0SDimitry Andric unwrapOrError(Obj->getFileName(), CGProfileSection.getContents()); 76204eeddc0SDimitry Andric BinaryStreamReader Reader(CGProfileContents, Obj->isLittleEndian() 763*5f757f3fSDimitry Andric ? llvm::endianness::little 764*5f757f3fSDimitry Andric : llvm::endianness::big); 76504eeddc0SDimitry Andric 76604eeddc0SDimitry Andric ListScope L(W, "CGProfile"); 76704eeddc0SDimitry Andric while (!Reader.empty()) { 76804eeddc0SDimitry Andric uint32_t FromIndex, ToIndex; 76904eeddc0SDimitry Andric uint64_t Count; 77004eeddc0SDimitry Andric if (Error Err = Reader.readInteger(FromIndex)) 77104eeddc0SDimitry Andric reportError(std::move(Err), Obj->getFileName()); 77204eeddc0SDimitry Andric if (Error Err = Reader.readInteger(ToIndex)) 77304eeddc0SDimitry Andric reportError(std::move(Err), Obj->getFileName()); 77404eeddc0SDimitry Andric if (Error Err = Reader.readInteger(Count)) 77504eeddc0SDimitry Andric reportError(std::move(Err), Obj->getFileName()); 77604eeddc0SDimitry Andric DictScope D(W, "CGProfileEntry"); 77704eeddc0SDimitry Andric W.printNumber("From", getSymbolName(*Obj->getSymbolByIndex(FromIndex)), 77804eeddc0SDimitry Andric FromIndex); 77904eeddc0SDimitry Andric W.printNumber("To", getSymbolName(*Obj->getSymbolByIndex(ToIndex)), 78004eeddc0SDimitry Andric ToIndex); 78104eeddc0SDimitry Andric W.printNumber("Weight", Count); 78204eeddc0SDimitry Andric } 78304eeddc0SDimitry Andric } 78404eeddc0SDimitry Andric 7850b57cec5SDimitry Andric void MachODumper::printNeededLibraries() { 7860b57cec5SDimitry Andric ListScope D(W, "NeededLibraries"); 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric using LibsTy = std::vector<StringRef>; 7890b57cec5SDimitry Andric LibsTy Libs; 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric for (const auto &Command : Obj->load_commands()) { 7920b57cec5SDimitry Andric if (Command.C.cmd == MachO::LC_LOAD_DYLIB || 7930b57cec5SDimitry Andric Command.C.cmd == MachO::LC_ID_DYLIB || 7940b57cec5SDimitry Andric Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 7950b57cec5SDimitry Andric Command.C.cmd == MachO::LC_REEXPORT_DYLIB || 7960b57cec5SDimitry Andric Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 7970b57cec5SDimitry Andric Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 7980b57cec5SDimitry Andric MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command); 7990b57cec5SDimitry Andric if (Dl.dylib.name < Dl.cmdsize) { 8000b57cec5SDimitry Andric auto *P = static_cast<const char*>(Command.Ptr) + Dl.dylib.name; 8010b57cec5SDimitry Andric Libs.push_back(P); 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric llvm::stable_sort(Libs); 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric for (const auto &L : Libs) { 8090b57cec5SDimitry Andric W.startLine() << L << "\n"; 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric void MachODumper::printMachODataInCode() { 8140b57cec5SDimitry Andric for (const auto &Load : Obj->load_commands()) { 8150b57cec5SDimitry Andric if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 8160b57cec5SDimitry Andric MachO::linkedit_data_command LLC = Obj->getLinkeditDataLoadCommand(Load); 8170b57cec5SDimitry Andric DictScope Group(W, "DataInCode"); 8180b57cec5SDimitry Andric W.printNumber("Data offset", LLC.dataoff); 8190b57cec5SDimitry Andric W.printNumber("Data size", LLC.datasize); 8200b57cec5SDimitry Andric ListScope D(W, "Data entries"); 8210b57cec5SDimitry Andric unsigned NumRegions = LLC.datasize / sizeof(MachO::data_in_code_entry); 8220b57cec5SDimitry Andric for (unsigned i = 0; i < NumRegions; ++i) { 8230b57cec5SDimitry Andric MachO::data_in_code_entry DICE = Obj->getDataInCodeTableEntry( 8240b57cec5SDimitry Andric LLC.dataoff, i); 8250b57cec5SDimitry Andric DictScope Group(W, "Entry"); 8260b57cec5SDimitry Andric W.printNumber("Index", i); 8270b57cec5SDimitry Andric W.printNumber("Offset", DICE.offset); 8280b57cec5SDimitry Andric W.printNumber("Length", DICE.length); 8290b57cec5SDimitry Andric W.printNumber("Kind", DICE.kind); 8300b57cec5SDimitry Andric } 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric void MachODumper::printMachOVersionMin() { 8360b57cec5SDimitry Andric for (const auto &Load : Obj->load_commands()) { 8370b57cec5SDimitry Andric StringRef Cmd; 8380b57cec5SDimitry Andric switch (Load.C.cmd) { 8390b57cec5SDimitry Andric case MachO::LC_VERSION_MIN_MACOSX: 8400b57cec5SDimitry Andric Cmd = "LC_VERSION_MIN_MACOSX"; 8410b57cec5SDimitry Andric break; 8420b57cec5SDimitry Andric case MachO::LC_VERSION_MIN_IPHONEOS: 8430b57cec5SDimitry Andric Cmd = "LC_VERSION_MIN_IPHONEOS"; 8440b57cec5SDimitry Andric break; 8450b57cec5SDimitry Andric case MachO::LC_VERSION_MIN_TVOS: 8460b57cec5SDimitry Andric Cmd = "LC_VERSION_MIN_TVOS"; 8470b57cec5SDimitry Andric break; 8480b57cec5SDimitry Andric case MachO::LC_VERSION_MIN_WATCHOS: 8490b57cec5SDimitry Andric Cmd = "LC_VERSION_MIN_WATCHOS"; 8500b57cec5SDimitry Andric break; 8510b57cec5SDimitry Andric case MachO::LC_BUILD_VERSION: 8520b57cec5SDimitry Andric Cmd = "LC_BUILD_VERSION"; 8530b57cec5SDimitry Andric break; 8540b57cec5SDimitry Andric default: 8550b57cec5SDimitry Andric continue; 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric DictScope Group(W, "MinVersion"); 8590b57cec5SDimitry Andric // Handle LC_BUILD_VERSION. 8600b57cec5SDimitry Andric if (Load.C.cmd == MachO::LC_BUILD_VERSION) { 8610b57cec5SDimitry Andric MachO::build_version_command BVC = Obj->getBuildVersionLoadCommand(Load); 8620b57cec5SDimitry Andric W.printString("Cmd", Cmd); 8630b57cec5SDimitry Andric W.printNumber("Size", BVC.cmdsize); 8640b57cec5SDimitry Andric W.printString("Platform", 8650b57cec5SDimitry Andric MachOObjectFile::getBuildPlatform(BVC.platform)); 8660b57cec5SDimitry Andric W.printString("Version", MachOObjectFile::getVersionString(BVC.minos)); 8670b57cec5SDimitry Andric if (BVC.sdk) 8680b57cec5SDimitry Andric W.printString("SDK", MachOObjectFile::getVersionString(BVC.sdk)); 8690b57cec5SDimitry Andric else 8700b57cec5SDimitry Andric W.printString("SDK", StringRef("n/a")); 8710b57cec5SDimitry Andric continue; 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric MachO::version_min_command VMC = Obj->getVersionMinLoadCommand(Load); 8750b57cec5SDimitry Andric W.printString("Cmd", Cmd); 8760b57cec5SDimitry Andric W.printNumber("Size", VMC.cmdsize); 8770b57cec5SDimitry Andric SmallString<32> Version; 8780b57cec5SDimitry Andric Version = utostr(MachOObjectFile::getVersionMinMajor(VMC, false)) + "." + 8790b57cec5SDimitry Andric utostr(MachOObjectFile::getVersionMinMinor(VMC, false)); 8800b57cec5SDimitry Andric uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, false); 8810b57cec5SDimitry Andric if (Update != 0) 8820b57cec5SDimitry Andric Version += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, false)); 8830b57cec5SDimitry Andric W.printString("Version", Version); 8840b57cec5SDimitry Andric SmallString<32> SDK; 8850b57cec5SDimitry Andric if (VMC.sdk == 0) 8860b57cec5SDimitry Andric SDK = "n/a"; 8870b57cec5SDimitry Andric else { 8880b57cec5SDimitry Andric SDK = utostr(MachOObjectFile::getVersionMinMajor(VMC, true)) + "." + 8890b57cec5SDimitry Andric utostr(MachOObjectFile::getVersionMinMinor(VMC, true)); 8900b57cec5SDimitry Andric uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, true); 8910b57cec5SDimitry Andric if (Update != 0) 8920b57cec5SDimitry Andric SDK += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, true)); 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric W.printString("SDK", SDK); 8950b57cec5SDimitry Andric } 8960b57cec5SDimitry Andric } 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric void MachODumper::printMachODysymtab() { 8990b57cec5SDimitry Andric for (const auto &Load : Obj->load_commands()) { 9000b57cec5SDimitry Andric if (Load.C.cmd == MachO::LC_DYSYMTAB) { 9010b57cec5SDimitry Andric MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand(); 9020b57cec5SDimitry Andric DictScope Group(W, "Dysymtab"); 9030b57cec5SDimitry Andric W.printNumber("ilocalsym", DLC.ilocalsym); 9040b57cec5SDimitry Andric W.printNumber("nlocalsym", DLC.nlocalsym); 9050b57cec5SDimitry Andric W.printNumber("iextdefsym", DLC.iextdefsym); 9060b57cec5SDimitry Andric W.printNumber("nextdefsym", DLC.nextdefsym); 9070b57cec5SDimitry Andric W.printNumber("iundefsym", DLC.iundefsym); 9080b57cec5SDimitry Andric W.printNumber("nundefsym", DLC.nundefsym); 9090b57cec5SDimitry Andric W.printNumber("tocoff", DLC.tocoff); 9100b57cec5SDimitry Andric W.printNumber("ntoc", DLC.ntoc); 9110b57cec5SDimitry Andric W.printNumber("modtaboff", DLC.modtaboff); 9120b57cec5SDimitry Andric W.printNumber("nmodtab", DLC.nmodtab); 9130b57cec5SDimitry Andric W.printNumber("extrefsymoff", DLC.extrefsymoff); 9140b57cec5SDimitry Andric W.printNumber("nextrefsyms", DLC.nextrefsyms); 9150b57cec5SDimitry Andric W.printNumber("indirectsymoff", DLC.indirectsymoff); 9160b57cec5SDimitry Andric W.printNumber("nindirectsyms", DLC.nindirectsyms); 9170b57cec5SDimitry Andric W.printNumber("extreloff", DLC.extreloff); 9180b57cec5SDimitry Andric W.printNumber("nextrel", DLC.nextrel); 9190b57cec5SDimitry Andric W.printNumber("locreloff", DLC.locreloff); 9200b57cec5SDimitry Andric W.printNumber("nlocrel", DLC.nlocrel); 9210b57cec5SDimitry Andric } 9220b57cec5SDimitry Andric } 9230b57cec5SDimitry Andric } 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric void MachODumper::printMachOSegment() { 9260b57cec5SDimitry Andric for (const auto &Load : Obj->load_commands()) { 9270b57cec5SDimitry Andric if (Load.C.cmd == MachO::LC_SEGMENT || Load.C.cmd == MachO::LC_SEGMENT_64) { 9280b57cec5SDimitry Andric MachOSegment MOSegment; 9290b57cec5SDimitry Andric getSegment(Obj, Load, MOSegment); 9300b57cec5SDimitry Andric DictScope Group(W, "Segment"); 9310b57cec5SDimitry Andric W.printString("Cmd", MOSegment.CmdName); 9320b57cec5SDimitry Andric W.printString("Name", MOSegment.SegName); 9330b57cec5SDimitry Andric W.printNumber("Size", MOSegment.cmdsize); 9340b57cec5SDimitry Andric W.printHex("vmaddr", MOSegment.vmaddr); 9350b57cec5SDimitry Andric W.printHex("vmsize", MOSegment.vmsize); 9360b57cec5SDimitry Andric W.printNumber("fileoff", MOSegment.fileoff); 9370b57cec5SDimitry Andric W.printNumber("filesize", MOSegment.filesize); 9380b57cec5SDimitry Andric W.printString("maxprot", getMask(MOSegment.maxprot)); 9390b57cec5SDimitry Andric W.printString("initprot", getMask(MOSegment.initprot)); 9400b57cec5SDimitry Andric W.printNumber("nsects", MOSegment.nsects); 9410b57cec5SDimitry Andric W.printHex("flags", MOSegment.flags); 9420b57cec5SDimitry Andric } 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric 9460b57cec5SDimitry Andric void MachODumper::printMachOIndirectSymbols() { 9470b57cec5SDimitry Andric for (const auto &Load : Obj->load_commands()) { 9480b57cec5SDimitry Andric if (Load.C.cmd == MachO::LC_DYSYMTAB) { 9490b57cec5SDimitry Andric MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand(); 9500b57cec5SDimitry Andric DictScope Group(W, "Indirect Symbols"); 9510b57cec5SDimitry Andric W.printNumber("Number", DLC.nindirectsyms); 9520b57cec5SDimitry Andric ListScope D(W, "Symbols"); 9530b57cec5SDimitry Andric for (unsigned i = 0; i < DLC.nindirectsyms; ++i) { 9540b57cec5SDimitry Andric DictScope Group(W, "Entry"); 9550b57cec5SDimitry Andric W.printNumber("Entry Index", i); 9560b57cec5SDimitry Andric W.printHex("Symbol Index", Obj->getIndirectSymbolTableEntry(DLC, i)); 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric 9620b57cec5SDimitry Andric void MachODumper::printMachOLinkerOptions() { 9630b57cec5SDimitry Andric for (const auto &Load : Obj->load_commands()) { 9640b57cec5SDimitry Andric if (Load.C.cmd == MachO::LC_LINKER_OPTION) { 9650b57cec5SDimitry Andric MachO::linker_option_command LOLC = Obj->getLinkerOptionLoadCommand(Load); 9660b57cec5SDimitry Andric DictScope Group(W, "Linker Options"); 9670b57cec5SDimitry Andric W.printNumber("Size", LOLC.cmdsize); 9680b57cec5SDimitry Andric ListScope D(W, "Strings"); 9690b57cec5SDimitry Andric uint64_t DataSize = LOLC.cmdsize - sizeof(MachO::linker_option_command); 9700b57cec5SDimitry Andric const char *P = Load.Ptr + sizeof(MachO::linker_option_command); 9710b57cec5SDimitry Andric StringRef Data(P, DataSize); 9720b57cec5SDimitry Andric for (unsigned i = 0; i < LOLC.count; ++i) { 9730b57cec5SDimitry Andric std::pair<StringRef,StringRef> Split = Data.split('\0'); 9740b57cec5SDimitry Andric W.printString("Value", Split.first); 9750b57cec5SDimitry Andric Data = Split.second; 9760b57cec5SDimitry Andric } 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric } 9790b57cec5SDimitry Andric } 980