1 //===-- MachODump.cpp - Object file dumping utility for llvm --------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the MachO-specific dumper for llvm-readobj.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "Error.h"
15 #include "ObjDumper.h"
16 #include "StackMapPrinter.h"
17 #include "llvm-readobj.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/Object/MachO.h"
21 #include "llvm/Support/Casting.h"
22 #include "llvm/Support/ScopedPrinter.h"
23 
24 using namespace llvm;
25 using namespace object;
26 
27 namespace {
28 
29 class MachODumper : public ObjDumper {
30 public:
31   MachODumper(const MachOObjectFile *Obj, ScopedPrinter &Writer)
32       : ObjDumper(Writer), Obj(Obj) {}
33 
34   void printFileHeaders() override;
35   void printSections() override;
36   void printRelocations() override;
37   void printSymbols() override;
38   void printDynamicSymbols() override;
39   void printUnwindInfo() override;
40   void printStackMap() const override;
41   void printSectionAsHex(StringRef SectionName) override;
42 
43   void printNeededLibraries() override;
44 
45   // MachO-specific.
46   void printMachODataInCode() override;
47   void printMachOVersionMin() override;
48   void printMachODysymtab() override;
49   void printMachOSegment() override;
50   void printMachOIndirectSymbols() override;
51   void printMachOLinkerOptions () override;
52 
53 private:
54   template<class MachHeader>
55   void printFileHeaders(const MachHeader &Header);
56 
57   void printSymbol(const SymbolRef &Symbol);
58 
59   void printRelocation(const RelocationRef &Reloc);
60 
61   void printRelocation(const MachOObjectFile *Obj, const RelocationRef &Reloc);
62 
63   void printSections(const MachOObjectFile *Obj);
64 
65   const MachOObjectFile *Obj;
66 };
67 
68 } // namespace
69 
70 
71 namespace llvm {
72 
73 std::error_code createMachODumper(const object::ObjectFile *Obj,
74                                   ScopedPrinter &Writer,
75                                   std::unique_ptr<ObjDumper> &Result) {
76   const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(Obj);
77   if (!MachOObj)
78     return readobj_error::unsupported_obj_file_format;
79 
80   Result.reset(new MachODumper(MachOObj, Writer));
81   return readobj_error::success;
82 }
83 
84 } // namespace llvm
85 
86 static const EnumEntry<uint32_t> MachOMagics[] = {
87   { "Magic",      MachO::MH_MAGIC    },
88   { "Cigam",      MachO::MH_CIGAM    },
89   { "Magic64",    MachO::MH_MAGIC_64 },
90   { "Cigam64",    MachO::MH_CIGAM_64 },
91   { "FatMagic",   MachO::FAT_MAGIC   },
92   { "FatCigam",   MachO::FAT_CIGAM   },
93 };
94 
95 static const EnumEntry<uint32_t> MachOHeaderFileTypes[] = {
96   { "Relocatable",          MachO::MH_OBJECT      },
97   { "Executable",           MachO::MH_EXECUTE     },
98   { "FixedVMLibrary",       MachO::MH_FVMLIB      },
99   { "Core",                 MachO::MH_CORE        },
100   { "PreloadedExecutable",  MachO::MH_PRELOAD     },
101   { "DynamicLibrary",       MachO::MH_DYLIB       },
102   { "DynamicLinker",        MachO::MH_DYLINKER    },
103   { "Bundle",               MachO::MH_BUNDLE      },
104   { "DynamicLibraryStub",   MachO::MH_DYLIB_STUB  },
105   { "DWARFSymbol",          MachO::MH_DSYM        },
106   { "KextBundle",           MachO::MH_KEXT_BUNDLE },
107 };
108 
109 static const EnumEntry<uint32_t> MachOHeaderCpuTypes[] = {
110   { "Any"       , static_cast<uint32_t>(MachO::CPU_TYPE_ANY) },
111   { "X86"       , MachO::CPU_TYPE_X86       },
112   { "X86-64"    , MachO::CPU_TYPE_X86_64    },
113   { "Mc98000"   , MachO::CPU_TYPE_MC98000   },
114   { "Arm"       , MachO::CPU_TYPE_ARM       },
115   { "Arm64"     , MachO::CPU_TYPE_ARM64     },
116   { "Sparc"     , MachO::CPU_TYPE_SPARC     },
117   { "PowerPC"   , MachO::CPU_TYPE_POWERPC   },
118   { "PowerPC64" , MachO::CPU_TYPE_POWERPC64 },
119 };
120 
121 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX86[] = {
122   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_I386_ALL),
123   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_386),
124   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486),
125   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486SX),
126   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_586),
127   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTPRO),
128   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M3),
129   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M5),
130   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON),
131   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON_MOBILE),
132   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3),
133   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_M),
134   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_XEON),
135   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_M),
136   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4),
137   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4_M),
138   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM),
139   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM_2),
140   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON),
141   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON_MP),
142 };
143 
144 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX64[] = {
145   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_ALL),
146   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_ARCH1),
147   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_H),
148 };
149 
150 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM[] = {
151   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_ALL),
152   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V4T),
153   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6),
154   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5),
155   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5TEJ),
156   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_XSCALE),
157   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7),
158   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7S),
159   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7K),
160   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6M),
161   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7M),
162   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7EM),
163 };
164 
165 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM64[] = {
166   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_ALL),
167 };
168 
169 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesSPARC[] = {
170   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_SPARC_ALL),
171 };
172 
173 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesPPC[] = {
174   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_ALL),
175   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_601),
176   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_602),
177   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603),
178   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603e),
179   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603ev),
180   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604),
181   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604e),
182   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_620),
183   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_750),
184   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7400),
185   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7450),
186   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_970),
187 };
188 
189 static const EnumEntry<uint32_t> MachOHeaderFlags[] = {
190   LLVM_READOBJ_ENUM_ENT(MachO, MH_NOUNDEFS),
191   LLVM_READOBJ_ENUM_ENT(MachO, MH_INCRLINK),
192   LLVM_READOBJ_ENUM_ENT(MachO, MH_DYLDLINK),
193   LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDATLOAD),
194   LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBOUND),
195   LLVM_READOBJ_ENUM_ENT(MachO, MH_SPLIT_SEGS),
196   LLVM_READOBJ_ENUM_ENT(MachO, MH_LAZY_INIT),
197   LLVM_READOBJ_ENUM_ENT(MachO, MH_TWOLEVEL),
198   LLVM_READOBJ_ENUM_ENT(MachO, MH_FORCE_FLAT),
199   LLVM_READOBJ_ENUM_ENT(MachO, MH_NOMULTIDEFS),
200   LLVM_READOBJ_ENUM_ENT(MachO, MH_NOFIXPREBINDING),
201   LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBINDABLE),
202   LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLMODSBOUND),
203   LLVM_READOBJ_ENUM_ENT(MachO, MH_SUBSECTIONS_VIA_SYMBOLS),
204   LLVM_READOBJ_ENUM_ENT(MachO, MH_CANONICAL),
205   LLVM_READOBJ_ENUM_ENT(MachO, MH_WEAK_DEFINES),
206   LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDS_TO_WEAK),
207   LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLOW_STACK_EXECUTION),
208   LLVM_READOBJ_ENUM_ENT(MachO, MH_ROOT_SAFE),
209   LLVM_READOBJ_ENUM_ENT(MachO, MH_SETUID_SAFE),
210   LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_REEXPORTED_DYLIBS),
211   LLVM_READOBJ_ENUM_ENT(MachO, MH_PIE),
212   LLVM_READOBJ_ENUM_ENT(MachO, MH_DEAD_STRIPPABLE_DYLIB),
213   LLVM_READOBJ_ENUM_ENT(MachO, MH_HAS_TLV_DESCRIPTORS),
214   LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_HEAP_EXECUTION),
215   LLVM_READOBJ_ENUM_ENT(MachO, MH_APP_EXTENSION_SAFE),
216 };
217 
218 static const EnumEntry<unsigned> MachOSectionAttributes[] = {
219   { "LocReloc"         , 1 <<  0 /*S_ATTR_LOC_RELOC          */ },
220   { "ExtReloc"         , 1 <<  1 /*S_ATTR_EXT_RELOC          */ },
221   { "SomeInstructions" , 1 <<  2 /*S_ATTR_SOME_INSTRUCTIONS  */ },
222   { "Debug"            , 1 << 17 /*S_ATTR_DEBUG              */ },
223   { "SelfModifyingCode", 1 << 18 /*S_ATTR_SELF_MODIFYING_CODE*/ },
224   { "LiveSupport"      , 1 << 19 /*S_ATTR_LIVE_SUPPORT       */ },
225   { "NoDeadStrip"      , 1 << 20 /*S_ATTR_NO_DEAD_STRIP      */ },
226   { "StripStaticSyms"  , 1 << 21 /*S_ATTR_STRIP_STATIC_SYMS  */ },
227   { "NoTOC"            , 1 << 22 /*S_ATTR_NO_TOC             */ },
228   { "PureInstructions" , 1 << 23 /*S_ATTR_PURE_INSTRUCTIONS  */ },
229 };
230 
231 static const EnumEntry<unsigned> MachOSymbolRefTypes[] = {
232   { "UndefinedNonLazy",                     0 },
233   { "ReferenceFlagUndefinedLazy",           1 },
234   { "ReferenceFlagDefined",                 2 },
235   { "ReferenceFlagPrivateDefined",          3 },
236   { "ReferenceFlagPrivateUndefinedNonLazy", 4 },
237   { "ReferenceFlagPrivateUndefinedLazy",    5 }
238 };
239 
240 static const EnumEntry<unsigned> MachOSymbolFlags[] = {
241   { "ReferencedDynamically", 0x10 },
242   { "NoDeadStrip",           0x20 },
243   { "WeakRef",               0x40 },
244   { "WeakDef",               0x80 },
245   { "AltEntry",             0x200 },
246 };
247 
248 static const EnumEntry<unsigned> MachOSymbolTypes[] = {
249   { "Undef",           0x0 },
250   { "Abs",             0x2 },
251   { "Indirect",        0xA },
252   { "PreboundUndef",   0xC },
253   { "Section",         0xE }
254 };
255 
256 namespace {
257   struct MachOSection {
258     ArrayRef<char> Name;
259     ArrayRef<char> SegmentName;
260     uint64_t Address;
261     uint64_t Size;
262     uint32_t Offset;
263     uint32_t Alignment;
264     uint32_t RelocationTableOffset;
265     uint32_t NumRelocationTableEntries;
266     uint32_t Flags;
267     uint32_t Reserved1;
268     uint32_t Reserved2;
269     uint32_t Reserved3;
270   };
271 
272   struct MachOSegment {
273     std::string CmdName;
274     std::string SegName;
275     uint64_t cmdsize;
276     uint64_t vmaddr;
277     uint64_t vmsize;
278     uint64_t fileoff;
279     uint64_t filesize;
280     uint32_t maxprot;
281     uint32_t initprot;
282     uint32_t nsects;
283     uint32_t flags;
284   };
285 
286   struct MachOSymbol {
287     uint32_t StringIndex;
288     uint8_t Type;
289     uint8_t SectionIndex;
290     uint16_t Flags;
291     uint64_t Value;
292   };
293 }
294 
295 static std::string getMask(uint32_t prot)
296 {
297   // TODO (davide): This always assumes prot is valid.
298   // Catch mistakes and report if needed.
299   std::string Prot;
300   Prot = "";
301   Prot += (prot & MachO::VM_PROT_READ) ? "r" : "-";
302   Prot += (prot & MachO::VM_PROT_WRITE) ? "w" : "-";
303   Prot += (prot & MachO::VM_PROT_EXECUTE) ? "x" : "-";
304   return Prot;
305 }
306 
307 static void getSection(const MachOObjectFile *Obj,
308                        DataRefImpl Sec,
309                        MachOSection &Section) {
310   if (!Obj->is64Bit()) {
311     MachO::section Sect = Obj->getSection(Sec);
312     Section.Address     = Sect.addr;
313     Section.Size        = Sect.size;
314     Section.Offset      = Sect.offset;
315     Section.Alignment   = Sect.align;
316     Section.RelocationTableOffset = Sect.reloff;
317     Section.NumRelocationTableEntries = Sect.nreloc;
318     Section.Flags       = Sect.flags;
319     Section.Reserved1   = Sect.reserved1;
320     Section.Reserved2   = Sect.reserved2;
321     return;
322   }
323   MachO::section_64 Sect = Obj->getSection64(Sec);
324   Section.Address     = Sect.addr;
325   Section.Size        = Sect.size;
326   Section.Offset      = Sect.offset;
327   Section.Alignment   = Sect.align;
328   Section.RelocationTableOffset = Sect.reloff;
329   Section.NumRelocationTableEntries = Sect.nreloc;
330   Section.Flags       = Sect.flags;
331   Section.Reserved1   = Sect.reserved1;
332   Section.Reserved2   = Sect.reserved2;
333   Section.Reserved3   = Sect.reserved3;
334 }
335 
336 static void getSegment(const MachOObjectFile *Obj,
337                        const MachOObjectFile::LoadCommandInfo &L,
338                        MachOSegment &Segment) {
339   if (!Obj->is64Bit()) {
340     MachO::segment_command SC = Obj->getSegmentLoadCommand(L);
341     Segment.CmdName = "LC_SEGMENT";
342     Segment.SegName = SC.segname;
343     Segment.cmdsize = SC.cmdsize;
344     Segment.vmaddr = SC.vmaddr;
345     Segment.vmsize = SC.vmsize;
346     Segment.fileoff = SC.fileoff;
347     Segment.filesize = SC.filesize;
348     Segment.maxprot = SC.maxprot;
349     Segment.initprot = SC.initprot;
350     Segment.nsects = SC.nsects;
351     Segment.flags = SC.flags;
352     return;
353   }
354   MachO::segment_command_64 SC = Obj->getSegment64LoadCommand(L);
355   Segment.CmdName = "LC_SEGMENT_64";
356   Segment.SegName = SC.segname;
357   Segment.cmdsize = SC.cmdsize;
358   Segment.vmaddr = SC.vmaddr;
359   Segment.vmsize = SC.vmsize;
360   Segment.fileoff = SC.fileoff;
361   Segment.filesize = SC.filesize;
362   Segment.maxprot = SC.maxprot;
363   Segment.initprot = SC.initprot;
364   Segment.nsects = SC.nsects;
365   Segment.flags = SC.flags;
366 }
367 
368 static void getSymbol(const MachOObjectFile *Obj,
369                       DataRefImpl DRI,
370                       MachOSymbol &Symbol) {
371   if (!Obj->is64Bit()) {
372     MachO::nlist Entry = Obj->getSymbolTableEntry(DRI);
373     Symbol.StringIndex  = Entry.n_strx;
374     Symbol.Type         = Entry.n_type;
375     Symbol.SectionIndex = Entry.n_sect;
376     Symbol.Flags        = Entry.n_desc;
377     Symbol.Value        = Entry.n_value;
378     return;
379   }
380   MachO::nlist_64 Entry = Obj->getSymbol64TableEntry(DRI);
381   Symbol.StringIndex  = Entry.n_strx;
382   Symbol.Type         = Entry.n_type;
383   Symbol.SectionIndex = Entry.n_sect;
384   Symbol.Flags        = Entry.n_desc;
385   Symbol.Value        = Entry.n_value;
386 }
387 
388 void MachODumper::printFileHeaders() {
389   DictScope H(W, "MachHeader");
390   if (!Obj->is64Bit()) {
391     printFileHeaders(Obj->getHeader());
392   } else {
393     printFileHeaders(Obj->getHeader64());
394     W.printHex("Reserved", Obj->getHeader64().reserved);
395   }
396 }
397 
398 template<class MachHeader>
399 void MachODumper::printFileHeaders(const MachHeader &Header) {
400   W.printEnum("Magic", Header.magic, makeArrayRef(MachOMagics));
401   W.printEnum("CpuType", Header.cputype, makeArrayRef(MachOHeaderCpuTypes));
402   uint32_t subtype = Header.cpusubtype & ~MachO::CPU_SUBTYPE_MASK;
403   switch (Header.cputype) {
404   case MachO::CPU_TYPE_X86:
405     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX86));
406     break;
407   case MachO::CPU_TYPE_X86_64:
408     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX64));
409     break;
410   case MachO::CPU_TYPE_ARM:
411     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM));
412     break;
413   case MachO::CPU_TYPE_POWERPC:
414     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesPPC));
415     break;
416   case MachO::CPU_TYPE_SPARC:
417     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesSPARC));
418     break;
419   case MachO::CPU_TYPE_ARM64:
420     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM64));
421     break;
422   case MachO::CPU_TYPE_POWERPC64:
423   default:
424     W.printHex("CpuSubtype", subtype);
425   }
426   W.printEnum("FileType", Header.filetype, makeArrayRef(MachOHeaderFileTypes));
427   W.printNumber("NumOfLoadCommands", Header.ncmds);
428   W.printNumber("SizeOfLoadCommands", Header.sizeofcmds);
429   W.printFlags("Flags", Header.flags, makeArrayRef(MachOHeaderFlags));
430 }
431 
432 void MachODumper::printSections() {
433   return printSections(Obj);
434 }
435 
436 void MachODumper::printSections(const MachOObjectFile *Obj) {
437   ListScope Group(W, "Sections");
438 
439   int SectionIndex = -1;
440   for (const SectionRef &Section : Obj->sections()) {
441     ++SectionIndex;
442 
443     MachOSection MOSection;
444     getSection(Obj, Section.getRawDataRefImpl(), MOSection);
445     DataRefImpl DR = Section.getRawDataRefImpl();
446 
447     StringRef Name;
448     error(Section.getName(Name));
449 
450     ArrayRef<char> RawName = Obj->getSectionRawName(DR);
451     StringRef SegmentName = Obj->getSectionFinalSegmentName(DR);
452     ArrayRef<char> RawSegmentName = Obj->getSectionRawFinalSegmentName(DR);
453 
454     DictScope SectionD(W, "Section");
455     W.printNumber("Index", SectionIndex);
456     W.printBinary("Name", Name, RawName);
457     W.printBinary("Segment", SegmentName, RawSegmentName);
458     W.printHex("Address", MOSection.Address);
459     W.printHex("Size", MOSection.Size);
460     W.printNumber("Offset", MOSection.Offset);
461     W.printNumber("Alignment", MOSection.Alignment);
462     W.printHex("RelocationOffset", MOSection.RelocationTableOffset);
463     W.printNumber("RelocationCount", MOSection.NumRelocationTableEntries);
464     W.printEnum("Type", MOSection.Flags & 0xFF,
465                 makeArrayRef(MachOSectionAttributes));
466     W.printFlags("Attributes", MOSection.Flags >> 8,
467                  makeArrayRef(MachOSectionAttributes));
468     W.printHex("Reserved1", MOSection.Reserved1);
469     W.printHex("Reserved2", MOSection.Reserved2);
470     if (Obj->is64Bit())
471       W.printHex("Reserved3", MOSection.Reserved3);
472 
473     if (opts::SectionRelocations) {
474       ListScope D(W, "Relocations");
475       for (const RelocationRef &Reloc : Section.relocations())
476         printRelocation(Reloc);
477     }
478 
479     if (opts::SectionSymbols) {
480       ListScope D(W, "Symbols");
481       for (const SymbolRef &Symbol : Obj->symbols()) {
482         if (!Section.containsSymbol(Symbol))
483           continue;
484 
485         printSymbol(Symbol);
486       }
487     }
488 
489     if (opts::SectionData) {
490       bool IsBSS = Section.isBSS();
491       if (!IsBSS) {
492         StringRef Data;
493         error(Section.getContents(Data));
494 
495         W.printBinaryBlock("SectionData", Data);
496       }
497     }
498   }
499 }
500 
501 void MachODumper::printRelocations() {
502   ListScope D(W, "Relocations");
503 
504   std::error_code EC;
505   for (const SectionRef &Section : Obj->sections()) {
506     StringRef Name;
507     error(Section.getName(Name));
508 
509     bool PrintedGroup = false;
510     for (const RelocationRef &Reloc : Section.relocations()) {
511       if (!PrintedGroup) {
512         W.startLine() << "Section " << Name << " {\n";
513         W.indent();
514         PrintedGroup = true;
515       }
516 
517       printRelocation(Reloc);
518     }
519 
520     if (PrintedGroup) {
521       W.unindent();
522       W.startLine() << "}\n";
523     }
524   }
525 }
526 
527 void MachODumper::printRelocation(const RelocationRef &Reloc) {
528   return printRelocation(Obj, Reloc);
529 }
530 
531 void MachODumper::printRelocation(const MachOObjectFile *Obj,
532                                   const RelocationRef &Reloc) {
533   uint64_t Offset = Reloc.getOffset();
534   SmallString<32> RelocName;
535   Reloc.getTypeName(RelocName);
536 
537   DataRefImpl DR = Reloc.getRawDataRefImpl();
538   MachO::any_relocation_info RE = Obj->getRelocation(DR);
539   bool IsScattered = Obj->isRelocationScattered(RE);
540   bool IsExtern = !IsScattered && Obj->getPlainRelocationExternal(RE);
541 
542   StringRef TargetName;
543   if (IsExtern) {
544     symbol_iterator Symbol = Reloc.getSymbol();
545     if (Symbol != Obj->symbol_end()) {
546       Expected<StringRef> TargetNameOrErr = Symbol->getName();
547       if (!TargetNameOrErr)
548         error(errorToErrorCode(TargetNameOrErr.takeError()));
549       TargetName = *TargetNameOrErr;
550     }
551   } else if (!IsScattered) {
552     section_iterator SecI = Obj->getRelocationSection(DR);
553     if (SecI != Obj->section_end()) {
554       error(SecI->getName(TargetName));
555     }
556   }
557   if (TargetName.empty())
558     TargetName = "-";
559 
560   if (opts::ExpandRelocs) {
561     DictScope Group(W, "Relocation");
562     W.printHex("Offset", Offset);
563     W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE));
564     W.printNumber("Length", Obj->getAnyRelocationLength(RE));
565     W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE));
566     if (IsScattered) {
567       W.printHex("Value", Obj->getScatteredRelocationValue(RE));
568     } else {
569       const char *Kind = IsExtern ? "Symbol" : "Section";
570       W.printNumber(Kind, TargetName, Obj->getPlainRelocationSymbolNum(RE));
571     }
572   } else {
573     SmallString<32> SymbolNameOrOffset("0x");
574     if (IsScattered) {
575       // Scattered relocations don't really have an associated symbol for some
576       // reason, even if one exists in the symtab at the correct address.
577       SymbolNameOrOffset += utohexstr(Obj->getScatteredRelocationValue(RE));
578     } else {
579       SymbolNameOrOffset = TargetName;
580     }
581 
582     raw_ostream& OS = W.startLine();
583     OS << W.hex(Offset)
584        << " " << Obj->getAnyRelocationPCRel(RE)
585        << " " << Obj->getAnyRelocationLength(RE);
586     if (IsScattered)
587       OS << " n/a";
588     else
589       OS << " " << Obj->getPlainRelocationExternal(RE);
590     OS << " " << RelocName
591        << " " << IsScattered
592        << " " << SymbolNameOrOffset
593        << "\n";
594   }
595 }
596 
597 void MachODumper::printSymbols() {
598   ListScope Group(W, "Symbols");
599 
600   for (const SymbolRef &Symbol : Obj->symbols()) {
601     printSymbol(Symbol);
602   }
603 }
604 
605 void MachODumper::printDynamicSymbols() {
606   ListScope Group(W, "DynamicSymbols");
607 }
608 
609 void MachODumper::printSymbol(const SymbolRef &Symbol) {
610   StringRef SymbolName;
611   Expected<StringRef> SymbolNameOrErr = Symbol.getName();
612   if (!SymbolNameOrErr) {
613     // TODO: Actually report errors helpfully.
614     consumeError(SymbolNameOrErr.takeError());
615   } else
616     SymbolName = *SymbolNameOrErr;
617 
618   MachOSymbol MOSymbol;
619   getSymbol(Obj, Symbol.getRawDataRefImpl(), MOSymbol);
620 
621   StringRef SectionName = "";
622   Expected<section_iterator> SecIOrErr = Symbol.getSection();
623   error(errorToErrorCode(SecIOrErr.takeError()));
624   section_iterator SecI = *SecIOrErr;
625   if (SecI != Obj->section_end())
626     error(SecI->getName(SectionName));
627 
628   DictScope D(W, "Symbol");
629   W.printNumber("Name", SymbolName, MOSymbol.StringIndex);
630   if (MOSymbol.Type & MachO::N_STAB) {
631     W.printHex("Type", "SymDebugTable", MOSymbol.Type);
632   } else {
633     if (MOSymbol.Type & MachO::N_PEXT)
634       W.startLine() << "PrivateExtern\n";
635     if (MOSymbol.Type & MachO::N_EXT)
636       W.startLine() << "Extern\n";
637     W.printEnum("Type", uint8_t(MOSymbol.Type & MachO::N_TYPE),
638                 makeArrayRef(MachOSymbolTypes));
639   }
640   W.printHex("Section", SectionName, MOSymbol.SectionIndex);
641   W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0xF),
642               makeArrayRef(MachOSymbolRefTypes));
643   W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0xF),
644                makeArrayRef(MachOSymbolFlags));
645   W.printHex("Value", MOSymbol.Value);
646 }
647 
648 void MachODumper::printUnwindInfo() {
649   W.startLine() << "UnwindInfo not implemented.\n";
650 }
651 
652 void MachODumper::printStackMap() const {
653   object::SectionRef StackMapSection;
654   for (auto Sec : Obj->sections()) {
655     StringRef Name;
656     Sec.getName(Name);
657     if (Name == "__llvm_stackmaps") {
658       StackMapSection = Sec;
659       break;
660     }
661   }
662 
663   if (StackMapSection == object::SectionRef())
664     return;
665 
666   StringRef StackMapContents;
667   StackMapSection.getContents(StackMapContents);
668   ArrayRef<uint8_t> StackMapContentsArray(
669       reinterpret_cast<const uint8_t*>(StackMapContents.data()),
670       StackMapContents.size());
671 
672   if (Obj->isLittleEndian())
673     prettyPrintStackMap(
674         W, StackMapV2Parser<support::little>(StackMapContentsArray));
675   else
676     prettyPrintStackMap(W,
677                         StackMapV2Parser<support::big>(StackMapContentsArray));
678 }
679 
680 void MachODumper::printSectionAsHex(StringRef SectionName) {
681   char *StrPtr;
682   long SectionIndex = strtol(SectionName.data(), &StrPtr, 10);
683   SectionRef SecTmp;
684   const SectionRef *Sec = &SecTmp;
685   if (*StrPtr)
686     SecTmp = unwrapOrError(Obj->getSection(SectionName));
687   else
688     SecTmp = unwrapOrError(Obj->getSection((unsigned int)SectionIndex));
689 
690   StringRef SecName;
691   error(Sec->getName(SecName));
692 
693   StringRef Data;
694   error(Sec->getContents(Data));
695   const uint8_t *SecContent = reinterpret_cast<const uint8_t *>(Data.data());
696 
697   SectionHexDump(SecName, SecContent, Data.size());
698 }
699 
700 void MachODumper::printNeededLibraries() {
701   ListScope D(W, "NeededLibraries");
702 
703   using LibsTy = std::vector<StringRef>;
704   LibsTy Libs;
705 
706   for (const auto &Command : Obj->load_commands()) {
707     if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
708         Command.C.cmd == MachO::LC_ID_DYLIB ||
709         Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
710         Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
711         Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
712         Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
713       MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
714       if (Dl.dylib.name < Dl.cmdsize) {
715         auto *P = static_cast<const char*>(Command.Ptr) + Dl.dylib.name;
716         Libs.push_back(P);
717       }
718     }
719   }
720 
721   std::stable_sort(Libs.begin(), Libs.end());
722 
723   for (const auto &L : Libs) {
724     outs() << "  " << L << "\n";
725   }
726 }
727 
728 void MachODumper::printMachODataInCode() {
729   for (const auto &Load : Obj->load_commands()) {
730     if (Load.C.cmd  == MachO::LC_DATA_IN_CODE) {
731       MachO::linkedit_data_command LLC = Obj->getLinkeditDataLoadCommand(Load);
732       DictScope Group(W, "DataInCode");
733       W.printNumber("Data offset", LLC.dataoff);
734       W.printNumber("Data size", LLC.datasize);
735       ListScope D(W, "Data entries");
736       unsigned NumRegions = LLC.datasize / sizeof(MachO::data_in_code_entry);
737       for (unsigned i = 0; i < NumRegions; ++i) {
738         MachO::data_in_code_entry DICE = Obj->getDataInCodeTableEntry(
739                                                               LLC.dataoff, i);
740         DictScope Group(W, "Entry");
741         W.printNumber("Index", i);
742         W.printNumber("Offset", DICE.offset);
743         W.printNumber("Length", DICE.length);
744         W.printNumber("Kind", DICE.kind);
745       }
746     }
747   }
748 }
749 
750 void MachODumper::printMachOVersionMin() {
751   for (const auto &Load : Obj->load_commands()) {
752     StringRef Cmd;
753     switch (Load.C.cmd) {
754     case MachO::LC_VERSION_MIN_MACOSX:
755       Cmd = "LC_VERSION_MIN_MACOSX";
756       break;
757     case MachO::LC_VERSION_MIN_IPHONEOS:
758       Cmd = "LC_VERSION_MIN_IPHONEOS";
759       break;
760     case MachO::LC_VERSION_MIN_TVOS:
761       Cmd = "LC_VERSION_MIN_TVOS";
762       break;
763     case MachO::LC_VERSION_MIN_WATCHOS:
764       Cmd = "LC_VERSION_MIN_WATCHOS";
765       break;
766     case MachO::LC_BUILD_VERSION:
767       Cmd = "LC_BUILD_VERSION";
768       break;
769     default:
770       continue;
771     }
772 
773     DictScope Group(W, "MinVersion");
774     // Handle LC_BUILD_VERSION.
775     if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
776       MachO::build_version_command BVC = Obj->getBuildVersionLoadCommand(Load);
777       W.printString("Cmd", Cmd);
778       W.printNumber("Size", BVC.cmdsize);
779       W.printString("Platform",
780                     MachOObjectFile::getBuildPlatform(BVC.platform));
781       W.printString("Version", MachOObjectFile::getVersionString(BVC.minos));
782       if (BVC.sdk)
783         W.printString("SDK", MachOObjectFile::getVersionString(BVC.sdk));
784       else
785         W.printString("SDK", StringRef("n/a"));
786       continue;
787     }
788 
789     MachO::version_min_command VMC = Obj->getVersionMinLoadCommand(Load);
790     W.printString("Cmd", Cmd);
791     W.printNumber("Size", VMC.cmdsize);
792     SmallString<32> Version;
793     Version = utostr(MachOObjectFile::getVersionMinMajor(VMC, false)) + "." +
794               utostr(MachOObjectFile::getVersionMinMinor(VMC, false));
795     uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, false);
796     if (Update != 0)
797       Version += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, false));
798     W.printString("Version", Version);
799     SmallString<32> SDK;
800     if (VMC.sdk == 0)
801       SDK = "n/a";
802     else {
803       SDK = utostr(MachOObjectFile::getVersionMinMajor(VMC, true)) + "." +
804             utostr(MachOObjectFile::getVersionMinMinor(VMC, true));
805       uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, true);
806       if (Update != 0)
807         SDK += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, true));
808     }
809     W.printString("SDK", SDK);
810   }
811 }
812 
813 void MachODumper::printMachODysymtab() {
814   for (const auto &Load : Obj->load_commands()) {
815     if (Load.C.cmd == MachO::LC_DYSYMTAB) {
816       MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand();
817       DictScope Group(W, "Dysymtab");
818       W.printNumber("ilocalsym", DLC.ilocalsym);
819       W.printNumber("nlocalsym", DLC.nlocalsym);
820       W.printNumber("iextdefsym", DLC.iextdefsym);
821       W.printNumber("nextdefsym", DLC.nextdefsym);
822       W.printNumber("iundefsym", DLC.iundefsym);
823       W.printNumber("nundefsym", DLC.nundefsym);
824       W.printNumber("tocoff", DLC.tocoff);
825       W.printNumber("ntoc", DLC.ntoc);
826       W.printNumber("modtaboff", DLC.modtaboff);
827       W.printNumber("nmodtab", DLC.nmodtab);
828       W.printNumber("extrefsymoff", DLC.extrefsymoff);
829       W.printNumber("nextrefsyms", DLC.nextrefsyms);
830       W.printNumber("indirectsymoff", DLC.indirectsymoff);
831       W.printNumber("nindirectsyms", DLC.nindirectsyms);
832       W.printNumber("extreloff", DLC.extreloff);
833       W.printNumber("nextrel", DLC.nextrel);
834       W.printNumber("locreloff", DLC.locreloff);
835       W.printNumber("nlocrel", DLC.nlocrel);
836     }
837   }
838 }
839 
840 void MachODumper::printMachOSegment() {
841   for (const auto &Load : Obj->load_commands()) {
842     if (Load.C.cmd == MachO::LC_SEGMENT || Load.C.cmd == MachO::LC_SEGMENT_64) {
843       MachOSegment MOSegment;
844       getSegment(Obj, Load, MOSegment);
845       DictScope Group(W, "Segment");
846       W.printString("Cmd", MOSegment.CmdName);
847       W.printString("Name", MOSegment.SegName);
848       W.printNumber("Size", MOSegment.cmdsize);
849       W.printHex("vmaddr", MOSegment.vmaddr);
850       W.printHex("vmsize", MOSegment.vmsize);
851       W.printNumber("fileoff", MOSegment.fileoff);
852       W.printNumber("filesize", MOSegment.filesize);
853       W.printString("maxprot", getMask(MOSegment.maxprot));
854       W.printString("initprot", getMask(MOSegment.initprot));
855       W.printNumber("nsects", MOSegment.nsects);
856       W.printHex("flags", MOSegment.flags);
857     }
858   }
859 }
860 
861 void MachODumper::printMachOIndirectSymbols() {
862   for (const auto &Load : Obj->load_commands()) {
863     if (Load.C.cmd == MachO::LC_DYSYMTAB) {
864       MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand();
865       DictScope Group(W, "Indirect Symbols");
866       W.printNumber("Number", DLC.nindirectsyms);
867       ListScope D(W, "Symbols");
868       for (unsigned i = 0; i < DLC.nindirectsyms; ++i) {
869         DictScope Group(W, "Entry");
870         W.printNumber("Entry Index", i);
871         W.printHex("Symbol Index", Obj->getIndirectSymbolTableEntry(DLC, i));
872       }
873     }
874   }
875 }
876 
877 void MachODumper::printMachOLinkerOptions() {
878   for (const auto &Load : Obj->load_commands()) {
879     if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
880       MachO::linker_option_command LOLC = Obj->getLinkerOptionLoadCommand(Load);
881       DictScope Group(W, "Linker Options");
882       W.printNumber("Size", LOLC.cmdsize);
883       ListScope D(W, "Strings");
884       uint64_t DataSize = LOLC.cmdsize - sizeof(MachO::linker_option_command);
885       const char *P = Load.Ptr + sizeof(MachO::linker_option_command);
886       StringRef Data(P, DataSize);
887       for (unsigned i = 0; i < LOLC.count; ++i) {
888         std::pair<StringRef,StringRef> Split = Data.split('\0');
889         W.printString("Value", Split.first);
890         Data = Split.second;
891       }
892     }
893   }
894 }
895