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