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