xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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:
MachODumper(const MachOObjectFile * Obj,ScopedPrinter & Writer)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 
canCompareSymbols() const4281ad6265SDimitry 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 
createMachODumper(const object::MachOObjectFile & Obj,ScopedPrinter & Writer)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 
getMask(uint32_t prot)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 
getSection(const MachOObjectFile * Obj,DataRefImpl Sec,MachOSection & Section)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 
getSegment(const MachOObjectFile * Obj,const MachOObjectFile::LoadCommandInfo & L,MachOSegment & Segment)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 
getSymbol(const MachOObjectFile * Obj,DataRefImpl DRI,MachOSymbol & Symbol)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 
printFileHeaders()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>
printFileHeaders(const MachHeader & Header)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 
printSectionHeaders()4660b57cec5SDimitry Andric void MachODumper::printSectionHeaders() { return printSectionHeaders(Obj); }
4670b57cec5SDimitry Andric 
printSectionHeaders(const MachOObjectFile * Obj)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 
printRelocations()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 
printRelocation(const RelocationRef & Reloc)5470b57cec5SDimitry Andric void MachODumper::printRelocation(const RelocationRef &Reloc) {
5480b57cec5SDimitry Andric   return printRelocation(Obj, Reloc);
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric 
printRelocation(const MachOObjectFile * Obj,const RelocationRef & Reloc)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 
getSymbolName(const SymbolRef & Symbol) const61381ad6265SDimitry 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 
getSymbolType(const SymbolRef & Symbol) const62181ad6265SDimitry 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 
compareSymbolsByName(SymbolRef LHS,SymbolRef RHS) const62781ad6265SDimitry Andric bool MachODumper::compareSymbolsByName(SymbolRef LHS, SymbolRef RHS) const {
62881ad6265SDimitry Andric   return getSymbolName(LHS).str().compare(getSymbolName(RHS).str()) < 0;
62981ad6265SDimitry Andric }
63081ad6265SDimitry Andric 
compareSymbolsByType(SymbolRef LHS,SymbolRef RHS) const63181ad6265SDimitry Andric bool MachODumper::compareSymbolsByType(SymbolRef LHS, SymbolRef RHS) const {
63281ad6265SDimitry Andric   return getSymbolType(LHS) < getSymbolType(RHS);
63381ad6265SDimitry Andric }
63481ad6265SDimitry Andric 
printSymbols(bool)635*5f757f3fSDimitry Andric void MachODumper::printSymbols(bool /*ExtraSymInfo*/) {
636*5f757f3fSDimitry Andric   printSymbols(std::nullopt);
637*5f757f3fSDimitry Andric }
63881ad6265SDimitry Andric 
printSymbols(std::optional<SymbolComparator> SymComp)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 
printDynamicSymbols()6550b57cec5SDimitry Andric void MachODumper::printDynamicSymbols() {
6560b57cec5SDimitry Andric   ListScope Group(W, "DynamicSymbols");
6570b57cec5SDimitry Andric }
printDynamicSymbols(std::optional<SymbolComparator> SymComp)658bdd1243dSDimitry Andric void MachODumper::printDynamicSymbols(std::optional<SymbolComparator> SymComp) {
65981ad6265SDimitry Andric   ListScope Group(W, "DynamicSymbols");
66081ad6265SDimitry Andric }
6610b57cec5SDimitry Andric 
printSymbol(const SymbolRef & Symbol)6620b57cec5SDimitry Andric void MachODumper::printSymbol(const SymbolRef &Symbol) {
66381ad6265SDimitry Andric   printSymbol(Symbol, W);
66481ad6265SDimitry Andric }
66581ad6265SDimitry Andric 
printSymbol(const SymbolRef & Symbol,ScopedPrinter & W)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 
printUnwindInfo()7080b57cec5SDimitry Andric void MachODumper::printUnwindInfo() {
7090b57cec5SDimitry Andric   W.startLine() << "UnwindInfo not implemented.\n";
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric 
printStackMap() const7120b57cec5SDimitry 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 
printCGProfile()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 
printNeededLibraries()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 
printMachODataInCode()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 
printMachOVersionMin()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 
printMachODysymtab()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 
printMachOSegment()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 
printMachOIndirectSymbols()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 
printMachOLinkerOptions()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