• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-objdump.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm-objdump.h"
15 #include "llvm-c/Disassembler.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/BinaryFormat/MachO.h"
20 #include "llvm/Config/config.h"
21 #include "llvm/DebugInfo/DIContext.h"
22 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
23 #include "llvm/Demangle/Demangle.h"
24 #include "llvm/MC/MCAsmInfo.h"
25 #include "llvm/MC/MCContext.h"
26 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCInstPrinter.h"
29 #include "llvm/MC/MCInstrDesc.h"
30 #include "llvm/MC/MCInstrInfo.h"
31 #include "llvm/MC/MCRegisterInfo.h"
32 #include "llvm/MC/MCSubtargetInfo.h"
33 #include "llvm/Object/MachO.h"
34 #include "llvm/Object/MachOUniversal.h"
35 #include "llvm/Support/Casting.h"
36 #include "llvm/Support/CommandLine.h"
37 #include "llvm/Support/Debug.h"
38 #include "llvm/Support/Endian.h"
39 #include "llvm/Support/Format.h"
40 #include "llvm/Support/FormattedStream.h"
41 #include "llvm/Support/GraphWriter.h"
42 #include "llvm/Support/LEB128.h"
43 #include "llvm/Support/MemoryBuffer.h"
44 #include "llvm/Support/TargetRegistry.h"
45 #include "llvm/Support/TargetSelect.h"
46 #include "llvm/Support/ToolOutputFile.h"
47 #include "llvm/Support/raw_ostream.h"
48 #include <algorithm>
49 #include <cstring>
50 #include <system_error>
51 
52 #ifdef HAVE_LIBXAR
53 extern "C" {
54 #include <xar/xar.h>
55 }
56 #endif
57 
58 using namespace llvm;
59 using namespace object;
60 
61 static cl::opt<bool>
62     UseDbg("g",
63            cl::desc("Print line information from debug info if available"));
64 
65 static cl::opt<std::string> DSYMFile("dsym",
66                                      cl::desc("Use .dSYM file for debug info"));
67 
68 static cl::opt<bool> FullLeadingAddr("full-leading-addr",
69                                      cl::desc("Print full leading address"));
70 
71 static cl::opt<bool> NoLeadingHeaders("no-leading-headers",
72                                       cl::desc("Print no leading headers"));
73 
74 cl::opt<bool> llvm::UniversalHeaders("universal-headers",
75                                      cl::desc("Print Mach-O universal headers "
76                                               "(requires -macho)"));
77 
78 cl::opt<bool>
79     ArchiveMemberOffsets("archive-member-offsets",
80                          cl::desc("Print the offset to each archive member for "
81                                   "Mach-O archives (requires -macho and "
82                                   "-archive-headers)"));
83 
84 cl::opt<bool>
85     llvm::IndirectSymbols("indirect-symbols",
86                           cl::desc("Print indirect symbol table for Mach-O "
87                                    "objects (requires -macho)"));
88 
89 cl::opt<bool>
90     llvm::DataInCode("data-in-code",
91                      cl::desc("Print the data in code table for Mach-O objects "
92                               "(requires -macho)"));
93 
94 cl::opt<bool>
95     llvm::LinkOptHints("link-opt-hints",
96                        cl::desc("Print the linker optimization hints for "
97                                 "Mach-O objects (requires -macho)"));
98 
99 cl::opt<bool>
100     llvm::InfoPlist("info-plist",
101                     cl::desc("Print the info plist section as strings for "
102                              "Mach-O objects (requires -macho)"));
103 
104 cl::opt<bool>
105     llvm::DylibsUsed("dylibs-used",
106                      cl::desc("Print the shared libraries used for linked "
107                               "Mach-O files (requires -macho)"));
108 
109 cl::opt<bool>
110     llvm::DylibId("dylib-id",
111                   cl::desc("Print the shared library's id for the dylib Mach-O "
112                            "file (requires -macho)"));
113 
114 cl::opt<bool>
115     llvm::NonVerbose("non-verbose",
116                      cl::desc("Print the info for Mach-O objects in "
117                               "non-verbose or numeric form (requires -macho)"));
118 
119 cl::opt<bool>
120     llvm::ObjcMetaData("objc-meta-data",
121                        cl::desc("Print the Objective-C runtime meta data for "
122                                 "Mach-O files (requires -macho)"));
123 
124 cl::opt<std::string> llvm::DisSymName(
125     "dis-symname",
126     cl::desc("disassemble just this symbol's instructions (requires -macho)"));
127 
128 static cl::opt<bool> NoSymbolicOperands(
129     "no-symbolic-operands",
130     cl::desc("do not symbolic operands when disassembling (requires -macho)"));
131 
132 static cl::list<std::string>
133     ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
134               cl::ZeroOrMore);
135 
136 bool ArchAll = false;
137 
138 static std::string ThumbTripleName;
139 
GetTarget(const MachOObjectFile * MachOObj,const char ** McpuDefault,const Target ** ThumbTarget)140 static const Target *GetTarget(const MachOObjectFile *MachOObj,
141                                const char **McpuDefault,
142                                const Target **ThumbTarget) {
143   // Figure out the target triple.
144   llvm::Triple TT(TripleName);
145   if (TripleName.empty()) {
146     TT = MachOObj->getArchTriple(McpuDefault);
147     TripleName = TT.str();
148   }
149 
150   if (TT.getArch() == Triple::arm) {
151     // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
152     // that support ARM are also capable of Thumb mode.
153     llvm::Triple ThumbTriple = TT;
154     std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
155     ThumbTriple.setArchName(ThumbName);
156     ThumbTripleName = ThumbTriple.str();
157   }
158 
159   // Get the target specific parser.
160   std::string Error;
161   const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
162   if (TheTarget && ThumbTripleName.empty())
163     return TheTarget;
164 
165   *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
166   if (*ThumbTarget)
167     return TheTarget;
168 
169   errs() << "llvm-objdump: error: unable to get target for '";
170   if (!TheTarget)
171     errs() << TripleName;
172   else
173     errs() << ThumbTripleName;
174   errs() << "', see --version and --triple.\n";
175   return nullptr;
176 }
177 
178 struct SymbolSorter {
operator ()SymbolSorter179   bool operator()(const SymbolRef &A, const SymbolRef &B) {
180     Expected<SymbolRef::Type> ATypeOrErr = A.getType();
181     if (!ATypeOrErr)
182       report_error(A.getObject()->getFileName(), ATypeOrErr.takeError());
183     SymbolRef::Type AType = *ATypeOrErr;
184     Expected<SymbolRef::Type> BTypeOrErr = B.getType();
185     if (!BTypeOrErr)
186       report_error(B.getObject()->getFileName(), BTypeOrErr.takeError());
187     SymbolRef::Type BType = *BTypeOrErr;
188     uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue();
189     uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue();
190     return AAddr < BAddr;
191   }
192 };
193 
194 // Types for the storted data in code table that is built before disassembly
195 // and the predicate function to sort them.
196 typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
197 typedef std::vector<DiceTableEntry> DiceTable;
198 typedef DiceTable::iterator dice_table_iterator;
199 
200 #ifdef HAVE_LIBXAR
201 namespace {
202 struct ScopedXarFile {
203   xar_t xar;
ScopedXarFile__anon33b510350111::ScopedXarFile204   ScopedXarFile(const char *filename, int32_t flags)
205       : xar(xar_open(filename, flags)) {}
~ScopedXarFile__anon33b510350111::ScopedXarFile206   ~ScopedXarFile() {
207     if (xar)
208       xar_close(xar);
209   }
210   ScopedXarFile(const ScopedXarFile &) = delete;
211   ScopedXarFile &operator=(const ScopedXarFile &) = delete;
operator xar_t__anon33b510350111::ScopedXarFile212   operator xar_t() { return xar; }
213 };
214 
215 struct ScopedXarIter {
216   xar_iter_t iter;
ScopedXarIter__anon33b510350111::ScopedXarIter217   ScopedXarIter() : iter(xar_iter_new()) {}
~ScopedXarIter__anon33b510350111::ScopedXarIter218   ~ScopedXarIter() {
219     if (iter)
220       xar_iter_free(iter);
221   }
222   ScopedXarIter(const ScopedXarIter &) = delete;
223   ScopedXarIter &operator=(const ScopedXarIter &) = delete;
operator xar_iter_t__anon33b510350111::ScopedXarIter224   operator xar_iter_t() { return iter; }
225 };
226 } // namespace
227 #endif // defined(HAVE_LIBXAR)
228 
229 // This is used to search for a data in code table entry for the PC being
230 // disassembled.  The j parameter has the PC in j.first.  A single data in code
231 // table entry can cover many bytes for each of its Kind's.  So if the offset,
232 // aka the i.first value, of the data in code table entry plus its Length
233 // covers the PC being searched for this will return true.  If not it will
234 // return false.
compareDiceTableEntries(const DiceTableEntry & i,const DiceTableEntry & j)235 static bool compareDiceTableEntries(const DiceTableEntry &i,
236                                     const DiceTableEntry &j) {
237   uint16_t Length;
238   i.second.getLength(Length);
239 
240   return j.first >= i.first && j.first < i.first + Length;
241 }
242 
DumpDataInCode(const uint8_t * bytes,uint64_t Length,unsigned short Kind)243 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
244                                unsigned short Kind) {
245   uint32_t Value, Size = 1;
246 
247   switch (Kind) {
248   default:
249   case MachO::DICE_KIND_DATA:
250     if (Length >= 4) {
251       if (!NoShowRawInsn)
252         dumpBytes(makeArrayRef(bytes, 4), outs());
253       Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
254       outs() << "\t.long " << Value;
255       Size = 4;
256     } else if (Length >= 2) {
257       if (!NoShowRawInsn)
258         dumpBytes(makeArrayRef(bytes, 2), outs());
259       Value = bytes[1] << 8 | bytes[0];
260       outs() << "\t.short " << Value;
261       Size = 2;
262     } else {
263       if (!NoShowRawInsn)
264         dumpBytes(makeArrayRef(bytes, 2), outs());
265       Value = bytes[0];
266       outs() << "\t.byte " << Value;
267       Size = 1;
268     }
269     if (Kind == MachO::DICE_KIND_DATA)
270       outs() << "\t@ KIND_DATA\n";
271     else
272       outs() << "\t@ data in code kind = " << Kind << "\n";
273     break;
274   case MachO::DICE_KIND_JUMP_TABLE8:
275     if (!NoShowRawInsn)
276       dumpBytes(makeArrayRef(bytes, 1), outs());
277     Value = bytes[0];
278     outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
279     Size = 1;
280     break;
281   case MachO::DICE_KIND_JUMP_TABLE16:
282     if (!NoShowRawInsn)
283       dumpBytes(makeArrayRef(bytes, 2), outs());
284     Value = bytes[1] << 8 | bytes[0];
285     outs() << "\t.short " << format("%5u", Value & 0xffff)
286            << "\t@ KIND_JUMP_TABLE16\n";
287     Size = 2;
288     break;
289   case MachO::DICE_KIND_JUMP_TABLE32:
290   case MachO::DICE_KIND_ABS_JUMP_TABLE32:
291     if (!NoShowRawInsn)
292       dumpBytes(makeArrayRef(bytes, 4), outs());
293     Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
294     outs() << "\t.long " << Value;
295     if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
296       outs() << "\t@ KIND_JUMP_TABLE32\n";
297     else
298       outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
299     Size = 4;
300     break;
301   }
302   return Size;
303 }
304 
getSectionsAndSymbols(MachOObjectFile * MachOObj,std::vector<SectionRef> & Sections,std::vector<SymbolRef> & Symbols,SmallVectorImpl<uint64_t> & FoundFns,uint64_t & BaseSegmentAddress)305 static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
306                                   std::vector<SectionRef> &Sections,
307                                   std::vector<SymbolRef> &Symbols,
308                                   SmallVectorImpl<uint64_t> &FoundFns,
309                                   uint64_t &BaseSegmentAddress) {
310   for (const SymbolRef &Symbol : MachOObj->symbols()) {
311     Expected<StringRef> SymName = Symbol.getName();
312     if (!SymName)
313       report_error(MachOObj->getFileName(), SymName.takeError());
314     if (!SymName->startswith("ltmp"))
315       Symbols.push_back(Symbol);
316   }
317 
318   for (const SectionRef &Section : MachOObj->sections()) {
319     StringRef SectName;
320     Section.getName(SectName);
321     Sections.push_back(Section);
322   }
323 
324   bool BaseSegmentAddressSet = false;
325   for (const auto &Command : MachOObj->load_commands()) {
326     if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
327       // We found a function starts segment, parse the addresses for later
328       // consumption.
329       MachO::linkedit_data_command LLC =
330           MachOObj->getLinkeditDataLoadCommand(Command);
331 
332       MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
333     } else if (Command.C.cmd == MachO::LC_SEGMENT) {
334       MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
335       StringRef SegName = SLC.segname;
336       if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
337         BaseSegmentAddressSet = true;
338         BaseSegmentAddress = SLC.vmaddr;
339       }
340     }
341   }
342 }
343 
PrintIndirectSymbolTable(MachOObjectFile * O,bool verbose,uint32_t n,uint32_t count,uint32_t stride,uint64_t addr)344 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
345                                      uint32_t n, uint32_t count,
346                                      uint32_t stride, uint64_t addr) {
347   MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
348   uint32_t nindirectsyms = Dysymtab.nindirectsyms;
349   if (n > nindirectsyms)
350     outs() << " (entries start past the end of the indirect symbol "
351               "table) (reserved1 field greater than the table size)";
352   else if (n + count > nindirectsyms)
353     outs() << " (entries extends past the end of the indirect symbol "
354               "table)";
355   outs() << "\n";
356   uint32_t cputype = O->getHeader().cputype;
357   if (cputype & MachO::CPU_ARCH_ABI64)
358     outs() << "address            index";
359   else
360     outs() << "address    index";
361   if (verbose)
362     outs() << " name\n";
363   else
364     outs() << "\n";
365   for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
366     if (cputype & MachO::CPU_ARCH_ABI64)
367       outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
368     else
369       outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
370     MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
371     uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
372     if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
373       outs() << "LOCAL\n";
374       continue;
375     }
376     if (indirect_symbol ==
377         (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
378       outs() << "LOCAL ABSOLUTE\n";
379       continue;
380     }
381     if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
382       outs() << "ABSOLUTE\n";
383       continue;
384     }
385     outs() << format("%5u ", indirect_symbol);
386     if (verbose) {
387       MachO::symtab_command Symtab = O->getSymtabLoadCommand();
388       if (indirect_symbol < Symtab.nsyms) {
389         symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
390         SymbolRef Symbol = *Sym;
391         Expected<StringRef> SymName = Symbol.getName();
392         if (!SymName)
393           report_error(O->getFileName(), SymName.takeError());
394         outs() << *SymName;
395       } else {
396         outs() << "?";
397       }
398     }
399     outs() << "\n";
400   }
401 }
402 
PrintIndirectSymbols(MachOObjectFile * O,bool verbose)403 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
404   for (const auto &Load : O->load_commands()) {
405     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
406       MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
407       for (unsigned J = 0; J < Seg.nsects; ++J) {
408         MachO::section_64 Sec = O->getSection64(Load, J);
409         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
410         if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
411             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
412             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
413             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
414             section_type == MachO::S_SYMBOL_STUBS) {
415           uint32_t stride;
416           if (section_type == MachO::S_SYMBOL_STUBS)
417             stride = Sec.reserved2;
418           else
419             stride = 8;
420           if (stride == 0) {
421             outs() << "Can't print indirect symbols for (" << Sec.segname << ","
422                    << Sec.sectname << ") "
423                    << "(size of stubs in reserved2 field is zero)\n";
424             continue;
425           }
426           uint32_t count = Sec.size / stride;
427           outs() << "Indirect symbols for (" << Sec.segname << ","
428                  << Sec.sectname << ") " << count << " entries";
429           uint32_t n = Sec.reserved1;
430           PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
431         }
432       }
433     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
434       MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
435       for (unsigned J = 0; J < Seg.nsects; ++J) {
436         MachO::section Sec = O->getSection(Load, J);
437         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
438         if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
439             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
440             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
441             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
442             section_type == MachO::S_SYMBOL_STUBS) {
443           uint32_t stride;
444           if (section_type == MachO::S_SYMBOL_STUBS)
445             stride = Sec.reserved2;
446           else
447             stride = 4;
448           if (stride == 0) {
449             outs() << "Can't print indirect symbols for (" << Sec.segname << ","
450                    << Sec.sectname << ") "
451                    << "(size of stubs in reserved2 field is zero)\n";
452             continue;
453           }
454           uint32_t count = Sec.size / stride;
455           outs() << "Indirect symbols for (" << Sec.segname << ","
456                  << Sec.sectname << ") " << count << " entries";
457           uint32_t n = Sec.reserved1;
458           PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
459         }
460       }
461     }
462   }
463 }
464 
PrintRType(const uint64_t cputype,const unsigned r_type)465 static void PrintRType(const uint64_t cputype, const unsigned r_type) {
466   static char const *generic_r_types[] = {
467     "VANILLA ", "PAIR    ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV     ",
468     "  6 (?) ", "  7 (?) ", "  8 (?) ", "  9 (?) ", " 10 (?) ", " 11 (?) ",
469     " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
470   };
471   static char const *x86_64_r_types[] = {
472     "UNSIGND ", "SIGNED  ", "BRANCH  ", "GOT_LD  ", "GOT     ", "SUB     ",
473     "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV     ", " 10 (?) ", " 11 (?) ",
474     " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
475   };
476   static char const *arm_r_types[] = {
477     "VANILLA ", "PAIR    ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ",
478     "BR24    ", "T_BR22  ", "T_BR32  ", "HALF    ", "HALFDIF ",
479     " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
480   };
481   static char const *arm64_r_types[] = {
482     "UNSIGND ", "SUB     ", "BR26    ", "PAGE21  ", "PAGOF12 ",
483     "GOTLDP  ", "GOTLDPOF", "PTRTGOT ", "TLVLDP  ", "TLVLDPOF",
484     "ADDEND  ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
485   };
486 
487   if (r_type > 0xf){
488     outs() << format("%-7u", r_type) << " ";
489     return;
490   }
491   switch (cputype) {
492     case MachO::CPU_TYPE_I386:
493       outs() << generic_r_types[r_type];
494       break;
495     case MachO::CPU_TYPE_X86_64:
496       outs() << x86_64_r_types[r_type];
497       break;
498     case MachO::CPU_TYPE_ARM:
499       outs() << arm_r_types[r_type];
500       break;
501     case MachO::CPU_TYPE_ARM64:
502       outs() << arm64_r_types[r_type];
503       break;
504     default:
505       outs() << format("%-7u ", r_type);
506   }
507 }
508 
PrintRLength(const uint64_t cputype,const unsigned r_type,const unsigned r_length,const bool previous_arm_half)509 static void PrintRLength(const uint64_t cputype, const unsigned r_type,
510                          const unsigned r_length, const bool previous_arm_half){
511   if (cputype == MachO::CPU_TYPE_ARM &&
512       (r_type == llvm::MachO::ARM_RELOC_HALF ||
513        r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF ||
514        previous_arm_half == true)) {
515     if ((r_length & 0x1) == 0)
516       outs() << "lo/";
517     else
518       outs() << "hi/";
519     if ((r_length & 0x1) == 0)
520       outs() << "arm ";
521     else
522       outs() << "thm ";
523   } else {
524     switch (r_length) {
525       case 0:
526         outs() << "byte   ";
527         break;
528       case 1:
529         outs() << "word   ";
530         break;
531       case 2:
532         outs() << "long   ";
533         break;
534       case 3:
535         if (cputype == MachO::CPU_TYPE_X86_64)
536           outs() << "quad   ";
537         else
538           outs() << format("?(%2d)  ", r_length);
539         break;
540       default:
541         outs() << format("?(%2d)  ", r_length);
542     }
543   }
544 }
545 
PrintRelocationEntries(const MachOObjectFile * O,const relocation_iterator Begin,const relocation_iterator End,const uint64_t cputype,const bool verbose)546 static void PrintRelocationEntries(const MachOObjectFile *O,
547                                    const relocation_iterator Begin,
548                                    const relocation_iterator End,
549                                    const uint64_t cputype,
550                                    const bool verbose) {
551   const MachO::symtab_command Symtab = O->getSymtabLoadCommand();
552   bool previous_arm_half = false;
553   bool previous_sectdiff = false;
554   uint32_t sectdiff_r_type = 0;
555 
556   for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) {
557     const DataRefImpl Rel = Reloc->getRawDataRefImpl();
558     const MachO::any_relocation_info RE = O->getRelocation(Rel);
559     const unsigned r_type = O->getAnyRelocationType(RE);
560     const bool r_scattered = O->isRelocationScattered(RE);
561     const unsigned r_pcrel = O->getAnyRelocationPCRel(RE);
562     const unsigned r_length = O->getAnyRelocationLength(RE);
563     const unsigned r_address = O->getAnyRelocationAddress(RE);
564     const bool r_extern = (r_scattered ? false :
565                            O->getPlainRelocationExternal(RE));
566     const uint32_t r_value = (r_scattered ?
567                               O->getScatteredRelocationValue(RE) : 0);
568     const unsigned r_symbolnum = (r_scattered ? 0 :
569                                   O->getPlainRelocationSymbolNum(RE));
570 
571     if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) {
572       if (verbose) {
573         // scattered: address
574         if ((cputype == MachO::CPU_TYPE_I386 &&
575              r_type == llvm::MachO::GENERIC_RELOC_PAIR) ||
576             (cputype == MachO::CPU_TYPE_ARM &&
577              r_type == llvm::MachO::ARM_RELOC_PAIR))
578           outs() << "         ";
579         else
580           outs() << format("%08x ", (unsigned int)r_address);
581 
582         // scattered: pcrel
583         if (r_pcrel)
584           outs() << "True  ";
585         else
586           outs() << "False ";
587 
588         // scattered: length
589         PrintRLength(cputype, r_type, r_length, previous_arm_half);
590 
591         // scattered: extern & type
592         outs() << "n/a    ";
593         PrintRType(cputype, r_type);
594 
595         // scattered: scattered & value
596         outs() << format("True      0x%08x", (unsigned int)r_value);
597         if (previous_sectdiff == false) {
598           if ((cputype == MachO::CPU_TYPE_ARM &&
599                r_type == llvm::MachO::ARM_RELOC_PAIR))
600             outs() << format(" half = 0x%04x ", (unsigned int)r_address);
601         }
602         else if (cputype == MachO::CPU_TYPE_ARM &&
603                  sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF)
604           outs() << format(" other_half = 0x%04x ", (unsigned int)r_address);
605         if ((cputype == MachO::CPU_TYPE_I386 &&
606              (r_type == llvm::MachO::GENERIC_RELOC_SECTDIFF ||
607               r_type == llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) ||
608             (cputype == MachO::CPU_TYPE_ARM &&
609              (sectdiff_r_type == llvm::MachO::ARM_RELOC_SECTDIFF ||
610               sectdiff_r_type == llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF ||
611               sectdiff_r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))) {
612                previous_sectdiff = true;
613                sectdiff_r_type = r_type;
614              }
615         else {
616           previous_sectdiff = false;
617           sectdiff_r_type = 0;
618         }
619         if (cputype == MachO::CPU_TYPE_ARM &&
620             (r_type == llvm::MachO::ARM_RELOC_HALF ||
621              r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
622           previous_arm_half = true;
623         else
624           previous_arm_half = false;
625         outs() << "\n";
626       }
627       else {
628         // scattered: address pcrel length extern type scattered value
629         outs() << format("%08x %1d     %-2d     n/a    %-7d 1         0x%08x\n",
630                          (unsigned int)r_address, r_pcrel, r_length, r_type,
631                          (unsigned int)r_value);
632       }
633     }
634     else {
635       if (verbose) {
636         // plain: address
637         if (cputype == MachO::CPU_TYPE_ARM &&
638             r_type == llvm::MachO::ARM_RELOC_PAIR)
639           outs() << "         ";
640         else
641           outs() << format("%08x ", (unsigned int)r_address);
642 
643         // plain: pcrel
644         if (r_pcrel)
645           outs() << "True  ";
646         else
647           outs() << "False ";
648 
649         // plain: length
650         PrintRLength(cputype, r_type, r_length, previous_arm_half);
651 
652         if (r_extern) {
653           // plain: extern & type & scattered
654           outs() << "True   ";
655           PrintRType(cputype, r_type);
656           outs() << "False     ";
657 
658           // plain: symbolnum/value
659           if (r_symbolnum > Symtab.nsyms)
660             outs() << format("?(%d)\n", r_symbolnum);
661           else {
662             SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum);
663             Expected<StringRef> SymNameNext = Symbol.getName();
664             const char *name = NULL;
665             if (SymNameNext)
666               name = SymNameNext->data();
667             if (name == NULL)
668               outs() << format("?(%d)\n", r_symbolnum);
669             else
670               outs() << name << "\n";
671           }
672         }
673         else {
674           // plain: extern & type & scattered
675           outs() << "False  ";
676           PrintRType(cputype, r_type);
677           outs() << "False     ";
678 
679           // plain: symbolnum/value
680           if (cputype == MachO::CPU_TYPE_ARM &&
681                    r_type == llvm::MachO::ARM_RELOC_PAIR)
682             outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
683           else if (cputype == MachO::CPU_TYPE_ARM64 &&
684                    r_type == llvm::MachO::ARM64_RELOC_ADDEND)
685             outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
686           else {
687             outs() << format("%d ", r_symbolnum);
688             if (r_symbolnum == llvm::MachO::R_ABS)
689               outs() << "R_ABS\n";
690             else {
691               // in this case, r_symbolnum is actually a 1-based section number
692               uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a;
693               if (r_symbolnum > 0 && r_symbolnum <= nsects) {
694                 llvm::object::DataRefImpl DRI;
695                 DRI.d.a = r_symbolnum-1;
696                 StringRef SegName = O->getSectionFinalSegmentName(DRI);
697                 StringRef SectName;
698                 if (O->getSectionName(DRI, SectName))
699                   outs() << "(?,?)\n";
700                 else
701                   outs() << "(" << SegName << "," << SectName << ")\n";
702               }
703               else {
704                 outs() << "(?,?)\n";
705               }
706             }
707           }
708         }
709         if (cputype == MachO::CPU_TYPE_ARM &&
710             (r_type == llvm::MachO::ARM_RELOC_HALF ||
711              r_type == llvm::MachO::ARM_RELOC_HALF_SECTDIFF))
712           previous_arm_half = true;
713         else
714           previous_arm_half = false;
715       }
716       else {
717         // plain: address pcrel length extern type scattered symbolnum/section
718         outs() << format("%08x %1d     %-2d     %1d      %-7d 0         %d\n",
719                          (unsigned int)r_address, r_pcrel, r_length, r_extern,
720                          r_type, r_symbolnum);
721       }
722     }
723   }
724 }
725 
PrintRelocations(const MachOObjectFile * O,const bool verbose)726 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
727   const uint64_t cputype = O->getHeader().cputype;
728   const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
729   if (Dysymtab.nextrel != 0) {
730     outs() << "External relocation information " << Dysymtab.nextrel
731            << " entries";
732     outs() << "\naddress  pcrel length extern type    scattered "
733               "symbolnum/value\n";
734     PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype,
735                            verbose);
736   }
737   if (Dysymtab.nlocrel != 0) {
738     outs() << format("Local relocation information %u entries",
739                      Dysymtab.nlocrel);
740     outs() << "\naddress  pcrel length extern type    scattered "
741               "symbolnum/value\n";
742     PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype,
743                            verbose);
744   }
745   for (const auto &Load : O->load_commands()) {
746     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
747       const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
748       for (unsigned J = 0; J < Seg.nsects; ++J) {
749         const MachO::section_64 Sec = O->getSection64(Load, J);
750         if (Sec.nreloc != 0) {
751           DataRefImpl DRI;
752           DRI.d.a = J;
753           const StringRef SegName = O->getSectionFinalSegmentName(DRI);
754           StringRef SectName;
755           if (O->getSectionName(DRI, SectName))
756             outs() << "Relocation information (" << SegName << ",?) "
757                    << format("%u entries", Sec.nreloc);
758           else
759             outs() << "Relocation information (" << SegName << ","
760                    << SectName << format(") %u entries", Sec.nreloc);
761           outs() << "\naddress  pcrel length extern type    scattered "
762                     "symbolnum/value\n";
763           PrintRelocationEntries(O, O->section_rel_begin(DRI),
764                                  O->section_rel_end(DRI), cputype, verbose);
765         }
766       }
767     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
768       const MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
769       for (unsigned J = 0; J < Seg.nsects; ++J) {
770         const MachO::section Sec = O->getSection(Load, J);
771         if (Sec.nreloc != 0) {
772           DataRefImpl DRI;
773           DRI.d.a = J;
774           const StringRef SegName = O->getSectionFinalSegmentName(DRI);
775           StringRef SectName;
776           if (O->getSectionName(DRI, SectName))
777             outs() << "Relocation information (" << SegName << ",?) "
778                    << format("%u entries", Sec.nreloc);
779           else
780             outs() << "Relocation information (" << SegName << ","
781                    << SectName << format(") %u entries", Sec.nreloc);
782           outs() << "\naddress  pcrel length extern type    scattered "
783                     "symbolnum/value\n";
784           PrintRelocationEntries(O, O->section_rel_begin(DRI),
785                                  O->section_rel_end(DRI), cputype, verbose);
786         }
787       }
788     }
789   }
790 }
791 
PrintDataInCodeTable(MachOObjectFile * O,bool verbose)792 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
793   MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
794   uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
795   outs() << "Data in code table (" << nentries << " entries)\n";
796   outs() << "offset     length kind\n";
797   for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
798        ++DI) {
799     uint32_t Offset;
800     DI->getOffset(Offset);
801     outs() << format("0x%08" PRIx32, Offset) << " ";
802     uint16_t Length;
803     DI->getLength(Length);
804     outs() << format("%6u", Length) << " ";
805     uint16_t Kind;
806     DI->getKind(Kind);
807     if (verbose) {
808       switch (Kind) {
809       case MachO::DICE_KIND_DATA:
810         outs() << "DATA";
811         break;
812       case MachO::DICE_KIND_JUMP_TABLE8:
813         outs() << "JUMP_TABLE8";
814         break;
815       case MachO::DICE_KIND_JUMP_TABLE16:
816         outs() << "JUMP_TABLE16";
817         break;
818       case MachO::DICE_KIND_JUMP_TABLE32:
819         outs() << "JUMP_TABLE32";
820         break;
821       case MachO::DICE_KIND_ABS_JUMP_TABLE32:
822         outs() << "ABS_JUMP_TABLE32";
823         break;
824       default:
825         outs() << format("0x%04" PRIx32, Kind);
826         break;
827       }
828     } else
829       outs() << format("0x%04" PRIx32, Kind);
830     outs() << "\n";
831   }
832 }
833 
PrintLinkOptHints(MachOObjectFile * O)834 static void PrintLinkOptHints(MachOObjectFile *O) {
835   MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
836   const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
837   uint32_t nloh = LohLC.datasize;
838   outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
839   for (uint32_t i = 0; i < nloh;) {
840     unsigned n;
841     uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
842     i += n;
843     outs() << "    identifier " << identifier << " ";
844     if (i >= nloh)
845       return;
846     switch (identifier) {
847     case 1:
848       outs() << "AdrpAdrp\n";
849       break;
850     case 2:
851       outs() << "AdrpLdr\n";
852       break;
853     case 3:
854       outs() << "AdrpAddLdr\n";
855       break;
856     case 4:
857       outs() << "AdrpLdrGotLdr\n";
858       break;
859     case 5:
860       outs() << "AdrpAddStr\n";
861       break;
862     case 6:
863       outs() << "AdrpLdrGotStr\n";
864       break;
865     case 7:
866       outs() << "AdrpAdd\n";
867       break;
868     case 8:
869       outs() << "AdrpLdrGot\n";
870       break;
871     default:
872       outs() << "Unknown identifier value\n";
873       break;
874     }
875     uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
876     i += n;
877     outs() << "    narguments " << narguments << "\n";
878     if (i >= nloh)
879       return;
880 
881     for (uint32_t j = 0; j < narguments; j++) {
882       uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
883       i += n;
884       outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
885       if (i >= nloh)
886         return;
887     }
888   }
889 }
890 
PrintDylibs(MachOObjectFile * O,bool JustId)891 static void PrintDylibs(MachOObjectFile *O, bool JustId) {
892   unsigned Index = 0;
893   for (const auto &Load : O->load_commands()) {
894     if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
895         (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
896                      Load.C.cmd == MachO::LC_LOAD_DYLIB ||
897                      Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
898                      Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
899                      Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
900                      Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
901       MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
902       if (dl.dylib.name < dl.cmdsize) {
903         const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
904         if (JustId)
905           outs() << p << "\n";
906         else {
907           outs() << "\t" << p;
908           outs() << " (compatibility version "
909                  << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
910                  << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
911                  << (dl.dylib.compatibility_version & 0xff) << ",";
912           outs() << " current version "
913                  << ((dl.dylib.current_version >> 16) & 0xffff) << "."
914                  << ((dl.dylib.current_version >> 8) & 0xff) << "."
915                  << (dl.dylib.current_version & 0xff) << ")\n";
916         }
917       } else {
918         outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
919         if (Load.C.cmd == MachO::LC_ID_DYLIB)
920           outs() << "LC_ID_DYLIB ";
921         else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
922           outs() << "LC_LOAD_DYLIB ";
923         else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
924           outs() << "LC_LOAD_WEAK_DYLIB ";
925         else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
926           outs() << "LC_LAZY_LOAD_DYLIB ";
927         else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
928           outs() << "LC_REEXPORT_DYLIB ";
929         else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
930           outs() << "LC_LOAD_UPWARD_DYLIB ";
931         else
932           outs() << "LC_??? ";
933         outs() << "command " << Index++ << "\n";
934       }
935     }
936   }
937 }
938 
939 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
940 
CreateSymbolAddressMap(MachOObjectFile * O,SymbolAddressMap * AddrMap)941 static void CreateSymbolAddressMap(MachOObjectFile *O,
942                                    SymbolAddressMap *AddrMap) {
943   // Create a map of symbol addresses to symbol names.
944   for (const SymbolRef &Symbol : O->symbols()) {
945     Expected<SymbolRef::Type> STOrErr = Symbol.getType();
946     if (!STOrErr)
947       report_error(O->getFileName(), STOrErr.takeError());
948     SymbolRef::Type ST = *STOrErr;
949     if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
950         ST == SymbolRef::ST_Other) {
951       uint64_t Address = Symbol.getValue();
952       Expected<StringRef> SymNameOrErr = Symbol.getName();
953       if (!SymNameOrErr)
954         report_error(O->getFileName(), SymNameOrErr.takeError());
955       StringRef SymName = *SymNameOrErr;
956       if (!SymName.startswith(".objc"))
957         (*AddrMap)[Address] = SymName;
958     }
959   }
960 }
961 
962 // GuessSymbolName is passed the address of what might be a symbol and a
963 // pointer to the SymbolAddressMap.  It returns the name of a symbol
964 // with that address or nullptr if no symbol is found with that address.
GuessSymbolName(uint64_t value,SymbolAddressMap * AddrMap)965 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
966   const char *SymbolName = nullptr;
967   // A DenseMap can't lookup up some values.
968   if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
969     StringRef name = AddrMap->lookup(value);
970     if (!name.empty())
971       SymbolName = name.data();
972   }
973   return SymbolName;
974 }
975 
DumpCstringChar(const char c)976 static void DumpCstringChar(const char c) {
977   char p[2];
978   p[0] = c;
979   p[1] = '\0';
980   outs().write_escaped(p);
981 }
982 
DumpCstringSection(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)983 static void DumpCstringSection(MachOObjectFile *O, const char *sect,
984                                uint32_t sect_size, uint64_t sect_addr,
985                                bool print_addresses) {
986   for (uint32_t i = 0; i < sect_size; i++) {
987     if (print_addresses) {
988       if (O->is64Bit())
989         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
990       else
991         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
992     }
993     for (; i < sect_size && sect[i] != '\0'; i++)
994       DumpCstringChar(sect[i]);
995     if (i < sect_size && sect[i] == '\0')
996       outs() << "\n";
997   }
998 }
999 
DumpLiteral4(uint32_t l,float f)1000 static void DumpLiteral4(uint32_t l, float f) {
1001   outs() << format("0x%08" PRIx32, l);
1002   if ((l & 0x7f800000) != 0x7f800000)
1003     outs() << format(" (%.16e)\n", f);
1004   else {
1005     if (l == 0x7f800000)
1006       outs() << " (+Infinity)\n";
1007     else if (l == 0xff800000)
1008       outs() << " (-Infinity)\n";
1009     else if ((l & 0x00400000) == 0x00400000)
1010       outs() << " (non-signaling Not-a-Number)\n";
1011     else
1012       outs() << " (signaling Not-a-Number)\n";
1013   }
1014 }
1015 
DumpLiteral4Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1016 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
1017                                 uint32_t sect_size, uint64_t sect_addr,
1018                                 bool print_addresses) {
1019   for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
1020     if (print_addresses) {
1021       if (O->is64Bit())
1022         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1023       else
1024         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1025     }
1026     float f;
1027     memcpy(&f, sect + i, sizeof(float));
1028     if (O->isLittleEndian() != sys::IsLittleEndianHost)
1029       sys::swapByteOrder(f);
1030     uint32_t l;
1031     memcpy(&l, sect + i, sizeof(uint32_t));
1032     if (O->isLittleEndian() != sys::IsLittleEndianHost)
1033       sys::swapByteOrder(l);
1034     DumpLiteral4(l, f);
1035   }
1036 }
1037 
DumpLiteral8(MachOObjectFile * O,uint32_t l0,uint32_t l1,double d)1038 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
1039                          double d) {
1040   outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
1041   uint32_t Hi, Lo;
1042   Hi = (O->isLittleEndian()) ? l1 : l0;
1043   Lo = (O->isLittleEndian()) ? l0 : l1;
1044 
1045   // Hi is the high word, so this is equivalent to if(isfinite(d))
1046   if ((Hi & 0x7ff00000) != 0x7ff00000)
1047     outs() << format(" (%.16e)\n", d);
1048   else {
1049     if (Hi == 0x7ff00000 && Lo == 0)
1050       outs() << " (+Infinity)\n";
1051     else if (Hi == 0xfff00000 && Lo == 0)
1052       outs() << " (-Infinity)\n";
1053     else if ((Hi & 0x00080000) == 0x00080000)
1054       outs() << " (non-signaling Not-a-Number)\n";
1055     else
1056       outs() << " (signaling Not-a-Number)\n";
1057   }
1058 }
1059 
DumpLiteral8Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1060 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
1061                                 uint32_t sect_size, uint64_t sect_addr,
1062                                 bool print_addresses) {
1063   for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
1064     if (print_addresses) {
1065       if (O->is64Bit())
1066         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1067       else
1068         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1069     }
1070     double d;
1071     memcpy(&d, sect + i, sizeof(double));
1072     if (O->isLittleEndian() != sys::IsLittleEndianHost)
1073       sys::swapByteOrder(d);
1074     uint32_t l0, l1;
1075     memcpy(&l0, sect + i, sizeof(uint32_t));
1076     memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1077     if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1078       sys::swapByteOrder(l0);
1079       sys::swapByteOrder(l1);
1080     }
1081     DumpLiteral8(O, l0, l1, d);
1082   }
1083 }
1084 
DumpLiteral16(uint32_t l0,uint32_t l1,uint32_t l2,uint32_t l3)1085 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
1086   outs() << format("0x%08" PRIx32, l0) << " ";
1087   outs() << format("0x%08" PRIx32, l1) << " ";
1088   outs() << format("0x%08" PRIx32, l2) << " ";
1089   outs() << format("0x%08" PRIx32, l3) << "\n";
1090 }
1091 
DumpLiteral16Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1092 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
1093                                  uint32_t sect_size, uint64_t sect_addr,
1094                                  bool print_addresses) {
1095   for (uint32_t i = 0; i < sect_size; i += 16) {
1096     if (print_addresses) {
1097       if (O->is64Bit())
1098         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1099       else
1100         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1101     }
1102     uint32_t l0, l1, l2, l3;
1103     memcpy(&l0, sect + i, sizeof(uint32_t));
1104     memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1105     memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
1106     memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
1107     if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1108       sys::swapByteOrder(l0);
1109       sys::swapByteOrder(l1);
1110       sys::swapByteOrder(l2);
1111       sys::swapByteOrder(l3);
1112     }
1113     DumpLiteral16(l0, l1, l2, l3);
1114   }
1115 }
1116 
DumpLiteralPointerSection(MachOObjectFile * O,const SectionRef & Section,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1117 static void DumpLiteralPointerSection(MachOObjectFile *O,
1118                                       const SectionRef &Section,
1119                                       const char *sect, uint32_t sect_size,
1120                                       uint64_t sect_addr,
1121                                       bool print_addresses) {
1122   // Collect the literal sections in this Mach-O file.
1123   std::vector<SectionRef> LiteralSections;
1124   for (const SectionRef &Section : O->sections()) {
1125     DataRefImpl Ref = Section.getRawDataRefImpl();
1126     uint32_t section_type;
1127     if (O->is64Bit()) {
1128       const MachO::section_64 Sec = O->getSection64(Ref);
1129       section_type = Sec.flags & MachO::SECTION_TYPE;
1130     } else {
1131       const MachO::section Sec = O->getSection(Ref);
1132       section_type = Sec.flags & MachO::SECTION_TYPE;
1133     }
1134     if (section_type == MachO::S_CSTRING_LITERALS ||
1135         section_type == MachO::S_4BYTE_LITERALS ||
1136         section_type == MachO::S_8BYTE_LITERALS ||
1137         section_type == MachO::S_16BYTE_LITERALS)
1138       LiteralSections.push_back(Section);
1139   }
1140 
1141   // Set the size of the literal pointer.
1142   uint32_t lp_size = O->is64Bit() ? 8 : 4;
1143 
1144   // Collect the external relocation symbols for the literal pointers.
1145   std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1146   for (const RelocationRef &Reloc : Section.relocations()) {
1147     DataRefImpl Rel;
1148     MachO::any_relocation_info RE;
1149     bool isExtern = false;
1150     Rel = Reloc.getRawDataRefImpl();
1151     RE = O->getRelocation(Rel);
1152     isExtern = O->getPlainRelocationExternal(RE);
1153     if (isExtern) {
1154       uint64_t RelocOffset = Reloc.getOffset();
1155       symbol_iterator RelocSym = Reloc.getSymbol();
1156       Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1157     }
1158   }
1159   array_pod_sort(Relocs.begin(), Relocs.end());
1160 
1161   // Dump each literal pointer.
1162   for (uint32_t i = 0; i < sect_size; i += lp_size) {
1163     if (print_addresses) {
1164       if (O->is64Bit())
1165         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1166       else
1167         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1168     }
1169     uint64_t lp;
1170     if (O->is64Bit()) {
1171       memcpy(&lp, sect + i, sizeof(uint64_t));
1172       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1173         sys::swapByteOrder(lp);
1174     } else {
1175       uint32_t li;
1176       memcpy(&li, sect + i, sizeof(uint32_t));
1177       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1178         sys::swapByteOrder(li);
1179       lp = li;
1180     }
1181 
1182     // First look for an external relocation entry for this literal pointer.
1183     auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1184       return P.first == i;
1185     });
1186     if (Reloc != Relocs.end()) {
1187       symbol_iterator RelocSym = Reloc->second;
1188       Expected<StringRef> SymName = RelocSym->getName();
1189       if (!SymName)
1190         report_error(O->getFileName(), SymName.takeError());
1191       outs() << "external relocation entry for symbol:" << *SymName << "\n";
1192       continue;
1193     }
1194 
1195     // For local references see what the section the literal pointer points to.
1196     auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
1197       return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
1198     });
1199     if (Sect == LiteralSections.end()) {
1200       outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
1201       continue;
1202     }
1203 
1204     uint64_t SectAddress = Sect->getAddress();
1205     uint64_t SectSize = Sect->getSize();
1206 
1207     StringRef SectName;
1208     Sect->getName(SectName);
1209     DataRefImpl Ref = Sect->getRawDataRefImpl();
1210     StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
1211     outs() << SegmentName << ":" << SectName << ":";
1212 
1213     uint32_t section_type;
1214     if (O->is64Bit()) {
1215       const MachO::section_64 Sec = O->getSection64(Ref);
1216       section_type = Sec.flags & MachO::SECTION_TYPE;
1217     } else {
1218       const MachO::section Sec = O->getSection(Ref);
1219       section_type = Sec.flags & MachO::SECTION_TYPE;
1220     }
1221 
1222     StringRef BytesStr;
1223     Sect->getContents(BytesStr);
1224     const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
1225 
1226     switch (section_type) {
1227     case MachO::S_CSTRING_LITERALS:
1228       for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
1229            i++) {
1230         DumpCstringChar(Contents[i]);
1231       }
1232       outs() << "\n";
1233       break;
1234     case MachO::S_4BYTE_LITERALS:
1235       float f;
1236       memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
1237       uint32_t l;
1238       memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
1239       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1240         sys::swapByteOrder(f);
1241         sys::swapByteOrder(l);
1242       }
1243       DumpLiteral4(l, f);
1244       break;
1245     case MachO::S_8BYTE_LITERALS: {
1246       double d;
1247       memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
1248       uint32_t l0, l1;
1249       memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1250       memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1251              sizeof(uint32_t));
1252       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1253         sys::swapByteOrder(f);
1254         sys::swapByteOrder(l0);
1255         sys::swapByteOrder(l1);
1256       }
1257       DumpLiteral8(O, l0, l1, d);
1258       break;
1259     }
1260     case MachO::S_16BYTE_LITERALS: {
1261       uint32_t l0, l1, l2, l3;
1262       memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1263       memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1264              sizeof(uint32_t));
1265       memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
1266              sizeof(uint32_t));
1267       memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
1268              sizeof(uint32_t));
1269       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1270         sys::swapByteOrder(l0);
1271         sys::swapByteOrder(l1);
1272         sys::swapByteOrder(l2);
1273         sys::swapByteOrder(l3);
1274       }
1275       DumpLiteral16(l0, l1, l2, l3);
1276       break;
1277     }
1278     }
1279   }
1280 }
1281 
DumpInitTermPointerSection(MachOObjectFile * O,const SectionRef & Section,const char * sect,uint32_t sect_size,uint64_t sect_addr,SymbolAddressMap * AddrMap,bool verbose)1282 static void DumpInitTermPointerSection(MachOObjectFile *O,
1283                                        const SectionRef &Section,
1284                                        const char *sect,
1285                                        uint32_t sect_size, uint64_t sect_addr,
1286                                        SymbolAddressMap *AddrMap,
1287                                        bool verbose) {
1288   uint32_t stride;
1289   stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
1290 
1291   // Collect the external relocation symbols for the pointers.
1292   std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1293   for (const RelocationRef &Reloc : Section.relocations()) {
1294     DataRefImpl Rel;
1295     MachO::any_relocation_info RE;
1296     bool isExtern = false;
1297     Rel = Reloc.getRawDataRefImpl();
1298     RE = O->getRelocation(Rel);
1299     isExtern = O->getPlainRelocationExternal(RE);
1300     if (isExtern) {
1301       uint64_t RelocOffset = Reloc.getOffset();
1302       symbol_iterator RelocSym = Reloc.getSymbol();
1303       Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1304     }
1305   }
1306   array_pod_sort(Relocs.begin(), Relocs.end());
1307 
1308   for (uint32_t i = 0; i < sect_size; i += stride) {
1309     const char *SymbolName = nullptr;
1310     uint64_t p;
1311     if (O->is64Bit()) {
1312       outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
1313       uint64_t pointer_value;
1314       memcpy(&pointer_value, sect + i, stride);
1315       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1316         sys::swapByteOrder(pointer_value);
1317       outs() << format("0x%016" PRIx64, pointer_value);
1318       p = pointer_value;
1319     } else {
1320       outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
1321       uint32_t pointer_value;
1322       memcpy(&pointer_value, sect + i, stride);
1323       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1324         sys::swapByteOrder(pointer_value);
1325       outs() << format("0x%08" PRIx32, pointer_value);
1326       p = pointer_value;
1327     }
1328     if (verbose) {
1329       // First look for an external relocation entry for this pointer.
1330       auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1331         return P.first == i;
1332       });
1333       if (Reloc != Relocs.end()) {
1334         symbol_iterator RelocSym = Reloc->second;
1335         Expected<StringRef> SymName = RelocSym->getName();
1336         if (!SymName)
1337           report_error(O->getFileName(), SymName.takeError());
1338         outs() << " " << *SymName;
1339       } else {
1340         SymbolName = GuessSymbolName(p, AddrMap);
1341         if (SymbolName)
1342           outs() << " " << SymbolName;
1343       }
1344     }
1345     outs() << "\n";
1346   }
1347 }
1348 
DumpRawSectionContents(MachOObjectFile * O,const char * sect,uint32_t size,uint64_t addr)1349 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
1350                                    uint32_t size, uint64_t addr) {
1351   uint32_t cputype = O->getHeader().cputype;
1352   if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
1353     uint32_t j;
1354     for (uint32_t i = 0; i < size; i += j, addr += j) {
1355       if (O->is64Bit())
1356         outs() << format("%016" PRIx64, addr) << "\t";
1357       else
1358         outs() << format("%08" PRIx64, addr) << "\t";
1359       for (j = 0; j < 16 && i + j < size; j++) {
1360         uint8_t byte_word = *(sect + i + j);
1361         outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1362       }
1363       outs() << "\n";
1364     }
1365   } else {
1366     uint32_t j;
1367     for (uint32_t i = 0; i < size; i += j, addr += j) {
1368       if (O->is64Bit())
1369         outs() << format("%016" PRIx64, addr) << "\t";
1370       else
1371         outs() << format("%08" PRIx64, addr) << "\t";
1372       for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
1373            j += sizeof(int32_t)) {
1374         if (i + j + sizeof(int32_t) <= size) {
1375           uint32_t long_word;
1376           memcpy(&long_word, sect + i + j, sizeof(int32_t));
1377           if (O->isLittleEndian() != sys::IsLittleEndianHost)
1378             sys::swapByteOrder(long_word);
1379           outs() << format("%08" PRIx32, long_word) << " ";
1380         } else {
1381           for (uint32_t k = 0; i + j + k < size; k++) {
1382             uint8_t byte_word = *(sect + i + j + k);
1383             outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1384           }
1385         }
1386       }
1387       outs() << "\n";
1388     }
1389   }
1390 }
1391 
1392 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
1393                              StringRef DisSegName, StringRef DisSectName);
1394 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
1395                                 uint32_t size, uint32_t addr);
1396 #ifdef HAVE_LIBXAR
1397 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
1398                                 uint32_t size, bool verbose,
1399                                 bool PrintXarHeader, bool PrintXarFileHeaders,
1400                                 std::string XarMemberName);
1401 #endif // defined(HAVE_LIBXAR)
1402 
DumpSectionContents(StringRef Filename,MachOObjectFile * O,bool verbose)1403 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
1404                                 bool verbose) {
1405   SymbolAddressMap AddrMap;
1406   if (verbose)
1407     CreateSymbolAddressMap(O, &AddrMap);
1408 
1409   for (unsigned i = 0; i < FilterSections.size(); ++i) {
1410     StringRef DumpSection = FilterSections[i];
1411     std::pair<StringRef, StringRef> DumpSegSectName;
1412     DumpSegSectName = DumpSection.split(',');
1413     StringRef DumpSegName, DumpSectName;
1414     if (DumpSegSectName.second.size()) {
1415       DumpSegName = DumpSegSectName.first;
1416       DumpSectName = DumpSegSectName.second;
1417     } else {
1418       DumpSegName = "";
1419       DumpSectName = DumpSegSectName.first;
1420     }
1421     for (const SectionRef &Section : O->sections()) {
1422       StringRef SectName;
1423       Section.getName(SectName);
1424       DataRefImpl Ref = Section.getRawDataRefImpl();
1425       StringRef SegName = O->getSectionFinalSegmentName(Ref);
1426       if ((DumpSegName.empty() || SegName == DumpSegName) &&
1427           (SectName == DumpSectName)) {
1428 
1429         uint32_t section_flags;
1430         if (O->is64Bit()) {
1431           const MachO::section_64 Sec = O->getSection64(Ref);
1432           section_flags = Sec.flags;
1433 
1434         } else {
1435           const MachO::section Sec = O->getSection(Ref);
1436           section_flags = Sec.flags;
1437         }
1438         uint32_t section_type = section_flags & MachO::SECTION_TYPE;
1439 
1440         StringRef BytesStr;
1441         Section.getContents(BytesStr);
1442         const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1443         uint32_t sect_size = BytesStr.size();
1444         uint64_t sect_addr = Section.getAddress();
1445 
1446         outs() << "Contents of (" << SegName << "," << SectName
1447                << ") section\n";
1448 
1449         if (verbose) {
1450           if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
1451               (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
1452             DisassembleMachO(Filename, O, SegName, SectName);
1453             continue;
1454           }
1455           if (SegName == "__TEXT" && SectName == "__info_plist") {
1456             outs() << sect;
1457             continue;
1458           }
1459           if (SegName == "__OBJC" && SectName == "__protocol") {
1460             DumpProtocolSection(O, sect, sect_size, sect_addr);
1461             continue;
1462           }
1463 #ifdef HAVE_LIBXAR
1464           if (SegName == "__LLVM" && SectName == "__bundle") {
1465             DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands,
1466                                ArchiveHeaders, "");
1467             continue;
1468           }
1469 #endif // defined(HAVE_LIBXAR)
1470           switch (section_type) {
1471           case MachO::S_REGULAR:
1472             DumpRawSectionContents(O, sect, sect_size, sect_addr);
1473             break;
1474           case MachO::S_ZEROFILL:
1475             outs() << "zerofill section and has no contents in the file\n";
1476             break;
1477           case MachO::S_CSTRING_LITERALS:
1478             DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1479             break;
1480           case MachO::S_4BYTE_LITERALS:
1481             DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1482             break;
1483           case MachO::S_8BYTE_LITERALS:
1484             DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1485             break;
1486           case MachO::S_16BYTE_LITERALS:
1487             DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
1488             break;
1489           case MachO::S_LITERAL_POINTERS:
1490             DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
1491                                       !NoLeadingAddr);
1492             break;
1493           case MachO::S_MOD_INIT_FUNC_POINTERS:
1494           case MachO::S_MOD_TERM_FUNC_POINTERS:
1495             DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr,
1496                                        &AddrMap, verbose);
1497             break;
1498           default:
1499             outs() << "Unknown section type ("
1500                    << format("0x%08" PRIx32, section_type) << ")\n";
1501             DumpRawSectionContents(O, sect, sect_size, sect_addr);
1502             break;
1503           }
1504         } else {
1505           if (section_type == MachO::S_ZEROFILL)
1506             outs() << "zerofill section and has no contents in the file\n";
1507           else
1508             DumpRawSectionContents(O, sect, sect_size, sect_addr);
1509         }
1510       }
1511     }
1512   }
1513 }
1514 
DumpInfoPlistSectionContents(StringRef Filename,MachOObjectFile * O)1515 static void DumpInfoPlistSectionContents(StringRef Filename,
1516                                          MachOObjectFile *O) {
1517   for (const SectionRef &Section : O->sections()) {
1518     StringRef SectName;
1519     Section.getName(SectName);
1520     DataRefImpl Ref = Section.getRawDataRefImpl();
1521     StringRef SegName = O->getSectionFinalSegmentName(Ref);
1522     if (SegName == "__TEXT" && SectName == "__info_plist") {
1523       if (!NoLeadingHeaders)
1524         outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
1525       StringRef BytesStr;
1526       Section.getContents(BytesStr);
1527       const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1528       outs() << format("%.*s", BytesStr.size(), sect) << "\n";
1529       return;
1530     }
1531   }
1532 }
1533 
1534 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
1535 // and if it is and there is a list of architecture flags is specified then
1536 // check to make sure this Mach-O file is one of those architectures or all
1537 // architectures were specified.  If not then an error is generated and this
1538 // routine returns false.  Else it returns true.
checkMachOAndArchFlags(ObjectFile * O,StringRef Filename)1539 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
1540   auto *MachO = dyn_cast<MachOObjectFile>(O);
1541 
1542   if (!MachO || ArchAll || ArchFlags.empty())
1543     return true;
1544 
1545   MachO::mach_header H;
1546   MachO::mach_header_64 H_64;
1547   Triple T;
1548   const char *McpuDefault, *ArchFlag;
1549   if (MachO->is64Bit()) {
1550     H_64 = MachO->MachOObjectFile::getHeader64();
1551     T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
1552                                        &McpuDefault, &ArchFlag);
1553   } else {
1554     H = MachO->MachOObjectFile::getHeader();
1555     T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
1556                                        &McpuDefault, &ArchFlag);
1557   }
1558   const std::string ArchFlagName(ArchFlag);
1559   if (none_of(ArchFlags, [&](const std::string &Name) {
1560         return Name == ArchFlagName;
1561       })) {
1562     errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n";
1563     return false;
1564   }
1565   return true;
1566 }
1567 
1568 static void printObjcMetaData(MachOObjectFile *O, bool verbose);
1569 
1570 // ProcessMachO() is passed a single opened Mach-O file, which may be an
1571 // archive member and or in a slice of a universal file.  It prints the
1572 // the file name and header info and then processes it according to the
1573 // command line options.
ProcessMachO(StringRef Name,MachOObjectFile * MachOOF,StringRef ArchiveMemberName=StringRef (),StringRef ArchitectureName=StringRef ())1574 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
1575                          StringRef ArchiveMemberName = StringRef(),
1576                          StringRef ArchitectureName = StringRef()) {
1577   // If we are doing some processing here on the Mach-O file print the header
1578   // info.  And don't print it otherwise like in the case of printing the
1579   // UniversalHeaders or ArchiveHeaders.
1580   if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
1581       Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
1582       DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData ||
1583       (FilterSections.size() != 0)) {
1584     if (!NoLeadingHeaders) {
1585       outs() << Name;
1586       if (!ArchiveMemberName.empty())
1587         outs() << '(' << ArchiveMemberName << ')';
1588       if (!ArchitectureName.empty())
1589         outs() << " (architecture " << ArchitectureName << ")";
1590       outs() << ":\n";
1591     }
1592   }
1593   // To use the report_error() form with an ArchiveName and FileName set
1594   // these up based on what is passed for Name and ArchiveMemberName.
1595   StringRef ArchiveName;
1596   StringRef FileName;
1597   if (!ArchiveMemberName.empty()) {
1598     ArchiveName = Name;
1599     FileName = ArchiveMemberName;
1600   } else {
1601     ArchiveName = StringRef();
1602     FileName = Name;
1603   }
1604 
1605   // If we need the symbol table to do the operation then check it here to
1606   // produce a good error message as to where the Mach-O file comes from in
1607   // the error message.
1608   if (Disassemble || IndirectSymbols || FilterSections.size() != 0 ||
1609       UnwindInfo)
1610     if (Error Err = MachOOF->checkSymbolTable())
1611       report_error(ArchiveName, FileName, std::move(Err), ArchitectureName);
1612 
1613   if (Disassemble) {
1614     if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE &&
1615         MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64)
1616       DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text");
1617     else
1618       DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
1619   }
1620   if (IndirectSymbols)
1621     PrintIndirectSymbols(MachOOF, !NonVerbose);
1622   if (DataInCode)
1623     PrintDataInCodeTable(MachOOF, !NonVerbose);
1624   if (LinkOptHints)
1625     PrintLinkOptHints(MachOOF);
1626   if (Relocations)
1627     PrintRelocations(MachOOF, !NonVerbose);
1628   if (SectionHeaders)
1629     PrintSectionHeaders(MachOOF);
1630   if (SectionContents)
1631     PrintSectionContents(MachOOF);
1632   if (FilterSections.size() != 0)
1633     DumpSectionContents(FileName, MachOOF, !NonVerbose);
1634   if (InfoPlist)
1635     DumpInfoPlistSectionContents(FileName, MachOOF);
1636   if (DylibsUsed)
1637     PrintDylibs(MachOOF, false);
1638   if (DylibId)
1639     PrintDylibs(MachOOF, true);
1640   if (SymbolTable)
1641     PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName);
1642   if (UnwindInfo)
1643     printMachOUnwindInfo(MachOOF);
1644   if (PrivateHeaders) {
1645     printMachOFileHeader(MachOOF);
1646     printMachOLoadCommands(MachOOF);
1647   }
1648   if (FirstPrivateHeader)
1649     printMachOFileHeader(MachOOF);
1650   if (ObjcMetaData)
1651     printObjcMetaData(MachOOF, !NonVerbose);
1652   if (ExportsTrie)
1653     printExportsTrie(MachOOF);
1654   if (Rebase)
1655     printRebaseTable(MachOOF);
1656   if (Bind)
1657     printBindTable(MachOOF);
1658   if (LazyBind)
1659     printLazyBindTable(MachOOF);
1660   if (WeakBind)
1661     printWeakBindTable(MachOOF);
1662 
1663   if (DwarfDumpType != DIDT_Null) {
1664     std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF);
1665     // Dump the complete DWARF structure.
1666     DIDumpOptions DumpOpts;
1667     DumpOpts.DumpType = DwarfDumpType;
1668     DICtx->dump(outs(), DumpOpts);
1669   }
1670 }
1671 
1672 // printUnknownCPUType() helps print_fat_headers for unknown CPU's.
printUnknownCPUType(uint32_t cputype,uint32_t cpusubtype)1673 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
1674   outs() << "    cputype (" << cputype << ")\n";
1675   outs() << "    cpusubtype (" << cpusubtype << ")\n";
1676 }
1677 
1678 // printCPUType() helps print_fat_headers by printing the cputype and
1679 // pusubtype (symbolically for the one's it knows about).
printCPUType(uint32_t cputype,uint32_t cpusubtype)1680 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
1681   switch (cputype) {
1682   case MachO::CPU_TYPE_I386:
1683     switch (cpusubtype) {
1684     case MachO::CPU_SUBTYPE_I386_ALL:
1685       outs() << "    cputype CPU_TYPE_I386\n";
1686       outs() << "    cpusubtype CPU_SUBTYPE_I386_ALL\n";
1687       break;
1688     default:
1689       printUnknownCPUType(cputype, cpusubtype);
1690       break;
1691     }
1692     break;
1693   case MachO::CPU_TYPE_X86_64:
1694     switch (cpusubtype) {
1695     case MachO::CPU_SUBTYPE_X86_64_ALL:
1696       outs() << "    cputype CPU_TYPE_X86_64\n";
1697       outs() << "    cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
1698       break;
1699     case MachO::CPU_SUBTYPE_X86_64_H:
1700       outs() << "    cputype CPU_TYPE_X86_64\n";
1701       outs() << "    cpusubtype CPU_SUBTYPE_X86_64_H\n";
1702       break;
1703     default:
1704       printUnknownCPUType(cputype, cpusubtype);
1705       break;
1706     }
1707     break;
1708   case MachO::CPU_TYPE_ARM:
1709     switch (cpusubtype) {
1710     case MachO::CPU_SUBTYPE_ARM_ALL:
1711       outs() << "    cputype CPU_TYPE_ARM\n";
1712       outs() << "    cpusubtype CPU_SUBTYPE_ARM_ALL\n";
1713       break;
1714     case MachO::CPU_SUBTYPE_ARM_V4T:
1715       outs() << "    cputype CPU_TYPE_ARM\n";
1716       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V4T\n";
1717       break;
1718     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
1719       outs() << "    cputype CPU_TYPE_ARM\n";
1720       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
1721       break;
1722     case MachO::CPU_SUBTYPE_ARM_XSCALE:
1723       outs() << "    cputype CPU_TYPE_ARM\n";
1724       outs() << "    cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
1725       break;
1726     case MachO::CPU_SUBTYPE_ARM_V6:
1727       outs() << "    cputype CPU_TYPE_ARM\n";
1728       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6\n";
1729       break;
1730     case MachO::CPU_SUBTYPE_ARM_V6M:
1731       outs() << "    cputype CPU_TYPE_ARM\n";
1732       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6M\n";
1733       break;
1734     case MachO::CPU_SUBTYPE_ARM_V7:
1735       outs() << "    cputype CPU_TYPE_ARM\n";
1736       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7\n";
1737       break;
1738     case MachO::CPU_SUBTYPE_ARM_V7EM:
1739       outs() << "    cputype CPU_TYPE_ARM\n";
1740       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
1741       break;
1742     case MachO::CPU_SUBTYPE_ARM_V7K:
1743       outs() << "    cputype CPU_TYPE_ARM\n";
1744       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7K\n";
1745       break;
1746     case MachO::CPU_SUBTYPE_ARM_V7M:
1747       outs() << "    cputype CPU_TYPE_ARM\n";
1748       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7M\n";
1749       break;
1750     case MachO::CPU_SUBTYPE_ARM_V7S:
1751       outs() << "    cputype CPU_TYPE_ARM\n";
1752       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7S\n";
1753       break;
1754     default:
1755       printUnknownCPUType(cputype, cpusubtype);
1756       break;
1757     }
1758     break;
1759   case MachO::CPU_TYPE_ARM64:
1760     switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
1761     case MachO::CPU_SUBTYPE_ARM64_ALL:
1762       outs() << "    cputype CPU_TYPE_ARM64\n";
1763       outs() << "    cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
1764       break;
1765     default:
1766       printUnknownCPUType(cputype, cpusubtype);
1767       break;
1768     }
1769     break;
1770   default:
1771     printUnknownCPUType(cputype, cpusubtype);
1772     break;
1773   }
1774 }
1775 
printMachOUniversalHeaders(const object::MachOUniversalBinary * UB,bool verbose)1776 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
1777                                        bool verbose) {
1778   outs() << "Fat headers\n";
1779   if (verbose) {
1780     if (UB->getMagic() == MachO::FAT_MAGIC)
1781       outs() << "fat_magic FAT_MAGIC\n";
1782     else // UB->getMagic() == MachO::FAT_MAGIC_64
1783       outs() << "fat_magic FAT_MAGIC_64\n";
1784   } else
1785     outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
1786 
1787   uint32_t nfat_arch = UB->getNumberOfObjects();
1788   StringRef Buf = UB->getData();
1789   uint64_t size = Buf.size();
1790   uint64_t big_size = sizeof(struct MachO::fat_header) +
1791                       nfat_arch * sizeof(struct MachO::fat_arch);
1792   outs() << "nfat_arch " << UB->getNumberOfObjects();
1793   if (nfat_arch == 0)
1794     outs() << " (malformed, contains zero architecture types)\n";
1795   else if (big_size > size)
1796     outs() << " (malformed, architectures past end of file)\n";
1797   else
1798     outs() << "\n";
1799 
1800   for (uint32_t i = 0; i < nfat_arch; ++i) {
1801     MachOUniversalBinary::ObjectForArch OFA(UB, i);
1802     uint32_t cputype = OFA.getCPUType();
1803     uint32_t cpusubtype = OFA.getCPUSubType();
1804     outs() << "architecture ";
1805     for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
1806       MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
1807       uint32_t other_cputype = other_OFA.getCPUType();
1808       uint32_t other_cpusubtype = other_OFA.getCPUSubType();
1809       if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
1810           (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
1811               (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
1812         outs() << "(illegal duplicate architecture) ";
1813         break;
1814       }
1815     }
1816     if (verbose) {
1817       outs() << OFA.getArchFlagName() << "\n";
1818       printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
1819     } else {
1820       outs() << i << "\n";
1821       outs() << "    cputype " << cputype << "\n";
1822       outs() << "    cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
1823              << "\n";
1824     }
1825     if (verbose &&
1826         (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
1827       outs() << "    capabilities CPU_SUBTYPE_LIB64\n";
1828     else
1829       outs() << "    capabilities "
1830              << format("0x%" PRIx32,
1831                        (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
1832     outs() << "    offset " << OFA.getOffset();
1833     if (OFA.getOffset() > size)
1834       outs() << " (past end of file)";
1835     if (OFA.getOffset() % (1 << OFA.getAlign()) != 0)
1836       outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
1837     outs() << "\n";
1838     outs() << "    size " << OFA.getSize();
1839     big_size = OFA.getOffset() + OFA.getSize();
1840     if (big_size > size)
1841       outs() << " (past end of file)";
1842     outs() << "\n";
1843     outs() << "    align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
1844            << ")\n";
1845   }
1846 }
1847 
printArchiveChild(StringRef Filename,const Archive::Child & C,bool verbose,bool print_offset,StringRef ArchitectureName=StringRef ())1848 static void printArchiveChild(StringRef Filename, const Archive::Child &C,
1849                               bool verbose, bool print_offset,
1850                               StringRef ArchitectureName = StringRef()) {
1851   if (print_offset)
1852     outs() << C.getChildOffset() << "\t";
1853   Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();
1854   if (!ModeOrErr)
1855     report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName);
1856   sys::fs::perms Mode = ModeOrErr.get();
1857   if (verbose) {
1858     // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
1859     // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
1860     outs() << "-";
1861     outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
1862     outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
1863     outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
1864     outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
1865     outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
1866     outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
1867     outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
1868     outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
1869     outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
1870   } else {
1871     outs() << format("0%o ", Mode);
1872   }
1873 
1874   Expected<unsigned> UIDOrErr = C.getUID();
1875   if (!UIDOrErr)
1876     report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName);
1877   unsigned UID = UIDOrErr.get();
1878   outs() << format("%3d/", UID);
1879   Expected<unsigned> GIDOrErr = C.getGID();
1880   if (!GIDOrErr)
1881     report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName);
1882   unsigned GID = GIDOrErr.get();
1883   outs() << format("%-3d ", GID);
1884   Expected<uint64_t> Size = C.getRawSize();
1885   if (!Size)
1886     report_error(Filename, C, Size.takeError(), ArchitectureName);
1887   outs() << format("%5" PRId64, Size.get()) << " ";
1888 
1889   StringRef RawLastModified = C.getRawLastModified();
1890   if (verbose) {
1891     unsigned Seconds;
1892     if (RawLastModified.getAsInteger(10, Seconds))
1893       outs() << "(date: \"" << RawLastModified
1894              << "\" contains non-decimal chars) ";
1895     else {
1896       // Since cime(3) returns a 26 character string of the form:
1897       // "Sun Sep 16 01:03:52 1973\n\0"
1898       // just print 24 characters.
1899       time_t t = Seconds;
1900       outs() << format("%.24s ", ctime(&t));
1901     }
1902   } else {
1903     outs() << RawLastModified << " ";
1904   }
1905 
1906   if (verbose) {
1907     Expected<StringRef> NameOrErr = C.getName();
1908     if (!NameOrErr) {
1909       consumeError(NameOrErr.takeError());
1910       Expected<StringRef> NameOrErr = C.getRawName();
1911       if (!NameOrErr)
1912         report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
1913       StringRef RawName = NameOrErr.get();
1914       outs() << RawName << "\n";
1915     } else {
1916       StringRef Name = NameOrErr.get();
1917       outs() << Name << "\n";
1918     }
1919   } else {
1920     Expected<StringRef> NameOrErr = C.getRawName();
1921     if (!NameOrErr)
1922       report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
1923     StringRef RawName = NameOrErr.get();
1924     outs() << RawName << "\n";
1925   }
1926 }
1927 
printArchiveHeaders(StringRef Filename,Archive * A,bool verbose,bool print_offset,StringRef ArchitectureName=StringRef ())1928 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
1929                                 bool print_offset,
1930                                 StringRef ArchitectureName = StringRef()) {
1931   Error Err = Error::success();
1932   ;
1933   for (const auto &C : A->children(Err, false))
1934     printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName);
1935 
1936   if (Err)
1937     report_error(StringRef(), Filename, std::move(Err), ArchitectureName);
1938 }
1939 
1940 // ParseInputMachO() parses the named Mach-O file in Filename and handles the
1941 // -arch flags selecting just those slices as specified by them and also parses
1942 // archive files.  Then for each individual Mach-O file ProcessMachO() is
1943 // called to process the file based on the command line options.
ParseInputMachO(StringRef Filename)1944 void llvm::ParseInputMachO(StringRef Filename) {
1945   // Check for -arch all and verifiy the -arch flags are valid.
1946   for (unsigned i = 0; i < ArchFlags.size(); ++i) {
1947     if (ArchFlags[i] == "all") {
1948       ArchAll = true;
1949     } else {
1950       if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
1951         errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] +
1952                       "'for the -arch option\n";
1953         return;
1954       }
1955     }
1956   }
1957 
1958   // Attempt to open the binary.
1959   Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
1960   if (!BinaryOrErr) {
1961     if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError()))
1962       report_error(Filename, std::move(E));
1963     else
1964       outs() << Filename << ": is not an object file\n";
1965     return;
1966   }
1967   Binary &Bin = *BinaryOrErr.get().getBinary();
1968 
1969   if (Archive *A = dyn_cast<Archive>(&Bin)) {
1970     outs() << "Archive : " << Filename << "\n";
1971     if (ArchiveHeaders)
1972       printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets);
1973 
1974     Error Err = Error::success();
1975     for (auto &C : A->children(Err)) {
1976       Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
1977       if (!ChildOrErr) {
1978         if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
1979           report_error(Filename, C, std::move(E));
1980         continue;
1981       }
1982       if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
1983         if (!checkMachOAndArchFlags(O, Filename))
1984           return;
1985         ProcessMachO(Filename, O, O->getFileName());
1986       }
1987     }
1988     if (Err)
1989       report_error(Filename, std::move(Err));
1990     return;
1991   }
1992   if (UniversalHeaders) {
1993     if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
1994       printMachOUniversalHeaders(UB, !NonVerbose);
1995   }
1996   if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
1997     // If we have a list of architecture flags specified dump only those.
1998     if (!ArchAll && ArchFlags.size() != 0) {
1999       // Look for a slice in the universal binary that matches each ArchFlag.
2000       bool ArchFound;
2001       for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2002         ArchFound = false;
2003         for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2004                                                    E = UB->end_objects();
2005              I != E; ++I) {
2006           if (ArchFlags[i] == I->getArchFlagName()) {
2007             ArchFound = true;
2008             Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
2009                 I->getAsObjectFile();
2010             std::string ArchitectureName = "";
2011             if (ArchFlags.size() > 1)
2012               ArchitectureName = I->getArchFlagName();
2013             if (ObjOrErr) {
2014               ObjectFile &O = *ObjOrErr.get();
2015               if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2016                 ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2017             } else if (auto E = isNotObjectErrorInvalidFileType(
2018                        ObjOrErr.takeError())) {
2019               report_error(Filename, StringRef(), std::move(E),
2020                            ArchitectureName);
2021               continue;
2022             } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2023                            I->getAsArchive()) {
2024               std::unique_ptr<Archive> &A = *AOrErr;
2025               outs() << "Archive : " << Filename;
2026               if (!ArchitectureName.empty())
2027                 outs() << " (architecture " << ArchitectureName << ")";
2028               outs() << "\n";
2029               if (ArchiveHeaders)
2030                 printArchiveHeaders(Filename, A.get(), !NonVerbose,
2031                                     ArchiveMemberOffsets, ArchitectureName);
2032               Error Err = Error::success();
2033               for (auto &C : A->children(Err)) {
2034                 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2035                 if (!ChildOrErr) {
2036                   if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2037                     report_error(Filename, C, std::move(E), ArchitectureName);
2038                   continue;
2039                 }
2040                 if (MachOObjectFile *O =
2041                         dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2042                   ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
2043               }
2044               if (Err)
2045                 report_error(Filename, std::move(Err));
2046             } else {
2047               consumeError(AOrErr.takeError());
2048               error("Mach-O universal file: " + Filename + " for " +
2049                     "architecture " + StringRef(I->getArchFlagName()) +
2050                     " is not a Mach-O file or an archive file");
2051             }
2052           }
2053         }
2054         if (!ArchFound) {
2055           errs() << "llvm-objdump: file: " + Filename + " does not contain "
2056                  << "architecture: " + ArchFlags[i] + "\n";
2057           return;
2058         }
2059       }
2060       return;
2061     }
2062     // No architecture flags were specified so if this contains a slice that
2063     // matches the host architecture dump only that.
2064     if (!ArchAll) {
2065       for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2066                                                  E = UB->end_objects();
2067            I != E; ++I) {
2068         if (MachOObjectFile::getHostArch().getArchName() ==
2069             I->getArchFlagName()) {
2070           Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2071           std::string ArchiveName;
2072           ArchiveName.clear();
2073           if (ObjOrErr) {
2074             ObjectFile &O = *ObjOrErr.get();
2075             if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2076               ProcessMachO(Filename, MachOOF);
2077           } else if (auto E = isNotObjectErrorInvalidFileType(
2078                      ObjOrErr.takeError())) {
2079             report_error(Filename, std::move(E));
2080             continue;
2081           } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2082                          I->getAsArchive()) {
2083             std::unique_ptr<Archive> &A = *AOrErr;
2084             outs() << "Archive : " << Filename << "\n";
2085             if (ArchiveHeaders)
2086               printArchiveHeaders(Filename, A.get(), !NonVerbose,
2087                                   ArchiveMemberOffsets);
2088             Error Err = Error::success();
2089             for (auto &C : A->children(Err)) {
2090               Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2091               if (!ChildOrErr) {
2092                 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2093                   report_error(Filename, C, std::move(E));
2094                 continue;
2095               }
2096               if (MachOObjectFile *O =
2097                       dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2098                 ProcessMachO(Filename, O, O->getFileName());
2099             }
2100             if (Err)
2101               report_error(Filename, std::move(Err));
2102           } else {
2103             consumeError(AOrErr.takeError());
2104             error("Mach-O universal file: " + Filename + " for architecture " +
2105                   StringRef(I->getArchFlagName()) +
2106                   " is not a Mach-O file or an archive file");
2107           }
2108           return;
2109         }
2110       }
2111     }
2112     // Either all architectures have been specified or none have been specified
2113     // and this does not contain the host architecture so dump all the slices.
2114     bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2115     for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2116                                                E = UB->end_objects();
2117          I != E; ++I) {
2118       Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2119       std::string ArchitectureName = "";
2120       if (moreThanOneArch)
2121         ArchitectureName = I->getArchFlagName();
2122       if (ObjOrErr) {
2123         ObjectFile &Obj = *ObjOrErr.get();
2124         if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
2125           ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2126       } else if (auto E = isNotObjectErrorInvalidFileType(
2127                  ObjOrErr.takeError())) {
2128         report_error(StringRef(), Filename, std::move(E), ArchitectureName);
2129         continue;
2130       } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2131                    I->getAsArchive()) {
2132         std::unique_ptr<Archive> &A = *AOrErr;
2133         outs() << "Archive : " << Filename;
2134         if (!ArchitectureName.empty())
2135           outs() << " (architecture " << ArchitectureName << ")";
2136         outs() << "\n";
2137         if (ArchiveHeaders)
2138           printArchiveHeaders(Filename, A.get(), !NonVerbose,
2139                               ArchiveMemberOffsets, ArchitectureName);
2140         Error Err = Error::success();
2141         for (auto &C : A->children(Err)) {
2142           Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2143           if (!ChildOrErr) {
2144             if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2145               report_error(Filename, C, std::move(E), ArchitectureName);
2146             continue;
2147           }
2148           if (MachOObjectFile *O =
2149                   dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2150             if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
2151               ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
2152                            ArchitectureName);
2153           }
2154         }
2155         if (Err)
2156           report_error(Filename, std::move(Err));
2157       } else {
2158         consumeError(AOrErr.takeError());
2159         error("Mach-O universal file: " + Filename + " for architecture " +
2160               StringRef(I->getArchFlagName()) +
2161               " is not a Mach-O file or an archive file");
2162       }
2163     }
2164     return;
2165   }
2166   if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
2167     if (!checkMachOAndArchFlags(O, Filename))
2168       return;
2169     if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) {
2170       ProcessMachO(Filename, MachOOF);
2171     } else
2172       errs() << "llvm-objdump: '" << Filename << "': "
2173              << "Object is not a Mach-O file type.\n";
2174     return;
2175   }
2176   llvm_unreachable("Input object can't be invalid at this point");
2177 }
2178 
2179 // The block of info used by the Symbolizer call backs.
2180 struct DisassembleInfo {
DisassembleInfoDisassembleInfo2181   DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap,
2182                   std::vector<SectionRef> *Sections, bool verbose)
2183     : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}
2184   bool verbose;
2185   MachOObjectFile *O;
2186   SectionRef S;
2187   SymbolAddressMap *AddrMap;
2188   std::vector<SectionRef> *Sections;
2189   const char *class_name = nullptr;
2190   const char *selector_name = nullptr;
2191   std::unique_ptr<char[]> method = nullptr;
2192   char *demangled_name = nullptr;
2193   uint64_t adrp_addr = 0;
2194   uint32_t adrp_inst = 0;
2195   std::unique_ptr<SymbolAddressMap> bindtable;
2196   uint32_t depth = 0;
2197 };
2198 
2199 // SymbolizerGetOpInfo() is the operand information call back function.
2200 // This is called to get the symbolic information for operand(s) of an
2201 // instruction when it is being done.  This routine does this from
2202 // the relocation information, symbol table, etc. That block of information
2203 // is a pointer to the struct DisassembleInfo that was passed when the
2204 // disassembler context was created and passed to back to here when
2205 // called back by the disassembler for instruction operands that could have
2206 // relocation information. The address of the instruction containing operand is
2207 // at the Pc parameter.  The immediate value the operand has is passed in
2208 // op_info->Value and is at Offset past the start of the instruction and has a
2209 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
2210 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
2211 // names and addends of the symbolic expression to add for the operand.  The
2212 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
2213 // information is returned then this function returns 1 else it returns 0.
SymbolizerGetOpInfo(void * DisInfo,uint64_t Pc,uint64_t Offset,uint64_t Size,int TagType,void * TagBuf)2214 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
2215                                uint64_t Size, int TagType, void *TagBuf) {
2216   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
2217   struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
2218   uint64_t value = op_info->Value;
2219 
2220   // Make sure all fields returned are zero if we don't set them.
2221   memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
2222   op_info->Value = value;
2223 
2224   // If the TagType is not the value 1 which it code knows about or if no
2225   // verbose symbolic information is wanted then just return 0, indicating no
2226   // information is being returned.
2227   if (TagType != 1 || !info->verbose)
2228     return 0;
2229 
2230   unsigned int Arch = info->O->getArch();
2231   if (Arch == Triple::x86) {
2232     if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
2233       return 0;
2234     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2235       // TODO:
2236       // Search the external relocation entries of a fully linked image
2237       // (if any) for an entry that matches this segment offset.
2238       // uint32_t seg_offset = (Pc + Offset);
2239       return 0;
2240     }
2241     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2242     // for an entry for this section offset.
2243     uint32_t sect_addr = info->S.getAddress();
2244     uint32_t sect_offset = (Pc + Offset) - sect_addr;
2245     bool reloc_found = false;
2246     DataRefImpl Rel;
2247     MachO::any_relocation_info RE;
2248     bool isExtern = false;
2249     SymbolRef Symbol;
2250     bool r_scattered = false;
2251     uint32_t r_value, pair_r_value, r_type;
2252     for (const RelocationRef &Reloc : info->S.relocations()) {
2253       uint64_t RelocOffset = Reloc.getOffset();
2254       if (RelocOffset == sect_offset) {
2255         Rel = Reloc.getRawDataRefImpl();
2256         RE = info->O->getRelocation(Rel);
2257         r_type = info->O->getAnyRelocationType(RE);
2258         r_scattered = info->O->isRelocationScattered(RE);
2259         if (r_scattered) {
2260           r_value = info->O->getScatteredRelocationValue(RE);
2261           if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2262               r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
2263             DataRefImpl RelNext = Rel;
2264             info->O->moveRelocationNext(RelNext);
2265             MachO::any_relocation_info RENext;
2266             RENext = info->O->getRelocation(RelNext);
2267             if (info->O->isRelocationScattered(RENext))
2268               pair_r_value = info->O->getScatteredRelocationValue(RENext);
2269             else
2270               return 0;
2271           }
2272         } else {
2273           isExtern = info->O->getPlainRelocationExternal(RE);
2274           if (isExtern) {
2275             symbol_iterator RelocSym = Reloc.getSymbol();
2276             Symbol = *RelocSym;
2277           }
2278         }
2279         reloc_found = true;
2280         break;
2281       }
2282     }
2283     if (reloc_found && isExtern) {
2284       Expected<StringRef> SymName = Symbol.getName();
2285       if (!SymName)
2286         report_error(info->O->getFileName(), SymName.takeError());
2287       const char *name = SymName->data();
2288       op_info->AddSymbol.Present = 1;
2289       op_info->AddSymbol.Name = name;
2290       // For i386 extern relocation entries the value in the instruction is
2291       // the offset from the symbol, and value is already set in op_info->Value.
2292       return 1;
2293     }
2294     if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2295                         r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
2296       const char *add = GuessSymbolName(r_value, info->AddrMap);
2297       const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2298       uint32_t offset = value - (r_value - pair_r_value);
2299       op_info->AddSymbol.Present = 1;
2300       if (add != nullptr)
2301         op_info->AddSymbol.Name = add;
2302       else
2303         op_info->AddSymbol.Value = r_value;
2304       op_info->SubtractSymbol.Present = 1;
2305       if (sub != nullptr)
2306         op_info->SubtractSymbol.Name = sub;
2307       else
2308         op_info->SubtractSymbol.Value = pair_r_value;
2309       op_info->Value = offset;
2310       return 1;
2311     }
2312     return 0;
2313   }
2314   if (Arch == Triple::x86_64) {
2315     if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
2316       return 0;
2317     // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external
2318     // relocation entries of a linked image (if any) for an entry that matches
2319     // this segment offset.
2320     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2321       uint64_t seg_offset = Pc + Offset;
2322       bool reloc_found = false;
2323       DataRefImpl Rel;
2324       MachO::any_relocation_info RE;
2325       bool isExtern = false;
2326       SymbolRef Symbol;
2327       for (const RelocationRef &Reloc : info->O->external_relocations()) {
2328         uint64_t RelocOffset = Reloc.getOffset();
2329         if (RelocOffset == seg_offset) {
2330           Rel = Reloc.getRawDataRefImpl();
2331           RE = info->O->getRelocation(Rel);
2332           // external relocation entries should always be external.
2333           isExtern = info->O->getPlainRelocationExternal(RE);
2334           if (isExtern) {
2335             symbol_iterator RelocSym = Reloc.getSymbol();
2336             Symbol = *RelocSym;
2337           }
2338           reloc_found = true;
2339           break;
2340         }
2341       }
2342       if (reloc_found && isExtern) {
2343         // The Value passed in will be adjusted by the Pc if the instruction
2344         // adds the Pc.  But for x86_64 external relocation entries the Value
2345         // is the offset from the external symbol.
2346         if (info->O->getAnyRelocationPCRel(RE))
2347           op_info->Value -= Pc + Offset + Size;
2348         Expected<StringRef> SymName = Symbol.getName();
2349         if (!SymName)
2350           report_error(info->O->getFileName(), SymName.takeError());
2351         const char *name = SymName->data();
2352         op_info->AddSymbol.Present = 1;
2353         op_info->AddSymbol.Name = name;
2354         return 1;
2355       }
2356       return 0;
2357     }
2358     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2359     // for an entry for this section offset.
2360     uint64_t sect_addr = info->S.getAddress();
2361     uint64_t sect_offset = (Pc + Offset) - sect_addr;
2362     bool reloc_found = false;
2363     DataRefImpl Rel;
2364     MachO::any_relocation_info RE;
2365     bool isExtern = false;
2366     SymbolRef Symbol;
2367     for (const RelocationRef &Reloc : info->S.relocations()) {
2368       uint64_t RelocOffset = Reloc.getOffset();
2369       if (RelocOffset == sect_offset) {
2370         Rel = Reloc.getRawDataRefImpl();
2371         RE = info->O->getRelocation(Rel);
2372         // NOTE: Scattered relocations don't exist on x86_64.
2373         isExtern = info->O->getPlainRelocationExternal(RE);
2374         if (isExtern) {
2375           symbol_iterator RelocSym = Reloc.getSymbol();
2376           Symbol = *RelocSym;
2377         }
2378         reloc_found = true;
2379         break;
2380       }
2381     }
2382     if (reloc_found && isExtern) {
2383       // The Value passed in will be adjusted by the Pc if the instruction
2384       // adds the Pc.  But for x86_64 external relocation entries the Value
2385       // is the offset from the external symbol.
2386       if (info->O->getAnyRelocationPCRel(RE))
2387         op_info->Value -= Pc + Offset + Size;
2388       Expected<StringRef> SymName = Symbol.getName();
2389       if (!SymName)
2390         report_error(info->O->getFileName(), SymName.takeError());
2391       const char *name = SymName->data();
2392       unsigned Type = info->O->getAnyRelocationType(RE);
2393       if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
2394         DataRefImpl RelNext = Rel;
2395         info->O->moveRelocationNext(RelNext);
2396         MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2397         unsigned TypeNext = info->O->getAnyRelocationType(RENext);
2398         bool isExternNext = info->O->getPlainRelocationExternal(RENext);
2399         unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
2400         if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
2401           op_info->SubtractSymbol.Present = 1;
2402           op_info->SubtractSymbol.Name = name;
2403           symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
2404           Symbol = *RelocSymNext;
2405           Expected<StringRef> SymNameNext = Symbol.getName();
2406           if (!SymNameNext)
2407             report_error(info->O->getFileName(), SymNameNext.takeError());
2408           name = SymNameNext->data();
2409         }
2410       }
2411       // TODO: add the VariantKinds to op_info->VariantKind for relocation types
2412       // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
2413       op_info->AddSymbol.Present = 1;
2414       op_info->AddSymbol.Name = name;
2415       return 1;
2416     }
2417     return 0;
2418   }
2419   if (Arch == Triple::arm) {
2420     if (Offset != 0 || (Size != 4 && Size != 2))
2421       return 0;
2422     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2423       // TODO:
2424       // Search the external relocation entries of a fully linked image
2425       // (if any) for an entry that matches this segment offset.
2426       // uint32_t seg_offset = (Pc + Offset);
2427       return 0;
2428     }
2429     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2430     // for an entry for this section offset.
2431     uint32_t sect_addr = info->S.getAddress();
2432     uint32_t sect_offset = (Pc + Offset) - sect_addr;
2433     DataRefImpl Rel;
2434     MachO::any_relocation_info RE;
2435     bool isExtern = false;
2436     SymbolRef Symbol;
2437     bool r_scattered = false;
2438     uint32_t r_value, pair_r_value, r_type, r_length, other_half;
2439     auto Reloc =
2440         find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
2441           uint64_t RelocOffset = Reloc.getOffset();
2442           return RelocOffset == sect_offset;
2443         });
2444 
2445     if (Reloc == info->S.relocations().end())
2446       return 0;
2447 
2448     Rel = Reloc->getRawDataRefImpl();
2449     RE = info->O->getRelocation(Rel);
2450     r_length = info->O->getAnyRelocationLength(RE);
2451     r_scattered = info->O->isRelocationScattered(RE);
2452     if (r_scattered) {
2453       r_value = info->O->getScatteredRelocationValue(RE);
2454       r_type = info->O->getScatteredRelocationType(RE);
2455     } else {
2456       r_type = info->O->getAnyRelocationType(RE);
2457       isExtern = info->O->getPlainRelocationExternal(RE);
2458       if (isExtern) {
2459         symbol_iterator RelocSym = Reloc->getSymbol();
2460         Symbol = *RelocSym;
2461       }
2462     }
2463     if (r_type == MachO::ARM_RELOC_HALF ||
2464         r_type == MachO::ARM_RELOC_SECTDIFF ||
2465         r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
2466         r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2467       DataRefImpl RelNext = Rel;
2468       info->O->moveRelocationNext(RelNext);
2469       MachO::any_relocation_info RENext;
2470       RENext = info->O->getRelocation(RelNext);
2471       other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
2472       if (info->O->isRelocationScattered(RENext))
2473         pair_r_value = info->O->getScatteredRelocationValue(RENext);
2474     }
2475 
2476     if (isExtern) {
2477       Expected<StringRef> SymName = Symbol.getName();
2478       if (!SymName)
2479         report_error(info->O->getFileName(), SymName.takeError());
2480       const char *name = SymName->data();
2481       op_info->AddSymbol.Present = 1;
2482       op_info->AddSymbol.Name = name;
2483       switch (r_type) {
2484       case MachO::ARM_RELOC_HALF:
2485         if ((r_length & 0x1) == 1) {
2486           op_info->Value = value << 16 | other_half;
2487           op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
2488         } else {
2489           op_info->Value = other_half << 16 | value;
2490           op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
2491         }
2492         break;
2493       default:
2494         break;
2495       }
2496       return 1;
2497     }
2498     // If we have a branch that is not an external relocation entry then
2499     // return 0 so the code in tryAddingSymbolicOperand() can use the
2500     // SymbolLookUp call back with the branch target address to look up the
2501     // symbol and possibility add an annotation for a symbol stub.
2502     if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
2503                           r_type == MachO::ARM_THUMB_RELOC_BR22))
2504       return 0;
2505 
2506     uint32_t offset = 0;
2507     if (r_type == MachO::ARM_RELOC_HALF ||
2508         r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2509       if ((r_length & 0x1) == 1)
2510         value = value << 16 | other_half;
2511       else
2512         value = other_half << 16 | value;
2513     }
2514     if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
2515                         r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
2516       offset = value - r_value;
2517       value = r_value;
2518     }
2519 
2520     if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
2521       if ((r_length & 0x1) == 1)
2522         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
2523       else
2524         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
2525       const char *add = GuessSymbolName(r_value, info->AddrMap);
2526       const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2527       int32_t offset = value - (r_value - pair_r_value);
2528       op_info->AddSymbol.Present = 1;
2529       if (add != nullptr)
2530         op_info->AddSymbol.Name = add;
2531       else
2532         op_info->AddSymbol.Value = r_value;
2533       op_info->SubtractSymbol.Present = 1;
2534       if (sub != nullptr)
2535         op_info->SubtractSymbol.Name = sub;
2536       else
2537         op_info->SubtractSymbol.Value = pair_r_value;
2538       op_info->Value = offset;
2539       return 1;
2540     }
2541 
2542     op_info->AddSymbol.Present = 1;
2543     op_info->Value = offset;
2544     if (r_type == MachO::ARM_RELOC_HALF) {
2545       if ((r_length & 0x1) == 1)
2546         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
2547       else
2548         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
2549     }
2550     const char *add = GuessSymbolName(value, info->AddrMap);
2551     if (add != nullptr) {
2552       op_info->AddSymbol.Name = add;
2553       return 1;
2554     }
2555     op_info->AddSymbol.Value = value;
2556     return 1;
2557   }
2558   if (Arch == Triple::aarch64) {
2559     if (Offset != 0 || Size != 4)
2560       return 0;
2561     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2562       // TODO:
2563       // Search the external relocation entries of a fully linked image
2564       // (if any) for an entry that matches this segment offset.
2565       // uint64_t seg_offset = (Pc + Offset);
2566       return 0;
2567     }
2568     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2569     // for an entry for this section offset.
2570     uint64_t sect_addr = info->S.getAddress();
2571     uint64_t sect_offset = (Pc + Offset) - sect_addr;
2572     auto Reloc =
2573         find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
2574           uint64_t RelocOffset = Reloc.getOffset();
2575           return RelocOffset == sect_offset;
2576         });
2577 
2578     if (Reloc == info->S.relocations().end())
2579       return 0;
2580 
2581     DataRefImpl Rel = Reloc->getRawDataRefImpl();
2582     MachO::any_relocation_info RE = info->O->getRelocation(Rel);
2583     uint32_t r_type = info->O->getAnyRelocationType(RE);
2584     if (r_type == MachO::ARM64_RELOC_ADDEND) {
2585       DataRefImpl RelNext = Rel;
2586       info->O->moveRelocationNext(RelNext);
2587       MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2588       if (value == 0) {
2589         value = info->O->getPlainRelocationSymbolNum(RENext);
2590         op_info->Value = value;
2591       }
2592     }
2593     // NOTE: Scattered relocations don't exist on arm64.
2594     if (!info->O->getPlainRelocationExternal(RE))
2595       return 0;
2596     Expected<StringRef> SymName = Reloc->getSymbol()->getName();
2597     if (!SymName)
2598       report_error(info->O->getFileName(), SymName.takeError());
2599     const char *name = SymName->data();
2600     op_info->AddSymbol.Present = 1;
2601     op_info->AddSymbol.Name = name;
2602 
2603     switch (r_type) {
2604     case MachO::ARM64_RELOC_PAGE21:
2605       /* @page */
2606       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
2607       break;
2608     case MachO::ARM64_RELOC_PAGEOFF12:
2609       /* @pageoff */
2610       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
2611       break;
2612     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
2613       /* @gotpage */
2614       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
2615       break;
2616     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
2617       /* @gotpageoff */
2618       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
2619       break;
2620     case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
2621       /* @tvlppage is not implemented in llvm-mc */
2622       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
2623       break;
2624     case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
2625       /* @tvlppageoff is not implemented in llvm-mc */
2626       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
2627       break;
2628     default:
2629     case MachO::ARM64_RELOC_BRANCH26:
2630       op_info->VariantKind = LLVMDisassembler_VariantKind_None;
2631       break;
2632     }
2633     return 1;
2634   }
2635   return 0;
2636 }
2637 
2638 // GuessCstringPointer is passed the address of what might be a pointer to a
2639 // literal string in a cstring section.  If that address is in a cstring section
2640 // it returns a pointer to that string.  Else it returns nullptr.
GuessCstringPointer(uint64_t ReferenceValue,struct DisassembleInfo * info)2641 static const char *GuessCstringPointer(uint64_t ReferenceValue,
2642                                        struct DisassembleInfo *info) {
2643   for (const auto &Load : info->O->load_commands()) {
2644     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2645       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2646       for (unsigned J = 0; J < Seg.nsects; ++J) {
2647         MachO::section_64 Sec = info->O->getSection64(Load, J);
2648         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2649         if (section_type == MachO::S_CSTRING_LITERALS &&
2650             ReferenceValue >= Sec.addr &&
2651             ReferenceValue < Sec.addr + Sec.size) {
2652           uint64_t sect_offset = ReferenceValue - Sec.addr;
2653           uint64_t object_offset = Sec.offset + sect_offset;
2654           StringRef MachOContents = info->O->getData();
2655           uint64_t object_size = MachOContents.size();
2656           const char *object_addr = (const char *)MachOContents.data();
2657           if (object_offset < object_size) {
2658             const char *name = object_addr + object_offset;
2659             return name;
2660           } else {
2661             return nullptr;
2662           }
2663         }
2664       }
2665     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2666       MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2667       for (unsigned J = 0; J < Seg.nsects; ++J) {
2668         MachO::section Sec = info->O->getSection(Load, J);
2669         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2670         if (section_type == MachO::S_CSTRING_LITERALS &&
2671             ReferenceValue >= Sec.addr &&
2672             ReferenceValue < Sec.addr + Sec.size) {
2673           uint64_t sect_offset = ReferenceValue - Sec.addr;
2674           uint64_t object_offset = Sec.offset + sect_offset;
2675           StringRef MachOContents = info->O->getData();
2676           uint64_t object_size = MachOContents.size();
2677           const char *object_addr = (const char *)MachOContents.data();
2678           if (object_offset < object_size) {
2679             const char *name = object_addr + object_offset;
2680             return name;
2681           } else {
2682             return nullptr;
2683           }
2684         }
2685       }
2686     }
2687   }
2688   return nullptr;
2689 }
2690 
2691 // GuessIndirectSymbol returns the name of the indirect symbol for the
2692 // ReferenceValue passed in or nullptr.  This is used when ReferenceValue maybe
2693 // an address of a symbol stub or a lazy or non-lazy pointer to associate the
2694 // symbol name being referenced by the stub or pointer.
GuessIndirectSymbol(uint64_t ReferenceValue,struct DisassembleInfo * info)2695 static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
2696                                        struct DisassembleInfo *info) {
2697   MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
2698   MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
2699   for (const auto &Load : info->O->load_commands()) {
2700     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2701       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2702       for (unsigned J = 0; J < Seg.nsects; ++J) {
2703         MachO::section_64 Sec = info->O->getSection64(Load, J);
2704         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2705         if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2706              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2707              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2708              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2709              section_type == MachO::S_SYMBOL_STUBS) &&
2710             ReferenceValue >= Sec.addr &&
2711             ReferenceValue < Sec.addr + Sec.size) {
2712           uint32_t stride;
2713           if (section_type == MachO::S_SYMBOL_STUBS)
2714             stride = Sec.reserved2;
2715           else
2716             stride = 8;
2717           if (stride == 0)
2718             return nullptr;
2719           uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2720           if (index < Dysymtab.nindirectsyms) {
2721             uint32_t indirect_symbol =
2722                 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2723             if (indirect_symbol < Symtab.nsyms) {
2724               symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2725               SymbolRef Symbol = *Sym;
2726               Expected<StringRef> SymName = Symbol.getName();
2727               if (!SymName)
2728                 report_error(info->O->getFileName(), SymName.takeError());
2729               const char *name = SymName->data();
2730               return name;
2731             }
2732           }
2733         }
2734       }
2735     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
2736       MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
2737       for (unsigned J = 0; J < Seg.nsects; ++J) {
2738         MachO::section Sec = info->O->getSection(Load, J);
2739         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
2740         if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
2741              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
2742              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
2743              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
2744              section_type == MachO::S_SYMBOL_STUBS) &&
2745             ReferenceValue >= Sec.addr &&
2746             ReferenceValue < Sec.addr + Sec.size) {
2747           uint32_t stride;
2748           if (section_type == MachO::S_SYMBOL_STUBS)
2749             stride = Sec.reserved2;
2750           else
2751             stride = 4;
2752           if (stride == 0)
2753             return nullptr;
2754           uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
2755           if (index < Dysymtab.nindirectsyms) {
2756             uint32_t indirect_symbol =
2757                 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
2758             if (indirect_symbol < Symtab.nsyms) {
2759               symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
2760               SymbolRef Symbol = *Sym;
2761               Expected<StringRef> SymName = Symbol.getName();
2762               if (!SymName)
2763                 report_error(info->O->getFileName(), SymName.takeError());
2764               const char *name = SymName->data();
2765               return name;
2766             }
2767           }
2768         }
2769       }
2770     }
2771   }
2772   return nullptr;
2773 }
2774 
2775 // method_reference() is called passing it the ReferenceName that might be
2776 // a reference it to an Objective-C method call.  If so then it allocates and
2777 // assembles a method call string with the values last seen and saved in
2778 // the DisassembleInfo's class_name and selector_name fields.  This is saved
2779 // into the method field of the info and any previous string is free'ed.
2780 // Then the class_name field in the info is set to nullptr.  The method call
2781 // string is set into ReferenceName and ReferenceType is set to
2782 // LLVMDisassembler_ReferenceType_Out_Objc_Message.  If this not a method call
2783 // then both ReferenceType and ReferenceName are left unchanged.
method_reference(struct DisassembleInfo * info,uint64_t * ReferenceType,const char ** ReferenceName)2784 static void method_reference(struct DisassembleInfo *info,
2785                              uint64_t *ReferenceType,
2786                              const char **ReferenceName) {
2787   unsigned int Arch = info->O->getArch();
2788   if (*ReferenceName != nullptr) {
2789     if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
2790       if (info->selector_name != nullptr) {
2791         if (info->class_name != nullptr) {
2792           info->method = llvm::make_unique<char[]>(
2793               5 + strlen(info->class_name) + strlen(info->selector_name));
2794           char *method = info->method.get();
2795           if (method != nullptr) {
2796             strcpy(method, "+[");
2797             strcat(method, info->class_name);
2798             strcat(method, " ");
2799             strcat(method, info->selector_name);
2800             strcat(method, "]");
2801             *ReferenceName = method;
2802             *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
2803           }
2804         } else {
2805           info->method =
2806               llvm::make_unique<char[]>(9 + strlen(info->selector_name));
2807           char *method = info->method.get();
2808           if (method != nullptr) {
2809             if (Arch == Triple::x86_64)
2810               strcpy(method, "-[%rdi ");
2811             else if (Arch == Triple::aarch64)
2812               strcpy(method, "-[x0 ");
2813             else
2814               strcpy(method, "-[r? ");
2815             strcat(method, info->selector_name);
2816             strcat(method, "]");
2817             *ReferenceName = method;
2818             *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
2819           }
2820         }
2821         info->class_name = nullptr;
2822       }
2823     } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
2824       if (info->selector_name != nullptr) {
2825         info->method =
2826             llvm::make_unique<char[]>(17 + strlen(info->selector_name));
2827         char *method = info->method.get();
2828         if (method != nullptr) {
2829           if (Arch == Triple::x86_64)
2830             strcpy(method, "-[[%rdi super] ");
2831           else if (Arch == Triple::aarch64)
2832             strcpy(method, "-[[x0 super] ");
2833           else
2834             strcpy(method, "-[[r? super] ");
2835           strcat(method, info->selector_name);
2836           strcat(method, "]");
2837           *ReferenceName = method;
2838           *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
2839         }
2840         info->class_name = nullptr;
2841       }
2842     }
2843   }
2844 }
2845 
2846 // GuessPointerPointer() is passed the address of what might be a pointer to
2847 // a reference to an Objective-C class, selector, message ref or cfstring.
2848 // If so the value of the pointer is returned and one of the booleans are set
2849 // to true.  If not zero is returned and all the booleans are set to false.
GuessPointerPointer(uint64_t ReferenceValue,struct DisassembleInfo * info,bool & classref,bool & selref,bool & msgref,bool & cfstring)2850 static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
2851                                     struct DisassembleInfo *info,
2852                                     bool &classref, bool &selref, bool &msgref,
2853                                     bool &cfstring) {
2854   classref = false;
2855   selref = false;
2856   msgref = false;
2857   cfstring = false;
2858   for (const auto &Load : info->O->load_commands()) {
2859     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
2860       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
2861       for (unsigned J = 0; J < Seg.nsects; ++J) {
2862         MachO::section_64 Sec = info->O->getSection64(Load, J);
2863         if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
2864              strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2865              strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
2866              strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
2867              strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
2868             ReferenceValue >= Sec.addr &&
2869             ReferenceValue < Sec.addr + Sec.size) {
2870           uint64_t sect_offset = ReferenceValue - Sec.addr;
2871           uint64_t object_offset = Sec.offset + sect_offset;
2872           StringRef MachOContents = info->O->getData();
2873           uint64_t object_size = MachOContents.size();
2874           const char *object_addr = (const char *)MachOContents.data();
2875           if (object_offset < object_size) {
2876             uint64_t pointer_value;
2877             memcpy(&pointer_value, object_addr + object_offset,
2878                    sizeof(uint64_t));
2879             if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2880               sys::swapByteOrder(pointer_value);
2881             if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
2882               selref = true;
2883             else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
2884                      strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
2885               classref = true;
2886             else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
2887                      ReferenceValue + 8 < Sec.addr + Sec.size) {
2888               msgref = true;
2889               memcpy(&pointer_value, object_addr + object_offset + 8,
2890                      sizeof(uint64_t));
2891               if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
2892                 sys::swapByteOrder(pointer_value);
2893             } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
2894               cfstring = true;
2895             return pointer_value;
2896           } else {
2897             return 0;
2898           }
2899         }
2900       }
2901     }
2902     // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
2903   }
2904   return 0;
2905 }
2906 
2907 // get_pointer_64 returns a pointer to the bytes in the object file at the
2908 // Address from a section in the Mach-O file.  And indirectly returns the
2909 // offset into the section, number of bytes left in the section past the offset
2910 // and which section is was being referenced.  If the Address is not in a
2911 // section nullptr is returned.
get_pointer_64(uint64_t Address,uint32_t & offset,uint32_t & left,SectionRef & S,DisassembleInfo * info,bool objc_only=false)2912 static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
2913                                   uint32_t &left, SectionRef &S,
2914                                   DisassembleInfo *info,
2915                                   bool objc_only = false) {
2916   offset = 0;
2917   left = 0;
2918   S = SectionRef();
2919   for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
2920     uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
2921     uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
2922     if (SectSize == 0)
2923       continue;
2924     if (objc_only) {
2925       StringRef SectName;
2926       ((*(info->Sections))[SectIdx]).getName(SectName);
2927       DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
2928       StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
2929       if (SegName != "__OBJC" && SectName != "__cstring")
2930         continue;
2931     }
2932     if (Address >= SectAddress && Address < SectAddress + SectSize) {
2933       S = (*(info->Sections))[SectIdx];
2934       offset = Address - SectAddress;
2935       left = SectSize - offset;
2936       StringRef SectContents;
2937       ((*(info->Sections))[SectIdx]).getContents(SectContents);
2938       return SectContents.data() + offset;
2939     }
2940   }
2941   return nullptr;
2942 }
2943 
get_pointer_32(uint32_t Address,uint32_t & offset,uint32_t & left,SectionRef & S,DisassembleInfo * info,bool objc_only=false)2944 static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
2945                                   uint32_t &left, SectionRef &S,
2946                                   DisassembleInfo *info,
2947                                   bool objc_only = false) {
2948   return get_pointer_64(Address, offset, left, S, info, objc_only);
2949 }
2950 
2951 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of
2952 // the symbol indirectly through n_value. Based on the relocation information
2953 // for the specified section offset in the specified section reference.
2954 // If no relocation information is found and a non-zero ReferenceValue for the
2955 // symbol is passed, look up that address in the info's AddrMap.
get_symbol_64(uint32_t sect_offset,SectionRef S,DisassembleInfo * info,uint64_t & n_value,uint64_t ReferenceValue=0)2956 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
2957                                  DisassembleInfo *info, uint64_t &n_value,
2958                                  uint64_t ReferenceValue = 0) {
2959   n_value = 0;
2960   if (!info->verbose)
2961     return nullptr;
2962 
2963   // See if there is an external relocation entry at the sect_offset.
2964   bool reloc_found = false;
2965   DataRefImpl Rel;
2966   MachO::any_relocation_info RE;
2967   bool isExtern = false;
2968   SymbolRef Symbol;
2969   for (const RelocationRef &Reloc : S.relocations()) {
2970     uint64_t RelocOffset = Reloc.getOffset();
2971     if (RelocOffset == sect_offset) {
2972       Rel = Reloc.getRawDataRefImpl();
2973       RE = info->O->getRelocation(Rel);
2974       if (info->O->isRelocationScattered(RE))
2975         continue;
2976       isExtern = info->O->getPlainRelocationExternal(RE);
2977       if (isExtern) {
2978         symbol_iterator RelocSym = Reloc.getSymbol();
2979         Symbol = *RelocSym;
2980       }
2981       reloc_found = true;
2982       break;
2983     }
2984   }
2985   // If there is an external relocation entry for a symbol in this section
2986   // at this section_offset then use that symbol's value for the n_value
2987   // and return its name.
2988   const char *SymbolName = nullptr;
2989   if (reloc_found && isExtern) {
2990     n_value = Symbol.getValue();
2991     Expected<StringRef> NameOrError = Symbol.getName();
2992     if (!NameOrError)
2993       report_error(info->O->getFileName(), NameOrError.takeError());
2994     StringRef Name = *NameOrError;
2995     if (!Name.empty()) {
2996       SymbolName = Name.data();
2997       return SymbolName;
2998     }
2999   }
3000 
3001   // TODO: For fully linked images, look through the external relocation
3002   // entries off the dynamic symtab command. For these the r_offset is from the
3003   // start of the first writeable segment in the Mach-O file.  So the offset
3004   // to this section from that segment is passed to this routine by the caller,
3005   // as the database_offset. Which is the difference of the section's starting
3006   // address and the first writable segment.
3007   //
3008   // NOTE: need add passing the database_offset to this routine.
3009 
3010   // We did not find an external relocation entry so look up the ReferenceValue
3011   // as an address of a symbol and if found return that symbol's name.
3012   SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
3013 
3014   return SymbolName;
3015 }
3016 
get_symbol_32(uint32_t sect_offset,SectionRef S,DisassembleInfo * info,uint32_t ReferenceValue)3017 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
3018                                  DisassembleInfo *info,
3019                                  uint32_t ReferenceValue) {
3020   uint64_t n_value64;
3021   return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
3022 }
3023 
3024 // These are structs in the Objective-C meta data and read to produce the
3025 // comments for disassembly.  While these are part of the ABI they are no
3026 // public defintions.  So the are here not in include/llvm/BinaryFormat/MachO.h
3027 // .
3028 
3029 // The cfstring object in a 64-bit Mach-O file.
3030 struct cfstring64_t {
3031   uint64_t isa;        // class64_t * (64-bit pointer)
3032   uint64_t flags;      // flag bits
3033   uint64_t characters; // char * (64-bit pointer)
3034   uint64_t length;     // number of non-NULL characters in above
3035 };
3036 
3037 // The class object in a 64-bit Mach-O file.
3038 struct class64_t {
3039   uint64_t isa;        // class64_t * (64-bit pointer)
3040   uint64_t superclass; // class64_t * (64-bit pointer)
3041   uint64_t cache;      // Cache (64-bit pointer)
3042   uint64_t vtable;     // IMP * (64-bit pointer)
3043   uint64_t data;       // class_ro64_t * (64-bit pointer)
3044 };
3045 
3046 struct class32_t {
3047   uint32_t isa;        /* class32_t * (32-bit pointer) */
3048   uint32_t superclass; /* class32_t * (32-bit pointer) */
3049   uint32_t cache;      /* Cache (32-bit pointer) */
3050   uint32_t vtable;     /* IMP * (32-bit pointer) */
3051   uint32_t data;       /* class_ro32_t * (32-bit pointer) */
3052 };
3053 
3054 struct class_ro64_t {
3055   uint32_t flags;
3056   uint32_t instanceStart;
3057   uint32_t instanceSize;
3058   uint32_t reserved;
3059   uint64_t ivarLayout;     // const uint8_t * (64-bit pointer)
3060   uint64_t name;           // const char * (64-bit pointer)
3061   uint64_t baseMethods;    // const method_list_t * (64-bit pointer)
3062   uint64_t baseProtocols;  // const protocol_list_t * (64-bit pointer)
3063   uint64_t ivars;          // const ivar_list_t * (64-bit pointer)
3064   uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
3065   uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
3066 };
3067 
3068 struct class_ro32_t {
3069   uint32_t flags;
3070   uint32_t instanceStart;
3071   uint32_t instanceSize;
3072   uint32_t ivarLayout;     /* const uint8_t * (32-bit pointer) */
3073   uint32_t name;           /* const char * (32-bit pointer) */
3074   uint32_t baseMethods;    /* const method_list_t * (32-bit pointer) */
3075   uint32_t baseProtocols;  /* const protocol_list_t * (32-bit pointer) */
3076   uint32_t ivars;          /* const ivar_list_t * (32-bit pointer) */
3077   uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
3078   uint32_t baseProperties; /* const struct objc_property_list *
3079                                                    (32-bit pointer) */
3080 };
3081 
3082 /* Values for class_ro{64,32}_t->flags */
3083 #define RO_META (1 << 0)
3084 #define RO_ROOT (1 << 1)
3085 #define RO_HAS_CXX_STRUCTORS (1 << 2)
3086 
3087 struct method_list64_t {
3088   uint32_t entsize;
3089   uint32_t count;
3090   /* struct method64_t first;  These structures follow inline */
3091 };
3092 
3093 struct method_list32_t {
3094   uint32_t entsize;
3095   uint32_t count;
3096   /* struct method32_t first;  These structures follow inline */
3097 };
3098 
3099 struct method64_t {
3100   uint64_t name;  /* SEL (64-bit pointer) */
3101   uint64_t types; /* const char * (64-bit pointer) */
3102   uint64_t imp;   /* IMP (64-bit pointer) */
3103 };
3104 
3105 struct method32_t {
3106   uint32_t name;  /* SEL (32-bit pointer) */
3107   uint32_t types; /* const char * (32-bit pointer) */
3108   uint32_t imp;   /* IMP (32-bit pointer) */
3109 };
3110 
3111 struct protocol_list64_t {
3112   uint64_t count; /* uintptr_t (a 64-bit value) */
3113   /* struct protocol64_t * list[0];  These pointers follow inline */
3114 };
3115 
3116 struct protocol_list32_t {
3117   uint32_t count; /* uintptr_t (a 32-bit value) */
3118   /* struct protocol32_t * list[0];  These pointers follow inline */
3119 };
3120 
3121 struct protocol64_t {
3122   uint64_t isa;                     /* id * (64-bit pointer) */
3123   uint64_t name;                    /* const char * (64-bit pointer) */
3124   uint64_t protocols;               /* struct protocol_list64_t *
3125                                                     (64-bit pointer) */
3126   uint64_t instanceMethods;         /* method_list_t * (64-bit pointer) */
3127   uint64_t classMethods;            /* method_list_t * (64-bit pointer) */
3128   uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
3129   uint64_t optionalClassMethods;    /* method_list_t * (64-bit pointer) */
3130   uint64_t instanceProperties;      /* struct objc_property_list *
3131                                                        (64-bit pointer) */
3132 };
3133 
3134 struct protocol32_t {
3135   uint32_t isa;                     /* id * (32-bit pointer) */
3136   uint32_t name;                    /* const char * (32-bit pointer) */
3137   uint32_t protocols;               /* struct protocol_list_t *
3138                                                     (32-bit pointer) */
3139   uint32_t instanceMethods;         /* method_list_t * (32-bit pointer) */
3140   uint32_t classMethods;            /* method_list_t * (32-bit pointer) */
3141   uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
3142   uint32_t optionalClassMethods;    /* method_list_t * (32-bit pointer) */
3143   uint32_t instanceProperties;      /* struct objc_property_list *
3144                                                        (32-bit pointer) */
3145 };
3146 
3147 struct ivar_list64_t {
3148   uint32_t entsize;
3149   uint32_t count;
3150   /* struct ivar64_t first;  These structures follow inline */
3151 };
3152 
3153 struct ivar_list32_t {
3154   uint32_t entsize;
3155   uint32_t count;
3156   /* struct ivar32_t first;  These structures follow inline */
3157 };
3158 
3159 struct ivar64_t {
3160   uint64_t offset; /* uintptr_t * (64-bit pointer) */
3161   uint64_t name;   /* const char * (64-bit pointer) */
3162   uint64_t type;   /* const char * (64-bit pointer) */
3163   uint32_t alignment;
3164   uint32_t size;
3165 };
3166 
3167 struct ivar32_t {
3168   uint32_t offset; /* uintptr_t * (32-bit pointer) */
3169   uint32_t name;   /* const char * (32-bit pointer) */
3170   uint32_t type;   /* const char * (32-bit pointer) */
3171   uint32_t alignment;
3172   uint32_t size;
3173 };
3174 
3175 struct objc_property_list64 {
3176   uint32_t entsize;
3177   uint32_t count;
3178   /* struct objc_property64 first;  These structures follow inline */
3179 };
3180 
3181 struct objc_property_list32 {
3182   uint32_t entsize;
3183   uint32_t count;
3184   /* struct objc_property32 first;  These structures follow inline */
3185 };
3186 
3187 struct objc_property64 {
3188   uint64_t name;       /* const char * (64-bit pointer) */
3189   uint64_t attributes; /* const char * (64-bit pointer) */
3190 };
3191 
3192 struct objc_property32 {
3193   uint32_t name;       /* const char * (32-bit pointer) */
3194   uint32_t attributes; /* const char * (32-bit pointer) */
3195 };
3196 
3197 struct category64_t {
3198   uint64_t name;               /* const char * (64-bit pointer) */
3199   uint64_t cls;                /* struct class_t * (64-bit pointer) */
3200   uint64_t instanceMethods;    /* struct method_list_t * (64-bit pointer) */
3201   uint64_t classMethods;       /* struct method_list_t * (64-bit pointer) */
3202   uint64_t protocols;          /* struct protocol_list_t * (64-bit pointer) */
3203   uint64_t instanceProperties; /* struct objc_property_list *
3204                                   (64-bit pointer) */
3205 };
3206 
3207 struct category32_t {
3208   uint32_t name;               /* const char * (32-bit pointer) */
3209   uint32_t cls;                /* struct class_t * (32-bit pointer) */
3210   uint32_t instanceMethods;    /* struct method_list_t * (32-bit pointer) */
3211   uint32_t classMethods;       /* struct method_list_t * (32-bit pointer) */
3212   uint32_t protocols;          /* struct protocol_list_t * (32-bit pointer) */
3213   uint32_t instanceProperties; /* struct objc_property_list *
3214                                   (32-bit pointer) */
3215 };
3216 
3217 struct objc_image_info64 {
3218   uint32_t version;
3219   uint32_t flags;
3220 };
3221 struct objc_image_info32 {
3222   uint32_t version;
3223   uint32_t flags;
3224 };
3225 struct imageInfo_t {
3226   uint32_t version;
3227   uint32_t flags;
3228 };
3229 /* masks for objc_image_info.flags */
3230 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
3231 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
3232 #define OBJC_IMAGE_IS_SIMULATED (1 << 5)
3233 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)
3234 
3235 struct message_ref64 {
3236   uint64_t imp; /* IMP (64-bit pointer) */
3237   uint64_t sel; /* SEL (64-bit pointer) */
3238 };
3239 
3240 struct message_ref32 {
3241   uint32_t imp; /* IMP (32-bit pointer) */
3242   uint32_t sel; /* SEL (32-bit pointer) */
3243 };
3244 
3245 // Objective-C 1 (32-bit only) meta data structs.
3246 
3247 struct objc_module_t {
3248   uint32_t version;
3249   uint32_t size;
3250   uint32_t name;   /* char * (32-bit pointer) */
3251   uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
3252 };
3253 
3254 struct objc_symtab_t {
3255   uint32_t sel_ref_cnt;
3256   uint32_t refs; /* SEL * (32-bit pointer) */
3257   uint16_t cls_def_cnt;
3258   uint16_t cat_def_cnt;
3259   // uint32_t defs[1];        /* void * (32-bit pointer) variable size */
3260 };
3261 
3262 struct objc_class_t {
3263   uint32_t isa;         /* struct objc_class * (32-bit pointer) */
3264   uint32_t super_class; /* struct objc_class * (32-bit pointer) */
3265   uint32_t name;        /* const char * (32-bit pointer) */
3266   int32_t version;
3267   int32_t info;
3268   int32_t instance_size;
3269   uint32_t ivars;       /* struct objc_ivar_list * (32-bit pointer) */
3270   uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
3271   uint32_t cache;       /* struct objc_cache * (32-bit pointer) */
3272   uint32_t protocols;   /* struct objc_protocol_list * (32-bit pointer) */
3273 };
3274 
3275 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
3276 // class is not a metaclass
3277 #define CLS_CLASS 0x1
3278 // class is a metaclass
3279 #define CLS_META 0x2
3280 
3281 struct objc_category_t {
3282   uint32_t category_name;    /* char * (32-bit pointer) */
3283   uint32_t class_name;       /* char * (32-bit pointer) */
3284   uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
3285   uint32_t class_methods;    /* struct objc_method_list * (32-bit pointer) */
3286   uint32_t protocols;        /* struct objc_protocol_list * (32-bit ptr) */
3287 };
3288 
3289 struct objc_ivar_t {
3290   uint32_t ivar_name; /* char * (32-bit pointer) */
3291   uint32_t ivar_type; /* char * (32-bit pointer) */
3292   int32_t ivar_offset;
3293 };
3294 
3295 struct objc_ivar_list_t {
3296   int32_t ivar_count;
3297   // struct objc_ivar_t ivar_list[1];          /* variable length structure */
3298 };
3299 
3300 struct objc_method_list_t {
3301   uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
3302   int32_t method_count;
3303   // struct objc_method_t method_list[1];      /* variable length structure */
3304 };
3305 
3306 struct objc_method_t {
3307   uint32_t method_name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3308   uint32_t method_types; /* char * (32-bit pointer) */
3309   uint32_t method_imp;   /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
3310                             (32-bit pointer) */
3311 };
3312 
3313 struct objc_protocol_list_t {
3314   uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
3315   int32_t count;
3316   // uint32_t list[1];   /* Protocol *, aka struct objc_protocol_t *
3317   //                        (32-bit pointer) */
3318 };
3319 
3320 struct objc_protocol_t {
3321   uint32_t isa;              /* struct objc_class * (32-bit pointer) */
3322   uint32_t protocol_name;    /* char * (32-bit pointer) */
3323   uint32_t protocol_list;    /* struct objc_protocol_list * (32-bit pointer) */
3324   uint32_t instance_methods; /* struct objc_method_description_list *
3325                                 (32-bit pointer) */
3326   uint32_t class_methods;    /* struct objc_method_description_list *
3327                                 (32-bit pointer) */
3328 };
3329 
3330 struct objc_method_description_list_t {
3331   int32_t count;
3332   // struct objc_method_description_t list[1];
3333 };
3334 
3335 struct objc_method_description_t {
3336   uint32_t name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3337   uint32_t types; /* char * (32-bit pointer) */
3338 };
3339 
swapStruct(struct cfstring64_t & cfs)3340 inline void swapStruct(struct cfstring64_t &cfs) {
3341   sys::swapByteOrder(cfs.isa);
3342   sys::swapByteOrder(cfs.flags);
3343   sys::swapByteOrder(cfs.characters);
3344   sys::swapByteOrder(cfs.length);
3345 }
3346 
swapStruct(struct class64_t & c)3347 inline void swapStruct(struct class64_t &c) {
3348   sys::swapByteOrder(c.isa);
3349   sys::swapByteOrder(c.superclass);
3350   sys::swapByteOrder(c.cache);
3351   sys::swapByteOrder(c.vtable);
3352   sys::swapByteOrder(c.data);
3353 }
3354 
swapStruct(struct class32_t & c)3355 inline void swapStruct(struct class32_t &c) {
3356   sys::swapByteOrder(c.isa);
3357   sys::swapByteOrder(c.superclass);
3358   sys::swapByteOrder(c.cache);
3359   sys::swapByteOrder(c.vtable);
3360   sys::swapByteOrder(c.data);
3361 }
3362 
swapStruct(struct class_ro64_t & cro)3363 inline void swapStruct(struct class_ro64_t &cro) {
3364   sys::swapByteOrder(cro.flags);
3365   sys::swapByteOrder(cro.instanceStart);
3366   sys::swapByteOrder(cro.instanceSize);
3367   sys::swapByteOrder(cro.reserved);
3368   sys::swapByteOrder(cro.ivarLayout);
3369   sys::swapByteOrder(cro.name);
3370   sys::swapByteOrder(cro.baseMethods);
3371   sys::swapByteOrder(cro.baseProtocols);
3372   sys::swapByteOrder(cro.ivars);
3373   sys::swapByteOrder(cro.weakIvarLayout);
3374   sys::swapByteOrder(cro.baseProperties);
3375 }
3376 
swapStruct(struct class_ro32_t & cro)3377 inline void swapStruct(struct class_ro32_t &cro) {
3378   sys::swapByteOrder(cro.flags);
3379   sys::swapByteOrder(cro.instanceStart);
3380   sys::swapByteOrder(cro.instanceSize);
3381   sys::swapByteOrder(cro.ivarLayout);
3382   sys::swapByteOrder(cro.name);
3383   sys::swapByteOrder(cro.baseMethods);
3384   sys::swapByteOrder(cro.baseProtocols);
3385   sys::swapByteOrder(cro.ivars);
3386   sys::swapByteOrder(cro.weakIvarLayout);
3387   sys::swapByteOrder(cro.baseProperties);
3388 }
3389 
swapStruct(struct method_list64_t & ml)3390 inline void swapStruct(struct method_list64_t &ml) {
3391   sys::swapByteOrder(ml.entsize);
3392   sys::swapByteOrder(ml.count);
3393 }
3394 
swapStruct(struct method_list32_t & ml)3395 inline void swapStruct(struct method_list32_t &ml) {
3396   sys::swapByteOrder(ml.entsize);
3397   sys::swapByteOrder(ml.count);
3398 }
3399 
swapStruct(struct method64_t & m)3400 inline void swapStruct(struct method64_t &m) {
3401   sys::swapByteOrder(m.name);
3402   sys::swapByteOrder(m.types);
3403   sys::swapByteOrder(m.imp);
3404 }
3405 
swapStruct(struct method32_t & m)3406 inline void swapStruct(struct method32_t &m) {
3407   sys::swapByteOrder(m.name);
3408   sys::swapByteOrder(m.types);
3409   sys::swapByteOrder(m.imp);
3410 }
3411 
swapStruct(struct protocol_list64_t & pl)3412 inline void swapStruct(struct protocol_list64_t &pl) {
3413   sys::swapByteOrder(pl.count);
3414 }
3415 
swapStruct(struct protocol_list32_t & pl)3416 inline void swapStruct(struct protocol_list32_t &pl) {
3417   sys::swapByteOrder(pl.count);
3418 }
3419 
swapStruct(struct protocol64_t & p)3420 inline void swapStruct(struct protocol64_t &p) {
3421   sys::swapByteOrder(p.isa);
3422   sys::swapByteOrder(p.name);
3423   sys::swapByteOrder(p.protocols);
3424   sys::swapByteOrder(p.instanceMethods);
3425   sys::swapByteOrder(p.classMethods);
3426   sys::swapByteOrder(p.optionalInstanceMethods);
3427   sys::swapByteOrder(p.optionalClassMethods);
3428   sys::swapByteOrder(p.instanceProperties);
3429 }
3430 
swapStruct(struct protocol32_t & p)3431 inline void swapStruct(struct protocol32_t &p) {
3432   sys::swapByteOrder(p.isa);
3433   sys::swapByteOrder(p.name);
3434   sys::swapByteOrder(p.protocols);
3435   sys::swapByteOrder(p.instanceMethods);
3436   sys::swapByteOrder(p.classMethods);
3437   sys::swapByteOrder(p.optionalInstanceMethods);
3438   sys::swapByteOrder(p.optionalClassMethods);
3439   sys::swapByteOrder(p.instanceProperties);
3440 }
3441 
swapStruct(struct ivar_list64_t & il)3442 inline void swapStruct(struct ivar_list64_t &il) {
3443   sys::swapByteOrder(il.entsize);
3444   sys::swapByteOrder(il.count);
3445 }
3446 
swapStruct(struct ivar_list32_t & il)3447 inline void swapStruct(struct ivar_list32_t &il) {
3448   sys::swapByteOrder(il.entsize);
3449   sys::swapByteOrder(il.count);
3450 }
3451 
swapStruct(struct ivar64_t & i)3452 inline void swapStruct(struct ivar64_t &i) {
3453   sys::swapByteOrder(i.offset);
3454   sys::swapByteOrder(i.name);
3455   sys::swapByteOrder(i.type);
3456   sys::swapByteOrder(i.alignment);
3457   sys::swapByteOrder(i.size);
3458 }
3459 
swapStruct(struct ivar32_t & i)3460 inline void swapStruct(struct ivar32_t &i) {
3461   sys::swapByteOrder(i.offset);
3462   sys::swapByteOrder(i.name);
3463   sys::swapByteOrder(i.type);
3464   sys::swapByteOrder(i.alignment);
3465   sys::swapByteOrder(i.size);
3466 }
3467 
swapStruct(struct objc_property_list64 & pl)3468 inline void swapStruct(struct objc_property_list64 &pl) {
3469   sys::swapByteOrder(pl.entsize);
3470   sys::swapByteOrder(pl.count);
3471 }
3472 
swapStruct(struct objc_property_list32 & pl)3473 inline void swapStruct(struct objc_property_list32 &pl) {
3474   sys::swapByteOrder(pl.entsize);
3475   sys::swapByteOrder(pl.count);
3476 }
3477 
swapStruct(struct objc_property64 & op)3478 inline void swapStruct(struct objc_property64 &op) {
3479   sys::swapByteOrder(op.name);
3480   sys::swapByteOrder(op.attributes);
3481 }
3482 
swapStruct(struct objc_property32 & op)3483 inline void swapStruct(struct objc_property32 &op) {
3484   sys::swapByteOrder(op.name);
3485   sys::swapByteOrder(op.attributes);
3486 }
3487 
swapStruct(struct category64_t & c)3488 inline void swapStruct(struct category64_t &c) {
3489   sys::swapByteOrder(c.name);
3490   sys::swapByteOrder(c.cls);
3491   sys::swapByteOrder(c.instanceMethods);
3492   sys::swapByteOrder(c.classMethods);
3493   sys::swapByteOrder(c.protocols);
3494   sys::swapByteOrder(c.instanceProperties);
3495 }
3496 
swapStruct(struct category32_t & c)3497 inline void swapStruct(struct category32_t &c) {
3498   sys::swapByteOrder(c.name);
3499   sys::swapByteOrder(c.cls);
3500   sys::swapByteOrder(c.instanceMethods);
3501   sys::swapByteOrder(c.classMethods);
3502   sys::swapByteOrder(c.protocols);
3503   sys::swapByteOrder(c.instanceProperties);
3504 }
3505 
swapStruct(struct objc_image_info64 & o)3506 inline void swapStruct(struct objc_image_info64 &o) {
3507   sys::swapByteOrder(o.version);
3508   sys::swapByteOrder(o.flags);
3509 }
3510 
swapStruct(struct objc_image_info32 & o)3511 inline void swapStruct(struct objc_image_info32 &o) {
3512   sys::swapByteOrder(o.version);
3513   sys::swapByteOrder(o.flags);
3514 }
3515 
swapStruct(struct imageInfo_t & o)3516 inline void swapStruct(struct imageInfo_t &o) {
3517   sys::swapByteOrder(o.version);
3518   sys::swapByteOrder(o.flags);
3519 }
3520 
swapStruct(struct message_ref64 & mr)3521 inline void swapStruct(struct message_ref64 &mr) {
3522   sys::swapByteOrder(mr.imp);
3523   sys::swapByteOrder(mr.sel);
3524 }
3525 
swapStruct(struct message_ref32 & mr)3526 inline void swapStruct(struct message_ref32 &mr) {
3527   sys::swapByteOrder(mr.imp);
3528   sys::swapByteOrder(mr.sel);
3529 }
3530 
swapStruct(struct objc_module_t & module)3531 inline void swapStruct(struct objc_module_t &module) {
3532   sys::swapByteOrder(module.version);
3533   sys::swapByteOrder(module.size);
3534   sys::swapByteOrder(module.name);
3535   sys::swapByteOrder(module.symtab);
3536 }
3537 
swapStruct(struct objc_symtab_t & symtab)3538 inline void swapStruct(struct objc_symtab_t &symtab) {
3539   sys::swapByteOrder(symtab.sel_ref_cnt);
3540   sys::swapByteOrder(symtab.refs);
3541   sys::swapByteOrder(symtab.cls_def_cnt);
3542   sys::swapByteOrder(symtab.cat_def_cnt);
3543 }
3544 
swapStruct(struct objc_class_t & objc_class)3545 inline void swapStruct(struct objc_class_t &objc_class) {
3546   sys::swapByteOrder(objc_class.isa);
3547   sys::swapByteOrder(objc_class.super_class);
3548   sys::swapByteOrder(objc_class.name);
3549   sys::swapByteOrder(objc_class.version);
3550   sys::swapByteOrder(objc_class.info);
3551   sys::swapByteOrder(objc_class.instance_size);
3552   sys::swapByteOrder(objc_class.ivars);
3553   sys::swapByteOrder(objc_class.methodLists);
3554   sys::swapByteOrder(objc_class.cache);
3555   sys::swapByteOrder(objc_class.protocols);
3556 }
3557 
swapStruct(struct objc_category_t & objc_category)3558 inline void swapStruct(struct objc_category_t &objc_category) {
3559   sys::swapByteOrder(objc_category.category_name);
3560   sys::swapByteOrder(objc_category.class_name);
3561   sys::swapByteOrder(objc_category.instance_methods);
3562   sys::swapByteOrder(objc_category.class_methods);
3563   sys::swapByteOrder(objc_category.protocols);
3564 }
3565 
swapStruct(struct objc_ivar_list_t & objc_ivar_list)3566 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
3567   sys::swapByteOrder(objc_ivar_list.ivar_count);
3568 }
3569 
swapStruct(struct objc_ivar_t & objc_ivar)3570 inline void swapStruct(struct objc_ivar_t &objc_ivar) {
3571   sys::swapByteOrder(objc_ivar.ivar_name);
3572   sys::swapByteOrder(objc_ivar.ivar_type);
3573   sys::swapByteOrder(objc_ivar.ivar_offset);
3574 }
3575 
swapStruct(struct objc_method_list_t & method_list)3576 inline void swapStruct(struct objc_method_list_t &method_list) {
3577   sys::swapByteOrder(method_list.obsolete);
3578   sys::swapByteOrder(method_list.method_count);
3579 }
3580 
swapStruct(struct objc_method_t & method)3581 inline void swapStruct(struct objc_method_t &method) {
3582   sys::swapByteOrder(method.method_name);
3583   sys::swapByteOrder(method.method_types);
3584   sys::swapByteOrder(method.method_imp);
3585 }
3586 
swapStruct(struct objc_protocol_list_t & protocol_list)3587 inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
3588   sys::swapByteOrder(protocol_list.next);
3589   sys::swapByteOrder(protocol_list.count);
3590 }
3591 
swapStruct(struct objc_protocol_t & protocol)3592 inline void swapStruct(struct objc_protocol_t &protocol) {
3593   sys::swapByteOrder(protocol.isa);
3594   sys::swapByteOrder(protocol.protocol_name);
3595   sys::swapByteOrder(protocol.protocol_list);
3596   sys::swapByteOrder(protocol.instance_methods);
3597   sys::swapByteOrder(protocol.class_methods);
3598 }
3599 
swapStruct(struct objc_method_description_list_t & mdl)3600 inline void swapStruct(struct objc_method_description_list_t &mdl) {
3601   sys::swapByteOrder(mdl.count);
3602 }
3603 
swapStruct(struct objc_method_description_t & md)3604 inline void swapStruct(struct objc_method_description_t &md) {
3605   sys::swapByteOrder(md.name);
3606   sys::swapByteOrder(md.types);
3607 }
3608 
3609 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
3610                                                  struct DisassembleInfo *info);
3611 
3612 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
3613 // to an Objective-C class and returns the class name.  It is also passed the
3614 // address of the pointer, so when the pointer is zero as it can be in an .o
3615 // file, that is used to look for an external relocation entry with a symbol
3616 // name.
get_objc2_64bit_class_name(uint64_t pointer_value,uint64_t ReferenceValue,struct DisassembleInfo * info)3617 static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
3618                                               uint64_t ReferenceValue,
3619                                               struct DisassembleInfo *info) {
3620   const char *r;
3621   uint32_t offset, left;
3622   SectionRef S;
3623 
3624   // The pointer_value can be 0 in an object file and have a relocation
3625   // entry for the class symbol at the ReferenceValue (the address of the
3626   // pointer).
3627   if (pointer_value == 0) {
3628     r = get_pointer_64(ReferenceValue, offset, left, S, info);
3629     if (r == nullptr || left < sizeof(uint64_t))
3630       return nullptr;
3631     uint64_t n_value;
3632     const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3633     if (symbol_name == nullptr)
3634       return nullptr;
3635     const char *class_name = strrchr(symbol_name, '$');
3636     if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
3637       return class_name + 2;
3638     else
3639       return nullptr;
3640   }
3641 
3642   // The case were the pointer_value is non-zero and points to a class defined
3643   // in this Mach-O file.
3644   r = get_pointer_64(pointer_value, offset, left, S, info);
3645   if (r == nullptr || left < sizeof(struct class64_t))
3646     return nullptr;
3647   struct class64_t c;
3648   memcpy(&c, r, sizeof(struct class64_t));
3649   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3650     swapStruct(c);
3651   if (c.data == 0)
3652     return nullptr;
3653   r = get_pointer_64(c.data, offset, left, S, info);
3654   if (r == nullptr || left < sizeof(struct class_ro64_t))
3655     return nullptr;
3656   struct class_ro64_t cro;
3657   memcpy(&cro, r, sizeof(struct class_ro64_t));
3658   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3659     swapStruct(cro);
3660   if (cro.name == 0)
3661     return nullptr;
3662   const char *name = get_pointer_64(cro.name, offset, left, S, info);
3663   return name;
3664 }
3665 
3666 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a
3667 // pointer to a cfstring and returns its name or nullptr.
get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,struct DisassembleInfo * info)3668 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
3669                                                  struct DisassembleInfo *info) {
3670   const char *r, *name;
3671   uint32_t offset, left;
3672   SectionRef S;
3673   struct cfstring64_t cfs;
3674   uint64_t cfs_characters;
3675 
3676   r = get_pointer_64(ReferenceValue, offset, left, S, info);
3677   if (r == nullptr || left < sizeof(struct cfstring64_t))
3678     return nullptr;
3679   memcpy(&cfs, r, sizeof(struct cfstring64_t));
3680   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3681     swapStruct(cfs);
3682   if (cfs.characters == 0) {
3683     uint64_t n_value;
3684     const char *symbol_name = get_symbol_64(
3685         offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
3686     if (symbol_name == nullptr)
3687       return nullptr;
3688     cfs_characters = n_value;
3689   } else
3690     cfs_characters = cfs.characters;
3691   name = get_pointer_64(cfs_characters, offset, left, S, info);
3692 
3693   return name;
3694 }
3695 
3696 // get_objc2_64bit_selref() is used for disassembly and is passed a the address
3697 // of a pointer to an Objective-C selector reference when the pointer value is
3698 // zero as in a .o file and is likely to have a external relocation entry with
3699 // who's symbol's n_value is the real pointer to the selector name.  If that is
3700 // the case the real pointer to the selector name is returned else 0 is
3701 // returned
get_objc2_64bit_selref(uint64_t ReferenceValue,struct DisassembleInfo * info)3702 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
3703                                        struct DisassembleInfo *info) {
3704   uint32_t offset, left;
3705   SectionRef S;
3706 
3707   const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
3708   if (r == nullptr || left < sizeof(uint64_t))
3709     return 0;
3710   uint64_t n_value;
3711   const char *symbol_name = get_symbol_64(offset, S, info, n_value);
3712   if (symbol_name == nullptr)
3713     return 0;
3714   return n_value;
3715 }
3716 
get_section(MachOObjectFile * O,const char * segname,const char * sectname)3717 static const SectionRef get_section(MachOObjectFile *O, const char *segname,
3718                                     const char *sectname) {
3719   for (const SectionRef &Section : O->sections()) {
3720     StringRef SectName;
3721     Section.getName(SectName);
3722     DataRefImpl Ref = Section.getRawDataRefImpl();
3723     StringRef SegName = O->getSectionFinalSegmentName(Ref);
3724     if (SegName == segname && SectName == sectname)
3725       return Section;
3726   }
3727   return SectionRef();
3728 }
3729 
3730 static void
walk_pointer_list_64(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint64_t,struct DisassembleInfo * info))3731 walk_pointer_list_64(const char *listname, const SectionRef S,
3732                      MachOObjectFile *O, struct DisassembleInfo *info,
3733                      void (*func)(uint64_t, struct DisassembleInfo *info)) {
3734   if (S == SectionRef())
3735     return;
3736 
3737   StringRef SectName;
3738   S.getName(SectName);
3739   DataRefImpl Ref = S.getRawDataRefImpl();
3740   StringRef SegName = O->getSectionFinalSegmentName(Ref);
3741   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3742 
3743   StringRef BytesStr;
3744   S.getContents(BytesStr);
3745   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3746 
3747   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
3748     uint32_t left = S.getSize() - i;
3749     uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
3750     uint64_t p = 0;
3751     memcpy(&p, Contents + i, size);
3752     if (i + sizeof(uint64_t) > S.getSize())
3753       outs() << listname << " list pointer extends past end of (" << SegName
3754              << "," << SectName << ") section\n";
3755     outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
3756 
3757     if (O->isLittleEndian() != sys::IsLittleEndianHost)
3758       sys::swapByteOrder(p);
3759 
3760     uint64_t n_value = 0;
3761     const char *name = get_symbol_64(i, S, info, n_value, p);
3762     if (name == nullptr)
3763       name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
3764 
3765     if (n_value != 0) {
3766       outs() << format("0x%" PRIx64, n_value);
3767       if (p != 0)
3768         outs() << " + " << format("0x%" PRIx64, p);
3769     } else
3770       outs() << format("0x%" PRIx64, p);
3771     if (name != nullptr)
3772       outs() << " " << name;
3773     outs() << "\n";
3774 
3775     p += n_value;
3776     if (func)
3777       func(p, info);
3778   }
3779 }
3780 
3781 static void
walk_pointer_list_32(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint32_t,struct DisassembleInfo * info))3782 walk_pointer_list_32(const char *listname, const SectionRef S,
3783                      MachOObjectFile *O, struct DisassembleInfo *info,
3784                      void (*func)(uint32_t, struct DisassembleInfo *info)) {
3785   if (S == SectionRef())
3786     return;
3787 
3788   StringRef SectName;
3789   S.getName(SectName);
3790   DataRefImpl Ref = S.getRawDataRefImpl();
3791   StringRef SegName = O->getSectionFinalSegmentName(Ref);
3792   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
3793 
3794   StringRef BytesStr;
3795   S.getContents(BytesStr);
3796   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
3797 
3798   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
3799     uint32_t left = S.getSize() - i;
3800     uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
3801     uint32_t p = 0;
3802     memcpy(&p, Contents + i, size);
3803     if (i + sizeof(uint32_t) > S.getSize())
3804       outs() << listname << " list pointer extends past end of (" << SegName
3805              << "," << SectName << ") section\n";
3806     uint32_t Address = S.getAddress() + i;
3807     outs() << format("%08" PRIx32, Address) << " ";
3808 
3809     if (O->isLittleEndian() != sys::IsLittleEndianHost)
3810       sys::swapByteOrder(p);
3811     outs() << format("0x%" PRIx32, p);
3812 
3813     const char *name = get_symbol_32(i, S, info, p);
3814     if (name != nullptr)
3815       outs() << " " << name;
3816     outs() << "\n";
3817 
3818     if (func)
3819       func(p, info);
3820   }
3821 }
3822 
print_layout_map(const char * layout_map,uint32_t left)3823 static void print_layout_map(const char *layout_map, uint32_t left) {
3824   if (layout_map == nullptr)
3825     return;
3826   outs() << "                layout map: ";
3827   do {
3828     outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
3829     left--;
3830     layout_map++;
3831   } while (*layout_map != '\0' && left != 0);
3832   outs() << "\n";
3833 }
3834 
print_layout_map64(uint64_t p,struct DisassembleInfo * info)3835 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
3836   uint32_t offset, left;
3837   SectionRef S;
3838   const char *layout_map;
3839 
3840   if (p == 0)
3841     return;
3842   layout_map = get_pointer_64(p, offset, left, S, info);
3843   print_layout_map(layout_map, left);
3844 }
3845 
print_layout_map32(uint32_t p,struct DisassembleInfo * info)3846 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
3847   uint32_t offset, left;
3848   SectionRef S;
3849   const char *layout_map;
3850 
3851   if (p == 0)
3852     return;
3853   layout_map = get_pointer_32(p, offset, left, S, info);
3854   print_layout_map(layout_map, left);
3855 }
3856 
print_method_list64_t(uint64_t p,struct DisassembleInfo * info,const char * indent)3857 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
3858                                   const char *indent) {
3859   struct method_list64_t ml;
3860   struct method64_t m;
3861   const char *r;
3862   uint32_t offset, xoffset, left, i;
3863   SectionRef S, xS;
3864   const char *name, *sym_name;
3865   uint64_t n_value;
3866 
3867   r = get_pointer_64(p, offset, left, S, info);
3868   if (r == nullptr)
3869     return;
3870   memset(&ml, '\0', sizeof(struct method_list64_t));
3871   if (left < sizeof(struct method_list64_t)) {
3872     memcpy(&ml, r, left);
3873     outs() << "   (method_list_t entends past the end of the section)\n";
3874   } else
3875     memcpy(&ml, r, sizeof(struct method_list64_t));
3876   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3877     swapStruct(ml);
3878   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
3879   outs() << indent << "\t\t     count " << ml.count << "\n";
3880 
3881   p += sizeof(struct method_list64_t);
3882   offset += sizeof(struct method_list64_t);
3883   for (i = 0; i < ml.count; i++) {
3884     r = get_pointer_64(p, offset, left, S, info);
3885     if (r == nullptr)
3886       return;
3887     memset(&m, '\0', sizeof(struct method64_t));
3888     if (left < sizeof(struct method64_t)) {
3889       memcpy(&m, r, left);
3890       outs() << indent << "   (method_t extends past the end of the section)\n";
3891     } else
3892       memcpy(&m, r, sizeof(struct method64_t));
3893     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3894       swapStruct(m);
3895 
3896     outs() << indent << "\t\t      name ";
3897     sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
3898                              info, n_value, m.name);
3899     if (n_value != 0) {
3900       if (info->verbose && sym_name != nullptr)
3901         outs() << sym_name;
3902       else
3903         outs() << format("0x%" PRIx64, n_value);
3904       if (m.name != 0)
3905         outs() << " + " << format("0x%" PRIx64, m.name);
3906     } else
3907       outs() << format("0x%" PRIx64, m.name);
3908     name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
3909     if (name != nullptr)
3910       outs() << format(" %.*s", left, name);
3911     outs() << "\n";
3912 
3913     outs() << indent << "\t\t     types ";
3914     sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
3915                              info, n_value, m.types);
3916     if (n_value != 0) {
3917       if (info->verbose && sym_name != nullptr)
3918         outs() << sym_name;
3919       else
3920         outs() << format("0x%" PRIx64, n_value);
3921       if (m.types != 0)
3922         outs() << " + " << format("0x%" PRIx64, m.types);
3923     } else
3924       outs() << format("0x%" PRIx64, m.types);
3925     name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
3926     if (name != nullptr)
3927       outs() << format(" %.*s", left, name);
3928     outs() << "\n";
3929 
3930     outs() << indent << "\t\t       imp ";
3931     name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
3932                          n_value, m.imp);
3933     if (info->verbose && name == nullptr) {
3934       if (n_value != 0) {
3935         outs() << format("0x%" PRIx64, n_value) << " ";
3936         if (m.imp != 0)
3937           outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
3938       } else
3939         outs() << format("0x%" PRIx64, m.imp) << " ";
3940     }
3941     if (name != nullptr)
3942       outs() << name;
3943     outs() << "\n";
3944 
3945     p += sizeof(struct method64_t);
3946     offset += sizeof(struct method64_t);
3947   }
3948 }
3949 
print_method_list32_t(uint64_t p,struct DisassembleInfo * info,const char * indent)3950 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
3951                                   const char *indent) {
3952   struct method_list32_t ml;
3953   struct method32_t m;
3954   const char *r, *name;
3955   uint32_t offset, xoffset, left, i;
3956   SectionRef S, xS;
3957 
3958   r = get_pointer_32(p, offset, left, S, info);
3959   if (r == nullptr)
3960     return;
3961   memset(&ml, '\0', sizeof(struct method_list32_t));
3962   if (left < sizeof(struct method_list32_t)) {
3963     memcpy(&ml, r, left);
3964     outs() << "   (method_list_t entends past the end of the section)\n";
3965   } else
3966     memcpy(&ml, r, sizeof(struct method_list32_t));
3967   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3968     swapStruct(ml);
3969   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
3970   outs() << indent << "\t\t     count " << ml.count << "\n";
3971 
3972   p += sizeof(struct method_list32_t);
3973   offset += sizeof(struct method_list32_t);
3974   for (i = 0; i < ml.count; i++) {
3975     r = get_pointer_32(p, offset, left, S, info);
3976     if (r == nullptr)
3977       return;
3978     memset(&m, '\0', sizeof(struct method32_t));
3979     if (left < sizeof(struct method32_t)) {
3980       memcpy(&ml, r, left);
3981       outs() << indent << "   (method_t entends past the end of the section)\n";
3982     } else
3983       memcpy(&m, r, sizeof(struct method32_t));
3984     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3985       swapStruct(m);
3986 
3987     outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
3988     name = get_pointer_32(m.name, xoffset, left, xS, info);
3989     if (name != nullptr)
3990       outs() << format(" %.*s", left, name);
3991     outs() << "\n";
3992 
3993     outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
3994     name = get_pointer_32(m.types, xoffset, left, xS, info);
3995     if (name != nullptr)
3996       outs() << format(" %.*s", left, name);
3997     outs() << "\n";
3998 
3999     outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
4000     name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
4001                          m.imp);
4002     if (name != nullptr)
4003       outs() << " " << name;
4004     outs() << "\n";
4005 
4006     p += sizeof(struct method32_t);
4007     offset += sizeof(struct method32_t);
4008   }
4009 }
4010 
print_method_list(uint32_t p,struct DisassembleInfo * info)4011 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
4012   uint32_t offset, left, xleft;
4013   SectionRef S;
4014   struct objc_method_list_t method_list;
4015   struct objc_method_t method;
4016   const char *r, *methods, *name, *SymbolName;
4017   int32_t i;
4018 
4019   r = get_pointer_32(p, offset, left, S, info, true);
4020   if (r == nullptr)
4021     return true;
4022 
4023   outs() << "\n";
4024   if (left > sizeof(struct objc_method_list_t)) {
4025     memcpy(&method_list, r, sizeof(struct objc_method_list_t));
4026   } else {
4027     outs() << "\t\t objc_method_list extends past end of the section\n";
4028     memset(&method_list, '\0', sizeof(struct objc_method_list_t));
4029     memcpy(&method_list, r, left);
4030   }
4031   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4032     swapStruct(method_list);
4033 
4034   outs() << "\t\t         obsolete "
4035          << format("0x%08" PRIx32, method_list.obsolete) << "\n";
4036   outs() << "\t\t     method_count " << method_list.method_count << "\n";
4037 
4038   methods = r + sizeof(struct objc_method_list_t);
4039   for (i = 0; i < method_list.method_count; i++) {
4040     if ((i + 1) * sizeof(struct objc_method_t) > left) {
4041       outs() << "\t\t remaining method's extend past the of the section\n";
4042       break;
4043     }
4044     memcpy(&method, methods + i * sizeof(struct objc_method_t),
4045            sizeof(struct objc_method_t));
4046     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4047       swapStruct(method);
4048 
4049     outs() << "\t\t      method_name "
4050            << format("0x%08" PRIx32, method.method_name);
4051     if (info->verbose) {
4052       name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
4053       if (name != nullptr)
4054         outs() << format(" %.*s", xleft, name);
4055       else
4056         outs() << " (not in an __OBJC section)";
4057     }
4058     outs() << "\n";
4059 
4060     outs() << "\t\t     method_types "
4061            << format("0x%08" PRIx32, method.method_types);
4062     if (info->verbose) {
4063       name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
4064       if (name != nullptr)
4065         outs() << format(" %.*s", xleft, name);
4066       else
4067         outs() << " (not in an __OBJC section)";
4068     }
4069     outs() << "\n";
4070 
4071     outs() << "\t\t       method_imp "
4072            << format("0x%08" PRIx32, method.method_imp) << " ";
4073     if (info->verbose) {
4074       SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
4075       if (SymbolName != nullptr)
4076         outs() << SymbolName;
4077     }
4078     outs() << "\n";
4079   }
4080   return false;
4081 }
4082 
print_protocol_list64_t(uint64_t p,struct DisassembleInfo * info)4083 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
4084   struct protocol_list64_t pl;
4085   uint64_t q, n_value;
4086   struct protocol64_t pc;
4087   const char *r;
4088   uint32_t offset, xoffset, left, i;
4089   SectionRef S, xS;
4090   const char *name, *sym_name;
4091 
4092   r = get_pointer_64(p, offset, left, S, info);
4093   if (r == nullptr)
4094     return;
4095   memset(&pl, '\0', sizeof(struct protocol_list64_t));
4096   if (left < sizeof(struct protocol_list64_t)) {
4097     memcpy(&pl, r, left);
4098     outs() << "   (protocol_list_t entends past the end of the section)\n";
4099   } else
4100     memcpy(&pl, r, sizeof(struct protocol_list64_t));
4101   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4102     swapStruct(pl);
4103   outs() << "                      count " << pl.count << "\n";
4104 
4105   p += sizeof(struct protocol_list64_t);
4106   offset += sizeof(struct protocol_list64_t);
4107   for (i = 0; i < pl.count; i++) {
4108     r = get_pointer_64(p, offset, left, S, info);
4109     if (r == nullptr)
4110       return;
4111     q = 0;
4112     if (left < sizeof(uint64_t)) {
4113       memcpy(&q, r, left);
4114       outs() << "   (protocol_t * entends past the end of the section)\n";
4115     } else
4116       memcpy(&q, r, sizeof(uint64_t));
4117     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4118       sys::swapByteOrder(q);
4119 
4120     outs() << "\t\t      list[" << i << "] ";
4121     sym_name = get_symbol_64(offset, S, info, n_value, q);
4122     if (n_value != 0) {
4123       if (info->verbose && sym_name != nullptr)
4124         outs() << sym_name;
4125       else
4126         outs() << format("0x%" PRIx64, n_value);
4127       if (q != 0)
4128         outs() << " + " << format("0x%" PRIx64, q);
4129     } else
4130       outs() << format("0x%" PRIx64, q);
4131     outs() << " (struct protocol_t *)\n";
4132 
4133     r = get_pointer_64(q + n_value, offset, left, S, info);
4134     if (r == nullptr)
4135       return;
4136     memset(&pc, '\0', sizeof(struct protocol64_t));
4137     if (left < sizeof(struct protocol64_t)) {
4138       memcpy(&pc, r, left);
4139       outs() << "   (protocol_t entends past the end of the section)\n";
4140     } else
4141       memcpy(&pc, r, sizeof(struct protocol64_t));
4142     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4143       swapStruct(pc);
4144 
4145     outs() << "\t\t\t      isa " << format("0x%" PRIx64, pc.isa) << "\n";
4146 
4147     outs() << "\t\t\t     name ";
4148     sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
4149                              info, n_value, pc.name);
4150     if (n_value != 0) {
4151       if (info->verbose && sym_name != nullptr)
4152         outs() << sym_name;
4153       else
4154         outs() << format("0x%" PRIx64, n_value);
4155       if (pc.name != 0)
4156         outs() << " + " << format("0x%" PRIx64, pc.name);
4157     } else
4158       outs() << format("0x%" PRIx64, pc.name);
4159     name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
4160     if (name != nullptr)
4161       outs() << format(" %.*s", left, name);
4162     outs() << "\n";
4163 
4164     outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
4165 
4166     outs() << "\t\t  instanceMethods ";
4167     sym_name =
4168         get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
4169                       S, info, n_value, pc.instanceMethods);
4170     if (n_value != 0) {
4171       if (info->verbose && sym_name != nullptr)
4172         outs() << sym_name;
4173       else
4174         outs() << format("0x%" PRIx64, n_value);
4175       if (pc.instanceMethods != 0)
4176         outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
4177     } else
4178       outs() << format("0x%" PRIx64, pc.instanceMethods);
4179     outs() << " (struct method_list_t *)\n";
4180     if (pc.instanceMethods + n_value != 0)
4181       print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
4182 
4183     outs() << "\t\t     classMethods ";
4184     sym_name =
4185         get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
4186                       info, n_value, pc.classMethods);
4187     if (n_value != 0) {
4188       if (info->verbose && sym_name != nullptr)
4189         outs() << sym_name;
4190       else
4191         outs() << format("0x%" PRIx64, n_value);
4192       if (pc.classMethods != 0)
4193         outs() << " + " << format("0x%" PRIx64, pc.classMethods);
4194     } else
4195       outs() << format("0x%" PRIx64, pc.classMethods);
4196     outs() << " (struct method_list_t *)\n";
4197     if (pc.classMethods + n_value != 0)
4198       print_method_list64_t(pc.classMethods + n_value, info, "\t");
4199 
4200     outs() << "\t  optionalInstanceMethods "
4201            << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
4202     outs() << "\t     optionalClassMethods "
4203            << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
4204     outs() << "\t       instanceProperties "
4205            << format("0x%" PRIx64, pc.instanceProperties) << "\n";
4206 
4207     p += sizeof(uint64_t);
4208     offset += sizeof(uint64_t);
4209   }
4210 }
4211 
print_protocol_list32_t(uint32_t p,struct DisassembleInfo * info)4212 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
4213   struct protocol_list32_t pl;
4214   uint32_t q;
4215   struct protocol32_t pc;
4216   const char *r;
4217   uint32_t offset, xoffset, left, i;
4218   SectionRef S, xS;
4219   const char *name;
4220 
4221   r = get_pointer_32(p, offset, left, S, info);
4222   if (r == nullptr)
4223     return;
4224   memset(&pl, '\0', sizeof(struct protocol_list32_t));
4225   if (left < sizeof(struct protocol_list32_t)) {
4226     memcpy(&pl, r, left);
4227     outs() << "   (protocol_list_t entends past the end of the section)\n";
4228   } else
4229     memcpy(&pl, r, sizeof(struct protocol_list32_t));
4230   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4231     swapStruct(pl);
4232   outs() << "                      count " << pl.count << "\n";
4233 
4234   p += sizeof(struct protocol_list32_t);
4235   offset += sizeof(struct protocol_list32_t);
4236   for (i = 0; i < pl.count; i++) {
4237     r = get_pointer_32(p, offset, left, S, info);
4238     if (r == nullptr)
4239       return;
4240     q = 0;
4241     if (left < sizeof(uint32_t)) {
4242       memcpy(&q, r, left);
4243       outs() << "   (protocol_t * entends past the end of the section)\n";
4244     } else
4245       memcpy(&q, r, sizeof(uint32_t));
4246     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4247       sys::swapByteOrder(q);
4248     outs() << "\t\t      list[" << i << "] " << format("0x%" PRIx32, q)
4249            << " (struct protocol_t *)\n";
4250     r = get_pointer_32(q, offset, left, S, info);
4251     if (r == nullptr)
4252       return;
4253     memset(&pc, '\0', sizeof(struct protocol32_t));
4254     if (left < sizeof(struct protocol32_t)) {
4255       memcpy(&pc, r, left);
4256       outs() << "   (protocol_t entends past the end of the section)\n";
4257     } else
4258       memcpy(&pc, r, sizeof(struct protocol32_t));
4259     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4260       swapStruct(pc);
4261     outs() << "\t\t\t      isa " << format("0x%" PRIx32, pc.isa) << "\n";
4262     outs() << "\t\t\t     name " << format("0x%" PRIx32, pc.name);
4263     name = get_pointer_32(pc.name, xoffset, left, xS, info);
4264     if (name != nullptr)
4265       outs() << format(" %.*s", left, name);
4266     outs() << "\n";
4267     outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
4268     outs() << "\t\t  instanceMethods "
4269            << format("0x%" PRIx32, pc.instanceMethods)
4270            << " (struct method_list_t *)\n";
4271     if (pc.instanceMethods != 0)
4272       print_method_list32_t(pc.instanceMethods, info, "\t");
4273     outs() << "\t\t     classMethods " << format("0x%" PRIx32, pc.classMethods)
4274            << " (struct method_list_t *)\n";
4275     if (pc.classMethods != 0)
4276       print_method_list32_t(pc.classMethods, info, "\t");
4277     outs() << "\t  optionalInstanceMethods "
4278            << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
4279     outs() << "\t     optionalClassMethods "
4280            << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
4281     outs() << "\t       instanceProperties "
4282            << format("0x%" PRIx32, pc.instanceProperties) << "\n";
4283     p += sizeof(uint32_t);
4284     offset += sizeof(uint32_t);
4285   }
4286 }
4287 
print_indent(uint32_t indent)4288 static void print_indent(uint32_t indent) {
4289   for (uint32_t i = 0; i < indent;) {
4290     if (indent - i >= 8) {
4291       outs() << "\t";
4292       i += 8;
4293     } else {
4294       for (uint32_t j = i; j < indent; j++)
4295         outs() << " ";
4296       return;
4297     }
4298   }
4299 }
4300 
print_method_description_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)4301 static bool print_method_description_list(uint32_t p, uint32_t indent,
4302                                           struct DisassembleInfo *info) {
4303   uint32_t offset, left, xleft;
4304   SectionRef S;
4305   struct objc_method_description_list_t mdl;
4306   struct objc_method_description_t md;
4307   const char *r, *list, *name;
4308   int32_t i;
4309 
4310   r = get_pointer_32(p, offset, left, S, info, true);
4311   if (r == nullptr)
4312     return true;
4313 
4314   outs() << "\n";
4315   if (left > sizeof(struct objc_method_description_list_t)) {
4316     memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
4317   } else {
4318     print_indent(indent);
4319     outs() << " objc_method_description_list extends past end of the section\n";
4320     memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
4321     memcpy(&mdl, r, left);
4322   }
4323   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4324     swapStruct(mdl);
4325 
4326   print_indent(indent);
4327   outs() << "        count " << mdl.count << "\n";
4328 
4329   list = r + sizeof(struct objc_method_description_list_t);
4330   for (i = 0; i < mdl.count; i++) {
4331     if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
4332       print_indent(indent);
4333       outs() << " remaining list entries extend past the of the section\n";
4334       break;
4335     }
4336     print_indent(indent);
4337     outs() << "        list[" << i << "]\n";
4338     memcpy(&md, list + i * sizeof(struct objc_method_description_t),
4339            sizeof(struct objc_method_description_t));
4340     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4341       swapStruct(md);
4342 
4343     print_indent(indent);
4344     outs() << "             name " << format("0x%08" PRIx32, md.name);
4345     if (info->verbose) {
4346       name = get_pointer_32(md.name, offset, xleft, S, info, true);
4347       if (name != nullptr)
4348         outs() << format(" %.*s", xleft, name);
4349       else
4350         outs() << " (not in an __OBJC section)";
4351     }
4352     outs() << "\n";
4353 
4354     print_indent(indent);
4355     outs() << "            types " << format("0x%08" PRIx32, md.types);
4356     if (info->verbose) {
4357       name = get_pointer_32(md.types, offset, xleft, S, info, true);
4358       if (name != nullptr)
4359         outs() << format(" %.*s", xleft, name);
4360       else
4361         outs() << " (not in an __OBJC section)";
4362     }
4363     outs() << "\n";
4364   }
4365   return false;
4366 }
4367 
4368 static bool print_protocol_list(uint32_t p, uint32_t indent,
4369                                 struct DisassembleInfo *info);
4370 
print_protocol(uint32_t p,uint32_t indent,struct DisassembleInfo * info)4371 static bool print_protocol(uint32_t p, uint32_t indent,
4372                            struct DisassembleInfo *info) {
4373   uint32_t offset, left;
4374   SectionRef S;
4375   struct objc_protocol_t protocol;
4376   const char *r, *name;
4377 
4378   r = get_pointer_32(p, offset, left, S, info, true);
4379   if (r == nullptr)
4380     return true;
4381 
4382   outs() << "\n";
4383   if (left >= sizeof(struct objc_protocol_t)) {
4384     memcpy(&protocol, r, sizeof(struct objc_protocol_t));
4385   } else {
4386     print_indent(indent);
4387     outs() << "            Protocol extends past end of the section\n";
4388     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
4389     memcpy(&protocol, r, left);
4390   }
4391   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4392     swapStruct(protocol);
4393 
4394   print_indent(indent);
4395   outs() << "              isa " << format("0x%08" PRIx32, protocol.isa)
4396          << "\n";
4397 
4398   print_indent(indent);
4399   outs() << "    protocol_name "
4400          << format("0x%08" PRIx32, protocol.protocol_name);
4401   if (info->verbose) {
4402     name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
4403     if (name != nullptr)
4404       outs() << format(" %.*s", left, name);
4405     else
4406       outs() << " (not in an __OBJC section)";
4407   }
4408   outs() << "\n";
4409 
4410   print_indent(indent);
4411   outs() << "    protocol_list "
4412          << format("0x%08" PRIx32, protocol.protocol_list);
4413   if (print_protocol_list(protocol.protocol_list, indent + 4, info))
4414     outs() << " (not in an __OBJC section)\n";
4415 
4416   print_indent(indent);
4417   outs() << " instance_methods "
4418          << format("0x%08" PRIx32, protocol.instance_methods);
4419   if (print_method_description_list(protocol.instance_methods, indent, info))
4420     outs() << " (not in an __OBJC section)\n";
4421 
4422   print_indent(indent);
4423   outs() << "    class_methods "
4424          << format("0x%08" PRIx32, protocol.class_methods);
4425   if (print_method_description_list(protocol.class_methods, indent, info))
4426     outs() << " (not in an __OBJC section)\n";
4427 
4428   return false;
4429 }
4430 
print_protocol_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)4431 static bool print_protocol_list(uint32_t p, uint32_t indent,
4432                                 struct DisassembleInfo *info) {
4433   uint32_t offset, left, l;
4434   SectionRef S;
4435   struct objc_protocol_list_t protocol_list;
4436   const char *r, *list;
4437   int32_t i;
4438 
4439   r = get_pointer_32(p, offset, left, S, info, true);
4440   if (r == nullptr)
4441     return true;
4442 
4443   outs() << "\n";
4444   if (left > sizeof(struct objc_protocol_list_t)) {
4445     memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
4446   } else {
4447     outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
4448     memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
4449     memcpy(&protocol_list, r, left);
4450   }
4451   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4452     swapStruct(protocol_list);
4453 
4454   print_indent(indent);
4455   outs() << "         next " << format("0x%08" PRIx32, protocol_list.next)
4456          << "\n";
4457   print_indent(indent);
4458   outs() << "        count " << protocol_list.count << "\n";
4459 
4460   list = r + sizeof(struct objc_protocol_list_t);
4461   for (i = 0; i < protocol_list.count; i++) {
4462     if ((i + 1) * sizeof(uint32_t) > left) {
4463       outs() << "\t\t remaining list entries extend past the of the section\n";
4464       break;
4465     }
4466     memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
4467     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4468       sys::swapByteOrder(l);
4469 
4470     print_indent(indent);
4471     outs() << "      list[" << i << "] " << format("0x%08" PRIx32, l);
4472     if (print_protocol(l, indent, info))
4473       outs() << "(not in an __OBJC section)\n";
4474   }
4475   return false;
4476 }
4477 
print_ivar_list64_t(uint64_t p,struct DisassembleInfo * info)4478 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
4479   struct ivar_list64_t il;
4480   struct ivar64_t i;
4481   const char *r;
4482   uint32_t offset, xoffset, left, j;
4483   SectionRef S, xS;
4484   const char *name, *sym_name, *ivar_offset_p;
4485   uint64_t ivar_offset, n_value;
4486 
4487   r = get_pointer_64(p, offset, left, S, info);
4488   if (r == nullptr)
4489     return;
4490   memset(&il, '\0', sizeof(struct ivar_list64_t));
4491   if (left < sizeof(struct ivar_list64_t)) {
4492     memcpy(&il, r, left);
4493     outs() << "   (ivar_list_t entends past the end of the section)\n";
4494   } else
4495     memcpy(&il, r, sizeof(struct ivar_list64_t));
4496   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4497     swapStruct(il);
4498   outs() << "                    entsize " << il.entsize << "\n";
4499   outs() << "                      count " << il.count << "\n";
4500 
4501   p += sizeof(struct ivar_list64_t);
4502   offset += sizeof(struct ivar_list64_t);
4503   for (j = 0; j < il.count; j++) {
4504     r = get_pointer_64(p, offset, left, S, info);
4505     if (r == nullptr)
4506       return;
4507     memset(&i, '\0', sizeof(struct ivar64_t));
4508     if (left < sizeof(struct ivar64_t)) {
4509       memcpy(&i, r, left);
4510       outs() << "   (ivar_t entends past the end of the section)\n";
4511     } else
4512       memcpy(&i, r, sizeof(struct ivar64_t));
4513     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4514       swapStruct(i);
4515 
4516     outs() << "\t\t\t   offset ";
4517     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
4518                              info, n_value, i.offset);
4519     if (n_value != 0) {
4520       if (info->verbose && sym_name != nullptr)
4521         outs() << sym_name;
4522       else
4523         outs() << format("0x%" PRIx64, n_value);
4524       if (i.offset != 0)
4525         outs() << " + " << format("0x%" PRIx64, i.offset);
4526     } else
4527       outs() << format("0x%" PRIx64, i.offset);
4528     ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
4529     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4530       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4531       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4532         sys::swapByteOrder(ivar_offset);
4533       outs() << " " << ivar_offset << "\n";
4534     } else
4535       outs() << "\n";
4536 
4537     outs() << "\t\t\t     name ";
4538     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
4539                              n_value, i.name);
4540     if (n_value != 0) {
4541       if (info->verbose && sym_name != nullptr)
4542         outs() << sym_name;
4543       else
4544         outs() << format("0x%" PRIx64, n_value);
4545       if (i.name != 0)
4546         outs() << " + " << format("0x%" PRIx64, i.name);
4547     } else
4548       outs() << format("0x%" PRIx64, i.name);
4549     name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
4550     if (name != nullptr)
4551       outs() << format(" %.*s", left, name);
4552     outs() << "\n";
4553 
4554     outs() << "\t\t\t     type ";
4555     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
4556                              n_value, i.name);
4557     name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
4558     if (n_value != 0) {
4559       if (info->verbose && sym_name != nullptr)
4560         outs() << sym_name;
4561       else
4562         outs() << format("0x%" PRIx64, n_value);
4563       if (i.type != 0)
4564         outs() << " + " << format("0x%" PRIx64, i.type);
4565     } else
4566       outs() << format("0x%" PRIx64, i.type);
4567     if (name != nullptr)
4568       outs() << format(" %.*s", left, name);
4569     outs() << "\n";
4570 
4571     outs() << "\t\t\talignment " << i.alignment << "\n";
4572     outs() << "\t\t\t     size " << i.size << "\n";
4573 
4574     p += sizeof(struct ivar64_t);
4575     offset += sizeof(struct ivar64_t);
4576   }
4577 }
4578 
print_ivar_list32_t(uint32_t p,struct DisassembleInfo * info)4579 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
4580   struct ivar_list32_t il;
4581   struct ivar32_t i;
4582   const char *r;
4583   uint32_t offset, xoffset, left, j;
4584   SectionRef S, xS;
4585   const char *name, *ivar_offset_p;
4586   uint32_t ivar_offset;
4587 
4588   r = get_pointer_32(p, offset, left, S, info);
4589   if (r == nullptr)
4590     return;
4591   memset(&il, '\0', sizeof(struct ivar_list32_t));
4592   if (left < sizeof(struct ivar_list32_t)) {
4593     memcpy(&il, r, left);
4594     outs() << "   (ivar_list_t entends past the end of the section)\n";
4595   } else
4596     memcpy(&il, r, sizeof(struct ivar_list32_t));
4597   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4598     swapStruct(il);
4599   outs() << "                    entsize " << il.entsize << "\n";
4600   outs() << "                      count " << il.count << "\n";
4601 
4602   p += sizeof(struct ivar_list32_t);
4603   offset += sizeof(struct ivar_list32_t);
4604   for (j = 0; j < il.count; j++) {
4605     r = get_pointer_32(p, offset, left, S, info);
4606     if (r == nullptr)
4607       return;
4608     memset(&i, '\0', sizeof(struct ivar32_t));
4609     if (left < sizeof(struct ivar32_t)) {
4610       memcpy(&i, r, left);
4611       outs() << "   (ivar_t entends past the end of the section)\n";
4612     } else
4613       memcpy(&i, r, sizeof(struct ivar32_t));
4614     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4615       swapStruct(i);
4616 
4617     outs() << "\t\t\t   offset " << format("0x%" PRIx32, i.offset);
4618     ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
4619     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
4620       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
4621       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4622         sys::swapByteOrder(ivar_offset);
4623       outs() << " " << ivar_offset << "\n";
4624     } else
4625       outs() << "\n";
4626 
4627     outs() << "\t\t\t     name " << format("0x%" PRIx32, i.name);
4628     name = get_pointer_32(i.name, xoffset, left, xS, info);
4629     if (name != nullptr)
4630       outs() << format(" %.*s", left, name);
4631     outs() << "\n";
4632 
4633     outs() << "\t\t\t     type " << format("0x%" PRIx32, i.type);
4634     name = get_pointer_32(i.type, xoffset, left, xS, info);
4635     if (name != nullptr)
4636       outs() << format(" %.*s", left, name);
4637     outs() << "\n";
4638 
4639     outs() << "\t\t\talignment " << i.alignment << "\n";
4640     outs() << "\t\t\t     size " << i.size << "\n";
4641 
4642     p += sizeof(struct ivar32_t);
4643     offset += sizeof(struct ivar32_t);
4644   }
4645 }
4646 
print_objc_property_list64(uint64_t p,struct DisassembleInfo * info)4647 static void print_objc_property_list64(uint64_t p,
4648                                        struct DisassembleInfo *info) {
4649   struct objc_property_list64 opl;
4650   struct objc_property64 op;
4651   const char *r;
4652   uint32_t offset, xoffset, left, j;
4653   SectionRef S, xS;
4654   const char *name, *sym_name;
4655   uint64_t n_value;
4656 
4657   r = get_pointer_64(p, offset, left, S, info);
4658   if (r == nullptr)
4659     return;
4660   memset(&opl, '\0', sizeof(struct objc_property_list64));
4661   if (left < sizeof(struct objc_property_list64)) {
4662     memcpy(&opl, r, left);
4663     outs() << "   (objc_property_list entends past the end of the section)\n";
4664   } else
4665     memcpy(&opl, r, sizeof(struct objc_property_list64));
4666   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4667     swapStruct(opl);
4668   outs() << "                    entsize " << opl.entsize << "\n";
4669   outs() << "                      count " << opl.count << "\n";
4670 
4671   p += sizeof(struct objc_property_list64);
4672   offset += sizeof(struct objc_property_list64);
4673   for (j = 0; j < opl.count; j++) {
4674     r = get_pointer_64(p, offset, left, S, info);
4675     if (r == nullptr)
4676       return;
4677     memset(&op, '\0', sizeof(struct objc_property64));
4678     if (left < sizeof(struct objc_property64)) {
4679       memcpy(&op, r, left);
4680       outs() << "   (objc_property entends past the end of the section)\n";
4681     } else
4682       memcpy(&op, r, sizeof(struct objc_property64));
4683     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4684       swapStruct(op);
4685 
4686     outs() << "\t\t\t     name ";
4687     sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
4688                              info, n_value, op.name);
4689     if (n_value != 0) {
4690       if (info->verbose && sym_name != nullptr)
4691         outs() << sym_name;
4692       else
4693         outs() << format("0x%" PRIx64, n_value);
4694       if (op.name != 0)
4695         outs() << " + " << format("0x%" PRIx64, op.name);
4696     } else
4697       outs() << format("0x%" PRIx64, op.name);
4698     name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
4699     if (name != nullptr)
4700       outs() << format(" %.*s", left, name);
4701     outs() << "\n";
4702 
4703     outs() << "\t\t\tattributes ";
4704     sym_name =
4705         get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
4706                       info, n_value, op.attributes);
4707     if (n_value != 0) {
4708       if (info->verbose && sym_name != nullptr)
4709         outs() << sym_name;
4710       else
4711         outs() << format("0x%" PRIx64, n_value);
4712       if (op.attributes != 0)
4713         outs() << " + " << format("0x%" PRIx64, op.attributes);
4714     } else
4715       outs() << format("0x%" PRIx64, op.attributes);
4716     name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
4717     if (name != nullptr)
4718       outs() << format(" %.*s", left, name);
4719     outs() << "\n";
4720 
4721     p += sizeof(struct objc_property64);
4722     offset += sizeof(struct objc_property64);
4723   }
4724 }
4725 
print_objc_property_list32(uint32_t p,struct DisassembleInfo * info)4726 static void print_objc_property_list32(uint32_t p,
4727                                        struct DisassembleInfo *info) {
4728   struct objc_property_list32 opl;
4729   struct objc_property32 op;
4730   const char *r;
4731   uint32_t offset, xoffset, left, j;
4732   SectionRef S, xS;
4733   const char *name;
4734 
4735   r = get_pointer_32(p, offset, left, S, info);
4736   if (r == nullptr)
4737     return;
4738   memset(&opl, '\0', sizeof(struct objc_property_list32));
4739   if (left < sizeof(struct objc_property_list32)) {
4740     memcpy(&opl, r, left);
4741     outs() << "   (objc_property_list entends past the end of the section)\n";
4742   } else
4743     memcpy(&opl, r, sizeof(struct objc_property_list32));
4744   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4745     swapStruct(opl);
4746   outs() << "                    entsize " << opl.entsize << "\n";
4747   outs() << "                      count " << opl.count << "\n";
4748 
4749   p += sizeof(struct objc_property_list32);
4750   offset += sizeof(struct objc_property_list32);
4751   for (j = 0; j < opl.count; j++) {
4752     r = get_pointer_32(p, offset, left, S, info);
4753     if (r == nullptr)
4754       return;
4755     memset(&op, '\0', sizeof(struct objc_property32));
4756     if (left < sizeof(struct objc_property32)) {
4757       memcpy(&op, r, left);
4758       outs() << "   (objc_property entends past the end of the section)\n";
4759     } else
4760       memcpy(&op, r, sizeof(struct objc_property32));
4761     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4762       swapStruct(op);
4763 
4764     outs() << "\t\t\t     name " << format("0x%" PRIx32, op.name);
4765     name = get_pointer_32(op.name, xoffset, left, xS, info);
4766     if (name != nullptr)
4767       outs() << format(" %.*s", left, name);
4768     outs() << "\n";
4769 
4770     outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
4771     name = get_pointer_32(op.attributes, xoffset, left, xS, info);
4772     if (name != nullptr)
4773       outs() << format(" %.*s", left, name);
4774     outs() << "\n";
4775 
4776     p += sizeof(struct objc_property32);
4777     offset += sizeof(struct objc_property32);
4778   }
4779 }
4780 
print_class_ro64_t(uint64_t p,struct DisassembleInfo * info,bool & is_meta_class)4781 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
4782                                bool &is_meta_class) {
4783   struct class_ro64_t cro;
4784   const char *r;
4785   uint32_t offset, xoffset, left;
4786   SectionRef S, xS;
4787   const char *name, *sym_name;
4788   uint64_t n_value;
4789 
4790   r = get_pointer_64(p, offset, left, S, info);
4791   if (r == nullptr || left < sizeof(struct class_ro64_t))
4792     return false;
4793   memcpy(&cro, r, sizeof(struct class_ro64_t));
4794   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4795     swapStruct(cro);
4796   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
4797   if (cro.flags & RO_META)
4798     outs() << " RO_META";
4799   if (cro.flags & RO_ROOT)
4800     outs() << " RO_ROOT";
4801   if (cro.flags & RO_HAS_CXX_STRUCTORS)
4802     outs() << " RO_HAS_CXX_STRUCTORS";
4803   outs() << "\n";
4804   outs() << "            instanceStart " << cro.instanceStart << "\n";
4805   outs() << "             instanceSize " << cro.instanceSize << "\n";
4806   outs() << "                 reserved " << format("0x%" PRIx32, cro.reserved)
4807          << "\n";
4808   outs() << "               ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
4809          << "\n";
4810   print_layout_map64(cro.ivarLayout, info);
4811 
4812   outs() << "                     name ";
4813   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
4814                            info, n_value, cro.name);
4815   if (n_value != 0) {
4816     if (info->verbose && sym_name != nullptr)
4817       outs() << sym_name;
4818     else
4819       outs() << format("0x%" PRIx64, n_value);
4820     if (cro.name != 0)
4821       outs() << " + " << format("0x%" PRIx64, cro.name);
4822   } else
4823     outs() << format("0x%" PRIx64, cro.name);
4824   name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
4825   if (name != nullptr)
4826     outs() << format(" %.*s", left, name);
4827   outs() << "\n";
4828 
4829   outs() << "              baseMethods ";
4830   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
4831                            S, info, n_value, cro.baseMethods);
4832   if (n_value != 0) {
4833     if (info->verbose && sym_name != nullptr)
4834       outs() << sym_name;
4835     else
4836       outs() << format("0x%" PRIx64, n_value);
4837     if (cro.baseMethods != 0)
4838       outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
4839   } else
4840     outs() << format("0x%" PRIx64, cro.baseMethods);
4841   outs() << " (struct method_list_t *)\n";
4842   if (cro.baseMethods + n_value != 0)
4843     print_method_list64_t(cro.baseMethods + n_value, info, "");
4844 
4845   outs() << "            baseProtocols ";
4846   sym_name =
4847       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
4848                     info, n_value, cro.baseProtocols);
4849   if (n_value != 0) {
4850     if (info->verbose && sym_name != nullptr)
4851       outs() << sym_name;
4852     else
4853       outs() << format("0x%" PRIx64, n_value);
4854     if (cro.baseProtocols != 0)
4855       outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
4856   } else
4857     outs() << format("0x%" PRIx64, cro.baseProtocols);
4858   outs() << "\n";
4859   if (cro.baseProtocols + n_value != 0)
4860     print_protocol_list64_t(cro.baseProtocols + n_value, info);
4861 
4862   outs() << "                    ivars ";
4863   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
4864                            info, n_value, cro.ivars);
4865   if (n_value != 0) {
4866     if (info->verbose && sym_name != nullptr)
4867       outs() << sym_name;
4868     else
4869       outs() << format("0x%" PRIx64, n_value);
4870     if (cro.ivars != 0)
4871       outs() << " + " << format("0x%" PRIx64, cro.ivars);
4872   } else
4873     outs() << format("0x%" PRIx64, cro.ivars);
4874   outs() << "\n";
4875   if (cro.ivars + n_value != 0)
4876     print_ivar_list64_t(cro.ivars + n_value, info);
4877 
4878   outs() << "           weakIvarLayout ";
4879   sym_name =
4880       get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
4881                     info, n_value, cro.weakIvarLayout);
4882   if (n_value != 0) {
4883     if (info->verbose && sym_name != nullptr)
4884       outs() << sym_name;
4885     else
4886       outs() << format("0x%" PRIx64, n_value);
4887     if (cro.weakIvarLayout != 0)
4888       outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
4889   } else
4890     outs() << format("0x%" PRIx64, cro.weakIvarLayout);
4891   outs() << "\n";
4892   print_layout_map64(cro.weakIvarLayout + n_value, info);
4893 
4894   outs() << "           baseProperties ";
4895   sym_name =
4896       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
4897                     info, n_value, cro.baseProperties);
4898   if (n_value != 0) {
4899     if (info->verbose && sym_name != nullptr)
4900       outs() << sym_name;
4901     else
4902       outs() << format("0x%" PRIx64, n_value);
4903     if (cro.baseProperties != 0)
4904       outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
4905   } else
4906     outs() << format("0x%" PRIx64, cro.baseProperties);
4907   outs() << "\n";
4908   if (cro.baseProperties + n_value != 0)
4909     print_objc_property_list64(cro.baseProperties + n_value, info);
4910 
4911   is_meta_class = (cro.flags & RO_META) != 0;
4912   return true;
4913 }
4914 
print_class_ro32_t(uint32_t p,struct DisassembleInfo * info,bool & is_meta_class)4915 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
4916                                bool &is_meta_class) {
4917   struct class_ro32_t cro;
4918   const char *r;
4919   uint32_t offset, xoffset, left;
4920   SectionRef S, xS;
4921   const char *name;
4922 
4923   r = get_pointer_32(p, offset, left, S, info);
4924   if (r == nullptr)
4925     return false;
4926   memset(&cro, '\0', sizeof(struct class_ro32_t));
4927   if (left < sizeof(struct class_ro32_t)) {
4928     memcpy(&cro, r, left);
4929     outs() << "   (class_ro_t entends past the end of the section)\n";
4930   } else
4931     memcpy(&cro, r, sizeof(struct class_ro32_t));
4932   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4933     swapStruct(cro);
4934   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
4935   if (cro.flags & RO_META)
4936     outs() << " RO_META";
4937   if (cro.flags & RO_ROOT)
4938     outs() << " RO_ROOT";
4939   if (cro.flags & RO_HAS_CXX_STRUCTORS)
4940     outs() << " RO_HAS_CXX_STRUCTORS";
4941   outs() << "\n";
4942   outs() << "            instanceStart " << cro.instanceStart << "\n";
4943   outs() << "             instanceSize " << cro.instanceSize << "\n";
4944   outs() << "               ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
4945          << "\n";
4946   print_layout_map32(cro.ivarLayout, info);
4947 
4948   outs() << "                     name " << format("0x%" PRIx32, cro.name);
4949   name = get_pointer_32(cro.name, xoffset, left, xS, info);
4950   if (name != nullptr)
4951     outs() << format(" %.*s", left, name);
4952   outs() << "\n";
4953 
4954   outs() << "              baseMethods "
4955          << format("0x%" PRIx32, cro.baseMethods)
4956          << " (struct method_list_t *)\n";
4957   if (cro.baseMethods != 0)
4958     print_method_list32_t(cro.baseMethods, info, "");
4959 
4960   outs() << "            baseProtocols "
4961          << format("0x%" PRIx32, cro.baseProtocols) << "\n";
4962   if (cro.baseProtocols != 0)
4963     print_protocol_list32_t(cro.baseProtocols, info);
4964   outs() << "                    ivars " << format("0x%" PRIx32, cro.ivars)
4965          << "\n";
4966   if (cro.ivars != 0)
4967     print_ivar_list32_t(cro.ivars, info);
4968   outs() << "           weakIvarLayout "
4969          << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
4970   print_layout_map32(cro.weakIvarLayout, info);
4971   outs() << "           baseProperties "
4972          << format("0x%" PRIx32, cro.baseProperties) << "\n";
4973   if (cro.baseProperties != 0)
4974     print_objc_property_list32(cro.baseProperties, info);
4975   is_meta_class = (cro.flags & RO_META) != 0;
4976   return true;
4977 }
4978 
print_class64_t(uint64_t p,struct DisassembleInfo * info)4979 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
4980   struct class64_t c;
4981   const char *r;
4982   uint32_t offset, left;
4983   SectionRef S;
4984   const char *name;
4985   uint64_t isa_n_value, n_value;
4986 
4987   r = get_pointer_64(p, offset, left, S, info);
4988   if (r == nullptr || left < sizeof(struct class64_t))
4989     return;
4990   memcpy(&c, r, sizeof(struct class64_t));
4991   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4992     swapStruct(c);
4993 
4994   outs() << "           isa " << format("0x%" PRIx64, c.isa);
4995   name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
4996                        isa_n_value, c.isa);
4997   if (name != nullptr)
4998     outs() << " " << name;
4999   outs() << "\n";
5000 
5001   outs() << "    superclass " << format("0x%" PRIx64, c.superclass);
5002   name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
5003                        n_value, c.superclass);
5004   if (name != nullptr)
5005     outs() << " " << name;
5006   else {
5007     name = get_dyld_bind_info_symbolname(S.getAddress() +
5008              offset + offsetof(struct class64_t, superclass), info);
5009     if (name != nullptr)
5010       outs() << " " << name;
5011   }
5012   outs() << "\n";
5013 
5014   outs() << "         cache " << format("0x%" PRIx64, c.cache);
5015   name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
5016                        n_value, c.cache);
5017   if (name != nullptr)
5018     outs() << " " << name;
5019   outs() << "\n";
5020 
5021   outs() << "        vtable " << format("0x%" PRIx64, c.vtable);
5022   name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
5023                        n_value, c.vtable);
5024   if (name != nullptr)
5025     outs() << " " << name;
5026   outs() << "\n";
5027 
5028   name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
5029                        n_value, c.data);
5030   outs() << "          data ";
5031   if (n_value != 0) {
5032     if (info->verbose && name != nullptr)
5033       outs() << name;
5034     else
5035       outs() << format("0x%" PRIx64, n_value);
5036     if (c.data != 0)
5037       outs() << " + " << format("0x%" PRIx64, c.data);
5038   } else
5039     outs() << format("0x%" PRIx64, c.data);
5040   outs() << " (struct class_ro_t *)";
5041 
5042   // This is a Swift class if some of the low bits of the pointer are set.
5043   if ((c.data + n_value) & 0x7)
5044     outs() << " Swift class";
5045   outs() << "\n";
5046   bool is_meta_class;
5047   if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
5048     return;
5049 
5050   if (!is_meta_class &&
5051       c.isa + isa_n_value != p &&
5052       c.isa + isa_n_value != 0 &&
5053       info->depth < 100) {
5054       info->depth++;
5055       outs() << "Meta Class\n";
5056       print_class64_t(c.isa + isa_n_value, info);
5057   }
5058 }
5059 
print_class32_t(uint32_t p,struct DisassembleInfo * info)5060 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
5061   struct class32_t c;
5062   const char *r;
5063   uint32_t offset, left;
5064   SectionRef S;
5065   const char *name;
5066 
5067   r = get_pointer_32(p, offset, left, S, info);
5068   if (r == nullptr)
5069     return;
5070   memset(&c, '\0', sizeof(struct class32_t));
5071   if (left < sizeof(struct class32_t)) {
5072     memcpy(&c, r, left);
5073     outs() << "   (class_t entends past the end of the section)\n";
5074   } else
5075     memcpy(&c, r, sizeof(struct class32_t));
5076   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5077     swapStruct(c);
5078 
5079   outs() << "           isa " << format("0x%" PRIx32, c.isa);
5080   name =
5081       get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
5082   if (name != nullptr)
5083     outs() << " " << name;
5084   outs() << "\n";
5085 
5086   outs() << "    superclass " << format("0x%" PRIx32, c.superclass);
5087   name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
5088                        c.superclass);
5089   if (name != nullptr)
5090     outs() << " " << name;
5091   outs() << "\n";
5092 
5093   outs() << "         cache " << format("0x%" PRIx32, c.cache);
5094   name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
5095                        c.cache);
5096   if (name != nullptr)
5097     outs() << " " << name;
5098   outs() << "\n";
5099 
5100   outs() << "        vtable " << format("0x%" PRIx32, c.vtable);
5101   name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
5102                        c.vtable);
5103   if (name != nullptr)
5104     outs() << " " << name;
5105   outs() << "\n";
5106 
5107   name =
5108       get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
5109   outs() << "          data " << format("0x%" PRIx32, c.data)
5110          << " (struct class_ro_t *)";
5111 
5112   // This is a Swift class if some of the low bits of the pointer are set.
5113   if (c.data & 0x3)
5114     outs() << " Swift class";
5115   outs() << "\n";
5116   bool is_meta_class;
5117   if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
5118     return;
5119 
5120   if (!is_meta_class) {
5121     outs() << "Meta Class\n";
5122     print_class32_t(c.isa, info);
5123   }
5124 }
5125 
print_objc_class_t(struct objc_class_t * objc_class,struct DisassembleInfo * info)5126 static void print_objc_class_t(struct objc_class_t *objc_class,
5127                                struct DisassembleInfo *info) {
5128   uint32_t offset, left, xleft;
5129   const char *name, *p, *ivar_list;
5130   SectionRef S;
5131   int32_t i;
5132   struct objc_ivar_list_t objc_ivar_list;
5133   struct objc_ivar_t ivar;
5134 
5135   outs() << "\t\t      isa " << format("0x%08" PRIx32, objc_class->isa);
5136   if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
5137     name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
5138     if (name != nullptr)
5139       outs() << format(" %.*s", left, name);
5140     else
5141       outs() << " (not in an __OBJC section)";
5142   }
5143   outs() << "\n";
5144 
5145   outs() << "\t      super_class "
5146          << format("0x%08" PRIx32, objc_class->super_class);
5147   if (info->verbose) {
5148     name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
5149     if (name != nullptr)
5150       outs() << format(" %.*s", left, name);
5151     else
5152       outs() << " (not in an __OBJC section)";
5153   }
5154   outs() << "\n";
5155 
5156   outs() << "\t\t     name " << format("0x%08" PRIx32, objc_class->name);
5157   if (info->verbose) {
5158     name = get_pointer_32(objc_class->name, offset, left, S, info, true);
5159     if (name != nullptr)
5160       outs() << format(" %.*s", left, name);
5161     else
5162       outs() << " (not in an __OBJC section)";
5163   }
5164   outs() << "\n";
5165 
5166   outs() << "\t\t  version " << format("0x%08" PRIx32, objc_class->version)
5167          << "\n";
5168 
5169   outs() << "\t\t     info " << format("0x%08" PRIx32, objc_class->info);
5170   if (info->verbose) {
5171     if (CLS_GETINFO(objc_class, CLS_CLASS))
5172       outs() << " CLS_CLASS";
5173     else if (CLS_GETINFO(objc_class, CLS_META))
5174       outs() << " CLS_META";
5175   }
5176   outs() << "\n";
5177 
5178   outs() << "\t    instance_size "
5179          << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
5180 
5181   p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
5182   outs() << "\t\t    ivars " << format("0x%08" PRIx32, objc_class->ivars);
5183   if (p != nullptr) {
5184     if (left > sizeof(struct objc_ivar_list_t)) {
5185       outs() << "\n";
5186       memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
5187     } else {
5188       outs() << " (entends past the end of the section)\n";
5189       memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
5190       memcpy(&objc_ivar_list, p, left);
5191     }
5192     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5193       swapStruct(objc_ivar_list);
5194     outs() << "\t\t       ivar_count " << objc_ivar_list.ivar_count << "\n";
5195     ivar_list = p + sizeof(struct objc_ivar_list_t);
5196     for (i = 0; i < objc_ivar_list.ivar_count; i++) {
5197       if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
5198         outs() << "\t\t remaining ivar's extend past the of the section\n";
5199         break;
5200       }
5201       memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
5202              sizeof(struct objc_ivar_t));
5203       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5204         swapStruct(ivar);
5205 
5206       outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
5207       if (info->verbose) {
5208         name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
5209         if (name != nullptr)
5210           outs() << format(" %.*s", xleft, name);
5211         else
5212           outs() << " (not in an __OBJC section)";
5213       }
5214       outs() << "\n";
5215 
5216       outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
5217       if (info->verbose) {
5218         name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
5219         if (name != nullptr)
5220           outs() << format(" %.*s", xleft, name);
5221         else
5222           outs() << " (not in an __OBJC section)";
5223       }
5224       outs() << "\n";
5225 
5226       outs() << "\t\t      ivar_offset "
5227              << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
5228     }
5229   } else {
5230     outs() << " (not in an __OBJC section)\n";
5231   }
5232 
5233   outs() << "\t\t  methods " << format("0x%08" PRIx32, objc_class->methodLists);
5234   if (print_method_list(objc_class->methodLists, info))
5235     outs() << " (not in an __OBJC section)\n";
5236 
5237   outs() << "\t\t    cache " << format("0x%08" PRIx32, objc_class->cache)
5238          << "\n";
5239 
5240   outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
5241   if (print_protocol_list(objc_class->protocols, 16, info))
5242     outs() << " (not in an __OBJC section)\n";
5243 }
5244 
print_objc_objc_category_t(struct objc_category_t * objc_category,struct DisassembleInfo * info)5245 static void print_objc_objc_category_t(struct objc_category_t *objc_category,
5246                                        struct DisassembleInfo *info) {
5247   uint32_t offset, left;
5248   const char *name;
5249   SectionRef S;
5250 
5251   outs() << "\t       category name "
5252          << format("0x%08" PRIx32, objc_category->category_name);
5253   if (info->verbose) {
5254     name = get_pointer_32(objc_category->category_name, offset, left, S, info,
5255                           true);
5256     if (name != nullptr)
5257       outs() << format(" %.*s", left, name);
5258     else
5259       outs() << " (not in an __OBJC section)";
5260   }
5261   outs() << "\n";
5262 
5263   outs() << "\t\t  class name "
5264          << format("0x%08" PRIx32, objc_category->class_name);
5265   if (info->verbose) {
5266     name =
5267         get_pointer_32(objc_category->class_name, offset, left, S, info, true);
5268     if (name != nullptr)
5269       outs() << format(" %.*s", left, name);
5270     else
5271       outs() << " (not in an __OBJC section)";
5272   }
5273   outs() << "\n";
5274 
5275   outs() << "\t    instance methods "
5276          << format("0x%08" PRIx32, objc_category->instance_methods);
5277   if (print_method_list(objc_category->instance_methods, info))
5278     outs() << " (not in an __OBJC section)\n";
5279 
5280   outs() << "\t       class methods "
5281          << format("0x%08" PRIx32, objc_category->class_methods);
5282   if (print_method_list(objc_category->class_methods, info))
5283     outs() << " (not in an __OBJC section)\n";
5284 }
5285 
print_category64_t(uint64_t p,struct DisassembleInfo * info)5286 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
5287   struct category64_t c;
5288   const char *r;
5289   uint32_t offset, xoffset, left;
5290   SectionRef S, xS;
5291   const char *name, *sym_name;
5292   uint64_t n_value;
5293 
5294   r = get_pointer_64(p, offset, left, S, info);
5295   if (r == nullptr)
5296     return;
5297   memset(&c, '\0', sizeof(struct category64_t));
5298   if (left < sizeof(struct category64_t)) {
5299     memcpy(&c, r, left);
5300     outs() << "   (category_t entends past the end of the section)\n";
5301   } else
5302     memcpy(&c, r, sizeof(struct category64_t));
5303   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5304     swapStruct(c);
5305 
5306   outs() << "              name ";
5307   sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
5308                            info, n_value, c.name);
5309   if (n_value != 0) {
5310     if (info->verbose && sym_name != nullptr)
5311       outs() << sym_name;
5312     else
5313       outs() << format("0x%" PRIx64, n_value);
5314     if (c.name != 0)
5315       outs() << " + " << format("0x%" PRIx64, c.name);
5316   } else
5317     outs() << format("0x%" PRIx64, c.name);
5318   name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
5319   if (name != nullptr)
5320     outs() << format(" %.*s", left, name);
5321   outs() << "\n";
5322 
5323   outs() << "               cls ";
5324   sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
5325                            n_value, c.cls);
5326   if (n_value != 0) {
5327     if (info->verbose && sym_name != nullptr)
5328       outs() << sym_name;
5329     else
5330       outs() << format("0x%" PRIx64, n_value);
5331     if (c.cls != 0)
5332       outs() << " + " << format("0x%" PRIx64, c.cls);
5333   } else
5334     outs() << format("0x%" PRIx64, c.cls);
5335   outs() << "\n";
5336   if (c.cls + n_value != 0)
5337     print_class64_t(c.cls + n_value, info);
5338 
5339   outs() << "   instanceMethods ";
5340   sym_name =
5341       get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
5342                     info, n_value, c.instanceMethods);
5343   if (n_value != 0) {
5344     if (info->verbose && sym_name != nullptr)
5345       outs() << sym_name;
5346     else
5347       outs() << format("0x%" PRIx64, n_value);
5348     if (c.instanceMethods != 0)
5349       outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
5350   } else
5351     outs() << format("0x%" PRIx64, c.instanceMethods);
5352   outs() << "\n";
5353   if (c.instanceMethods + n_value != 0)
5354     print_method_list64_t(c.instanceMethods + n_value, info, "");
5355 
5356   outs() << "      classMethods ";
5357   sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
5358                            S, info, n_value, c.classMethods);
5359   if (n_value != 0) {
5360     if (info->verbose && sym_name != nullptr)
5361       outs() << sym_name;
5362     else
5363       outs() << format("0x%" PRIx64, n_value);
5364     if (c.classMethods != 0)
5365       outs() << " + " << format("0x%" PRIx64, c.classMethods);
5366   } else
5367     outs() << format("0x%" PRIx64, c.classMethods);
5368   outs() << "\n";
5369   if (c.classMethods + n_value != 0)
5370     print_method_list64_t(c.classMethods + n_value, info, "");
5371 
5372   outs() << "         protocols ";
5373   sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
5374                            info, n_value, c.protocols);
5375   if (n_value != 0) {
5376     if (info->verbose && sym_name != nullptr)
5377       outs() << sym_name;
5378     else
5379       outs() << format("0x%" PRIx64, n_value);
5380     if (c.protocols != 0)
5381       outs() << " + " << format("0x%" PRIx64, c.protocols);
5382   } else
5383     outs() << format("0x%" PRIx64, c.protocols);
5384   outs() << "\n";
5385   if (c.protocols + n_value != 0)
5386     print_protocol_list64_t(c.protocols + n_value, info);
5387 
5388   outs() << "instanceProperties ";
5389   sym_name =
5390       get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
5391                     S, info, n_value, c.instanceProperties);
5392   if (n_value != 0) {
5393     if (info->verbose && sym_name != nullptr)
5394       outs() << sym_name;
5395     else
5396       outs() << format("0x%" PRIx64, n_value);
5397     if (c.instanceProperties != 0)
5398       outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
5399   } else
5400     outs() << format("0x%" PRIx64, c.instanceProperties);
5401   outs() << "\n";
5402   if (c.instanceProperties + n_value != 0)
5403     print_objc_property_list64(c.instanceProperties + n_value, info);
5404 }
5405 
print_category32_t(uint32_t p,struct DisassembleInfo * info)5406 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
5407   struct category32_t c;
5408   const char *r;
5409   uint32_t offset, left;
5410   SectionRef S, xS;
5411   const char *name;
5412 
5413   r = get_pointer_32(p, offset, left, S, info);
5414   if (r == nullptr)
5415     return;
5416   memset(&c, '\0', sizeof(struct category32_t));
5417   if (left < sizeof(struct category32_t)) {
5418     memcpy(&c, r, left);
5419     outs() << "   (category_t entends past the end of the section)\n";
5420   } else
5421     memcpy(&c, r, sizeof(struct category32_t));
5422   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5423     swapStruct(c);
5424 
5425   outs() << "              name " << format("0x%" PRIx32, c.name);
5426   name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
5427                        c.name);
5428   if (name)
5429     outs() << " " << name;
5430   outs() << "\n";
5431 
5432   outs() << "               cls " << format("0x%" PRIx32, c.cls) << "\n";
5433   if (c.cls != 0)
5434     print_class32_t(c.cls, info);
5435   outs() << "   instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
5436          << "\n";
5437   if (c.instanceMethods != 0)
5438     print_method_list32_t(c.instanceMethods, info, "");
5439   outs() << "      classMethods " << format("0x%" PRIx32, c.classMethods)
5440          << "\n";
5441   if (c.classMethods != 0)
5442     print_method_list32_t(c.classMethods, info, "");
5443   outs() << "         protocols " << format("0x%" PRIx32, c.protocols) << "\n";
5444   if (c.protocols != 0)
5445     print_protocol_list32_t(c.protocols, info);
5446   outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
5447          << "\n";
5448   if (c.instanceProperties != 0)
5449     print_objc_property_list32(c.instanceProperties, info);
5450 }
5451 
print_message_refs64(SectionRef S,struct DisassembleInfo * info)5452 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
5453   uint32_t i, left, offset, xoffset;
5454   uint64_t p, n_value;
5455   struct message_ref64 mr;
5456   const char *name, *sym_name;
5457   const char *r;
5458   SectionRef xS;
5459 
5460   if (S == SectionRef())
5461     return;
5462 
5463   StringRef SectName;
5464   S.getName(SectName);
5465   DataRefImpl Ref = S.getRawDataRefImpl();
5466   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5467   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5468   offset = 0;
5469   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5470     p = S.getAddress() + i;
5471     r = get_pointer_64(p, offset, left, S, info);
5472     if (r == nullptr)
5473       return;
5474     memset(&mr, '\0', sizeof(struct message_ref64));
5475     if (left < sizeof(struct message_ref64)) {
5476       memcpy(&mr, r, left);
5477       outs() << "   (message_ref entends past the end of the section)\n";
5478     } else
5479       memcpy(&mr, r, sizeof(struct message_ref64));
5480     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5481       swapStruct(mr);
5482 
5483     outs() << "  imp ";
5484     name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
5485                          n_value, mr.imp);
5486     if (n_value != 0) {
5487       outs() << format("0x%" PRIx64, n_value) << " ";
5488       if (mr.imp != 0)
5489         outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
5490     } else
5491       outs() << format("0x%" PRIx64, mr.imp) << " ";
5492     if (name != nullptr)
5493       outs() << " " << name;
5494     outs() << "\n";
5495 
5496     outs() << "  sel ";
5497     sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
5498                              info, n_value, mr.sel);
5499     if (n_value != 0) {
5500       if (info->verbose && sym_name != nullptr)
5501         outs() << sym_name;
5502       else
5503         outs() << format("0x%" PRIx64, n_value);
5504       if (mr.sel != 0)
5505         outs() << " + " << format("0x%" PRIx64, mr.sel);
5506     } else
5507       outs() << format("0x%" PRIx64, mr.sel);
5508     name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
5509     if (name != nullptr)
5510       outs() << format(" %.*s", left, name);
5511     outs() << "\n";
5512 
5513     offset += sizeof(struct message_ref64);
5514   }
5515 }
5516 
print_message_refs32(SectionRef S,struct DisassembleInfo * info)5517 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
5518   uint32_t i, left, offset, xoffset, p;
5519   struct message_ref32 mr;
5520   const char *name, *r;
5521   SectionRef xS;
5522 
5523   if (S == SectionRef())
5524     return;
5525 
5526   StringRef SectName;
5527   S.getName(SectName);
5528   DataRefImpl Ref = S.getRawDataRefImpl();
5529   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5530   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5531   offset = 0;
5532   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
5533     p = S.getAddress() + i;
5534     r = get_pointer_32(p, offset, left, S, info);
5535     if (r == nullptr)
5536       return;
5537     memset(&mr, '\0', sizeof(struct message_ref32));
5538     if (left < sizeof(struct message_ref32)) {
5539       memcpy(&mr, r, left);
5540       outs() << "   (message_ref entends past the end of the section)\n";
5541     } else
5542       memcpy(&mr, r, sizeof(struct message_ref32));
5543     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5544       swapStruct(mr);
5545 
5546     outs() << "  imp " << format("0x%" PRIx32, mr.imp);
5547     name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
5548                          mr.imp);
5549     if (name != nullptr)
5550       outs() << " " << name;
5551     outs() << "\n";
5552 
5553     outs() << "  sel " << format("0x%" PRIx32, mr.sel);
5554     name = get_pointer_32(mr.sel, xoffset, left, xS, info);
5555     if (name != nullptr)
5556       outs() << " " << name;
5557     outs() << "\n";
5558 
5559     offset += sizeof(struct message_ref32);
5560   }
5561 }
5562 
print_image_info64(SectionRef S,struct DisassembleInfo * info)5563 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
5564   uint32_t left, offset, swift_version;
5565   uint64_t p;
5566   struct objc_image_info64 o;
5567   const char *r;
5568 
5569   if (S == SectionRef())
5570     return;
5571 
5572   StringRef SectName;
5573   S.getName(SectName);
5574   DataRefImpl Ref = S.getRawDataRefImpl();
5575   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5576   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5577   p = S.getAddress();
5578   r = get_pointer_64(p, offset, left, S, info);
5579   if (r == nullptr)
5580     return;
5581   memset(&o, '\0', sizeof(struct objc_image_info64));
5582   if (left < sizeof(struct objc_image_info64)) {
5583     memcpy(&o, r, left);
5584     outs() << "   (objc_image_info entends past the end of the section)\n";
5585   } else
5586     memcpy(&o, r, sizeof(struct objc_image_info64));
5587   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5588     swapStruct(o);
5589   outs() << "  version " << o.version << "\n";
5590   outs() << "    flags " << format("0x%" PRIx32, o.flags);
5591   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
5592     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5593   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
5594     outs() << " OBJC_IMAGE_SUPPORTS_GC";
5595   if (o.flags & OBJC_IMAGE_IS_SIMULATED)
5596     outs() << " OBJC_IMAGE_IS_SIMULATED";
5597   if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES)
5598     outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
5599   swift_version = (o.flags >> 8) & 0xff;
5600   if (swift_version != 0) {
5601     if (swift_version == 1)
5602       outs() << " Swift 1.0";
5603     else if (swift_version == 2)
5604       outs() << " Swift 1.1";
5605     else if(swift_version == 3)
5606       outs() << " Swift 2.0";
5607     else if(swift_version == 4)
5608       outs() << " Swift 3.0";
5609     else if(swift_version == 5)
5610       outs() << " Swift 4.0";
5611     else if(swift_version == 6)
5612       outs() << " Swift 4.1";
5613     else
5614       outs() << " unknown future Swift version (" << swift_version << ")";
5615   }
5616   outs() << "\n";
5617 }
5618 
print_image_info32(SectionRef S,struct DisassembleInfo * info)5619 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
5620   uint32_t left, offset, swift_version, p;
5621   struct objc_image_info32 o;
5622   const char *r;
5623 
5624   if (S == SectionRef())
5625     return;
5626 
5627   StringRef SectName;
5628   S.getName(SectName);
5629   DataRefImpl Ref = S.getRawDataRefImpl();
5630   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5631   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5632   p = S.getAddress();
5633   r = get_pointer_32(p, offset, left, S, info);
5634   if (r == nullptr)
5635     return;
5636   memset(&o, '\0', sizeof(struct objc_image_info32));
5637   if (left < sizeof(struct objc_image_info32)) {
5638     memcpy(&o, r, left);
5639     outs() << "   (objc_image_info entends past the end of the section)\n";
5640   } else
5641     memcpy(&o, r, sizeof(struct objc_image_info32));
5642   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5643     swapStruct(o);
5644   outs() << "  version " << o.version << "\n";
5645   outs() << "    flags " << format("0x%" PRIx32, o.flags);
5646   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
5647     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
5648   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
5649     outs() << " OBJC_IMAGE_SUPPORTS_GC";
5650   swift_version = (o.flags >> 8) & 0xff;
5651   if (swift_version != 0) {
5652     if (swift_version == 1)
5653       outs() << " Swift 1.0";
5654     else if (swift_version == 2)
5655       outs() << " Swift 1.1";
5656     else if(swift_version == 3)
5657       outs() << " Swift 2.0";
5658     else if(swift_version == 4)
5659       outs() << " Swift 3.0";
5660     else if(swift_version == 5)
5661       outs() << " Swift 4.0";
5662     else if(swift_version == 6)
5663       outs() << " Swift 4.1";
5664     else
5665       outs() << " unknown future Swift version (" << swift_version << ")";
5666   }
5667   outs() << "\n";
5668 }
5669 
print_image_info(SectionRef S,struct DisassembleInfo * info)5670 static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
5671   uint32_t left, offset, p;
5672   struct imageInfo_t o;
5673   const char *r;
5674 
5675   StringRef SectName;
5676   S.getName(SectName);
5677   DataRefImpl Ref = S.getRawDataRefImpl();
5678   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
5679   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
5680   p = S.getAddress();
5681   r = get_pointer_32(p, offset, left, S, info);
5682   if (r == nullptr)
5683     return;
5684   memset(&o, '\0', sizeof(struct imageInfo_t));
5685   if (left < sizeof(struct imageInfo_t)) {
5686     memcpy(&o, r, left);
5687     outs() << " (imageInfo entends past the end of the section)\n";
5688   } else
5689     memcpy(&o, r, sizeof(struct imageInfo_t));
5690   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5691     swapStruct(o);
5692   outs() << "  version " << o.version << "\n";
5693   outs() << "    flags " << format("0x%" PRIx32, o.flags);
5694   if (o.flags & 0x1)
5695     outs() << "  F&C";
5696   if (o.flags & 0x2)
5697     outs() << " GC";
5698   if (o.flags & 0x4)
5699     outs() << " GC-only";
5700   else
5701     outs() << " RR";
5702   outs() << "\n";
5703 }
5704 
printObjc2_64bit_MetaData(MachOObjectFile * O,bool verbose)5705 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
5706   SymbolAddressMap AddrMap;
5707   if (verbose)
5708     CreateSymbolAddressMap(O, &AddrMap);
5709 
5710   std::vector<SectionRef> Sections;
5711   for (const SectionRef &Section : O->sections()) {
5712     StringRef SectName;
5713     Section.getName(SectName);
5714     Sections.push_back(Section);
5715   }
5716 
5717   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
5718 
5719   SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5720   if (CL == SectionRef())
5721     CL = get_section(O, "__DATA", "__objc_classlist");
5722   if (CL == SectionRef())
5723     CL = get_section(O, "__DATA_CONST", "__objc_classlist");
5724   if (CL == SectionRef())
5725     CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
5726   info.S = CL;
5727   walk_pointer_list_64("class", CL, O, &info, print_class64_t);
5728 
5729   SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5730   if (CR == SectionRef())
5731     CR = get_section(O, "__DATA", "__objc_classrefs");
5732   if (CR == SectionRef())
5733     CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
5734   if (CR == SectionRef())
5735     CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
5736   info.S = CR;
5737   walk_pointer_list_64("class refs", CR, O, &info, nullptr);
5738 
5739   SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5740   if (SR == SectionRef())
5741     SR = get_section(O, "__DATA", "__objc_superrefs");
5742   if (SR == SectionRef())
5743     SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
5744   if (SR == SectionRef())
5745     SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
5746   info.S = SR;
5747   walk_pointer_list_64("super refs", SR, O, &info, nullptr);
5748 
5749   SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5750   if (CA == SectionRef())
5751     CA = get_section(O, "__DATA", "__objc_catlist");
5752   if (CA == SectionRef())
5753     CA = get_section(O, "__DATA_CONST", "__objc_catlist");
5754   if (CA == SectionRef())
5755     CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
5756   info.S = CA;
5757   walk_pointer_list_64("category", CA, O, &info, print_category64_t);
5758 
5759   SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5760   if (PL == SectionRef())
5761     PL = get_section(O, "__DATA", "__objc_protolist");
5762   if (PL == SectionRef())
5763     PL = get_section(O, "__DATA_CONST", "__objc_protolist");
5764   if (PL == SectionRef())
5765     PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
5766   info.S = PL;
5767   walk_pointer_list_64("protocol", PL, O, &info, nullptr);
5768 
5769   SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5770   if (MR == SectionRef())
5771     MR = get_section(O, "__DATA", "__objc_msgrefs");
5772   if (MR == SectionRef())
5773     MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
5774   if (MR == SectionRef())
5775     MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
5776   info.S = MR;
5777   print_message_refs64(MR, &info);
5778 
5779   SectionRef II = get_section(O, "__OBJC2", "__image_info");
5780   if (II == SectionRef())
5781     II = get_section(O, "__DATA", "__objc_imageinfo");
5782   if (II == SectionRef())
5783     II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
5784   if (II == SectionRef())
5785     II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
5786   info.S = II;
5787   print_image_info64(II, &info);
5788 }
5789 
printObjc2_32bit_MetaData(MachOObjectFile * O,bool verbose)5790 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5791   SymbolAddressMap AddrMap;
5792   if (verbose)
5793     CreateSymbolAddressMap(O, &AddrMap);
5794 
5795   std::vector<SectionRef> Sections;
5796   for (const SectionRef &Section : O->sections()) {
5797     StringRef SectName;
5798     Section.getName(SectName);
5799     Sections.push_back(Section);
5800   }
5801 
5802   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
5803 
5804   SectionRef CL = get_section(O, "__OBJC2", "__class_list");
5805   if (CL == SectionRef())
5806     CL = get_section(O, "__DATA", "__objc_classlist");
5807   if (CL == SectionRef())
5808     CL = get_section(O, "__DATA_CONST", "__objc_classlist");
5809   if (CL == SectionRef())
5810     CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
5811   info.S = CL;
5812   walk_pointer_list_32("class", CL, O, &info, print_class32_t);
5813 
5814   SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
5815   if (CR == SectionRef())
5816     CR = get_section(O, "__DATA", "__objc_classrefs");
5817   if (CR == SectionRef())
5818     CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
5819   if (CR == SectionRef())
5820     CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
5821   info.S = CR;
5822   walk_pointer_list_32("class refs", CR, O, &info, nullptr);
5823 
5824   SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
5825   if (SR == SectionRef())
5826     SR = get_section(O, "__DATA", "__objc_superrefs");
5827   if (SR == SectionRef())
5828     SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
5829   if (SR == SectionRef())
5830     SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
5831   info.S = SR;
5832   walk_pointer_list_32("super refs", SR, O, &info, nullptr);
5833 
5834   SectionRef CA = get_section(O, "__OBJC2", "__category_list");
5835   if (CA == SectionRef())
5836     CA = get_section(O, "__DATA", "__objc_catlist");
5837   if (CA == SectionRef())
5838     CA = get_section(O, "__DATA_CONST", "__objc_catlist");
5839   if (CA == SectionRef())
5840     CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
5841   info.S = CA;
5842   walk_pointer_list_32("category", CA, O, &info, print_category32_t);
5843 
5844   SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
5845   if (PL == SectionRef())
5846     PL = get_section(O, "__DATA", "__objc_protolist");
5847   if (PL == SectionRef())
5848     PL = get_section(O, "__DATA_CONST", "__objc_protolist");
5849   if (PL == SectionRef())
5850     PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
5851   info.S = PL;
5852   walk_pointer_list_32("protocol", PL, O, &info, nullptr);
5853 
5854   SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
5855   if (MR == SectionRef())
5856     MR = get_section(O, "__DATA", "__objc_msgrefs");
5857   if (MR == SectionRef())
5858     MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
5859   if (MR == SectionRef())
5860     MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
5861   info.S = MR;
5862   print_message_refs32(MR, &info);
5863 
5864   SectionRef II = get_section(O, "__OBJC2", "__image_info");
5865   if (II == SectionRef())
5866     II = get_section(O, "__DATA", "__objc_imageinfo");
5867   if (II == SectionRef())
5868     II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
5869   if (II == SectionRef())
5870     II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
5871   info.S = II;
5872   print_image_info32(II, &info);
5873 }
5874 
printObjc1_32bit_MetaData(MachOObjectFile * O,bool verbose)5875 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
5876   uint32_t i, j, p, offset, xoffset, left, defs_left, def;
5877   const char *r, *name, *defs;
5878   struct objc_module_t module;
5879   SectionRef S, xS;
5880   struct objc_symtab_t symtab;
5881   struct objc_class_t objc_class;
5882   struct objc_category_t objc_category;
5883 
5884   outs() << "Objective-C segment\n";
5885   S = get_section(O, "__OBJC", "__module_info");
5886   if (S == SectionRef())
5887     return false;
5888 
5889   SymbolAddressMap AddrMap;
5890   if (verbose)
5891     CreateSymbolAddressMap(O, &AddrMap);
5892 
5893   std::vector<SectionRef> Sections;
5894   for (const SectionRef &Section : O->sections()) {
5895     StringRef SectName;
5896     Section.getName(SectName);
5897     Sections.push_back(Section);
5898   }
5899 
5900   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
5901 
5902   for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
5903     p = S.getAddress() + i;
5904     r = get_pointer_32(p, offset, left, S, &info, true);
5905     if (r == nullptr)
5906       return true;
5907     memset(&module, '\0', sizeof(struct objc_module_t));
5908     if (left < sizeof(struct objc_module_t)) {
5909       memcpy(&module, r, left);
5910       outs() << "   (module extends past end of __module_info section)\n";
5911     } else
5912       memcpy(&module, r, sizeof(struct objc_module_t));
5913     if (O->isLittleEndian() != sys::IsLittleEndianHost)
5914       swapStruct(module);
5915 
5916     outs() << "Module " << format("0x%" PRIx32, p) << "\n";
5917     outs() << "    version " << module.version << "\n";
5918     outs() << "       size " << module.size << "\n";
5919     outs() << "       name ";
5920     name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
5921     if (name != nullptr)
5922       outs() << format("%.*s", left, name);
5923     else
5924       outs() << format("0x%08" PRIx32, module.name)
5925              << "(not in an __OBJC section)";
5926     outs() << "\n";
5927 
5928     r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
5929     if (module.symtab == 0 || r == nullptr) {
5930       outs() << "     symtab " << format("0x%08" PRIx32, module.symtab)
5931              << " (not in an __OBJC section)\n";
5932       continue;
5933     }
5934     outs() << "     symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
5935     memset(&symtab, '\0', sizeof(struct objc_symtab_t));
5936     defs_left = 0;
5937     defs = nullptr;
5938     if (left < sizeof(struct objc_symtab_t)) {
5939       memcpy(&symtab, r, left);
5940       outs() << "\tsymtab extends past end of an __OBJC section)\n";
5941     } else {
5942       memcpy(&symtab, r, sizeof(struct objc_symtab_t));
5943       if (left > sizeof(struct objc_symtab_t)) {
5944         defs_left = left - sizeof(struct objc_symtab_t);
5945         defs = r + sizeof(struct objc_symtab_t);
5946       }
5947     }
5948     if (O->isLittleEndian() != sys::IsLittleEndianHost)
5949       swapStruct(symtab);
5950 
5951     outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
5952     r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
5953     outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
5954     if (r == nullptr)
5955       outs() << " (not in an __OBJC section)";
5956     outs() << "\n";
5957     outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
5958     outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
5959     if (symtab.cls_def_cnt > 0)
5960       outs() << "\tClass Definitions\n";
5961     for (j = 0; j < symtab.cls_def_cnt; j++) {
5962       if ((j + 1) * sizeof(uint32_t) > defs_left) {
5963         outs() << "\t(remaining class defs entries entends past the end of the "
5964                << "section)\n";
5965         break;
5966       }
5967       memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
5968       if (O->isLittleEndian() != sys::IsLittleEndianHost)
5969         sys::swapByteOrder(def);
5970 
5971       r = get_pointer_32(def, xoffset, left, xS, &info, true);
5972       outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
5973       if (r != nullptr) {
5974         if (left > sizeof(struct objc_class_t)) {
5975           outs() << "\n";
5976           memcpy(&objc_class, r, sizeof(struct objc_class_t));
5977         } else {
5978           outs() << " (entends past the end of the section)\n";
5979           memset(&objc_class, '\0', sizeof(struct objc_class_t));
5980           memcpy(&objc_class, r, left);
5981         }
5982         if (O->isLittleEndian() != sys::IsLittleEndianHost)
5983           swapStruct(objc_class);
5984         print_objc_class_t(&objc_class, &info);
5985       } else {
5986         outs() << "(not in an __OBJC section)\n";
5987       }
5988 
5989       if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
5990         outs() << "\tMeta Class";
5991         r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
5992         if (r != nullptr) {
5993           if (left > sizeof(struct objc_class_t)) {
5994             outs() << "\n";
5995             memcpy(&objc_class, r, sizeof(struct objc_class_t));
5996           } else {
5997             outs() << " (entends past the end of the section)\n";
5998             memset(&objc_class, '\0', sizeof(struct objc_class_t));
5999             memcpy(&objc_class, r, left);
6000           }
6001           if (O->isLittleEndian() != sys::IsLittleEndianHost)
6002             swapStruct(objc_class);
6003           print_objc_class_t(&objc_class, &info);
6004         } else {
6005           outs() << "(not in an __OBJC section)\n";
6006         }
6007       }
6008     }
6009     if (symtab.cat_def_cnt > 0)
6010       outs() << "\tCategory Definitions\n";
6011     for (j = 0; j < symtab.cat_def_cnt; j++) {
6012       if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
6013         outs() << "\t(remaining category defs entries entends past the end of "
6014                << "the section)\n";
6015         break;
6016       }
6017       memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
6018              sizeof(uint32_t));
6019       if (O->isLittleEndian() != sys::IsLittleEndianHost)
6020         sys::swapByteOrder(def);
6021 
6022       r = get_pointer_32(def, xoffset, left, xS, &info, true);
6023       outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
6024              << format("0x%08" PRIx32, def);
6025       if (r != nullptr) {
6026         if (left > sizeof(struct objc_category_t)) {
6027           outs() << "\n";
6028           memcpy(&objc_category, r, sizeof(struct objc_category_t));
6029         } else {
6030           outs() << " (entends past the end of the section)\n";
6031           memset(&objc_category, '\0', sizeof(struct objc_category_t));
6032           memcpy(&objc_category, r, left);
6033         }
6034         if (O->isLittleEndian() != sys::IsLittleEndianHost)
6035           swapStruct(objc_category);
6036         print_objc_objc_category_t(&objc_category, &info);
6037       } else {
6038         outs() << "(not in an __OBJC section)\n";
6039       }
6040     }
6041   }
6042   const SectionRef II = get_section(O, "__OBJC", "__image_info");
6043   if (II != SectionRef())
6044     print_image_info(II, &info);
6045 
6046   return true;
6047 }
6048 
DumpProtocolSection(MachOObjectFile * O,const char * sect,uint32_t size,uint32_t addr)6049 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
6050                                 uint32_t size, uint32_t addr) {
6051   SymbolAddressMap AddrMap;
6052   CreateSymbolAddressMap(O, &AddrMap);
6053 
6054   std::vector<SectionRef> Sections;
6055   for (const SectionRef &Section : O->sections()) {
6056     StringRef SectName;
6057     Section.getName(SectName);
6058     Sections.push_back(Section);
6059   }
6060 
6061   struct DisassembleInfo info(O, &AddrMap, &Sections, true);
6062 
6063   const char *p;
6064   struct objc_protocol_t protocol;
6065   uint32_t left, paddr;
6066   for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
6067     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
6068     left = size - (p - sect);
6069     if (left < sizeof(struct objc_protocol_t)) {
6070       outs() << "Protocol extends past end of __protocol section\n";
6071       memcpy(&protocol, p, left);
6072     } else
6073       memcpy(&protocol, p, sizeof(struct objc_protocol_t));
6074     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6075       swapStruct(protocol);
6076     paddr = addr + (p - sect);
6077     outs() << "Protocol " << format("0x%" PRIx32, paddr);
6078     if (print_protocol(paddr, 0, &info))
6079       outs() << "(not in an __OBJC section)\n";
6080   }
6081 }
6082 
6083 #ifdef HAVE_LIBXAR
swapStruct(struct xar_header & xar)6084 inline void swapStruct(struct xar_header &xar) {
6085   sys::swapByteOrder(xar.magic);
6086   sys::swapByteOrder(xar.size);
6087   sys::swapByteOrder(xar.version);
6088   sys::swapByteOrder(xar.toc_length_compressed);
6089   sys::swapByteOrder(xar.toc_length_uncompressed);
6090   sys::swapByteOrder(xar.cksum_alg);
6091 }
6092 
PrintModeVerbose(uint32_t mode)6093 static void PrintModeVerbose(uint32_t mode) {
6094   switch(mode & S_IFMT){
6095   case S_IFDIR:
6096     outs() << "d";
6097     break;
6098   case S_IFCHR:
6099     outs() << "c";
6100     break;
6101   case S_IFBLK:
6102     outs() << "b";
6103     break;
6104   case S_IFREG:
6105     outs() << "-";
6106     break;
6107   case S_IFLNK:
6108     outs() << "l";
6109     break;
6110   case S_IFSOCK:
6111     outs() << "s";
6112     break;
6113   default:
6114     outs() << "?";
6115     break;
6116   }
6117 
6118   /* owner permissions */
6119   if(mode & S_IREAD)
6120     outs() << "r";
6121   else
6122     outs() << "-";
6123   if(mode & S_IWRITE)
6124     outs() << "w";
6125   else
6126     outs() << "-";
6127   if(mode & S_ISUID)
6128     outs() << "s";
6129   else if(mode & S_IEXEC)
6130     outs() << "x";
6131   else
6132     outs() << "-";
6133 
6134   /* group permissions */
6135   if(mode & (S_IREAD >> 3))
6136     outs() << "r";
6137   else
6138     outs() << "-";
6139   if(mode & (S_IWRITE >> 3))
6140     outs() << "w";
6141   else
6142     outs() << "-";
6143   if(mode & S_ISGID)
6144     outs() << "s";
6145   else if(mode & (S_IEXEC >> 3))
6146     outs() << "x";
6147   else
6148     outs() << "-";
6149 
6150   /* other permissions */
6151   if(mode & (S_IREAD >> 6))
6152     outs() << "r";
6153   else
6154     outs() << "-";
6155   if(mode & (S_IWRITE >> 6))
6156     outs() << "w";
6157   else
6158     outs() << "-";
6159   if(mode & S_ISVTX)
6160     outs() << "t";
6161   else if(mode & (S_IEXEC >> 6))
6162     outs() << "x";
6163   else
6164     outs() << "-";
6165 }
6166 
PrintXarFilesSummary(const char * XarFilename,xar_t xar)6167 static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
6168   xar_file_t xf;
6169   const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
6170   char *endp;
6171   uint32_t mode_value;
6172 
6173   ScopedXarIter xi;
6174   if (!xi) {
6175     errs() << "Can't obtain an xar iterator for xar archive "
6176            << XarFilename << "\n";
6177     return;
6178   }
6179 
6180   // Go through the xar's files.
6181   for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
6182     ScopedXarIter xp;
6183     if(!xp){
6184       errs() << "Can't obtain an xar iterator for xar archive "
6185              << XarFilename << "\n";
6186       return;
6187     }
6188     type = nullptr;
6189     mode = nullptr;
6190     user = nullptr;
6191     group = nullptr;
6192     size = nullptr;
6193     mtime = nullptr;
6194     name = nullptr;
6195     for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
6196       const char *val = nullptr;
6197       xar_prop_get(xf, key, &val);
6198 #if 0 // Useful for debugging.
6199       outs() << "key: " << key << " value: " << val << "\n";
6200 #endif
6201       if(strcmp(key, "type") == 0)
6202         type = val;
6203       if(strcmp(key, "mode") == 0)
6204         mode = val;
6205       if(strcmp(key, "user") == 0)
6206         user = val;
6207       if(strcmp(key, "group") == 0)
6208         group = val;
6209       if(strcmp(key, "data/size") == 0)
6210         size = val;
6211       if(strcmp(key, "mtime") == 0)
6212         mtime = val;
6213       if(strcmp(key, "name") == 0)
6214         name = val;
6215     }
6216     if(mode != nullptr){
6217       mode_value = strtoul(mode, &endp, 8);
6218       if(*endp != '\0')
6219         outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
6220       if(strcmp(type, "file") == 0)
6221         mode_value |= S_IFREG;
6222       PrintModeVerbose(mode_value);
6223       outs() << " ";
6224     }
6225     if(user != nullptr)
6226       outs() << format("%10s/", user);
6227     if(group != nullptr)
6228       outs() << format("%-10s ", group);
6229     if(size != nullptr)
6230       outs() << format("%7s ", size);
6231     if(mtime != nullptr){
6232       for(m = mtime; *m != 'T' && *m != '\0'; m++)
6233         outs() << *m;
6234       if(*m == 'T')
6235         m++;
6236       outs() << " ";
6237       for( ; *m != 'Z' && *m != '\0'; m++)
6238         outs() << *m;
6239       outs() << " ";
6240     }
6241     if(name != nullptr)
6242       outs() << name;
6243     outs() << "\n";
6244   }
6245 }
6246 
DumpBitcodeSection(MachOObjectFile * O,const char * sect,uint32_t size,bool verbose,bool PrintXarHeader,bool PrintXarFileHeaders,std::string XarMemberName)6247 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
6248                                 uint32_t size, bool verbose,
6249                                 bool PrintXarHeader, bool PrintXarFileHeaders,
6250                                 std::string XarMemberName) {
6251   if(size < sizeof(struct xar_header)) {
6252     outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
6253               "of struct xar_header)\n";
6254     return;
6255   }
6256   struct xar_header XarHeader;
6257   memcpy(&XarHeader, sect, sizeof(struct xar_header));
6258   if (sys::IsLittleEndianHost)
6259     swapStruct(XarHeader);
6260   if (PrintXarHeader) {
6261     if (!XarMemberName.empty())
6262       outs() << "In xar member " << XarMemberName << ": ";
6263     else
6264       outs() << "For (__LLVM,__bundle) section: ";
6265     outs() << "xar header\n";
6266     if (XarHeader.magic == XAR_HEADER_MAGIC)
6267       outs() << "                  magic XAR_HEADER_MAGIC\n";
6268     else
6269       outs() << "                  magic "
6270              << format_hex(XarHeader.magic, 10, true)
6271              << " (not XAR_HEADER_MAGIC)\n";
6272     outs() << "                   size " << XarHeader.size << "\n";
6273     outs() << "                version " << XarHeader.version << "\n";
6274     outs() << "  toc_length_compressed " << XarHeader.toc_length_compressed
6275            << "\n";
6276     outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
6277            << "\n";
6278     outs() << "              cksum_alg ";
6279     switch (XarHeader.cksum_alg) {
6280       case XAR_CKSUM_NONE:
6281         outs() << "XAR_CKSUM_NONE\n";
6282         break;
6283       case XAR_CKSUM_SHA1:
6284         outs() << "XAR_CKSUM_SHA1\n";
6285         break;
6286       case XAR_CKSUM_MD5:
6287         outs() << "XAR_CKSUM_MD5\n";
6288         break;
6289 #ifdef XAR_CKSUM_SHA256
6290       case XAR_CKSUM_SHA256:
6291         outs() << "XAR_CKSUM_SHA256\n";
6292         break;
6293 #endif
6294 #ifdef XAR_CKSUM_SHA512
6295       case XAR_CKSUM_SHA512:
6296         outs() << "XAR_CKSUM_SHA512\n";
6297         break;
6298 #endif
6299       default:
6300         outs() << XarHeader.cksum_alg << "\n";
6301     }
6302   }
6303 
6304   SmallString<128> XarFilename;
6305   int FD;
6306   std::error_code XarEC =
6307       sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
6308   if (XarEC) {
6309     errs() << XarEC.message() << "\n";
6310     return;
6311   }
6312   ToolOutputFile XarFile(XarFilename, FD);
6313   raw_fd_ostream &XarOut = XarFile.os();
6314   StringRef XarContents(sect, size);
6315   XarOut << XarContents;
6316   XarOut.close();
6317   if (XarOut.has_error())
6318     return;
6319 
6320   ScopedXarFile xar(XarFilename.c_str(), READ);
6321   if (!xar) {
6322     errs() << "Can't create temporary xar archive " << XarFilename << "\n";
6323     return;
6324   }
6325 
6326   SmallString<128> TocFilename;
6327   std::error_code TocEC =
6328       sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
6329   if (TocEC) {
6330     errs() << TocEC.message() << "\n";
6331     return;
6332   }
6333   xar_serialize(xar, TocFilename.c_str());
6334 
6335   if (PrintXarFileHeaders) {
6336     if (!XarMemberName.empty())
6337       outs() << "In xar member " << XarMemberName << ": ";
6338     else
6339       outs() << "For (__LLVM,__bundle) section: ";
6340     outs() << "xar archive files:\n";
6341     PrintXarFilesSummary(XarFilename.c_str(), xar);
6342   }
6343 
6344   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
6345     MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
6346   if (std::error_code EC = FileOrErr.getError()) {
6347     errs() << EC.message() << "\n";
6348     return;
6349   }
6350   std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
6351 
6352   if (!XarMemberName.empty())
6353     outs() << "In xar member " << XarMemberName << ": ";
6354   else
6355     outs() << "For (__LLVM,__bundle) section: ";
6356   outs() << "xar table of contents:\n";
6357   outs() << Buffer->getBuffer() << "\n";
6358 
6359   // TODO: Go through the xar's files.
6360   ScopedXarIter xi;
6361   if(!xi){
6362     errs() << "Can't obtain an xar iterator for xar archive "
6363            << XarFilename.c_str() << "\n";
6364     return;
6365   }
6366   for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
6367     const char *key;
6368     const char *member_name, *member_type, *member_size_string;
6369     size_t member_size;
6370 
6371     ScopedXarIter xp;
6372     if(!xp){
6373       errs() << "Can't obtain an xar iterator for xar archive "
6374              << XarFilename.c_str() << "\n";
6375       return;
6376     }
6377     member_name = NULL;
6378     member_type = NULL;
6379     member_size_string = NULL;
6380     for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
6381       const char *val = nullptr;
6382       xar_prop_get(xf, key, &val);
6383 #if 0 // Useful for debugging.
6384       outs() << "key: " << key << " value: " << val << "\n";
6385 #endif
6386       if (strcmp(key, "name") == 0)
6387         member_name = val;
6388       if (strcmp(key, "type") == 0)
6389         member_type = val;
6390       if (strcmp(key, "data/size") == 0)
6391         member_size_string = val;
6392     }
6393     /*
6394      * If we find a file with a name, date/size and type properties
6395      * and with the type being "file" see if that is a xar file.
6396      */
6397     if (member_name != NULL && member_type != NULL &&
6398         strcmp(member_type, "file") == 0 &&
6399         member_size_string != NULL){
6400       // Extract the file into a buffer.
6401       char *endptr;
6402       member_size = strtoul(member_size_string, &endptr, 10);
6403       if (*endptr == '\0' && member_size != 0) {
6404         char *buffer;
6405         if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
6406 #if 0 // Useful for debugging.
6407           outs() << "xar member: " << member_name << " extracted\n";
6408 #endif
6409           // Set the XarMemberName we want to see printed in the header.
6410           std::string OldXarMemberName;
6411           // If XarMemberName is already set this is nested. So
6412           // save the old name and create the nested name.
6413           if (!XarMemberName.empty()) {
6414             OldXarMemberName = XarMemberName;
6415             XarMemberName =
6416                 (Twine("[") + XarMemberName + "]" + member_name).str();
6417           } else {
6418             OldXarMemberName = "";
6419             XarMemberName = member_name;
6420           }
6421           // See if this is could be a xar file (nested).
6422           if (member_size >= sizeof(struct xar_header)) {
6423 #if 0 // Useful for debugging.
6424             outs() << "could be a xar file: " << member_name << "\n";
6425 #endif
6426             memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
6427             if (sys::IsLittleEndianHost)
6428               swapStruct(XarHeader);
6429             if (XarHeader.magic == XAR_HEADER_MAGIC)
6430               DumpBitcodeSection(O, buffer, member_size, verbose,
6431                                  PrintXarHeader, PrintXarFileHeaders,
6432                                  XarMemberName);
6433           }
6434           XarMemberName = OldXarMemberName;
6435           delete buffer;
6436         }
6437       }
6438     }
6439   }
6440 }
6441 #endif // defined(HAVE_LIBXAR)
6442 
printObjcMetaData(MachOObjectFile * O,bool verbose)6443 static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
6444   if (O->is64Bit())
6445     printObjc2_64bit_MetaData(O, verbose);
6446   else {
6447     MachO::mach_header H;
6448     H = O->getHeader();
6449     if (H.cputype == MachO::CPU_TYPE_ARM)
6450       printObjc2_32bit_MetaData(O, verbose);
6451     else {
6452       // This is the 32-bit non-arm cputype case.  Which is normally
6453       // the first Objective-C ABI.  But it may be the case of a
6454       // binary for the iOS simulator which is the second Objective-C
6455       // ABI.  In that case printObjc1_32bit_MetaData() will determine that
6456       // and return false.
6457       if (!printObjc1_32bit_MetaData(O, verbose))
6458         printObjc2_32bit_MetaData(O, verbose);
6459     }
6460   }
6461 }
6462 
6463 // GuessLiteralPointer returns a string which for the item in the Mach-O file
6464 // for the address passed in as ReferenceValue for printing as a comment with
6465 // the instruction and also returns the corresponding type of that item
6466 // indirectly through ReferenceType.
6467 //
6468 // If ReferenceValue is an address of literal cstring then a pointer to the
6469 // cstring is returned and ReferenceType is set to
6470 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
6471 //
6472 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or
6473 // Class ref that name is returned and the ReferenceType is set accordingly.
6474 //
6475 // Lastly, literals which are Symbol address in a literal pool are looked for
6476 // and if found the symbol name is returned and ReferenceType is set to
6477 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
6478 //
6479 // If there is no item in the Mach-O file for the address passed in as
6480 // ReferenceValue nullptr is returned and ReferenceType is unchanged.
GuessLiteralPointer(uint64_t ReferenceValue,uint64_t ReferencePC,uint64_t * ReferenceType,struct DisassembleInfo * info)6481 static const char *GuessLiteralPointer(uint64_t ReferenceValue,
6482                                        uint64_t ReferencePC,
6483                                        uint64_t *ReferenceType,
6484                                        struct DisassembleInfo *info) {
6485   // First see if there is an external relocation entry at the ReferencePC.
6486   if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
6487     uint64_t sect_addr = info->S.getAddress();
6488     uint64_t sect_offset = ReferencePC - sect_addr;
6489     bool reloc_found = false;
6490     DataRefImpl Rel;
6491     MachO::any_relocation_info RE;
6492     bool isExtern = false;
6493     SymbolRef Symbol;
6494     for (const RelocationRef &Reloc : info->S.relocations()) {
6495       uint64_t RelocOffset = Reloc.getOffset();
6496       if (RelocOffset == sect_offset) {
6497         Rel = Reloc.getRawDataRefImpl();
6498         RE = info->O->getRelocation(Rel);
6499         if (info->O->isRelocationScattered(RE))
6500           continue;
6501         isExtern = info->O->getPlainRelocationExternal(RE);
6502         if (isExtern) {
6503           symbol_iterator RelocSym = Reloc.getSymbol();
6504           Symbol = *RelocSym;
6505         }
6506         reloc_found = true;
6507         break;
6508       }
6509     }
6510     // If there is an external relocation entry for a symbol in a section
6511     // then used that symbol's value for the value of the reference.
6512     if (reloc_found && isExtern) {
6513       if (info->O->getAnyRelocationPCRel(RE)) {
6514         unsigned Type = info->O->getAnyRelocationType(RE);
6515         if (Type == MachO::X86_64_RELOC_SIGNED) {
6516           ReferenceValue = Symbol.getValue();
6517         }
6518       }
6519     }
6520   }
6521 
6522   // Look for literals such as Objective-C CFStrings refs, Selector refs,
6523   // Message refs and Class refs.
6524   bool classref, selref, msgref, cfstring;
6525   uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
6526                                                selref, msgref, cfstring);
6527   if (classref && pointer_value == 0) {
6528     // Note the ReferenceValue is a pointer into the __objc_classrefs section.
6529     // And the pointer_value in that section is typically zero as it will be
6530     // set by dyld as part of the "bind information".
6531     const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
6532     if (name != nullptr) {
6533       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6534       const char *class_name = strrchr(name, '$');
6535       if (class_name != nullptr && class_name[1] == '_' &&
6536           class_name[2] != '\0') {
6537         info->class_name = class_name + 2;
6538         return name;
6539       }
6540     }
6541   }
6542 
6543   if (classref) {
6544     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6545     const char *name =
6546         get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
6547     if (name != nullptr)
6548       info->class_name = name;
6549     else
6550       name = "bad class ref";
6551     return name;
6552   }
6553 
6554   if (cfstring) {
6555     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
6556     const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
6557     return name;
6558   }
6559 
6560   if (selref && pointer_value == 0)
6561     pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
6562 
6563   if (pointer_value != 0)
6564     ReferenceValue = pointer_value;
6565 
6566   const char *name = GuessCstringPointer(ReferenceValue, info);
6567   if (name) {
6568     if (pointer_value != 0 && selref) {
6569       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
6570       info->selector_name = name;
6571     } else if (pointer_value != 0 && msgref) {
6572       info->class_name = nullptr;
6573       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
6574       info->selector_name = name;
6575     } else
6576       *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
6577     return name;
6578   }
6579 
6580   // Lastly look for an indirect symbol with this ReferenceValue which is in
6581   // a literal pool.  If found return that symbol name.
6582   name = GuessIndirectSymbol(ReferenceValue, info);
6583   if (name) {
6584     *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
6585     return name;
6586   }
6587 
6588   return nullptr;
6589 }
6590 
6591 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
6592 // the Symbolizer.  It looks up the ReferenceValue using the info passed via the
6593 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
6594 // is created and returns the symbol name that matches the ReferenceValue or
6595 // nullptr if none.  The ReferenceType is passed in for the IN type of
6596 // reference the instruction is making from the values in defined in the header
6597 // "llvm-c/Disassembler.h".  On return the ReferenceType can set to a specific
6598 // Out type and the ReferenceName will also be set which is added as a comment
6599 // to the disassembled instruction.
6600 //
6601 // If the symbol name is a C++ mangled name then the demangled name is
6602 // returned through ReferenceName and ReferenceType is set to
6603 // LLVMDisassembler_ReferenceType_DeMangled_Name .
6604 //
6605 // When this is called to get a symbol name for a branch target then the
6606 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
6607 // SymbolValue will be looked for in the indirect symbol table to determine if
6608 // it is an address for a symbol stub.  If so then the symbol name for that
6609 // stub is returned indirectly through ReferenceName and then ReferenceType is
6610 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
6611 //
6612 // When this is called with an value loaded via a PC relative load then
6613 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
6614 // SymbolValue is checked to be an address of literal pointer, symbol pointer,
6615 // or an Objective-C meta data reference.  If so the output ReferenceType is
6616 // set to correspond to that as well as setting the ReferenceName.
SymbolizerSymbolLookUp(void * DisInfo,uint64_t ReferenceValue,uint64_t * ReferenceType,uint64_t ReferencePC,const char ** ReferenceName)6617 static const char *SymbolizerSymbolLookUp(void *DisInfo,
6618                                           uint64_t ReferenceValue,
6619                                           uint64_t *ReferenceType,
6620                                           uint64_t ReferencePC,
6621                                           const char **ReferenceName) {
6622   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
6623   // If no verbose symbolic information is wanted then just return nullptr.
6624   if (!info->verbose) {
6625     *ReferenceName = nullptr;
6626     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6627     return nullptr;
6628   }
6629 
6630   const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
6631 
6632   if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
6633     *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
6634     if (*ReferenceName != nullptr) {
6635       method_reference(info, ReferenceType, ReferenceName);
6636       if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
6637         *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
6638     } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6639       if (info->demangled_name != nullptr)
6640         free(info->demangled_name);
6641       int status;
6642       info->demangled_name =
6643           itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
6644       if (info->demangled_name != nullptr) {
6645         *ReferenceName = info->demangled_name;
6646         *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
6647       } else
6648         *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6649     } else
6650       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6651   } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
6652     *ReferenceName =
6653         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6654     if (*ReferenceName)
6655       method_reference(info, ReferenceType, ReferenceName);
6656     else
6657       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6658     // If this is arm64 and the reference is an adrp instruction save the
6659     // instruction, passed in ReferenceValue and the address of the instruction
6660     // for use later if we see and add immediate instruction.
6661   } else if (info->O->getArch() == Triple::aarch64 &&
6662              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
6663     info->adrp_inst = ReferenceValue;
6664     info->adrp_addr = ReferencePC;
6665     SymbolName = nullptr;
6666     *ReferenceName = nullptr;
6667     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6668     // If this is arm64 and reference is an add immediate instruction and we
6669     // have
6670     // seen an adrp instruction just before it and the adrp's Xd register
6671     // matches
6672     // this add's Xn register reconstruct the value being referenced and look to
6673     // see if it is a literal pointer.  Note the add immediate instruction is
6674     // passed in ReferenceValue.
6675   } else if (info->O->getArch() == Triple::aarch64 &&
6676              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
6677              ReferencePC - 4 == info->adrp_addr &&
6678              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6679              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6680     uint32_t addxri_inst;
6681     uint64_t adrp_imm, addxri_imm;
6682 
6683     adrp_imm =
6684         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6685     if (info->adrp_inst & 0x0200000)
6686       adrp_imm |= 0xfffffffffc000000LL;
6687 
6688     addxri_inst = ReferenceValue;
6689     addxri_imm = (addxri_inst >> 10) & 0xfff;
6690     if (((addxri_inst >> 22) & 0x3) == 1)
6691       addxri_imm <<= 12;
6692 
6693     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6694                      (adrp_imm << 12) + addxri_imm;
6695 
6696     *ReferenceName =
6697         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6698     if (*ReferenceName == nullptr)
6699       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6700     // If this is arm64 and the reference is a load register instruction and we
6701     // have seen an adrp instruction just before it and the adrp's Xd register
6702     // matches this add's Xn register reconstruct the value being referenced and
6703     // look to see if it is a literal pointer.  Note the load register
6704     // instruction is passed in ReferenceValue.
6705   } else if (info->O->getArch() == Triple::aarch64 &&
6706              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
6707              ReferencePC - 4 == info->adrp_addr &&
6708              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6709              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6710     uint32_t ldrxui_inst;
6711     uint64_t adrp_imm, ldrxui_imm;
6712 
6713     adrp_imm =
6714         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6715     if (info->adrp_inst & 0x0200000)
6716       adrp_imm |= 0xfffffffffc000000LL;
6717 
6718     ldrxui_inst = ReferenceValue;
6719     ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
6720 
6721     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6722                      (adrp_imm << 12) + (ldrxui_imm << 3);
6723 
6724     *ReferenceName =
6725         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6726     if (*ReferenceName == nullptr)
6727       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6728   }
6729   // If this arm64 and is an load register (PC-relative) instruction the
6730   // ReferenceValue is the PC plus the immediate value.
6731   else if (info->O->getArch() == Triple::aarch64 &&
6732            (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
6733             *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
6734     *ReferenceName =
6735         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6736     if (*ReferenceName == nullptr)
6737       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6738   } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6739     if (info->demangled_name != nullptr)
6740       free(info->demangled_name);
6741     int status;
6742     info->demangled_name =
6743         itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
6744     if (info->demangled_name != nullptr) {
6745       *ReferenceName = info->demangled_name;
6746       *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
6747     }
6748   }
6749   else {
6750     *ReferenceName = nullptr;
6751     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6752   }
6753 
6754   return SymbolName;
6755 }
6756 
6757 /// Emits the comments that are stored in the CommentStream.
6758 /// Each comment in the CommentStream must end with a newline.
emitComments(raw_svector_ostream & CommentStream,SmallString<128> & CommentsToEmit,formatted_raw_ostream & FormattedOS,const MCAsmInfo & MAI)6759 static void emitComments(raw_svector_ostream &CommentStream,
6760                          SmallString<128> &CommentsToEmit,
6761                          formatted_raw_ostream &FormattedOS,
6762                          const MCAsmInfo &MAI) {
6763   // Flush the stream before taking its content.
6764   StringRef Comments = CommentsToEmit.str();
6765   // Get the default information for printing a comment.
6766   StringRef CommentBegin = MAI.getCommentString();
6767   unsigned CommentColumn = MAI.getCommentColumn();
6768   bool IsFirst = true;
6769   while (!Comments.empty()) {
6770     if (!IsFirst)
6771       FormattedOS << '\n';
6772     // Emit a line of comments.
6773     FormattedOS.PadToColumn(CommentColumn);
6774     size_t Position = Comments.find('\n');
6775     FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
6776     // Move after the newline character.
6777     Comments = Comments.substr(Position + 1);
6778     IsFirst = false;
6779   }
6780   FormattedOS.flush();
6781 
6782   // Tell the comment stream that the vector changed underneath it.
6783   CommentsToEmit.clear();
6784 }
6785 
DisassembleMachO(StringRef Filename,MachOObjectFile * MachOOF,StringRef DisSegName,StringRef DisSectName)6786 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
6787                              StringRef DisSegName, StringRef DisSectName) {
6788   const char *McpuDefault = nullptr;
6789   const Target *ThumbTarget = nullptr;
6790   const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
6791   if (!TheTarget) {
6792     // GetTarget prints out stuff.
6793     return;
6794   }
6795   std::string MachOMCPU;
6796   if (MCPU.empty() && McpuDefault)
6797     MachOMCPU = McpuDefault;
6798   else
6799     MachOMCPU = MCPU;
6800 
6801   std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
6802   std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
6803   if (ThumbTarget)
6804     ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
6805 
6806   // Package up features to be passed to target/subtarget
6807   std::string FeaturesStr;
6808   if (MAttrs.size()) {
6809     SubtargetFeatures Features;
6810     for (unsigned i = 0; i != MAttrs.size(); ++i)
6811       Features.AddFeature(MAttrs[i]);
6812     FeaturesStr = Features.getString();
6813   }
6814 
6815   // Set up disassembler.
6816   std::unique_ptr<const MCRegisterInfo> MRI(
6817       TheTarget->createMCRegInfo(TripleName));
6818   std::unique_ptr<const MCAsmInfo> AsmInfo(
6819       TheTarget->createMCAsmInfo(*MRI, TripleName));
6820   std::unique_ptr<const MCSubtargetInfo> STI(
6821       TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
6822   MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr);
6823   std::unique_ptr<MCDisassembler> DisAsm(
6824       TheTarget->createMCDisassembler(*STI, Ctx));
6825   std::unique_ptr<MCSymbolizer> Symbolizer;
6826   struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
6827   std::unique_ptr<MCRelocationInfo> RelInfo(
6828       TheTarget->createMCRelocationInfo(TripleName, Ctx));
6829   if (RelInfo) {
6830     Symbolizer.reset(TheTarget->createMCSymbolizer(
6831         TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6832         &SymbolizerInfo, &Ctx, std::move(RelInfo)));
6833     DisAsm->setSymbolizer(std::move(Symbolizer));
6834   }
6835   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
6836   std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
6837       Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
6838   // Set the display preference for hex vs. decimal immediates.
6839   IP->setPrintImmHex(PrintImmHex);
6840   // Comment stream and backing vector.
6841   SmallString<128> CommentsToEmit;
6842   raw_svector_ostream CommentStream(CommentsToEmit);
6843   // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
6844   // if it is done then arm64 comments for string literals don't get printed
6845   // and some constant get printed instead and not setting it causes intel
6846   // (32-bit and 64-bit) comments printed with different spacing before the
6847   // comment causing different diffs with the 'C' disassembler library API.
6848   // IP->setCommentStream(CommentStream);
6849 
6850   if (!AsmInfo || !STI || !DisAsm || !IP) {
6851     errs() << "error: couldn't initialize disassembler for target "
6852            << TripleName << '\n';
6853     return;
6854   }
6855 
6856   // Set up separate thumb disassembler if needed.
6857   std::unique_ptr<const MCRegisterInfo> ThumbMRI;
6858   std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
6859   std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
6860   std::unique_ptr<MCDisassembler> ThumbDisAsm;
6861   std::unique_ptr<MCInstPrinter> ThumbIP;
6862   std::unique_ptr<MCContext> ThumbCtx;
6863   std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
6864   struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
6865   std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
6866   if (ThumbTarget) {
6867     ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
6868     ThumbAsmInfo.reset(
6869         ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName));
6870     ThumbSTI.reset(
6871         ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
6872                                            FeaturesStr));
6873     ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr));
6874     ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
6875     MCContext *PtrThumbCtx = ThumbCtx.get();
6876     ThumbRelInfo.reset(
6877         ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
6878     if (ThumbRelInfo) {
6879       ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
6880           ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
6881           &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
6882       ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
6883     }
6884     int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
6885     ThumbIP.reset(ThumbTarget->createMCInstPrinter(
6886         Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
6887         *ThumbInstrInfo, *ThumbMRI));
6888     // Set the display preference for hex vs. decimal immediates.
6889     ThumbIP->setPrintImmHex(PrintImmHex);
6890   }
6891 
6892   if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) {
6893     errs() << "error: couldn't initialize disassembler for target "
6894            << ThumbTripleName << '\n';
6895     return;
6896   }
6897 
6898   MachO::mach_header Header = MachOOF->getHeader();
6899 
6900   // FIXME: Using the -cfg command line option, this code used to be able to
6901   // annotate relocations with the referenced symbol's name, and if this was
6902   // inside a __[cf]string section, the data it points to. This is now replaced
6903   // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
6904   std::vector<SectionRef> Sections;
6905   std::vector<SymbolRef> Symbols;
6906   SmallVector<uint64_t, 8> FoundFns;
6907   uint64_t BaseSegmentAddress;
6908 
6909   getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
6910                         BaseSegmentAddress);
6911 
6912   // Sort the symbols by address, just in case they didn't come in that way.
6913   llvm::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
6914 
6915   // Build a data in code table that is sorted on by the address of each entry.
6916   uint64_t BaseAddress = 0;
6917   if (Header.filetype == MachO::MH_OBJECT)
6918     BaseAddress = Sections[0].getAddress();
6919   else
6920     BaseAddress = BaseSegmentAddress;
6921   DiceTable Dices;
6922   for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
6923        DI != DE; ++DI) {
6924     uint32_t Offset;
6925     DI->getOffset(Offset);
6926     Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
6927   }
6928   array_pod_sort(Dices.begin(), Dices.end());
6929 
6930 #ifndef NDEBUG
6931   raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
6932 #else
6933   raw_ostream &DebugOut = nulls();
6934 #endif
6935 
6936   std::unique_ptr<DIContext> diContext;
6937   ObjectFile *DbgObj = MachOOF;
6938   // Try to find debug info and set up the DIContext for it.
6939   if (UseDbg) {
6940     // A separate DSym file path was specified, parse it as a macho file,
6941     // get the sections and supply it to the section name parsing machinery.
6942     if (!DSYMFile.empty()) {
6943       ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
6944           MemoryBuffer::getFileOrSTDIN(DSYMFile);
6945       if (std::error_code EC = BufOrErr.getError()) {
6946         errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';
6947         return;
6948       }
6949       Expected<std::unique_ptr<MachOObjectFile>> DbgObjCheck =
6950           ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef());
6951 
6952       if (DbgObjCheck.takeError())
6953         report_error(MachOOF->getFileName(), DbgObjCheck.takeError());
6954       DbgObj = DbgObjCheck.get().release();
6955     }
6956 
6957     // Setup the DIContext
6958     diContext = DWARFContext::create(*DbgObj);
6959   }
6960 
6961   if (FilterSections.size() == 0)
6962     outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
6963 
6964   for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
6965     StringRef SectName;
6966     if (Sections[SectIdx].getName(SectName) || SectName != DisSectName)
6967       continue;
6968 
6969     DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
6970 
6971     StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
6972     if (SegmentName != DisSegName)
6973       continue;
6974 
6975     StringRef BytesStr;
6976     Sections[SectIdx].getContents(BytesStr);
6977     ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
6978                             BytesStr.size());
6979     uint64_t SectAddress = Sections[SectIdx].getAddress();
6980 
6981     bool symbolTableWorked = false;
6982 
6983     // Create a map of symbol addresses to symbol names for use by
6984     // the SymbolizerSymbolLookUp() routine.
6985     SymbolAddressMap AddrMap;
6986     bool DisSymNameFound = false;
6987     for (const SymbolRef &Symbol : MachOOF->symbols()) {
6988       Expected<SymbolRef::Type> STOrErr = Symbol.getType();
6989       if (!STOrErr)
6990         report_error(MachOOF->getFileName(), STOrErr.takeError());
6991       SymbolRef::Type ST = *STOrErr;
6992       if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
6993           ST == SymbolRef::ST_Other) {
6994         uint64_t Address = Symbol.getValue();
6995         Expected<StringRef> SymNameOrErr = Symbol.getName();
6996         if (!SymNameOrErr)
6997           report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
6998         StringRef SymName = *SymNameOrErr;
6999         AddrMap[Address] = SymName;
7000         if (!DisSymName.empty() && DisSymName == SymName)
7001           DisSymNameFound = true;
7002       }
7003     }
7004     if (!DisSymName.empty() && !DisSymNameFound) {
7005       outs() << "Can't find -dis-symname: " << DisSymName << "\n";
7006       return;
7007     }
7008     // Set up the block of info used by the Symbolizer call backs.
7009     SymbolizerInfo.verbose = !NoSymbolicOperands;
7010     SymbolizerInfo.O = MachOOF;
7011     SymbolizerInfo.S = Sections[SectIdx];
7012     SymbolizerInfo.AddrMap = &AddrMap;
7013     SymbolizerInfo.Sections = &Sections;
7014     // Same for the ThumbSymbolizer
7015     ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
7016     ThumbSymbolizerInfo.O = MachOOF;
7017     ThumbSymbolizerInfo.S = Sections[SectIdx];
7018     ThumbSymbolizerInfo.AddrMap = &AddrMap;
7019     ThumbSymbolizerInfo.Sections = &Sections;
7020 
7021     unsigned int Arch = MachOOF->getArch();
7022 
7023     // Skip all symbols if this is a stubs file.
7024     if (Bytes.size() == 0)
7025       return;
7026 
7027     // If the section has symbols but no symbol at the start of the section
7028     // these are used to make sure the bytes before the first symbol are
7029     // disassembled.
7030     bool FirstSymbol = true;
7031     bool FirstSymbolAtSectionStart = true;
7032 
7033     // Disassemble symbol by symbol.
7034     for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
7035       Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
7036       if (!SymNameOrErr)
7037         report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
7038       StringRef SymName = *SymNameOrErr;
7039 
7040       Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType();
7041       if (!STOrErr)
7042         report_error(MachOOF->getFileName(), STOrErr.takeError());
7043       SymbolRef::Type ST = *STOrErr;
7044       if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
7045         continue;
7046 
7047       // Make sure the symbol is defined in this section.
7048       bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
7049       if (!containsSym) {
7050         if (!DisSymName.empty() && DisSymName == SymName) {
7051           outs() << "-dis-symname: " << DisSymName << " not in the section\n";
7052           return;
7053         }
7054         continue;
7055       }
7056       // The __mh_execute_header is special and we need to deal with that fact
7057       // this symbol is before the start of the (__TEXT,__text) section and at the
7058       // address of the start of the __TEXT segment.  This is because this symbol
7059       // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
7060       // start of the section in a standard MH_EXECUTE filetype.
7061       if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
7062         outs() << "-dis-symname: __mh_execute_header not in any section\n";
7063         return;
7064       }
7065       // When this code is trying to disassemble a symbol at a time and in the
7066       // case there is only the __mh_execute_header symbol left as in a stripped
7067       // executable, we need to deal with this by ignoring this symbol so the
7068       // whole section is disassembled and this symbol is then not displayed.
7069       if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
7070           SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
7071           SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
7072         continue;
7073 
7074       // If we are only disassembling one symbol see if this is that symbol.
7075       if (!DisSymName.empty() && DisSymName != SymName)
7076         continue;
7077 
7078       // Start at the address of the symbol relative to the section's address.
7079       uint64_t SectSize = Sections[SectIdx].getSize();
7080       uint64_t Start = Symbols[SymIdx].getValue();
7081       uint64_t SectionAddress = Sections[SectIdx].getAddress();
7082       Start -= SectionAddress;
7083 
7084       if (Start > SectSize) {
7085         outs() << "section data ends, " << SymName
7086                << " lies outside valid range\n";
7087         return;
7088       }
7089 
7090       // Stop disassembling either at the beginning of the next symbol or at
7091       // the end of the section.
7092       bool containsNextSym = false;
7093       uint64_t NextSym = 0;
7094       uint64_t NextSymIdx = SymIdx + 1;
7095       while (Symbols.size() > NextSymIdx) {
7096         Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType();
7097         if (!STOrErr)
7098           report_error(MachOOF->getFileName(), STOrErr.takeError());
7099         SymbolRef::Type NextSymType = *STOrErr;
7100         if (NextSymType == SymbolRef::ST_Function) {
7101           containsNextSym =
7102               Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
7103           NextSym = Symbols[NextSymIdx].getValue();
7104           NextSym -= SectionAddress;
7105           break;
7106         }
7107         ++NextSymIdx;
7108       }
7109 
7110       uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
7111       uint64_t Size;
7112 
7113       symbolTableWorked = true;
7114 
7115       DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
7116       bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb;
7117 
7118       // We only need the dedicated Thumb target if there's a real choice
7119       // (i.e. we're not targeting M-class) and the function is Thumb.
7120       bool UseThumbTarget = IsThumb && ThumbTarget;
7121 
7122       // If we are not specifying a symbol to start disassembly with and this
7123       // is the first symbol in the section but not at the start of the section
7124       // then move the disassembly index to the start of the section and
7125       // don't print the symbol name just yet.  This is so the bytes before the
7126       // first symbol are disassembled.
7127       uint64_t SymbolStart = Start;
7128       if (DisSymName.empty() && FirstSymbol && Start != 0) {
7129         FirstSymbolAtSectionStart = false;
7130         Start = 0;
7131       }
7132       else
7133         outs() << SymName << ":\n";
7134 
7135       DILineInfo lastLine;
7136       for (uint64_t Index = Start; Index < End; Index += Size) {
7137         MCInst Inst;
7138 
7139         // If this is the first symbol in the section and it was not at the
7140         // start of the section, see if we are at its Index now and if so print
7141         // the symbol name.
7142         if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart)
7143           outs() << SymName << ":\n";
7144 
7145         uint64_t PC = SectAddress + Index;
7146         if (!NoLeadingAddr) {
7147           if (FullLeadingAddr) {
7148             if (MachOOF->is64Bit())
7149               outs() << format("%016" PRIx64, PC);
7150             else
7151               outs() << format("%08" PRIx64, PC);
7152           } else {
7153             outs() << format("%8" PRIx64 ":", PC);
7154           }
7155         }
7156         if (!NoShowRawInsn || Arch == Triple::arm)
7157           outs() << "\t";
7158 
7159         // Check the data in code table here to see if this is data not an
7160         // instruction to be disassembled.
7161         DiceTable Dice;
7162         Dice.push_back(std::make_pair(PC, DiceRef()));
7163         dice_table_iterator DTI =
7164             std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
7165                         compareDiceTableEntries);
7166         if (DTI != Dices.end()) {
7167           uint16_t Length;
7168           DTI->second.getLength(Length);
7169           uint16_t Kind;
7170           DTI->second.getKind(Kind);
7171           Size = DumpDataInCode(Bytes.data() + Index, Length, Kind);
7172           if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
7173               (PC == (DTI->first + Length - 1)) && (Length & 1))
7174             Size++;
7175           continue;
7176         }
7177 
7178         SmallVector<char, 64> AnnotationsBytes;
7179         raw_svector_ostream Annotations(AnnotationsBytes);
7180 
7181         bool gotInst;
7182         if (UseThumbTarget)
7183           gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
7184                                                 PC, DebugOut, Annotations);
7185         else
7186           gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
7187                                            DebugOut, Annotations);
7188         if (gotInst) {
7189           if (!NoShowRawInsn || Arch == Triple::arm) {
7190             dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
7191           }
7192           formatted_raw_ostream FormattedOS(outs());
7193           StringRef AnnotationsStr = Annotations.str();
7194           if (UseThumbTarget)
7195             ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
7196           else
7197             IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI);
7198           emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
7199 
7200           // Print debug info.
7201           if (diContext) {
7202             DILineInfo dli = diContext->getLineInfoForAddress(PC);
7203             // Print valid line info if it changed.
7204             if (dli != lastLine && dli.Line != 0)
7205               outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
7206                      << dli.Column;
7207             lastLine = dli;
7208           }
7209           outs() << "\n";
7210         } else {
7211           unsigned int Arch = MachOOF->getArch();
7212           if (Arch == Triple::x86_64 || Arch == Triple::x86) {
7213             outs() << format("\t.byte 0x%02x #bad opcode\n",
7214                              *(Bytes.data() + Index) & 0xff);
7215             Size = 1; // skip exactly one illegible byte and move on.
7216           } else if (Arch == Triple::aarch64 ||
7217                      (Arch == Triple::arm && !IsThumb)) {
7218             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7219                               (*(Bytes.data() + Index + 1) & 0xff) << 8 |
7220                               (*(Bytes.data() + Index + 2) & 0xff) << 16 |
7221                               (*(Bytes.data() + Index + 3) & 0xff) << 24;
7222             outs() << format("\t.long\t0x%08x\n", opcode);
7223             Size = 4;
7224           } else if (Arch == Triple::arm) {
7225             assert(IsThumb && "ARM mode should have been dealt with above");
7226             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7227                               (*(Bytes.data() + Index + 1) & 0xff) << 8;
7228             outs() << format("\t.short\t0x%04x\n", opcode);
7229             Size = 2;
7230           } else{
7231             errs() << "llvm-objdump: warning: invalid instruction encoding\n";
7232             if (Size == 0)
7233               Size = 1; // skip illegible bytes
7234           }
7235         }
7236       }
7237       // Now that we are done disassembled the first symbol set the bool that
7238       // were doing this to false.
7239       FirstSymbol = false;
7240     }
7241     if (!symbolTableWorked) {
7242       // Reading the symbol table didn't work, disassemble the whole section.
7243       uint64_t SectAddress = Sections[SectIdx].getAddress();
7244       uint64_t SectSize = Sections[SectIdx].getSize();
7245       uint64_t InstSize;
7246       for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
7247         MCInst Inst;
7248 
7249         uint64_t PC = SectAddress + Index;
7250         SmallVector<char, 64> AnnotationsBytes;
7251         raw_svector_ostream Annotations(AnnotationsBytes);
7252         if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
7253                                    DebugOut, Annotations)) {
7254           if (!NoLeadingAddr) {
7255             if (FullLeadingAddr) {
7256               if (MachOOF->is64Bit())
7257                 outs() << format("%016" PRIx64, PC);
7258               else
7259                 outs() << format("%08" PRIx64, PC);
7260             } else {
7261               outs() << format("%8" PRIx64 ":", PC);
7262             }
7263           }
7264           if (!NoShowRawInsn || Arch == Triple::arm) {
7265             outs() << "\t";
7266             dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
7267           }
7268           StringRef AnnotationsStr = Annotations.str();
7269           IP->printInst(&Inst, outs(), AnnotationsStr, *STI);
7270           outs() << "\n";
7271         } else {
7272           unsigned int Arch = MachOOF->getArch();
7273           if (Arch == Triple::x86_64 || Arch == Triple::x86) {
7274             outs() << format("\t.byte 0x%02x #bad opcode\n",
7275                              *(Bytes.data() + Index) & 0xff);
7276             InstSize = 1; // skip exactly one illegible byte and move on.
7277           } else {
7278             errs() << "llvm-objdump: warning: invalid instruction encoding\n";
7279             if (InstSize == 0)
7280               InstSize = 1; // skip illegible bytes
7281           }
7282         }
7283       }
7284     }
7285     // The TripleName's need to be reset if we are called again for a different
7286     // archtecture.
7287     TripleName = "";
7288     ThumbTripleName = "";
7289 
7290     if (SymbolizerInfo.demangled_name != nullptr)
7291       free(SymbolizerInfo.demangled_name);
7292     if (ThumbSymbolizerInfo.demangled_name != nullptr)
7293       free(ThumbSymbolizerInfo.demangled_name);
7294   }
7295 }
7296 
7297 //===----------------------------------------------------------------------===//
7298 // __compact_unwind section dumping
7299 //===----------------------------------------------------------------------===//
7300 
7301 namespace {
7302 
7303 template <typename T>
read(StringRef Contents,ptrdiff_t Offset)7304 static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
7305   using llvm::support::little;
7306   using llvm::support::unaligned;
7307 
7308   if (Offset + sizeof(T) > Contents.size()) {
7309     outs() << "warning: attempt to read past end of buffer\n";
7310     return T();
7311   }
7312 
7313   uint64_t Val =
7314       support::endian::read<T, little, unaligned>(Contents.data() + Offset);
7315   return Val;
7316 }
7317 
7318 template <typename T>
readNext(StringRef Contents,ptrdiff_t & Offset)7319 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
7320   T Val = read<T>(Contents, Offset);
7321   Offset += sizeof(T);
7322   return Val;
7323 }
7324 
7325 struct CompactUnwindEntry {
7326   uint32_t OffsetInSection;
7327 
7328   uint64_t FunctionAddr;
7329   uint32_t Length;
7330   uint32_t CompactEncoding;
7331   uint64_t PersonalityAddr;
7332   uint64_t LSDAAddr;
7333 
7334   RelocationRef FunctionReloc;
7335   RelocationRef PersonalityReloc;
7336   RelocationRef LSDAReloc;
7337 
CompactUnwindEntry__anon33b510350811::CompactUnwindEntry7338   CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
7339       : OffsetInSection(Offset) {
7340     if (Is64)
7341       read<uint64_t>(Contents, Offset);
7342     else
7343       read<uint32_t>(Contents, Offset);
7344   }
7345 
7346 private:
read__anon33b510350811::CompactUnwindEntry7347   template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
7348     FunctionAddr = readNext<UIntPtr>(Contents, Offset);
7349     Length = readNext<uint32_t>(Contents, Offset);
7350     CompactEncoding = readNext<uint32_t>(Contents, Offset);
7351     PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
7352     LSDAAddr = readNext<UIntPtr>(Contents, Offset);
7353   }
7354 };
7355 }
7356 
7357 /// Given a relocation from __compact_unwind, consisting of the RelocationRef
7358 /// and data being relocated, determine the best base Name and Addend to use for
7359 /// display purposes.
7360 ///
7361 /// 1. An Extern relocation will directly reference a symbol (and the data is
7362 ///    then already an addend), so use that.
7363 /// 2. Otherwise the data is an offset in the object file's layout; try to find
7364 //     a symbol before it in the same section, and use the offset from there.
7365 /// 3. Finally, if all that fails, fall back to an offset from the start of the
7366 ///    referenced section.
findUnwindRelocNameAddend(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr,StringRef & Name,uint64_t & Addend)7367 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
7368                                       std::map<uint64_t, SymbolRef> &Symbols,
7369                                       const RelocationRef &Reloc, uint64_t Addr,
7370                                       StringRef &Name, uint64_t &Addend) {
7371   if (Reloc.getSymbol() != Obj->symbol_end()) {
7372     Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName();
7373     if (!NameOrErr)
7374       report_error(Obj->getFileName(), NameOrErr.takeError());
7375     Name = *NameOrErr;
7376     Addend = Addr;
7377     return;
7378   }
7379 
7380   auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
7381   SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
7382 
7383   uint64_t SectionAddr = RelocSection.getAddress();
7384 
7385   auto Sym = Symbols.upper_bound(Addr);
7386   if (Sym == Symbols.begin()) {
7387     // The first symbol in the object is after this reference, the best we can
7388     // do is section-relative notation.
7389     RelocSection.getName(Name);
7390     Addend = Addr - SectionAddr;
7391     return;
7392   }
7393 
7394   // Go back one so that SymbolAddress <= Addr.
7395   --Sym;
7396 
7397   auto SectOrErr = Sym->second.getSection();
7398   if (!SectOrErr)
7399     report_error(Obj->getFileName(), SectOrErr.takeError());
7400   section_iterator SymSection = *SectOrErr;
7401   if (RelocSection == *SymSection) {
7402     // There's a valid symbol in the same section before this reference.
7403     Expected<StringRef> NameOrErr = Sym->second.getName();
7404     if (!NameOrErr)
7405       report_error(Obj->getFileName(), NameOrErr.takeError());
7406     Name = *NameOrErr;
7407     Addend = Addr - Sym->first;
7408     return;
7409   }
7410 
7411   // There is a symbol before this reference, but it's in a different
7412   // section. Probably not helpful to mention it, so use the section name.
7413   RelocSection.getName(Name);
7414   Addend = Addr - SectionAddr;
7415 }
7416 
printUnwindRelocDest(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr)7417 static void printUnwindRelocDest(const MachOObjectFile *Obj,
7418                                  std::map<uint64_t, SymbolRef> &Symbols,
7419                                  const RelocationRef &Reloc, uint64_t Addr) {
7420   StringRef Name;
7421   uint64_t Addend;
7422 
7423   if (!Reloc.getObject())
7424     return;
7425 
7426   findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
7427 
7428   outs() << Name;
7429   if (Addend)
7430     outs() << " + " << format("0x%" PRIx64, Addend);
7431 }
7432 
7433 static void
printMachOCompactUnwindSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & CompactUnwind)7434 printMachOCompactUnwindSection(const MachOObjectFile *Obj,
7435                                std::map<uint64_t, SymbolRef> &Symbols,
7436                                const SectionRef &CompactUnwind) {
7437 
7438   if (!Obj->isLittleEndian()) {
7439     outs() << "Skipping big-endian __compact_unwind section\n";
7440     return;
7441   }
7442 
7443   bool Is64 = Obj->is64Bit();
7444   uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
7445   uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
7446 
7447   StringRef Contents;
7448   CompactUnwind.getContents(Contents);
7449 
7450   SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
7451 
7452   // First populate the initial raw offsets, encodings and so on from the entry.
7453   for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
7454     CompactUnwindEntry Entry(Contents, Offset, Is64);
7455     CompactUnwinds.push_back(Entry);
7456   }
7457 
7458   // Next we need to look at the relocations to find out what objects are
7459   // actually being referred to.
7460   for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
7461     uint64_t RelocAddress = Reloc.getOffset();
7462 
7463     uint32_t EntryIdx = RelocAddress / EntrySize;
7464     uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
7465     CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
7466 
7467     if (OffsetInEntry == 0)
7468       Entry.FunctionReloc = Reloc;
7469     else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
7470       Entry.PersonalityReloc = Reloc;
7471     else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
7472       Entry.LSDAReloc = Reloc;
7473     else {
7474       outs() << "Invalid relocation in __compact_unwind section\n";
7475       return;
7476     }
7477   }
7478 
7479   // Finally, we're ready to print the data we've gathered.
7480   outs() << "Contents of __compact_unwind section:\n";
7481   for (auto &Entry : CompactUnwinds) {
7482     outs() << "  Entry at offset "
7483            << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
7484 
7485     // 1. Start of the region this entry applies to.
7486     outs() << "    start:                " << format("0x%" PRIx64,
7487                                                      Entry.FunctionAddr) << ' ';
7488     printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
7489     outs() << '\n';
7490 
7491     // 2. Length of the region this entry applies to.
7492     outs() << "    length:               " << format("0x%" PRIx32, Entry.Length)
7493            << '\n';
7494     // 3. The 32-bit compact encoding.
7495     outs() << "    compact encoding:     "
7496            << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
7497 
7498     // 4. The personality function, if present.
7499     if (Entry.PersonalityReloc.getObject()) {
7500       outs() << "    personality function: "
7501              << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
7502       printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
7503                            Entry.PersonalityAddr);
7504       outs() << '\n';
7505     }
7506 
7507     // 5. This entry's language-specific data area.
7508     if (Entry.LSDAReloc.getObject()) {
7509       outs() << "    LSDA:                 " << format("0x%" PRIx64,
7510                                                        Entry.LSDAAddr) << ' ';
7511       printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
7512       outs() << '\n';
7513     }
7514   }
7515 }
7516 
7517 //===----------------------------------------------------------------------===//
7518 // __unwind_info section dumping
7519 //===----------------------------------------------------------------------===//
7520 
printRegularSecondLevelUnwindPage(StringRef PageData)7521 static void printRegularSecondLevelUnwindPage(StringRef PageData) {
7522   ptrdiff_t Pos = 0;
7523   uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7524   (void)Kind;
7525   assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
7526 
7527   uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7528   uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7529 
7530   Pos = EntriesStart;
7531   for (unsigned i = 0; i < NumEntries; ++i) {
7532     uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
7533     uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
7534 
7535     outs() << "      [" << i << "]: "
7536            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7537            << ", "
7538            << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
7539   }
7540 }
7541 
printCompressedSecondLevelUnwindPage(StringRef PageData,uint32_t FunctionBase,const SmallVectorImpl<uint32_t> & CommonEncodings)7542 static void printCompressedSecondLevelUnwindPage(
7543     StringRef PageData, uint32_t FunctionBase,
7544     const SmallVectorImpl<uint32_t> &CommonEncodings) {
7545   ptrdiff_t Pos = 0;
7546   uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7547   (void)Kind;
7548   assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
7549 
7550   uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7551   uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7552 
7553   uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos);
7554   readNext<uint16_t>(PageData, Pos);
7555   StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos);
7556 
7557   Pos = EntriesStart;
7558   for (unsigned i = 0; i < NumEntries; ++i) {
7559     uint32_t Entry = readNext<uint32_t>(PageData, Pos);
7560     uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
7561     uint32_t EncodingIdx = Entry >> 24;
7562 
7563     uint32_t Encoding;
7564     if (EncodingIdx < CommonEncodings.size())
7565       Encoding = CommonEncodings[EncodingIdx];
7566     else
7567       Encoding = read<uint32_t>(PageEncodings,
7568                                 sizeof(uint32_t) *
7569                                     (EncodingIdx - CommonEncodings.size()));
7570 
7571     outs() << "      [" << i << "]: "
7572            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7573            << ", "
7574            << "encoding[" << EncodingIdx
7575            << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
7576   }
7577 }
7578 
printMachOUnwindInfoSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & UnwindInfo)7579 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
7580                                         std::map<uint64_t, SymbolRef> &Symbols,
7581                                         const SectionRef &UnwindInfo) {
7582 
7583   if (!Obj->isLittleEndian()) {
7584     outs() << "Skipping big-endian __unwind_info section\n";
7585     return;
7586   }
7587 
7588   outs() << "Contents of __unwind_info section:\n";
7589 
7590   StringRef Contents;
7591   UnwindInfo.getContents(Contents);
7592   ptrdiff_t Pos = 0;
7593 
7594   //===----------------------------------
7595   // Section header
7596   //===----------------------------------
7597 
7598   uint32_t Version = readNext<uint32_t>(Contents, Pos);
7599   outs() << "  Version:                                   "
7600          << format("0x%" PRIx32, Version) << '\n';
7601   if (Version != 1) {
7602     outs() << "    Skipping section with unknown version\n";
7603     return;
7604   }
7605 
7606   uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
7607   outs() << "  Common encodings array section offset:     "
7608          << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
7609   uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
7610   outs() << "  Number of common encodings in array:       "
7611          << format("0x%" PRIx32, NumCommonEncodings) << '\n';
7612 
7613   uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
7614   outs() << "  Personality function array section offset: "
7615          << format("0x%" PRIx32, PersonalitiesStart) << '\n';
7616   uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
7617   outs() << "  Number of personality functions in array:  "
7618          << format("0x%" PRIx32, NumPersonalities) << '\n';
7619 
7620   uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
7621   outs() << "  Index array section offset:                "
7622          << format("0x%" PRIx32, IndicesStart) << '\n';
7623   uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
7624   outs() << "  Number of indices in array:                "
7625          << format("0x%" PRIx32, NumIndices) << '\n';
7626 
7627   //===----------------------------------
7628   // A shared list of common encodings
7629   //===----------------------------------
7630 
7631   // These occupy indices in the range [0, N] whenever an encoding is referenced
7632   // from a compressed 2nd level index table. In practice the linker only
7633   // creates ~128 of these, so that indices are available to embed encodings in
7634   // the 2nd level index.
7635 
7636   SmallVector<uint32_t, 64> CommonEncodings;
7637   outs() << "  Common encodings: (count = " << NumCommonEncodings << ")\n";
7638   Pos = CommonEncodingsStart;
7639   for (unsigned i = 0; i < NumCommonEncodings; ++i) {
7640     uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
7641     CommonEncodings.push_back(Encoding);
7642 
7643     outs() << "    encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
7644            << '\n';
7645   }
7646 
7647   //===----------------------------------
7648   // Personality functions used in this executable
7649   //===----------------------------------
7650 
7651   // There should be only a handful of these (one per source language,
7652   // roughly). Particularly since they only get 2 bits in the compact encoding.
7653 
7654   outs() << "  Personality functions: (count = " << NumPersonalities << ")\n";
7655   Pos = PersonalitiesStart;
7656   for (unsigned i = 0; i < NumPersonalities; ++i) {
7657     uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
7658     outs() << "    personality[" << i + 1
7659            << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
7660   }
7661 
7662   //===----------------------------------
7663   // The level 1 index entries
7664   //===----------------------------------
7665 
7666   // These specify an approximate place to start searching for the more detailed
7667   // information, sorted by PC.
7668 
7669   struct IndexEntry {
7670     uint32_t FunctionOffset;
7671     uint32_t SecondLevelPageStart;
7672     uint32_t LSDAStart;
7673   };
7674 
7675   SmallVector<IndexEntry, 4> IndexEntries;
7676 
7677   outs() << "  Top level indices: (count = " << NumIndices << ")\n";
7678   Pos = IndicesStart;
7679   for (unsigned i = 0; i < NumIndices; ++i) {
7680     IndexEntry Entry;
7681 
7682     Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
7683     Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
7684     Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
7685     IndexEntries.push_back(Entry);
7686 
7687     outs() << "    [" << i << "]: "
7688            << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
7689            << ", "
7690            << "2nd level page offset="
7691            << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
7692            << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
7693   }
7694 
7695   //===----------------------------------
7696   // Next come the LSDA tables
7697   //===----------------------------------
7698 
7699   // The LSDA layout is rather implicit: it's a contiguous array of entries from
7700   // the first top-level index's LSDAOffset to the last (sentinel).
7701 
7702   outs() << "  LSDA descriptors:\n";
7703   Pos = IndexEntries[0].LSDAStart;
7704   const uint32_t LSDASize = 2 * sizeof(uint32_t);
7705   int NumLSDAs =
7706       (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
7707 
7708   for (int i = 0; i < NumLSDAs; ++i) {
7709     uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
7710     uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
7711     outs() << "    [" << i << "]: "
7712            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7713            << ", "
7714            << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
7715   }
7716 
7717   //===----------------------------------
7718   // Finally, the 2nd level indices
7719   //===----------------------------------
7720 
7721   // Generally these are 4K in size, and have 2 possible forms:
7722   //   + Regular stores up to 511 entries with disparate encodings
7723   //   + Compressed stores up to 1021 entries if few enough compact encoding
7724   //     values are used.
7725   outs() << "  Second level indices:\n";
7726   for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
7727     // The final sentinel top-level index has no associated 2nd level page
7728     if (IndexEntries[i].SecondLevelPageStart == 0)
7729       break;
7730 
7731     outs() << "    Second level index[" << i << "]: "
7732            << "offset in section="
7733            << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
7734            << ", "
7735            << "base function offset="
7736            << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
7737 
7738     Pos = IndexEntries[i].SecondLevelPageStart;
7739     if (Pos + sizeof(uint32_t) > Contents.size()) {
7740       outs() << "warning: invalid offset for second level page: " << Pos << '\n';
7741       continue;
7742     }
7743 
7744     uint32_t Kind =
7745         *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
7746     if (Kind == 2)
7747       printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
7748     else if (Kind == 3)
7749       printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
7750                                            IndexEntries[i].FunctionOffset,
7751                                            CommonEncodings);
7752     else
7753       outs() << "    Skipping 2nd level page with unknown kind " << Kind
7754              << '\n';
7755   }
7756 }
7757 
printMachOUnwindInfo(const MachOObjectFile * Obj)7758 void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
7759   std::map<uint64_t, SymbolRef> Symbols;
7760   for (const SymbolRef &SymRef : Obj->symbols()) {
7761     // Discard any undefined or absolute symbols. They're not going to take part
7762     // in the convenience lookup for unwind info and just take up resources.
7763     auto SectOrErr = SymRef.getSection();
7764     if (!SectOrErr) {
7765       // TODO: Actually report errors helpfully.
7766       consumeError(SectOrErr.takeError());
7767       continue;
7768     }
7769     section_iterator Section = *SectOrErr;
7770     if (Section == Obj->section_end())
7771       continue;
7772 
7773     uint64_t Addr = SymRef.getValue();
7774     Symbols.insert(std::make_pair(Addr, SymRef));
7775   }
7776 
7777   for (const SectionRef &Section : Obj->sections()) {
7778     StringRef SectName;
7779     Section.getName(SectName);
7780     if (SectName == "__compact_unwind")
7781       printMachOCompactUnwindSection(Obj, Symbols, Section);
7782     else if (SectName == "__unwind_info")
7783       printMachOUnwindInfoSection(Obj, Symbols, Section);
7784   }
7785 }
7786 
PrintMachHeader(uint32_t magic,uint32_t cputype,uint32_t cpusubtype,uint32_t filetype,uint32_t ncmds,uint32_t sizeofcmds,uint32_t flags,bool verbose)7787 static void PrintMachHeader(uint32_t magic, uint32_t cputype,
7788                             uint32_t cpusubtype, uint32_t filetype,
7789                             uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
7790                             bool verbose) {
7791   outs() << "Mach header\n";
7792   outs() << "      magic cputype cpusubtype  caps    filetype ncmds "
7793             "sizeofcmds      flags\n";
7794   if (verbose) {
7795     if (magic == MachO::MH_MAGIC)
7796       outs() << "   MH_MAGIC";
7797     else if (magic == MachO::MH_MAGIC_64)
7798       outs() << "MH_MAGIC_64";
7799     else
7800       outs() << format(" 0x%08" PRIx32, magic);
7801     switch (cputype) {
7802     case MachO::CPU_TYPE_I386:
7803       outs() << "    I386";
7804       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7805       case MachO::CPU_SUBTYPE_I386_ALL:
7806         outs() << "        ALL";
7807         break;
7808       default:
7809         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7810         break;
7811       }
7812       break;
7813     case MachO::CPU_TYPE_X86_64:
7814       outs() << "  X86_64";
7815       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7816       case MachO::CPU_SUBTYPE_X86_64_ALL:
7817         outs() << "        ALL";
7818         break;
7819       case MachO::CPU_SUBTYPE_X86_64_H:
7820         outs() << "    Haswell";
7821         break;
7822       default:
7823         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7824         break;
7825       }
7826       break;
7827     case MachO::CPU_TYPE_ARM:
7828       outs() << "     ARM";
7829       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7830       case MachO::CPU_SUBTYPE_ARM_ALL:
7831         outs() << "        ALL";
7832         break;
7833       case MachO::CPU_SUBTYPE_ARM_V4T:
7834         outs() << "        V4T";
7835         break;
7836       case MachO::CPU_SUBTYPE_ARM_V5TEJ:
7837         outs() << "      V5TEJ";
7838         break;
7839       case MachO::CPU_SUBTYPE_ARM_XSCALE:
7840         outs() << "     XSCALE";
7841         break;
7842       case MachO::CPU_SUBTYPE_ARM_V6:
7843         outs() << "         V6";
7844         break;
7845       case MachO::CPU_SUBTYPE_ARM_V6M:
7846         outs() << "        V6M";
7847         break;
7848       case MachO::CPU_SUBTYPE_ARM_V7:
7849         outs() << "         V7";
7850         break;
7851       case MachO::CPU_SUBTYPE_ARM_V7EM:
7852         outs() << "       V7EM";
7853         break;
7854       case MachO::CPU_SUBTYPE_ARM_V7K:
7855         outs() << "        V7K";
7856         break;
7857       case MachO::CPU_SUBTYPE_ARM_V7M:
7858         outs() << "        V7M";
7859         break;
7860       case MachO::CPU_SUBTYPE_ARM_V7S:
7861         outs() << "        V7S";
7862         break;
7863       default:
7864         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7865         break;
7866       }
7867       break;
7868     case MachO::CPU_TYPE_ARM64:
7869       outs() << "   ARM64";
7870       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7871       case MachO::CPU_SUBTYPE_ARM64_ALL:
7872         outs() << "        ALL";
7873         break;
7874       default:
7875         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7876         break;
7877       }
7878       break;
7879     case MachO::CPU_TYPE_POWERPC:
7880       outs() << "     PPC";
7881       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7882       case MachO::CPU_SUBTYPE_POWERPC_ALL:
7883         outs() << "        ALL";
7884         break;
7885       default:
7886         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7887         break;
7888       }
7889       break;
7890     case MachO::CPU_TYPE_POWERPC64:
7891       outs() << "   PPC64";
7892       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
7893       case MachO::CPU_SUBTYPE_POWERPC_ALL:
7894         outs() << "        ALL";
7895         break;
7896       default:
7897         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7898         break;
7899       }
7900       break;
7901     default:
7902       outs() << format(" %7d", cputype);
7903       outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
7904       break;
7905     }
7906     if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
7907       outs() << " LIB64";
7908     } else {
7909       outs() << format("  0x%02" PRIx32,
7910                        (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
7911     }
7912     switch (filetype) {
7913     case MachO::MH_OBJECT:
7914       outs() << "      OBJECT";
7915       break;
7916     case MachO::MH_EXECUTE:
7917       outs() << "     EXECUTE";
7918       break;
7919     case MachO::MH_FVMLIB:
7920       outs() << "      FVMLIB";
7921       break;
7922     case MachO::MH_CORE:
7923       outs() << "        CORE";
7924       break;
7925     case MachO::MH_PRELOAD:
7926       outs() << "     PRELOAD";
7927       break;
7928     case MachO::MH_DYLIB:
7929       outs() << "       DYLIB";
7930       break;
7931     case MachO::MH_DYLIB_STUB:
7932       outs() << "  DYLIB_STUB";
7933       break;
7934     case MachO::MH_DYLINKER:
7935       outs() << "    DYLINKER";
7936       break;
7937     case MachO::MH_BUNDLE:
7938       outs() << "      BUNDLE";
7939       break;
7940     case MachO::MH_DSYM:
7941       outs() << "        DSYM";
7942       break;
7943     case MachO::MH_KEXT_BUNDLE:
7944       outs() << "  KEXTBUNDLE";
7945       break;
7946     default:
7947       outs() << format("  %10u", filetype);
7948       break;
7949     }
7950     outs() << format(" %5u", ncmds);
7951     outs() << format(" %10u", sizeofcmds);
7952     uint32_t f = flags;
7953     if (f & MachO::MH_NOUNDEFS) {
7954       outs() << "   NOUNDEFS";
7955       f &= ~MachO::MH_NOUNDEFS;
7956     }
7957     if (f & MachO::MH_INCRLINK) {
7958       outs() << " INCRLINK";
7959       f &= ~MachO::MH_INCRLINK;
7960     }
7961     if (f & MachO::MH_DYLDLINK) {
7962       outs() << " DYLDLINK";
7963       f &= ~MachO::MH_DYLDLINK;
7964     }
7965     if (f & MachO::MH_BINDATLOAD) {
7966       outs() << " BINDATLOAD";
7967       f &= ~MachO::MH_BINDATLOAD;
7968     }
7969     if (f & MachO::MH_PREBOUND) {
7970       outs() << " PREBOUND";
7971       f &= ~MachO::MH_PREBOUND;
7972     }
7973     if (f & MachO::MH_SPLIT_SEGS) {
7974       outs() << " SPLIT_SEGS";
7975       f &= ~MachO::MH_SPLIT_SEGS;
7976     }
7977     if (f & MachO::MH_LAZY_INIT) {
7978       outs() << " LAZY_INIT";
7979       f &= ~MachO::MH_LAZY_INIT;
7980     }
7981     if (f & MachO::MH_TWOLEVEL) {
7982       outs() << " TWOLEVEL";
7983       f &= ~MachO::MH_TWOLEVEL;
7984     }
7985     if (f & MachO::MH_FORCE_FLAT) {
7986       outs() << " FORCE_FLAT";
7987       f &= ~MachO::MH_FORCE_FLAT;
7988     }
7989     if (f & MachO::MH_NOMULTIDEFS) {
7990       outs() << " NOMULTIDEFS";
7991       f &= ~MachO::MH_NOMULTIDEFS;
7992     }
7993     if (f & MachO::MH_NOFIXPREBINDING) {
7994       outs() << " NOFIXPREBINDING";
7995       f &= ~MachO::MH_NOFIXPREBINDING;
7996     }
7997     if (f & MachO::MH_PREBINDABLE) {
7998       outs() << " PREBINDABLE";
7999       f &= ~MachO::MH_PREBINDABLE;
8000     }
8001     if (f & MachO::MH_ALLMODSBOUND) {
8002       outs() << " ALLMODSBOUND";
8003       f &= ~MachO::MH_ALLMODSBOUND;
8004     }
8005     if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
8006       outs() << " SUBSECTIONS_VIA_SYMBOLS";
8007       f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
8008     }
8009     if (f & MachO::MH_CANONICAL) {
8010       outs() << " CANONICAL";
8011       f &= ~MachO::MH_CANONICAL;
8012     }
8013     if (f & MachO::MH_WEAK_DEFINES) {
8014       outs() << " WEAK_DEFINES";
8015       f &= ~MachO::MH_WEAK_DEFINES;
8016     }
8017     if (f & MachO::MH_BINDS_TO_WEAK) {
8018       outs() << " BINDS_TO_WEAK";
8019       f &= ~MachO::MH_BINDS_TO_WEAK;
8020     }
8021     if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
8022       outs() << " ALLOW_STACK_EXECUTION";
8023       f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
8024     }
8025     if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
8026       outs() << " DEAD_STRIPPABLE_DYLIB";
8027       f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
8028     }
8029     if (f & MachO::MH_PIE) {
8030       outs() << " PIE";
8031       f &= ~MachO::MH_PIE;
8032     }
8033     if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
8034       outs() << " NO_REEXPORTED_DYLIBS";
8035       f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
8036     }
8037     if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
8038       outs() << " MH_HAS_TLV_DESCRIPTORS";
8039       f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
8040     }
8041     if (f & MachO::MH_NO_HEAP_EXECUTION) {
8042       outs() << " MH_NO_HEAP_EXECUTION";
8043       f &= ~MachO::MH_NO_HEAP_EXECUTION;
8044     }
8045     if (f & MachO::MH_APP_EXTENSION_SAFE) {
8046       outs() << " APP_EXTENSION_SAFE";
8047       f &= ~MachO::MH_APP_EXTENSION_SAFE;
8048     }
8049     if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
8050       outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO";
8051       f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO;
8052     }
8053     if (f != 0 || flags == 0)
8054       outs() << format(" 0x%08" PRIx32, f);
8055   } else {
8056     outs() << format(" 0x%08" PRIx32, magic);
8057     outs() << format(" %7d", cputype);
8058     outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8059     outs() << format("  0x%02" PRIx32,
8060                      (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8061     outs() << format("  %10u", filetype);
8062     outs() << format(" %5u", ncmds);
8063     outs() << format(" %10u", sizeofcmds);
8064     outs() << format(" 0x%08" PRIx32, flags);
8065   }
8066   outs() << "\n";
8067 }
8068 
PrintSegmentCommand(uint32_t cmd,uint32_t cmdsize,StringRef SegName,uint64_t vmaddr,uint64_t vmsize,uint64_t fileoff,uint64_t filesize,uint32_t maxprot,uint32_t initprot,uint32_t nsects,uint32_t flags,uint32_t object_size,bool verbose)8069 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
8070                                 StringRef SegName, uint64_t vmaddr,
8071                                 uint64_t vmsize, uint64_t fileoff,
8072                                 uint64_t filesize, uint32_t maxprot,
8073                                 uint32_t initprot, uint32_t nsects,
8074                                 uint32_t flags, uint32_t object_size,
8075                                 bool verbose) {
8076   uint64_t expected_cmdsize;
8077   if (cmd == MachO::LC_SEGMENT) {
8078     outs() << "      cmd LC_SEGMENT\n";
8079     expected_cmdsize = nsects;
8080     expected_cmdsize *= sizeof(struct MachO::section);
8081     expected_cmdsize += sizeof(struct MachO::segment_command);
8082   } else {
8083     outs() << "      cmd LC_SEGMENT_64\n";
8084     expected_cmdsize = nsects;
8085     expected_cmdsize *= sizeof(struct MachO::section_64);
8086     expected_cmdsize += sizeof(struct MachO::segment_command_64);
8087   }
8088   outs() << "  cmdsize " << cmdsize;
8089   if (cmdsize != expected_cmdsize)
8090     outs() << " Inconsistent size\n";
8091   else
8092     outs() << "\n";
8093   outs() << "  segname " << SegName << "\n";
8094   if (cmd == MachO::LC_SEGMENT_64) {
8095     outs() << "   vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
8096     outs() << "   vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
8097   } else {
8098     outs() << "   vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
8099     outs() << "   vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
8100   }
8101   outs() << "  fileoff " << fileoff;
8102   if (fileoff > object_size)
8103     outs() << " (past end of file)\n";
8104   else
8105     outs() << "\n";
8106   outs() << " filesize " << filesize;
8107   if (fileoff + filesize > object_size)
8108     outs() << " (past end of file)\n";
8109   else
8110     outs() << "\n";
8111   if (verbose) {
8112     if ((maxprot &
8113          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8114            MachO::VM_PROT_EXECUTE)) != 0)
8115       outs() << "  maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
8116     else {
8117       outs() << "  maxprot ";
8118       outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
8119       outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8120       outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8121     }
8122     if ((initprot &
8123          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8124            MachO::VM_PROT_EXECUTE)) != 0)
8125       outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
8126     else {
8127       outs() << " initprot ";
8128       outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
8129       outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8130       outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8131     }
8132   } else {
8133     outs() << "  maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
8134     outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
8135   }
8136   outs() << "   nsects " << nsects << "\n";
8137   if (verbose) {
8138     outs() << "    flags";
8139     if (flags == 0)
8140       outs() << " (none)\n";
8141     else {
8142       if (flags & MachO::SG_HIGHVM) {
8143         outs() << " HIGHVM";
8144         flags &= ~MachO::SG_HIGHVM;
8145       }
8146       if (flags & MachO::SG_FVMLIB) {
8147         outs() << " FVMLIB";
8148         flags &= ~MachO::SG_FVMLIB;
8149       }
8150       if (flags & MachO::SG_NORELOC) {
8151         outs() << " NORELOC";
8152         flags &= ~MachO::SG_NORELOC;
8153       }
8154       if (flags & MachO::SG_PROTECTED_VERSION_1) {
8155         outs() << " PROTECTED_VERSION_1";
8156         flags &= ~MachO::SG_PROTECTED_VERSION_1;
8157       }
8158       if (flags)
8159         outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
8160       else
8161         outs() << "\n";
8162     }
8163   } else {
8164     outs() << "    flags " << format("0x%" PRIx32, flags) << "\n";
8165   }
8166 }
8167 
PrintSection(const char * sectname,const char * segname,uint64_t addr,uint64_t size,uint32_t offset,uint32_t align,uint32_t reloff,uint32_t nreloc,uint32_t flags,uint32_t reserved1,uint32_t reserved2,uint32_t cmd,const char * sg_segname,uint32_t filetype,uint32_t object_size,bool verbose)8168 static void PrintSection(const char *sectname, const char *segname,
8169                          uint64_t addr, uint64_t size, uint32_t offset,
8170                          uint32_t align, uint32_t reloff, uint32_t nreloc,
8171                          uint32_t flags, uint32_t reserved1, uint32_t reserved2,
8172                          uint32_t cmd, const char *sg_segname,
8173                          uint32_t filetype, uint32_t object_size,
8174                          bool verbose) {
8175   outs() << "Section\n";
8176   outs() << "  sectname " << format("%.16s\n", sectname);
8177   outs() << "   segname " << format("%.16s", segname);
8178   if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
8179     outs() << " (does not match segment)\n";
8180   else
8181     outs() << "\n";
8182   if (cmd == MachO::LC_SEGMENT_64) {
8183     outs() << "      addr " << format("0x%016" PRIx64, addr) << "\n";
8184     outs() << "      size " << format("0x%016" PRIx64, size);
8185   } else {
8186     outs() << "      addr " << format("0x%08" PRIx64, addr) << "\n";
8187     outs() << "      size " << format("0x%08" PRIx64, size);
8188   }
8189   if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
8190     outs() << " (past end of file)\n";
8191   else
8192     outs() << "\n";
8193   outs() << "    offset " << offset;
8194   if (offset > object_size)
8195     outs() << " (past end of file)\n";
8196   else
8197     outs() << "\n";
8198   uint32_t align_shifted = 1 << align;
8199   outs() << "     align 2^" << align << " (" << align_shifted << ")\n";
8200   outs() << "    reloff " << reloff;
8201   if (reloff > object_size)
8202     outs() << " (past end of file)\n";
8203   else
8204     outs() << "\n";
8205   outs() << "    nreloc " << nreloc;
8206   if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
8207     outs() << " (past end of file)\n";
8208   else
8209     outs() << "\n";
8210   uint32_t section_type = flags & MachO::SECTION_TYPE;
8211   if (verbose) {
8212     outs() << "      type";
8213     if (section_type == MachO::S_REGULAR)
8214       outs() << " S_REGULAR\n";
8215     else if (section_type == MachO::S_ZEROFILL)
8216       outs() << " S_ZEROFILL\n";
8217     else if (section_type == MachO::S_CSTRING_LITERALS)
8218       outs() << " S_CSTRING_LITERALS\n";
8219     else if (section_type == MachO::S_4BYTE_LITERALS)
8220       outs() << " S_4BYTE_LITERALS\n";
8221     else if (section_type == MachO::S_8BYTE_LITERALS)
8222       outs() << " S_8BYTE_LITERALS\n";
8223     else if (section_type == MachO::S_16BYTE_LITERALS)
8224       outs() << " S_16BYTE_LITERALS\n";
8225     else if (section_type == MachO::S_LITERAL_POINTERS)
8226       outs() << " S_LITERAL_POINTERS\n";
8227     else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
8228       outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
8229     else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
8230       outs() << " S_LAZY_SYMBOL_POINTERS\n";
8231     else if (section_type == MachO::S_SYMBOL_STUBS)
8232       outs() << " S_SYMBOL_STUBS\n";
8233     else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
8234       outs() << " S_MOD_INIT_FUNC_POINTERS\n";
8235     else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
8236       outs() << " S_MOD_TERM_FUNC_POINTERS\n";
8237     else if (section_type == MachO::S_COALESCED)
8238       outs() << " S_COALESCED\n";
8239     else if (section_type == MachO::S_INTERPOSING)
8240       outs() << " S_INTERPOSING\n";
8241     else if (section_type == MachO::S_DTRACE_DOF)
8242       outs() << " S_DTRACE_DOF\n";
8243     else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
8244       outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
8245     else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
8246       outs() << " S_THREAD_LOCAL_REGULAR\n";
8247     else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
8248       outs() << " S_THREAD_LOCAL_ZEROFILL\n";
8249     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
8250       outs() << " S_THREAD_LOCAL_VARIABLES\n";
8251     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8252       outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
8253     else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
8254       outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
8255     else
8256       outs() << format("0x%08" PRIx32, section_type) << "\n";
8257     outs() << "attributes";
8258     uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
8259     if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
8260       outs() << " PURE_INSTRUCTIONS";
8261     if (section_attributes & MachO::S_ATTR_NO_TOC)
8262       outs() << " NO_TOC";
8263     if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
8264       outs() << " STRIP_STATIC_SYMS";
8265     if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
8266       outs() << " NO_DEAD_STRIP";
8267     if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
8268       outs() << " LIVE_SUPPORT";
8269     if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
8270       outs() << " SELF_MODIFYING_CODE";
8271     if (section_attributes & MachO::S_ATTR_DEBUG)
8272       outs() << " DEBUG";
8273     if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
8274       outs() << " SOME_INSTRUCTIONS";
8275     if (section_attributes & MachO::S_ATTR_EXT_RELOC)
8276       outs() << " EXT_RELOC";
8277     if (section_attributes & MachO::S_ATTR_LOC_RELOC)
8278       outs() << " LOC_RELOC";
8279     if (section_attributes == 0)
8280       outs() << " (none)";
8281     outs() << "\n";
8282   } else
8283     outs() << "     flags " << format("0x%08" PRIx32, flags) << "\n";
8284   outs() << " reserved1 " << reserved1;
8285   if (section_type == MachO::S_SYMBOL_STUBS ||
8286       section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
8287       section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
8288       section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
8289       section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8290     outs() << " (index into indirect symbol table)\n";
8291   else
8292     outs() << "\n";
8293   outs() << " reserved2 " << reserved2;
8294   if (section_type == MachO::S_SYMBOL_STUBS)
8295     outs() << " (size of stubs)\n";
8296   else
8297     outs() << "\n";
8298 }
8299 
PrintSymtabLoadCommand(MachO::symtab_command st,bool Is64Bit,uint32_t object_size)8300 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
8301                                    uint32_t object_size) {
8302   outs() << "     cmd LC_SYMTAB\n";
8303   outs() << " cmdsize " << st.cmdsize;
8304   if (st.cmdsize != sizeof(struct MachO::symtab_command))
8305     outs() << " Incorrect size\n";
8306   else
8307     outs() << "\n";
8308   outs() << "  symoff " << st.symoff;
8309   if (st.symoff > object_size)
8310     outs() << " (past end of file)\n";
8311   else
8312     outs() << "\n";
8313   outs() << "   nsyms " << st.nsyms;
8314   uint64_t big_size;
8315   if (Is64Bit) {
8316     big_size = st.nsyms;
8317     big_size *= sizeof(struct MachO::nlist_64);
8318     big_size += st.symoff;
8319     if (big_size > object_size)
8320       outs() << " (past end of file)\n";
8321     else
8322       outs() << "\n";
8323   } else {
8324     big_size = st.nsyms;
8325     big_size *= sizeof(struct MachO::nlist);
8326     big_size += st.symoff;
8327     if (big_size > object_size)
8328       outs() << " (past end of file)\n";
8329     else
8330       outs() << "\n";
8331   }
8332   outs() << "  stroff " << st.stroff;
8333   if (st.stroff > object_size)
8334     outs() << " (past end of file)\n";
8335   else
8336     outs() << "\n";
8337   outs() << " strsize " << st.strsize;
8338   big_size = st.stroff;
8339   big_size += st.strsize;
8340   if (big_size > object_size)
8341     outs() << " (past end of file)\n";
8342   else
8343     outs() << "\n";
8344 }
8345 
PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,uint32_t nsyms,uint32_t object_size,bool Is64Bit)8346 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
8347                                      uint32_t nsyms, uint32_t object_size,
8348                                      bool Is64Bit) {
8349   outs() << "            cmd LC_DYSYMTAB\n";
8350   outs() << "        cmdsize " << dyst.cmdsize;
8351   if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
8352     outs() << " Incorrect size\n";
8353   else
8354     outs() << "\n";
8355   outs() << "      ilocalsym " << dyst.ilocalsym;
8356   if (dyst.ilocalsym > nsyms)
8357     outs() << " (greater than the number of symbols)\n";
8358   else
8359     outs() << "\n";
8360   outs() << "      nlocalsym " << dyst.nlocalsym;
8361   uint64_t big_size;
8362   big_size = dyst.ilocalsym;
8363   big_size += dyst.nlocalsym;
8364   if (big_size > nsyms)
8365     outs() << " (past the end of the symbol table)\n";
8366   else
8367     outs() << "\n";
8368   outs() << "     iextdefsym " << dyst.iextdefsym;
8369   if (dyst.iextdefsym > nsyms)
8370     outs() << " (greater than the number of symbols)\n";
8371   else
8372     outs() << "\n";
8373   outs() << "     nextdefsym " << dyst.nextdefsym;
8374   big_size = dyst.iextdefsym;
8375   big_size += dyst.nextdefsym;
8376   if (big_size > nsyms)
8377     outs() << " (past the end of the symbol table)\n";
8378   else
8379     outs() << "\n";
8380   outs() << "      iundefsym " << dyst.iundefsym;
8381   if (dyst.iundefsym > nsyms)
8382     outs() << " (greater than the number of symbols)\n";
8383   else
8384     outs() << "\n";
8385   outs() << "      nundefsym " << dyst.nundefsym;
8386   big_size = dyst.iundefsym;
8387   big_size += dyst.nundefsym;
8388   if (big_size > nsyms)
8389     outs() << " (past the end of the symbol table)\n";
8390   else
8391     outs() << "\n";
8392   outs() << "         tocoff " << dyst.tocoff;
8393   if (dyst.tocoff > object_size)
8394     outs() << " (past end of file)\n";
8395   else
8396     outs() << "\n";
8397   outs() << "           ntoc " << dyst.ntoc;
8398   big_size = dyst.ntoc;
8399   big_size *= sizeof(struct MachO::dylib_table_of_contents);
8400   big_size += dyst.tocoff;
8401   if (big_size > object_size)
8402     outs() << " (past end of file)\n";
8403   else
8404     outs() << "\n";
8405   outs() << "      modtaboff " << dyst.modtaboff;
8406   if (dyst.modtaboff > object_size)
8407     outs() << " (past end of file)\n";
8408   else
8409     outs() << "\n";
8410   outs() << "        nmodtab " << dyst.nmodtab;
8411   uint64_t modtabend;
8412   if (Is64Bit) {
8413     modtabend = dyst.nmodtab;
8414     modtabend *= sizeof(struct MachO::dylib_module_64);
8415     modtabend += dyst.modtaboff;
8416   } else {
8417     modtabend = dyst.nmodtab;
8418     modtabend *= sizeof(struct MachO::dylib_module);
8419     modtabend += dyst.modtaboff;
8420   }
8421   if (modtabend > object_size)
8422     outs() << " (past end of file)\n";
8423   else
8424     outs() << "\n";
8425   outs() << "   extrefsymoff " << dyst.extrefsymoff;
8426   if (dyst.extrefsymoff > object_size)
8427     outs() << " (past end of file)\n";
8428   else
8429     outs() << "\n";
8430   outs() << "    nextrefsyms " << dyst.nextrefsyms;
8431   big_size = dyst.nextrefsyms;
8432   big_size *= sizeof(struct MachO::dylib_reference);
8433   big_size += dyst.extrefsymoff;
8434   if (big_size > object_size)
8435     outs() << " (past end of file)\n";
8436   else
8437     outs() << "\n";
8438   outs() << " indirectsymoff " << dyst.indirectsymoff;
8439   if (dyst.indirectsymoff > object_size)
8440     outs() << " (past end of file)\n";
8441   else
8442     outs() << "\n";
8443   outs() << "  nindirectsyms " << dyst.nindirectsyms;
8444   big_size = dyst.nindirectsyms;
8445   big_size *= sizeof(uint32_t);
8446   big_size += dyst.indirectsymoff;
8447   if (big_size > object_size)
8448     outs() << " (past end of file)\n";
8449   else
8450     outs() << "\n";
8451   outs() << "      extreloff " << dyst.extreloff;
8452   if (dyst.extreloff > object_size)
8453     outs() << " (past end of file)\n";
8454   else
8455     outs() << "\n";
8456   outs() << "        nextrel " << dyst.nextrel;
8457   big_size = dyst.nextrel;
8458   big_size *= sizeof(struct MachO::relocation_info);
8459   big_size += dyst.extreloff;
8460   if (big_size > object_size)
8461     outs() << " (past end of file)\n";
8462   else
8463     outs() << "\n";
8464   outs() << "      locreloff " << dyst.locreloff;
8465   if (dyst.locreloff > object_size)
8466     outs() << " (past end of file)\n";
8467   else
8468     outs() << "\n";
8469   outs() << "        nlocrel " << dyst.nlocrel;
8470   big_size = dyst.nlocrel;
8471   big_size *= sizeof(struct MachO::relocation_info);
8472   big_size += dyst.locreloff;
8473   if (big_size > object_size)
8474     outs() << " (past end of file)\n";
8475   else
8476     outs() << "\n";
8477 }
8478 
PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,uint32_t object_size)8479 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
8480                                      uint32_t object_size) {
8481   if (dc.cmd == MachO::LC_DYLD_INFO)
8482     outs() << "            cmd LC_DYLD_INFO\n";
8483   else
8484     outs() << "            cmd LC_DYLD_INFO_ONLY\n";
8485   outs() << "        cmdsize " << dc.cmdsize;
8486   if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
8487     outs() << " Incorrect size\n";
8488   else
8489     outs() << "\n";
8490   outs() << "     rebase_off " << dc.rebase_off;
8491   if (dc.rebase_off > object_size)
8492     outs() << " (past end of file)\n";
8493   else
8494     outs() << "\n";
8495   outs() << "    rebase_size " << dc.rebase_size;
8496   uint64_t big_size;
8497   big_size = dc.rebase_off;
8498   big_size += dc.rebase_size;
8499   if (big_size > object_size)
8500     outs() << " (past end of file)\n";
8501   else
8502     outs() << "\n";
8503   outs() << "       bind_off " << dc.bind_off;
8504   if (dc.bind_off > object_size)
8505     outs() << " (past end of file)\n";
8506   else
8507     outs() << "\n";
8508   outs() << "      bind_size " << dc.bind_size;
8509   big_size = dc.bind_off;
8510   big_size += dc.bind_size;
8511   if (big_size > object_size)
8512     outs() << " (past end of file)\n";
8513   else
8514     outs() << "\n";
8515   outs() << "  weak_bind_off " << dc.weak_bind_off;
8516   if (dc.weak_bind_off > object_size)
8517     outs() << " (past end of file)\n";
8518   else
8519     outs() << "\n";
8520   outs() << " weak_bind_size " << dc.weak_bind_size;
8521   big_size = dc.weak_bind_off;
8522   big_size += dc.weak_bind_size;
8523   if (big_size > object_size)
8524     outs() << " (past end of file)\n";
8525   else
8526     outs() << "\n";
8527   outs() << "  lazy_bind_off " << dc.lazy_bind_off;
8528   if (dc.lazy_bind_off > object_size)
8529     outs() << " (past end of file)\n";
8530   else
8531     outs() << "\n";
8532   outs() << " lazy_bind_size " << dc.lazy_bind_size;
8533   big_size = dc.lazy_bind_off;
8534   big_size += dc.lazy_bind_size;
8535   if (big_size > object_size)
8536     outs() << " (past end of file)\n";
8537   else
8538     outs() << "\n";
8539   outs() << "     export_off " << dc.export_off;
8540   if (dc.export_off > object_size)
8541     outs() << " (past end of file)\n";
8542   else
8543     outs() << "\n";
8544   outs() << "    export_size " << dc.export_size;
8545   big_size = dc.export_off;
8546   big_size += dc.export_size;
8547   if (big_size > object_size)
8548     outs() << " (past end of file)\n";
8549   else
8550     outs() << "\n";
8551 }
8552 
PrintDyldLoadCommand(MachO::dylinker_command dyld,const char * Ptr)8553 static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
8554                                  const char *Ptr) {
8555   if (dyld.cmd == MachO::LC_ID_DYLINKER)
8556     outs() << "          cmd LC_ID_DYLINKER\n";
8557   else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
8558     outs() << "          cmd LC_LOAD_DYLINKER\n";
8559   else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
8560     outs() << "          cmd LC_DYLD_ENVIRONMENT\n";
8561   else
8562     outs() << "          cmd ?(" << dyld.cmd << ")\n";
8563   outs() << "      cmdsize " << dyld.cmdsize;
8564   if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
8565     outs() << " Incorrect size\n";
8566   else
8567     outs() << "\n";
8568   if (dyld.name >= dyld.cmdsize)
8569     outs() << "         name ?(bad offset " << dyld.name << ")\n";
8570   else {
8571     const char *P = (const char *)(Ptr) + dyld.name;
8572     outs() << "         name " << P << " (offset " << dyld.name << ")\n";
8573   }
8574 }
8575 
PrintUuidLoadCommand(MachO::uuid_command uuid)8576 static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
8577   outs() << "     cmd LC_UUID\n";
8578   outs() << " cmdsize " << uuid.cmdsize;
8579   if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
8580     outs() << " Incorrect size\n";
8581   else
8582     outs() << "\n";
8583   outs() << "    uuid ";
8584   for (int i = 0; i < 16; ++i) {
8585     outs() << format("%02" PRIX32, uuid.uuid[i]);
8586     if (i == 3 || i == 5 || i == 7 || i == 9)
8587       outs() << "-";
8588   }
8589   outs() << "\n";
8590 }
8591 
PrintRpathLoadCommand(MachO::rpath_command rpath,const char * Ptr)8592 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
8593   outs() << "          cmd LC_RPATH\n";
8594   outs() << "      cmdsize " << rpath.cmdsize;
8595   if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
8596     outs() << " Incorrect size\n";
8597   else
8598     outs() << "\n";
8599   if (rpath.path >= rpath.cmdsize)
8600     outs() << "         path ?(bad offset " << rpath.path << ")\n";
8601   else {
8602     const char *P = (const char *)(Ptr) + rpath.path;
8603     outs() << "         path " << P << " (offset " << rpath.path << ")\n";
8604   }
8605 }
8606 
PrintVersionMinLoadCommand(MachO::version_min_command vd)8607 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
8608   StringRef LoadCmdName;
8609   switch (vd.cmd) {
8610   case MachO::LC_VERSION_MIN_MACOSX:
8611     LoadCmdName = "LC_VERSION_MIN_MACOSX";
8612     break;
8613   case MachO::LC_VERSION_MIN_IPHONEOS:
8614     LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
8615     break;
8616   case MachO::LC_VERSION_MIN_TVOS:
8617     LoadCmdName = "LC_VERSION_MIN_TVOS";
8618     break;
8619   case MachO::LC_VERSION_MIN_WATCHOS:
8620     LoadCmdName = "LC_VERSION_MIN_WATCHOS";
8621     break;
8622   default:
8623     llvm_unreachable("Unknown version min load command");
8624   }
8625 
8626   outs() << "      cmd " << LoadCmdName << '\n';
8627   outs() << "  cmdsize " << vd.cmdsize;
8628   if (vd.cmdsize != sizeof(struct MachO::version_min_command))
8629     outs() << " Incorrect size\n";
8630   else
8631     outs() << "\n";
8632   outs() << "  version "
8633          << MachOObjectFile::getVersionMinMajor(vd, false) << "."
8634          << MachOObjectFile::getVersionMinMinor(vd, false);
8635   uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
8636   if (Update != 0)
8637     outs() << "." << Update;
8638   outs() << "\n";
8639   if (vd.sdk == 0)
8640     outs() << "      sdk n/a";
8641   else {
8642     outs() << "      sdk "
8643            << MachOObjectFile::getVersionMinMajor(vd, true) << "."
8644            << MachOObjectFile::getVersionMinMinor(vd, true);
8645   }
8646   Update = MachOObjectFile::getVersionMinUpdate(vd, true);
8647   if (Update != 0)
8648     outs() << "." << Update;
8649   outs() << "\n";
8650 }
8651 
PrintNoteLoadCommand(MachO::note_command Nt)8652 static void PrintNoteLoadCommand(MachO::note_command Nt) {
8653   outs() << "       cmd LC_NOTE\n";
8654   outs() << "   cmdsize " << Nt.cmdsize;
8655   if (Nt.cmdsize != sizeof(struct MachO::note_command))
8656     outs() << " Incorrect size\n";
8657   else
8658     outs() << "\n";
8659   const char *d = Nt.data_owner;
8660   outs() << "data_owner " << format("%.16s\n", d);
8661   outs() << "    offset " << Nt.offset << "\n";
8662   outs() << "      size " << Nt.size << "\n";
8663 }
8664 
PrintBuildToolVersion(MachO::build_tool_version bv)8665 static void PrintBuildToolVersion(MachO::build_tool_version bv) {
8666   outs() << "      tool " << MachOObjectFile::getBuildTool(bv.tool) << "\n";
8667   outs() << "   version " << MachOObjectFile::getVersionString(bv.version)
8668          << "\n";
8669 }
8670 
PrintBuildVersionLoadCommand(const MachOObjectFile * obj,MachO::build_version_command bd)8671 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj,
8672                                          MachO::build_version_command bd) {
8673   outs() << "       cmd LC_BUILD_VERSION\n";
8674   outs() << "   cmdsize " << bd.cmdsize;
8675   if (bd.cmdsize !=
8676       sizeof(struct MachO::build_version_command) +
8677           bd.ntools * sizeof(struct MachO::build_tool_version))
8678     outs() << " Incorrect size\n";
8679   else
8680     outs() << "\n";
8681   outs() << "  platform " << MachOObjectFile::getBuildPlatform(bd.platform)
8682          << "\n";
8683   if (bd.sdk)
8684     outs() << "       sdk " << MachOObjectFile::getVersionString(bd.sdk)
8685            << "\n";
8686   else
8687     outs() << "       sdk n/a\n";
8688   outs() << "     minos " << MachOObjectFile::getVersionString(bd.minos)
8689          << "\n";
8690   outs() << "    ntools " << bd.ntools << "\n";
8691   for (unsigned i = 0; i < bd.ntools; ++i) {
8692     MachO::build_tool_version bv = obj->getBuildToolVersion(i);
8693     PrintBuildToolVersion(bv);
8694   }
8695 }
8696 
PrintSourceVersionCommand(MachO::source_version_command sd)8697 static void PrintSourceVersionCommand(MachO::source_version_command sd) {
8698   outs() << "      cmd LC_SOURCE_VERSION\n";
8699   outs() << "  cmdsize " << sd.cmdsize;
8700   if (sd.cmdsize != sizeof(struct MachO::source_version_command))
8701     outs() << " Incorrect size\n";
8702   else
8703     outs() << "\n";
8704   uint64_t a = (sd.version >> 40) & 0xffffff;
8705   uint64_t b = (sd.version >> 30) & 0x3ff;
8706   uint64_t c = (sd.version >> 20) & 0x3ff;
8707   uint64_t d = (sd.version >> 10) & 0x3ff;
8708   uint64_t e = sd.version & 0x3ff;
8709   outs() << "  version " << a << "." << b;
8710   if (e != 0)
8711     outs() << "." << c << "." << d << "." << e;
8712   else if (d != 0)
8713     outs() << "." << c << "." << d;
8714   else if (c != 0)
8715     outs() << "." << c;
8716   outs() << "\n";
8717 }
8718 
PrintEntryPointCommand(MachO::entry_point_command ep)8719 static void PrintEntryPointCommand(MachO::entry_point_command ep) {
8720   outs() << "       cmd LC_MAIN\n";
8721   outs() << "   cmdsize " << ep.cmdsize;
8722   if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
8723     outs() << " Incorrect size\n";
8724   else
8725     outs() << "\n";
8726   outs() << "  entryoff " << ep.entryoff << "\n";
8727   outs() << " stacksize " << ep.stacksize << "\n";
8728 }
8729 
PrintEncryptionInfoCommand(MachO::encryption_info_command ec,uint32_t object_size)8730 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
8731                                        uint32_t object_size) {
8732   outs() << "          cmd LC_ENCRYPTION_INFO\n";
8733   outs() << "      cmdsize " << ec.cmdsize;
8734   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
8735     outs() << " Incorrect size\n";
8736   else
8737     outs() << "\n";
8738   outs() << "     cryptoff " << ec.cryptoff;
8739   if (ec.cryptoff > object_size)
8740     outs() << " (past end of file)\n";
8741   else
8742     outs() << "\n";
8743   outs() << "    cryptsize " << ec.cryptsize;
8744   if (ec.cryptsize > object_size)
8745     outs() << " (past end of file)\n";
8746   else
8747     outs() << "\n";
8748   outs() << "      cryptid " << ec.cryptid << "\n";
8749 }
8750 
PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,uint32_t object_size)8751 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
8752                                          uint32_t object_size) {
8753   outs() << "          cmd LC_ENCRYPTION_INFO_64\n";
8754   outs() << "      cmdsize " << ec.cmdsize;
8755   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
8756     outs() << " Incorrect size\n";
8757   else
8758     outs() << "\n";
8759   outs() << "     cryptoff " << ec.cryptoff;
8760   if (ec.cryptoff > object_size)
8761     outs() << " (past end of file)\n";
8762   else
8763     outs() << "\n";
8764   outs() << "    cryptsize " << ec.cryptsize;
8765   if (ec.cryptsize > object_size)
8766     outs() << " (past end of file)\n";
8767   else
8768     outs() << "\n";
8769   outs() << "      cryptid " << ec.cryptid << "\n";
8770   outs() << "          pad " << ec.pad << "\n";
8771 }
8772 
PrintLinkerOptionCommand(MachO::linker_option_command lo,const char * Ptr)8773 static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
8774                                      const char *Ptr) {
8775   outs() << "     cmd LC_LINKER_OPTION\n";
8776   outs() << " cmdsize " << lo.cmdsize;
8777   if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
8778     outs() << " Incorrect size\n";
8779   else
8780     outs() << "\n";
8781   outs() << "   count " << lo.count << "\n";
8782   const char *string = Ptr + sizeof(struct MachO::linker_option_command);
8783   uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
8784   uint32_t i = 0;
8785   while (left > 0) {
8786     while (*string == '\0' && left > 0) {
8787       string++;
8788       left--;
8789     }
8790     if (left > 0) {
8791       i++;
8792       outs() << "  string #" << i << " " << format("%.*s\n", left, string);
8793       uint32_t NullPos = StringRef(string, left).find('\0');
8794       uint32_t len = std::min(NullPos, left) + 1;
8795       string += len;
8796       left -= len;
8797     }
8798   }
8799   if (lo.count != i)
8800     outs() << "   count " << lo.count << " does not match number of strings "
8801            << i << "\n";
8802 }
8803 
PrintSubFrameworkCommand(MachO::sub_framework_command sub,const char * Ptr)8804 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
8805                                      const char *Ptr) {
8806   outs() << "          cmd LC_SUB_FRAMEWORK\n";
8807   outs() << "      cmdsize " << sub.cmdsize;
8808   if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
8809     outs() << " Incorrect size\n";
8810   else
8811     outs() << "\n";
8812   if (sub.umbrella < sub.cmdsize) {
8813     const char *P = Ptr + sub.umbrella;
8814     outs() << "     umbrella " << P << " (offset " << sub.umbrella << ")\n";
8815   } else {
8816     outs() << "     umbrella ?(bad offset " << sub.umbrella << ")\n";
8817   }
8818 }
8819 
PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,const char * Ptr)8820 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
8821                                     const char *Ptr) {
8822   outs() << "          cmd LC_SUB_UMBRELLA\n";
8823   outs() << "      cmdsize " << sub.cmdsize;
8824   if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
8825     outs() << " Incorrect size\n";
8826   else
8827     outs() << "\n";
8828   if (sub.sub_umbrella < sub.cmdsize) {
8829     const char *P = Ptr + sub.sub_umbrella;
8830     outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
8831   } else {
8832     outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
8833   }
8834 }
8835 
PrintSubLibraryCommand(MachO::sub_library_command sub,const char * Ptr)8836 static void PrintSubLibraryCommand(MachO::sub_library_command sub,
8837                                    const char *Ptr) {
8838   outs() << "          cmd LC_SUB_LIBRARY\n";
8839   outs() << "      cmdsize " << sub.cmdsize;
8840   if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
8841     outs() << " Incorrect size\n";
8842   else
8843     outs() << "\n";
8844   if (sub.sub_library < sub.cmdsize) {
8845     const char *P = Ptr + sub.sub_library;
8846     outs() << "  sub_library " << P << " (offset " << sub.sub_library << ")\n";
8847   } else {
8848     outs() << "  sub_library ?(bad offset " << sub.sub_library << ")\n";
8849   }
8850 }
8851 
PrintSubClientCommand(MachO::sub_client_command sub,const char * Ptr)8852 static void PrintSubClientCommand(MachO::sub_client_command sub,
8853                                   const char *Ptr) {
8854   outs() << "          cmd LC_SUB_CLIENT\n";
8855   outs() << "      cmdsize " << sub.cmdsize;
8856   if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
8857     outs() << " Incorrect size\n";
8858   else
8859     outs() << "\n";
8860   if (sub.client < sub.cmdsize) {
8861     const char *P = Ptr + sub.client;
8862     outs() << "       client " << P << " (offset " << sub.client << ")\n";
8863   } else {
8864     outs() << "       client ?(bad offset " << sub.client << ")\n";
8865   }
8866 }
8867 
PrintRoutinesCommand(MachO::routines_command r)8868 static void PrintRoutinesCommand(MachO::routines_command r) {
8869   outs() << "          cmd LC_ROUTINES\n";
8870   outs() << "      cmdsize " << r.cmdsize;
8871   if (r.cmdsize != sizeof(struct MachO::routines_command))
8872     outs() << " Incorrect size\n";
8873   else
8874     outs() << "\n";
8875   outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
8876   outs() << "  init_module " << r.init_module << "\n";
8877   outs() << "    reserved1 " << r.reserved1 << "\n";
8878   outs() << "    reserved2 " << r.reserved2 << "\n";
8879   outs() << "    reserved3 " << r.reserved3 << "\n";
8880   outs() << "    reserved4 " << r.reserved4 << "\n";
8881   outs() << "    reserved5 " << r.reserved5 << "\n";
8882   outs() << "    reserved6 " << r.reserved6 << "\n";
8883 }
8884 
PrintRoutinesCommand64(MachO::routines_command_64 r)8885 static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
8886   outs() << "          cmd LC_ROUTINES_64\n";
8887   outs() << "      cmdsize " << r.cmdsize;
8888   if (r.cmdsize != sizeof(struct MachO::routines_command_64))
8889     outs() << " Incorrect size\n";
8890   else
8891     outs() << "\n";
8892   outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
8893   outs() << "  init_module " << r.init_module << "\n";
8894   outs() << "    reserved1 " << r.reserved1 << "\n";
8895   outs() << "    reserved2 " << r.reserved2 << "\n";
8896   outs() << "    reserved3 " << r.reserved3 << "\n";
8897   outs() << "    reserved4 " << r.reserved4 << "\n";
8898   outs() << "    reserved5 " << r.reserved5 << "\n";
8899   outs() << "    reserved6 " << r.reserved6 << "\n";
8900 }
8901 
Print_x86_thread_state32_t(MachO::x86_thread_state32_t & cpu32)8902 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) {
8903   outs() << "\t    eax " << format("0x%08" PRIx32, cpu32.eax);
8904   outs() << " ebx    " << format("0x%08" PRIx32, cpu32.ebx);
8905   outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx);
8906   outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n";
8907   outs() << "\t    edi " << format("0x%08" PRIx32, cpu32.edi);
8908   outs() << " esi    " << format("0x%08" PRIx32, cpu32.esi);
8909   outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp);
8910   outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n";
8911   outs() << "\t    ss  " << format("0x%08" PRIx32, cpu32.ss);
8912   outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags);
8913   outs() << " eip " << format("0x%08" PRIx32, cpu32.eip);
8914   outs() << " cs  " << format("0x%08" PRIx32, cpu32.cs) << "\n";
8915   outs() << "\t    ds  " << format("0x%08" PRIx32, cpu32.ds);
8916   outs() << " es     " << format("0x%08" PRIx32, cpu32.es);
8917   outs() << " fs  " << format("0x%08" PRIx32, cpu32.fs);
8918   outs() << " gs  " << format("0x%08" PRIx32, cpu32.gs) << "\n";
8919 }
8920 
Print_x86_thread_state64_t(MachO::x86_thread_state64_t & cpu64)8921 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
8922   outs() << "   rax  " << format("0x%016" PRIx64, cpu64.rax);
8923   outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
8924   outs() << " rcx  " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
8925   outs() << "   rdx  " << format("0x%016" PRIx64, cpu64.rdx);
8926   outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
8927   outs() << " rsi  " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
8928   outs() << "   rbp  " << format("0x%016" PRIx64, cpu64.rbp);
8929   outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
8930   outs() << " r8   " << format("0x%016" PRIx64, cpu64.r8) << "\n";
8931   outs() << "    r9  " << format("0x%016" PRIx64, cpu64.r9);
8932   outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
8933   outs() << " r11  " << format("0x%016" PRIx64, cpu64.r11) << "\n";
8934   outs() << "   r12  " << format("0x%016" PRIx64, cpu64.r12);
8935   outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
8936   outs() << " r14  " << format("0x%016" PRIx64, cpu64.r14) << "\n";
8937   outs() << "   r15  " << format("0x%016" PRIx64, cpu64.r15);
8938   outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
8939   outs() << "rflags  " << format("0x%016" PRIx64, cpu64.rflags);
8940   outs() << " cs  " << format("0x%016" PRIx64, cpu64.cs);
8941   outs() << " fs   " << format("0x%016" PRIx64, cpu64.fs) << "\n";
8942   outs() << "    gs  " << format("0x%016" PRIx64, cpu64.gs) << "\n";
8943 }
8944 
Print_mmst_reg(MachO::mmst_reg_t & r)8945 static void Print_mmst_reg(MachO::mmst_reg_t &r) {
8946   uint32_t f;
8947   outs() << "\t      mmst_reg  ";
8948   for (f = 0; f < 10; f++)
8949     outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
8950   outs() << "\n";
8951   outs() << "\t      mmst_rsrv ";
8952   for (f = 0; f < 6; f++)
8953     outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
8954   outs() << "\n";
8955 }
8956 
Print_xmm_reg(MachO::xmm_reg_t & r)8957 static void Print_xmm_reg(MachO::xmm_reg_t &r) {
8958   uint32_t f;
8959   outs() << "\t      xmm_reg ";
8960   for (f = 0; f < 16; f++)
8961     outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
8962   outs() << "\n";
8963 }
8964 
Print_x86_float_state_t(MachO::x86_float_state64_t & fpu)8965 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
8966   outs() << "\t    fpu_reserved[0] " << fpu.fpu_reserved[0];
8967   outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
8968   outs() << "\t    control: invalid " << fpu.fpu_fcw.invalid;
8969   outs() << " denorm " << fpu.fpu_fcw.denorm;
8970   outs() << " zdiv " << fpu.fpu_fcw.zdiv;
8971   outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
8972   outs() << " undfl " << fpu.fpu_fcw.undfl;
8973   outs() << " precis " << fpu.fpu_fcw.precis << "\n";
8974   outs() << "\t\t     pc ";
8975   if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
8976     outs() << "FP_PREC_24B ";
8977   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
8978     outs() << "FP_PREC_53B ";
8979   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
8980     outs() << "FP_PREC_64B ";
8981   else
8982     outs() << fpu.fpu_fcw.pc << " ";
8983   outs() << "rc ";
8984   if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
8985     outs() << "FP_RND_NEAR ";
8986   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
8987     outs() << "FP_RND_DOWN ";
8988   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
8989     outs() << "FP_RND_UP ";
8990   else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
8991     outs() << "FP_CHOP ";
8992   outs() << "\n";
8993   outs() << "\t    status: invalid " << fpu.fpu_fsw.invalid;
8994   outs() << " denorm " << fpu.fpu_fsw.denorm;
8995   outs() << " zdiv " << fpu.fpu_fsw.zdiv;
8996   outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
8997   outs() << " undfl " << fpu.fpu_fsw.undfl;
8998   outs() << " precis " << fpu.fpu_fsw.precis;
8999   outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
9000   outs() << "\t            errsumm " << fpu.fpu_fsw.errsumm;
9001   outs() << " c0 " << fpu.fpu_fsw.c0;
9002   outs() << " c1 " << fpu.fpu_fsw.c1;
9003   outs() << " c2 " << fpu.fpu_fsw.c2;
9004   outs() << " tos " << fpu.fpu_fsw.tos;
9005   outs() << " c3 " << fpu.fpu_fsw.c3;
9006   outs() << " busy " << fpu.fpu_fsw.busy << "\n";
9007   outs() << "\t    fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
9008   outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
9009   outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
9010   outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
9011   outs() << "\t    fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
9012   outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
9013   outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
9014   outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
9015   outs() << "\t    fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
9016   outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
9017   outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
9018   outs() << "\n";
9019   outs() << "\t    fpu_stmm0:\n";
9020   Print_mmst_reg(fpu.fpu_stmm0);
9021   outs() << "\t    fpu_stmm1:\n";
9022   Print_mmst_reg(fpu.fpu_stmm1);
9023   outs() << "\t    fpu_stmm2:\n";
9024   Print_mmst_reg(fpu.fpu_stmm2);
9025   outs() << "\t    fpu_stmm3:\n";
9026   Print_mmst_reg(fpu.fpu_stmm3);
9027   outs() << "\t    fpu_stmm4:\n";
9028   Print_mmst_reg(fpu.fpu_stmm4);
9029   outs() << "\t    fpu_stmm5:\n";
9030   Print_mmst_reg(fpu.fpu_stmm5);
9031   outs() << "\t    fpu_stmm6:\n";
9032   Print_mmst_reg(fpu.fpu_stmm6);
9033   outs() << "\t    fpu_stmm7:\n";
9034   Print_mmst_reg(fpu.fpu_stmm7);
9035   outs() << "\t    fpu_xmm0:\n";
9036   Print_xmm_reg(fpu.fpu_xmm0);
9037   outs() << "\t    fpu_xmm1:\n";
9038   Print_xmm_reg(fpu.fpu_xmm1);
9039   outs() << "\t    fpu_xmm2:\n";
9040   Print_xmm_reg(fpu.fpu_xmm2);
9041   outs() << "\t    fpu_xmm3:\n";
9042   Print_xmm_reg(fpu.fpu_xmm3);
9043   outs() << "\t    fpu_xmm4:\n";
9044   Print_xmm_reg(fpu.fpu_xmm4);
9045   outs() << "\t    fpu_xmm5:\n";
9046   Print_xmm_reg(fpu.fpu_xmm5);
9047   outs() << "\t    fpu_xmm6:\n";
9048   Print_xmm_reg(fpu.fpu_xmm6);
9049   outs() << "\t    fpu_xmm7:\n";
9050   Print_xmm_reg(fpu.fpu_xmm7);
9051   outs() << "\t    fpu_xmm8:\n";
9052   Print_xmm_reg(fpu.fpu_xmm8);
9053   outs() << "\t    fpu_xmm9:\n";
9054   Print_xmm_reg(fpu.fpu_xmm9);
9055   outs() << "\t    fpu_xmm10:\n";
9056   Print_xmm_reg(fpu.fpu_xmm10);
9057   outs() << "\t    fpu_xmm11:\n";
9058   Print_xmm_reg(fpu.fpu_xmm11);
9059   outs() << "\t    fpu_xmm12:\n";
9060   Print_xmm_reg(fpu.fpu_xmm12);
9061   outs() << "\t    fpu_xmm13:\n";
9062   Print_xmm_reg(fpu.fpu_xmm13);
9063   outs() << "\t    fpu_xmm14:\n";
9064   Print_xmm_reg(fpu.fpu_xmm14);
9065   outs() << "\t    fpu_xmm15:\n";
9066   Print_xmm_reg(fpu.fpu_xmm15);
9067   outs() << "\t    fpu_rsrv4:\n";
9068   for (uint32_t f = 0; f < 6; f++) {
9069     outs() << "\t            ";
9070     for (uint32_t g = 0; g < 16; g++)
9071       outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
9072     outs() << "\n";
9073   }
9074   outs() << "\t    fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
9075   outs() << "\n";
9076 }
9077 
Print_x86_exception_state_t(MachO::x86_exception_state64_t & exc64)9078 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
9079   outs() << "\t    trapno " << format("0x%08" PRIx32, exc64.trapno);
9080   outs() << " err " << format("0x%08" PRIx32, exc64.err);
9081   outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
9082 }
9083 
Print_arm_thread_state32_t(MachO::arm_thread_state32_t & cpu32)9084 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
9085   outs() << "\t    r0  " << format("0x%08" PRIx32, cpu32.r[0]);
9086   outs() << " r1     "   << format("0x%08" PRIx32, cpu32.r[1]);
9087   outs() << " r2  "      << format("0x%08" PRIx32, cpu32.r[2]);
9088   outs() << " r3  "      << format("0x%08" PRIx32, cpu32.r[3]) << "\n";
9089   outs() << "\t    r4  " << format("0x%08" PRIx32, cpu32.r[4]);
9090   outs() << " r5     "   << format("0x%08" PRIx32, cpu32.r[5]);
9091   outs() << " r6  "      << format("0x%08" PRIx32, cpu32.r[6]);
9092   outs() << " r7  "      << format("0x%08" PRIx32, cpu32.r[7]) << "\n";
9093   outs() << "\t    r8  " << format("0x%08" PRIx32, cpu32.r[8]);
9094   outs() << " r9     "   << format("0x%08" PRIx32, cpu32.r[9]);
9095   outs() << " r10 "      << format("0x%08" PRIx32, cpu32.r[10]);
9096   outs() << " r11 "      << format("0x%08" PRIx32, cpu32.r[11]) << "\n";
9097   outs() << "\t    r12 " << format("0x%08" PRIx32, cpu32.r[12]);
9098   outs() << " sp     "   << format("0x%08" PRIx32, cpu32.sp);
9099   outs() << " lr  "      << format("0x%08" PRIx32, cpu32.lr);
9100   outs() << " pc  "      << format("0x%08" PRIx32, cpu32.pc) << "\n";
9101   outs() << "\t   cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n";
9102 }
9103 
Print_arm_thread_state64_t(MachO::arm_thread_state64_t & cpu64)9104 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
9105   outs() << "\t    x0  " << format("0x%016" PRIx64, cpu64.x[0]);
9106   outs() << " x1  "      << format("0x%016" PRIx64, cpu64.x[1]);
9107   outs() << " x2  "      << format("0x%016" PRIx64, cpu64.x[2]) << "\n";
9108   outs() << "\t    x3  " << format("0x%016" PRIx64, cpu64.x[3]);
9109   outs() << " x4  "      << format("0x%016" PRIx64, cpu64.x[4]);
9110   outs() << " x5  "      << format("0x%016" PRIx64, cpu64.x[5]) << "\n";
9111   outs() << "\t    x6  " << format("0x%016" PRIx64, cpu64.x[6]);
9112   outs() << " x7  "      << format("0x%016" PRIx64, cpu64.x[7]);
9113   outs() << " x8  "      << format("0x%016" PRIx64, cpu64.x[8]) << "\n";
9114   outs() << "\t    x9  " << format("0x%016" PRIx64, cpu64.x[9]);
9115   outs() << " x10 "      << format("0x%016" PRIx64, cpu64.x[10]);
9116   outs() << " x11 "      << format("0x%016" PRIx64, cpu64.x[11]) << "\n";
9117   outs() << "\t    x12 " << format("0x%016" PRIx64, cpu64.x[12]);
9118   outs() << " x13 "      << format("0x%016" PRIx64, cpu64.x[13]);
9119   outs() << " x14 "      << format("0x%016" PRIx64, cpu64.x[14]) << "\n";
9120   outs() << "\t    x15 " << format("0x%016" PRIx64, cpu64.x[15]);
9121   outs() << " x16 "      << format("0x%016" PRIx64, cpu64.x[16]);
9122   outs() << " x17 "      << format("0x%016" PRIx64, cpu64.x[17]) << "\n";
9123   outs() << "\t    x18 " << format("0x%016" PRIx64, cpu64.x[18]);
9124   outs() << " x19 "      << format("0x%016" PRIx64, cpu64.x[19]);
9125   outs() << " x20 "      << format("0x%016" PRIx64, cpu64.x[20]) << "\n";
9126   outs() << "\t    x21 " << format("0x%016" PRIx64, cpu64.x[21]);
9127   outs() << " x22 "      << format("0x%016" PRIx64, cpu64.x[22]);
9128   outs() << " x23 "      << format("0x%016" PRIx64, cpu64.x[23]) << "\n";
9129   outs() << "\t    x24 " << format("0x%016" PRIx64, cpu64.x[24]);
9130   outs() << " x25 "      << format("0x%016" PRIx64, cpu64.x[25]);
9131   outs() << " x26 "      << format("0x%016" PRIx64, cpu64.x[26]) << "\n";
9132   outs() << "\t    x27 " << format("0x%016" PRIx64, cpu64.x[27]);
9133   outs() << " x28 "      << format("0x%016" PRIx64, cpu64.x[28]);
9134   outs() << "  fp "      << format("0x%016" PRIx64, cpu64.fp) << "\n";
9135   outs() << "\t     lr " << format("0x%016" PRIx64, cpu64.lr);
9136   outs() << " sp  "      << format("0x%016" PRIx64, cpu64.sp);
9137   outs() << "  pc "      << format("0x%016" PRIx64, cpu64.pc) << "\n";
9138   outs() << "\t   cpsr " << format("0x%08"  PRIx32, cpu64.cpsr) << "\n";
9139 }
9140 
PrintThreadCommand(MachO::thread_command t,const char * Ptr,bool isLittleEndian,uint32_t cputype)9141 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
9142                                bool isLittleEndian, uint32_t cputype) {
9143   if (t.cmd == MachO::LC_THREAD)
9144     outs() << "        cmd LC_THREAD\n";
9145   else if (t.cmd == MachO::LC_UNIXTHREAD)
9146     outs() << "        cmd LC_UNIXTHREAD\n";
9147   else
9148     outs() << "        cmd " << t.cmd << " (unknown)\n";
9149   outs() << "    cmdsize " << t.cmdsize;
9150   if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
9151     outs() << " Incorrect size\n";
9152   else
9153     outs() << "\n";
9154 
9155   const char *begin = Ptr + sizeof(struct MachO::thread_command);
9156   const char *end = Ptr + t.cmdsize;
9157   uint32_t flavor, count, left;
9158   if (cputype == MachO::CPU_TYPE_I386) {
9159     while (begin < end) {
9160       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9161         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9162         begin += sizeof(uint32_t);
9163       } else {
9164         flavor = 0;
9165         begin = end;
9166       }
9167       if (isLittleEndian != sys::IsLittleEndianHost)
9168         sys::swapByteOrder(flavor);
9169       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9170         memcpy((char *)&count, begin, sizeof(uint32_t));
9171         begin += sizeof(uint32_t);
9172       } else {
9173         count = 0;
9174         begin = end;
9175       }
9176       if (isLittleEndian != sys::IsLittleEndianHost)
9177         sys::swapByteOrder(count);
9178       if (flavor == MachO::x86_THREAD_STATE32) {
9179         outs() << "     flavor i386_THREAD_STATE\n";
9180         if (count == MachO::x86_THREAD_STATE32_COUNT)
9181           outs() << "      count i386_THREAD_STATE_COUNT\n";
9182         else
9183           outs() << "      count " << count
9184                  << " (not x86_THREAD_STATE32_COUNT)\n";
9185         MachO::x86_thread_state32_t cpu32;
9186         left = end - begin;
9187         if (left >= sizeof(MachO::x86_thread_state32_t)) {
9188           memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t));
9189           begin += sizeof(MachO::x86_thread_state32_t);
9190         } else {
9191           memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t));
9192           memcpy(&cpu32, begin, left);
9193           begin += left;
9194         }
9195         if (isLittleEndian != sys::IsLittleEndianHost)
9196           swapStruct(cpu32);
9197         Print_x86_thread_state32_t(cpu32);
9198       } else if (flavor == MachO::x86_THREAD_STATE) {
9199         outs() << "     flavor x86_THREAD_STATE\n";
9200         if (count == MachO::x86_THREAD_STATE_COUNT)
9201           outs() << "      count x86_THREAD_STATE_COUNT\n";
9202         else
9203           outs() << "      count " << count
9204                  << " (not x86_THREAD_STATE_COUNT)\n";
9205         struct MachO::x86_thread_state_t ts;
9206         left = end - begin;
9207         if (left >= sizeof(MachO::x86_thread_state_t)) {
9208           memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9209           begin += sizeof(MachO::x86_thread_state_t);
9210         } else {
9211           memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9212           memcpy(&ts, begin, left);
9213           begin += left;
9214         }
9215         if (isLittleEndian != sys::IsLittleEndianHost)
9216           swapStruct(ts);
9217         if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) {
9218           outs() << "\t    tsh.flavor x86_THREAD_STATE32 ";
9219           if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT)
9220             outs() << "tsh.count x86_THREAD_STATE32_COUNT\n";
9221           else
9222             outs() << "tsh.count " << ts.tsh.count
9223                    << " (not x86_THREAD_STATE32_COUNT\n";
9224           Print_x86_thread_state32_t(ts.uts.ts32);
9225         } else {
9226           outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9227                  << ts.tsh.count << "\n";
9228         }
9229       } else {
9230         outs() << "     flavor " << flavor << " (unknown)\n";
9231         outs() << "      count " << count << "\n";
9232         outs() << "      state (unknown)\n";
9233         begin += count * sizeof(uint32_t);
9234       }
9235     }
9236   } else if (cputype == MachO::CPU_TYPE_X86_64) {
9237     while (begin < end) {
9238       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9239         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9240         begin += sizeof(uint32_t);
9241       } else {
9242         flavor = 0;
9243         begin = end;
9244       }
9245       if (isLittleEndian != sys::IsLittleEndianHost)
9246         sys::swapByteOrder(flavor);
9247       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9248         memcpy((char *)&count, begin, sizeof(uint32_t));
9249         begin += sizeof(uint32_t);
9250       } else {
9251         count = 0;
9252         begin = end;
9253       }
9254       if (isLittleEndian != sys::IsLittleEndianHost)
9255         sys::swapByteOrder(count);
9256       if (flavor == MachO::x86_THREAD_STATE64) {
9257         outs() << "     flavor x86_THREAD_STATE64\n";
9258         if (count == MachO::x86_THREAD_STATE64_COUNT)
9259           outs() << "      count x86_THREAD_STATE64_COUNT\n";
9260         else
9261           outs() << "      count " << count
9262                  << " (not x86_THREAD_STATE64_COUNT)\n";
9263         MachO::x86_thread_state64_t cpu64;
9264         left = end - begin;
9265         if (left >= sizeof(MachO::x86_thread_state64_t)) {
9266           memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
9267           begin += sizeof(MachO::x86_thread_state64_t);
9268         } else {
9269           memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
9270           memcpy(&cpu64, begin, left);
9271           begin += left;
9272         }
9273         if (isLittleEndian != sys::IsLittleEndianHost)
9274           swapStruct(cpu64);
9275         Print_x86_thread_state64_t(cpu64);
9276       } else if (flavor == MachO::x86_THREAD_STATE) {
9277         outs() << "     flavor x86_THREAD_STATE\n";
9278         if (count == MachO::x86_THREAD_STATE_COUNT)
9279           outs() << "      count x86_THREAD_STATE_COUNT\n";
9280         else
9281           outs() << "      count " << count
9282                  << " (not x86_THREAD_STATE_COUNT)\n";
9283         struct MachO::x86_thread_state_t ts;
9284         left = end - begin;
9285         if (left >= sizeof(MachO::x86_thread_state_t)) {
9286           memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9287           begin += sizeof(MachO::x86_thread_state_t);
9288         } else {
9289           memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9290           memcpy(&ts, begin, left);
9291           begin += left;
9292         }
9293         if (isLittleEndian != sys::IsLittleEndianHost)
9294           swapStruct(ts);
9295         if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
9296           outs() << "\t    tsh.flavor x86_THREAD_STATE64 ";
9297           if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
9298             outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
9299           else
9300             outs() << "tsh.count " << ts.tsh.count
9301                    << " (not x86_THREAD_STATE64_COUNT\n";
9302           Print_x86_thread_state64_t(ts.uts.ts64);
9303         } else {
9304           outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9305                  << ts.tsh.count << "\n";
9306         }
9307       } else if (flavor == MachO::x86_FLOAT_STATE) {
9308         outs() << "     flavor x86_FLOAT_STATE\n";
9309         if (count == MachO::x86_FLOAT_STATE_COUNT)
9310           outs() << "      count x86_FLOAT_STATE_COUNT\n";
9311         else
9312           outs() << "      count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
9313         struct MachO::x86_float_state_t fs;
9314         left = end - begin;
9315         if (left >= sizeof(MachO::x86_float_state_t)) {
9316           memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
9317           begin += sizeof(MachO::x86_float_state_t);
9318         } else {
9319           memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
9320           memcpy(&fs, begin, left);
9321           begin += left;
9322         }
9323         if (isLittleEndian != sys::IsLittleEndianHost)
9324           swapStruct(fs);
9325         if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
9326           outs() << "\t    fsh.flavor x86_FLOAT_STATE64 ";
9327           if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
9328             outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
9329           else
9330             outs() << "fsh.count " << fs.fsh.count
9331                    << " (not x86_FLOAT_STATE64_COUNT\n";
9332           Print_x86_float_state_t(fs.ufs.fs64);
9333         } else {
9334           outs() << "\t    fsh.flavor " << fs.fsh.flavor << "  fsh.count "
9335                  << fs.fsh.count << "\n";
9336         }
9337       } else if (flavor == MachO::x86_EXCEPTION_STATE) {
9338         outs() << "     flavor x86_EXCEPTION_STATE\n";
9339         if (count == MachO::x86_EXCEPTION_STATE_COUNT)
9340           outs() << "      count x86_EXCEPTION_STATE_COUNT\n";
9341         else
9342           outs() << "      count " << count
9343                  << " (not x86_EXCEPTION_STATE_COUNT)\n";
9344         struct MachO::x86_exception_state_t es;
9345         left = end - begin;
9346         if (left >= sizeof(MachO::x86_exception_state_t)) {
9347           memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
9348           begin += sizeof(MachO::x86_exception_state_t);
9349         } else {
9350           memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
9351           memcpy(&es, begin, left);
9352           begin += left;
9353         }
9354         if (isLittleEndian != sys::IsLittleEndianHost)
9355           swapStruct(es);
9356         if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
9357           outs() << "\t    esh.flavor x86_EXCEPTION_STATE64\n";
9358           if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
9359             outs() << "\t    esh.count x86_EXCEPTION_STATE64_COUNT\n";
9360           else
9361             outs() << "\t    esh.count " << es.esh.count
9362                    << " (not x86_EXCEPTION_STATE64_COUNT\n";
9363           Print_x86_exception_state_t(es.ues.es64);
9364         } else {
9365           outs() << "\t    esh.flavor " << es.esh.flavor << "  esh.count "
9366                  << es.esh.count << "\n";
9367         }
9368       } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
9369         outs() << "     flavor x86_EXCEPTION_STATE64\n";
9370         if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
9371           outs() << "      count x86_EXCEPTION_STATE64_COUNT\n";
9372         else
9373           outs() << "      count " << count
9374                  << " (not x86_EXCEPTION_STATE64_COUNT)\n";
9375         struct MachO::x86_exception_state64_t es64;
9376         left = end - begin;
9377         if (left >= sizeof(MachO::x86_exception_state64_t)) {
9378           memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
9379           begin += sizeof(MachO::x86_exception_state64_t);
9380         } else {
9381           memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
9382           memcpy(&es64, begin, left);
9383           begin += left;
9384         }
9385         if (isLittleEndian != sys::IsLittleEndianHost)
9386           swapStruct(es64);
9387         Print_x86_exception_state_t(es64);
9388       } else {
9389         outs() << "     flavor " << flavor << " (unknown)\n";
9390         outs() << "      count " << count << "\n";
9391         outs() << "      state (unknown)\n";
9392         begin += count * sizeof(uint32_t);
9393       }
9394     }
9395   } else if (cputype == MachO::CPU_TYPE_ARM) {
9396     while (begin < end) {
9397       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9398         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9399         begin += sizeof(uint32_t);
9400       } else {
9401         flavor = 0;
9402         begin = end;
9403       }
9404       if (isLittleEndian != sys::IsLittleEndianHost)
9405         sys::swapByteOrder(flavor);
9406       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9407         memcpy((char *)&count, begin, sizeof(uint32_t));
9408         begin += sizeof(uint32_t);
9409       } else {
9410         count = 0;
9411         begin = end;
9412       }
9413       if (isLittleEndian != sys::IsLittleEndianHost)
9414         sys::swapByteOrder(count);
9415       if (flavor == MachO::ARM_THREAD_STATE) {
9416         outs() << "     flavor ARM_THREAD_STATE\n";
9417         if (count == MachO::ARM_THREAD_STATE_COUNT)
9418           outs() << "      count ARM_THREAD_STATE_COUNT\n";
9419         else
9420           outs() << "      count " << count
9421                  << " (not ARM_THREAD_STATE_COUNT)\n";
9422         MachO::arm_thread_state32_t cpu32;
9423         left = end - begin;
9424         if (left >= sizeof(MachO::arm_thread_state32_t)) {
9425           memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t));
9426           begin += sizeof(MachO::arm_thread_state32_t);
9427         } else {
9428           memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t));
9429           memcpy(&cpu32, begin, left);
9430           begin += left;
9431         }
9432         if (isLittleEndian != sys::IsLittleEndianHost)
9433           swapStruct(cpu32);
9434         Print_arm_thread_state32_t(cpu32);
9435       } else {
9436         outs() << "     flavor " << flavor << " (unknown)\n";
9437         outs() << "      count " << count << "\n";
9438         outs() << "      state (unknown)\n";
9439         begin += count * sizeof(uint32_t);
9440       }
9441     }
9442   } else if (cputype == MachO::CPU_TYPE_ARM64) {
9443     while (begin < end) {
9444       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9445         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9446         begin += sizeof(uint32_t);
9447       } else {
9448         flavor = 0;
9449         begin = end;
9450       }
9451       if (isLittleEndian != sys::IsLittleEndianHost)
9452         sys::swapByteOrder(flavor);
9453       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9454         memcpy((char *)&count, begin, sizeof(uint32_t));
9455         begin += sizeof(uint32_t);
9456       } else {
9457         count = 0;
9458         begin = end;
9459       }
9460       if (isLittleEndian != sys::IsLittleEndianHost)
9461         sys::swapByteOrder(count);
9462       if (flavor == MachO::ARM_THREAD_STATE64) {
9463         outs() << "     flavor ARM_THREAD_STATE64\n";
9464         if (count == MachO::ARM_THREAD_STATE64_COUNT)
9465           outs() << "      count ARM_THREAD_STATE64_COUNT\n";
9466         else
9467           outs() << "      count " << count
9468                  << " (not ARM_THREAD_STATE64_COUNT)\n";
9469         MachO::arm_thread_state64_t cpu64;
9470         left = end - begin;
9471         if (left >= sizeof(MachO::arm_thread_state64_t)) {
9472           memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
9473           begin += sizeof(MachO::arm_thread_state64_t);
9474         } else {
9475           memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
9476           memcpy(&cpu64, begin, left);
9477           begin += left;
9478         }
9479         if (isLittleEndian != sys::IsLittleEndianHost)
9480           swapStruct(cpu64);
9481         Print_arm_thread_state64_t(cpu64);
9482       } else {
9483         outs() << "     flavor " << flavor << " (unknown)\n";
9484         outs() << "      count " << count << "\n";
9485         outs() << "      state (unknown)\n";
9486         begin += count * sizeof(uint32_t);
9487       }
9488     }
9489   } else {
9490     while (begin < end) {
9491       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9492         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9493         begin += sizeof(uint32_t);
9494       } else {
9495         flavor = 0;
9496         begin = end;
9497       }
9498       if (isLittleEndian != sys::IsLittleEndianHost)
9499         sys::swapByteOrder(flavor);
9500       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9501         memcpy((char *)&count, begin, sizeof(uint32_t));
9502         begin += sizeof(uint32_t);
9503       } else {
9504         count = 0;
9505         begin = end;
9506       }
9507       if (isLittleEndian != sys::IsLittleEndianHost)
9508         sys::swapByteOrder(count);
9509       outs() << "     flavor " << flavor << "\n";
9510       outs() << "      count " << count << "\n";
9511       outs() << "      state (Unknown cputype/cpusubtype)\n";
9512       begin += count * sizeof(uint32_t);
9513     }
9514   }
9515 }
9516 
PrintDylibCommand(MachO::dylib_command dl,const char * Ptr)9517 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
9518   if (dl.cmd == MachO::LC_ID_DYLIB)
9519     outs() << "          cmd LC_ID_DYLIB\n";
9520   else if (dl.cmd == MachO::LC_LOAD_DYLIB)
9521     outs() << "          cmd LC_LOAD_DYLIB\n";
9522   else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
9523     outs() << "          cmd LC_LOAD_WEAK_DYLIB\n";
9524   else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
9525     outs() << "          cmd LC_REEXPORT_DYLIB\n";
9526   else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
9527     outs() << "          cmd LC_LAZY_LOAD_DYLIB\n";
9528   else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
9529     outs() << "          cmd LC_LOAD_UPWARD_DYLIB\n";
9530   else
9531     outs() << "          cmd " << dl.cmd << " (unknown)\n";
9532   outs() << "      cmdsize " << dl.cmdsize;
9533   if (dl.cmdsize < sizeof(struct MachO::dylib_command))
9534     outs() << " Incorrect size\n";
9535   else
9536     outs() << "\n";
9537   if (dl.dylib.name < dl.cmdsize) {
9538     const char *P = (const char *)(Ptr) + dl.dylib.name;
9539     outs() << "         name " << P << " (offset " << dl.dylib.name << ")\n";
9540   } else {
9541     outs() << "         name ?(bad offset " << dl.dylib.name << ")\n";
9542   }
9543   outs() << "   time stamp " << dl.dylib.timestamp << " ";
9544   time_t t = dl.dylib.timestamp;
9545   outs() << ctime(&t);
9546   outs() << "      current version ";
9547   if (dl.dylib.current_version == 0xffffffff)
9548     outs() << "n/a\n";
9549   else
9550     outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
9551            << ((dl.dylib.current_version >> 8) & 0xff) << "."
9552            << (dl.dylib.current_version & 0xff) << "\n";
9553   outs() << "compatibility version ";
9554   if (dl.dylib.compatibility_version == 0xffffffff)
9555     outs() << "n/a\n";
9556   else
9557     outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
9558            << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
9559            << (dl.dylib.compatibility_version & 0xff) << "\n";
9560 }
9561 
PrintLinkEditDataCommand(MachO::linkedit_data_command ld,uint32_t object_size)9562 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
9563                                      uint32_t object_size) {
9564   if (ld.cmd == MachO::LC_CODE_SIGNATURE)
9565     outs() << "      cmd LC_CODE_SIGNATURE\n";
9566   else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
9567     outs() << "      cmd LC_SEGMENT_SPLIT_INFO\n";
9568   else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
9569     outs() << "      cmd LC_FUNCTION_STARTS\n";
9570   else if (ld.cmd == MachO::LC_DATA_IN_CODE)
9571     outs() << "      cmd LC_DATA_IN_CODE\n";
9572   else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
9573     outs() << "      cmd LC_DYLIB_CODE_SIGN_DRS\n";
9574   else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
9575     outs() << "      cmd LC_LINKER_OPTIMIZATION_HINT\n";
9576   else
9577     outs() << "      cmd " << ld.cmd << " (?)\n";
9578   outs() << "  cmdsize " << ld.cmdsize;
9579   if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
9580     outs() << " Incorrect size\n";
9581   else
9582     outs() << "\n";
9583   outs() << "  dataoff " << ld.dataoff;
9584   if (ld.dataoff > object_size)
9585     outs() << " (past end of file)\n";
9586   else
9587     outs() << "\n";
9588   outs() << " datasize " << ld.datasize;
9589   uint64_t big_size = ld.dataoff;
9590   big_size += ld.datasize;
9591   if (big_size > object_size)
9592     outs() << " (past end of file)\n";
9593   else
9594     outs() << "\n";
9595 }
9596 
PrintLoadCommands(const MachOObjectFile * Obj,uint32_t filetype,uint32_t cputype,bool verbose)9597 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
9598                               uint32_t cputype, bool verbose) {
9599   StringRef Buf = Obj->getData();
9600   unsigned Index = 0;
9601   for (const auto &Command : Obj->load_commands()) {
9602     outs() << "Load command " << Index++ << "\n";
9603     if (Command.C.cmd == MachO::LC_SEGMENT) {
9604       MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
9605       const char *sg_segname = SLC.segname;
9606       PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
9607                           SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
9608                           SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
9609                           verbose);
9610       for (unsigned j = 0; j < SLC.nsects; j++) {
9611         MachO::section S = Obj->getSection(Command, j);
9612         PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
9613                      S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
9614                      SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
9615       }
9616     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
9617       MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
9618       const char *sg_segname = SLC_64.segname;
9619       PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
9620                           SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
9621                           SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
9622                           SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
9623       for (unsigned j = 0; j < SLC_64.nsects; j++) {
9624         MachO::section_64 S_64 = Obj->getSection64(Command, j);
9625         PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
9626                      S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
9627                      S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
9628                      sg_segname, filetype, Buf.size(), verbose);
9629       }
9630     } else if (Command.C.cmd == MachO::LC_SYMTAB) {
9631       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
9632       PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
9633     } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
9634       MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
9635       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
9636       PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
9637                                Obj->is64Bit());
9638     } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
9639                Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
9640       MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
9641       PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
9642     } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
9643                Command.C.cmd == MachO::LC_ID_DYLINKER ||
9644                Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
9645       MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
9646       PrintDyldLoadCommand(Dyld, Command.Ptr);
9647     } else if (Command.C.cmd == MachO::LC_UUID) {
9648       MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
9649       PrintUuidLoadCommand(Uuid);
9650     } else if (Command.C.cmd == MachO::LC_RPATH) {
9651       MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
9652       PrintRpathLoadCommand(Rpath, Command.Ptr);
9653     } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
9654                Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
9655                Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
9656                Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
9657       MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
9658       PrintVersionMinLoadCommand(Vd);
9659     } else if (Command.C.cmd == MachO::LC_NOTE) {
9660       MachO::note_command Nt = Obj->getNoteLoadCommand(Command);
9661       PrintNoteLoadCommand(Nt);
9662     } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) {
9663       MachO::build_version_command Bv =
9664           Obj->getBuildVersionLoadCommand(Command);
9665       PrintBuildVersionLoadCommand(Obj, Bv);
9666     } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
9667       MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
9668       PrintSourceVersionCommand(Sd);
9669     } else if (Command.C.cmd == MachO::LC_MAIN) {
9670       MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
9671       PrintEntryPointCommand(Ep);
9672     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
9673       MachO::encryption_info_command Ei =
9674           Obj->getEncryptionInfoCommand(Command);
9675       PrintEncryptionInfoCommand(Ei, Buf.size());
9676     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
9677       MachO::encryption_info_command_64 Ei =
9678           Obj->getEncryptionInfoCommand64(Command);
9679       PrintEncryptionInfoCommand64(Ei, Buf.size());
9680     } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
9681       MachO::linker_option_command Lo =
9682           Obj->getLinkerOptionLoadCommand(Command);
9683       PrintLinkerOptionCommand(Lo, Command.Ptr);
9684     } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
9685       MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
9686       PrintSubFrameworkCommand(Sf, Command.Ptr);
9687     } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
9688       MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
9689       PrintSubUmbrellaCommand(Sf, Command.Ptr);
9690     } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
9691       MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
9692       PrintSubLibraryCommand(Sl, Command.Ptr);
9693     } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
9694       MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
9695       PrintSubClientCommand(Sc, Command.Ptr);
9696     } else if (Command.C.cmd == MachO::LC_ROUTINES) {
9697       MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
9698       PrintRoutinesCommand(Rc);
9699     } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
9700       MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
9701       PrintRoutinesCommand64(Rc);
9702     } else if (Command.C.cmd == MachO::LC_THREAD ||
9703                Command.C.cmd == MachO::LC_UNIXTHREAD) {
9704       MachO::thread_command Tc = Obj->getThreadCommand(Command);
9705       PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
9706     } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
9707                Command.C.cmd == MachO::LC_ID_DYLIB ||
9708                Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
9709                Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
9710                Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
9711                Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
9712       MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
9713       PrintDylibCommand(Dl, Command.Ptr);
9714     } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
9715                Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
9716                Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
9717                Command.C.cmd == MachO::LC_DATA_IN_CODE ||
9718                Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
9719                Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
9720       MachO::linkedit_data_command Ld =
9721           Obj->getLinkeditDataLoadCommand(Command);
9722       PrintLinkEditDataCommand(Ld, Buf.size());
9723     } else {
9724       outs() << "      cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
9725              << ")\n";
9726       outs() << "  cmdsize " << Command.C.cmdsize << "\n";
9727       // TODO: get and print the raw bytes of the load command.
9728     }
9729     // TODO: print all the other kinds of load commands.
9730   }
9731 }
9732 
PrintMachHeader(const MachOObjectFile * Obj,bool verbose)9733 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
9734   if (Obj->is64Bit()) {
9735     MachO::mach_header_64 H_64;
9736     H_64 = Obj->getHeader64();
9737     PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
9738                     H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
9739   } else {
9740     MachO::mach_header H;
9741     H = Obj->getHeader();
9742     PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
9743                     H.sizeofcmds, H.flags, verbose);
9744   }
9745 }
9746 
printMachOFileHeader(const object::ObjectFile * Obj)9747 void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
9748   const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
9749   PrintMachHeader(file, !NonVerbose);
9750 }
9751 
printMachOLoadCommands(const object::ObjectFile * Obj)9752 void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) {
9753   const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
9754   uint32_t filetype = 0;
9755   uint32_t cputype = 0;
9756   if (file->is64Bit()) {
9757     MachO::mach_header_64 H_64;
9758     H_64 = file->getHeader64();
9759     filetype = H_64.filetype;
9760     cputype = H_64.cputype;
9761   } else {
9762     MachO::mach_header H;
9763     H = file->getHeader();
9764     filetype = H.filetype;
9765     cputype = H.cputype;
9766   }
9767   PrintLoadCommands(file, filetype, cputype, !NonVerbose);
9768 }
9769 
9770 //===----------------------------------------------------------------------===//
9771 // export trie dumping
9772 //===----------------------------------------------------------------------===//
9773 
printMachOExportsTrie(const object::MachOObjectFile * Obj)9774 void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) {
9775   uint64_t BaseSegmentAddress = 0;
9776   for (const auto &Command : Obj->load_commands()) {
9777     if (Command.C.cmd == MachO::LC_SEGMENT) {
9778       MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command);
9779       if (Seg.fileoff == 0 && Seg.filesize != 0) {
9780         BaseSegmentAddress = Seg.vmaddr;
9781         break;
9782       }
9783     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
9784       MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command);
9785       if (Seg.fileoff == 0 && Seg.filesize != 0) {
9786         BaseSegmentAddress = Seg.vmaddr;
9787         break;
9788       }
9789     }
9790   }
9791   Error Err = Error::success();
9792   for (const llvm::object::ExportEntry &Entry : Obj->exports(Err)) {
9793     uint64_t Flags = Entry.flags();
9794     bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
9795     bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
9796     bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
9797                         MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
9798     bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
9799                 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
9800     bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
9801     if (ReExport)
9802       outs() << "[re-export] ";
9803     else
9804       outs() << format("0x%08llX  ",
9805                        Entry.address() + BaseSegmentAddress);
9806     outs() << Entry.name();
9807     if (WeakDef || ThreadLocal || Resolver || Abs) {
9808       bool NeedsComma = false;
9809       outs() << " [";
9810       if (WeakDef) {
9811         outs() << "weak_def";
9812         NeedsComma = true;
9813       }
9814       if (ThreadLocal) {
9815         if (NeedsComma)
9816           outs() << ", ";
9817         outs() << "per-thread";
9818         NeedsComma = true;
9819       }
9820       if (Abs) {
9821         if (NeedsComma)
9822           outs() << ", ";
9823         outs() << "absolute";
9824         NeedsComma = true;
9825       }
9826       if (Resolver) {
9827         if (NeedsComma)
9828           outs() << ", ";
9829         outs() << format("resolver=0x%08llX", Entry.other());
9830         NeedsComma = true;
9831       }
9832       outs() << "]";
9833     }
9834     if (ReExport) {
9835       StringRef DylibName = "unknown";
9836       int Ordinal = Entry.other() - 1;
9837       Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
9838       if (Entry.otherName().empty())
9839         outs() << " (from " << DylibName << ")";
9840       else
9841         outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
9842     }
9843     outs() << "\n";
9844   }
9845   if (Err)
9846     report_error(Obj->getFileName(), std::move(Err));
9847 }
9848 
9849 //===----------------------------------------------------------------------===//
9850 // rebase table dumping
9851 //===----------------------------------------------------------------------===//
9852 
printMachORebaseTable(object::MachOObjectFile * Obj)9853 void llvm::printMachORebaseTable(object::MachOObjectFile *Obj) {
9854   outs() << "segment  section            address     type\n";
9855   Error Err = Error::success();
9856   for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) {
9857     StringRef SegmentName = Entry.segmentName();
9858     StringRef SectionName = Entry.sectionName();
9859     uint64_t Address = Entry.address();
9860 
9861     // Table lines look like: __DATA  __nl_symbol_ptr  0x0000F00C  pointer
9862     outs() << format("%-8s %-18s 0x%08" PRIX64 "  %s\n",
9863                      SegmentName.str().c_str(), SectionName.str().c_str(),
9864                      Address, Entry.typeName().str().c_str());
9865   }
9866   if (Err)
9867     report_error(Obj->getFileName(), std::move(Err));
9868 }
9869 
ordinalName(const object::MachOObjectFile * Obj,int Ordinal)9870 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
9871   StringRef DylibName;
9872   switch (Ordinal) {
9873   case MachO::BIND_SPECIAL_DYLIB_SELF:
9874     return "this-image";
9875   case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
9876     return "main-executable";
9877   case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
9878     return "flat-namespace";
9879   default:
9880     if (Ordinal > 0) {
9881       std::error_code EC =
9882           Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
9883       if (EC)
9884         return "<<bad library ordinal>>";
9885       return DylibName;
9886     }
9887   }
9888   return "<<unknown special ordinal>>";
9889 }
9890 
9891 //===----------------------------------------------------------------------===//
9892 // bind table dumping
9893 //===----------------------------------------------------------------------===//
9894 
printMachOBindTable(object::MachOObjectFile * Obj)9895 void llvm::printMachOBindTable(object::MachOObjectFile *Obj) {
9896   // Build table of sections so names can used in final output.
9897   outs() << "segment  section            address    type       "
9898             "addend dylib            symbol\n";
9899   Error Err = Error::success();
9900   for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) {
9901     StringRef SegmentName = Entry.segmentName();
9902     StringRef SectionName = Entry.sectionName();
9903     uint64_t Address = Entry.address();
9904 
9905     // Table lines look like:
9906     //  __DATA  __got  0x00012010    pointer   0 libSystem ___stack_chk_guard
9907     StringRef Attr;
9908     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
9909       Attr = " (weak_import)";
9910     outs() << left_justify(SegmentName, 8) << " "
9911            << left_justify(SectionName, 18) << " "
9912            << format_hex(Address, 10, true) << " "
9913            << left_justify(Entry.typeName(), 8) << " "
9914            << format_decimal(Entry.addend(), 8) << " "
9915            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
9916            << Entry.symbolName() << Attr << "\n";
9917   }
9918   if (Err)
9919     report_error(Obj->getFileName(), std::move(Err));
9920 }
9921 
9922 //===----------------------------------------------------------------------===//
9923 // lazy bind table dumping
9924 //===----------------------------------------------------------------------===//
9925 
printMachOLazyBindTable(object::MachOObjectFile * Obj)9926 void llvm::printMachOLazyBindTable(object::MachOObjectFile *Obj) {
9927   outs() << "segment  section            address     "
9928             "dylib            symbol\n";
9929   Error Err = Error::success();
9930   for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) {
9931     StringRef SegmentName = Entry.segmentName();
9932     StringRef SectionName = Entry.sectionName();
9933     uint64_t Address = Entry.address();
9934 
9935     // Table lines look like:
9936     //  __DATA  __got  0x00012010 libSystem ___stack_chk_guard
9937     outs() << left_justify(SegmentName, 8) << " "
9938            << left_justify(SectionName, 18) << " "
9939            << format_hex(Address, 10, true) << " "
9940            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
9941            << Entry.symbolName() << "\n";
9942   }
9943   if (Err)
9944     report_error(Obj->getFileName(), std::move(Err));
9945 }
9946 
9947 //===----------------------------------------------------------------------===//
9948 // weak bind table dumping
9949 //===----------------------------------------------------------------------===//
9950 
printMachOWeakBindTable(object::MachOObjectFile * Obj)9951 void llvm::printMachOWeakBindTable(object::MachOObjectFile *Obj) {
9952   outs() << "segment  section            address     "
9953             "type       addend   symbol\n";
9954   Error Err = Error::success();
9955   for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) {
9956     // Strong symbols don't have a location to update.
9957     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
9958       outs() << "                                        strong              "
9959              << Entry.symbolName() << "\n";
9960       continue;
9961     }
9962     StringRef SegmentName = Entry.segmentName();
9963     StringRef SectionName = Entry.sectionName();
9964     uint64_t Address = Entry.address();
9965 
9966     // Table lines look like:
9967     // __DATA  __data  0x00001000  pointer    0   _foo
9968     outs() << left_justify(SegmentName, 8) << " "
9969            << left_justify(SectionName, 18) << " "
9970            << format_hex(Address, 10, true) << " "
9971            << left_justify(Entry.typeName(), 8) << " "
9972            << format_decimal(Entry.addend(), 8) << "   " << Entry.symbolName()
9973            << "\n";
9974   }
9975   if (Err)
9976     report_error(Obj->getFileName(), std::move(Err));
9977 }
9978 
9979 // get_dyld_bind_info_symbolname() is used for disassembly and passed an
9980 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind
9981 // information for that address. If the address is found its binding symbol
9982 // name is returned.  If not nullptr is returned.
get_dyld_bind_info_symbolname(uint64_t ReferenceValue,struct DisassembleInfo * info)9983 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
9984                                                  struct DisassembleInfo *info) {
9985   if (info->bindtable == nullptr) {
9986     info->bindtable = llvm::make_unique<SymbolAddressMap>();
9987     Error Err = Error::success();
9988     for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) {
9989       uint64_t Address = Entry.address();
9990       StringRef name = Entry.symbolName();
9991       if (!name.empty())
9992         (*info->bindtable)[Address] = name;
9993     }
9994     if (Err)
9995       report_error(info->O->getFileName(), std::move(Err));
9996   }
9997   auto name = info->bindtable->lookup(ReferenceValue);
9998   return !name.empty() ? name.data() : nullptr;
9999 }
10000 
10001