57db9ed7b2d87b5404e6cd555af7646dab73a53c
[oota-llvm.git] / tools / llvm-readobj / MachODumper.cpp
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 "llvm-readobj.h"
15 #include "Error.h"
16 #include "ObjDumper.h"
17 #include "StackMapPrinter.h"
18 #include "StreamWriter.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/Object/MachO.h"
22 #include "llvm/Support/Casting.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, StreamWriter& Writer)
32     : ObjDumper(Writer)
33     , Obj(Obj) { }
34
35   void printFileHeaders() override;
36   void printSections() override;
37   void printRelocations() override;
38   void printSymbols() override;
39   void printDynamicSymbols() override;
40   void printUnwindInfo() override;
41   void printStackMap() const override;
42
43   // MachO-specific.
44   void printMachODataInCode() override;
45   void printMachOVersionMin() override;
46
47 private:
48   template<class MachHeader>
49   void printFileHeaders(const MachHeader &Header);
50
51   void printSymbol(const SymbolRef &Symbol);
52
53   void printRelocation(const RelocationRef &Reloc);
54
55   void printRelocation(const MachOObjectFile *Obj, const RelocationRef &Reloc);
56
57   void printSections(const MachOObjectFile *Obj);
58
59   const MachOObjectFile *Obj;
60 };
61
62 } // namespace
63
64
65 namespace llvm {
66
67 std::error_code createMachODumper(const object::ObjectFile *Obj,
68                                   StreamWriter &Writer,
69                                   std::unique_ptr<ObjDumper> &Result) {
70   const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(Obj);
71   if (!MachOObj)
72     return readobj_error::unsupported_obj_file_format;
73
74   Result.reset(new MachODumper(MachOObj, Writer));
75   return readobj_error::success;
76 }
77
78 } // namespace llvm
79
80 static const EnumEntry<uint32_t> MachOMagics[] = {
81   { "Magic",      MachO::MH_MAGIC    },
82   { "Cigam",      MachO::MH_CIGAM    },
83   { "Magic64",    MachO::MH_MAGIC_64 },
84   { "Cigam64",    MachO::MH_CIGAM_64 },
85   { "FatMagic",   MachO::FAT_MAGIC   },
86   { "FatCigam",   MachO::FAT_CIGAM   },
87 };
88
89 static const EnumEntry<uint32_t> MachOHeaderFileTypes[] = {
90   { "Relocatable",          MachO::MH_OBJECT      },
91   { "Executable",           MachO::MH_EXECUTE     },
92   { "FixedVMLibrary",       MachO::MH_FVMLIB      },
93   { "Core",                 MachO::MH_CORE        },
94   { "PreloadedExecutable",  MachO::MH_PRELOAD     },
95   { "DynamicLibrary",       MachO::MH_DYLIB       },
96   { "DynamicLinker",        MachO::MH_DYLINKER    },
97   { "Bundle",               MachO::MH_BUNDLE      },
98   { "DynamicLibraryStub",   MachO::MH_DYLIB_STUB  },
99   { "DWARFSymbol",          MachO::MH_DSYM        },
100   { "KextBundle",           MachO::MH_KEXT_BUNDLE },
101 };
102
103 static const EnumEntry<uint32_t> MachOHeaderCpuTypes[] = {
104   { "Any"       , static_cast<uint32_t>(MachO::CPU_TYPE_ANY) },
105   { "X86"       , MachO::CPU_TYPE_X86       },
106   { "X86-64"    , MachO::CPU_TYPE_X86_64    },
107   { "Mc98000"   , MachO::CPU_TYPE_MC98000   },
108   { "Arm"       , MachO::CPU_TYPE_ARM       },
109   { "Arm64"     , MachO::CPU_TYPE_ARM64     },
110   { "Sparc"     , MachO::CPU_TYPE_SPARC     },
111   { "PowerPC"   , MachO::CPU_TYPE_POWERPC   },
112   { "PowerPC64" , MachO::CPU_TYPE_POWERPC64 },
113 };
114
115 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX86[] = {
116   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_I386_ALL),
117   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_386),
118   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486),
119   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486SX),
120   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_586),
121   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTPRO),
122   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M3),
123   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M5),
124   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON),
125   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON_MOBILE),
126   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3),
127   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_M),
128   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_XEON),
129   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_M),
130   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4),
131   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4_M),
132   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM),
133   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM_2),
134   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON),
135   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON_MP),
136 };
137
138 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesX64[] = {
139   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_ALL),
140   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_ARCH1),
141   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_H),
142 };
143
144 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM[] = {
145   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_ALL),
146   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V4T),
147   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6),
148   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5),
149   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5TEJ),
150   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_XSCALE),
151   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7),
152   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7S),
153   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7K),
154   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6M),
155   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7M),
156   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7EM),
157 };
158
159 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesARM64[] = {
160   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_ALL),
161 };
162
163 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesSPARC[] = {
164   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_SPARC_ALL),
165 };
166
167 static const EnumEntry<uint32_t> MachOHeaderCpuSubtypesPPC[] = {
168   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_ALL),
169   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_601),
170   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_602),
171   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603),
172   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603e),
173   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603ev),
174   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604),
175   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604e),
176   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_620),
177   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_750),
178   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7400),
179   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7450),
180   LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_970),
181 };
182
183 static const EnumEntry<uint32_t> MachOHeaderFlags[] = {
184   LLVM_READOBJ_ENUM_ENT(MachO, MH_NOUNDEFS),
185   LLVM_READOBJ_ENUM_ENT(MachO, MH_INCRLINK),
186   LLVM_READOBJ_ENUM_ENT(MachO, MH_DYLDLINK),
187   LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDATLOAD),
188   LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBOUND),
189   LLVM_READOBJ_ENUM_ENT(MachO, MH_SPLIT_SEGS),
190   LLVM_READOBJ_ENUM_ENT(MachO, MH_LAZY_INIT),
191   LLVM_READOBJ_ENUM_ENT(MachO, MH_TWOLEVEL),
192   LLVM_READOBJ_ENUM_ENT(MachO, MH_FORCE_FLAT),
193   LLVM_READOBJ_ENUM_ENT(MachO, MH_NOMULTIDEFS),
194   LLVM_READOBJ_ENUM_ENT(MachO, MH_NOFIXPREBINDING),
195   LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBINDABLE),
196   LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLMODSBOUND),
197   LLVM_READOBJ_ENUM_ENT(MachO, MH_SUBSECTIONS_VIA_SYMBOLS),
198   LLVM_READOBJ_ENUM_ENT(MachO, MH_CANONICAL),
199   LLVM_READOBJ_ENUM_ENT(MachO, MH_WEAK_DEFINES),
200   LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDS_TO_WEAK),
201   LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLOW_STACK_EXECUTION),
202   LLVM_READOBJ_ENUM_ENT(MachO, MH_ROOT_SAFE),
203   LLVM_READOBJ_ENUM_ENT(MachO, MH_SETUID_SAFE),
204   LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_REEXPORTED_DYLIBS),
205   LLVM_READOBJ_ENUM_ENT(MachO, MH_PIE),
206   LLVM_READOBJ_ENUM_ENT(MachO, MH_DEAD_STRIPPABLE_DYLIB),
207   LLVM_READOBJ_ENUM_ENT(MachO, MH_HAS_TLV_DESCRIPTORS),
208   LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_HEAP_EXECUTION),
209   LLVM_READOBJ_ENUM_ENT(MachO, MH_APP_EXTENSION_SAFE),
210 };
211
212 static const EnumEntry<unsigned> MachOSectionAttributes[] = {
213   { "LocReloc"         , 1 <<  0 /*S_ATTR_LOC_RELOC          */ },
214   { "ExtReloc"         , 1 <<  1 /*S_ATTR_EXT_RELOC          */ },
215   { "SomeInstructions" , 1 <<  2 /*S_ATTR_SOME_INSTRUCTIONS  */ },
216   { "Debug"            , 1 << 17 /*S_ATTR_DEBUG              */ },
217   { "SelfModifyingCode", 1 << 18 /*S_ATTR_SELF_MODIFYING_CODE*/ },
218   { "LiveSupport"      , 1 << 19 /*S_ATTR_LIVE_SUPPORT       */ },
219   { "NoDeadStrip"      , 1 << 20 /*S_ATTR_NO_DEAD_STRIP      */ },
220   { "StripStaticSyms"  , 1 << 21 /*S_ATTR_STRIP_STATIC_SYMS  */ },
221   { "NoTOC"            , 1 << 22 /*S_ATTR_NO_TOC             */ },
222   { "PureInstructions" , 1 << 23 /*S_ATTR_PURE_INSTRUCTIONS  */ },
223 };
224
225 static const EnumEntry<unsigned> MachOSymbolRefTypes[] = {
226   { "UndefinedNonLazy",                     0 },
227   { "ReferenceFlagUndefinedLazy",           1 },
228   { "ReferenceFlagDefined",                 2 },
229   { "ReferenceFlagPrivateDefined",          3 },
230   { "ReferenceFlagPrivateUndefinedNonLazy", 4 },
231   { "ReferenceFlagPrivateUndefinedLazy",    5 }
232 };
233
234 static const EnumEntry<unsigned> MachOSymbolFlags[] = {
235   { "ReferencedDynamically", 0x10 },
236   { "NoDeadStrip",           0x20 },
237   { "WeakRef",               0x40 },
238   { "WeakDef",               0x80 }
239 };
240
241 static const EnumEntry<unsigned> MachOSymbolTypes[] = {
242   { "Undef",           0x0 },
243   { "Abs",             0x2 },
244   { "Indirect",        0xA },
245   { "PreboundUndef",   0xC },
246   { "Section",         0xE }
247 };
248
249 namespace {
250   struct MachOSection {
251     ArrayRef<char> Name;
252     ArrayRef<char> SegmentName;
253     uint64_t Address;
254     uint64_t Size;
255     uint32_t Offset;
256     uint32_t Alignment;
257     uint32_t RelocationTableOffset;
258     uint32_t NumRelocationTableEntries;
259     uint32_t Flags;
260     uint32_t Reserved1;
261     uint32_t Reserved2;
262   };
263
264   struct MachOSymbol {
265     uint32_t StringIndex;
266     uint8_t Type;
267     uint8_t SectionIndex;
268     uint16_t Flags;
269     uint64_t Value;
270   };
271 }
272
273 static void getSection(const MachOObjectFile *Obj,
274                        DataRefImpl Sec,
275                        MachOSection &Section) {
276   if (!Obj->is64Bit()) {
277     MachO::section Sect = Obj->getSection(Sec);
278     Section.Address     = Sect.addr;
279     Section.Size        = Sect.size;
280     Section.Offset      = Sect.offset;
281     Section.Alignment   = Sect.align;
282     Section.RelocationTableOffset = Sect.reloff;
283     Section.NumRelocationTableEntries = Sect.nreloc;
284     Section.Flags       = Sect.flags;
285     Section.Reserved1   = Sect.reserved1;
286     Section.Reserved2   = Sect.reserved2;
287     return;
288   }
289   MachO::section_64 Sect = Obj->getSection64(Sec);
290   Section.Address     = Sect.addr;
291   Section.Size        = Sect.size;
292   Section.Offset      = Sect.offset;
293   Section.Alignment   = Sect.align;
294   Section.RelocationTableOffset = Sect.reloff;
295   Section.NumRelocationTableEntries = Sect.nreloc;
296   Section.Flags       = Sect.flags;
297   Section.Reserved1   = Sect.reserved1;
298   Section.Reserved2   = Sect.reserved2;
299 }
300
301
302 static void getSymbol(const MachOObjectFile *Obj,
303                       DataRefImpl DRI,
304                       MachOSymbol &Symbol) {
305   if (!Obj->is64Bit()) {
306     MachO::nlist Entry = Obj->getSymbolTableEntry(DRI);
307     Symbol.StringIndex  = Entry.n_strx;
308     Symbol.Type         = Entry.n_type;
309     Symbol.SectionIndex = Entry.n_sect;
310     Symbol.Flags        = Entry.n_desc;
311     Symbol.Value        = Entry.n_value;
312     return;
313   }
314   MachO::nlist_64 Entry = Obj->getSymbol64TableEntry(DRI);
315   Symbol.StringIndex  = Entry.n_strx;
316   Symbol.Type         = Entry.n_type;
317   Symbol.SectionIndex = Entry.n_sect;
318   Symbol.Flags        = Entry.n_desc;
319   Symbol.Value        = Entry.n_value;
320 }
321
322 void MachODumper::printFileHeaders() {
323   DictScope H(W, "MachHeader");
324   if (!Obj->is64Bit()) {
325     printFileHeaders(Obj->getHeader());
326   } else {
327     printFileHeaders(Obj->getHeader64());
328     W.printHex("Reserved", Obj->getHeader64().reserved);
329   }
330 }
331
332 template<class MachHeader>
333 void MachODumper::printFileHeaders(const MachHeader &Header) {
334   W.printEnum("Magic", Header.magic, makeArrayRef(MachOMagics));
335   W.printEnum("CpuType", Header.cputype, makeArrayRef(MachOHeaderCpuTypes));
336   uint32_t subtype = Header.cpusubtype & ~MachO::CPU_SUBTYPE_MASK;
337   switch (Header.cputype) {
338   case MachO::CPU_TYPE_X86:
339     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX86));
340     break;
341   case MachO::CPU_TYPE_X86_64:
342     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX64));
343     break;
344   case MachO::CPU_TYPE_ARM:
345     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM));
346     break;
347   case MachO::CPU_TYPE_POWERPC:
348     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesPPC));
349     break;
350   case MachO::CPU_TYPE_SPARC:
351     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesSPARC));
352     break;
353   case MachO::CPU_TYPE_ARM64:
354     W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM64));
355     break;
356   case MachO::CPU_TYPE_POWERPC64:
357   default:
358     W.printHex("CpuSubtype", subtype);
359   }
360   W.printEnum("FileType", Header.filetype, makeArrayRef(MachOHeaderFileTypes));
361   W.printNumber("NumOfLoadCommands", Header.ncmds);
362   W.printNumber("SizeOfLoadCommands", Header.sizeofcmds);
363   W.printFlags("Flags", Header.flags, makeArrayRef(MachOHeaderFlags));
364 }
365
366 void MachODumper::printSections() {
367   return printSections(Obj);
368 }
369
370 void MachODumper::printSections(const MachOObjectFile *Obj) {
371   ListScope Group(W, "Sections");
372
373   int SectionIndex = -1;
374   for (const SectionRef &Section : Obj->sections()) {
375     ++SectionIndex;
376
377     MachOSection MOSection;
378     getSection(Obj, Section.getRawDataRefImpl(), MOSection);
379     DataRefImpl DR = Section.getRawDataRefImpl();
380
381     StringRef Name;
382     error(Section.getName(Name));
383
384     ArrayRef<char> RawName = Obj->getSectionRawName(DR);
385     StringRef SegmentName = Obj->getSectionFinalSegmentName(DR);
386     ArrayRef<char> RawSegmentName = Obj->getSectionRawFinalSegmentName(DR);
387
388     DictScope SectionD(W, "Section");
389     W.printNumber("Index", SectionIndex);
390     W.printBinary("Name", Name, RawName);
391     W.printBinary("Segment", SegmentName, RawSegmentName);
392     W.printHex("Address", MOSection.Address);
393     W.printHex("Size", MOSection.Size);
394     W.printNumber("Offset", MOSection.Offset);
395     W.printNumber("Alignment", MOSection.Alignment);
396     W.printHex("RelocationOffset", MOSection.RelocationTableOffset);
397     W.printNumber("RelocationCount", MOSection.NumRelocationTableEntries);
398     W.printEnum("Type", MOSection.Flags & 0xFF,
399                 makeArrayRef(MachOSectionAttributes));
400     W.printFlags("Attributes", MOSection.Flags >> 8,
401                  makeArrayRef(MachOSectionAttributes));
402     W.printHex("Reserved1", MOSection.Reserved1);
403     W.printHex("Reserved2", MOSection.Reserved2);
404
405     if (opts::SectionRelocations) {
406       ListScope D(W, "Relocations");
407       for (const RelocationRef &Reloc : Section.relocations())
408         printRelocation(Reloc);
409     }
410
411     if (opts::SectionSymbols) {
412       ListScope D(W, "Symbols");
413       for (const SymbolRef &Symbol : Obj->symbols()) {
414         if (!Section.containsSymbol(Symbol))
415           continue;
416
417         printSymbol(Symbol);
418       }
419     }
420
421     if (opts::SectionData) {
422       bool IsBSS = Section.isBSS();
423       if (!IsBSS) {
424         StringRef Data;
425         error(Section.getContents(Data));
426
427         W.printBinaryBlock("SectionData", Data);
428       }
429     }
430   }
431 }
432
433 void MachODumper::printRelocations() {
434   ListScope D(W, "Relocations");
435
436   std::error_code EC;
437   for (const SectionRef &Section : Obj->sections()) {
438     StringRef Name;
439     error(Section.getName(Name));
440
441     bool PrintedGroup = false;
442     for (const RelocationRef &Reloc : Section.relocations()) {
443       if (!PrintedGroup) {
444         W.startLine() << "Section " << Name << " {\n";
445         W.indent();
446         PrintedGroup = true;
447       }
448
449       printRelocation(Reloc);
450     }
451
452     if (PrintedGroup) {
453       W.unindent();
454       W.startLine() << "}\n";
455     }
456   }
457 }
458
459 void MachODumper::printRelocation(const RelocationRef &Reloc) {
460   return printRelocation(Obj, Reloc);
461 }
462
463 void MachODumper::printRelocation(const MachOObjectFile *Obj,
464                                   const RelocationRef &Reloc) {
465   uint64_t Offset = Reloc.getOffset();
466   SmallString<32> RelocName;
467   Reloc.getTypeName(RelocName);
468
469   DataRefImpl DR = Reloc.getRawDataRefImpl();
470   MachO::any_relocation_info RE = Obj->getRelocation(DR);
471   bool IsScattered = Obj->isRelocationScattered(RE);
472   bool IsExtern = !IsScattered && Obj->getPlainRelocationExternal(RE);
473
474   StringRef TargetName;
475   if (IsExtern) {
476     symbol_iterator Symbol = Reloc.getSymbol();
477     if (Symbol != Obj->symbol_end()) {
478       ErrorOr<StringRef> TargetNameOrErr = Symbol->getName();
479       error(TargetNameOrErr.getError());
480       TargetName = *TargetNameOrErr;
481     }
482   } else if (!IsScattered) {
483     section_iterator SecI = Obj->getRelocationSection(DR);
484     if (SecI != Obj->section_end()) {
485       error(SecI->getName(TargetName));
486     }
487   }
488   if (TargetName.empty())
489     TargetName = "-";
490
491   if (opts::ExpandRelocs) {
492     DictScope Group(W, "Relocation");
493     W.printHex("Offset", Offset);
494     W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE));
495     W.printNumber("Length", Obj->getAnyRelocationLength(RE));
496     W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE));
497     if (IsScattered) {
498       W.printHex("Value", Obj->getScatteredRelocationValue(RE));
499     } else {
500       const char *Kind = IsExtern ? "Symbol" : "Section";
501       W.printNumber(Kind, TargetName, Obj->getPlainRelocationSymbolNum(RE));
502     }
503   } else {
504     SmallString<32> SymbolNameOrOffset("0x");
505     if (IsScattered) {
506       // Scattered relocations don't really have an associated symbol for some
507       // reason, even if one exists in the symtab at the correct address.
508       SymbolNameOrOffset += utohexstr(Obj->getScatteredRelocationValue(RE));
509     } else {
510       SymbolNameOrOffset = TargetName;
511     }
512
513     raw_ostream& OS = W.startLine();
514     OS << W.hex(Offset)
515        << " " << Obj->getAnyRelocationPCRel(RE)
516        << " " << Obj->getAnyRelocationLength(RE);
517     if (IsScattered)
518       OS << " n/a";
519     else
520       OS << " " << Obj->getPlainRelocationExternal(RE);
521     OS << " " << RelocName
522        << " " << IsScattered
523        << " " << SymbolNameOrOffset
524        << "\n";
525   }
526 }
527
528 void MachODumper::printSymbols() {
529   ListScope Group(W, "Symbols");
530
531   for (const SymbolRef &Symbol : Obj->symbols()) {
532     printSymbol(Symbol);
533   }
534 }
535
536 void MachODumper::printDynamicSymbols() {
537   ListScope Group(W, "DynamicSymbols");
538 }
539
540 void MachODumper::printSymbol(const SymbolRef &Symbol) {
541   StringRef SymbolName;
542   if (ErrorOr<StringRef> SymbolNameOrErr = Symbol.getName())
543     SymbolName = *SymbolNameOrErr;
544
545   MachOSymbol MOSymbol;
546   getSymbol(Obj, Symbol.getRawDataRefImpl(), MOSymbol);
547
548   StringRef SectionName = "";
549   ErrorOr<section_iterator> SecIOrErr = Symbol.getSection();
550   error(SecIOrErr.getError());
551   section_iterator SecI = *SecIOrErr;
552   if (SecI != Obj->section_end())
553     error(SecI->getName(SectionName));
554
555   DictScope D(W, "Symbol");
556   W.printNumber("Name", SymbolName, MOSymbol.StringIndex);
557   if (MOSymbol.Type & MachO::N_STAB) {
558     W.printHex("Type", "SymDebugTable", MOSymbol.Type);
559   } else {
560     if (MOSymbol.Type & MachO::N_PEXT)
561       W.startLine() << "PrivateExtern\n";
562     if (MOSymbol.Type & MachO::N_EXT)
563       W.startLine() << "Extern\n";
564     W.printEnum("Type", uint8_t(MOSymbol.Type & MachO::N_TYPE),
565                 makeArrayRef(MachOSymbolTypes));
566   }
567   W.printHex("Section", SectionName, MOSymbol.SectionIndex);
568   W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0xF),
569               makeArrayRef(MachOSymbolRefTypes));
570   W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0xF),
571                makeArrayRef(MachOSymbolFlags));
572   W.printHex("Value", MOSymbol.Value);
573 }
574
575 void MachODumper::printUnwindInfo() {
576   W.startLine() << "UnwindInfo not implemented.\n";
577 }
578
579 void MachODumper::printStackMap() const {
580   object::SectionRef StackMapSection;
581   for (auto Sec : Obj->sections()) {
582     StringRef Name;
583     Sec.getName(Name);
584     if (Name == "__llvm_stackmaps") {
585       StackMapSection = Sec;
586       break;
587     }
588   }
589
590   if (StackMapSection == object::SectionRef())
591     return;
592
593   StringRef StackMapContents;
594   StackMapSection.getContents(StackMapContents);
595   ArrayRef<uint8_t> StackMapContentsArray(
596       reinterpret_cast<const uint8_t*>(StackMapContents.data()),
597       StackMapContents.size());
598
599   if (Obj->isLittleEndian())
600      prettyPrintStackMap(
601                       llvm::outs(),
602                       StackMapV1Parser<support::little>(StackMapContentsArray));
603   else
604      prettyPrintStackMap(llvm::outs(),
605                          StackMapV1Parser<support::big>(StackMapContentsArray));
606 }
607
608 void MachODumper::printMachODataInCode() {
609   for (const auto &Load : Obj->load_commands()) {
610     if (Load.C.cmd  == MachO::LC_DATA_IN_CODE) {
611       MachO::linkedit_data_command LLC = Obj->getLinkeditDataLoadCommand(Load);
612       DictScope Group(W, "DataInCode");
613       W.printNumber("Data offset", LLC.dataoff);
614       W.printNumber("Data size", LLC.datasize);
615       ListScope D(W, "Data entries");
616       unsigned NumRegions = LLC.datasize / sizeof(MachO::data_in_code_entry);
617       for (unsigned i = 0; i < NumRegions; ++i) {
618         MachO::data_in_code_entry DICE = Obj->getDataInCodeTableEntry(
619                                                               LLC.dataoff, i);
620         DictScope Group(W, "Entry");
621         W.printNumber("Index", i);
622         W.printNumber("Offset", DICE.offset);
623         W.printNumber("Length", DICE.length);
624         W.printNumber("Kind", DICE.kind);
625       }
626     }
627   }
628 }
629
630 void MachODumper::printMachOVersionMin() {
631   for (const auto &Load : Obj->load_commands()) {
632     if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
633         Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
634       MachO::version_min_command VMC = Obj->getVersionMinLoadCommand(Load);
635       DictScope Group(W, "MinVersion");
636       StringRef Cmd;
637       if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX)
638         Cmd = "LC_VERSION_MIN_MACOSX";
639       else
640         Cmd = "LC_VERSION_MIN_IPHONEOS";
641       W.printString("Cmd", Cmd);
642       W.printNumber("Size", VMC.cmdsize);
643       SmallString<32> Version;
644       Version = utostr(MachOObjectFile::getVersionMinMajor(VMC, false)) + "." +
645         utostr(MachOObjectFile::getVersionMinMinor(VMC, false));
646       uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, false);
647       if (Update != 0)
648         Version += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC,
649                                                                      false));
650       W.printString("Version", Version);
651       SmallString<32> SDK;
652       if (VMC.sdk == 0)
653         SDK = "n/a";
654       else {
655         SDK = utostr(MachOObjectFile::getVersionMinMajor(VMC, true)) + "." +
656           utostr(MachOObjectFile::getVersionMinMinor(VMC, true));
657         uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, true);
658         if (Update != 0)
659           SDK += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC,
660                                                                    true));
661       }
662       W.printString("SDK", SDK);
663     }
664   }
665 }