xref: /llvm-project/llvm/tools/llvm-objdump/MachODump.cpp (revision 92412c106f5275b4b385f7c2d882008181de2854)
1 //===-- MachODump.cpp - Object file dumping utility for llvm --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the MachO-specific dumper for llvm-objdump.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "MachODump.h"
14 
15 #include "ObjdumpOptID.h"
16 #include "llvm-objdump.h"
17 #include "llvm-c/Disassembler.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/BinaryFormat/MachO.h"
21 #include "llvm/Config/config.h"
22 #include "llvm/DebugInfo/DIContext.h"
23 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
24 #include "llvm/Demangle/Demangle.h"
25 #include "llvm/MC/MCAsmInfo.h"
26 #include "llvm/MC/MCContext.h"
27 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
28 #include "llvm/MC/MCInst.h"
29 #include "llvm/MC/MCInstPrinter.h"
30 #include "llvm/MC/MCInstrDesc.h"
31 #include "llvm/MC/MCInstrInfo.h"
32 #include "llvm/MC/MCRegisterInfo.h"
33 #include "llvm/MC/MCSubtargetInfo.h"
34 #include "llvm/MC/MCTargetOptions.h"
35 #include "llvm/MC/TargetRegistry.h"
36 #include "llvm/Object/MachO.h"
37 #include "llvm/Object/MachOUniversal.h"
38 #include "llvm/Option/ArgList.h"
39 #include "llvm/Support/Casting.h"
40 #include "llvm/Support/Debug.h"
41 #include "llvm/Support/Endian.h"
42 #include "llvm/Support/Format.h"
43 #include "llvm/Support/FormattedStream.h"
44 #include "llvm/Support/GraphWriter.h"
45 #include "llvm/Support/LEB128.h"
46 #include "llvm/Support/MemoryBuffer.h"
47 #include "llvm/Support/TargetSelect.h"
48 #include "llvm/Support/ToolOutputFile.h"
49 #include "llvm/Support/WithColor.h"
50 #include "llvm/Support/raw_ostream.h"
51 #include "llvm/TargetParser/Triple.h"
52 #include <algorithm>
53 #include <cstring>
54 #include <system_error>
55 
56 using namespace llvm;
57 using namespace llvm::object;
58 using namespace llvm::objdump;
59 
60 bool objdump::FirstPrivateHeader;
61 bool objdump::ExportsTrie;
62 bool objdump::Rebase;
63 bool objdump::Rpaths;
64 bool objdump::Bind;
65 bool objdump::LazyBind;
66 bool objdump::WeakBind;
67 static bool UseDbg;
68 static std::string DSYMFile;
69 bool objdump::FullLeadingAddr;
70 bool objdump::LeadingHeaders;
71 bool objdump::UniversalHeaders;
72 static bool ArchiveMemberOffsets;
73 bool objdump::IndirectSymbols;
74 bool objdump::DataInCode;
75 FunctionStartsMode objdump::FunctionStartsType =
76     objdump::FunctionStartsMode::None;
77 bool objdump::LinkOptHints;
78 bool objdump::InfoPlist;
79 bool objdump::ChainedFixups;
80 bool objdump::DyldInfo;
81 bool objdump::DylibsUsed;
82 bool objdump::DylibId;
83 bool objdump::Verbose;
84 bool objdump::ObjcMetaData;
85 std::string objdump::DisSymName;
86 bool objdump::SymbolicOperands;
87 static std::vector<std::string> ArchFlags;
88 
89 static bool ArchAll = false;
90 static std::string ThumbTripleName;
91 
92 static StringRef ordinalName(const object::MachOObjectFile *, int);
93 
94 void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) {
95   FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header);
96   ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie);
97   Rebase = InputArgs.hasArg(OBJDUMP_rebase);
98   Rpaths = InputArgs.hasArg(OBJDUMP_rpaths);
99   Bind = InputArgs.hasArg(OBJDUMP_bind);
100   LazyBind = InputArgs.hasArg(OBJDUMP_lazy_bind);
101   WeakBind = InputArgs.hasArg(OBJDUMP_weak_bind);
102   UseDbg = InputArgs.hasArg(OBJDUMP_g);
103   DSYMFile = InputArgs.getLastArgValue(OBJDUMP_dsym_EQ).str();
104   FullLeadingAddr = InputArgs.hasArg(OBJDUMP_full_leading_addr);
105   LeadingHeaders = !InputArgs.hasArg(OBJDUMP_no_leading_headers);
106   UniversalHeaders = InputArgs.hasArg(OBJDUMP_universal_headers);
107   ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets);
108   IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols);
109   DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code);
110   if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_function_starts_EQ)) {
111     FunctionStartsType = StringSwitch<FunctionStartsMode>(A->getValue())
112                              .Case("addrs", FunctionStartsMode::Addrs)
113                              .Case("names", FunctionStartsMode::Names)
114                              .Case("both", FunctionStartsMode::Both)
115                              .Default(FunctionStartsMode::None);
116     if (FunctionStartsType == FunctionStartsMode::None)
117       invalidArgValue(A);
118   }
119   LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints);
120   InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist);
121   ChainedFixups = InputArgs.hasArg(OBJDUMP_chained_fixups);
122   DyldInfo = InputArgs.hasArg(OBJDUMP_dyld_info);
123   DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used);
124   DylibId = InputArgs.hasArg(OBJDUMP_dylib_id);
125   Verbose = !InputArgs.hasArg(OBJDUMP_non_verbose);
126   ObjcMetaData = InputArgs.hasArg(OBJDUMP_objc_meta_data);
127   DisSymName = InputArgs.getLastArgValue(OBJDUMP_dis_symname).str();
128   SymbolicOperands = !InputArgs.hasArg(OBJDUMP_no_symbolic_operands);
129   ArchFlags = InputArgs.getAllArgValues(OBJDUMP_arch_EQ);
130 }
131 
132 static const Target *GetTarget(const MachOObjectFile *MachOObj,
133                                const char **McpuDefault,
134                                const Target **ThumbTarget) {
135   // Figure out the target triple.
136   Triple TT(TripleName);
137   if (TripleName.empty()) {
138     TT = MachOObj->getArchTriple(McpuDefault);
139     TripleName = TT.str();
140   }
141 
142   if (TT.getArch() == Triple::arm) {
143     // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
144     // that support ARM are also capable of Thumb mode.
145     Triple ThumbTriple = TT;
146     std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
147     ThumbTriple.setArchName(ThumbName);
148     ThumbTripleName = ThumbTriple.str();
149   }
150 
151   // Get the target specific parser.
152   std::string Error;
153   const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
154   if (TheTarget && ThumbTripleName.empty())
155     return TheTarget;
156 
157   *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
158   if (*ThumbTarget)
159     return TheTarget;
160 
161   WithColor::error(errs(), "llvm-objdump") << "unable to get target for '";
162   if (!TheTarget)
163     errs() << TripleName;
164   else
165     errs() << ThumbTripleName;
166   errs() << "', see --version and --triple.\n";
167   return nullptr;
168 }
169 
170 namespace {
171 struct SymbolSorter {
172   bool operator()(const SymbolRef &A, const SymbolRef &B) {
173     Expected<SymbolRef::Type> ATypeOrErr = A.getType();
174     if (!ATypeOrErr)
175       reportError(ATypeOrErr.takeError(), A.getObject()->getFileName());
176     SymbolRef::Type AType = *ATypeOrErr;
177     Expected<SymbolRef::Type> BTypeOrErr = B.getType();
178     if (!BTypeOrErr)
179       reportError(BTypeOrErr.takeError(), B.getObject()->getFileName());
180     SymbolRef::Type BType = *BTypeOrErr;
181     uint64_t AAddr =
182         (AType != SymbolRef::ST_Function) ? 0 : cantFail(A.getValue());
183     uint64_t BAddr =
184         (BType != SymbolRef::ST_Function) ? 0 : cantFail(B.getValue());
185     return AAddr < BAddr;
186   }
187 };
188 
189 class MachODumper : public Dumper {
190   const object::MachOObjectFile &Obj;
191 
192 public:
193   MachODumper(const object::MachOObjectFile &O) : Dumper(O), Obj(O) {}
194   void printPrivateHeaders() override;
195 };
196 } // namespace
197 
198 std::unique_ptr<Dumper>
199 objdump::createMachODumper(const object::MachOObjectFile &Obj) {
200   return std::make_unique<MachODumper>(Obj);
201 }
202 
203 // Types for the storted data in code table that is built before disassembly
204 // and the predicate function to sort them.
205 typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
206 typedef std::vector<DiceTableEntry> DiceTable;
207 typedef DiceTable::iterator dice_table_iterator;
208 
209 // This is used to search for a data in code table entry for the PC being
210 // disassembled.  The j parameter has the PC in j.first.  A single data in code
211 // table entry can cover many bytes for each of its Kind's.  So if the offset,
212 // aka the i.first value, of the data in code table entry plus its Length
213 // covers the PC being searched for this will return true.  If not it will
214 // return false.
215 static bool compareDiceTableEntries(const DiceTableEntry &i,
216                                     const DiceTableEntry &j) {
217   uint16_t Length;
218   i.second.getLength(Length);
219 
220   return j.first >= i.first && j.first < i.first + Length;
221 }
222 
223 static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
224                                unsigned short Kind) {
225   uint32_t Value, Size = 1;
226 
227   switch (Kind) {
228   default:
229   case MachO::DICE_KIND_DATA:
230     if (Length >= 4) {
231       if (ShowRawInsn)
232         dumpBytes(ArrayRef(bytes, 4), outs());
233       Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
234       outs() << "\t.long " << Value;
235       Size = 4;
236     } else if (Length >= 2) {
237       if (ShowRawInsn)
238         dumpBytes(ArrayRef(bytes, 2), outs());
239       Value = bytes[1] << 8 | bytes[0];
240       outs() << "\t.short " << Value;
241       Size = 2;
242     } else {
243       if (ShowRawInsn)
244         dumpBytes(ArrayRef(bytes, 2), outs());
245       Value = bytes[0];
246       outs() << "\t.byte " << Value;
247       Size = 1;
248     }
249     if (Kind == MachO::DICE_KIND_DATA)
250       outs() << "\t@ KIND_DATA\n";
251     else
252       outs() << "\t@ data in code kind = " << Kind << "\n";
253     break;
254   case MachO::DICE_KIND_JUMP_TABLE8:
255     if (ShowRawInsn)
256       dumpBytes(ArrayRef(bytes, 1), outs());
257     Value = bytes[0];
258     outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
259     Size = 1;
260     break;
261   case MachO::DICE_KIND_JUMP_TABLE16:
262     if (ShowRawInsn)
263       dumpBytes(ArrayRef(bytes, 2), outs());
264     Value = bytes[1] << 8 | bytes[0];
265     outs() << "\t.short " << format("%5u", Value & 0xffff)
266            << "\t@ KIND_JUMP_TABLE16\n";
267     Size = 2;
268     break;
269   case MachO::DICE_KIND_JUMP_TABLE32:
270   case MachO::DICE_KIND_ABS_JUMP_TABLE32:
271     if (ShowRawInsn)
272       dumpBytes(ArrayRef(bytes, 4), outs());
273     Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
274     outs() << "\t.long " << Value;
275     if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
276       outs() << "\t@ KIND_JUMP_TABLE32\n";
277     else
278       outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
279     Size = 4;
280     break;
281   }
282   return Size;
283 }
284 
285 static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
286                                   std::vector<SectionRef> &Sections,
287                                   std::vector<SymbolRef> &Symbols,
288                                   SmallVectorImpl<uint64_t> &FoundFns,
289                                   uint64_t &BaseSegmentAddress) {
290   const StringRef FileName = MachOObj->getFileName();
291   for (const SymbolRef &Symbol : MachOObj->symbols()) {
292     StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
293     if (!SymName.starts_with("ltmp"))
294       Symbols.push_back(Symbol);
295   }
296 
297   append_range(Sections, MachOObj->sections());
298 
299   bool BaseSegmentAddressSet = false;
300   for (const auto &Command : MachOObj->load_commands()) {
301     if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
302       // We found a function starts segment, parse the addresses for later
303       // consumption.
304       MachO::linkedit_data_command LLC =
305           MachOObj->getLinkeditDataLoadCommand(Command);
306 
307       MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
308     } else if (Command.C.cmd == MachO::LC_SEGMENT) {
309       MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
310       StringRef SegName = SLC.segname;
311       if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
312         BaseSegmentAddressSet = true;
313         BaseSegmentAddress = SLC.vmaddr;
314       }
315     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
316       MachO::segment_command_64 SLC = MachOObj->getSegment64LoadCommand(Command);
317       StringRef SegName = SLC.segname;
318       if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
319         BaseSegmentAddressSet = true;
320         BaseSegmentAddress = SLC.vmaddr;
321       }
322     }
323   }
324 }
325 
326 static bool DumpAndSkipDataInCode(uint64_t PC, const uint8_t *bytes,
327                                  DiceTable &Dices, uint64_t &InstSize) {
328   // Check the data in code table here to see if this is data not an
329   // instruction to be disassembled.
330   DiceTable Dice;
331   Dice.push_back(std::make_pair(PC, DiceRef()));
332   dice_table_iterator DTI =
333       std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
334                   compareDiceTableEntries);
335   if (DTI != Dices.end()) {
336     uint16_t Length;
337     DTI->second.getLength(Length);
338     uint16_t Kind;
339     DTI->second.getKind(Kind);
340     InstSize = DumpDataInCode(bytes, Length, Kind);
341     if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
342         (PC == (DTI->first + Length - 1)) && (Length & 1))
343       InstSize++;
344     return true;
345   }
346   return false;
347 }
348 
349 static void printRelocationTargetName(const MachOObjectFile *O,
350                                       const MachO::any_relocation_info &RE,
351                                       raw_string_ostream &Fmt) {
352   // Target of a scattered relocation is an address.  In the interest of
353   // generating pretty output, scan through the symbol table looking for a
354   // symbol that aligns with that address.  If we find one, print it.
355   // Otherwise, we just print the hex address of the target.
356   const StringRef FileName = O->getFileName();
357   if (O->isRelocationScattered(RE)) {
358     uint32_t Val = O->getPlainRelocationSymbolNum(RE);
359 
360     for (const SymbolRef &Symbol : O->symbols()) {
361       uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
362       if (Addr != Val)
363         continue;
364       Fmt << unwrapOrError(Symbol.getName(), FileName);
365       return;
366     }
367 
368     // If we couldn't find a symbol that this relocation refers to, try
369     // to find a section beginning instead.
370     for (const SectionRef &Section : ToolSectionFilter(*O)) {
371       uint64_t Addr = Section.getAddress();
372       if (Addr != Val)
373         continue;
374       StringRef NameOrErr = unwrapOrError(Section.getName(), O->getFileName());
375       Fmt << NameOrErr;
376       return;
377     }
378 
379     Fmt << format("0x%x", Val);
380     return;
381   }
382 
383   StringRef S;
384   bool isExtern = O->getPlainRelocationExternal(RE);
385   uint64_t Val = O->getPlainRelocationSymbolNum(RE);
386 
387   if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND &&
388       (O->getArch() == Triple::aarch64 || O->getArch() == Triple::aarch64_be)) {
389     Fmt << format("0x%0" PRIx64, Val);
390     return;
391   }
392 
393   if (isExtern) {
394     symbol_iterator SI = O->symbol_begin();
395     std::advance(SI, Val);
396     S = unwrapOrError(SI->getName(), FileName);
397   } else {
398     section_iterator SI = O->section_begin();
399     // Adjust for the fact that sections are 1-indexed.
400     if (Val == 0) {
401       Fmt << "0 (?,?)";
402       return;
403     }
404     uint32_t I = Val - 1;
405     while (I != 0 && SI != O->section_end()) {
406       --I;
407       std::advance(SI, 1);
408     }
409     if (SI == O->section_end()) {
410       Fmt << Val << " (?,?)";
411     } else {
412       if (Expected<StringRef> NameOrErr = SI->getName())
413         S = *NameOrErr;
414       else
415         consumeError(NameOrErr.takeError());
416     }
417   }
418 
419   Fmt << S;
420 }
421 
422 Error objdump::getMachORelocationValueString(const MachOObjectFile *Obj,
423                                              const RelocationRef &RelRef,
424                                              SmallVectorImpl<char> &Result) {
425   DataRefImpl Rel = RelRef.getRawDataRefImpl();
426   MachO::any_relocation_info RE = Obj->getRelocation(Rel);
427 
428   unsigned Arch = Obj->getArch();
429 
430   std::string FmtBuf;
431   raw_string_ostream Fmt(FmtBuf);
432   unsigned Type = Obj->getAnyRelocationType(RE);
433   bool IsPCRel = Obj->getAnyRelocationPCRel(RE);
434 
435   // Determine any addends that should be displayed with the relocation.
436   // These require decoding the relocation type, which is triple-specific.
437 
438   // X86_64 has entirely custom relocation types.
439   if (Arch == Triple::x86_64) {
440     switch (Type) {
441     case MachO::X86_64_RELOC_GOT_LOAD:
442     case MachO::X86_64_RELOC_GOT: {
443       printRelocationTargetName(Obj, RE, Fmt);
444       Fmt << "@GOT";
445       if (IsPCRel)
446         Fmt << "PCREL";
447       break;
448     }
449     case MachO::X86_64_RELOC_SUBTRACTOR: {
450       DataRefImpl RelNext = Rel;
451       Obj->moveRelocationNext(RelNext);
452       MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
453 
454       // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
455       // X86_64_RELOC_UNSIGNED.
456       // NOTE: Scattered relocations don't exist on x86_64.
457       unsigned RType = Obj->getAnyRelocationType(RENext);
458       if (RType != MachO::X86_64_RELOC_UNSIGNED)
459         reportError(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after "
460                                         "X86_64_RELOC_SUBTRACTOR.");
461 
462       // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
463       // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
464       printRelocationTargetName(Obj, RENext, Fmt);
465       Fmt << "-";
466       printRelocationTargetName(Obj, RE, Fmt);
467       break;
468     }
469     case MachO::X86_64_RELOC_TLV:
470       printRelocationTargetName(Obj, RE, Fmt);
471       Fmt << "@TLV";
472       if (IsPCRel)
473         Fmt << "P";
474       break;
475     case MachO::X86_64_RELOC_SIGNED_1:
476       printRelocationTargetName(Obj, RE, Fmt);
477       Fmt << "-1";
478       break;
479     case MachO::X86_64_RELOC_SIGNED_2:
480       printRelocationTargetName(Obj, RE, Fmt);
481       Fmt << "-2";
482       break;
483     case MachO::X86_64_RELOC_SIGNED_4:
484       printRelocationTargetName(Obj, RE, Fmt);
485       Fmt << "-4";
486       break;
487     default:
488       printRelocationTargetName(Obj, RE, Fmt);
489       break;
490     }
491     // X86 and ARM share some relocation types in common.
492   } else if (Arch == Triple::x86 || Arch == Triple::arm ||
493              Arch == Triple::ppc) {
494     // Generic relocation types...
495     switch (Type) {
496     case MachO::GENERIC_RELOC_PAIR: // prints no info
497       return Error::success();
498     case MachO::GENERIC_RELOC_SECTDIFF: {
499       DataRefImpl RelNext = Rel;
500       Obj->moveRelocationNext(RelNext);
501       MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
502 
503       // X86 sect diff's must be followed by a relocation of type
504       // GENERIC_RELOC_PAIR.
505       unsigned RType = Obj->getAnyRelocationType(RENext);
506 
507       if (RType != MachO::GENERIC_RELOC_PAIR)
508         reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
509                                         "GENERIC_RELOC_SECTDIFF.");
510 
511       printRelocationTargetName(Obj, RE, Fmt);
512       Fmt << "-";
513       printRelocationTargetName(Obj, RENext, Fmt);
514       break;
515     }
516     }
517 
518     if (Arch == Triple::x86 || Arch == Triple::ppc) {
519       switch (Type) {
520       case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
521         DataRefImpl RelNext = Rel;
522         Obj->moveRelocationNext(RelNext);
523         MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
524 
525         // X86 sect diff's must be followed by a relocation of type
526         // GENERIC_RELOC_PAIR.
527         unsigned RType = Obj->getAnyRelocationType(RENext);
528         if (RType != MachO::GENERIC_RELOC_PAIR)
529           reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
530                                           "GENERIC_RELOC_LOCAL_SECTDIFF.");
531 
532         printRelocationTargetName(Obj, RE, Fmt);
533         Fmt << "-";
534         printRelocationTargetName(Obj, RENext, Fmt);
535         break;
536       }
537       case MachO::GENERIC_RELOC_TLV: {
538         printRelocationTargetName(Obj, RE, Fmt);
539         Fmt << "@TLV";
540         if (IsPCRel)
541           Fmt << "P";
542         break;
543       }
544       default:
545         printRelocationTargetName(Obj, RE, Fmt);
546       }
547     } else { // ARM-specific relocations
548       switch (Type) {
549       case MachO::ARM_RELOC_HALF:
550       case MachO::ARM_RELOC_HALF_SECTDIFF: {
551         // Half relocations steal a bit from the length field to encode
552         // whether this is an upper16 or a lower16 relocation.
553         bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1;
554 
555         if (isUpper)
556           Fmt << ":upper16:(";
557         else
558           Fmt << ":lower16:(";
559         printRelocationTargetName(Obj, RE, Fmt);
560 
561         DataRefImpl RelNext = Rel;
562         Obj->moveRelocationNext(RelNext);
563         MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
564 
565         // ARM half relocs must be followed by a relocation of type
566         // ARM_RELOC_PAIR.
567         unsigned RType = Obj->getAnyRelocationType(RENext);
568         if (RType != MachO::ARM_RELOC_PAIR)
569           reportError(Obj->getFileName(), "Expected ARM_RELOC_PAIR after "
570                                           "ARM_RELOC_HALF");
571 
572         // NOTE: The half of the target virtual address is stashed in the
573         // address field of the secondary relocation, but we can't reverse
574         // engineer the constant offset from it without decoding the movw/movt
575         // instruction to find the other half in its immediate field.
576 
577         // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
578         // symbol/section pointer of the follow-on relocation.
579         if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
580           Fmt << "-";
581           printRelocationTargetName(Obj, RENext, Fmt);
582         }
583 
584         Fmt << ")";
585         break;
586       }
587       default: {
588         printRelocationTargetName(Obj, RE, Fmt);
589       }
590       }
591     }
592   } else
593     printRelocationTargetName(Obj, RE, Fmt);
594 
595   Fmt.flush();
596   Result.append(FmtBuf.begin(), FmtBuf.end());
597   return Error::success();
598 }
599 
600 static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
601                                      uint32_t n, uint32_t count,
602                                      uint32_t stride, uint64_t addr) {
603   MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
604   uint32_t nindirectsyms = Dysymtab.nindirectsyms;
605   if (n > nindirectsyms)
606     outs() << " (entries start past the end of the indirect symbol "
607               "table) (reserved1 field greater than the table size)";
608   else if (n + count > nindirectsyms)
609     outs() << " (entries extends past the end of the indirect symbol "
610               "table)";
611   outs() << "\n";
612   uint32_t cputype = O->getHeader().cputype;
613   if (cputype & MachO::CPU_ARCH_ABI64)
614     outs() << "address            index";
615   else
616     outs() << "address    index";
617   if (verbose)
618     outs() << " name\n";
619   else
620     outs() << "\n";
621   for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
622     if (cputype & MachO::CPU_ARCH_ABI64)
623       outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
624     else
625       outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
626     MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
627     uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
628     if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
629       outs() << "LOCAL\n";
630       continue;
631     }
632     if (indirect_symbol ==
633         (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
634       outs() << "LOCAL ABSOLUTE\n";
635       continue;
636     }
637     if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
638       outs() << "ABSOLUTE\n";
639       continue;
640     }
641     outs() << format("%5u ", indirect_symbol);
642     if (verbose) {
643       MachO::symtab_command Symtab = O->getSymtabLoadCommand();
644       if (indirect_symbol < Symtab.nsyms) {
645         symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
646         SymbolRef Symbol = *Sym;
647         outs() << unwrapOrError(Symbol.getName(), O->getFileName());
648       } else {
649         outs() << "?";
650       }
651     }
652     outs() << "\n";
653   }
654 }
655 
656 static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
657   for (const auto &Load : O->load_commands()) {
658     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
659       MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
660       for (unsigned J = 0; J < Seg.nsects; ++J) {
661         MachO::section_64 Sec = O->getSection64(Load, J);
662         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
663         if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
664             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
665             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
666             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
667             section_type == MachO::S_SYMBOL_STUBS) {
668           uint32_t stride;
669           if (section_type == MachO::S_SYMBOL_STUBS)
670             stride = Sec.reserved2;
671           else
672             stride = 8;
673           if (stride == 0) {
674             outs() << "Can't print indirect symbols for (" << Sec.segname << ","
675                    << Sec.sectname << ") "
676                    << "(size of stubs in reserved2 field is zero)\n";
677             continue;
678           }
679           uint32_t count = Sec.size / stride;
680           outs() << "Indirect symbols for (" << Sec.segname << ","
681                  << Sec.sectname << ") " << count << " entries";
682           uint32_t n = Sec.reserved1;
683           PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
684         }
685       }
686     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
687       MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
688       for (unsigned J = 0; J < Seg.nsects; ++J) {
689         MachO::section Sec = O->getSection(Load, J);
690         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
691         if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
692             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
693             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
694             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
695             section_type == MachO::S_SYMBOL_STUBS) {
696           uint32_t stride;
697           if (section_type == MachO::S_SYMBOL_STUBS)
698             stride = Sec.reserved2;
699           else
700             stride = 4;
701           if (stride == 0) {
702             outs() << "Can't print indirect symbols for (" << Sec.segname << ","
703                    << Sec.sectname << ") "
704                    << "(size of stubs in reserved2 field is zero)\n";
705             continue;
706           }
707           uint32_t count = Sec.size / stride;
708           outs() << "Indirect symbols for (" << Sec.segname << ","
709                  << Sec.sectname << ") " << count << " entries";
710           uint32_t n = Sec.reserved1;
711           PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
712         }
713       }
714     }
715   }
716 }
717 
718 static void PrintRType(const uint64_t cputype, const unsigned r_type) {
719   static char const *generic_r_types[] = {
720     "VANILLA ", "PAIR    ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV     ",
721     "  6 (?) ", "  7 (?) ", "  8 (?) ", "  9 (?) ", " 10 (?) ", " 11 (?) ",
722     " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
723   };
724   static char const *x86_64_r_types[] = {
725     "UNSIGND ", "SIGNED  ", "BRANCH  ", "GOT_LD  ", "GOT     ", "SUB     ",
726     "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV     ", " 10 (?) ", " 11 (?) ",
727     " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
728   };
729   static char const *arm_r_types[] = {
730     "VANILLA ", "PAIR    ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ",
731     "BR24    ", "T_BR22  ", "T_BR32  ", "HALF    ", "HALFDIF ",
732     " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
733   };
734   static char const *arm64_r_types[] = {
735     "UNSIGND ", "SUB     ", "BR26    ", "PAGE21  ", "PAGOF12 ",
736     "GOTLDP  ", "GOTLDPOF", "PTRTGOT ", "TLVLDP  ", "TLVLDPOF",
737     "ADDEND  ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
738   };
739 
740   if (r_type > 0xf){
741     outs() << format("%-7u", r_type) << " ";
742     return;
743   }
744   switch (cputype) {
745     case MachO::CPU_TYPE_I386:
746       outs() << generic_r_types[r_type];
747       break;
748     case MachO::CPU_TYPE_X86_64:
749       outs() << x86_64_r_types[r_type];
750       break;
751     case MachO::CPU_TYPE_ARM:
752       outs() << arm_r_types[r_type];
753       break;
754     case MachO::CPU_TYPE_ARM64:
755     case MachO::CPU_TYPE_ARM64_32:
756       outs() << arm64_r_types[r_type];
757       break;
758     default:
759       outs() << format("%-7u ", r_type);
760   }
761 }
762 
763 static void PrintRLength(const uint64_t cputype, const unsigned r_type,
764                          const unsigned r_length, const bool previous_arm_half){
765   if (cputype == MachO::CPU_TYPE_ARM &&
766       (r_type == MachO::ARM_RELOC_HALF ||
767        r_type == MachO::ARM_RELOC_HALF_SECTDIFF || previous_arm_half == true)) {
768     if ((r_length & 0x1) == 0)
769       outs() << "lo/";
770     else
771       outs() << "hi/";
772     if ((r_length & 0x1) == 0)
773       outs() << "arm ";
774     else
775       outs() << "thm ";
776   } else {
777     switch (r_length) {
778       case 0:
779         outs() << "byte   ";
780         break;
781       case 1:
782         outs() << "word   ";
783         break;
784       case 2:
785         outs() << "long   ";
786         break;
787       case 3:
788         if (cputype == MachO::CPU_TYPE_X86_64)
789           outs() << "quad   ";
790         else
791           outs() << format("?(%2d)  ", r_length);
792         break;
793       default:
794         outs() << format("?(%2d)  ", r_length);
795     }
796   }
797 }
798 
799 static void PrintRelocationEntries(const MachOObjectFile *O,
800                                    const relocation_iterator Begin,
801                                    const relocation_iterator End,
802                                    const uint64_t cputype,
803                                    const bool verbose) {
804   const MachO::symtab_command Symtab = O->getSymtabLoadCommand();
805   bool previous_arm_half = false;
806   bool previous_sectdiff = false;
807   uint32_t sectdiff_r_type = 0;
808 
809   for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) {
810     const DataRefImpl Rel = Reloc->getRawDataRefImpl();
811     const MachO::any_relocation_info RE = O->getRelocation(Rel);
812     const unsigned r_type = O->getAnyRelocationType(RE);
813     const bool r_scattered = O->isRelocationScattered(RE);
814     const unsigned r_pcrel = O->getAnyRelocationPCRel(RE);
815     const unsigned r_length = O->getAnyRelocationLength(RE);
816     const unsigned r_address = O->getAnyRelocationAddress(RE);
817     const bool r_extern = (r_scattered ? false :
818                            O->getPlainRelocationExternal(RE));
819     const uint32_t r_value = (r_scattered ?
820                               O->getScatteredRelocationValue(RE) : 0);
821     const unsigned r_symbolnum = (r_scattered ? 0 :
822                                   O->getPlainRelocationSymbolNum(RE));
823 
824     if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) {
825       if (verbose) {
826         // scattered: address
827         if ((cputype == MachO::CPU_TYPE_I386 &&
828              r_type == MachO::GENERIC_RELOC_PAIR) ||
829             (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR))
830           outs() << "         ";
831         else
832           outs() << format("%08x ", (unsigned int)r_address);
833 
834         // scattered: pcrel
835         if (r_pcrel)
836           outs() << "True  ";
837         else
838           outs() << "False ";
839 
840         // scattered: length
841         PrintRLength(cputype, r_type, r_length, previous_arm_half);
842 
843         // scattered: extern & type
844         outs() << "n/a    ";
845         PrintRType(cputype, r_type);
846 
847         // scattered: scattered & value
848         outs() << format("True      0x%08x", (unsigned int)r_value);
849         if (previous_sectdiff == false) {
850           if ((cputype == MachO::CPU_TYPE_ARM &&
851                r_type == MachO::ARM_RELOC_PAIR))
852             outs() << format(" half = 0x%04x ", (unsigned int)r_address);
853         } else if (cputype == MachO::CPU_TYPE_ARM &&
854                    sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF)
855           outs() << format(" other_half = 0x%04x ", (unsigned int)r_address);
856         if ((cputype == MachO::CPU_TYPE_I386 &&
857              (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
858               r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) ||
859             (cputype == MachO::CPU_TYPE_ARM &&
860              (sectdiff_r_type == MachO::ARM_RELOC_SECTDIFF ||
861               sectdiff_r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
862               sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF))) {
863           previous_sectdiff = true;
864           sectdiff_r_type = r_type;
865         } else {
866           previous_sectdiff = false;
867           sectdiff_r_type = 0;
868         }
869         if (cputype == MachO::CPU_TYPE_ARM &&
870             (r_type == MachO::ARM_RELOC_HALF ||
871              r_type == MachO::ARM_RELOC_HALF_SECTDIFF))
872           previous_arm_half = true;
873         else
874           previous_arm_half = false;
875         outs() << "\n";
876       }
877       else {
878         // scattered: address pcrel length extern type scattered value
879         outs() << format("%08x %1d     %-2d     n/a    %-7d 1         0x%08x\n",
880                          (unsigned int)r_address, r_pcrel, r_length, r_type,
881                          (unsigned int)r_value);
882       }
883     }
884     else {
885       if (verbose) {
886         // plain: address
887         if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)
888           outs() << "         ";
889         else
890           outs() << format("%08x ", (unsigned int)r_address);
891 
892         // plain: pcrel
893         if (r_pcrel)
894           outs() << "True  ";
895         else
896           outs() << "False ";
897 
898         // plain: length
899         PrintRLength(cputype, r_type, r_length, previous_arm_half);
900 
901         if (r_extern) {
902           // plain: extern & type & scattered
903           outs() << "True   ";
904           PrintRType(cputype, r_type);
905           outs() << "False     ";
906 
907           // plain: symbolnum/value
908           if (r_symbolnum > Symtab.nsyms)
909             outs() << format("?(%d)\n", r_symbolnum);
910           else {
911             SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum);
912             Expected<StringRef> SymNameNext = Symbol.getName();
913             const char *name = nullptr;
914             if (SymNameNext)
915               name = SymNameNext->data();
916             if (name == nullptr)
917               outs() << format("?(%d)\n", r_symbolnum);
918             else
919               outs() << name << "\n";
920           }
921         }
922         else {
923           // plain: extern & type & scattered
924           outs() << "False  ";
925           PrintRType(cputype, r_type);
926           outs() << "False     ";
927 
928           // plain: symbolnum/value
929           if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)
930             outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
931           else if ((cputype == MachO::CPU_TYPE_ARM64 ||
932                     cputype == MachO::CPU_TYPE_ARM64_32) &&
933                    r_type == MachO::ARM64_RELOC_ADDEND)
934             outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
935           else {
936             outs() << format("%d ", r_symbolnum);
937             if (r_symbolnum == MachO::R_ABS)
938               outs() << "R_ABS\n";
939             else {
940               // in this case, r_symbolnum is actually a 1-based section number
941               uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a;
942               if (r_symbolnum > 0 && r_symbolnum <= nsects) {
943                 object::DataRefImpl DRI;
944                 DRI.d.a = r_symbolnum-1;
945                 StringRef SegName = O->getSectionFinalSegmentName(DRI);
946                 if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
947                   outs() << "(" << SegName << "," << *NameOrErr << ")\n";
948                 else
949                   outs() << "(?,?)\n";
950               }
951               else {
952                 outs() << "(?,?)\n";
953               }
954             }
955           }
956         }
957         if (cputype == MachO::CPU_TYPE_ARM &&
958             (r_type == MachO::ARM_RELOC_HALF ||
959              r_type == MachO::ARM_RELOC_HALF_SECTDIFF))
960           previous_arm_half = true;
961         else
962           previous_arm_half = false;
963       }
964       else {
965         // plain: address pcrel length extern type scattered symbolnum/section
966         outs() << format("%08x %1d     %-2d     %1d      %-7d 0         %d\n",
967                          (unsigned int)r_address, r_pcrel, r_length, r_extern,
968                          r_type, r_symbolnum);
969       }
970     }
971   }
972 }
973 
974 static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
975   const uint64_t cputype = O->getHeader().cputype;
976   const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
977   if (Dysymtab.nextrel != 0) {
978     outs() << "External relocation information " << Dysymtab.nextrel
979            << " entries";
980     outs() << "\naddress  pcrel length extern type    scattered "
981               "symbolnum/value\n";
982     PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype,
983                            verbose);
984   }
985   if (Dysymtab.nlocrel != 0) {
986     outs() << format("Local relocation information %u entries",
987                      Dysymtab.nlocrel);
988     outs() << "\naddress  pcrel length extern type    scattered "
989               "symbolnum/value\n";
990     PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype,
991                            verbose);
992   }
993   for (const auto &Load : O->load_commands()) {
994     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
995       const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
996       for (unsigned J = 0; J < Seg.nsects; ++J) {
997         const MachO::section_64 Sec = O->getSection64(Load, J);
998         if (Sec.nreloc != 0) {
999           DataRefImpl DRI;
1000           DRI.d.a = J;
1001           const StringRef SegName = O->getSectionFinalSegmentName(DRI);
1002           if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
1003             outs() << "Relocation information (" << SegName << "," << *NameOrErr
1004                    << format(") %u entries", Sec.nreloc);
1005           else
1006             outs() << "Relocation information (" << SegName << ",?) "
1007                    << format("%u entries", Sec.nreloc);
1008           outs() << "\naddress  pcrel length extern type    scattered "
1009                     "symbolnum/value\n";
1010           PrintRelocationEntries(O, O->section_rel_begin(DRI),
1011                                  O->section_rel_end(DRI), cputype, verbose);
1012         }
1013       }
1014     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1015       const MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
1016       for (unsigned J = 0; J < Seg.nsects; ++J) {
1017         const MachO::section Sec = O->getSection(Load, J);
1018         if (Sec.nreloc != 0) {
1019           DataRefImpl DRI;
1020           DRI.d.a = J;
1021           const StringRef SegName = O->getSectionFinalSegmentName(DRI);
1022           if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
1023             outs() << "Relocation information (" << SegName << "," << *NameOrErr
1024                    << format(") %u entries", Sec.nreloc);
1025           else
1026             outs() << "Relocation information (" << SegName << ",?) "
1027                    << format("%u entries", Sec.nreloc);
1028           outs() << "\naddress  pcrel length extern type    scattered "
1029                     "symbolnum/value\n";
1030           PrintRelocationEntries(O, O->section_rel_begin(DRI),
1031                                  O->section_rel_end(DRI), cputype, verbose);
1032         }
1033       }
1034     }
1035   }
1036 }
1037 
1038 static void PrintFunctionStarts(MachOObjectFile *O) {
1039   uint64_t BaseSegmentAddress = 0;
1040   for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
1041     if (Command.C.cmd == MachO::LC_SEGMENT) {
1042       MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
1043       if (StringRef(SLC.segname) == "__TEXT") {
1044         BaseSegmentAddress = SLC.vmaddr;
1045         break;
1046       }
1047     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1048       MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
1049       if (StringRef(SLC.segname) == "__TEXT") {
1050         BaseSegmentAddress = SLC.vmaddr;
1051         break;
1052       }
1053     }
1054   }
1055 
1056   SmallVector<uint64_t, 8> FunctionStarts;
1057   for (const MachOObjectFile::LoadCommandInfo &LC : O->load_commands()) {
1058     if (LC.C.cmd == MachO::LC_FUNCTION_STARTS) {
1059       MachO::linkedit_data_command FunctionStartsLC =
1060           O->getLinkeditDataLoadCommand(LC);
1061       O->ReadULEB128s(FunctionStartsLC.dataoff, FunctionStarts);
1062       break;
1063     }
1064   }
1065 
1066   DenseMap<uint64_t, StringRef> SymbolNames;
1067   if (FunctionStartsType == FunctionStartsMode::Names ||
1068       FunctionStartsType == FunctionStartsMode::Both) {
1069     for (SymbolRef Sym : O->symbols()) {
1070       if (Expected<uint64_t> Addr = Sym.getAddress()) {
1071         if (Expected<StringRef> Name = Sym.getName()) {
1072           SymbolNames[*Addr] = *Name;
1073         }
1074       }
1075     }
1076   }
1077 
1078   for (uint64_t S : FunctionStarts) {
1079     uint64_t Addr = BaseSegmentAddress + S;
1080     if (FunctionStartsType == FunctionStartsMode::Names) {
1081       auto It = SymbolNames.find(Addr);
1082       if (It != SymbolNames.end())
1083         outs() << It->second << "\n";
1084     } else {
1085       if (O->is64Bit())
1086         outs() << format("%016" PRIx64, Addr);
1087       else
1088         outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr));
1089 
1090       if (FunctionStartsType == FunctionStartsMode::Both) {
1091         auto It = SymbolNames.find(Addr);
1092         if (It != SymbolNames.end())
1093           outs() << " " << It->second;
1094         else
1095           outs() << " ?";
1096       }
1097       outs() << "\n";
1098     }
1099   }
1100 }
1101 
1102 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
1103   MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
1104   uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
1105   outs() << "Data in code table (" << nentries << " entries)\n";
1106   outs() << "offset     length kind\n";
1107   for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
1108        ++DI) {
1109     uint32_t Offset;
1110     DI->getOffset(Offset);
1111     outs() << format("0x%08" PRIx32, Offset) << " ";
1112     uint16_t Length;
1113     DI->getLength(Length);
1114     outs() << format("%6u", Length) << " ";
1115     uint16_t Kind;
1116     DI->getKind(Kind);
1117     if (verbose) {
1118       switch (Kind) {
1119       case MachO::DICE_KIND_DATA:
1120         outs() << "DATA";
1121         break;
1122       case MachO::DICE_KIND_JUMP_TABLE8:
1123         outs() << "JUMP_TABLE8";
1124         break;
1125       case MachO::DICE_KIND_JUMP_TABLE16:
1126         outs() << "JUMP_TABLE16";
1127         break;
1128       case MachO::DICE_KIND_JUMP_TABLE32:
1129         outs() << "JUMP_TABLE32";
1130         break;
1131       case MachO::DICE_KIND_ABS_JUMP_TABLE32:
1132         outs() << "ABS_JUMP_TABLE32";
1133         break;
1134       default:
1135         outs() << format("0x%04" PRIx32, Kind);
1136         break;
1137       }
1138     } else
1139       outs() << format("0x%04" PRIx32, Kind);
1140     outs() << "\n";
1141   }
1142 }
1143 
1144 static void PrintLinkOptHints(MachOObjectFile *O) {
1145   MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
1146   const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
1147   uint32_t nloh = LohLC.datasize;
1148   outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
1149   for (uint32_t i = 0; i < nloh;) {
1150     unsigned n;
1151     uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
1152     i += n;
1153     outs() << "    identifier " << identifier << " ";
1154     if (i >= nloh)
1155       return;
1156     switch (identifier) {
1157     case 1:
1158       outs() << "AdrpAdrp\n";
1159       break;
1160     case 2:
1161       outs() << "AdrpLdr\n";
1162       break;
1163     case 3:
1164       outs() << "AdrpAddLdr\n";
1165       break;
1166     case 4:
1167       outs() << "AdrpLdrGotLdr\n";
1168       break;
1169     case 5:
1170       outs() << "AdrpAddStr\n";
1171       break;
1172     case 6:
1173       outs() << "AdrpLdrGotStr\n";
1174       break;
1175     case 7:
1176       outs() << "AdrpAdd\n";
1177       break;
1178     case 8:
1179       outs() << "AdrpLdrGot\n";
1180       break;
1181     default:
1182       outs() << "Unknown identifier value\n";
1183       break;
1184     }
1185     uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
1186     i += n;
1187     outs() << "    narguments " << narguments << "\n";
1188     if (i >= nloh)
1189       return;
1190 
1191     for (uint32_t j = 0; j < narguments; j++) {
1192       uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
1193       i += n;
1194       outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
1195       if (i >= nloh)
1196         return;
1197     }
1198   }
1199 }
1200 
1201 static SmallVector<std::string> GetSegmentNames(object::MachOObjectFile *O) {
1202   SmallVector<std::string> Ret;
1203   for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
1204     if (Command.C.cmd == MachO::LC_SEGMENT) {
1205       MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
1206       Ret.push_back(SLC.segname);
1207     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1208       MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
1209       Ret.push_back(SLC.segname);
1210     }
1211   }
1212   return Ret;
1213 }
1214 
1215 static void
1216 PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) {
1217   outs() << "chained fixups header (LC_DYLD_CHAINED_FIXUPS)\n";
1218   outs() << "  fixups_version = " << H.fixups_version << '\n';
1219   outs() << "  starts_offset  = " << H.starts_offset << '\n';
1220   outs() << "  imports_offset = " << H.imports_offset << '\n';
1221   outs() << "  symbols_offset = " << H.symbols_offset << '\n';
1222   outs() << "  imports_count  = " << H.imports_count << '\n';
1223 
1224   outs() << "  imports_format = " << H.imports_format;
1225   switch (H.imports_format) {
1226   case llvm::MachO::DYLD_CHAINED_IMPORT:
1227     outs() << " (DYLD_CHAINED_IMPORT)";
1228     break;
1229   case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND:
1230     outs() << " (DYLD_CHAINED_IMPORT_ADDEND)";
1231     break;
1232   case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND64:
1233     outs() << " (DYLD_CHAINED_IMPORT_ADDEND64)";
1234     break;
1235   }
1236   outs() << '\n';
1237 
1238   outs() << "  symbols_format = " << H.symbols_format;
1239   if (H.symbols_format == llvm::MachO::DYLD_CHAINED_SYMBOL_ZLIB)
1240     outs() << " (zlib compressed)";
1241   outs() << '\n';
1242 }
1243 
1244 static constexpr std::array<StringRef, 13> PointerFormats{
1245     "DYLD_CHAINED_PTR_ARM64E",
1246     "DYLD_CHAINED_PTR_64",
1247     "DYLD_CHAINED_PTR_32",
1248     "DYLD_CHAINED_PTR_32_CACHE",
1249     "DYLD_CHAINED_PTR_32_FIRMWARE",
1250     "DYLD_CHAINED_PTR_64_OFFSET",
1251     "DYLD_CHAINED_PTR_ARM64E_KERNEL",
1252     "DYLD_CHAINED_PTR_64_KERNEL_CACHE",
1253     "DYLD_CHAINED_PTR_ARM64E_USERLAND",
1254     "DYLD_CHAINED_PTR_ARM64E_FIRMWARE",
1255     "DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE",
1256     "DYLD_CHAINED_PTR_ARM64E_USERLAND24",
1257 };
1258 
1259 static void PrintChainedFixupsSegment(const ChainedFixupsSegment &Segment,
1260                                       StringRef SegName) {
1261   outs() << "chained starts in segment " << Segment.SegIdx << " (" << SegName
1262          << ")\n";
1263   outs() << "  size = " << Segment.Header.size << '\n';
1264   outs() << "  page_size = " << format("0x%0" PRIx16, Segment.Header.page_size)
1265          << '\n';
1266 
1267   outs() << "  pointer_format = " << Segment.Header.pointer_format;
1268   if ((Segment.Header.pointer_format - 1) <
1269       MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24)
1270     outs() << " (" << PointerFormats[Segment.Header.pointer_format - 1] << ")";
1271   outs() << '\n';
1272 
1273   outs() << "  segment_offset = "
1274          << format("0x%0" PRIx64, Segment.Header.segment_offset) << '\n';
1275   outs() << "  max_valid_pointer = " << Segment.Header.max_valid_pointer
1276          << '\n';
1277   outs() << "  page_count = " << Segment.Header.page_count << '\n';
1278   for (auto [Index, PageStart] : enumerate(Segment.PageStarts)) {
1279     outs() << "    page_start[" << Index << "] = " << PageStart;
1280     // FIXME: Support DYLD_CHAINED_PTR_START_MULTI (32-bit only)
1281     if (PageStart == MachO::DYLD_CHAINED_PTR_START_NONE)
1282       outs() << " (DYLD_CHAINED_PTR_START_NONE)";
1283     outs() << '\n';
1284   }
1285 }
1286 
1287 static void PrintChainedFixupTarget(ChainedFixupTarget &Target, size_t Idx,
1288                                     int Format, MachOObjectFile *O) {
1289   if (Format == MachO::DYLD_CHAINED_IMPORT)
1290     outs() << "dyld chained import";
1291   else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND)
1292     outs() << "dyld chained import addend";
1293   else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND64)
1294     outs() << "dyld chained import addend64";
1295   // FIXME: otool prints the encoded value as well.
1296   outs() << '[' << Idx << "]\n";
1297 
1298   outs() << "  lib_ordinal = " << Target.libOrdinal() << " ("
1299          << ordinalName(O, Target.libOrdinal()) << ")\n";
1300   outs() << "  weak_import = " << Target.weakImport() << '\n';
1301   outs() << "  name_offset = " << Target.nameOffset() << " ("
1302          << Target.symbolName() << ")\n";
1303   if (Format != MachO::DYLD_CHAINED_IMPORT)
1304     outs() << "  addend      = " << (int64_t)Target.addend() << '\n';
1305 }
1306 
1307 static void PrintChainedFixups(MachOObjectFile *O) {
1308   // MachOObjectFile::getChainedFixupsHeader() reads LC_DYLD_CHAINED_FIXUPS.
1309   // FIXME: Support chained fixups in __TEXT,__chain_starts section too.
1310   auto ChainedFixupHeader =
1311       unwrapOrError(O->getChainedFixupsHeader(), O->getFileName());
1312   if (!ChainedFixupHeader)
1313     return;
1314 
1315   PrintChainedFixupsHeader(*ChainedFixupHeader);
1316 
1317   auto [SegCount, Segments] =
1318       unwrapOrError(O->getChainedFixupsSegments(), O->getFileName());
1319 
1320   auto SegNames = GetSegmentNames(O);
1321 
1322   size_t StartsIdx = 0;
1323   outs() << "chained starts in image\n";
1324   outs() << "  seg_count = " << SegCount << '\n';
1325   for (size_t I = 0; I < SegCount; ++I) {
1326     uint64_t SegOffset = 0;
1327     if (StartsIdx < Segments.size() && I == Segments[StartsIdx].SegIdx) {
1328       SegOffset = Segments[StartsIdx].Offset;
1329       ++StartsIdx;
1330     }
1331 
1332     outs() << "    seg_offset[" << I << "] = " << SegOffset << " ("
1333            << SegNames[I] << ")\n";
1334   }
1335 
1336   for (const ChainedFixupsSegment &S : Segments)
1337     PrintChainedFixupsSegment(S, SegNames[S.SegIdx]);
1338 
1339   auto FixupTargets =
1340       unwrapOrError(O->getDyldChainedFixupTargets(), O->getFileName());
1341 
1342   uint32_t ImportsFormat = ChainedFixupHeader->imports_format;
1343   for (auto [Idx, Target] : enumerate(FixupTargets))
1344     PrintChainedFixupTarget(Target, Idx, ImportsFormat, O);
1345 }
1346 
1347 static void PrintDyldInfo(MachOObjectFile *O) {
1348   Error Err = Error::success();
1349 
1350   size_t SegmentWidth = strlen("segment");
1351   size_t SectionWidth = strlen("section");
1352   size_t AddressWidth = strlen("address");
1353   size_t AddendWidth = strlen("addend");
1354   size_t DylibWidth = strlen("dylib");
1355   const size_t PointerWidth = 2 + O->getBytesInAddress() * 2;
1356 
1357   auto HexLength = [](uint64_t Num) {
1358     return Num ? (size_t)divideCeil(Log2_64(Num), 4) : 1;
1359   };
1360   for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
1361     SegmentWidth = std::max(SegmentWidth, Entry.segmentName().size());
1362     SectionWidth = std::max(SectionWidth, Entry.sectionName().size());
1363     AddressWidth = std::max(AddressWidth, HexLength(Entry.address()) + 2);
1364     if (Entry.isBind()) {
1365       AddendWidth = std::max(AddendWidth, HexLength(Entry.addend()) + 2);
1366       DylibWidth = std::max(DylibWidth, Entry.symbolName().size());
1367     }
1368   }
1369   // Errors will be handled when printing the table.
1370   if (Err)
1371     consumeError(std::move(Err));
1372 
1373   outs() << "dyld information:\n";
1374   outs() << left_justify("segment", SegmentWidth) << ' '
1375          << left_justify("section", SectionWidth) << ' '
1376          << left_justify("address", AddressWidth) << ' '
1377          << left_justify("pointer", PointerWidth) << " type   "
1378          << left_justify("addend", AddendWidth) << ' '
1379          << left_justify("dylib", DylibWidth) << " symbol/vm address\n";
1380   for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
1381     outs() << left_justify(Entry.segmentName(), SegmentWidth) << ' '
1382            << left_justify(Entry.sectionName(), SectionWidth) << ' ' << "0x"
1383            << left_justify(utohexstr(Entry.address()), AddressWidth - 2) << ' '
1384            << format_hex(Entry.rawValue(), PointerWidth, true) << ' ';
1385     if (Entry.isBind()) {
1386       outs() << "bind   "
1387              << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2)
1388              << ' ' << left_justify(ordinalName(O, Entry.ordinal()), DylibWidth)
1389              << ' ' << Entry.symbolName();
1390       if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
1391         outs() << " (weak import)";
1392       outs() << '\n';
1393     } else {
1394       assert(Entry.isRebase());
1395       outs() << "rebase";
1396       outs().indent(AddendWidth + DylibWidth + 2);
1397       outs() << format("0x%" PRIX64, Entry.pointerValue()) << '\n';
1398     }
1399   }
1400   if (Err)
1401     reportError(std::move(Err), O->getFileName());
1402 
1403   // TODO: Print opcode-based fixups if the object uses those.
1404 }
1405 
1406 static void PrintDylibs(MachOObjectFile *O, bool JustId) {
1407   unsigned Index = 0;
1408   for (const auto &Load : O->load_commands()) {
1409     if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
1410         (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
1411                      Load.C.cmd == MachO::LC_LOAD_DYLIB ||
1412                      Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
1413                      Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
1414                      Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
1415                      Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
1416       MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
1417       if (dl.dylib.name < dl.cmdsize) {
1418         const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
1419         if (JustId)
1420           outs() << p << "\n";
1421         else {
1422           outs() << "\t" << p;
1423           outs() << " (compatibility version "
1424                  << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
1425                  << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
1426                  << (dl.dylib.compatibility_version & 0xff) << ",";
1427           outs() << " current version "
1428                  << ((dl.dylib.current_version >> 16) & 0xffff) << "."
1429                  << ((dl.dylib.current_version >> 8) & 0xff) << "."
1430                  << (dl.dylib.current_version & 0xff);
1431           if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
1432             outs() << ", weak";
1433           if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
1434             outs() << ", reexport";
1435           if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
1436             outs() << ", upward";
1437           if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
1438             outs() << ", lazy";
1439           outs() << ")\n";
1440         }
1441       } else {
1442         outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
1443         if (Load.C.cmd == MachO::LC_ID_DYLIB)
1444           outs() << "LC_ID_DYLIB ";
1445         else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
1446           outs() << "LC_LOAD_DYLIB ";
1447         else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
1448           outs() << "LC_LOAD_WEAK_DYLIB ";
1449         else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
1450           outs() << "LC_LAZY_LOAD_DYLIB ";
1451         else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
1452           outs() << "LC_REEXPORT_DYLIB ";
1453         else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
1454           outs() << "LC_LOAD_UPWARD_DYLIB ";
1455         else
1456           outs() << "LC_??? ";
1457         outs() << "command " << Index++ << "\n";
1458       }
1459     }
1460   }
1461 }
1462 
1463 static void printRpaths(MachOObjectFile *O) {
1464   for (const auto &Command : O->load_commands()) {
1465     if (Command.C.cmd == MachO::LC_RPATH) {
1466       auto Rpath = O->getRpathCommand(Command);
1467       const char *P = (const char *)(Command.Ptr) + Rpath.path;
1468       outs() << P << "\n";
1469     }
1470   }
1471 }
1472 
1473 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
1474 
1475 static void CreateSymbolAddressMap(MachOObjectFile *O,
1476                                    SymbolAddressMap *AddrMap) {
1477   // Create a map of symbol addresses to symbol names.
1478   const StringRef FileName = O->getFileName();
1479   for (const SymbolRef &Symbol : O->symbols()) {
1480     SymbolRef::Type ST = unwrapOrError(Symbol.getType(), FileName);
1481     if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
1482         ST == SymbolRef::ST_Other) {
1483       uint64_t Address = cantFail(Symbol.getValue());
1484       StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
1485       if (!SymName.starts_with(".objc"))
1486         (*AddrMap)[Address] = SymName;
1487     }
1488   }
1489 }
1490 
1491 // GuessSymbolName is passed the address of what might be a symbol and a
1492 // pointer to the SymbolAddressMap.  It returns the name of a symbol
1493 // with that address or nullptr if no symbol is found with that address.
1494 static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
1495   const char *SymbolName = nullptr;
1496   // A DenseMap can't lookup up some values.
1497   if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
1498     StringRef name = AddrMap->lookup(value);
1499     if (!name.empty())
1500       SymbolName = name.data();
1501   }
1502   return SymbolName;
1503 }
1504 
1505 static void DumpCstringChar(const char c) {
1506   char p[2];
1507   p[0] = c;
1508   p[1] = '\0';
1509   outs().write_escaped(p);
1510 }
1511 
1512 static void DumpCstringSection(MachOObjectFile *O, const char *sect,
1513                                uint32_t sect_size, uint64_t sect_addr,
1514                                bool print_addresses) {
1515   for (uint32_t i = 0; i < sect_size; i++) {
1516     if (print_addresses) {
1517       if (O->is64Bit())
1518         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1519       else
1520         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1521     }
1522     for (; i < sect_size && sect[i] != '\0'; i++)
1523       DumpCstringChar(sect[i]);
1524     if (i < sect_size && sect[i] == '\0')
1525       outs() << "\n";
1526   }
1527 }
1528 
1529 static void DumpLiteral4(uint32_t l, float f) {
1530   outs() << format("0x%08" PRIx32, l);
1531   if ((l & 0x7f800000) != 0x7f800000)
1532     outs() << format(" (%.16e)\n", f);
1533   else {
1534     if (l == 0x7f800000)
1535       outs() << " (+Infinity)\n";
1536     else if (l == 0xff800000)
1537       outs() << " (-Infinity)\n";
1538     else if ((l & 0x00400000) == 0x00400000)
1539       outs() << " (non-signaling Not-a-Number)\n";
1540     else
1541       outs() << " (signaling Not-a-Number)\n";
1542   }
1543 }
1544 
1545 static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
1546                                 uint32_t sect_size, uint64_t sect_addr,
1547                                 bool print_addresses) {
1548   for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
1549     if (print_addresses) {
1550       if (O->is64Bit())
1551         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1552       else
1553         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1554     }
1555     float f;
1556     memcpy(&f, sect + i, sizeof(float));
1557     if (O->isLittleEndian() != sys::IsLittleEndianHost)
1558       sys::swapByteOrder(f);
1559     uint32_t l;
1560     memcpy(&l, sect + i, sizeof(uint32_t));
1561     if (O->isLittleEndian() != sys::IsLittleEndianHost)
1562       sys::swapByteOrder(l);
1563     DumpLiteral4(l, f);
1564   }
1565 }
1566 
1567 static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
1568                          double d) {
1569   outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
1570   uint32_t Hi, Lo;
1571   Hi = (O->isLittleEndian()) ? l1 : l0;
1572   Lo = (O->isLittleEndian()) ? l0 : l1;
1573 
1574   // Hi is the high word, so this is equivalent to if(isfinite(d))
1575   if ((Hi & 0x7ff00000) != 0x7ff00000)
1576     outs() << format(" (%.16e)\n", d);
1577   else {
1578     if (Hi == 0x7ff00000 && Lo == 0)
1579       outs() << " (+Infinity)\n";
1580     else if (Hi == 0xfff00000 && Lo == 0)
1581       outs() << " (-Infinity)\n";
1582     else if ((Hi & 0x00080000) == 0x00080000)
1583       outs() << " (non-signaling Not-a-Number)\n";
1584     else
1585       outs() << " (signaling Not-a-Number)\n";
1586   }
1587 }
1588 
1589 static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
1590                                 uint32_t sect_size, uint64_t sect_addr,
1591                                 bool print_addresses) {
1592   for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
1593     if (print_addresses) {
1594       if (O->is64Bit())
1595         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1596       else
1597         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1598     }
1599     double d;
1600     memcpy(&d, sect + i, sizeof(double));
1601     if (O->isLittleEndian() != sys::IsLittleEndianHost)
1602       sys::swapByteOrder(d);
1603     uint32_t l0, l1;
1604     memcpy(&l0, sect + i, sizeof(uint32_t));
1605     memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1606     if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1607       sys::swapByteOrder(l0);
1608       sys::swapByteOrder(l1);
1609     }
1610     DumpLiteral8(O, l0, l1, d);
1611   }
1612 }
1613 
1614 static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
1615   outs() << format("0x%08" PRIx32, l0) << " ";
1616   outs() << format("0x%08" PRIx32, l1) << " ";
1617   outs() << format("0x%08" PRIx32, l2) << " ";
1618   outs() << format("0x%08" PRIx32, l3) << "\n";
1619 }
1620 
1621 static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
1622                                  uint32_t sect_size, uint64_t sect_addr,
1623                                  bool print_addresses) {
1624   for (uint32_t i = 0; i < sect_size; i += 16) {
1625     if (print_addresses) {
1626       if (O->is64Bit())
1627         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1628       else
1629         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1630     }
1631     uint32_t l0, l1, l2, l3;
1632     memcpy(&l0, sect + i, sizeof(uint32_t));
1633     memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1634     memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
1635     memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
1636     if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1637       sys::swapByteOrder(l0);
1638       sys::swapByteOrder(l1);
1639       sys::swapByteOrder(l2);
1640       sys::swapByteOrder(l3);
1641     }
1642     DumpLiteral16(l0, l1, l2, l3);
1643   }
1644 }
1645 
1646 static void DumpLiteralPointerSection(MachOObjectFile *O,
1647                                       const SectionRef &Section,
1648                                       const char *sect, uint32_t sect_size,
1649                                       uint64_t sect_addr,
1650                                       bool print_addresses) {
1651   // Collect the literal sections in this Mach-O file.
1652   std::vector<SectionRef> LiteralSections;
1653   for (const SectionRef &Section : O->sections()) {
1654     DataRefImpl Ref = Section.getRawDataRefImpl();
1655     uint32_t section_type;
1656     if (O->is64Bit()) {
1657       const MachO::section_64 Sec = O->getSection64(Ref);
1658       section_type = Sec.flags & MachO::SECTION_TYPE;
1659     } else {
1660       const MachO::section Sec = O->getSection(Ref);
1661       section_type = Sec.flags & MachO::SECTION_TYPE;
1662     }
1663     if (section_type == MachO::S_CSTRING_LITERALS ||
1664         section_type == MachO::S_4BYTE_LITERALS ||
1665         section_type == MachO::S_8BYTE_LITERALS ||
1666         section_type == MachO::S_16BYTE_LITERALS)
1667       LiteralSections.push_back(Section);
1668   }
1669 
1670   // Set the size of the literal pointer.
1671   uint32_t lp_size = O->is64Bit() ? 8 : 4;
1672 
1673   // Collect the external relocation symbols for the literal pointers.
1674   std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1675   for (const RelocationRef &Reloc : Section.relocations()) {
1676     DataRefImpl Rel;
1677     MachO::any_relocation_info RE;
1678     bool isExtern = false;
1679     Rel = Reloc.getRawDataRefImpl();
1680     RE = O->getRelocation(Rel);
1681     isExtern = O->getPlainRelocationExternal(RE);
1682     if (isExtern) {
1683       uint64_t RelocOffset = Reloc.getOffset();
1684       symbol_iterator RelocSym = Reloc.getSymbol();
1685       Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1686     }
1687   }
1688   array_pod_sort(Relocs.begin(), Relocs.end());
1689 
1690   // Dump each literal pointer.
1691   for (uint32_t i = 0; i < sect_size; i += lp_size) {
1692     if (print_addresses) {
1693       if (O->is64Bit())
1694         outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1695       else
1696         outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1697     }
1698     uint64_t lp;
1699     if (O->is64Bit()) {
1700       memcpy(&lp, sect + i, sizeof(uint64_t));
1701       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1702         sys::swapByteOrder(lp);
1703     } else {
1704       uint32_t li;
1705       memcpy(&li, sect + i, sizeof(uint32_t));
1706       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1707         sys::swapByteOrder(li);
1708       lp = li;
1709     }
1710 
1711     // First look for an external relocation entry for this literal pointer.
1712     auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1713       return P.first == i;
1714     });
1715     if (Reloc != Relocs.end()) {
1716       symbol_iterator RelocSym = Reloc->second;
1717       StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName());
1718       outs() << "external relocation entry for symbol:" << SymName << "\n";
1719       continue;
1720     }
1721 
1722     // For local references see what the section the literal pointer points to.
1723     auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
1724       return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
1725     });
1726     if (Sect == LiteralSections.end()) {
1727       outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
1728       continue;
1729     }
1730 
1731     uint64_t SectAddress = Sect->getAddress();
1732     uint64_t SectSize = Sect->getSize();
1733 
1734     StringRef SectName;
1735     Expected<StringRef> SectNameOrErr = Sect->getName();
1736     if (SectNameOrErr)
1737       SectName = *SectNameOrErr;
1738     else
1739       consumeError(SectNameOrErr.takeError());
1740 
1741     DataRefImpl Ref = Sect->getRawDataRefImpl();
1742     StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
1743     outs() << SegmentName << ":" << SectName << ":";
1744 
1745     uint32_t section_type;
1746     if (O->is64Bit()) {
1747       const MachO::section_64 Sec = O->getSection64(Ref);
1748       section_type = Sec.flags & MachO::SECTION_TYPE;
1749     } else {
1750       const MachO::section Sec = O->getSection(Ref);
1751       section_type = Sec.flags & MachO::SECTION_TYPE;
1752     }
1753 
1754     StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName());
1755 
1756     const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
1757 
1758     switch (section_type) {
1759     case MachO::S_CSTRING_LITERALS:
1760       for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
1761            i++) {
1762         DumpCstringChar(Contents[i]);
1763       }
1764       outs() << "\n";
1765       break;
1766     case MachO::S_4BYTE_LITERALS:
1767       float f;
1768       memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
1769       uint32_t l;
1770       memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
1771       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1772         sys::swapByteOrder(f);
1773         sys::swapByteOrder(l);
1774       }
1775       DumpLiteral4(l, f);
1776       break;
1777     case MachO::S_8BYTE_LITERALS: {
1778       double d;
1779       memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
1780       uint32_t l0, l1;
1781       memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1782       memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1783              sizeof(uint32_t));
1784       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1785         sys::swapByteOrder(f);
1786         sys::swapByteOrder(l0);
1787         sys::swapByteOrder(l1);
1788       }
1789       DumpLiteral8(O, l0, l1, d);
1790       break;
1791     }
1792     case MachO::S_16BYTE_LITERALS: {
1793       uint32_t l0, l1, l2, l3;
1794       memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1795       memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1796              sizeof(uint32_t));
1797       memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
1798              sizeof(uint32_t));
1799       memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
1800              sizeof(uint32_t));
1801       if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1802         sys::swapByteOrder(l0);
1803         sys::swapByteOrder(l1);
1804         sys::swapByteOrder(l2);
1805         sys::swapByteOrder(l3);
1806       }
1807       DumpLiteral16(l0, l1, l2, l3);
1808       break;
1809     }
1810     }
1811   }
1812 }
1813 
1814 static void DumpInitTermPointerSection(MachOObjectFile *O,
1815                                        const SectionRef &Section,
1816                                        const char *sect,
1817                                        uint32_t sect_size, uint64_t sect_addr,
1818                                        SymbolAddressMap *AddrMap,
1819                                        bool verbose) {
1820   uint32_t stride;
1821   stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
1822 
1823   // Collect the external relocation symbols for the pointers.
1824   std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1825   for (const RelocationRef &Reloc : Section.relocations()) {
1826     DataRefImpl Rel;
1827     MachO::any_relocation_info RE;
1828     bool isExtern = false;
1829     Rel = Reloc.getRawDataRefImpl();
1830     RE = O->getRelocation(Rel);
1831     isExtern = O->getPlainRelocationExternal(RE);
1832     if (isExtern) {
1833       uint64_t RelocOffset = Reloc.getOffset();
1834       symbol_iterator RelocSym = Reloc.getSymbol();
1835       Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1836     }
1837   }
1838   array_pod_sort(Relocs.begin(), Relocs.end());
1839 
1840   for (uint32_t i = 0; i < sect_size; i += stride) {
1841     const char *SymbolName = nullptr;
1842     uint64_t p;
1843     if (O->is64Bit()) {
1844       outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
1845       uint64_t pointer_value;
1846       memcpy(&pointer_value, sect + i, stride);
1847       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1848         sys::swapByteOrder(pointer_value);
1849       outs() << format("0x%016" PRIx64, pointer_value);
1850       p = pointer_value;
1851     } else {
1852       outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
1853       uint32_t pointer_value;
1854       memcpy(&pointer_value, sect + i, stride);
1855       if (O->isLittleEndian() != sys::IsLittleEndianHost)
1856         sys::swapByteOrder(pointer_value);
1857       outs() << format("0x%08" PRIx32, pointer_value);
1858       p = pointer_value;
1859     }
1860     if (verbose) {
1861       // First look for an external relocation entry for this pointer.
1862       auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1863         return P.first == i;
1864       });
1865       if (Reloc != Relocs.end()) {
1866         symbol_iterator RelocSym = Reloc->second;
1867         outs() << " " << unwrapOrError(RelocSym->getName(), O->getFileName());
1868       } else {
1869         SymbolName = GuessSymbolName(p, AddrMap);
1870         if (SymbolName)
1871           outs() << " " << SymbolName;
1872       }
1873     }
1874     outs() << "\n";
1875   }
1876 }
1877 
1878 static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
1879                                    uint32_t size, uint64_t addr) {
1880   uint32_t cputype = O->getHeader().cputype;
1881   if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
1882     uint32_t j;
1883     for (uint32_t i = 0; i < size; i += j, addr += j) {
1884       if (O->is64Bit())
1885         outs() << format("%016" PRIx64, addr) << "\t";
1886       else
1887         outs() << format("%08" PRIx64, addr) << "\t";
1888       for (j = 0; j < 16 && i + j < size; j++) {
1889         uint8_t byte_word = *(sect + i + j);
1890         outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1891       }
1892       outs() << "\n";
1893     }
1894   } else {
1895     uint32_t j;
1896     for (uint32_t i = 0; i < size; i += j, addr += j) {
1897       if (O->is64Bit())
1898         outs() << format("%016" PRIx64, addr) << "\t";
1899       else
1900         outs() << format("%08" PRIx64, addr) << "\t";
1901       for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
1902            j += sizeof(int32_t)) {
1903         if (i + j + sizeof(int32_t) <= size) {
1904           uint32_t long_word;
1905           memcpy(&long_word, sect + i + j, sizeof(int32_t));
1906           if (O->isLittleEndian() != sys::IsLittleEndianHost)
1907             sys::swapByteOrder(long_word);
1908           outs() << format("%08" PRIx32, long_word) << " ";
1909         } else {
1910           for (uint32_t k = 0; i + j + k < size; k++) {
1911             uint8_t byte_word = *(sect + i + j + k);
1912             outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1913           }
1914         }
1915       }
1916       outs() << "\n";
1917     }
1918   }
1919 }
1920 
1921 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
1922                              StringRef DisSegName, StringRef DisSectName);
1923 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
1924                                 uint32_t size, uint32_t addr);
1925 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
1926                                 bool verbose) {
1927   SymbolAddressMap AddrMap;
1928   if (verbose)
1929     CreateSymbolAddressMap(O, &AddrMap);
1930 
1931   for (unsigned i = 0; i < FilterSections.size(); ++i) {
1932     StringRef DumpSection = FilterSections[i];
1933     std::pair<StringRef, StringRef> DumpSegSectName;
1934     DumpSegSectName = DumpSection.split(',');
1935     StringRef DumpSegName, DumpSectName;
1936     if (!DumpSegSectName.second.empty()) {
1937       DumpSegName = DumpSegSectName.first;
1938       DumpSectName = DumpSegSectName.second;
1939     } else {
1940       DumpSegName = "";
1941       DumpSectName = DumpSegSectName.first;
1942     }
1943     for (const SectionRef &Section : O->sections()) {
1944       StringRef SectName;
1945       Expected<StringRef> SecNameOrErr = Section.getName();
1946       if (SecNameOrErr)
1947         SectName = *SecNameOrErr;
1948       else
1949         consumeError(SecNameOrErr.takeError());
1950 
1951       if (!DumpSection.empty())
1952         FoundSectionSet.insert(DumpSection);
1953 
1954       DataRefImpl Ref = Section.getRawDataRefImpl();
1955       StringRef SegName = O->getSectionFinalSegmentName(Ref);
1956       if ((DumpSegName.empty() || SegName == DumpSegName) &&
1957           (SectName == DumpSectName)) {
1958 
1959         uint32_t section_flags;
1960         if (O->is64Bit()) {
1961           const MachO::section_64 Sec = O->getSection64(Ref);
1962           section_flags = Sec.flags;
1963 
1964         } else {
1965           const MachO::section Sec = O->getSection(Ref);
1966           section_flags = Sec.flags;
1967         }
1968         uint32_t section_type = section_flags & MachO::SECTION_TYPE;
1969 
1970         StringRef BytesStr =
1971             unwrapOrError(Section.getContents(), O->getFileName());
1972         const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1973         uint32_t sect_size = BytesStr.size();
1974         uint64_t sect_addr = Section.getAddress();
1975 
1976         if (LeadingHeaders)
1977           outs() << "Contents of (" << SegName << "," << SectName
1978                  << ") section\n";
1979 
1980         if (verbose) {
1981           if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
1982               (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
1983             DisassembleMachO(Filename, O, SegName, SectName);
1984             continue;
1985           }
1986           if (SegName == "__TEXT" && SectName == "__info_plist") {
1987             outs() << sect;
1988             continue;
1989           }
1990           if (SegName == "__OBJC" && SectName == "__protocol") {
1991             DumpProtocolSection(O, sect, sect_size, sect_addr);
1992             continue;
1993           }
1994           switch (section_type) {
1995           case MachO::S_REGULAR:
1996             DumpRawSectionContents(O, sect, sect_size, sect_addr);
1997             break;
1998           case MachO::S_ZEROFILL:
1999             outs() << "zerofill section and has no contents in the file\n";
2000             break;
2001           case MachO::S_CSTRING_LITERALS:
2002             DumpCstringSection(O, sect, sect_size, sect_addr, LeadingAddr);
2003             break;
2004           case MachO::S_4BYTE_LITERALS:
2005             DumpLiteral4Section(O, sect, sect_size, sect_addr, LeadingAddr);
2006             break;
2007           case MachO::S_8BYTE_LITERALS:
2008             DumpLiteral8Section(O, sect, sect_size, sect_addr, LeadingAddr);
2009             break;
2010           case MachO::S_16BYTE_LITERALS:
2011             DumpLiteral16Section(O, sect, sect_size, sect_addr, LeadingAddr);
2012             break;
2013           case MachO::S_LITERAL_POINTERS:
2014             DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
2015                                       LeadingAddr);
2016             break;
2017           case MachO::S_MOD_INIT_FUNC_POINTERS:
2018           case MachO::S_MOD_TERM_FUNC_POINTERS:
2019             DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr,
2020                                        &AddrMap, verbose);
2021             break;
2022           default:
2023             outs() << "Unknown section type ("
2024                    << format("0x%08" PRIx32, section_type) << ")\n";
2025             DumpRawSectionContents(O, sect, sect_size, sect_addr);
2026             break;
2027           }
2028         } else {
2029           if (section_type == MachO::S_ZEROFILL)
2030             outs() << "zerofill section and has no contents in the file\n";
2031           else
2032             DumpRawSectionContents(O, sect, sect_size, sect_addr);
2033         }
2034       }
2035     }
2036   }
2037 }
2038 
2039 static void DumpInfoPlistSectionContents(StringRef Filename,
2040                                          MachOObjectFile *O) {
2041   for (const SectionRef &Section : O->sections()) {
2042     StringRef SectName;
2043     Expected<StringRef> SecNameOrErr = Section.getName();
2044     if (SecNameOrErr)
2045       SectName = *SecNameOrErr;
2046     else
2047       consumeError(SecNameOrErr.takeError());
2048 
2049     DataRefImpl Ref = Section.getRawDataRefImpl();
2050     StringRef SegName = O->getSectionFinalSegmentName(Ref);
2051     if (SegName == "__TEXT" && SectName == "__info_plist") {
2052       if (LeadingHeaders)
2053         outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
2054       StringRef BytesStr =
2055           unwrapOrError(Section.getContents(), O->getFileName());
2056       const char *sect = reinterpret_cast<const char *>(BytesStr.data());
2057       outs() << format("%.*s", BytesStr.size(), sect) << "\n";
2058       return;
2059     }
2060   }
2061 }
2062 
2063 // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
2064 // and if it is and there is a list of architecture flags is specified then
2065 // check to make sure this Mach-O file is one of those architectures or all
2066 // architectures were specified.  If not then an error is generated and this
2067 // routine returns false.  Else it returns true.
2068 static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
2069   auto *MachO = dyn_cast<MachOObjectFile>(O);
2070 
2071   if (!MachO || ArchAll || ArchFlags.empty())
2072     return true;
2073 
2074   MachO::mach_header H;
2075   MachO::mach_header_64 H_64;
2076   Triple T;
2077   const char *McpuDefault, *ArchFlag;
2078   if (MachO->is64Bit()) {
2079     H_64 = MachO->MachOObjectFile::getHeader64();
2080     T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
2081                                        &McpuDefault, &ArchFlag);
2082   } else {
2083     H = MachO->MachOObjectFile::getHeader();
2084     T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
2085                                        &McpuDefault, &ArchFlag);
2086   }
2087   const std::string ArchFlagName(ArchFlag);
2088   if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
2089     WithColor::error(errs(), "llvm-objdump")
2090         << Filename << ": no architecture specified.\n";
2091     return false;
2092   }
2093   return true;
2094 }
2095 
2096 static void printObjcMetaData(MachOObjectFile *O, bool verbose);
2097 
2098 // ProcessMachO() is passed a single opened Mach-O file, which may be an
2099 // archive member and or in a slice of a universal file.  It prints the
2100 // the file name and header info and then processes it according to the
2101 // command line options.
2102 static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
2103                          StringRef ArchiveMemberName = StringRef(),
2104                          StringRef ArchitectureName = StringRef()) {
2105   std::unique_ptr<Dumper> D = createMachODumper(*MachOOF);
2106 
2107   // If we are doing some processing here on the Mach-O file print the header
2108   // info.  And don't print it otherwise like in the case of printing the
2109   // UniversalHeaders or ArchiveHeaders.
2110   if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
2111       Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
2112       DataInCode || FunctionStartsType != FunctionStartsMode::None ||
2113       LinkOptHints || ChainedFixups || DyldInfo || DylibsUsed || DylibId ||
2114       Rpaths || ObjcMetaData || (!FilterSections.empty())) {
2115     if (LeadingHeaders) {
2116       outs() << Name;
2117       if (!ArchiveMemberName.empty())
2118         outs() << '(' << ArchiveMemberName << ')';
2119       if (!ArchitectureName.empty())
2120         outs() << " (architecture " << ArchitectureName << ")";
2121       outs() << ":\n";
2122     }
2123   }
2124   // To use the report_error() form with an ArchiveName and FileName set
2125   // these up based on what is passed for Name and ArchiveMemberName.
2126   StringRef ArchiveName;
2127   StringRef FileName;
2128   if (!ArchiveMemberName.empty()) {
2129     ArchiveName = Name;
2130     FileName = ArchiveMemberName;
2131   } else {
2132     ArchiveName = StringRef();
2133     FileName = Name;
2134   }
2135 
2136   // If we need the symbol table to do the operation then check it here to
2137   // produce a good error message as to where the Mach-O file comes from in
2138   // the error message.
2139   if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo)
2140     if (Error Err = MachOOF->checkSymbolTable())
2141       reportError(std::move(Err), FileName, ArchiveName, ArchitectureName);
2142 
2143   if (DisassembleAll) {
2144     for (const SectionRef &Section : MachOOF->sections()) {
2145       StringRef SectName;
2146       if (Expected<StringRef> NameOrErr = Section.getName())
2147         SectName = *NameOrErr;
2148       else
2149         consumeError(NameOrErr.takeError());
2150 
2151       if (SectName == "__text") {
2152         DataRefImpl Ref = Section.getRawDataRefImpl();
2153         StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref);
2154         DisassembleMachO(FileName, MachOOF, SegName, SectName);
2155       }
2156     }
2157   }
2158   else if (Disassemble) {
2159     if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE &&
2160         MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64)
2161       DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text");
2162     else
2163       DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
2164   }
2165   if (IndirectSymbols)
2166     PrintIndirectSymbols(MachOOF, Verbose);
2167   if (DataInCode)
2168     PrintDataInCodeTable(MachOOF, Verbose);
2169   if (FunctionStartsType != FunctionStartsMode::None)
2170     PrintFunctionStarts(MachOOF);
2171   if (LinkOptHints)
2172     PrintLinkOptHints(MachOOF);
2173   if (Relocations)
2174     PrintRelocations(MachOOF, Verbose);
2175   if (SectionHeaders)
2176     printSectionHeaders(*MachOOF);
2177   if (SectionContents)
2178     printSectionContents(MachOOF);
2179   if (!FilterSections.empty())
2180     DumpSectionContents(FileName, MachOOF, Verbose);
2181   if (InfoPlist)
2182     DumpInfoPlistSectionContents(FileName, MachOOF);
2183   if (DyldInfo)
2184     PrintDyldInfo(MachOOF);
2185   if (ChainedFixups)
2186     PrintChainedFixups(MachOOF);
2187   if (DylibsUsed)
2188     PrintDylibs(MachOOF, false);
2189   if (DylibId)
2190     PrintDylibs(MachOOF, true);
2191   if (SymbolTable)
2192     D->printSymbolTable(ArchiveName, ArchitectureName);
2193   if (UnwindInfo)
2194     printMachOUnwindInfo(MachOOF);
2195   if (PrivateHeaders) {
2196     printMachOFileHeader(MachOOF);
2197     printMachOLoadCommands(MachOOF);
2198   }
2199   if (FirstPrivateHeader)
2200     printMachOFileHeader(MachOOF);
2201   if (ObjcMetaData)
2202     printObjcMetaData(MachOOF, Verbose);
2203   if (ExportsTrie)
2204     printExportsTrie(MachOOF);
2205   if (Rebase)
2206     printRebaseTable(MachOOF);
2207   if (Rpaths)
2208     printRpaths(MachOOF);
2209   if (Bind)
2210     printBindTable(MachOOF);
2211   if (LazyBind)
2212     printLazyBindTable(MachOOF);
2213   if (WeakBind)
2214     printWeakBindTable(MachOOF);
2215 
2216   if (DwarfDumpType != DIDT_Null) {
2217     std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF);
2218     // Dump the complete DWARF structure.
2219     DIDumpOptions DumpOpts;
2220     DumpOpts.DumpType = DwarfDumpType;
2221     DICtx->dump(outs(), DumpOpts);
2222   }
2223 }
2224 
2225 // printUnknownCPUType() helps print_fat_headers for unknown CPU's.
2226 static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
2227   outs() << "    cputype (" << cputype << ")\n";
2228   outs() << "    cpusubtype (" << cpusubtype << ")\n";
2229 }
2230 
2231 // printCPUType() helps print_fat_headers by printing the cputype and
2232 // pusubtype (symbolically for the one's it knows about).
2233 static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
2234   switch (cputype) {
2235   case MachO::CPU_TYPE_I386:
2236     switch (cpusubtype) {
2237     case MachO::CPU_SUBTYPE_I386_ALL:
2238       outs() << "    cputype CPU_TYPE_I386\n";
2239       outs() << "    cpusubtype CPU_SUBTYPE_I386_ALL\n";
2240       break;
2241     default:
2242       printUnknownCPUType(cputype, cpusubtype);
2243       break;
2244     }
2245     break;
2246   case MachO::CPU_TYPE_X86_64:
2247     switch (cpusubtype) {
2248     case MachO::CPU_SUBTYPE_X86_64_ALL:
2249       outs() << "    cputype CPU_TYPE_X86_64\n";
2250       outs() << "    cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
2251       break;
2252     case MachO::CPU_SUBTYPE_X86_64_H:
2253       outs() << "    cputype CPU_TYPE_X86_64\n";
2254       outs() << "    cpusubtype CPU_SUBTYPE_X86_64_H\n";
2255       break;
2256     default:
2257       printUnknownCPUType(cputype, cpusubtype);
2258       break;
2259     }
2260     break;
2261   case MachO::CPU_TYPE_ARM:
2262     switch (cpusubtype) {
2263     case MachO::CPU_SUBTYPE_ARM_ALL:
2264       outs() << "    cputype CPU_TYPE_ARM\n";
2265       outs() << "    cpusubtype CPU_SUBTYPE_ARM_ALL\n";
2266       break;
2267     case MachO::CPU_SUBTYPE_ARM_V4T:
2268       outs() << "    cputype CPU_TYPE_ARM\n";
2269       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V4T\n";
2270       break;
2271     case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2272       outs() << "    cputype CPU_TYPE_ARM\n";
2273       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
2274       break;
2275     case MachO::CPU_SUBTYPE_ARM_XSCALE:
2276       outs() << "    cputype CPU_TYPE_ARM\n";
2277       outs() << "    cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
2278       break;
2279     case MachO::CPU_SUBTYPE_ARM_V6:
2280       outs() << "    cputype CPU_TYPE_ARM\n";
2281       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6\n";
2282       break;
2283     case MachO::CPU_SUBTYPE_ARM_V6M:
2284       outs() << "    cputype CPU_TYPE_ARM\n";
2285       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6M\n";
2286       break;
2287     case MachO::CPU_SUBTYPE_ARM_V7:
2288       outs() << "    cputype CPU_TYPE_ARM\n";
2289       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7\n";
2290       break;
2291     case MachO::CPU_SUBTYPE_ARM_V7EM:
2292       outs() << "    cputype CPU_TYPE_ARM\n";
2293       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
2294       break;
2295     case MachO::CPU_SUBTYPE_ARM_V7K:
2296       outs() << "    cputype CPU_TYPE_ARM\n";
2297       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7K\n";
2298       break;
2299     case MachO::CPU_SUBTYPE_ARM_V7M:
2300       outs() << "    cputype CPU_TYPE_ARM\n";
2301       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7M\n";
2302       break;
2303     case MachO::CPU_SUBTYPE_ARM_V7S:
2304       outs() << "    cputype CPU_TYPE_ARM\n";
2305       outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7S\n";
2306       break;
2307     default:
2308       printUnknownCPUType(cputype, cpusubtype);
2309       break;
2310     }
2311     break;
2312   case MachO::CPU_TYPE_ARM64:
2313     switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
2314     case MachO::CPU_SUBTYPE_ARM64_ALL:
2315       outs() << "    cputype CPU_TYPE_ARM64\n";
2316       outs() << "    cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
2317       break;
2318     case MachO::CPU_SUBTYPE_ARM64_V8:
2319       outs() << "    cputype CPU_TYPE_ARM64\n";
2320       outs() << "    cpusubtype CPU_SUBTYPE_ARM64_V8\n";
2321       break;
2322     case MachO::CPU_SUBTYPE_ARM64E:
2323       outs() << "    cputype CPU_TYPE_ARM64\n";
2324       outs() << "    cpusubtype CPU_SUBTYPE_ARM64E\n";
2325       break;
2326     default:
2327       printUnknownCPUType(cputype, cpusubtype);
2328       break;
2329     }
2330     break;
2331   case MachO::CPU_TYPE_ARM64_32:
2332     switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
2333     case MachO::CPU_SUBTYPE_ARM64_32_V8:
2334       outs() << "    cputype CPU_TYPE_ARM64_32\n";
2335       outs() << "    cpusubtype CPU_SUBTYPE_ARM64_32_V8\n";
2336       break;
2337     default:
2338       printUnknownCPUType(cputype, cpusubtype);
2339       break;
2340     }
2341     break;
2342   default:
2343     printUnknownCPUType(cputype, cpusubtype);
2344     break;
2345   }
2346 }
2347 
2348 static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
2349                                        bool verbose) {
2350   outs() << "Fat headers\n";
2351   if (verbose) {
2352     if (UB->getMagic() == MachO::FAT_MAGIC)
2353       outs() << "fat_magic FAT_MAGIC\n";
2354     else // UB->getMagic() == MachO::FAT_MAGIC_64
2355       outs() << "fat_magic FAT_MAGIC_64\n";
2356   } else
2357     outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
2358 
2359   uint32_t nfat_arch = UB->getNumberOfObjects();
2360   StringRef Buf = UB->getData();
2361   uint64_t size = Buf.size();
2362   uint64_t big_size = sizeof(struct MachO::fat_header) +
2363                       nfat_arch * sizeof(struct MachO::fat_arch);
2364   outs() << "nfat_arch " << UB->getNumberOfObjects();
2365   if (nfat_arch == 0)
2366     outs() << " (malformed, contains zero architecture types)\n";
2367   else if (big_size > size)
2368     outs() << " (malformed, architectures past end of file)\n";
2369   else
2370     outs() << "\n";
2371 
2372   for (uint32_t i = 0; i < nfat_arch; ++i) {
2373     MachOUniversalBinary::ObjectForArch OFA(UB, i);
2374     uint32_t cputype = OFA.getCPUType();
2375     uint32_t cpusubtype = OFA.getCPUSubType();
2376     outs() << "architecture ";
2377     for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
2378       MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
2379       uint32_t other_cputype = other_OFA.getCPUType();
2380       uint32_t other_cpusubtype = other_OFA.getCPUSubType();
2381       if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
2382           (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
2383               (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
2384         outs() << "(illegal duplicate architecture) ";
2385         break;
2386       }
2387     }
2388     if (verbose) {
2389       outs() << OFA.getArchFlagName() << "\n";
2390       printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
2391     } else {
2392       outs() << i << "\n";
2393       outs() << "    cputype " << cputype << "\n";
2394       outs() << "    cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
2395              << "\n";
2396     }
2397     if (verbose && cputype == MachO::CPU_TYPE_ARM64 &&
2398         MachO::CPU_SUBTYPE_ARM64E_IS_VERSIONED_PTRAUTH_ABI(cpusubtype)) {
2399       outs() << "    capabilities CPU_SUBTYPE_ARM64E_";
2400       if (MachO::CPU_SUBTYPE_ARM64E_IS_KERNEL_PTRAUTH_ABI(cpusubtype))
2401         outs() << "KERNEL_";
2402       outs() << format("PTRAUTH_VERSION %d",
2403                        MachO::CPU_SUBTYPE_ARM64E_PTRAUTH_VERSION(cpusubtype))
2404              << "\n";
2405     } else if (verbose && (cpusubtype & MachO::CPU_SUBTYPE_MASK) ==
2406                               MachO::CPU_SUBTYPE_LIB64)
2407       outs() << "    capabilities CPU_SUBTYPE_LIB64\n";
2408     else
2409       outs() << "    capabilities "
2410              << format("0x%" PRIx32,
2411                        (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
2412     outs() << "    offset " << OFA.getOffset();
2413     if (OFA.getOffset() > size)
2414       outs() << " (past end of file)";
2415     if (OFA.getOffset() % (1ull << OFA.getAlign()) != 0)
2416       outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
2417     outs() << "\n";
2418     outs() << "    size " << OFA.getSize();
2419     big_size = OFA.getOffset() + OFA.getSize();
2420     if (big_size > size)
2421       outs() << " (past end of file)";
2422     outs() << "\n";
2423     outs() << "    align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
2424            << ")\n";
2425   }
2426 }
2427 
2428 static void printArchiveChild(StringRef Filename, const Archive::Child &C,
2429                               size_t ChildIndex, bool verbose,
2430                               bool print_offset,
2431                               StringRef ArchitectureName = StringRef()) {
2432   if (print_offset)
2433     outs() << C.getChildOffset() << "\t";
2434   sys::fs::perms Mode =
2435       unwrapOrError(C.getAccessMode(), getFileNameForError(C, ChildIndex),
2436                     Filename, ArchitectureName);
2437   if (verbose) {
2438     // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
2439     // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
2440     outs() << "-";
2441     outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
2442     outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
2443     outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
2444     outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
2445     outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
2446     outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
2447     outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
2448     outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
2449     outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
2450   } else {
2451     outs() << format("0%o ", Mode);
2452   }
2453 
2454   outs() << format("%3d/%-3d %5" PRId64 " ",
2455                    unwrapOrError(C.getUID(), getFileNameForError(C, ChildIndex),
2456                                  Filename, ArchitectureName),
2457                    unwrapOrError(C.getGID(), getFileNameForError(C, ChildIndex),
2458                                  Filename, ArchitectureName),
2459                    unwrapOrError(C.getRawSize(),
2460                                  getFileNameForError(C, ChildIndex), Filename,
2461                                  ArchitectureName));
2462 
2463   StringRef RawLastModified = C.getRawLastModified();
2464   if (verbose) {
2465     unsigned Seconds;
2466     if (RawLastModified.getAsInteger(10, Seconds))
2467       outs() << "(date: \"" << RawLastModified
2468              << "\" contains non-decimal chars) ";
2469     else {
2470       // Since cime(3) returns a 26 character string of the form:
2471       // "Sun Sep 16 01:03:52 1973\n\0"
2472       // just print 24 characters.
2473       time_t t = Seconds;
2474       outs() << format("%.24s ", ctime(&t));
2475     }
2476   } else {
2477     outs() << RawLastModified << " ";
2478   }
2479 
2480   if (verbose) {
2481     Expected<StringRef> NameOrErr = C.getName();
2482     if (!NameOrErr) {
2483       consumeError(NameOrErr.takeError());
2484       outs() << unwrapOrError(C.getRawName(),
2485                               getFileNameForError(C, ChildIndex), Filename,
2486                               ArchitectureName)
2487              << "\n";
2488     } else {
2489       StringRef Name = NameOrErr.get();
2490       outs() << Name << "\n";
2491     }
2492   } else {
2493     outs() << unwrapOrError(C.getRawName(), getFileNameForError(C, ChildIndex),
2494                             Filename, ArchitectureName)
2495            << "\n";
2496   }
2497 }
2498 
2499 static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
2500                                 bool print_offset,
2501                                 StringRef ArchitectureName = StringRef()) {
2502   Error Err = Error::success();
2503   size_t I = 0;
2504   for (const auto &C : A->children(Err, false))
2505     printArchiveChild(Filename, C, I++, verbose, print_offset,
2506                       ArchitectureName);
2507 
2508   if (Err)
2509     reportError(std::move(Err), Filename, "", ArchitectureName);
2510 }
2511 
2512 static bool ValidateArchFlags() {
2513   // Check for -arch all and verifiy the -arch flags are valid.
2514   for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2515     if (ArchFlags[i] == "all") {
2516       ArchAll = true;
2517     } else {
2518       if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
2519         WithColor::error(errs(), "llvm-objdump")
2520             << "unknown architecture named '" + ArchFlags[i] +
2521                    "'for the -arch option\n";
2522         return false;
2523       }
2524     }
2525   }
2526   return true;
2527 }
2528 
2529 // ParseInputMachO() parses the named Mach-O file in Filename and handles the
2530 // -arch flags selecting just those slices as specified by them and also parses
2531 // archive files.  Then for each individual Mach-O file ProcessMachO() is
2532 // called to process the file based on the command line options.
2533 void objdump::parseInputMachO(StringRef Filename) {
2534   if (!ValidateArchFlags())
2535     return;
2536 
2537   // Attempt to open the binary.
2538   Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
2539   if (!BinaryOrErr) {
2540     if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError()))
2541       reportError(std::move(E), Filename);
2542     else
2543       outs() << Filename << ": is not an object file\n";
2544     return;
2545   }
2546   Binary &Bin = *BinaryOrErr.get().getBinary();
2547 
2548   if (Archive *A = dyn_cast<Archive>(&Bin)) {
2549     outs() << "Archive : " << Filename << "\n";
2550     if (ArchiveHeaders)
2551       printArchiveHeaders(Filename, A, Verbose, ArchiveMemberOffsets);
2552 
2553     Error Err = Error::success();
2554     unsigned I = -1;
2555     for (auto &C : A->children(Err)) {
2556       ++I;
2557       Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2558       if (!ChildOrErr) {
2559         if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2560           reportError(std::move(E), getFileNameForError(C, I), Filename);
2561         continue;
2562       }
2563       if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2564         if (!checkMachOAndArchFlags(O, Filename))
2565           return;
2566         ProcessMachO(Filename, O, O->getFileName());
2567       }
2568     }
2569     if (Err)
2570       reportError(std::move(Err), Filename);
2571     return;
2572   }
2573   if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
2574     parseInputMachO(UB);
2575     return;
2576   }
2577   if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
2578     if (!checkMachOAndArchFlags(O, Filename))
2579       return;
2580     if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O))
2581       ProcessMachO(Filename, MachOOF);
2582     else
2583       WithColor::error(errs(), "llvm-objdump")
2584           << Filename << "': "
2585           << "object is not a Mach-O file type.\n";
2586     return;
2587   }
2588   llvm_unreachable("Input object can't be invalid at this point");
2589 }
2590 
2591 void objdump::parseInputMachO(MachOUniversalBinary *UB) {
2592   if (!ValidateArchFlags())
2593     return;
2594 
2595   auto Filename = UB->getFileName();
2596 
2597   if (UniversalHeaders)
2598     printMachOUniversalHeaders(UB, Verbose);
2599 
2600   // If we have a list of architecture flags specified dump only those.
2601   if (!ArchAll && !ArchFlags.empty()) {
2602     // Look for a slice in the universal binary that matches each ArchFlag.
2603     bool ArchFound;
2604     for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2605       ArchFound = false;
2606       for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2607                                                   E = UB->end_objects();
2608             I != E; ++I) {
2609         if (ArchFlags[i] == I->getArchFlagName()) {
2610           ArchFound = true;
2611           Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
2612               I->getAsObjectFile();
2613           std::string ArchitectureName;
2614           if (ArchFlags.size() > 1)
2615             ArchitectureName = I->getArchFlagName();
2616           if (ObjOrErr) {
2617             ObjectFile &O = *ObjOrErr.get();
2618             if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2619               ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2620           } else if (Error E = isNotObjectErrorInvalidFileType(
2621                          ObjOrErr.takeError())) {
2622             reportError(std::move(E), "", Filename, ArchitectureName);
2623             continue;
2624           } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2625                          I->getAsArchive()) {
2626             std::unique_ptr<Archive> &A = *AOrErr;
2627             outs() << "Archive : " << Filename;
2628             if (!ArchitectureName.empty())
2629               outs() << " (architecture " << ArchitectureName << ")";
2630             outs() << "\n";
2631             if (ArchiveHeaders)
2632               printArchiveHeaders(Filename, A.get(), Verbose,
2633                                   ArchiveMemberOffsets, ArchitectureName);
2634             Error Err = Error::success();
2635             unsigned I = -1;
2636             for (auto &C : A->children(Err)) {
2637               ++I;
2638               Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2639               if (!ChildOrErr) {
2640                 if (Error E =
2641                         isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2642                   reportError(std::move(E), getFileNameForError(C, I), Filename,
2643                               ArchitectureName);
2644                 continue;
2645               }
2646               if (MachOObjectFile *O =
2647                       dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2648                 ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
2649             }
2650             if (Err)
2651               reportError(std::move(Err), Filename);
2652           } else {
2653             consumeError(AOrErr.takeError());
2654             reportError(Filename,
2655                         "Mach-O universal file for architecture " +
2656                             StringRef(I->getArchFlagName()) +
2657                             " is not a Mach-O file or an archive file");
2658           }
2659         }
2660       }
2661       if (!ArchFound) {
2662         WithColor::error(errs(), "llvm-objdump")
2663             << "file: " + Filename + " does not contain "
2664             << "architecture: " + ArchFlags[i] + "\n";
2665         return;
2666       }
2667     }
2668     return;
2669   }
2670   // No architecture flags were specified so if this contains a slice that
2671   // matches the host architecture dump only that.
2672   if (!ArchAll) {
2673     for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2674                                                 E = UB->end_objects();
2675           I != E; ++I) {
2676       if (MachOObjectFile::getHostArch().getArchName() ==
2677           I->getArchFlagName()) {
2678         Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2679         std::string ArchiveName;
2680         ArchiveName.clear();
2681         if (ObjOrErr) {
2682           ObjectFile &O = *ObjOrErr.get();
2683           if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2684             ProcessMachO(Filename, MachOOF);
2685         } else if (Error E =
2686                        isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2687           reportError(std::move(E), Filename);
2688         } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2689                        I->getAsArchive()) {
2690           std::unique_ptr<Archive> &A = *AOrErr;
2691           outs() << "Archive : " << Filename << "\n";
2692           if (ArchiveHeaders)
2693             printArchiveHeaders(Filename, A.get(), Verbose,
2694                                 ArchiveMemberOffsets);
2695           Error Err = Error::success();
2696           unsigned I = -1;
2697           for (auto &C : A->children(Err)) {
2698             ++I;
2699             Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2700             if (!ChildOrErr) {
2701               if (Error E =
2702                       isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2703                 reportError(std::move(E), getFileNameForError(C, I), Filename);
2704               continue;
2705             }
2706             if (MachOObjectFile *O =
2707                     dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2708               ProcessMachO(Filename, O, O->getFileName());
2709           }
2710           if (Err)
2711             reportError(std::move(Err), Filename);
2712         } else {
2713           consumeError(AOrErr.takeError());
2714           reportError(Filename, "Mach-O universal file for architecture " +
2715                                     StringRef(I->getArchFlagName()) +
2716                                     " is not a Mach-O file or an archive file");
2717         }
2718         return;
2719       }
2720     }
2721   }
2722   // Either all architectures have been specified or none have been specified
2723   // and this does not contain the host architecture so dump all the slices.
2724   bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2725   for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2726                                               E = UB->end_objects();
2727         I != E; ++I) {
2728     Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2729     std::string ArchitectureName;
2730     if (moreThanOneArch)
2731       ArchitectureName = I->getArchFlagName();
2732     if (ObjOrErr) {
2733       ObjectFile &Obj = *ObjOrErr.get();
2734       if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
2735         ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2736     } else if (Error E =
2737                    isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2738       reportError(std::move(E), Filename, "", ArchitectureName);
2739     } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
2740       std::unique_ptr<Archive> &A = *AOrErr;
2741       outs() << "Archive : " << Filename;
2742       if (!ArchitectureName.empty())
2743         outs() << " (architecture " << ArchitectureName << ")";
2744       outs() << "\n";
2745       if (ArchiveHeaders)
2746         printArchiveHeaders(Filename, A.get(), Verbose, ArchiveMemberOffsets,
2747                             ArchitectureName);
2748       Error Err = Error::success();
2749       unsigned I = -1;
2750       for (auto &C : A->children(Err)) {
2751         ++I;
2752         Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2753         if (!ChildOrErr) {
2754           if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2755             reportError(std::move(E), getFileNameForError(C, I), Filename,
2756                         ArchitectureName);
2757           continue;
2758         }
2759         if (MachOObjectFile *O =
2760                 dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2761           if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
2762             ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
2763                           ArchitectureName);
2764         }
2765       }
2766       if (Err)
2767         reportError(std::move(Err), Filename);
2768     } else {
2769       consumeError(AOrErr.takeError());
2770       reportError(Filename, "Mach-O universal file for architecture " +
2771                                 StringRef(I->getArchFlagName()) +
2772                                 " is not a Mach-O file or an archive file");
2773     }
2774   }
2775 }
2776 
2777 namespace {
2778 // The block of info used by the Symbolizer call backs.
2779 struct DisassembleInfo {
2780   DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap,
2781                   std::vector<SectionRef> *Sections, bool verbose)
2782     : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}
2783   bool verbose;
2784   MachOObjectFile *O;
2785   SectionRef S;
2786   SymbolAddressMap *AddrMap;
2787   std::vector<SectionRef> *Sections;
2788   const char *class_name = nullptr;
2789   const char *selector_name = nullptr;
2790   std::unique_ptr<char[]> method = nullptr;
2791   char *demangled_name = nullptr;
2792   uint64_t adrp_addr = 0;
2793   uint32_t adrp_inst = 0;
2794   std::unique_ptr<SymbolAddressMap> bindtable;
2795   uint32_t depth = 0;
2796 };
2797 } // namespace
2798 
2799 // SymbolizerGetOpInfo() is the operand information call back function.
2800 // This is called to get the symbolic information for operand(s) of an
2801 // instruction when it is being done.  This routine does this from
2802 // the relocation information, symbol table, etc. That block of information
2803 // is a pointer to the struct DisassembleInfo that was passed when the
2804 // disassembler context was created and passed to back to here when
2805 // called back by the disassembler for instruction operands that could have
2806 // relocation information. The address of the instruction containing operand is
2807 // at the Pc parameter.  The immediate value the operand has is passed in
2808 // op_info->Value and is at Offset past the start of the instruction and has a
2809 // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
2810 // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
2811 // names and addends of the symbolic expression to add for the operand.  The
2812 // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
2813 // information is returned then this function returns 1 else it returns 0.
2814 static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
2815                                uint64_t OpSize, uint64_t InstSize, int TagType,
2816                                void *TagBuf) {
2817   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
2818   struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
2819   uint64_t value = op_info->Value;
2820 
2821   // Make sure all fields returned are zero if we don't set them.
2822   memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
2823   op_info->Value = value;
2824 
2825   // If the TagType is not the value 1 which it code knows about or if no
2826   // verbose symbolic information is wanted then just return 0, indicating no
2827   // information is being returned.
2828   if (TagType != 1 || !info->verbose)
2829     return 0;
2830 
2831   unsigned int Arch = info->O->getArch();
2832   if (Arch == Triple::x86) {
2833     if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0)
2834       return 0;
2835     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2836       // TODO:
2837       // Search the external relocation entries of a fully linked image
2838       // (if any) for an entry that matches this segment offset.
2839       // uint32_t seg_offset = (Pc + Offset);
2840       return 0;
2841     }
2842     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2843     // for an entry for this section offset.
2844     uint32_t sect_addr = info->S.getAddress();
2845     uint32_t sect_offset = (Pc + Offset) - sect_addr;
2846     bool reloc_found = false;
2847     DataRefImpl Rel;
2848     MachO::any_relocation_info RE;
2849     bool isExtern = false;
2850     SymbolRef Symbol;
2851     bool r_scattered = false;
2852     uint32_t r_value, pair_r_value, r_type;
2853     for (const RelocationRef &Reloc : info->S.relocations()) {
2854       uint64_t RelocOffset = Reloc.getOffset();
2855       if (RelocOffset == sect_offset) {
2856         Rel = Reloc.getRawDataRefImpl();
2857         RE = info->O->getRelocation(Rel);
2858         r_type = info->O->getAnyRelocationType(RE);
2859         r_scattered = info->O->isRelocationScattered(RE);
2860         if (r_scattered) {
2861           r_value = info->O->getScatteredRelocationValue(RE);
2862           if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2863               r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
2864             DataRefImpl RelNext = Rel;
2865             info->O->moveRelocationNext(RelNext);
2866             MachO::any_relocation_info RENext;
2867             RENext = info->O->getRelocation(RelNext);
2868             if (info->O->isRelocationScattered(RENext))
2869               pair_r_value = info->O->getScatteredRelocationValue(RENext);
2870             else
2871               return 0;
2872           }
2873         } else {
2874           isExtern = info->O->getPlainRelocationExternal(RE);
2875           if (isExtern) {
2876             symbol_iterator RelocSym = Reloc.getSymbol();
2877             Symbol = *RelocSym;
2878           }
2879         }
2880         reloc_found = true;
2881         break;
2882       }
2883     }
2884     if (reloc_found && isExtern) {
2885       op_info->AddSymbol.Present = 1;
2886       op_info->AddSymbol.Name =
2887           unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2888       // For i386 extern relocation entries the value in the instruction is
2889       // the offset from the symbol, and value is already set in op_info->Value.
2890       return 1;
2891     }
2892     if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2893                         r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
2894       const char *add = GuessSymbolName(r_value, info->AddrMap);
2895       const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2896       uint32_t offset = value - (r_value - pair_r_value);
2897       op_info->AddSymbol.Present = 1;
2898       if (add != nullptr)
2899         op_info->AddSymbol.Name = add;
2900       else
2901         op_info->AddSymbol.Value = r_value;
2902       op_info->SubtractSymbol.Present = 1;
2903       if (sub != nullptr)
2904         op_info->SubtractSymbol.Name = sub;
2905       else
2906         op_info->SubtractSymbol.Value = pair_r_value;
2907       op_info->Value = offset;
2908       return 1;
2909     }
2910     return 0;
2911   }
2912   if (Arch == Triple::x86_64) {
2913     if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0)
2914       return 0;
2915     // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external
2916     // relocation entries of a linked image (if any) for an entry that matches
2917     // this segment offset.
2918     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2919       uint64_t seg_offset = Pc + Offset;
2920       bool reloc_found = false;
2921       DataRefImpl Rel;
2922       MachO::any_relocation_info RE;
2923       bool isExtern = false;
2924       SymbolRef Symbol;
2925       for (const RelocationRef &Reloc : info->O->external_relocations()) {
2926         uint64_t RelocOffset = Reloc.getOffset();
2927         if (RelocOffset == seg_offset) {
2928           Rel = Reloc.getRawDataRefImpl();
2929           RE = info->O->getRelocation(Rel);
2930           // external relocation entries should always be external.
2931           isExtern = info->O->getPlainRelocationExternal(RE);
2932           if (isExtern) {
2933             symbol_iterator RelocSym = Reloc.getSymbol();
2934             Symbol = *RelocSym;
2935           }
2936           reloc_found = true;
2937           break;
2938         }
2939       }
2940       if (reloc_found && isExtern) {
2941         // The Value passed in will be adjusted by the Pc if the instruction
2942         // adds the Pc.  But for x86_64 external relocation entries the Value
2943         // is the offset from the external symbol.
2944         if (info->O->getAnyRelocationPCRel(RE))
2945           op_info->Value -= Pc + InstSize;
2946         const char *name =
2947             unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2948         op_info->AddSymbol.Present = 1;
2949         op_info->AddSymbol.Name = name;
2950         return 1;
2951       }
2952       return 0;
2953     }
2954     // In MH_OBJECT filetypes search the section's relocation entries (if any)
2955     // for an entry for this section offset.
2956     uint64_t sect_addr = info->S.getAddress();
2957     uint64_t sect_offset = (Pc + Offset) - sect_addr;
2958     bool reloc_found = false;
2959     DataRefImpl Rel;
2960     MachO::any_relocation_info RE;
2961     bool isExtern = false;
2962     SymbolRef Symbol;
2963     for (const RelocationRef &Reloc : info->S.relocations()) {
2964       uint64_t RelocOffset = Reloc.getOffset();
2965       if (RelocOffset == sect_offset) {
2966         Rel = Reloc.getRawDataRefImpl();
2967         RE = info->O->getRelocation(Rel);
2968         // NOTE: Scattered relocations don't exist on x86_64.
2969         isExtern = info->O->getPlainRelocationExternal(RE);
2970         if (isExtern) {
2971           symbol_iterator RelocSym = Reloc.getSymbol();
2972           Symbol = *RelocSym;
2973         }
2974         reloc_found = true;
2975         break;
2976       }
2977     }
2978     if (reloc_found && isExtern) {
2979       // The Value passed in will be adjusted by the Pc if the instruction
2980       // adds the Pc.  But for x86_64 external relocation entries the Value
2981       // is the offset from the external symbol.
2982       if (info->O->getAnyRelocationPCRel(RE))
2983         op_info->Value -= Pc + InstSize;
2984       const char *name =
2985           unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2986       unsigned Type = info->O->getAnyRelocationType(RE);
2987       if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
2988         DataRefImpl RelNext = Rel;
2989         info->O->moveRelocationNext(RelNext);
2990         MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2991         unsigned TypeNext = info->O->getAnyRelocationType(RENext);
2992         bool isExternNext = info->O->getPlainRelocationExternal(RENext);
2993         unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
2994         if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
2995           op_info->SubtractSymbol.Present = 1;
2996           op_info->SubtractSymbol.Name = name;
2997           symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
2998           Symbol = *RelocSymNext;
2999           name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
3000         }
3001       }
3002       // TODO: add the VariantKinds to op_info->VariantKind for relocation types
3003       // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
3004       op_info->AddSymbol.Present = 1;
3005       op_info->AddSymbol.Name = name;
3006       return 1;
3007     }
3008     return 0;
3009   }
3010   if (Arch == Triple::arm) {
3011     if (Offset != 0 || (InstSize != 4 && InstSize != 2))
3012       return 0;
3013     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
3014       // TODO:
3015       // Search the external relocation entries of a fully linked image
3016       // (if any) for an entry that matches this segment offset.
3017       // uint32_t seg_offset = (Pc + Offset);
3018       return 0;
3019     }
3020     // In MH_OBJECT filetypes search the section's relocation entries (if any)
3021     // for an entry for this section offset.
3022     uint32_t sect_addr = info->S.getAddress();
3023     uint32_t sect_offset = (Pc + Offset) - sect_addr;
3024     DataRefImpl Rel;
3025     MachO::any_relocation_info RE;
3026     bool isExtern = false;
3027     SymbolRef Symbol;
3028     bool r_scattered = false;
3029     uint32_t r_value, pair_r_value, r_type, r_length, other_half;
3030     auto Reloc =
3031         find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
3032           uint64_t RelocOffset = Reloc.getOffset();
3033           return RelocOffset == sect_offset;
3034         });
3035 
3036     if (Reloc == info->S.relocations().end())
3037       return 0;
3038 
3039     Rel = Reloc->getRawDataRefImpl();
3040     RE = info->O->getRelocation(Rel);
3041     r_length = info->O->getAnyRelocationLength(RE);
3042     r_scattered = info->O->isRelocationScattered(RE);
3043     if (r_scattered) {
3044       r_value = info->O->getScatteredRelocationValue(RE);
3045       r_type = info->O->getScatteredRelocationType(RE);
3046     } else {
3047       r_type = info->O->getAnyRelocationType(RE);
3048       isExtern = info->O->getPlainRelocationExternal(RE);
3049       if (isExtern) {
3050         symbol_iterator RelocSym = Reloc->getSymbol();
3051         Symbol = *RelocSym;
3052       }
3053     }
3054     if (r_type == MachO::ARM_RELOC_HALF ||
3055         r_type == MachO::ARM_RELOC_SECTDIFF ||
3056         r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
3057         r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3058       DataRefImpl RelNext = Rel;
3059       info->O->moveRelocationNext(RelNext);
3060       MachO::any_relocation_info RENext;
3061       RENext = info->O->getRelocation(RelNext);
3062       other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
3063       if (info->O->isRelocationScattered(RENext))
3064         pair_r_value = info->O->getScatteredRelocationValue(RENext);
3065     }
3066 
3067     if (isExtern) {
3068       const char *name =
3069           unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
3070       op_info->AddSymbol.Present = 1;
3071       op_info->AddSymbol.Name = name;
3072       switch (r_type) {
3073       case MachO::ARM_RELOC_HALF:
3074         if ((r_length & 0x1) == 1) {
3075           op_info->Value = value << 16 | other_half;
3076           op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3077         } else {
3078           op_info->Value = other_half << 16 | value;
3079           op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3080         }
3081         break;
3082       default:
3083         break;
3084       }
3085       return 1;
3086     }
3087     // If we have a branch that is not an external relocation entry then
3088     // return 0 so the code in tryAddingSymbolicOperand() can use the
3089     // SymbolLookUp call back with the branch target address to look up the
3090     // symbol and possibility add an annotation for a symbol stub.
3091     if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
3092                           r_type == MachO::ARM_THUMB_RELOC_BR22))
3093       return 0;
3094 
3095     uint32_t offset = 0;
3096     if (r_type == MachO::ARM_RELOC_HALF ||
3097         r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3098       if ((r_length & 0x1) == 1)
3099         value = value << 16 | other_half;
3100       else
3101         value = other_half << 16 | value;
3102     }
3103     if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
3104                         r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
3105       offset = value - r_value;
3106       value = r_value;
3107     }
3108 
3109     if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3110       if ((r_length & 0x1) == 1)
3111         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3112       else
3113         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3114       const char *add = GuessSymbolName(r_value, info->AddrMap);
3115       const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
3116       int32_t offset = value - (r_value - pair_r_value);
3117       op_info->AddSymbol.Present = 1;
3118       if (add != nullptr)
3119         op_info->AddSymbol.Name = add;
3120       else
3121         op_info->AddSymbol.Value = r_value;
3122       op_info->SubtractSymbol.Present = 1;
3123       if (sub != nullptr)
3124         op_info->SubtractSymbol.Name = sub;
3125       else
3126         op_info->SubtractSymbol.Value = pair_r_value;
3127       op_info->Value = offset;
3128       return 1;
3129     }
3130 
3131     op_info->AddSymbol.Present = 1;
3132     op_info->Value = offset;
3133     if (r_type == MachO::ARM_RELOC_HALF) {
3134       if ((r_length & 0x1) == 1)
3135         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3136       else
3137         op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3138     }
3139     const char *add = GuessSymbolName(value, info->AddrMap);
3140     if (add != nullptr) {
3141       op_info->AddSymbol.Name = add;
3142       return 1;
3143     }
3144     op_info->AddSymbol.Value = value;
3145     return 1;
3146   }
3147   if (Arch == Triple::aarch64) {
3148     if (Offset != 0 || InstSize != 4)
3149       return 0;
3150     if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
3151       // TODO:
3152       // Search the external relocation entries of a fully linked image
3153       // (if any) for an entry that matches this segment offset.
3154       // uint64_t seg_offset = (Pc + Offset);
3155       return 0;
3156     }
3157     // In MH_OBJECT filetypes search the section's relocation entries (if any)
3158     // for an entry for this section offset.
3159     uint64_t sect_addr = info->S.getAddress();
3160     uint64_t sect_offset = (Pc + Offset) - sect_addr;
3161     auto Reloc =
3162         find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
3163           uint64_t RelocOffset = Reloc.getOffset();
3164           return RelocOffset == sect_offset;
3165         });
3166 
3167     if (Reloc == info->S.relocations().end())
3168       return 0;
3169 
3170     DataRefImpl Rel = Reloc->getRawDataRefImpl();
3171     MachO::any_relocation_info RE = info->O->getRelocation(Rel);
3172     uint32_t r_type = info->O->getAnyRelocationType(RE);
3173     if (r_type == MachO::ARM64_RELOC_ADDEND) {
3174       DataRefImpl RelNext = Rel;
3175       info->O->moveRelocationNext(RelNext);
3176       MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
3177       if (value == 0) {
3178         value = info->O->getPlainRelocationSymbolNum(RENext);
3179         op_info->Value = value;
3180       }
3181     }
3182     // NOTE: Scattered relocations don't exist on arm64.
3183     if (!info->O->getPlainRelocationExternal(RE))
3184       return 0;
3185     const char *name =
3186         unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName())
3187             .data();
3188     op_info->AddSymbol.Present = 1;
3189     op_info->AddSymbol.Name = name;
3190 
3191     switch (r_type) {
3192     case MachO::ARM64_RELOC_PAGE21:
3193       /* @page */
3194       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
3195       break;
3196     case MachO::ARM64_RELOC_PAGEOFF12:
3197       /* @pageoff */
3198       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
3199       break;
3200     case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
3201       /* @gotpage */
3202       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
3203       break;
3204     case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
3205       /* @gotpageoff */
3206       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
3207       break;
3208     case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
3209       /* @tvlppage is not implemented in llvm-mc */
3210       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
3211       break;
3212     case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
3213       /* @tvlppageoff is not implemented in llvm-mc */
3214       op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
3215       break;
3216     default:
3217     case MachO::ARM64_RELOC_BRANCH26:
3218       op_info->VariantKind = LLVMDisassembler_VariantKind_None;
3219       break;
3220     }
3221     return 1;
3222   }
3223   return 0;
3224 }
3225 
3226 // GuessCstringPointer is passed the address of what might be a pointer to a
3227 // literal string in a cstring section.  If that address is in a cstring section
3228 // it returns a pointer to that string.  Else it returns nullptr.
3229 static const char *GuessCstringPointer(uint64_t ReferenceValue,
3230                                        struct DisassembleInfo *info) {
3231   for (const auto &Load : info->O->load_commands()) {
3232     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3233       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3234       for (unsigned J = 0; J < Seg.nsects; ++J) {
3235         MachO::section_64 Sec = info->O->getSection64(Load, J);
3236         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3237         if (section_type == MachO::S_CSTRING_LITERALS &&
3238             ReferenceValue >= Sec.addr &&
3239             ReferenceValue < Sec.addr + Sec.size) {
3240           uint64_t sect_offset = ReferenceValue - Sec.addr;
3241           uint64_t object_offset = Sec.offset + sect_offset;
3242           StringRef MachOContents = info->O->getData();
3243           uint64_t object_size = MachOContents.size();
3244           const char *object_addr = (const char *)MachOContents.data();
3245           if (object_offset < object_size) {
3246             const char *name = object_addr + object_offset;
3247             return name;
3248           } else {
3249             return nullptr;
3250           }
3251         }
3252       }
3253     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
3254       MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
3255       for (unsigned J = 0; J < Seg.nsects; ++J) {
3256         MachO::section Sec = info->O->getSection(Load, J);
3257         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3258         if (section_type == MachO::S_CSTRING_LITERALS &&
3259             ReferenceValue >= Sec.addr &&
3260             ReferenceValue < Sec.addr + Sec.size) {
3261           uint64_t sect_offset = ReferenceValue - Sec.addr;
3262           uint64_t object_offset = Sec.offset + sect_offset;
3263           StringRef MachOContents = info->O->getData();
3264           uint64_t object_size = MachOContents.size();
3265           const char *object_addr = (const char *)MachOContents.data();
3266           if (object_offset < object_size) {
3267             const char *name = object_addr + object_offset;
3268             return name;
3269           } else {
3270             return nullptr;
3271           }
3272         }
3273       }
3274     }
3275   }
3276   return nullptr;
3277 }
3278 
3279 // GuessIndirectSymbol returns the name of the indirect symbol for the
3280 // ReferenceValue passed in or nullptr.  This is used when ReferenceValue maybe
3281 // an address of a symbol stub or a lazy or non-lazy pointer to associate the
3282 // symbol name being referenced by the stub or pointer.
3283 static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
3284                                        struct DisassembleInfo *info) {
3285   MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
3286   MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
3287   for (const auto &Load : info->O->load_commands()) {
3288     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3289       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3290       for (unsigned J = 0; J < Seg.nsects; ++J) {
3291         MachO::section_64 Sec = info->O->getSection64(Load, J);
3292         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3293         if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
3294              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
3295              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
3296              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
3297              section_type == MachO::S_SYMBOL_STUBS) &&
3298             ReferenceValue >= Sec.addr &&
3299             ReferenceValue < Sec.addr + Sec.size) {
3300           uint32_t stride;
3301           if (section_type == MachO::S_SYMBOL_STUBS)
3302             stride = Sec.reserved2;
3303           else
3304             stride = 8;
3305           if (stride == 0)
3306             return nullptr;
3307           uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
3308           if (index < Dysymtab.nindirectsyms) {
3309             uint32_t indirect_symbol =
3310                 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
3311             if (indirect_symbol < Symtab.nsyms) {
3312               symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
3313               return unwrapOrError(Sym->getName(), info->O->getFileName())
3314                   .data();
3315             }
3316           }
3317         }
3318       }
3319     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
3320       MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
3321       for (unsigned J = 0; J < Seg.nsects; ++J) {
3322         MachO::section Sec = info->O->getSection(Load, J);
3323         uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3324         if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
3325              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
3326              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
3327              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
3328              section_type == MachO::S_SYMBOL_STUBS) &&
3329             ReferenceValue >= Sec.addr &&
3330             ReferenceValue < Sec.addr + Sec.size) {
3331           uint32_t stride;
3332           if (section_type == MachO::S_SYMBOL_STUBS)
3333             stride = Sec.reserved2;
3334           else
3335             stride = 4;
3336           if (stride == 0)
3337             return nullptr;
3338           uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
3339           if (index < Dysymtab.nindirectsyms) {
3340             uint32_t indirect_symbol =
3341                 info->O->getIndirectSymbolTableEntry(Dysymtab, index);
3342             if (indirect_symbol < Symtab.nsyms) {
3343               symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
3344               return unwrapOrError(Sym->getName(), info->O->getFileName())
3345                   .data();
3346             }
3347           }
3348         }
3349       }
3350     }
3351   }
3352   return nullptr;
3353 }
3354 
3355 // method_reference() is called passing it the ReferenceName that might be
3356 // a reference it to an Objective-C method call.  If so then it allocates and
3357 // assembles a method call string with the values last seen and saved in
3358 // the DisassembleInfo's class_name and selector_name fields.  This is saved
3359 // into the method field of the info and any previous string is free'ed.
3360 // Then the class_name field in the info is set to nullptr.  The method call
3361 // string is set into ReferenceName and ReferenceType is set to
3362 // LLVMDisassembler_ReferenceType_Out_Objc_Message.  If this not a method call
3363 // then both ReferenceType and ReferenceName are left unchanged.
3364 static void method_reference(struct DisassembleInfo *info,
3365                              uint64_t *ReferenceType,
3366                              const char **ReferenceName) {
3367   unsigned int Arch = info->O->getArch();
3368   if (*ReferenceName != nullptr) {
3369     if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
3370       if (info->selector_name != nullptr) {
3371         if (info->class_name != nullptr) {
3372           info->method = std::make_unique<char[]>(
3373               5 + strlen(info->class_name) + strlen(info->selector_name));
3374           char *method = info->method.get();
3375           if (method != nullptr) {
3376             strcpy(method, "+[");
3377             strcat(method, info->class_name);
3378             strcat(method, " ");
3379             strcat(method, info->selector_name);
3380             strcat(method, "]");
3381             *ReferenceName = method;
3382             *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3383           }
3384         } else {
3385           info->method =
3386               std::make_unique<char[]>(9 + strlen(info->selector_name));
3387           char *method = info->method.get();
3388           if (method != nullptr) {
3389             if (Arch == Triple::x86_64)
3390               strcpy(method, "-[%rdi ");
3391             else if (Arch == Triple::aarch64)
3392               strcpy(method, "-[x0 ");
3393             else
3394               strcpy(method, "-[r? ");
3395             strcat(method, info->selector_name);
3396             strcat(method, "]");
3397             *ReferenceName = method;
3398             *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3399           }
3400         }
3401         info->class_name = nullptr;
3402       }
3403     } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
3404       if (info->selector_name != nullptr) {
3405         info->method =
3406             std::make_unique<char[]>(17 + strlen(info->selector_name));
3407         char *method = info->method.get();
3408         if (method != nullptr) {
3409           if (Arch == Triple::x86_64)
3410             strcpy(method, "-[[%rdi super] ");
3411           else if (Arch == Triple::aarch64)
3412             strcpy(method, "-[[x0 super] ");
3413           else
3414             strcpy(method, "-[[r? super] ");
3415           strcat(method, info->selector_name);
3416           strcat(method, "]");
3417           *ReferenceName = method;
3418           *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3419         }
3420         info->class_name = nullptr;
3421       }
3422     }
3423   }
3424 }
3425 
3426 // GuessPointerPointer() is passed the address of what might be a pointer to
3427 // a reference to an Objective-C class, selector, message ref or cfstring.
3428 // If so the value of the pointer is returned and one of the booleans are set
3429 // to true.  If not zero is returned and all the booleans are set to false.
3430 static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
3431                                     struct DisassembleInfo *info,
3432                                     bool &classref, bool &selref, bool &msgref,
3433                                     bool &cfstring) {
3434   classref = false;
3435   selref = false;
3436   msgref = false;
3437   cfstring = false;
3438   for (const auto &Load : info->O->load_commands()) {
3439     if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3440       MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3441       for (unsigned J = 0; J < Seg.nsects; ++J) {
3442         MachO::section_64 Sec = info->O->getSection64(Load, J);
3443         if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
3444              strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
3445              strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
3446              strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
3447              strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
3448             ReferenceValue >= Sec.addr &&
3449             ReferenceValue < Sec.addr + Sec.size) {
3450           uint64_t sect_offset = ReferenceValue - Sec.addr;
3451           uint64_t object_offset = Sec.offset + sect_offset;
3452           StringRef MachOContents = info->O->getData();
3453           uint64_t object_size = MachOContents.size();
3454           const char *object_addr = (const char *)MachOContents.data();
3455           if (object_offset < object_size) {
3456             uint64_t pointer_value;
3457             memcpy(&pointer_value, object_addr + object_offset,
3458                    sizeof(uint64_t));
3459             if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3460               sys::swapByteOrder(pointer_value);
3461             if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
3462               selref = true;
3463             else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
3464                      strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
3465               classref = true;
3466             else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
3467                      ReferenceValue + 8 < Sec.addr + Sec.size) {
3468               msgref = true;
3469               memcpy(&pointer_value, object_addr + object_offset + 8,
3470                      sizeof(uint64_t));
3471               if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3472                 sys::swapByteOrder(pointer_value);
3473             } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
3474               cfstring = true;
3475             return pointer_value;
3476           } else {
3477             return 0;
3478           }
3479         }
3480       }
3481     }
3482     // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
3483   }
3484   return 0;
3485 }
3486 
3487 // get_pointer_64 returns a pointer to the bytes in the object file at the
3488 // Address from a section in the Mach-O file.  And indirectly returns the
3489 // offset into the section, number of bytes left in the section past the offset
3490 // and which section is was being referenced.  If the Address is not in a
3491 // section nullptr is returned.
3492 static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
3493                                   uint32_t &left, SectionRef &S,
3494                                   DisassembleInfo *info,
3495                                   bool objc_only = false) {
3496   offset = 0;
3497   left = 0;
3498   S = SectionRef();
3499   for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
3500     uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
3501     uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
3502     if (SectSize == 0)
3503       continue;
3504     if (objc_only) {
3505       StringRef SectName;
3506       Expected<StringRef> SecNameOrErr =
3507           ((*(info->Sections))[SectIdx]).getName();
3508       if (SecNameOrErr)
3509         SectName = *SecNameOrErr;
3510       else
3511         consumeError(SecNameOrErr.takeError());
3512 
3513       DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
3514       StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
3515       if (SegName != "__OBJC" && SectName != "__cstring")
3516         continue;
3517     }
3518     if (Address >= SectAddress && Address < SectAddress + SectSize) {
3519       S = (*(info->Sections))[SectIdx];
3520       offset = Address - SectAddress;
3521       left = SectSize - offset;
3522       StringRef SectContents = unwrapOrError(
3523           ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName());
3524       return SectContents.data() + offset;
3525     }
3526   }
3527   return nullptr;
3528 }
3529 
3530 static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
3531                                   uint32_t &left, SectionRef &S,
3532                                   DisassembleInfo *info,
3533                                   bool objc_only = false) {
3534   return get_pointer_64(Address, offset, left, S, info, objc_only);
3535 }
3536 
3537 // get_symbol_64() returns the name of a symbol (or nullptr) and the address of
3538 // the symbol indirectly through n_value. Based on the relocation information
3539 // for the specified section offset in the specified section reference.
3540 // If no relocation information is found and a non-zero ReferenceValue for the
3541 // symbol is passed, look up that address in the info's AddrMap.
3542 static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
3543                                  DisassembleInfo *info, uint64_t &n_value,
3544                                  uint64_t ReferenceValue = 0) {
3545   n_value = 0;
3546   if (!info->verbose)
3547     return nullptr;
3548 
3549   // See if there is an external relocation entry at the sect_offset.
3550   bool reloc_found = false;
3551   DataRefImpl Rel;
3552   MachO::any_relocation_info RE;
3553   bool isExtern = false;
3554   SymbolRef Symbol;
3555   for (const RelocationRef &Reloc : S.relocations()) {
3556     uint64_t RelocOffset = Reloc.getOffset();
3557     if (RelocOffset == sect_offset) {
3558       Rel = Reloc.getRawDataRefImpl();
3559       RE = info->O->getRelocation(Rel);
3560       if (info->O->isRelocationScattered(RE))
3561         continue;
3562       isExtern = info->O->getPlainRelocationExternal(RE);
3563       if (isExtern) {
3564         symbol_iterator RelocSym = Reloc.getSymbol();
3565         Symbol = *RelocSym;
3566       }
3567       reloc_found = true;
3568       break;
3569     }
3570   }
3571   // If there is an external relocation entry for a symbol in this section
3572   // at this section_offset then use that symbol's value for the n_value
3573   // and return its name.
3574   const char *SymbolName = nullptr;
3575   if (reloc_found && isExtern) {
3576     n_value = cantFail(Symbol.getValue());
3577     StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName());
3578     if (!Name.empty()) {
3579       SymbolName = Name.data();
3580       return SymbolName;
3581     }
3582   }
3583 
3584   // TODO: For fully linked images, look through the external relocation
3585   // entries off the dynamic symtab command. For these the r_offset is from the
3586   // start of the first writeable segment in the Mach-O file.  So the offset
3587   // to this section from that segment is passed to this routine by the caller,
3588   // as the database_offset. Which is the difference of the section's starting
3589   // address and the first writable segment.
3590   //
3591   // NOTE: need add passing the database_offset to this routine.
3592 
3593   // We did not find an external relocation entry so look up the ReferenceValue
3594   // as an address of a symbol and if found return that symbol's name.
3595   SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
3596 
3597   return SymbolName;
3598 }
3599 
3600 static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
3601                                  DisassembleInfo *info,
3602                                  uint32_t ReferenceValue) {
3603   uint64_t n_value64;
3604   return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
3605 }
3606 
3607 namespace {
3608 
3609 // These are structs in the Objective-C meta data and read to produce the
3610 // comments for disassembly.  While these are part of the ABI they are no
3611 // public defintions.  So the are here not in include/llvm/BinaryFormat/MachO.h
3612 // .
3613 
3614 // The cfstring object in a 64-bit Mach-O file.
3615 struct cfstring64_t {
3616   uint64_t isa;        // class64_t * (64-bit pointer)
3617   uint64_t flags;      // flag bits
3618   uint64_t characters; // char * (64-bit pointer)
3619   uint64_t length;     // number of non-NULL characters in above
3620 };
3621 
3622 // The class object in a 64-bit Mach-O file.
3623 struct class64_t {
3624   uint64_t isa;        // class64_t * (64-bit pointer)
3625   uint64_t superclass; // class64_t * (64-bit pointer)
3626   uint64_t cache;      // Cache (64-bit pointer)
3627   uint64_t vtable;     // IMP * (64-bit pointer)
3628   uint64_t data;       // class_ro64_t * (64-bit pointer)
3629 };
3630 
3631 struct class32_t {
3632   uint32_t isa;        /* class32_t * (32-bit pointer) */
3633   uint32_t superclass; /* class32_t * (32-bit pointer) */
3634   uint32_t cache;      /* Cache (32-bit pointer) */
3635   uint32_t vtable;     /* IMP * (32-bit pointer) */
3636   uint32_t data;       /* class_ro32_t * (32-bit pointer) */
3637 };
3638 
3639 struct class_ro64_t {
3640   uint32_t flags;
3641   uint32_t instanceStart;
3642   uint32_t instanceSize;
3643   uint32_t reserved;
3644   uint64_t ivarLayout;     // const uint8_t * (64-bit pointer)
3645   uint64_t name;           // const char * (64-bit pointer)
3646   uint64_t baseMethods;    // const method_list_t * (64-bit pointer)
3647   uint64_t baseProtocols;  // const protocol_list_t * (64-bit pointer)
3648   uint64_t ivars;          // const ivar_list_t * (64-bit pointer)
3649   uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
3650   uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
3651 };
3652 
3653 struct class_ro32_t {
3654   uint32_t flags;
3655   uint32_t instanceStart;
3656   uint32_t instanceSize;
3657   uint32_t ivarLayout;     /* const uint8_t * (32-bit pointer) */
3658   uint32_t name;           /* const char * (32-bit pointer) */
3659   uint32_t baseMethods;    /* const method_list_t * (32-bit pointer) */
3660   uint32_t baseProtocols;  /* const protocol_list_t * (32-bit pointer) */
3661   uint32_t ivars;          /* const ivar_list_t * (32-bit pointer) */
3662   uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
3663   uint32_t baseProperties; /* const struct objc_property_list *
3664                                                    (32-bit pointer) */
3665 };
3666 
3667 /* Values for class_ro{64,32}_t->flags */
3668 #define RO_META (1 << 0)
3669 #define RO_ROOT (1 << 1)
3670 #define RO_HAS_CXX_STRUCTORS (1 << 2)
3671 
3672 /* Values for method_list{64,32}_t->entsize */
3673 #define ML_HAS_RELATIVE_PTRS (1 << 31)
3674 #define ML_ENTSIZE_MASK 0xFFFF
3675 
3676 struct method_list64_t {
3677   uint32_t entsize;
3678   uint32_t count;
3679   /* struct method64_t first;  These structures follow inline */
3680 };
3681 
3682 struct method_list32_t {
3683   uint32_t entsize;
3684   uint32_t count;
3685   /* struct method32_t first;  These structures follow inline */
3686 };
3687 
3688 struct method64_t {
3689   uint64_t name;  /* SEL (64-bit pointer) */
3690   uint64_t types; /* const char * (64-bit pointer) */
3691   uint64_t imp;   /* IMP (64-bit pointer) */
3692 };
3693 
3694 struct method32_t {
3695   uint32_t name;  /* SEL (32-bit pointer) */
3696   uint32_t types; /* const char * (32-bit pointer) */
3697   uint32_t imp;   /* IMP (32-bit pointer) */
3698 };
3699 
3700 struct method_relative_t {
3701   int32_t name;  /* SEL (32-bit relative) */
3702   int32_t types; /* const char * (32-bit relative) */
3703   int32_t imp;   /* IMP (32-bit relative) */
3704 };
3705 
3706 struct protocol_list64_t {
3707   uint64_t count; /* uintptr_t (a 64-bit value) */
3708   /* struct protocol64_t * list[0];  These pointers follow inline */
3709 };
3710 
3711 struct protocol_list32_t {
3712   uint32_t count; /* uintptr_t (a 32-bit value) */
3713   /* struct protocol32_t * list[0];  These pointers follow inline */
3714 };
3715 
3716 struct protocol64_t {
3717   uint64_t isa;                     /* id * (64-bit pointer) */
3718   uint64_t name;                    /* const char * (64-bit pointer) */
3719   uint64_t protocols;               /* struct protocol_list64_t *
3720                                                     (64-bit pointer) */
3721   uint64_t instanceMethods;         /* method_list_t * (64-bit pointer) */
3722   uint64_t classMethods;            /* method_list_t * (64-bit pointer) */
3723   uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
3724   uint64_t optionalClassMethods;    /* method_list_t * (64-bit pointer) */
3725   uint64_t instanceProperties;      /* struct objc_property_list *
3726                                                        (64-bit pointer) */
3727 };
3728 
3729 struct protocol32_t {
3730   uint32_t isa;                     /* id * (32-bit pointer) */
3731   uint32_t name;                    /* const char * (32-bit pointer) */
3732   uint32_t protocols;               /* struct protocol_list_t *
3733                                                     (32-bit pointer) */
3734   uint32_t instanceMethods;         /* method_list_t * (32-bit pointer) */
3735   uint32_t classMethods;            /* method_list_t * (32-bit pointer) */
3736   uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
3737   uint32_t optionalClassMethods;    /* method_list_t * (32-bit pointer) */
3738   uint32_t instanceProperties;      /* struct objc_property_list *
3739                                                        (32-bit pointer) */
3740 };
3741 
3742 struct ivar_list64_t {
3743   uint32_t entsize;
3744   uint32_t count;
3745   /* struct ivar64_t first;  These structures follow inline */
3746 };
3747 
3748 struct ivar_list32_t {
3749   uint32_t entsize;
3750   uint32_t count;
3751   /* struct ivar32_t first;  These structures follow inline */
3752 };
3753 
3754 struct ivar64_t {
3755   uint64_t offset; /* uintptr_t * (64-bit pointer) */
3756   uint64_t name;   /* const char * (64-bit pointer) */
3757   uint64_t type;   /* const char * (64-bit pointer) */
3758   uint32_t alignment;
3759   uint32_t size;
3760 };
3761 
3762 struct ivar32_t {
3763   uint32_t offset; /* uintptr_t * (32-bit pointer) */
3764   uint32_t name;   /* const char * (32-bit pointer) */
3765   uint32_t type;   /* const char * (32-bit pointer) */
3766   uint32_t alignment;
3767   uint32_t size;
3768 };
3769 
3770 struct objc_property_list64 {
3771   uint32_t entsize;
3772   uint32_t count;
3773   /* struct objc_property64 first;  These structures follow inline */
3774 };
3775 
3776 struct objc_property_list32 {
3777   uint32_t entsize;
3778   uint32_t count;
3779   /* struct objc_property32 first;  These structures follow inline */
3780 };
3781 
3782 struct objc_property64 {
3783   uint64_t name;       /* const char * (64-bit pointer) */
3784   uint64_t attributes; /* const char * (64-bit pointer) */
3785 };
3786 
3787 struct objc_property32 {
3788   uint32_t name;       /* const char * (32-bit pointer) */
3789   uint32_t attributes; /* const char * (32-bit pointer) */
3790 };
3791 
3792 struct category64_t {
3793   uint64_t name;               /* const char * (64-bit pointer) */
3794   uint64_t cls;                /* struct class_t * (64-bit pointer) */
3795   uint64_t instanceMethods;    /* struct method_list_t * (64-bit pointer) */
3796   uint64_t classMethods;       /* struct method_list_t * (64-bit pointer) */
3797   uint64_t protocols;          /* struct protocol_list_t * (64-bit pointer) */
3798   uint64_t instanceProperties; /* struct objc_property_list *
3799                                   (64-bit pointer) */
3800 };
3801 
3802 struct category32_t {
3803   uint32_t name;               /* const char * (32-bit pointer) */
3804   uint32_t cls;                /* struct class_t * (32-bit pointer) */
3805   uint32_t instanceMethods;    /* struct method_list_t * (32-bit pointer) */
3806   uint32_t classMethods;       /* struct method_list_t * (32-bit pointer) */
3807   uint32_t protocols;          /* struct protocol_list_t * (32-bit pointer) */
3808   uint32_t instanceProperties; /* struct objc_property_list *
3809                                   (32-bit pointer) */
3810 };
3811 
3812 struct objc_image_info64 {
3813   uint32_t version;
3814   uint32_t flags;
3815 };
3816 struct objc_image_info32 {
3817   uint32_t version;
3818   uint32_t flags;
3819 };
3820 struct imageInfo_t {
3821   uint32_t version;
3822   uint32_t flags;
3823 };
3824 /* masks for objc_image_info.flags */
3825 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
3826 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
3827 #define OBJC_IMAGE_IS_SIMULATED (1 << 5)
3828 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)
3829 
3830 struct message_ref64 {
3831   uint64_t imp; /* IMP (64-bit pointer) */
3832   uint64_t sel; /* SEL (64-bit pointer) */
3833 };
3834 
3835 struct message_ref32 {
3836   uint32_t imp; /* IMP (32-bit pointer) */
3837   uint32_t sel; /* SEL (32-bit pointer) */
3838 };
3839 
3840 // Objective-C 1 (32-bit only) meta data structs.
3841 
3842 struct objc_module_t {
3843   uint32_t version;
3844   uint32_t size;
3845   uint32_t name;   /* char * (32-bit pointer) */
3846   uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
3847 };
3848 
3849 struct objc_symtab_t {
3850   uint32_t sel_ref_cnt;
3851   uint32_t refs; /* SEL * (32-bit pointer) */
3852   uint16_t cls_def_cnt;
3853   uint16_t cat_def_cnt;
3854   // uint32_t defs[1];        /* void * (32-bit pointer) variable size */
3855 };
3856 
3857 struct objc_class_t {
3858   uint32_t isa;         /* struct objc_class * (32-bit pointer) */
3859   uint32_t super_class; /* struct objc_class * (32-bit pointer) */
3860   uint32_t name;        /* const char * (32-bit pointer) */
3861   int32_t version;
3862   int32_t info;
3863   int32_t instance_size;
3864   uint32_t ivars;       /* struct objc_ivar_list * (32-bit pointer) */
3865   uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
3866   uint32_t cache;       /* struct objc_cache * (32-bit pointer) */
3867   uint32_t protocols;   /* struct objc_protocol_list * (32-bit pointer) */
3868 };
3869 
3870 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
3871 // class is not a metaclass
3872 #define CLS_CLASS 0x1
3873 // class is a metaclass
3874 #define CLS_META 0x2
3875 
3876 struct objc_category_t {
3877   uint32_t category_name;    /* char * (32-bit pointer) */
3878   uint32_t class_name;       /* char * (32-bit pointer) */
3879   uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
3880   uint32_t class_methods;    /* struct objc_method_list * (32-bit pointer) */
3881   uint32_t protocols;        /* struct objc_protocol_list * (32-bit ptr) */
3882 };
3883 
3884 struct objc_ivar_t {
3885   uint32_t ivar_name; /* char * (32-bit pointer) */
3886   uint32_t ivar_type; /* char * (32-bit pointer) */
3887   int32_t ivar_offset;
3888 };
3889 
3890 struct objc_ivar_list_t {
3891   int32_t ivar_count;
3892   // struct objc_ivar_t ivar_list[1];          /* variable length structure */
3893 };
3894 
3895 struct objc_method_list_t {
3896   uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
3897   int32_t method_count;
3898   // struct objc_method_t method_list[1];      /* variable length structure */
3899 };
3900 
3901 struct objc_method_t {
3902   uint32_t method_name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3903   uint32_t method_types; /* char * (32-bit pointer) */
3904   uint32_t method_imp;   /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
3905                             (32-bit pointer) */
3906 };
3907 
3908 struct objc_protocol_list_t {
3909   uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
3910   int32_t count;
3911   // uint32_t list[1];   /* Protocol *, aka struct objc_protocol_t *
3912   //                        (32-bit pointer) */
3913 };
3914 
3915 struct objc_protocol_t {
3916   uint32_t isa;              /* struct objc_class * (32-bit pointer) */
3917   uint32_t protocol_name;    /* char * (32-bit pointer) */
3918   uint32_t protocol_list;    /* struct objc_protocol_list * (32-bit pointer) */
3919   uint32_t instance_methods; /* struct objc_method_description_list *
3920                                 (32-bit pointer) */
3921   uint32_t class_methods;    /* struct objc_method_description_list *
3922                                 (32-bit pointer) */
3923 };
3924 
3925 struct objc_method_description_list_t {
3926   int32_t count;
3927   // struct objc_method_description_t list[1];
3928 };
3929 
3930 struct objc_method_description_t {
3931   uint32_t name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3932   uint32_t types; /* char * (32-bit pointer) */
3933 };
3934 
3935 inline void swapStruct(struct cfstring64_t &cfs) {
3936   sys::swapByteOrder(cfs.isa);
3937   sys::swapByteOrder(cfs.flags);
3938   sys::swapByteOrder(cfs.characters);
3939   sys::swapByteOrder(cfs.length);
3940 }
3941 
3942 inline void swapStruct(struct class64_t &c) {
3943   sys::swapByteOrder(c.isa);
3944   sys::swapByteOrder(c.superclass);
3945   sys::swapByteOrder(c.cache);
3946   sys::swapByteOrder(c.vtable);
3947   sys::swapByteOrder(c.data);
3948 }
3949 
3950 inline void swapStruct(struct class32_t &c) {
3951   sys::swapByteOrder(c.isa);
3952   sys::swapByteOrder(c.superclass);
3953   sys::swapByteOrder(c.cache);
3954   sys::swapByteOrder(c.vtable);
3955   sys::swapByteOrder(c.data);
3956 }
3957 
3958 inline void swapStruct(struct class_ro64_t &cro) {
3959   sys::swapByteOrder(cro.flags);
3960   sys::swapByteOrder(cro.instanceStart);
3961   sys::swapByteOrder(cro.instanceSize);
3962   sys::swapByteOrder(cro.reserved);
3963   sys::swapByteOrder(cro.ivarLayout);
3964   sys::swapByteOrder(cro.name);
3965   sys::swapByteOrder(cro.baseMethods);
3966   sys::swapByteOrder(cro.baseProtocols);
3967   sys::swapByteOrder(cro.ivars);
3968   sys::swapByteOrder(cro.weakIvarLayout);
3969   sys::swapByteOrder(cro.baseProperties);
3970 }
3971 
3972 inline void swapStruct(struct class_ro32_t &cro) {
3973   sys::swapByteOrder(cro.flags);
3974   sys::swapByteOrder(cro.instanceStart);
3975   sys::swapByteOrder(cro.instanceSize);
3976   sys::swapByteOrder(cro.ivarLayout);
3977   sys::swapByteOrder(cro.name);
3978   sys::swapByteOrder(cro.baseMethods);
3979   sys::swapByteOrder(cro.baseProtocols);
3980   sys::swapByteOrder(cro.ivars);
3981   sys::swapByteOrder(cro.weakIvarLayout);
3982   sys::swapByteOrder(cro.baseProperties);
3983 }
3984 
3985 inline void swapStruct(struct method_list64_t &ml) {
3986   sys::swapByteOrder(ml.entsize);
3987   sys::swapByteOrder(ml.count);
3988 }
3989 
3990 inline void swapStruct(struct method_list32_t &ml) {
3991   sys::swapByteOrder(ml.entsize);
3992   sys::swapByteOrder(ml.count);
3993 }
3994 
3995 inline void swapStruct(struct method64_t &m) {
3996   sys::swapByteOrder(m.name);
3997   sys::swapByteOrder(m.types);
3998   sys::swapByteOrder(m.imp);
3999 }
4000 
4001 inline void swapStruct(struct method32_t &m) {
4002   sys::swapByteOrder(m.name);
4003   sys::swapByteOrder(m.types);
4004   sys::swapByteOrder(m.imp);
4005 }
4006 
4007 inline void swapStruct(struct method_relative_t &m) {
4008   sys::swapByteOrder(m.name);
4009   sys::swapByteOrder(m.types);
4010   sys::swapByteOrder(m.imp);
4011 }
4012 
4013 inline void swapStruct(struct protocol_list64_t &pl) {
4014   sys::swapByteOrder(pl.count);
4015 }
4016 
4017 inline void swapStruct(struct protocol_list32_t &pl) {
4018   sys::swapByteOrder(pl.count);
4019 }
4020 
4021 inline void swapStruct(struct protocol64_t &p) {
4022   sys::swapByteOrder(p.isa);
4023   sys::swapByteOrder(p.name);
4024   sys::swapByteOrder(p.protocols);
4025   sys::swapByteOrder(p.instanceMethods);
4026   sys::swapByteOrder(p.classMethods);
4027   sys::swapByteOrder(p.optionalInstanceMethods);
4028   sys::swapByteOrder(p.optionalClassMethods);
4029   sys::swapByteOrder(p.instanceProperties);
4030 }
4031 
4032 inline void swapStruct(struct protocol32_t &p) {
4033   sys::swapByteOrder(p.isa);
4034   sys::swapByteOrder(p.name);
4035   sys::swapByteOrder(p.protocols);
4036   sys::swapByteOrder(p.instanceMethods);
4037   sys::swapByteOrder(p.classMethods);
4038   sys::swapByteOrder(p.optionalInstanceMethods);
4039   sys::swapByteOrder(p.optionalClassMethods);
4040   sys::swapByteOrder(p.instanceProperties);
4041 }
4042 
4043 inline void swapStruct(struct ivar_list64_t &il) {
4044   sys::swapByteOrder(il.entsize);
4045   sys::swapByteOrder(il.count);
4046 }
4047 
4048 inline void swapStruct(struct ivar_list32_t &il) {
4049   sys::swapByteOrder(il.entsize);
4050   sys::swapByteOrder(il.count);
4051 }
4052 
4053 inline void swapStruct(struct ivar64_t &i) {
4054   sys::swapByteOrder(i.offset);
4055   sys::swapByteOrder(i.name);
4056   sys::swapByteOrder(i.type);
4057   sys::swapByteOrder(i.alignment);
4058   sys::swapByteOrder(i.size);
4059 }
4060 
4061 inline void swapStruct(struct ivar32_t &i) {
4062   sys::swapByteOrder(i.offset);
4063   sys::swapByteOrder(i.name);
4064   sys::swapByteOrder(i.type);
4065   sys::swapByteOrder(i.alignment);
4066   sys::swapByteOrder(i.size);
4067 }
4068 
4069 inline void swapStruct(struct objc_property_list64 &pl) {
4070   sys::swapByteOrder(pl.entsize);
4071   sys::swapByteOrder(pl.count);
4072 }
4073 
4074 inline void swapStruct(struct objc_property_list32 &pl) {
4075   sys::swapByteOrder(pl.entsize);
4076   sys::swapByteOrder(pl.count);
4077 }
4078 
4079 inline void swapStruct(struct objc_property64 &op) {
4080   sys::swapByteOrder(op.name);
4081   sys::swapByteOrder(op.attributes);
4082 }
4083 
4084 inline void swapStruct(struct objc_property32 &op) {
4085   sys::swapByteOrder(op.name);
4086   sys::swapByteOrder(op.attributes);
4087 }
4088 
4089 inline void swapStruct(struct category64_t &c) {
4090   sys::swapByteOrder(c.name);
4091   sys::swapByteOrder(c.cls);
4092   sys::swapByteOrder(c.instanceMethods);
4093   sys::swapByteOrder(c.classMethods);
4094   sys::swapByteOrder(c.protocols);
4095   sys::swapByteOrder(c.instanceProperties);
4096 }
4097 
4098 inline void swapStruct(struct category32_t &c) {
4099   sys::swapByteOrder(c.name);
4100   sys::swapByteOrder(c.cls);
4101   sys::swapByteOrder(c.instanceMethods);
4102   sys::swapByteOrder(c.classMethods);
4103   sys::swapByteOrder(c.protocols);
4104   sys::swapByteOrder(c.instanceProperties);
4105 }
4106 
4107 inline void swapStruct(struct objc_image_info64 &o) {
4108   sys::swapByteOrder(o.version);
4109   sys::swapByteOrder(o.flags);
4110 }
4111 
4112 inline void swapStruct(struct objc_image_info32 &o) {
4113   sys::swapByteOrder(o.version);
4114   sys::swapByteOrder(o.flags);
4115 }
4116 
4117 inline void swapStruct(struct imageInfo_t &o) {
4118   sys::swapByteOrder(o.version);
4119   sys::swapByteOrder(o.flags);
4120 }
4121 
4122 inline void swapStruct(struct message_ref64 &mr) {
4123   sys::swapByteOrder(mr.imp);
4124   sys::swapByteOrder(mr.sel);
4125 }
4126 
4127 inline void swapStruct(struct message_ref32 &mr) {
4128   sys::swapByteOrder(mr.imp);
4129   sys::swapByteOrder(mr.sel);
4130 }
4131 
4132 inline void swapStruct(struct objc_module_t &module) {
4133   sys::swapByteOrder(module.version);
4134   sys::swapByteOrder(module.size);
4135   sys::swapByteOrder(module.name);
4136   sys::swapByteOrder(module.symtab);
4137 }
4138 
4139 inline void swapStruct(struct objc_symtab_t &symtab) {
4140   sys::swapByteOrder(symtab.sel_ref_cnt);
4141   sys::swapByteOrder(symtab.refs);
4142   sys::swapByteOrder(symtab.cls_def_cnt);
4143   sys::swapByteOrder(symtab.cat_def_cnt);
4144 }
4145 
4146 inline void swapStruct(struct objc_class_t &objc_class) {
4147   sys::swapByteOrder(objc_class.isa);
4148   sys::swapByteOrder(objc_class.super_class);
4149   sys::swapByteOrder(objc_class.name);
4150   sys::swapByteOrder(objc_class.version);
4151   sys::swapByteOrder(objc_class.info);
4152   sys::swapByteOrder(objc_class.instance_size);
4153   sys::swapByteOrder(objc_class.ivars);
4154   sys::swapByteOrder(objc_class.methodLists);
4155   sys::swapByteOrder(objc_class.cache);
4156   sys::swapByteOrder(objc_class.protocols);
4157 }
4158 
4159 inline void swapStruct(struct objc_category_t &objc_category) {
4160   sys::swapByteOrder(objc_category.category_name);
4161   sys::swapByteOrder(objc_category.class_name);
4162   sys::swapByteOrder(objc_category.instance_methods);
4163   sys::swapByteOrder(objc_category.class_methods);
4164   sys::swapByteOrder(objc_category.protocols);
4165 }
4166 
4167 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
4168   sys::swapByteOrder(objc_ivar_list.ivar_count);
4169 }
4170 
4171 inline void swapStruct(struct objc_ivar_t &objc_ivar) {
4172   sys::swapByteOrder(objc_ivar.ivar_name);
4173   sys::swapByteOrder(objc_ivar.ivar_type);
4174   sys::swapByteOrder(objc_ivar.ivar_offset);
4175 }
4176 
4177 inline void swapStruct(struct objc_method_list_t &method_list) {
4178   sys::swapByteOrder(method_list.obsolete);
4179   sys::swapByteOrder(method_list.method_count);
4180 }
4181 
4182 inline void swapStruct(struct objc_method_t &method) {
4183   sys::swapByteOrder(method.method_name);
4184   sys::swapByteOrder(method.method_types);
4185   sys::swapByteOrder(method.method_imp);
4186 }
4187 
4188 inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
4189   sys::swapByteOrder(protocol_list.next);
4190   sys::swapByteOrder(protocol_list.count);
4191 }
4192 
4193 inline void swapStruct(struct objc_protocol_t &protocol) {
4194   sys::swapByteOrder(protocol.isa);
4195   sys::swapByteOrder(protocol.protocol_name);
4196   sys::swapByteOrder(protocol.protocol_list);
4197   sys::swapByteOrder(protocol.instance_methods);
4198   sys::swapByteOrder(protocol.class_methods);
4199 }
4200 
4201 inline void swapStruct(struct objc_method_description_list_t &mdl) {
4202   sys::swapByteOrder(mdl.count);
4203 }
4204 
4205 inline void swapStruct(struct objc_method_description_t &md) {
4206   sys::swapByteOrder(md.name);
4207   sys::swapByteOrder(md.types);
4208 }
4209 
4210 } // namespace
4211 
4212 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
4213                                                  struct DisassembleInfo *info);
4214 
4215 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
4216 // to an Objective-C class and returns the class name.  It is also passed the
4217 // address of the pointer, so when the pointer is zero as it can be in an .o
4218 // file, that is used to look for an external relocation entry with a symbol
4219 // name.
4220 static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
4221                                               uint64_t ReferenceValue,
4222                                               struct DisassembleInfo *info) {
4223   const char *r;
4224   uint32_t offset, left;
4225   SectionRef S;
4226 
4227   // The pointer_value can be 0 in an object file and have a relocation
4228   // entry for the class symbol at the ReferenceValue (the address of the
4229   // pointer).
4230   if (pointer_value == 0) {
4231     r = get_pointer_64(ReferenceValue, offset, left, S, info);
4232     if (r == nullptr || left < sizeof(uint64_t))
4233       return nullptr;
4234     uint64_t n_value;
4235     const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4236     if (symbol_name == nullptr)
4237       return nullptr;
4238     const char *class_name = strrchr(symbol_name, '$');
4239     if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
4240       return class_name + 2;
4241     else
4242       return nullptr;
4243   }
4244 
4245   // The case were the pointer_value is non-zero and points to a class defined
4246   // in this Mach-O file.
4247   r = get_pointer_64(pointer_value, offset, left, S, info);
4248   if (r == nullptr || left < sizeof(struct class64_t))
4249     return nullptr;
4250   struct class64_t c;
4251   memcpy(&c, r, sizeof(struct class64_t));
4252   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4253     swapStruct(c);
4254   if (c.data == 0)
4255     return nullptr;
4256   r = get_pointer_64(c.data, offset, left, S, info);
4257   if (r == nullptr || left < sizeof(struct class_ro64_t))
4258     return nullptr;
4259   struct class_ro64_t cro;
4260   memcpy(&cro, r, sizeof(struct class_ro64_t));
4261   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4262     swapStruct(cro);
4263   if (cro.name == 0)
4264     return nullptr;
4265   const char *name = get_pointer_64(cro.name, offset, left, S, info);
4266   return name;
4267 }
4268 
4269 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a
4270 // pointer to a cfstring and returns its name or nullptr.
4271 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
4272                                                  struct DisassembleInfo *info) {
4273   const char *r, *name;
4274   uint32_t offset, left;
4275   SectionRef S;
4276   struct cfstring64_t cfs;
4277   uint64_t cfs_characters;
4278 
4279   r = get_pointer_64(ReferenceValue, offset, left, S, info);
4280   if (r == nullptr || left < sizeof(struct cfstring64_t))
4281     return nullptr;
4282   memcpy(&cfs, r, sizeof(struct cfstring64_t));
4283   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4284     swapStruct(cfs);
4285   if (cfs.characters == 0) {
4286     uint64_t n_value;
4287     const char *symbol_name = get_symbol_64(
4288         offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
4289     if (symbol_name == nullptr)
4290       return nullptr;
4291     cfs_characters = n_value;
4292   } else
4293     cfs_characters = cfs.characters;
4294   name = get_pointer_64(cfs_characters, offset, left, S, info);
4295 
4296   return name;
4297 }
4298 
4299 // get_objc2_64bit_selref() is used for disassembly and is passed a the address
4300 // of a pointer to an Objective-C selector reference when the pointer value is
4301 // zero as in a .o file and is likely to have a external relocation entry with
4302 // who's symbol's n_value is the real pointer to the selector name.  If that is
4303 // the case the real pointer to the selector name is returned else 0 is
4304 // returned
4305 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
4306                                        struct DisassembleInfo *info) {
4307   uint32_t offset, left;
4308   SectionRef S;
4309 
4310   const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
4311   if (r == nullptr || left < sizeof(uint64_t))
4312     return 0;
4313   uint64_t n_value;
4314   const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4315   if (symbol_name == nullptr)
4316     return 0;
4317   return n_value;
4318 }
4319 
4320 static const SectionRef get_section(MachOObjectFile *O, const char *segname,
4321                                     const char *sectname) {
4322   for (const SectionRef &Section : O->sections()) {
4323     StringRef SectName;
4324     Expected<StringRef> SecNameOrErr = Section.getName();
4325     if (SecNameOrErr)
4326       SectName = *SecNameOrErr;
4327     else
4328       consumeError(SecNameOrErr.takeError());
4329 
4330     DataRefImpl Ref = Section.getRawDataRefImpl();
4331     StringRef SegName = O->getSectionFinalSegmentName(Ref);
4332     if (SegName == segname && SectName == sectname)
4333       return Section;
4334   }
4335   return SectionRef();
4336 }
4337 
4338 static void
4339 walk_pointer_list_64(const char *listname, const SectionRef S,
4340                      MachOObjectFile *O, struct DisassembleInfo *info,
4341                      void (*func)(uint64_t, struct DisassembleInfo *info)) {
4342   if (S == SectionRef())
4343     return;
4344 
4345   StringRef SectName;
4346   Expected<StringRef> SecNameOrErr = S.getName();
4347   if (SecNameOrErr)
4348     SectName = *SecNameOrErr;
4349   else
4350     consumeError(SecNameOrErr.takeError());
4351 
4352   DataRefImpl Ref = S.getRawDataRefImpl();
4353   StringRef SegName = O->getSectionFinalSegmentName(Ref);
4354   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4355 
4356   StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4357   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4358 
4359   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
4360     uint32_t left = S.getSize() - i;
4361     uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
4362     uint64_t p = 0;
4363     memcpy(&p, Contents + i, size);
4364     if (i + sizeof(uint64_t) > S.getSize())
4365       outs() << listname << " list pointer extends past end of (" << SegName
4366              << "," << SectName << ") section\n";
4367     outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
4368 
4369     if (O->isLittleEndian() != sys::IsLittleEndianHost)
4370       sys::swapByteOrder(p);
4371 
4372     uint64_t n_value = 0;
4373     const char *name = get_symbol_64(i, S, info, n_value, p);
4374     if (name == nullptr)
4375       name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
4376 
4377     if (n_value != 0) {
4378       outs() << format("0x%" PRIx64, n_value);
4379       if (p != 0)
4380         outs() << " + " << format("0x%" PRIx64, p);
4381     } else
4382       outs() << format("0x%" PRIx64, p);
4383     if (name != nullptr)
4384       outs() << " " << name;
4385     outs() << "\n";
4386 
4387     p += n_value;
4388     if (func)
4389       func(p, info);
4390   }
4391 }
4392 
4393 static void
4394 walk_pointer_list_32(const char *listname, const SectionRef S,
4395                      MachOObjectFile *O, struct DisassembleInfo *info,
4396                      void (*func)(uint32_t, struct DisassembleInfo *info)) {
4397   if (S == SectionRef())
4398     return;
4399 
4400   StringRef SectName = unwrapOrError(S.getName(), O->getFileName());
4401   DataRefImpl Ref = S.getRawDataRefImpl();
4402   StringRef SegName = O->getSectionFinalSegmentName(Ref);
4403   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4404 
4405   StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4406   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4407 
4408   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
4409     uint32_t left = S.getSize() - i;
4410     uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
4411     uint32_t p = 0;
4412     memcpy(&p, Contents + i, size);
4413     if (i + sizeof(uint32_t) > S.getSize())
4414       outs() << listname << " list pointer extends past end of (" << SegName
4415              << "," << SectName << ") section\n";
4416     uint32_t Address = S.getAddress() + i;
4417     outs() << format("%08" PRIx32, Address) << " ";
4418 
4419     if (O->isLittleEndian() != sys::IsLittleEndianHost)
4420       sys::swapByteOrder(p);
4421     outs() << format("0x%" PRIx32, p);
4422 
4423     const char *name = get_symbol_32(i, S, info, p);
4424     if (name != nullptr)
4425       outs() << " " << name;
4426     outs() << "\n";
4427 
4428     if (func)
4429       func(p, info);
4430   }
4431 }
4432 
4433 static void print_layout_map(const char *layout_map, uint32_t left) {
4434   if (layout_map == nullptr)
4435     return;
4436   outs() << "                layout map: ";
4437   do {
4438     outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
4439     left--;
4440     layout_map++;
4441   } while (*layout_map != '\0' && left != 0);
4442   outs() << "\n";
4443 }
4444 
4445 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
4446   uint32_t offset, left;
4447   SectionRef S;
4448   const char *layout_map;
4449 
4450   if (p == 0)
4451     return;
4452   layout_map = get_pointer_64(p, offset, left, S, info);
4453   print_layout_map(layout_map, left);
4454 }
4455 
4456 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
4457   uint32_t offset, left;
4458   SectionRef S;
4459   const char *layout_map;
4460 
4461   if (p == 0)
4462     return;
4463   layout_map = get_pointer_32(p, offset, left, S, info);
4464   print_layout_map(layout_map, left);
4465 }
4466 
4467 static void print_relative_method_list(uint32_t structSizeAndFlags,
4468                                        uint32_t structCount, uint64_t p,
4469                                        struct DisassembleInfo *info,
4470                                        const char *indent,
4471                                        uint32_t pointerBits) {
4472   struct method_relative_t m;
4473   const char *r, *name;
4474   uint32_t offset, xoffset, left, i;
4475   SectionRef S, xS;
4476 
4477   assert(((structSizeAndFlags & ML_HAS_RELATIVE_PTRS) != 0) &&
4478          "expected structSizeAndFlags to have ML_HAS_RELATIVE_PTRS flag");
4479 
4480   outs() << indent << "\t\t   entsize "
4481          << (structSizeAndFlags & ML_ENTSIZE_MASK) << " (relative) \n";
4482   outs() << indent << "\t\t     count " << structCount << "\n";
4483 
4484   for (i = 0; i < structCount; i++) {
4485     r = get_pointer_64(p, offset, left, S, info);
4486     memset(&m, '\0', sizeof(struct method_relative_t));
4487     if (left < sizeof(struct method_relative_t)) {
4488       memcpy(&m, r, left);
4489       outs() << indent << "   (method_t extends past the end of the section)\n";
4490     } else
4491       memcpy(&m, r, sizeof(struct method_relative_t));
4492     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4493       swapStruct(m);
4494 
4495     outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
4496     uint64_t relNameRefVA = p + offsetof(struct method_relative_t, name);
4497     uint64_t absNameRefVA = relNameRefVA + m.name;
4498     outs() << " (" << format("0x%" PRIx32, absNameRefVA) << ")";
4499 
4500     // since this is a relative list, absNameRefVA is the address of the
4501     // __objc_selrefs entry, so a pointer, not the actual name
4502     const char *nameRefPtr =
4503         get_pointer_64(absNameRefVA, xoffset, left, xS, info);
4504     if (nameRefPtr) {
4505       uint32_t pointerSize = pointerBits / CHAR_BIT;
4506       if (left < pointerSize)
4507         outs() << indent << " (nameRefPtr extends past the end of the section)";
4508       else {
4509         if (pointerSize == 64) {
4510           uint64_t nameOff_64 = *reinterpret_cast<const uint64_t *>(nameRefPtr);
4511           if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4512             sys::swapByteOrder(nameOff_64);
4513           name = get_pointer_64(nameOff_64, xoffset, left, xS, info);
4514         } else {
4515           uint32_t nameOff_32 = *reinterpret_cast<const uint32_t *>(nameRefPtr);
4516           if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4517             sys::swapByteOrder(nameOff_32);
4518           name = get_pointer_32(nameOff_32, xoffset, left, xS, info);
4519         }
4520         if (name != nullptr)
4521           outs() << format(" %.*s", left, name);
4522       }
4523     }
4524     outs() << "\n";
4525 
4526     outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
4527     uint64_t relTypesVA = p + offsetof(struct method_relative_t, types);
4528     uint64_t absTypesVA = relTypesVA + m.types;
4529     outs() << " (" << format("0x%" PRIx32, absTypesVA) << ")";
4530     name = get_pointer_32(absTypesVA, xoffset, left, xS, info);
4531     if (name != nullptr)
4532       outs() << format(" %.*s", left, name);
4533     outs() << "\n";
4534 
4535     outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
4536     uint64_t relImpVA = p + offsetof(struct method_relative_t, imp);
4537     uint64_t absImpVA = relImpVA + m.imp;
4538     outs() << " (" << format("0x%" PRIx32, absImpVA) << ")";
4539     name = GuessSymbolName(absImpVA, info->AddrMap);
4540     if (name != nullptr)
4541       outs() << " " << name;
4542     outs() << "\n";
4543 
4544     p += sizeof(struct method_relative_t);
4545     offset += sizeof(struct method_relative_t);
4546   }
4547 }
4548 
4549 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
4550                                   const char *indent) {
4551   struct method_list64_t ml;
4552   struct method64_t m;
4553   const char *r;
4554   uint32_t offset, xoffset, left, i;
4555   SectionRef S, xS;
4556   const char *name, *sym_name;
4557   uint64_t n_value;
4558 
4559   r = get_pointer_64(p, offset, left, S, info);
4560   if (r == nullptr)
4561     return;
4562   memset(&ml, '\0', sizeof(struct method_list64_t));
4563   if (left < sizeof(struct method_list64_t)) {
4564     memcpy(&ml, r, left);
4565     outs() << "   (method_list_t entends past the end of the section)\n";
4566   } else
4567     memcpy(&ml, r, sizeof(struct method_list64_t));
4568   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4569     swapStruct(ml);
4570   p += sizeof(struct method_list64_t);
4571 
4572   if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) {
4573     print_relative_method_list(ml.entsize, ml.count, p, info, indent,
4574                                /*pointerBits=*/64);
4575     return;
4576   }
4577 
4578   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4579   outs() << indent << "\t\t     count " << ml.count << "\n";
4580 
4581   offset += sizeof(struct method_list64_t);
4582   for (i = 0; i < ml.count; i++) {
4583     r = get_pointer_64(p, offset, left, S, info);
4584     if (r == nullptr)
4585       return;
4586     memset(&m, '\0', sizeof(struct method64_t));
4587     if (left < sizeof(struct method64_t)) {
4588       memcpy(&m, r, left);
4589       outs() << indent << "   (method_t extends past the end of the section)\n";
4590     } else
4591       memcpy(&m, r, sizeof(struct method64_t));
4592     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4593       swapStruct(m);
4594 
4595     outs() << indent << "\t\t      name ";
4596     sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
4597                              info, n_value, m.name);
4598     if (n_value != 0) {
4599       if (info->verbose && sym_name != nullptr)
4600         outs() << sym_name;
4601       else
4602         outs() << format("0x%" PRIx64, n_value);
4603       if (m.name != 0)
4604         outs() << " + " << format("0x%" PRIx64, m.name);
4605     } else
4606       outs() << format("0x%" PRIx64, m.name);
4607     name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
4608     if (name != nullptr)
4609       outs() << format(" %.*s", left, name);
4610     outs() << "\n";
4611 
4612     outs() << indent << "\t\t     types ";
4613     sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
4614                              info, n_value, m.types);
4615     if (n_value != 0) {
4616       if (info->verbose && sym_name != nullptr)
4617         outs() << sym_name;
4618       else
4619         outs() << format("0x%" PRIx64, n_value);
4620       if (m.types != 0)
4621         outs() << " + " << format("0x%" PRIx64, m.types);
4622     } else
4623       outs() << format("0x%" PRIx64, m.types);
4624     name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
4625     if (name != nullptr)
4626       outs() << format(" %.*s", left, name);
4627     outs() << "\n";
4628 
4629     outs() << indent << "\t\t       imp ";
4630     name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
4631                          n_value, m.imp);
4632     if (info->verbose && name == nullptr) {
4633       if (n_value != 0) {
4634         outs() << format("0x%" PRIx64, n_value) << " ";
4635         if (m.imp != 0)
4636           outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
4637       } else
4638         outs() << format("0x%" PRIx64, m.imp) << " ";
4639     }
4640     if (name != nullptr)
4641       outs() << name;
4642     outs() << "\n";
4643 
4644     p += sizeof(struct method64_t);
4645     offset += sizeof(struct method64_t);
4646   }
4647 }
4648 
4649 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
4650                                   const char *indent) {
4651   struct method_list32_t ml;
4652   struct method32_t m;
4653   const char *r, *name;
4654   uint32_t offset, xoffset, left, i;
4655   SectionRef S, xS;
4656 
4657   r = get_pointer_32(p, offset, left, S, info);
4658   if (r == nullptr)
4659     return;
4660   memset(&ml, '\0', sizeof(struct method_list32_t));
4661   if (left < sizeof(struct method_list32_t)) {
4662     memcpy(&ml, r, left);
4663     outs() << "   (method_list_t entends past the end of the section)\n";
4664   } else
4665     memcpy(&ml, r, sizeof(struct method_list32_t));
4666   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4667     swapStruct(ml);
4668   p += sizeof(struct method_list32_t);
4669 
4670   if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) {
4671     print_relative_method_list(ml.entsize, ml.count, p, info, indent,
4672                                /*pointerBits=*/32);
4673     return;
4674   }
4675 
4676   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4677   outs() << indent << "\t\t     count " << ml.count << "\n";
4678 
4679   offset += sizeof(struct method_list32_t);
4680   for (i = 0; i < ml.count; i++) {
4681     r = get_pointer_32(p, offset, left, S, info);
4682     if (r == nullptr)
4683       return;
4684     memset(&m, '\0', sizeof(struct method32_t));
4685     if (left < sizeof(struct method32_t)) {
4686       memcpy(&ml, r, left);
4687       outs() << indent << "   (method_t entends past the end of the section)\n";
4688     } else
4689       memcpy(&m, r, sizeof(struct method32_t));
4690     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4691       swapStruct(m);
4692 
4693     outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
4694     name = get_pointer_32(m.name, xoffset, left, xS, info);
4695     if (name != nullptr)
4696       outs() << format(" %.*s", left, name);
4697     outs() << "\n";
4698 
4699     outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
4700     name = get_pointer_32(m.types, xoffset, left, xS, info);
4701     if (name != nullptr)
4702       outs() << format(" %.*s", left, name);
4703     outs() << "\n";
4704 
4705     outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
4706     name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
4707                          m.imp);
4708     if (name != nullptr)
4709       outs() << " " << name;
4710     outs() << "\n";
4711 
4712     p += sizeof(struct method32_t);
4713     offset += sizeof(struct method32_t);
4714   }
4715 }
4716 
4717 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
4718   uint32_t offset, left, xleft;
4719   SectionRef S;
4720   struct objc_method_list_t method_list;
4721   struct objc_method_t method;
4722   const char *r, *methods, *name, *SymbolName;
4723   int32_t i;
4724 
4725   r = get_pointer_32(p, offset, left, S, info, true);
4726   if (r == nullptr)
4727     return true;
4728 
4729   outs() << "\n";
4730   if (left > sizeof(struct objc_method_list_t)) {
4731     memcpy(&method_list, r, sizeof(struct objc_method_list_t));
4732   } else {
4733     outs() << "\t\t objc_method_list extends past end of the section\n";
4734     memset(&method_list, '\0', sizeof(struct objc_method_list_t));
4735     memcpy(&method_list, r, left);
4736   }
4737   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4738     swapStruct(method_list);
4739 
4740   outs() << "\t\t         obsolete "
4741          << format("0x%08" PRIx32, method_list.obsolete) << "\n";
4742   outs() << "\t\t     method_count " << method_list.method_count << "\n";
4743 
4744   methods = r + sizeof(struct objc_method_list_t);
4745   for (i = 0; i < method_list.method_count; i++) {
4746     if ((i + 1) * sizeof(struct objc_method_t) > left) {
4747       outs() << "\t\t remaining method's extend past the of the section\n";
4748       break;
4749     }
4750     memcpy(&method, methods + i * sizeof(struct objc_method_t),
4751            sizeof(struct objc_method_t));
4752     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4753       swapStruct(method);
4754 
4755     outs() << "\t\t      method_name "
4756            << format("0x%08" PRIx32, method.method_name);
4757     if (info->verbose) {
4758       name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
4759       if (name != nullptr)
4760         outs() << format(" %.*s", xleft, name);
4761       else
4762         outs() << " (not in an __OBJC section)";
4763     }
4764     outs() << "\n";
4765 
4766     outs() << "\t\t     method_types "
4767            << format("0x%08" PRIx32, method.method_types);
4768     if (info->verbose) {
4769       name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
4770       if (name != nullptr)
4771         outs() << format(" %.*s", xleft, name);
4772       else
4773         outs() << " (not in an __OBJC section)";
4774     }
4775     outs() << "\n";
4776 
4777     outs() << "\t\t       method_imp "
4778            << format("0x%08" PRIx32, method.method_imp) << " ";
4779     if (info->verbose) {
4780       SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
4781       if (SymbolName != nullptr)
4782         outs() << SymbolName;
4783     }
4784     outs() << "\n";
4785   }
4786   return false;
4787 }
4788 
4789 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
4790   struct protocol_list64_t pl;
4791   uint64_t q, n_value;
4792   struct protocol64_t pc;
4793   const char *r;
4794   uint32_t offset, xoffset, left, i;
4795   SectionRef S, xS;
4796   const char *name, *sym_name;
4797 
4798   r = get_pointer_64(p, offset, left, S, info);
4799   if (r == nullptr)
4800     return;
4801   memset(&pl, '\0', sizeof(struct protocol_list64_t));
4802   if (left < sizeof(struct protocol_list64_t)) {
4803     memcpy(&pl, r, left);
4804     outs() << "   (protocol_list_t entends past the end of the section)\n";
4805   } else
4806     memcpy(&pl, r, sizeof(struct protocol_list64_t));
4807   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4808     swapStruct(pl);
4809   outs() << "                      count " << pl.count << "\n";
4810 
4811   p += sizeof(struct protocol_list64_t);
4812   offset += sizeof(struct protocol_list64_t);
4813   for (i = 0; i < pl.count; i++) {
4814     r = get_pointer_64(p, offset, left, S, info);
4815     if (r == nullptr)
4816       return;
4817     q = 0;
4818     if (left < sizeof(uint64_t)) {
4819       memcpy(&q, r, left);
4820       outs() << "   (protocol_t * entends past the end of the section)\n";
4821     } else
4822       memcpy(&q, r, sizeof(uint64_t));
4823     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4824       sys::swapByteOrder(q);
4825 
4826     outs() << "\t\t      list[" << i << "] ";
4827     sym_name = get_symbol_64(offset, S, info, n_value, q);
4828     if (n_value != 0) {
4829       if (info->verbose && sym_name != nullptr)
4830         outs() << sym_name;
4831       else
4832         outs() << format("0x%" PRIx64, n_value);
4833       if (q != 0)
4834         outs() << " + " << format("0x%" PRIx64, q);
4835     } else
4836       outs() << format("0x%" PRIx64, q);
4837     outs() << " (struct protocol_t *)\n";
4838 
4839     r = get_pointer_64(q + n_value, offset, left, S, info);
4840     if (r == nullptr)
4841       return;
4842     memset(&pc, '\0', sizeof(struct protocol64_t));
4843     if (left < sizeof(struct protocol64_t)) {
4844       memcpy(&pc, r, left);
4845       outs() << "   (protocol_t entends past the end of the section)\n";
4846     } else
4847       memcpy(&pc, r, sizeof(struct protocol64_t));
4848     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4849       swapStruct(pc);
4850 
4851     outs() << "\t\t\t      isa " << format("0x%" PRIx64, pc.isa) << "\n";
4852 
4853     outs() << "\t\t\t     name ";
4854     sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
4855                              info, n_value, pc.name);
4856     if (n_value != 0) {
4857       if (info->verbose && sym_name != nullptr)
4858         outs() << sym_name;
4859       else
4860         outs() << format("0x%" PRIx64, n_value);
4861       if (pc.name != 0)
4862         outs() << " + " << format("0x%" PRIx64, pc.name);
4863     } else
4864       outs() << format("0x%" PRIx64, pc.name);
4865     name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
4866     if (name != nullptr)
4867       outs() << format(" %.*s", left, name);
4868     outs() << "\n";
4869 
4870     outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
4871 
4872     outs() << "\t\t  instanceMethods ";
4873     sym_name =
4874         get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
4875                       S, info, n_value, pc.instanceMethods);
4876     if (n_value != 0) {
4877       if (info->verbose && sym_name != nullptr)
4878         outs() << sym_name;
4879       else
4880         outs() << format("0x%" PRIx64, n_value);
4881       if (pc.instanceMethods != 0)
4882         outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
4883     } else
4884       outs() << format("0x%" PRIx64, pc.instanceMethods);
4885     outs() << " (struct method_list_t *)\n";
4886     if (pc.instanceMethods + n_value != 0)
4887       print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
4888 
4889     outs() << "\t\t     classMethods ";
4890     sym_name =
4891         get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
4892                       info, n_value, pc.classMethods);
4893     if (n_value != 0) {
4894       if (info->verbose && sym_name != nullptr)
4895         outs() << sym_name;
4896       else
4897         outs() << format("0x%" PRIx64, n_value);
4898       if (pc.classMethods != 0)
4899         outs() << " + " << format("0x%" PRIx64, pc.classMethods);
4900     } else
4901       outs() << format("0x%" PRIx64, pc.classMethods);
4902     outs() << " (struct method_list_t *)\n";
4903     if (pc.classMethods + n_value != 0)
4904       print_method_list64_t(pc.classMethods + n_value, info, "\t");
4905 
4906     outs() << "\t  optionalInstanceMethods "
4907            << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
4908     outs() << "\t     optionalClassMethods "
4909            << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
4910     outs() << "\t       instanceProperties "
4911            << format("0x%" PRIx64, pc.instanceProperties) << "\n";
4912 
4913     p += sizeof(uint64_t);
4914     offset += sizeof(uint64_t);
4915   }
4916 }
4917 
4918 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
4919   struct protocol_list32_t pl;
4920   uint32_t q;
4921   struct protocol32_t pc;
4922   const char *r;
4923   uint32_t offset, xoffset, left, i;
4924   SectionRef S, xS;
4925   const char *name;
4926 
4927   r = get_pointer_32(p, offset, left, S, info);
4928   if (r == nullptr)
4929     return;
4930   memset(&pl, '\0', sizeof(struct protocol_list32_t));
4931   if (left < sizeof(struct protocol_list32_t)) {
4932     memcpy(&pl, r, left);
4933     outs() << "   (protocol_list_t entends past the end of the section)\n";
4934   } else
4935     memcpy(&pl, r, sizeof(struct protocol_list32_t));
4936   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4937     swapStruct(pl);
4938   outs() << "                      count " << pl.count << "\n";
4939 
4940   p += sizeof(struct protocol_list32_t);
4941   offset += sizeof(struct protocol_list32_t);
4942   for (i = 0; i < pl.count; i++) {
4943     r = get_pointer_32(p, offset, left, S, info);
4944     if (r == nullptr)
4945       return;
4946     q = 0;
4947     if (left < sizeof(uint32_t)) {
4948       memcpy(&q, r, left);
4949       outs() << "   (protocol_t * entends past the end of the section)\n";
4950     } else
4951       memcpy(&q, r, sizeof(uint32_t));
4952     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4953       sys::swapByteOrder(q);
4954     outs() << "\t\t      list[" << i << "] " << format("0x%" PRIx32, q)
4955            << " (struct protocol_t *)\n";
4956     r = get_pointer_32(q, offset, left, S, info);
4957     if (r == nullptr)
4958       return;
4959     memset(&pc, '\0', sizeof(struct protocol32_t));
4960     if (left < sizeof(struct protocol32_t)) {
4961       memcpy(&pc, r, left);
4962       outs() << "   (protocol_t entends past the end of the section)\n";
4963     } else
4964       memcpy(&pc, r, sizeof(struct protocol32_t));
4965     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4966       swapStruct(pc);
4967     outs() << "\t\t\t      isa " << format("0x%" PRIx32, pc.isa) << "\n";
4968     outs() << "\t\t\t     name " << format("0x%" PRIx32, pc.name);
4969     name = get_pointer_32(pc.name, xoffset, left, xS, info);
4970     if (name != nullptr)
4971       outs() << format(" %.*s", left, name);
4972     outs() << "\n";
4973     outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
4974     outs() << "\t\t  instanceMethods "
4975            << format("0x%" PRIx32, pc.instanceMethods)
4976            << " (struct method_list_t *)\n";
4977     if (pc.instanceMethods != 0)
4978       print_method_list32_t(pc.instanceMethods, info, "\t");
4979     outs() << "\t\t     classMethods " << format("0x%" PRIx32, pc.classMethods)
4980            << " (struct method_list_t *)\n";
4981     if (pc.classMethods != 0)
4982       print_method_list32_t(pc.classMethods, info, "\t");
4983     outs() << "\t  optionalInstanceMethods "
4984            << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
4985     outs() << "\t     optionalClassMethods "
4986            << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
4987     outs() << "\t       instanceProperties "
4988            << format("0x%" PRIx32, pc.instanceProperties) << "\n";
4989     p += sizeof(uint32_t);
4990     offset += sizeof(uint32_t);
4991   }
4992 }
4993 
4994 static void print_indent(uint32_t indent) {
4995   for (uint32_t i = 0; i < indent;) {
4996     if (indent - i >= 8) {
4997       outs() << "\t";
4998       i += 8;
4999     } else {
5000       for (uint32_t j = i; j < indent; j++)
5001         outs() << " ";
5002       return;
5003     }
5004   }
5005 }
5006 
5007 static bool print_method_description_list(uint32_t p, uint32_t indent,
5008                                           struct DisassembleInfo *info) {
5009   uint32_t offset, left, xleft;
5010   SectionRef S;
5011   struct objc_method_description_list_t mdl;
5012   struct objc_method_description_t md;
5013   const char *r, *list, *name;
5014   int32_t i;
5015 
5016   r = get_pointer_32(p, offset, left, S, info, true);
5017   if (r == nullptr)
5018     return true;
5019 
5020   outs() << "\n";
5021   if (left > sizeof(struct objc_method_description_list_t)) {
5022     memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
5023   } else {
5024     print_indent(indent);
5025     outs() << " objc_method_description_list extends past end of the section\n";
5026     memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
5027     memcpy(&mdl, r, left);
5028   }
5029   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5030     swapStruct(mdl);
5031 
5032   print_indent(indent);
5033   outs() << "        count " << mdl.count << "\n";
5034 
5035   list = r + sizeof(struct objc_method_description_list_t);
5036   for (i = 0; i < mdl.count; i++) {
5037     if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
5038       print_indent(indent);
5039       outs() << " remaining list entries extend past the of the section\n";
5040       break;
5041     }
5042     print_indent(indent);
5043     outs() << "        list[" << i << "]\n";
5044     memcpy(&md, list + i * sizeof(struct objc_method_description_t),
5045            sizeof(struct objc_method_description_t));
5046     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5047       swapStruct(md);
5048 
5049     print_indent(indent);
5050     outs() << "             name " << format("0x%08" PRIx32, md.name);
5051     if (info->verbose) {
5052       name = get_pointer_32(md.name, offset, xleft, S, info, true);
5053       if (name != nullptr)
5054         outs() << format(" %.*s", xleft, name);
5055       else
5056         outs() << " (not in an __OBJC section)";
5057     }
5058     outs() << "\n";
5059 
5060     print_indent(indent);
5061     outs() << "            types " << format("0x%08" PRIx32, md.types);
5062     if (info->verbose) {
5063       name = get_pointer_32(md.types, offset, xleft, S, info, true);
5064       if (name != nullptr)
5065         outs() << format(" %.*s", xleft, name);
5066       else
5067         outs() << " (not in an __OBJC section)";
5068     }
5069     outs() << "\n";
5070   }
5071   return false;
5072 }
5073 
5074 static bool print_protocol_list(uint32_t p, uint32_t indent,
5075                                 struct DisassembleInfo *info);
5076 
5077 static bool print_protocol(uint32_t p, uint32_t indent,
5078                            struct DisassembleInfo *info) {
5079   uint32_t offset, left;
5080   SectionRef S;
5081   struct objc_protocol_t protocol;
5082   const char *r, *name;
5083 
5084   r = get_pointer_32(p, offset, left, S, info, true);
5085   if (r == nullptr)
5086     return true;
5087 
5088   outs() << "\n";
5089   if (left >= sizeof(struct objc_protocol_t)) {
5090     memcpy(&protocol, r, sizeof(struct objc_protocol_t));
5091   } else {
5092     print_indent(indent);
5093     outs() << "            Protocol extends past end of the section\n";
5094     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
5095     memcpy(&protocol, r, left);
5096   }
5097   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5098     swapStruct(protocol);
5099 
5100   print_indent(indent);
5101   outs() << "              isa " << format("0x%08" PRIx32, protocol.isa)
5102          << "\n";
5103 
5104   print_indent(indent);
5105   outs() << "    protocol_name "
5106          << format("0x%08" PRIx32, protocol.protocol_name);
5107   if (info->verbose) {
5108     name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
5109     if (name != nullptr)
5110       outs() << format(" %.*s", left, name);
5111     else
5112       outs() << " (not in an __OBJC section)";
5113   }
5114   outs() << "\n";
5115 
5116   print_indent(indent);
5117   outs() << "    protocol_list "
5118          << format("0x%08" PRIx32, protocol.protocol_list);
5119   if (print_protocol_list(protocol.protocol_list, indent + 4, info))
5120     outs() << " (not in an __OBJC section)\n";
5121 
5122   print_indent(indent);
5123   outs() << " instance_methods "
5124          << format("0x%08" PRIx32, protocol.instance_methods);
5125   if (print_method_description_list(protocol.instance_methods, indent, info))
5126     outs() << " (not in an __OBJC section)\n";
5127 
5128   print_indent(indent);
5129   outs() << "    class_methods "
5130          << format("0x%08" PRIx32, protocol.class_methods);
5131   if (print_method_description_list(protocol.class_methods, indent, info))
5132     outs() << " (not in an __OBJC section)\n";
5133 
5134   return false;
5135 }
5136 
5137 static bool print_protocol_list(uint32_t p, uint32_t indent,
5138                                 struct DisassembleInfo *info) {
5139   uint32_t offset, left, l;
5140   SectionRef S;
5141   struct objc_protocol_list_t protocol_list;
5142   const char *r, *list;
5143   int32_t i;
5144 
5145   r = get_pointer_32(p, offset, left, S, info, true);
5146   if (r == nullptr)
5147     return true;
5148 
5149   outs() << "\n";
5150   if (left > sizeof(struct objc_protocol_list_t)) {
5151     memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
5152   } else {
5153     outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
5154     memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
5155     memcpy(&protocol_list, r, left);
5156   }
5157   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5158     swapStruct(protocol_list);
5159 
5160   print_indent(indent);
5161   outs() << "         next " << format("0x%08" PRIx32, protocol_list.next)
5162          << "\n";
5163   print_indent(indent);
5164   outs() << "        count " << protocol_list.count << "\n";
5165 
5166   list = r + sizeof(struct objc_protocol_list_t);
5167   for (i = 0; i < protocol_list.count; i++) {
5168     if ((i + 1) * sizeof(uint32_t) > left) {
5169       outs() << "\t\t remaining list entries extend past the of the section\n";
5170       break;
5171     }
5172     memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
5173     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5174       sys::swapByteOrder(l);
5175 
5176     print_indent(indent);
5177     outs() << "      list[" << i << "] " << format("0x%08" PRIx32, l);
5178     if (print_protocol(l, indent, info))
5179       outs() << "(not in an __OBJC section)\n";
5180   }
5181   return false;
5182 }
5183 
5184 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
5185   struct ivar_list64_t il;
5186   struct ivar64_t i;
5187   const char *r;
5188   uint32_t offset, xoffset, left, j;
5189   SectionRef S, xS;
5190   const char *name, *sym_name, *ivar_offset_p;
5191   uint64_t ivar_offset, n_value;
5192 
5193   r = get_pointer_64(p, offset, left, S, info);
5194   if (r == nullptr)
5195     return;
5196   memset(&il, '\0', sizeof(struct ivar_list64_t));
5197   if (left < sizeof(struct ivar_list64_t)) {
5198     memcpy(&il, r, left);
5199     outs() << "   (ivar_list_t entends past the end of the section)\n";
5200   } else
5201     memcpy(&il, r, sizeof(struct ivar_list64_t));
5202   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5203     swapStruct(il);
5204   outs() << "                    entsize " << il.entsize << "\n";
5205   outs() << "                      count " << il.count << "\n";
5206 
5207   p += sizeof(struct ivar_list64_t);
5208   offset += sizeof(struct ivar_list64_t);
5209   for (j = 0; j < il.count; j++) {
5210     r = get_pointer_64(p, offset, left, S, info);
5211     if (r == nullptr)
5212       return;
5213     memset(&i, '\0', sizeof(struct ivar64_t));
5214     if (left < sizeof(struct ivar64_t)) {
5215       memcpy(&i, r, left);
5216       outs() << "   (ivar_t entends past the end of the section)\n";
5217     } else
5218       memcpy(&i, r, sizeof(struct ivar64_t));
5219     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5220       swapStruct(i);
5221 
5222     outs() << "\t\t\t   offset ";
5223     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
5224                              info, n_value, i.offset);
5225     if (n_value != 0) {
5226       if (info->verbose && sym_name != nullptr)
5227         outs() << sym_name;
5228       else
5229         outs() << format("0x%" PRIx64, n_value);
5230       if (i.offset != 0)
5231         outs() << " + " << format("0x%" PRIx64, i.offset);
5232     } else
5233       outs() << format("0x%" PRIx64, i.offset);
5234     ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
5235     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5236       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5237       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5238         sys::swapByteOrder(ivar_offset);
5239       outs() << " " << ivar_offset << "\n";
5240     } else
5241       outs() << "\n";
5242 
5243     outs() << "\t\t\t     name ";
5244     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
5245                              n_value, i.name);
5246     if (n_value != 0) {
5247       if (info->verbose && sym_name != nullptr)
5248         outs() << sym_name;
5249       else
5250         outs() << format("0x%" PRIx64, n_value);
5251       if (i.name != 0)
5252         outs() << " + " << format("0x%" PRIx64, i.name);
5253     } else
5254       outs() << format("0x%" PRIx64, i.name);
5255     name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
5256     if (name != nullptr)
5257       outs() << format(" %.*s", left, name);
5258     outs() << "\n";
5259 
5260     outs() << "\t\t\t     type ";
5261     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
5262                              n_value, i.name);
5263     name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
5264     if (n_value != 0) {
5265       if (info->verbose && sym_name != nullptr)
5266         outs() << sym_name;
5267       else
5268         outs() << format("0x%" PRIx64, n_value);
5269       if (i.type != 0)
5270         outs() << " + " << format("0x%" PRIx64, i.type);
5271     } else
5272       outs() << format("0x%" PRIx64, i.type);
5273     if (name != nullptr)
5274       outs() << format(" %.*s", left, name);
5275     outs() << "\n";
5276 
5277     outs() << "\t\t\talignment " << i.alignment << "\n";
5278     outs() << "\t\t\t     size " << i.size << "\n";
5279 
5280     p += sizeof(struct ivar64_t);
5281     offset += sizeof(struct ivar64_t);
5282   }
5283 }
5284 
5285 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
5286   struct ivar_list32_t il;
5287   struct ivar32_t i;
5288   const char *r;
5289   uint32_t offset, xoffset, left, j;
5290   SectionRef S, xS;
5291   const char *name, *ivar_offset_p;
5292   uint32_t ivar_offset;
5293 
5294   r = get_pointer_32(p, offset, left, S, info);
5295   if (r == nullptr)
5296     return;
5297   memset(&il, '\0', sizeof(struct ivar_list32_t));
5298   if (left < sizeof(struct ivar_list32_t)) {
5299     memcpy(&il, r, left);
5300     outs() << "   (ivar_list_t entends past the end of the section)\n";
5301   } else
5302     memcpy(&il, r, sizeof(struct ivar_list32_t));
5303   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5304     swapStruct(il);
5305   outs() << "                    entsize " << il.entsize << "\n";
5306   outs() << "                      count " << il.count << "\n";
5307 
5308   p += sizeof(struct ivar_list32_t);
5309   offset += sizeof(struct ivar_list32_t);
5310   for (j = 0; j < il.count; j++) {
5311     r = get_pointer_32(p, offset, left, S, info);
5312     if (r == nullptr)
5313       return;
5314     memset(&i, '\0', sizeof(struct ivar32_t));
5315     if (left < sizeof(struct ivar32_t)) {
5316       memcpy(&i, r, left);
5317       outs() << "   (ivar_t entends past the end of the section)\n";
5318     } else
5319       memcpy(&i, r, sizeof(struct ivar32_t));
5320     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5321       swapStruct(i);
5322 
5323     outs() << "\t\t\t   offset " << format("0x%" PRIx32, i.offset);
5324     ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
5325     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5326       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5327       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5328         sys::swapByteOrder(ivar_offset);
5329       outs() << " " << ivar_offset << "\n";
5330     } else
5331       outs() << "\n";
5332 
5333     outs() << "\t\t\t     name " << format("0x%" PRIx32, i.name);
5334     name = get_pointer_32(i.name, xoffset, left, xS, info);
5335     if (name != nullptr)
5336       outs() << format(" %.*s", left, name);
5337     outs() << "\n";
5338 
5339     outs() << "\t\t\t     type " << format("0x%" PRIx32, i.type);
5340     name = get_pointer_32(i.type, xoffset, left, xS, info);
5341     if (name != nullptr)
5342       outs() << format(" %.*s", left, name);
5343     outs() << "\n";
5344 
5345     outs() << "\t\t\talignment " << i.alignment << "\n";
5346     outs() << "\t\t\t     size " << i.size << "\n";
5347 
5348     p += sizeof(struct ivar32_t);
5349     offset += sizeof(struct ivar32_t);
5350   }
5351 }
5352 
5353 static void print_objc_property_list64(uint64_t p,
5354                                        struct DisassembleInfo *info) {
5355   struct objc_property_list64 opl;
5356   struct objc_property64 op;
5357   const char *r;
5358   uint32_t offset, xoffset, left, j;
5359   SectionRef S, xS;
5360   const char *name, *sym_name;
5361   uint64_t n_value;
5362 
5363   r = get_pointer_64(p, offset, left, S, info);
5364   if (r == nullptr)
5365     return;
5366   memset(&opl, '\0', sizeof(struct objc_property_list64));
5367   if (left < sizeof(struct objc_property_list64)) {
5368     memcpy(&opl, r, left);
5369     outs() << "   (objc_property_list entends past the end of the section)\n";
5370   } else
5371     memcpy(&opl, r, sizeof(struct objc_property_list64));
5372   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5373     swapStruct(opl);
5374   outs() << "                    entsize " << opl.entsize << "\n";
5375   outs() << "                      count " << opl.count << "\n";
5376 
5377   p += sizeof(struct objc_property_list64);
5378   offset += sizeof(struct objc_property_list64);
5379   for (j = 0; j < opl.count; j++) {
5380     r = get_pointer_64(p, offset, left, S, info);
5381     if (r == nullptr)
5382       return;
5383     memset(&op, '\0', sizeof(struct objc_property64));
5384     if (left < sizeof(struct objc_property64)) {
5385       memcpy(&op, r, left);
5386       outs() << "   (objc_property entends past the end of the section)\n";
5387     } else
5388       memcpy(&op, r, sizeof(struct objc_property64));
5389     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5390       swapStruct(op);
5391 
5392     outs() << "\t\t\t     name ";
5393     sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
5394                              info, n_value, op.name);
5395     if (n_value != 0) {
5396       if (info->verbose && sym_name != nullptr)
5397         outs() << sym_name;
5398       else
5399         outs() << format("0x%" PRIx64, n_value);
5400       if (op.name != 0)
5401         outs() << " + " << format("0x%" PRIx64, op.name);
5402     } else
5403       outs() << format("0x%" PRIx64, op.name);
5404     name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
5405     if (name != nullptr)
5406       outs() << format(" %.*s", left, name);
5407     outs() << "\n";
5408 
5409     outs() << "\t\t\tattributes ";
5410     sym_name =
5411         get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
5412                       info, n_value, op.attributes);
5413     if (n_value != 0) {
5414       if (info->verbose && sym_name != nullptr)
5415         outs() << sym_name;
5416       else
5417         outs() << format("0x%" PRIx64, n_value);
5418       if (op.attributes != 0)
5419         outs() << " + " << format("0x%" PRIx64, op.attributes);
5420     } else
5421       outs() << format("0x%" PRIx64, op.attributes);
5422     name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
5423     if (name != nullptr)
5424       outs() << format(" %.*s", left, name);
5425     outs() << "\n";
5426 
5427     p += sizeof(struct objc_property64);
5428     offset += sizeof(struct objc_property64);
5429   }
5430 }
5431 
5432 static void print_objc_property_list32(uint32_t p,
5433                                        struct DisassembleInfo *info) {
5434   struct objc_property_list32 opl;
5435   struct objc_property32 op;
5436   const char *r;
5437   uint32_t offset, xoffset, left, j;
5438   SectionRef S, xS;
5439   const char *name;
5440 
5441   r = get_pointer_32(p, offset, left, S, info);
5442   if (r == nullptr)
5443     return;
5444   memset(&opl, '\0', sizeof(struct objc_property_list32));
5445   if (left < sizeof(struct objc_property_list32)) {
5446     memcpy(&opl, r, left);
5447     outs() << "   (objc_property_list entends past the end of the section)\n";
5448   } else
5449     memcpy(&opl, r, sizeof(struct objc_property_list32));
5450   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5451     swapStruct(opl);
5452   outs() << "                    entsize " << opl.entsize << "\n";
5453   outs() << "                      count " << opl.count << "\n";
5454 
5455   p += sizeof(struct objc_property_list32);
5456   offset += sizeof(struct objc_property_list32);
5457   for (j = 0; j < opl.count; j++) {
5458     r = get_pointer_32(p, offset, left, S, info);
5459     if (r == nullptr)
5460       return;
5461     memset(&op, '\0', sizeof(struct objc_property32));
5462     if (left < sizeof(struct objc_property32)) {
5463       memcpy(&op, r, left);
5464       outs() << "   (objc_property entends past the end of the section)\n";
5465     } else
5466       memcpy(&op, r, sizeof(struct objc_property32));
5467     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5468       swapStruct(op);
5469 
5470     outs() << "\t\t\t     name " << format("0x%" PRIx32, op.name);
5471     name = get_pointer_32(op.name, xoffset, left, xS, info);
5472     if (name != nullptr)
5473       outs() << format(" %.*s", left, name);
5474     outs() << "\n";
5475 
5476     outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
5477     name = get_pointer_32(op.attributes, xoffset, left, xS, info);
5478     if (name != nullptr)
5479       outs() << format(" %.*s", left, name);
5480     outs() << "\n";
5481 
5482     p += sizeof(struct objc_property32);
5483     offset += sizeof(struct objc_property32);
5484   }
5485 }
5486 
5487 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
5488                                bool &is_meta_class) {
5489   struct class_ro64_t cro;
5490   const char *r;
5491   uint32_t offset, xoffset, left;
5492   SectionRef S, xS;
5493   const char *name, *sym_name;
5494   uint64_t n_value;
5495 
5496   r = get_pointer_64(p, offset, left, S, info);
5497   if (r == nullptr || left < sizeof(struct class_ro64_t))
5498     return false;
5499   memcpy(&cro, r, sizeof(struct class_ro64_t));
5500   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5501     swapStruct(cro);
5502   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5503   if (cro.flags & RO_META)
5504     outs() << " RO_META";
5505   if (cro.flags & RO_ROOT)
5506     outs() << " RO_ROOT";
5507   if (cro.flags & RO_HAS_CXX_STRUCTORS)
5508     outs() << " RO_HAS_CXX_STRUCTORS";
5509   outs() << "\n";
5510   outs() << "            instanceStart " << cro.instanceStart << "\n";
5511   outs() << "             instanceSize " << cro.instanceSize << "\n";
5512   outs() << "                 reserved " << format("0x%" PRIx32, cro.reserved)
5513          << "\n";
5514   outs() << "               ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
5515          << "\n";
5516   print_layout_map64(cro.ivarLayout, info);
5517 
5518   outs() << "                     name ";
5519   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
5520                            info, n_value, cro.name);
5521   if (n_value != 0) {
5522     if (info->verbose && sym_name != nullptr)
5523       outs() << sym_name;
5524     else
5525       outs() << format("0x%" PRIx64, n_value);
5526     if (cro.name != 0)
5527       outs() << " + " << format("0x%" PRIx64, cro.name);
5528   } else
5529     outs() << format("0x%" PRIx64, cro.name);
5530   name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
5531   if (name != nullptr)
5532     outs() << format(" %.*s", left, name);
5533   outs() << "\n";
5534 
5535   outs() << "              baseMethods ";
5536   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
5537                            S, info, n_value, cro.baseMethods);
5538   if (n_value != 0) {
5539     if (info->verbose && sym_name != nullptr)
5540       outs() << sym_name;
5541     else
5542       outs() << format("0x%" PRIx64, n_value);
5543     if (cro.baseMethods != 0)
5544       outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
5545   } else
5546     outs() << format("0x%" PRIx64, cro.baseMethods);
5547   outs() << " (struct method_list_t *)\n";
5548   if (cro.baseMethods + n_value != 0)
5549     print_method_list64_t(cro.baseMethods + n_value, info, "");
5550 
5551   outs() << "            baseProtocols ";
5552   sym_name =
5553       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
5554                     info, n_value, cro.baseProtocols);
5555   if (n_value != 0) {
5556     if (info->verbose && sym_name != nullptr)
5557       outs() << sym_name;
5558     else
5559       outs() << format("0x%" PRIx64, n_value);
5560     if (cro.baseProtocols != 0)
5561       outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
5562   } else
5563     outs() << format("0x%" PRIx64, cro.baseProtocols);
5564   outs() << "\n";
5565   if (cro.baseProtocols + n_value != 0)
5566     print_protocol_list64_t(cro.baseProtocols + n_value, info);
5567 
5568   outs() << "                    ivars ";
5569   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
5570                            info, n_value, cro.ivars);
5571   if (n_value != 0) {
5572     if (info->verbose && sym_name != nullptr)
5573       outs() << sym_name;
5574     else
5575       outs() << format("0x%" PRIx64, n_value);
5576     if (cro.ivars != 0)
5577       outs() << " + " << format("0x%" PRIx64, cro.ivars);
5578   } else
5579     outs() << format("0x%" PRIx64, cro.ivars);
5580   outs() << "\n";
5581   if (cro.ivars + n_value != 0)
5582     print_ivar_list64_t(cro.ivars + n_value, info);
5583 
5584   outs() << "           weakIvarLayout ";
5585   sym_name =
5586       get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
5587                     info, n_value, cro.weakIvarLayout);
5588   if (n_value != 0) {
5589     if (info->verbose && sym_name != nullptr)
5590       outs() << sym_name;
5591     else
5592       outs() << format("0x%" PRIx64, n_value);
5593     if (cro.weakIvarLayout != 0)
5594       outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
5595   } else
5596     outs() << format("0x%" PRIx64, cro.weakIvarLayout);
5597   outs() << "\n";
5598   print_layout_map64(cro.weakIvarLayout + n_value, info);
5599 
5600   outs() << "           baseProperties ";
5601   sym_name =
5602       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
5603                     info, n_value, cro.baseProperties);
5604   if (n_value != 0) {
5605     if (info->verbose && sym_name != nullptr)
5606       outs() << sym_name;
5607     else
5608       outs() << format("0x%" PRIx64, n_value);
5609     if (cro.baseProperties != 0)
5610       outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
5611   } else
5612     outs() << format("0x%" PRIx64, cro.baseProperties);
5613   outs() << "\n";
5614   if (cro.baseProperties + n_value != 0)
5615     print_objc_property_list64(cro.baseProperties + n_value, info);
5616 
5617   is_meta_class = (cro.flags & RO_META) != 0;
5618   return true;
5619 }
5620 
5621 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
5622                                bool &is_meta_class) {
5623   struct class_ro32_t cro;
5624   const char *r;
5625   uint32_t offset, xoffset, left;
5626   SectionRef S, xS;
5627   const char *name;
5628 
5629   r = get_pointer_32(p, offset, left, S, info);
5630   if (r == nullptr)
5631     return false;
5632   memset(&cro, '\0', sizeof(struct class_ro32_t));
5633   if (left < sizeof(struct class_ro32_t)) {
5634     memcpy(&cro, r, left);
5635     outs() << "   (class_ro_t entends past the end of the section)\n";
5636   } else
5637     memcpy(&cro, r, sizeof(struct class_ro32_t));
5638   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5639     swapStruct(cro);
5640   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5641   if (cro.flags & RO_META)
5642     outs() << " RO_META";
5643   if (cro.flags & RO_ROOT)
5644     outs() << " RO_ROOT";
5645   if (cro.flags & RO_HAS_CXX_STRUCTORS)
5646     outs() << " RO_HAS_CXX_STRUCTORS";
5647   outs() << "\n";
5648   outs() << "            instanceStart " << cro.instanceStart << "\n";
5649   outs() << "             instanceSize " << cro.instanceSize << "\n";
5650   outs() << "               ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
5651          << "\n";
5652   print_layout_map32(cro.ivarLayout, info);
5653 
5654   outs() << "                     name " << format("0x%" PRIx32, cro.name);
5655   name = get_pointer_32(cro.name, xoffset, left, xS, info);
5656   if (name != nullptr)
5657     outs() << format(" %.*s", left, name);
5658   outs() << "\n";
5659 
5660   outs() << "              baseMethods "
5661          << format("0x%" PRIx32, cro.baseMethods)
5662          << " (struct method_list_t *)\n";
5663   if (cro.baseMethods != 0)
5664     print_method_list32_t(cro.baseMethods, info, "");
5665 
5666   outs() << "            baseProtocols "
5667          << format("0x%" PRIx32, cro.baseProtocols) << "\n";
5668   if (cro.baseProtocols != 0)
5669     print_protocol_list32_t(cro.baseProtocols, info);
5670   outs() << "                    ivars " << format("0x%" PRIx32, cro.ivars)
5671          << "\n";
5672   if (cro.ivars != 0)
5673     print_ivar_list32_t(cro.ivars, info);
5674   outs() << "           weakIvarLayout "
5675          << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
5676   print_layout_map32(cro.weakIvarLayout, info);
5677   outs() << "           baseProperties "
5678          << format("0x%" PRIx32, cro.baseProperties) << "\n";
5679   if (cro.baseProperties != 0)
5680     print_objc_property_list32(cro.baseProperties, info);
5681   is_meta_class = (cro.flags & RO_META) != 0;
5682   return true;
5683 }
5684 
5685 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
5686   struct class64_t c;
5687   const char *r;
5688   uint32_t offset, left;
5689   SectionRef S;
5690   const char *name;
5691   uint64_t isa_n_value, n_value;
5692 
5693   r = get_pointer_64(p, offset, left, S, info);
5694   if (r == nullptr || left < sizeof(struct class64_t))
5695     return;
5696   memcpy(&c, r, sizeof(struct class64_t));
5697   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5698     swapStruct(c);
5699 
5700   outs() << "           isa " << format("0x%" PRIx64, c.isa);
5701   name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
5702                        isa_n_value, c.isa);
5703   if (name != nullptr)
5704     outs() << " " << name;
5705   outs() << "\n";
5706 
5707   outs() << "    superclass " << format("0x%" PRIx64, c.superclass);
5708   name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
5709                        n_value, c.superclass);
5710   if (name != nullptr)
5711     outs() << " " << name;
5712   else {
5713     name = get_dyld_bind_info_symbolname(S.getAddress() +
5714              offset + offsetof(struct class64_t, superclass), info);
5715     if (name != nullptr)
5716       outs() << " " << name;
5717   }
5718   outs() << "\n";
5719 
5720   outs() << "         cache " << format("0x%" PRIx64, c.cache);
5721   name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
5722                        n_value, c.cache);
5723   if (name != nullptr)
5724     outs() << " " << name;
5725   outs() << "\n";
5726 
5727   outs() << "        vtable " << format("0x%" PRIx64, c.vtable);
5728   name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
5729                        n_value, c.vtable);
5730   if (name != nullptr)
5731     outs() << " " << name;
5732   outs() << "\n";
5733 
5734   name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
5735                        n_value, c.data);
5736   outs() << "          data ";
5737   if (n_value != 0) {
5738     if (info->verbose && name != nullptr)
5739       outs() << name;
5740     else
5741       outs() << format("0x%" PRIx64, n_value);
5742     if (c.data != 0)
5743       outs() << " + " << format("0x%" PRIx64, c.data);
5744   } else
5745     outs() << format("0x%" PRIx64, c.data);
5746   outs() << " (struct class_ro_t *)";
5747 
5748   // This is a Swift class if some of the low bits of the pointer are set.
5749   if ((c.data + n_value) & 0x7)
5750     outs() << " Swift class";
5751   outs() << "\n";
5752   bool is_meta_class;
5753   if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
5754     return;
5755 
5756   if (!is_meta_class &&
5757       c.isa + isa_n_value != p &&
5758       c.isa + isa_n_value != 0 &&
5759       info->depth < 100) {
5760       info->depth++;
5761       outs() << "Meta Class\n";
5762       print_class64_t(c.isa + isa_n_value, info);
5763   }
5764 }
5765 
5766 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
5767   struct class32_t c;
5768   const char *r;
5769   uint32_t offset, left;
5770   SectionRef S;
5771   const char *name;
5772 
5773   r = get_pointer_32(p, offset, left, S, info);
5774   if (r == nullptr)
5775     return;
5776   memset(&c, '\0', sizeof(struct class32_t));
5777   if (left < sizeof(struct class32_t)) {
5778     memcpy(&c, r, left);
5779     outs() << "   (class_t entends past the end of the section)\n";
5780   } else
5781     memcpy(&c, r, sizeof(struct class32_t));
5782   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5783     swapStruct(c);
5784 
5785   outs() << "           isa " << format("0x%" PRIx32, c.isa);
5786   name =
5787       get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
5788   if (name != nullptr)
5789     outs() << " " << name;
5790   outs() << "\n";
5791 
5792   outs() << "    superclass " << format("0x%" PRIx32, c.superclass);
5793   name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
5794                        c.superclass);
5795   if (name != nullptr)
5796     outs() << " " << name;
5797   outs() << "\n";
5798 
5799   outs() << "         cache " << format("0x%" PRIx32, c.cache);
5800   name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
5801                        c.cache);
5802   if (name != nullptr)
5803     outs() << " " << name;
5804   outs() << "\n";
5805 
5806   outs() << "        vtable " << format("0x%" PRIx32, c.vtable);
5807   name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
5808                        c.vtable);
5809   if (name != nullptr)
5810     outs() << " " << name;
5811   outs() << "\n";
5812 
5813   name =
5814       get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
5815   outs() << "          data " << format("0x%" PRIx32, c.data)
5816          << " (struct class_ro_t *)";
5817 
5818   // This is a Swift class if some of the low bits of the pointer are set.
5819   if (c.data & 0x3)
5820     outs() << " Swift class";
5821   outs() << "\n";
5822   bool is_meta_class;
5823   if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
5824     return;
5825 
5826   if (!is_meta_class) {
5827     outs() << "Meta Class\n";
5828     print_class32_t(c.isa, info);
5829   }
5830 }
5831 
5832 static void print_objc_class_t(struct objc_class_t *objc_class,
5833                                struct DisassembleInfo *info) {
5834   uint32_t offset, left, xleft;
5835   const char *name, *p, *ivar_list;
5836   SectionRef S;
5837   int32_t i;
5838   struct objc_ivar_list_t objc_ivar_list;
5839   struct objc_ivar_t ivar;
5840 
5841   outs() << "\t\t      isa " << format("0x%08" PRIx32, objc_class->isa);
5842   if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
5843     name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
5844     if (name != nullptr)
5845       outs() << format(" %.*s", left, name);
5846     else
5847       outs() << " (not in an __OBJC section)";
5848   }
5849   outs() << "\n";
5850 
5851   outs() << "\t      super_class "
5852          << format("0x%08" PRIx32, objc_class->super_class);
5853   if (info->verbose) {
5854     name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
5855     if (name != nullptr)
5856       outs() << format(" %.*s", left, name);
5857     else
5858       outs() << " (not in an __OBJC section)";
5859   }
5860   outs() << "\n";
5861 
5862   outs() << "\t\t     name " << format("0x%08" PRIx32, objc_class->name);
5863   if (info->verbose) {
5864     name = get_pointer_32(objc_class->name, offset, left, S, info, true);
5865     if (name != nullptr)
5866       outs() << format(" %.*s", left, name);
5867     else
5868       outs() << " (not in an __OBJC section)";
5869   }
5870   outs() << "\n";
5871 
5872   outs() << "\t\t  version " << format("0x%08" PRIx32, objc_class->version)
5873          << "\n";
5874 
5875   outs() << "\t\t     info " << format("0x%08" PRIx32, objc_class->info);
5876   if (info->verbose) {
5877     if (CLS_GETINFO(objc_class, CLS_CLASS))
5878       outs() << " CLS_CLASS";
5879     else if (CLS_GETINFO(objc_class, CLS_META))
5880       outs() << " CLS_META";
5881   }
5882   outs() << "\n";
5883 
5884   outs() << "\t    instance_size "
5885          << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
5886 
5887   p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
5888   outs() << "\t\t    ivars " << format("0x%08" PRIx32, objc_class->ivars);
5889   if (p != nullptr) {
5890     if (left > sizeof(struct objc_ivar_list_t)) {
5891       outs() << "\n";
5892       memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
5893     } else {
5894       outs() << " (entends past the end of the section)\n";
5895       memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
5896       memcpy(&objc_ivar_list, p, left);
5897     }
5898     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5899       swapStruct(objc_ivar_list);
5900     outs() << "\t\t       ivar_count " << objc_ivar_list.ivar_count << "\n";
5901     ivar_list = p + sizeof(struct objc_ivar_list_t);
5902     for (i = 0; i < objc_ivar_list.ivar_count; i++) {
5903       if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
5904         outs() << "\t\t remaining ivar's extend past the of the section\n";
5905         break;
5906       }
5907       memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
5908              sizeof(struct objc_ivar_t));
5909       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5910         swapStruct(ivar);
5911 
5912       outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
5913       if (info->verbose) {
5914         name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
5915         if (name != nullptr)
5916           outs() << format(" %.*s", xleft, name);
5917         else
5918           outs() << " (not in an __OBJC section)";
5919       }
5920       outs() << "\n";
5921 
5922       outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
5923       if (info->verbose) {
5924         name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
5925         if (name != nullptr)
5926           outs() << format(" %.*s", xleft, name);
5927         else
5928           outs() << " (not in an __OBJC section)";
5929       }
5930       outs() << "\n";
5931 
5932       outs() << "\t\t      ivar_offset "
5933              << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
5934     }
5935   } else {
5936     outs() << " (not in an __OBJC section)\n";
5937   }
5938 
5939   outs() << "\t\t  methods " << format("0x%08" PRIx32, objc_class->methodLists);
5940   if (print_method_list(objc_class->methodLists, info))
5941     outs() << " (not in an __OBJC section)\n";
5942 
5943   outs() << "\t\t    cache " << format("0x%08" PRIx32, objc_class->cache)
5944          << "\n";
5945 
5946   outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
5947   if (print_protocol_list(objc_class->protocols, 16, info))
5948     outs() << " (not in an __OBJC section)\n";
5949 }
5950 
5951 static void print_objc_objc_category_t(struct objc_category_t *objc_category,
5952                                        struct DisassembleInfo *info) {
5953   uint32_t offset, left;
5954   const char *name;
5955   SectionRef S;
5956 
5957   outs() << "\t       category name "
5958          << format("0x%08" PRIx32, objc_category->category_name);
5959   if (info->verbose) {
5960     name = get_pointer_32(objc_category->category_name, offset, left, S, info,
5961                           true);
5962     if (name != nullptr)
5963       outs() << format(" %.*s", left, name);
5964     else
5965       outs() << " (not in an __OBJC section)";
5966   }
5967   outs() << "\n";
5968 
5969   outs() << "\t\t  class name "
5970          << format("0x%08" PRIx32, objc_category->class_name);
5971   if (info->verbose) {
5972     name =
5973         get_pointer_32(objc_category->class_name, offset, left, S, info, true);
5974     if (name != nullptr)
5975       outs() << format(" %.*s", left, name);
5976     else
5977       outs() << " (not in an __OBJC section)";
5978   }
5979   outs() << "\n";
5980 
5981   outs() << "\t    instance methods "
5982          << format("0x%08" PRIx32, objc_category->instance_methods);
5983   if (print_method_list(objc_category->instance_methods, info))
5984     outs() << " (not in an __OBJC section)\n";
5985 
5986   outs() << "\t       class methods "
5987          << format("0x%08" PRIx32, objc_category->class_methods);
5988   if (print_method_list(objc_category->class_methods, info))
5989     outs() << " (not in an __OBJC section)\n";
5990 }
5991 
5992 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
5993   struct category64_t c;
5994   const char *r;
5995   uint32_t offset, xoffset, left;
5996   SectionRef S, xS;
5997   const char *name, *sym_name;
5998   uint64_t n_value;
5999 
6000   r = get_pointer_64(p, offset, left, S, info);
6001   if (r == nullptr)
6002     return;
6003   memset(&c, '\0', sizeof(struct category64_t));
6004   if (left < sizeof(struct category64_t)) {
6005     memcpy(&c, r, left);
6006     outs() << "   (category_t entends past the end of the section)\n";
6007   } else
6008     memcpy(&c, r, sizeof(struct category64_t));
6009   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6010     swapStruct(c);
6011 
6012   outs() << "              name ";
6013   sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
6014                            info, n_value, c.name);
6015   if (n_value != 0) {
6016     if (info->verbose && sym_name != nullptr)
6017       outs() << sym_name;
6018     else
6019       outs() << format("0x%" PRIx64, n_value);
6020     if (c.name != 0)
6021       outs() << " + " << format("0x%" PRIx64, c.name);
6022   } else
6023     outs() << format("0x%" PRIx64, c.name);
6024   name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
6025   if (name != nullptr)
6026     outs() << format(" %.*s", left, name);
6027   outs() << "\n";
6028 
6029   outs() << "               cls ";
6030   sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
6031                            n_value, c.cls);
6032   if (n_value != 0) {
6033     if (info->verbose && sym_name != nullptr)
6034       outs() << sym_name;
6035     else
6036       outs() << format("0x%" PRIx64, n_value);
6037     if (c.cls != 0)
6038       outs() << " + " << format("0x%" PRIx64, c.cls);
6039   } else
6040     outs() << format("0x%" PRIx64, c.cls);
6041   outs() << "\n";
6042   if (c.cls + n_value != 0)
6043     print_class64_t(c.cls + n_value, info);
6044 
6045   outs() << "   instanceMethods ";
6046   sym_name =
6047       get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
6048                     info, n_value, c.instanceMethods);
6049   if (n_value != 0) {
6050     if (info->verbose && sym_name != nullptr)
6051       outs() << sym_name;
6052     else
6053       outs() << format("0x%" PRIx64, n_value);
6054     if (c.instanceMethods != 0)
6055       outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
6056   } else
6057     outs() << format("0x%" PRIx64, c.instanceMethods);
6058   outs() << "\n";
6059   if (c.instanceMethods + n_value != 0)
6060     print_method_list64_t(c.instanceMethods + n_value, info, "");
6061 
6062   outs() << "      classMethods ";
6063   sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
6064                            S, info, n_value, c.classMethods);
6065   if (n_value != 0) {
6066     if (info->verbose && sym_name != nullptr)
6067       outs() << sym_name;
6068     else
6069       outs() << format("0x%" PRIx64, n_value);
6070     if (c.classMethods != 0)
6071       outs() << " + " << format("0x%" PRIx64, c.classMethods);
6072   } else
6073     outs() << format("0x%" PRIx64, c.classMethods);
6074   outs() << "\n";
6075   if (c.classMethods + n_value != 0)
6076     print_method_list64_t(c.classMethods + n_value, info, "");
6077 
6078   outs() << "         protocols ";
6079   sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
6080                            info, n_value, c.protocols);
6081   if (n_value != 0) {
6082     if (info->verbose && sym_name != nullptr)
6083       outs() << sym_name;
6084     else
6085       outs() << format("0x%" PRIx64, n_value);
6086     if (c.protocols != 0)
6087       outs() << " + " << format("0x%" PRIx64, c.protocols);
6088   } else
6089     outs() << format("0x%" PRIx64, c.protocols);
6090   outs() << "\n";
6091   if (c.protocols + n_value != 0)
6092     print_protocol_list64_t(c.protocols + n_value, info);
6093 
6094   outs() << "instanceProperties ";
6095   sym_name =
6096       get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
6097                     S, info, n_value, c.instanceProperties);
6098   if (n_value != 0) {
6099     if (info->verbose && sym_name != nullptr)
6100       outs() << sym_name;
6101     else
6102       outs() << format("0x%" PRIx64, n_value);
6103     if (c.instanceProperties != 0)
6104       outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
6105   } else
6106     outs() << format("0x%" PRIx64, c.instanceProperties);
6107   outs() << "\n";
6108   if (c.instanceProperties + n_value != 0)
6109     print_objc_property_list64(c.instanceProperties + n_value, info);
6110 }
6111 
6112 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
6113   struct category32_t c;
6114   const char *r;
6115   uint32_t offset, left;
6116   SectionRef S, xS;
6117   const char *name;
6118 
6119   r = get_pointer_32(p, offset, left, S, info);
6120   if (r == nullptr)
6121     return;
6122   memset(&c, '\0', sizeof(struct category32_t));
6123   if (left < sizeof(struct category32_t)) {
6124     memcpy(&c, r, left);
6125     outs() << "   (category_t entends past the end of the section)\n";
6126   } else
6127     memcpy(&c, r, sizeof(struct category32_t));
6128   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6129     swapStruct(c);
6130 
6131   outs() << "              name " << format("0x%" PRIx32, c.name);
6132   name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
6133                        c.name);
6134   if (name)
6135     outs() << " " << name;
6136   outs() << "\n";
6137 
6138   outs() << "               cls " << format("0x%" PRIx32, c.cls) << "\n";
6139   if (c.cls != 0)
6140     print_class32_t(c.cls, info);
6141   outs() << "   instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
6142          << "\n";
6143   if (c.instanceMethods != 0)
6144     print_method_list32_t(c.instanceMethods, info, "");
6145   outs() << "      classMethods " << format("0x%" PRIx32, c.classMethods)
6146          << "\n";
6147   if (c.classMethods != 0)
6148     print_method_list32_t(c.classMethods, info, "");
6149   outs() << "         protocols " << format("0x%" PRIx32, c.protocols) << "\n";
6150   if (c.protocols != 0)
6151     print_protocol_list32_t(c.protocols, info);
6152   outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
6153          << "\n";
6154   if (c.instanceProperties != 0)
6155     print_objc_property_list32(c.instanceProperties, info);
6156 }
6157 
6158 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
6159   uint32_t i, left, offset, xoffset;
6160   uint64_t p, n_value;
6161   struct message_ref64 mr;
6162   const char *name, *sym_name;
6163   const char *r;
6164   SectionRef xS;
6165 
6166   if (S == SectionRef())
6167     return;
6168 
6169   StringRef SectName;
6170   Expected<StringRef> SecNameOrErr = S.getName();
6171   if (SecNameOrErr)
6172     SectName = *SecNameOrErr;
6173   else
6174     consumeError(SecNameOrErr.takeError());
6175 
6176   DataRefImpl Ref = S.getRawDataRefImpl();
6177   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6178   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6179   offset = 0;
6180   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6181     p = S.getAddress() + i;
6182     r = get_pointer_64(p, offset, left, S, info);
6183     if (r == nullptr)
6184       return;
6185     memset(&mr, '\0', sizeof(struct message_ref64));
6186     if (left < sizeof(struct message_ref64)) {
6187       memcpy(&mr, r, left);
6188       outs() << "   (message_ref entends past the end of the section)\n";
6189     } else
6190       memcpy(&mr, r, sizeof(struct message_ref64));
6191     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6192       swapStruct(mr);
6193 
6194     outs() << "  imp ";
6195     name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
6196                          n_value, mr.imp);
6197     if (n_value != 0) {
6198       outs() << format("0x%" PRIx64, n_value) << " ";
6199       if (mr.imp != 0)
6200         outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
6201     } else
6202       outs() << format("0x%" PRIx64, mr.imp) << " ";
6203     if (name != nullptr)
6204       outs() << " " << name;
6205     outs() << "\n";
6206 
6207     outs() << "  sel ";
6208     sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
6209                              info, n_value, mr.sel);
6210     if (n_value != 0) {
6211       if (info->verbose && sym_name != nullptr)
6212         outs() << sym_name;
6213       else
6214         outs() << format("0x%" PRIx64, n_value);
6215       if (mr.sel != 0)
6216         outs() << " + " << format("0x%" PRIx64, mr.sel);
6217     } else
6218       outs() << format("0x%" PRIx64, mr.sel);
6219     name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
6220     if (name != nullptr)
6221       outs() << format(" %.*s", left, name);
6222     outs() << "\n";
6223 
6224     offset += sizeof(struct message_ref64);
6225   }
6226 }
6227 
6228 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
6229   uint32_t i, left, offset, xoffset, p;
6230   struct message_ref32 mr;
6231   const char *name, *r;
6232   SectionRef xS;
6233 
6234   if (S == SectionRef())
6235     return;
6236 
6237   StringRef SectName;
6238   Expected<StringRef> SecNameOrErr = S.getName();
6239   if (SecNameOrErr)
6240     SectName = *SecNameOrErr;
6241   else
6242     consumeError(SecNameOrErr.takeError());
6243 
6244   DataRefImpl Ref = S.getRawDataRefImpl();
6245   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6246   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6247   offset = 0;
6248   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6249     p = S.getAddress() + i;
6250     r = get_pointer_32(p, offset, left, S, info);
6251     if (r == nullptr)
6252       return;
6253     memset(&mr, '\0', sizeof(struct message_ref32));
6254     if (left < sizeof(struct message_ref32)) {
6255       memcpy(&mr, r, left);
6256       outs() << "   (message_ref entends past the end of the section)\n";
6257     } else
6258       memcpy(&mr, r, sizeof(struct message_ref32));
6259     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6260       swapStruct(mr);
6261 
6262     outs() << "  imp " << format("0x%" PRIx32, mr.imp);
6263     name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
6264                          mr.imp);
6265     if (name != nullptr)
6266       outs() << " " << name;
6267     outs() << "\n";
6268 
6269     outs() << "  sel " << format("0x%" PRIx32, mr.sel);
6270     name = get_pointer_32(mr.sel, xoffset, left, xS, info);
6271     if (name != nullptr)
6272       outs() << " " << name;
6273     outs() << "\n";
6274 
6275     offset += sizeof(struct message_ref32);
6276   }
6277 }
6278 
6279 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
6280   uint32_t left, offset, swift_version;
6281   uint64_t p;
6282   struct objc_image_info64 o;
6283   const char *r;
6284 
6285   if (S == SectionRef())
6286     return;
6287 
6288   StringRef SectName;
6289   Expected<StringRef> SecNameOrErr = S.getName();
6290   if (SecNameOrErr)
6291     SectName = *SecNameOrErr;
6292   else
6293     consumeError(SecNameOrErr.takeError());
6294 
6295   DataRefImpl Ref = S.getRawDataRefImpl();
6296   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6297   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6298   p = S.getAddress();
6299   r = get_pointer_64(p, offset, left, S, info);
6300   if (r == nullptr)
6301     return;
6302   memset(&o, '\0', sizeof(struct objc_image_info64));
6303   if (left < sizeof(struct objc_image_info64)) {
6304     memcpy(&o, r, left);
6305     outs() << "   (objc_image_info entends past the end of the section)\n";
6306   } else
6307     memcpy(&o, r, sizeof(struct objc_image_info64));
6308   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6309     swapStruct(o);
6310   outs() << "  version " << o.version << "\n";
6311   outs() << "    flags " << format("0x%" PRIx32, o.flags);
6312   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6313     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6314   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6315     outs() << " OBJC_IMAGE_SUPPORTS_GC";
6316   if (o.flags & OBJC_IMAGE_IS_SIMULATED)
6317     outs() << " OBJC_IMAGE_IS_SIMULATED";
6318   if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES)
6319     outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
6320   swift_version = (o.flags >> 8) & 0xff;
6321   if (swift_version != 0) {
6322     if (swift_version == 1)
6323       outs() << " Swift 1.0";
6324     else if (swift_version == 2)
6325       outs() << " Swift 1.1";
6326     else if(swift_version == 3)
6327       outs() << " Swift 2.0";
6328     else if(swift_version == 4)
6329       outs() << " Swift 3.0";
6330     else if(swift_version == 5)
6331       outs() << " Swift 4.0";
6332     else if(swift_version == 6)
6333       outs() << " Swift 4.1/Swift 4.2";
6334     else if(swift_version == 7)
6335       outs() << " Swift 5 or later";
6336     else
6337       outs() << " unknown future Swift version (" << swift_version << ")";
6338   }
6339   outs() << "\n";
6340 }
6341 
6342 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
6343   uint32_t left, offset, swift_version, p;
6344   struct objc_image_info32 o;
6345   const char *r;
6346 
6347   if (S == SectionRef())
6348     return;
6349 
6350   StringRef SectName;
6351   Expected<StringRef> SecNameOrErr = S.getName();
6352   if (SecNameOrErr)
6353     SectName = *SecNameOrErr;
6354   else
6355     consumeError(SecNameOrErr.takeError());
6356 
6357   DataRefImpl Ref = S.getRawDataRefImpl();
6358   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6359   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6360   p = S.getAddress();
6361   r = get_pointer_32(p, offset, left, S, info);
6362   if (r == nullptr)
6363     return;
6364   memset(&o, '\0', sizeof(struct objc_image_info32));
6365   if (left < sizeof(struct objc_image_info32)) {
6366     memcpy(&o, r, left);
6367     outs() << "   (objc_image_info entends past the end of the section)\n";
6368   } else
6369     memcpy(&o, r, sizeof(struct objc_image_info32));
6370   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6371     swapStruct(o);
6372   outs() << "  version " << o.version << "\n";
6373   outs() << "    flags " << format("0x%" PRIx32, o.flags);
6374   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6375     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6376   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6377     outs() << " OBJC_IMAGE_SUPPORTS_GC";
6378   swift_version = (o.flags >> 8) & 0xff;
6379   if (swift_version != 0) {
6380     if (swift_version == 1)
6381       outs() << " Swift 1.0";
6382     else if (swift_version == 2)
6383       outs() << " Swift 1.1";
6384     else if(swift_version == 3)
6385       outs() << " Swift 2.0";
6386     else if(swift_version == 4)
6387       outs() << " Swift 3.0";
6388     else if(swift_version == 5)
6389       outs() << " Swift 4.0";
6390     else if(swift_version == 6)
6391       outs() << " Swift 4.1/Swift 4.2";
6392     else if(swift_version == 7)
6393       outs() << " Swift 5 or later";
6394     else
6395       outs() << " unknown future Swift version (" << swift_version << ")";
6396   }
6397   outs() << "\n";
6398 }
6399 
6400 static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
6401   uint32_t left, offset, p;
6402   struct imageInfo_t o;
6403   const char *r;
6404 
6405   StringRef SectName;
6406   Expected<StringRef> SecNameOrErr = S.getName();
6407   if (SecNameOrErr)
6408     SectName = *SecNameOrErr;
6409   else
6410     consumeError(SecNameOrErr.takeError());
6411 
6412   DataRefImpl Ref = S.getRawDataRefImpl();
6413   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6414   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6415   p = S.getAddress();
6416   r = get_pointer_32(p, offset, left, S, info);
6417   if (r == nullptr)
6418     return;
6419   memset(&o, '\0', sizeof(struct imageInfo_t));
6420   if (left < sizeof(struct imageInfo_t)) {
6421     memcpy(&o, r, left);
6422     outs() << " (imageInfo entends past the end of the section)\n";
6423   } else
6424     memcpy(&o, r, sizeof(struct imageInfo_t));
6425   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6426     swapStruct(o);
6427   outs() << "  version " << o.version << "\n";
6428   outs() << "    flags " << format("0x%" PRIx32, o.flags);
6429   if (o.flags & 0x1)
6430     outs() << "  F&C";
6431   if (o.flags & 0x2)
6432     outs() << " GC";
6433   if (o.flags & 0x4)
6434     outs() << " GC-only";
6435   else
6436     outs() << " RR";
6437   outs() << "\n";
6438 }
6439 
6440 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
6441   SymbolAddressMap AddrMap;
6442   if (verbose)
6443     CreateSymbolAddressMap(O, &AddrMap);
6444 
6445   std::vector<SectionRef> Sections;
6446   append_range(Sections, O->sections());
6447 
6448   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6449 
6450   SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6451   if (CL == SectionRef())
6452     CL = get_section(O, "__DATA", "__objc_classlist");
6453   if (CL == SectionRef())
6454     CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6455   if (CL == SectionRef())
6456     CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6457   info.S = CL;
6458   walk_pointer_list_64("class", CL, O, &info, print_class64_t);
6459 
6460   SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6461   if (CR == SectionRef())
6462     CR = get_section(O, "__DATA", "__objc_classrefs");
6463   if (CR == SectionRef())
6464     CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6465   if (CR == SectionRef())
6466     CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6467   info.S = CR;
6468   walk_pointer_list_64("class refs", CR, O, &info, nullptr);
6469 
6470   SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6471   if (SR == SectionRef())
6472     SR = get_section(O, "__DATA", "__objc_superrefs");
6473   if (SR == SectionRef())
6474     SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6475   if (SR == SectionRef())
6476     SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6477   info.S = SR;
6478   walk_pointer_list_64("super refs", SR, O, &info, nullptr);
6479 
6480   SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6481   if (CA == SectionRef())
6482     CA = get_section(O, "__DATA", "__objc_catlist");
6483   if (CA == SectionRef())
6484     CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6485   if (CA == SectionRef())
6486     CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6487   info.S = CA;
6488   walk_pointer_list_64("category", CA, O, &info, print_category64_t);
6489 
6490   SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6491   if (PL == SectionRef())
6492     PL = get_section(O, "__DATA", "__objc_protolist");
6493   if (PL == SectionRef())
6494     PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6495   if (PL == SectionRef())
6496     PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6497   info.S = PL;
6498   walk_pointer_list_64("protocol", PL, O, &info, nullptr);
6499 
6500   SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6501   if (MR == SectionRef())
6502     MR = get_section(O, "__DATA", "__objc_msgrefs");
6503   if (MR == SectionRef())
6504     MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6505   if (MR == SectionRef())
6506     MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6507   info.S = MR;
6508   print_message_refs64(MR, &info);
6509 
6510   SectionRef II = get_section(O, "__OBJC2", "__image_info");
6511   if (II == SectionRef())
6512     II = get_section(O, "__DATA", "__objc_imageinfo");
6513   if (II == SectionRef())
6514     II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6515   if (II == SectionRef())
6516     II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6517   info.S = II;
6518   print_image_info64(II, &info);
6519 }
6520 
6521 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6522   SymbolAddressMap AddrMap;
6523   if (verbose)
6524     CreateSymbolAddressMap(O, &AddrMap);
6525 
6526   std::vector<SectionRef> Sections;
6527   append_range(Sections, O->sections());
6528 
6529   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6530 
6531   SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6532   if (CL == SectionRef())
6533     CL = get_section(O, "__DATA", "__objc_classlist");
6534   if (CL == SectionRef())
6535     CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6536   if (CL == SectionRef())
6537     CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6538   info.S = CL;
6539   walk_pointer_list_32("class", CL, O, &info, print_class32_t);
6540 
6541   SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6542   if (CR == SectionRef())
6543     CR = get_section(O, "__DATA", "__objc_classrefs");
6544   if (CR == SectionRef())
6545     CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6546   if (CR == SectionRef())
6547     CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6548   info.S = CR;
6549   walk_pointer_list_32("class refs", CR, O, &info, nullptr);
6550 
6551   SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6552   if (SR == SectionRef())
6553     SR = get_section(O, "__DATA", "__objc_superrefs");
6554   if (SR == SectionRef())
6555     SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6556   if (SR == SectionRef())
6557     SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6558   info.S = SR;
6559   walk_pointer_list_32("super refs", SR, O, &info, nullptr);
6560 
6561   SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6562   if (CA == SectionRef())
6563     CA = get_section(O, "__DATA", "__objc_catlist");
6564   if (CA == SectionRef())
6565     CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6566   if (CA == SectionRef())
6567     CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6568   info.S = CA;
6569   walk_pointer_list_32("category", CA, O, &info, print_category32_t);
6570 
6571   SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6572   if (PL == SectionRef())
6573     PL = get_section(O, "__DATA", "__objc_protolist");
6574   if (PL == SectionRef())
6575     PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6576   if (PL == SectionRef())
6577     PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6578   info.S = PL;
6579   walk_pointer_list_32("protocol", PL, O, &info, nullptr);
6580 
6581   SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6582   if (MR == SectionRef())
6583     MR = get_section(O, "__DATA", "__objc_msgrefs");
6584   if (MR == SectionRef())
6585     MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6586   if (MR == SectionRef())
6587     MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6588   info.S = MR;
6589   print_message_refs32(MR, &info);
6590 
6591   SectionRef II = get_section(O, "__OBJC2", "__image_info");
6592   if (II == SectionRef())
6593     II = get_section(O, "__DATA", "__objc_imageinfo");
6594   if (II == SectionRef())
6595     II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6596   if (II == SectionRef())
6597     II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6598   info.S = II;
6599   print_image_info32(II, &info);
6600 }
6601 
6602 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6603   uint32_t i, j, p, offset, xoffset, left, defs_left, def;
6604   const char *r, *name, *defs;
6605   struct objc_module_t module;
6606   SectionRef S, xS;
6607   struct objc_symtab_t symtab;
6608   struct objc_class_t objc_class;
6609   struct objc_category_t objc_category;
6610 
6611   outs() << "Objective-C segment\n";
6612   S = get_section(O, "__OBJC", "__module_info");
6613   if (S == SectionRef())
6614     return false;
6615 
6616   SymbolAddressMap AddrMap;
6617   if (verbose)
6618     CreateSymbolAddressMap(O, &AddrMap);
6619 
6620   std::vector<SectionRef> Sections;
6621   append_range(Sections, O->sections());
6622 
6623   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6624 
6625   for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
6626     p = S.getAddress() + i;
6627     r = get_pointer_32(p, offset, left, S, &info, true);
6628     if (r == nullptr)
6629       return true;
6630     memset(&module, '\0', sizeof(struct objc_module_t));
6631     if (left < sizeof(struct objc_module_t)) {
6632       memcpy(&module, r, left);
6633       outs() << "   (module extends past end of __module_info section)\n";
6634     } else
6635       memcpy(&module, r, sizeof(struct objc_module_t));
6636     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6637       swapStruct(module);
6638 
6639     outs() << "Module " << format("0x%" PRIx32, p) << "\n";
6640     outs() << "    version " << module.version << "\n";
6641     outs() << "       size " << module.size << "\n";
6642     outs() << "       name ";
6643     name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
6644     if (name != nullptr)
6645       outs() << format("%.*s", left, name);
6646     else
6647       outs() << format("0x%08" PRIx32, module.name)
6648              << "(not in an __OBJC section)";
6649     outs() << "\n";
6650 
6651     r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
6652     if (module.symtab == 0 || r == nullptr) {
6653       outs() << "     symtab " << format("0x%08" PRIx32, module.symtab)
6654              << " (not in an __OBJC section)\n";
6655       continue;
6656     }
6657     outs() << "     symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
6658     memset(&symtab, '\0', sizeof(struct objc_symtab_t));
6659     defs_left = 0;
6660     defs = nullptr;
6661     if (left < sizeof(struct objc_symtab_t)) {
6662       memcpy(&symtab, r, left);
6663       outs() << "\tsymtab extends past end of an __OBJC section)\n";
6664     } else {
6665       memcpy(&symtab, r, sizeof(struct objc_symtab_t));
6666       if (left > sizeof(struct objc_symtab_t)) {
6667         defs_left = left - sizeof(struct objc_symtab_t);
6668         defs = r + sizeof(struct objc_symtab_t);
6669       }
6670     }
6671     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6672       swapStruct(symtab);
6673 
6674     outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
6675     r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
6676     outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
6677     if (r == nullptr)
6678       outs() << " (not in an __OBJC section)";
6679     outs() << "\n";
6680     outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
6681     outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
6682     if (symtab.cls_def_cnt > 0)
6683       outs() << "\tClass Definitions\n";
6684     for (j = 0; j < symtab.cls_def_cnt; j++) {
6685       if ((j + 1) * sizeof(uint32_t) > defs_left) {
6686         outs() << "\t(remaining class defs entries entends past the end of the "
6687                << "section)\n";
6688         break;
6689       }
6690       memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
6691       if (O->isLittleEndian() != sys::IsLittleEndianHost)
6692         sys::swapByteOrder(def);
6693 
6694       r = get_pointer_32(def, xoffset, left, xS, &info, true);
6695       outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
6696       if (r != nullptr) {
6697         if (left > sizeof(struct objc_class_t)) {
6698           outs() << "\n";
6699           memcpy(&objc_class, r, sizeof(struct objc_class_t));
6700         } else {
6701           outs() << " (entends past the end of the section)\n";
6702           memset(&objc_class, '\0', sizeof(struct objc_class_t));
6703           memcpy(&objc_class, r, left);
6704         }
6705         if (O->isLittleEndian() != sys::IsLittleEndianHost)
6706           swapStruct(objc_class);
6707         print_objc_class_t(&objc_class, &info);
6708       } else {
6709         outs() << "(not in an __OBJC section)\n";
6710       }
6711 
6712       if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
6713         outs() << "\tMeta Class";
6714         r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
6715         if (r != nullptr) {
6716           if (left > sizeof(struct objc_class_t)) {
6717             outs() << "\n";
6718             memcpy(&objc_class, r, sizeof(struct objc_class_t));
6719           } else {
6720             outs() << " (entends past the end of the section)\n";
6721             memset(&objc_class, '\0', sizeof(struct objc_class_t));
6722             memcpy(&objc_class, r, left);
6723           }
6724           if (O->isLittleEndian() != sys::IsLittleEndianHost)
6725             swapStruct(objc_class);
6726           print_objc_class_t(&objc_class, &info);
6727         } else {
6728           outs() << "(not in an __OBJC section)\n";
6729         }
6730       }
6731     }
6732     if (symtab.cat_def_cnt > 0)
6733       outs() << "\tCategory Definitions\n";
6734     for (j = 0; j < symtab.cat_def_cnt; j++) {
6735       if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
6736         outs() << "\t(remaining category defs entries entends past the end of "
6737                << "the section)\n";
6738         break;
6739       }
6740       memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
6741              sizeof(uint32_t));
6742       if (O->isLittleEndian() != sys::IsLittleEndianHost)
6743         sys::swapByteOrder(def);
6744 
6745       r = get_pointer_32(def, xoffset, left, xS, &info, true);
6746       outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
6747              << format("0x%08" PRIx32, def);
6748       if (r != nullptr) {
6749         if (left > sizeof(struct objc_category_t)) {
6750           outs() << "\n";
6751           memcpy(&objc_category, r, sizeof(struct objc_category_t));
6752         } else {
6753           outs() << " (entends past the end of the section)\n";
6754           memset(&objc_category, '\0', sizeof(struct objc_category_t));
6755           memcpy(&objc_category, r, left);
6756         }
6757         if (O->isLittleEndian() != sys::IsLittleEndianHost)
6758           swapStruct(objc_category);
6759         print_objc_objc_category_t(&objc_category, &info);
6760       } else {
6761         outs() << "(not in an __OBJC section)\n";
6762       }
6763     }
6764   }
6765   const SectionRef II = get_section(O, "__OBJC", "__image_info");
6766   if (II != SectionRef())
6767     print_image_info(II, &info);
6768 
6769   return true;
6770 }
6771 
6772 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
6773                                 uint32_t size, uint32_t addr) {
6774   SymbolAddressMap AddrMap;
6775   CreateSymbolAddressMap(O, &AddrMap);
6776 
6777   std::vector<SectionRef> Sections;
6778   append_range(Sections, O->sections());
6779 
6780   struct DisassembleInfo info(O, &AddrMap, &Sections, true);
6781 
6782   const char *p;
6783   struct objc_protocol_t protocol;
6784   uint32_t left, paddr;
6785   for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
6786     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
6787     left = size - (p - sect);
6788     if (left < sizeof(struct objc_protocol_t)) {
6789       outs() << "Protocol extends past end of __protocol section\n";
6790       memcpy(&protocol, p, left);
6791     } else
6792       memcpy(&protocol, p, sizeof(struct objc_protocol_t));
6793     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6794       swapStruct(protocol);
6795     paddr = addr + (p - sect);
6796     outs() << "Protocol " << format("0x%" PRIx32, paddr);
6797     if (print_protocol(paddr, 0, &info))
6798       outs() << "(not in an __OBJC section)\n";
6799   }
6800 }
6801 
6802 static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
6803   if (O->is64Bit())
6804     printObjc2_64bit_MetaData(O, verbose);
6805   else {
6806     MachO::mach_header H;
6807     H = O->getHeader();
6808     if (H.cputype == MachO::CPU_TYPE_ARM)
6809       printObjc2_32bit_MetaData(O, verbose);
6810     else {
6811       // This is the 32-bit non-arm cputype case.  Which is normally
6812       // the first Objective-C ABI.  But it may be the case of a
6813       // binary for the iOS simulator which is the second Objective-C
6814       // ABI.  In that case printObjc1_32bit_MetaData() will determine that
6815       // and return false.
6816       if (!printObjc1_32bit_MetaData(O, verbose))
6817         printObjc2_32bit_MetaData(O, verbose);
6818     }
6819   }
6820 }
6821 
6822 // GuessLiteralPointer returns a string which for the item in the Mach-O file
6823 // for the address passed in as ReferenceValue for printing as a comment with
6824 // the instruction and also returns the corresponding type of that item
6825 // indirectly through ReferenceType.
6826 //
6827 // If ReferenceValue is an address of literal cstring then a pointer to the
6828 // cstring is returned and ReferenceType is set to
6829 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
6830 //
6831 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or
6832 // Class ref that name is returned and the ReferenceType is set accordingly.
6833 //
6834 // Lastly, literals which are Symbol address in a literal pool are looked for
6835 // and if found the symbol name is returned and ReferenceType is set to
6836 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
6837 //
6838 // If there is no item in the Mach-O file for the address passed in as
6839 // ReferenceValue nullptr is returned and ReferenceType is unchanged.
6840 static const char *GuessLiteralPointer(uint64_t ReferenceValue,
6841                                        uint64_t ReferencePC,
6842                                        uint64_t *ReferenceType,
6843                                        struct DisassembleInfo *info) {
6844   // First see if there is an external relocation entry at the ReferencePC.
6845   if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
6846     uint64_t sect_addr = info->S.getAddress();
6847     uint64_t sect_offset = ReferencePC - sect_addr;
6848     bool reloc_found = false;
6849     DataRefImpl Rel;
6850     MachO::any_relocation_info RE;
6851     bool isExtern = false;
6852     SymbolRef Symbol;
6853     for (const RelocationRef &Reloc : info->S.relocations()) {
6854       uint64_t RelocOffset = Reloc.getOffset();
6855       if (RelocOffset == sect_offset) {
6856         Rel = Reloc.getRawDataRefImpl();
6857         RE = info->O->getRelocation(Rel);
6858         if (info->O->isRelocationScattered(RE))
6859           continue;
6860         isExtern = info->O->getPlainRelocationExternal(RE);
6861         if (isExtern) {
6862           symbol_iterator RelocSym = Reloc.getSymbol();
6863           Symbol = *RelocSym;
6864         }
6865         reloc_found = true;
6866         break;
6867       }
6868     }
6869     // If there is an external relocation entry for a symbol in a section
6870     // then used that symbol's value for the value of the reference.
6871     if (reloc_found && isExtern) {
6872       if (info->O->getAnyRelocationPCRel(RE)) {
6873         unsigned Type = info->O->getAnyRelocationType(RE);
6874         if (Type == MachO::X86_64_RELOC_SIGNED) {
6875           ReferenceValue = cantFail(Symbol.getValue());
6876         }
6877       }
6878     }
6879   }
6880 
6881   // Look for literals such as Objective-C CFStrings refs, Selector refs,
6882   // Message refs and Class refs.
6883   bool classref, selref, msgref, cfstring;
6884   uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
6885                                                selref, msgref, cfstring);
6886   if (classref && pointer_value == 0) {
6887     // Note the ReferenceValue is a pointer into the __objc_classrefs section.
6888     // And the pointer_value in that section is typically zero as it will be
6889     // set by dyld as part of the "bind information".
6890     const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
6891     if (name != nullptr) {
6892       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6893       const char *class_name = strrchr(name, '$');
6894       if (class_name != nullptr && class_name[1] == '_' &&
6895           class_name[2] != '\0') {
6896         info->class_name = class_name + 2;
6897         return name;
6898       }
6899     }
6900   }
6901 
6902   if (classref) {
6903     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6904     const char *name =
6905         get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
6906     if (name != nullptr)
6907       info->class_name = name;
6908     else
6909       name = "bad class ref";
6910     return name;
6911   }
6912 
6913   if (cfstring) {
6914     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
6915     const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
6916     return name;
6917   }
6918 
6919   if (selref && pointer_value == 0)
6920     pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
6921 
6922   if (pointer_value != 0)
6923     ReferenceValue = pointer_value;
6924 
6925   const char *name = GuessCstringPointer(ReferenceValue, info);
6926   if (name) {
6927     if (pointer_value != 0 && selref) {
6928       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
6929       info->selector_name = name;
6930     } else if (pointer_value != 0 && msgref) {
6931       info->class_name = nullptr;
6932       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
6933       info->selector_name = name;
6934     } else
6935       *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
6936     return name;
6937   }
6938 
6939   // Lastly look for an indirect symbol with this ReferenceValue which is in
6940   // a literal pool.  If found return that symbol name.
6941   name = GuessIndirectSymbol(ReferenceValue, info);
6942   if (name) {
6943     *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
6944     return name;
6945   }
6946 
6947   return nullptr;
6948 }
6949 
6950 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
6951 // the Symbolizer.  It looks up the ReferenceValue using the info passed via the
6952 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
6953 // is created and returns the symbol name that matches the ReferenceValue or
6954 // nullptr if none.  The ReferenceType is passed in for the IN type of
6955 // reference the instruction is making from the values in defined in the header
6956 // "llvm-c/Disassembler.h".  On return the ReferenceType can set to a specific
6957 // Out type and the ReferenceName will also be set which is added as a comment
6958 // to the disassembled instruction.
6959 //
6960 // If the symbol name is a C++ mangled name then the demangled name is
6961 // returned through ReferenceName and ReferenceType is set to
6962 // LLVMDisassembler_ReferenceType_DeMangled_Name .
6963 //
6964 // When this is called to get a symbol name for a branch target then the
6965 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
6966 // SymbolValue will be looked for in the indirect symbol table to determine if
6967 // it is an address for a symbol stub.  If so then the symbol name for that
6968 // stub is returned indirectly through ReferenceName and then ReferenceType is
6969 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
6970 //
6971 // When this is called with an value loaded via a PC relative load then
6972 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
6973 // SymbolValue is checked to be an address of literal pointer, symbol pointer,
6974 // or an Objective-C meta data reference.  If so the output ReferenceType is
6975 // set to correspond to that as well as setting the ReferenceName.
6976 static const char *SymbolizerSymbolLookUp(void *DisInfo,
6977                                           uint64_t ReferenceValue,
6978                                           uint64_t *ReferenceType,
6979                                           uint64_t ReferencePC,
6980                                           const char **ReferenceName) {
6981   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
6982   // If no verbose symbolic information is wanted then just return nullptr.
6983   if (!info->verbose) {
6984     *ReferenceName = nullptr;
6985     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6986     return nullptr;
6987   }
6988 
6989   const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
6990 
6991   if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
6992     *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
6993     if (*ReferenceName != nullptr) {
6994       method_reference(info, ReferenceType, ReferenceName);
6995       if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
6996         *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
6997     } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6998       if (info->demangled_name != nullptr)
6999         free(info->demangled_name);
7000       info->demangled_name = itaniumDemangle(SymbolName + 1);
7001       if (info->demangled_name != nullptr) {
7002         *ReferenceName = info->demangled_name;
7003         *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
7004       } else
7005         *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7006     } else
7007       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7008   } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
7009     *ReferenceName =
7010         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7011     if (*ReferenceName)
7012       method_reference(info, ReferenceType, ReferenceName);
7013     else
7014       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7015     // If this is arm64 and the reference is an adrp instruction save the
7016     // instruction, passed in ReferenceValue and the address of the instruction
7017     // for use later if we see and add immediate instruction.
7018   } else if (info->O->getArch() == Triple::aarch64 &&
7019              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
7020     info->adrp_inst = ReferenceValue;
7021     info->adrp_addr = ReferencePC;
7022     SymbolName = nullptr;
7023     *ReferenceName = nullptr;
7024     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7025     // If this is arm64 and reference is an add immediate instruction and we
7026     // have
7027     // seen an adrp instruction just before it and the adrp's Xd register
7028     // matches
7029     // this add's Xn register reconstruct the value being referenced and look to
7030     // see if it is a literal pointer.  Note the add immediate instruction is
7031     // passed in ReferenceValue.
7032   } else if (info->O->getArch() == Triple::aarch64 &&
7033              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
7034              ReferencePC - 4 == info->adrp_addr &&
7035              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
7036              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
7037     uint32_t addxri_inst;
7038     uint64_t adrp_imm, addxri_imm;
7039 
7040     adrp_imm =
7041         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
7042     if (info->adrp_inst & 0x0200000)
7043       adrp_imm |= 0xfffffffffc000000LL;
7044 
7045     addxri_inst = ReferenceValue;
7046     addxri_imm = (addxri_inst >> 10) & 0xfff;
7047     if (((addxri_inst >> 22) & 0x3) == 1)
7048       addxri_imm <<= 12;
7049 
7050     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
7051                      (adrp_imm << 12) + addxri_imm;
7052 
7053     *ReferenceName =
7054         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7055     if (*ReferenceName == nullptr)
7056       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7057     // If this is arm64 and the reference is a load register instruction and we
7058     // have seen an adrp instruction just before it and the adrp's Xd register
7059     // matches this add's Xn register reconstruct the value being referenced and
7060     // look to see if it is a literal pointer.  Note the load register
7061     // instruction is passed in ReferenceValue.
7062   } else if (info->O->getArch() == Triple::aarch64 &&
7063              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
7064              ReferencePC - 4 == info->adrp_addr &&
7065              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
7066              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
7067     uint32_t ldrxui_inst;
7068     uint64_t adrp_imm, ldrxui_imm;
7069 
7070     adrp_imm =
7071         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
7072     if (info->adrp_inst & 0x0200000)
7073       adrp_imm |= 0xfffffffffc000000LL;
7074 
7075     ldrxui_inst = ReferenceValue;
7076     ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
7077 
7078     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
7079                      (adrp_imm << 12) + (ldrxui_imm << 3);
7080 
7081     *ReferenceName =
7082         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7083     if (*ReferenceName == nullptr)
7084       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7085   }
7086   // If this arm64 and is an load register (PC-relative) instruction the
7087   // ReferenceValue is the PC plus the immediate value.
7088   else if (info->O->getArch() == Triple::aarch64 &&
7089            (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
7090             *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
7091     *ReferenceName =
7092         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7093     if (*ReferenceName == nullptr)
7094       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7095   } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
7096     if (info->demangled_name != nullptr)
7097       free(info->demangled_name);
7098     info->demangled_name = itaniumDemangle(SymbolName + 1);
7099     if (info->demangled_name != nullptr) {
7100       *ReferenceName = info->demangled_name;
7101       *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
7102     }
7103   }
7104   else {
7105     *ReferenceName = nullptr;
7106     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7107   }
7108 
7109   return SymbolName;
7110 }
7111 
7112 /// Emits the comments that are stored in the CommentStream.
7113 /// Each comment in the CommentStream must end with a newline.
7114 static void emitComments(raw_svector_ostream &CommentStream,
7115                          SmallString<128> &CommentsToEmit,
7116                          formatted_raw_ostream &FormattedOS,
7117                          const MCAsmInfo &MAI) {
7118   // Flush the stream before taking its content.
7119   StringRef Comments = CommentsToEmit.str();
7120   // Get the default information for printing a comment.
7121   StringRef CommentBegin = MAI.getCommentString();
7122   unsigned CommentColumn = MAI.getCommentColumn();
7123   ListSeparator LS("\n");
7124   while (!Comments.empty()) {
7125     FormattedOS << LS;
7126     // Emit a line of comments.
7127     FormattedOS.PadToColumn(CommentColumn);
7128     size_t Position = Comments.find('\n');
7129     FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
7130     // Move after the newline character.
7131     Comments = Comments.substr(Position + 1);
7132   }
7133   FormattedOS.flush();
7134 
7135   // Tell the comment stream that the vector changed underneath it.
7136   CommentsToEmit.clear();
7137 }
7138 
7139 const MachOObjectFile *
7140 objdump::getMachODSymObject(const MachOObjectFile *MachOOF, StringRef Filename,
7141                             std::unique_ptr<Binary> &DSYMBinary,
7142                             std::unique_ptr<MemoryBuffer> &DSYMBuf) {
7143   const MachOObjectFile *DbgObj = MachOOF;
7144   std::string DSYMPath;
7145 
7146   // Auto-detect w/o --dsym.
7147   if (DSYMFile.empty()) {
7148     sys::fs::file_status DSYMStatus;
7149     Twine FilenameDSYM = Filename + ".dSYM";
7150     if (!status(FilenameDSYM, DSYMStatus)) {
7151       if (sys::fs::is_directory(DSYMStatus)) {
7152         SmallString<1024> Path;
7153         FilenameDSYM.toVector(Path);
7154         sys::path::append(Path, "Contents", "Resources", "DWARF",
7155                           sys::path::filename(Filename));
7156         DSYMPath = std::string(Path);
7157       } else if (sys::fs::is_regular_file(DSYMStatus)) {
7158         DSYMPath = FilenameDSYM.str();
7159       }
7160     }
7161   }
7162 
7163   if (DSYMPath.empty() && !DSYMFile.empty()) {
7164     // If DSYMPath is a .dSYM directory, append the Mach-O file.
7165     if (sys::fs::is_directory(DSYMFile) &&
7166         sys::path::extension(DSYMFile) == ".dSYM") {
7167       SmallString<128> ShortName(sys::path::filename(DSYMFile));
7168       sys::path::replace_extension(ShortName, "");
7169       SmallString<1024> FullPath(DSYMFile);
7170       sys::path::append(FullPath, "Contents", "Resources", "DWARF", ShortName);
7171       DSYMPath = FullPath.str();
7172     } else {
7173       DSYMPath = DSYMFile;
7174     }
7175   }
7176 
7177   if (!DSYMPath.empty()) {
7178     // Load the file.
7179     ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
7180         MemoryBuffer::getFileOrSTDIN(DSYMPath);
7181     if (std::error_code EC = BufOrErr.getError()) {
7182       reportError(errorCodeToError(EC), DSYMPath);
7183       return nullptr;
7184     }
7185 
7186     // We need to keep the file alive, because we're replacing DbgObj with it.
7187     DSYMBuf = std::move(BufOrErr.get());
7188 
7189     Expected<std::unique_ptr<Binary>> BinaryOrErr =
7190         createBinary(DSYMBuf->getMemBufferRef());
7191     if (!BinaryOrErr) {
7192       reportError(BinaryOrErr.takeError(), DSYMPath);
7193       return nullptr;
7194     }
7195 
7196     // We need to keep the Binary alive with the buffer
7197     DSYMBinary = std::move(BinaryOrErr.get());
7198     if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) {
7199       // this is a Mach-O object file, use it
7200       if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) {
7201         DbgObj = MachDSYM;
7202       } else {
7203         WithColor::error(errs(), "llvm-objdump")
7204             << DSYMPath << " is not a Mach-O file type.\n";
7205         return nullptr;
7206       }
7207     } else if (auto *UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())) {
7208       // this is a Universal Binary, find a Mach-O for this architecture
7209       uint32_t CPUType, CPUSubType;
7210       const char *ArchFlag;
7211       if (MachOOF->is64Bit()) {
7212         const MachO::mach_header_64 H_64 = MachOOF->getHeader64();
7213         CPUType = H_64.cputype;
7214         CPUSubType = H_64.cpusubtype;
7215       } else {
7216         const MachO::mach_header H = MachOOF->getHeader();
7217         CPUType = H.cputype;
7218         CPUSubType = H.cpusubtype;
7219       }
7220       Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr,
7221                                                 &ArchFlag);
7222       Expected<std::unique_ptr<MachOObjectFile>> MachDSYM =
7223           UB->getMachOObjectForArch(ArchFlag);
7224       if (!MachDSYM) {
7225         reportError(MachDSYM.takeError(), DSYMPath);
7226         return nullptr;
7227       }
7228 
7229       // We need to keep the Binary alive with the buffer
7230       DbgObj = &*MachDSYM.get();
7231       DSYMBinary = std::move(*MachDSYM);
7232     } else {
7233       WithColor::error(errs(), "llvm-objdump")
7234           << DSYMPath << " is not a Mach-O or Universal file type.\n";
7235       return nullptr;
7236     }
7237   }
7238   return DbgObj;
7239 }
7240 
7241 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
7242                              StringRef DisSegName, StringRef DisSectName) {
7243   const char *McpuDefault = nullptr;
7244   const Target *ThumbTarget = nullptr;
7245   const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
7246   if (!TheTarget) {
7247     // GetTarget prints out stuff.
7248     return;
7249   }
7250   std::string MachOMCPU;
7251   if (MCPU.empty() && McpuDefault)
7252     MachOMCPU = McpuDefault;
7253   else
7254     MachOMCPU = MCPU;
7255 
7256 #define CHECK_TARGET_INFO_CREATION(NAME)                                       \
7257   do {                                                                         \
7258     if (!NAME) {                                                               \
7259       WithColor::error(errs(), "llvm-objdump")                                 \
7260           << "couldn't initialize disassembler for target " << TripleName      \
7261           << '\n';                                                             \
7262       return;                                                                  \
7263     }                                                                          \
7264   } while (false)
7265 #define CHECK_THUMB_TARGET_INFO_CREATION(NAME)                                 \
7266   do {                                                                         \
7267     if (!NAME) {                                                               \
7268       WithColor::error(errs(), "llvm-objdump")                                 \
7269           << "couldn't initialize disassembler for target " << ThumbTripleName \
7270           << '\n';                                                             \
7271       return;                                                                  \
7272     }                                                                          \
7273   } while (false)
7274 
7275   std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
7276   CHECK_TARGET_INFO_CREATION(InstrInfo);
7277   std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
7278   if (ThumbTarget) {
7279     ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
7280     CHECK_THUMB_TARGET_INFO_CREATION(ThumbInstrInfo);
7281   }
7282 
7283   // Package up features to be passed to target/subtarget
7284   std::string FeaturesStr;
7285   if (!MAttrs.empty()) {
7286     SubtargetFeatures Features;
7287     for (unsigned i = 0; i != MAttrs.size(); ++i)
7288       Features.AddFeature(MAttrs[i]);
7289     FeaturesStr = Features.getString();
7290   }
7291 
7292   MCTargetOptions MCOptions;
7293   // Set up disassembler.
7294   std::unique_ptr<const MCRegisterInfo> MRI(
7295       TheTarget->createMCRegInfo(TripleName));
7296   CHECK_TARGET_INFO_CREATION(MRI);
7297   std::unique_ptr<const MCAsmInfo> AsmInfo(
7298       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
7299   CHECK_TARGET_INFO_CREATION(AsmInfo);
7300   std::unique_ptr<const MCSubtargetInfo> STI(
7301       TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
7302   CHECK_TARGET_INFO_CREATION(STI);
7303   MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
7304   std::unique_ptr<MCDisassembler> DisAsm(
7305       TheTarget->createMCDisassembler(*STI, Ctx));
7306   CHECK_TARGET_INFO_CREATION(DisAsm);
7307   std::unique_ptr<MCSymbolizer> Symbolizer;
7308   struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
7309   std::unique_ptr<MCRelocationInfo> RelInfo(
7310       TheTarget->createMCRelocationInfo(TripleName, Ctx));
7311   if (RelInfo) {
7312     Symbolizer.reset(TheTarget->createMCSymbolizer(
7313         TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7314         &SymbolizerInfo, &Ctx, std::move(RelInfo)));
7315     DisAsm->setSymbolizer(std::move(Symbolizer));
7316   }
7317   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
7318   std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
7319       Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
7320   CHECK_TARGET_INFO_CREATION(IP);
7321   // Set the display preference for hex vs. decimal immediates.
7322   IP->setPrintImmHex(PrintImmHex);
7323   // Comment stream and backing vector.
7324   SmallString<128> CommentsToEmit;
7325   raw_svector_ostream CommentStream(CommentsToEmit);
7326   // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
7327   // if it is done then arm64 comments for string literals don't get printed
7328   // and some constant get printed instead and not setting it causes intel
7329   // (32-bit and 64-bit) comments printed with different spacing before the
7330   // comment causing different diffs with the 'C' disassembler library API.
7331   // IP->setCommentStream(CommentStream);
7332 
7333   for (StringRef Opt : DisassemblerOptions)
7334     if (!IP->applyTargetSpecificCLOption(Opt))
7335       reportError(Filename, "unrecognized disassembler option: " + Opt);
7336 
7337   // Set up separate thumb disassembler if needed.
7338   std::unique_ptr<const MCRegisterInfo> ThumbMRI;
7339   std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
7340   std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
7341   std::unique_ptr<MCDisassembler> ThumbDisAsm;
7342   std::unique_ptr<MCInstPrinter> ThumbIP;
7343   std::unique_ptr<MCContext> ThumbCtx;
7344   std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
7345   struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
7346   std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
7347   if (ThumbTarget) {
7348     ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
7349     CHECK_THUMB_TARGET_INFO_CREATION(ThumbMRI);
7350     ThumbAsmInfo.reset(
7351         ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions));
7352     CHECK_THUMB_TARGET_INFO_CREATION(ThumbAsmInfo);
7353     ThumbSTI.reset(
7354         ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
7355                                            FeaturesStr));
7356     CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI);
7357     ThumbCtx.reset(new MCContext(Triple(ThumbTripleName), ThumbAsmInfo.get(),
7358                                  ThumbMRI.get(), ThumbSTI.get()));
7359     ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
7360     CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm);
7361     MCContext *PtrThumbCtx = ThumbCtx.get();
7362     ThumbRelInfo.reset(
7363         ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
7364     if (ThumbRelInfo) {
7365       ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
7366           ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7367           &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
7368       ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
7369     }
7370     int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
7371     ThumbIP.reset(ThumbTarget->createMCInstPrinter(
7372         Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
7373         *ThumbInstrInfo, *ThumbMRI));
7374     CHECK_THUMB_TARGET_INFO_CREATION(ThumbIP);
7375     // Set the display preference for hex vs. decimal immediates.
7376     ThumbIP->setPrintImmHex(PrintImmHex);
7377   }
7378 
7379 #undef CHECK_TARGET_INFO_CREATION
7380 #undef CHECK_THUMB_TARGET_INFO_CREATION
7381 
7382   MachO::mach_header Header = MachOOF->getHeader();
7383 
7384   // FIXME: Using the -cfg command line option, this code used to be able to
7385   // annotate relocations with the referenced symbol's name, and if this was
7386   // inside a __[cf]string section, the data it points to. This is now replaced
7387   // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
7388   std::vector<SectionRef> Sections;
7389   std::vector<SymbolRef> Symbols;
7390   SmallVector<uint64_t, 8> FoundFns;
7391   uint64_t BaseSegmentAddress = 0;
7392 
7393   getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
7394                         BaseSegmentAddress);
7395 
7396   // Sort the symbols by address, just in case they didn't come in that way.
7397   llvm::stable_sort(Symbols, SymbolSorter());
7398 
7399   // Build a data in code table that is sorted on by the address of each entry.
7400   uint64_t BaseAddress = 0;
7401   if (Header.filetype == MachO::MH_OBJECT)
7402     BaseAddress = Sections[0].getAddress();
7403   else
7404     BaseAddress = BaseSegmentAddress;
7405   DiceTable Dices;
7406   for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
7407        DI != DE; ++DI) {
7408     uint32_t Offset;
7409     DI->getOffset(Offset);
7410     Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
7411   }
7412   array_pod_sort(Dices.begin(), Dices.end());
7413 
7414   // Try to find debug info and set up the DIContext for it.
7415   std::unique_ptr<DIContext> diContext;
7416   std::unique_ptr<Binary> DSYMBinary;
7417   std::unique_ptr<MemoryBuffer> DSYMBuf;
7418   if (UseDbg) {
7419     // If separate DSym file path was specified, parse it as a macho file,
7420     // get the sections and supply it to the section name parsing machinery.
7421     if (const ObjectFile *DbgObj =
7422             getMachODSymObject(MachOOF, Filename, DSYMBinary, DSYMBuf)) {
7423       // Setup the DIContext
7424       diContext = DWARFContext::create(*DbgObj);
7425     } else {
7426       return;
7427     }
7428   }
7429 
7430   if (FilterSections.empty())
7431     outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
7432 
7433   for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
7434     Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName();
7435     if (!SecNameOrErr) {
7436       consumeError(SecNameOrErr.takeError());
7437       continue;
7438     }
7439     if (*SecNameOrErr != DisSectName)
7440       continue;
7441 
7442     DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
7443 
7444     StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
7445     if (SegmentName != DisSegName)
7446       continue;
7447 
7448     StringRef BytesStr =
7449         unwrapOrError(Sections[SectIdx].getContents(), Filename);
7450     ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr);
7451     uint64_t SectAddress = Sections[SectIdx].getAddress();
7452 
7453     bool symbolTableWorked = false;
7454 
7455     // Create a map of symbol addresses to symbol names for use by
7456     // the SymbolizerSymbolLookUp() routine.
7457     SymbolAddressMap AddrMap;
7458     bool DisSymNameFound = false;
7459     for (const SymbolRef &Symbol : MachOOF->symbols()) {
7460       SymbolRef::Type ST =
7461           unwrapOrError(Symbol.getType(), MachOOF->getFileName());
7462       if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
7463           ST == SymbolRef::ST_Other) {
7464         uint64_t Address = cantFail(Symbol.getValue());
7465         StringRef SymName =
7466             unwrapOrError(Symbol.getName(), MachOOF->getFileName());
7467         AddrMap[Address] = SymName;
7468         if (!DisSymName.empty() && DisSymName == SymName)
7469           DisSymNameFound = true;
7470       }
7471     }
7472     if (!DisSymName.empty() && !DisSymNameFound) {
7473       outs() << "Can't find -dis-symname: " << DisSymName << "\n";
7474       return;
7475     }
7476     // Set up the block of info used by the Symbolizer call backs.
7477     SymbolizerInfo.verbose = SymbolicOperands;
7478     SymbolizerInfo.O = MachOOF;
7479     SymbolizerInfo.S = Sections[SectIdx];
7480     SymbolizerInfo.AddrMap = &AddrMap;
7481     SymbolizerInfo.Sections = &Sections;
7482     // Same for the ThumbSymbolizer
7483     ThumbSymbolizerInfo.verbose = SymbolicOperands;
7484     ThumbSymbolizerInfo.O = MachOOF;
7485     ThumbSymbolizerInfo.S = Sections[SectIdx];
7486     ThumbSymbolizerInfo.AddrMap = &AddrMap;
7487     ThumbSymbolizerInfo.Sections = &Sections;
7488 
7489     unsigned int Arch = MachOOF->getArch();
7490 
7491     // Skip all symbols if this is a stubs file.
7492     if (Bytes.empty())
7493       return;
7494 
7495     // If the section has symbols but no symbol at the start of the section
7496     // these are used to make sure the bytes before the first symbol are
7497     // disassembled.
7498     bool FirstSymbol = true;
7499     bool FirstSymbolAtSectionStart = true;
7500 
7501     // Disassemble symbol by symbol.
7502     for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
7503       StringRef SymName =
7504           unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName());
7505       SymbolRef::Type ST =
7506           unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName());
7507       if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
7508         continue;
7509 
7510       // Make sure the symbol is defined in this section.
7511       bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
7512       if (!containsSym) {
7513         if (!DisSymName.empty() && DisSymName == SymName) {
7514           outs() << "-dis-symname: " << DisSymName << " not in the section\n";
7515           return;
7516         }
7517         continue;
7518       }
7519       // The __mh_execute_header is special and we need to deal with that fact
7520       // this symbol is before the start of the (__TEXT,__text) section and at the
7521       // address of the start of the __TEXT segment.  This is because this symbol
7522       // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
7523       // start of the section in a standard MH_EXECUTE filetype.
7524       if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
7525         outs() << "-dis-symname: __mh_execute_header not in any section\n";
7526         return;
7527       }
7528       // When this code is trying to disassemble a symbol at a time and in the
7529       // case there is only the __mh_execute_header symbol left as in a stripped
7530       // executable, we need to deal with this by ignoring this symbol so the
7531       // whole section is disassembled and this symbol is then not displayed.
7532       if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
7533           SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
7534           SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
7535         continue;
7536 
7537       // If we are only disassembling one symbol see if this is that symbol.
7538       if (!DisSymName.empty() && DisSymName != SymName)
7539         continue;
7540 
7541       // Start at the address of the symbol relative to the section's address.
7542       uint64_t SectSize = Sections[SectIdx].getSize();
7543       uint64_t Start = cantFail(Symbols[SymIdx].getValue());
7544       uint64_t SectionAddress = Sections[SectIdx].getAddress();
7545       Start -= SectionAddress;
7546 
7547       if (Start > SectSize) {
7548         outs() << "section data ends, " << SymName
7549                << " lies outside valid range\n";
7550         return;
7551       }
7552 
7553       // Stop disassembling either at the beginning of the next symbol or at
7554       // the end of the section.
7555       bool containsNextSym = false;
7556       uint64_t NextSym = 0;
7557       uint64_t NextSymIdx = SymIdx + 1;
7558       while (Symbols.size() > NextSymIdx) {
7559         SymbolRef::Type NextSymType = unwrapOrError(
7560             Symbols[NextSymIdx].getType(), MachOOF->getFileName());
7561         if (NextSymType == SymbolRef::ST_Function) {
7562           containsNextSym =
7563               Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
7564           NextSym = cantFail(Symbols[NextSymIdx].getValue());
7565           NextSym -= SectionAddress;
7566           break;
7567         }
7568         ++NextSymIdx;
7569       }
7570 
7571       uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
7572       uint64_t Size;
7573 
7574       symbolTableWorked = true;
7575 
7576       DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
7577       uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb));
7578       bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb;
7579 
7580       // We only need the dedicated Thumb target if there's a real choice
7581       // (i.e. we're not targeting M-class) and the function is Thumb.
7582       bool UseThumbTarget = IsThumb && ThumbTarget;
7583 
7584       // If we are not specifying a symbol to start disassembly with and this
7585       // is the first symbol in the section but not at the start of the section
7586       // then move the disassembly index to the start of the section and
7587       // don't print the symbol name just yet.  This is so the bytes before the
7588       // first symbol are disassembled.
7589       uint64_t SymbolStart = Start;
7590       if (DisSymName.empty() && FirstSymbol && Start != 0) {
7591         FirstSymbolAtSectionStart = false;
7592         Start = 0;
7593       }
7594       else
7595         outs() << SymName << ":\n";
7596 
7597       DILineInfo lastLine;
7598       for (uint64_t Index = Start; Index < End; Index += Size) {
7599         MCInst Inst;
7600 
7601         // If this is the first symbol in the section and it was not at the
7602         // start of the section, see if we are at its Index now and if so print
7603         // the symbol name.
7604         if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart)
7605           outs() << SymName << ":\n";
7606 
7607         uint64_t PC = SectAddress + Index;
7608         if (LeadingAddr) {
7609           if (FullLeadingAddr) {
7610             if (MachOOF->is64Bit())
7611               outs() << format("%016" PRIx64, PC);
7612             else
7613               outs() << format("%08" PRIx64, PC);
7614           } else {
7615             outs() << format("%8" PRIx64 ":", PC);
7616           }
7617         }
7618         if (ShowRawInsn || Arch == Triple::arm)
7619           outs() << "\t";
7620 
7621         if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size))
7622           continue;
7623 
7624         SmallVector<char, 64> AnnotationsBytes;
7625         raw_svector_ostream Annotations(AnnotationsBytes);
7626 
7627         bool gotInst;
7628         if (UseThumbTarget)
7629           gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
7630                                                 PC, Annotations);
7631         else
7632           gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
7633                                            Annotations);
7634         if (gotInst) {
7635           if (ShowRawInsn || Arch == Triple::arm) {
7636             dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs());
7637           }
7638           formatted_raw_ostream FormattedOS(outs());
7639           StringRef AnnotationsStr = Annotations.str();
7640           if (UseThumbTarget)
7641             ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI,
7642                                FormattedOS);
7643           else
7644             IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS);
7645           emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
7646 
7647           // Print debug info.
7648           if (diContext) {
7649             DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx});
7650             // Print valid line info if it changed.
7651             if (dli != lastLine && dli.Line != 0)
7652               outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
7653                      << dli.Column;
7654             lastLine = dli;
7655           }
7656           outs() << "\n";
7657         } else {
7658           if (MachOOF->getArchTriple().isX86()) {
7659             outs() << format("\t.byte 0x%02x #bad opcode\n",
7660                              *(Bytes.data() + Index) & 0xff);
7661             Size = 1; // skip exactly one illegible byte and move on.
7662           } else if (Arch == Triple::aarch64 ||
7663                      (Arch == Triple::arm && !IsThumb)) {
7664             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7665                               (*(Bytes.data() + Index + 1) & 0xff) << 8 |
7666                               (*(Bytes.data() + Index + 2) & 0xff) << 16 |
7667                               (*(Bytes.data() + Index + 3) & 0xff) << 24;
7668             outs() << format("\t.long\t0x%08x\n", opcode);
7669             Size = 4;
7670           } else if (Arch == Triple::arm) {
7671             assert(IsThumb && "ARM mode should have been dealt with above");
7672             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7673                               (*(Bytes.data() + Index + 1) & 0xff) << 8;
7674             outs() << format("\t.short\t0x%04x\n", opcode);
7675             Size = 2;
7676           } else{
7677             WithColor::warning(errs(), "llvm-objdump")
7678                 << "invalid instruction encoding\n";
7679             if (Size == 0)
7680               Size = 1; // skip illegible bytes
7681           }
7682         }
7683       }
7684       // Now that we are done disassembled the first symbol set the bool that
7685       // were doing this to false.
7686       FirstSymbol = false;
7687     }
7688     if (!symbolTableWorked) {
7689       // Reading the symbol table didn't work, disassemble the whole section.
7690       uint64_t SectAddress = Sections[SectIdx].getAddress();
7691       uint64_t SectSize = Sections[SectIdx].getSize();
7692       uint64_t InstSize;
7693       for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
7694         MCInst Inst;
7695 
7696         uint64_t PC = SectAddress + Index;
7697 
7698         if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize))
7699           continue;
7700 
7701         SmallVector<char, 64> AnnotationsBytes;
7702         raw_svector_ostream Annotations(AnnotationsBytes);
7703         if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
7704                                    Annotations)) {
7705           if (LeadingAddr) {
7706             if (FullLeadingAddr) {
7707               if (MachOOF->is64Bit())
7708                 outs() << format("%016" PRIx64, PC);
7709               else
7710                 outs() << format("%08" PRIx64, PC);
7711             } else {
7712               outs() << format("%8" PRIx64 ":", PC);
7713             }
7714           }
7715           if (ShowRawInsn || Arch == Triple::arm) {
7716             outs() << "\t";
7717             dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs());
7718           }
7719           StringRef AnnotationsStr = Annotations.str();
7720           IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs());
7721           outs() << "\n";
7722         } else {
7723           if (MachOOF->getArchTriple().isX86()) {
7724             outs() << format("\t.byte 0x%02x #bad opcode\n",
7725                              *(Bytes.data() + Index) & 0xff);
7726             InstSize = 1; // skip exactly one illegible byte and move on.
7727           } else {
7728             WithColor::warning(errs(), "llvm-objdump")
7729                 << "invalid instruction encoding\n";
7730             if (InstSize == 0)
7731               InstSize = 1; // skip illegible bytes
7732           }
7733         }
7734       }
7735     }
7736     // The TripleName's need to be reset if we are called again for a different
7737     // architecture.
7738     TripleName = "";
7739     ThumbTripleName = "";
7740 
7741     if (SymbolizerInfo.demangled_name != nullptr)
7742       free(SymbolizerInfo.demangled_name);
7743     if (ThumbSymbolizerInfo.demangled_name != nullptr)
7744       free(ThumbSymbolizerInfo.demangled_name);
7745   }
7746 }
7747 
7748 //===----------------------------------------------------------------------===//
7749 // __compact_unwind section dumping
7750 //===----------------------------------------------------------------------===//
7751 
7752 namespace {
7753 
7754 template <typename T>
7755 static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
7756   if (Offset + sizeof(T) > Contents.size()) {
7757     outs() << "warning: attempt to read past end of buffer\n";
7758     return T();
7759   }
7760 
7761   uint64_t Val = support::endian::read<T, llvm::endianness::little>(
7762       Contents.data() + Offset);
7763   return Val;
7764 }
7765 
7766 template <typename T>
7767 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
7768   T Val = read<T>(Contents, Offset);
7769   Offset += sizeof(T);
7770   return Val;
7771 }
7772 
7773 struct CompactUnwindEntry {
7774   uint32_t OffsetInSection;
7775 
7776   uint64_t FunctionAddr;
7777   uint32_t Length;
7778   uint32_t CompactEncoding;
7779   uint64_t PersonalityAddr;
7780   uint64_t LSDAAddr;
7781 
7782   RelocationRef FunctionReloc;
7783   RelocationRef PersonalityReloc;
7784   RelocationRef LSDAReloc;
7785 
7786   CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
7787       : OffsetInSection(Offset) {
7788     if (Is64)
7789       read<uint64_t>(Contents, Offset);
7790     else
7791       read<uint32_t>(Contents, Offset);
7792   }
7793 
7794 private:
7795   template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
7796     FunctionAddr = readNext<UIntPtr>(Contents, Offset);
7797     Length = readNext<uint32_t>(Contents, Offset);
7798     CompactEncoding = readNext<uint32_t>(Contents, Offset);
7799     PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
7800     LSDAAddr = readNext<UIntPtr>(Contents, Offset);
7801   }
7802 };
7803 }
7804 
7805 /// Given a relocation from __compact_unwind, consisting of the RelocationRef
7806 /// and data being relocated, determine the best base Name and Addend to use for
7807 /// display purposes.
7808 ///
7809 /// 1. An Extern relocation will directly reference a symbol (and the data is
7810 ///    then already an addend), so use that.
7811 /// 2. Otherwise the data is an offset in the object file's layout; try to find
7812 //     a symbol before it in the same section, and use the offset from there.
7813 /// 3. Finally, if all that fails, fall back to an offset from the start of the
7814 ///    referenced section.
7815 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
7816                                       std::map<uint64_t, SymbolRef> &Symbols,
7817                                       const RelocationRef &Reloc, uint64_t Addr,
7818                                       StringRef &Name, uint64_t &Addend) {
7819   if (Reloc.getSymbol() != Obj->symbol_end()) {
7820     Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName());
7821     Addend = Addr;
7822     return;
7823   }
7824 
7825   auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
7826   SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
7827 
7828   uint64_t SectionAddr = RelocSection.getAddress();
7829 
7830   auto Sym = Symbols.upper_bound(Addr);
7831   if (Sym == Symbols.begin()) {
7832     // The first symbol in the object is after this reference, the best we can
7833     // do is section-relative notation.
7834     if (Expected<StringRef> NameOrErr = RelocSection.getName())
7835       Name = *NameOrErr;
7836     else
7837       consumeError(NameOrErr.takeError());
7838 
7839     Addend = Addr - SectionAddr;
7840     return;
7841   }
7842 
7843   // Go back one so that SymbolAddress <= Addr.
7844   --Sym;
7845 
7846   section_iterator SymSection =
7847       unwrapOrError(Sym->second.getSection(), Obj->getFileName());
7848   if (RelocSection == *SymSection) {
7849     // There's a valid symbol in the same section before this reference.
7850     Name = unwrapOrError(Sym->second.getName(), Obj->getFileName());
7851     Addend = Addr - Sym->first;
7852     return;
7853   }
7854 
7855   // There is a symbol before this reference, but it's in a different
7856   // section. Probably not helpful to mention it, so use the section name.
7857   if (Expected<StringRef> NameOrErr = RelocSection.getName())
7858     Name = *NameOrErr;
7859   else
7860     consumeError(NameOrErr.takeError());
7861 
7862   Addend = Addr - SectionAddr;
7863 }
7864 
7865 static void printUnwindRelocDest(const MachOObjectFile *Obj,
7866                                  std::map<uint64_t, SymbolRef> &Symbols,
7867                                  const RelocationRef &Reloc, uint64_t Addr) {
7868   StringRef Name;
7869   uint64_t Addend;
7870 
7871   if (!Reloc.getObject())
7872     return;
7873 
7874   findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
7875 
7876   outs() << Name;
7877   if (Addend)
7878     outs() << " + " << format("0x%" PRIx64, Addend);
7879 }
7880 
7881 static void
7882 printMachOCompactUnwindSection(const MachOObjectFile *Obj,
7883                                std::map<uint64_t, SymbolRef> &Symbols,
7884                                const SectionRef &CompactUnwind) {
7885 
7886   if (!Obj->isLittleEndian()) {
7887     outs() << "Skipping big-endian __compact_unwind section\n";
7888     return;
7889   }
7890 
7891   bool Is64 = Obj->is64Bit();
7892   uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
7893   uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
7894 
7895   StringRef Contents =
7896       unwrapOrError(CompactUnwind.getContents(), Obj->getFileName());
7897   SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
7898 
7899   // First populate the initial raw offsets, encodings and so on from the entry.
7900   for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
7901     CompactUnwindEntry Entry(Contents, Offset, Is64);
7902     CompactUnwinds.push_back(Entry);
7903   }
7904 
7905   // Next we need to look at the relocations to find out what objects are
7906   // actually being referred to.
7907   for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
7908     uint64_t RelocAddress = Reloc.getOffset();
7909 
7910     uint32_t EntryIdx = RelocAddress / EntrySize;
7911     uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
7912     CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
7913 
7914     if (OffsetInEntry == 0)
7915       Entry.FunctionReloc = Reloc;
7916     else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
7917       Entry.PersonalityReloc = Reloc;
7918     else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
7919       Entry.LSDAReloc = Reloc;
7920     else {
7921       outs() << "Invalid relocation in __compact_unwind section\n";
7922       return;
7923     }
7924   }
7925 
7926   // Finally, we're ready to print the data we've gathered.
7927   outs() << "Contents of __compact_unwind section:\n";
7928   for (auto &Entry : CompactUnwinds) {
7929     outs() << "  Entry at offset "
7930            << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
7931 
7932     // 1. Start of the region this entry applies to.
7933     outs() << "    start:                " << format("0x%" PRIx64,
7934                                                      Entry.FunctionAddr) << ' ';
7935     printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
7936     outs() << '\n';
7937 
7938     // 2. Length of the region this entry applies to.
7939     outs() << "    length:               " << format("0x%" PRIx32, Entry.Length)
7940            << '\n';
7941     // 3. The 32-bit compact encoding.
7942     outs() << "    compact encoding:     "
7943            << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
7944 
7945     // 4. The personality function, if present.
7946     if (Entry.PersonalityReloc.getObject()) {
7947       outs() << "    personality function: "
7948              << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
7949       printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
7950                            Entry.PersonalityAddr);
7951       outs() << '\n';
7952     }
7953 
7954     // 5. This entry's language-specific data area.
7955     if (Entry.LSDAReloc.getObject()) {
7956       outs() << "    LSDA:                 " << format("0x%" PRIx64,
7957                                                        Entry.LSDAAddr) << ' ';
7958       printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
7959       outs() << '\n';
7960     }
7961   }
7962 }
7963 
7964 //===----------------------------------------------------------------------===//
7965 // __unwind_info section dumping
7966 //===----------------------------------------------------------------------===//
7967 
7968 static void printRegularSecondLevelUnwindPage(StringRef PageData) {
7969   ptrdiff_t Pos = 0;
7970   uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7971   (void)Kind;
7972   assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
7973 
7974   uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7975   uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7976 
7977   Pos = EntriesStart;
7978   for (unsigned i = 0; i < NumEntries; ++i) {
7979     uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
7980     uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
7981 
7982     outs() << "      [" << i << "]: "
7983            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7984            << ", "
7985            << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
7986   }
7987 }
7988 
7989 static void printCompressedSecondLevelUnwindPage(
7990     StringRef PageData, uint32_t FunctionBase,
7991     const SmallVectorImpl<uint32_t> &CommonEncodings) {
7992   ptrdiff_t Pos = 0;
7993   uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7994   (void)Kind;
7995   assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
7996 
7997   uint32_t NumCommonEncodings = CommonEncodings.size();
7998   uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7999   uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
8000 
8001   uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos);
8002   uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos);
8003   SmallVector<uint32_t, 64> PageEncodings;
8004   if (NumPageEncodings) {
8005     outs() << "      Page encodings: (count = " << NumPageEncodings << ")\n";
8006     Pos = PageEncodingsStart;
8007     for (unsigned i = 0; i < NumPageEncodings; ++i) {
8008       uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
8009       PageEncodings.push_back(Encoding);
8010       outs() << "        encoding[" << (i + NumCommonEncodings)
8011              << "]: " << format("0x%08" PRIx32, Encoding) << '\n';
8012     }
8013   }
8014 
8015   Pos = EntriesStart;
8016   for (unsigned i = 0; i < NumEntries; ++i) {
8017     uint32_t Entry = readNext<uint32_t>(PageData, Pos);
8018     uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
8019     uint32_t EncodingIdx = Entry >> 24;
8020 
8021     uint32_t Encoding;
8022     if (EncodingIdx < NumCommonEncodings)
8023       Encoding = CommonEncodings[EncodingIdx];
8024     else
8025       Encoding = PageEncodings[EncodingIdx - NumCommonEncodings];
8026 
8027     outs() << "      [" << i << "]: "
8028            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8029            << ", "
8030            << "encoding[" << EncodingIdx
8031            << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
8032   }
8033 }
8034 
8035 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
8036                                         std::map<uint64_t, SymbolRef> &Symbols,
8037                                         const SectionRef &UnwindInfo) {
8038 
8039   if (!Obj->isLittleEndian()) {
8040     outs() << "Skipping big-endian __unwind_info section\n";
8041     return;
8042   }
8043 
8044   outs() << "Contents of __unwind_info section:\n";
8045 
8046   StringRef Contents =
8047       unwrapOrError(UnwindInfo.getContents(), Obj->getFileName());
8048   ptrdiff_t Pos = 0;
8049 
8050   //===----------------------------------
8051   // Section header
8052   //===----------------------------------
8053 
8054   uint32_t Version = readNext<uint32_t>(Contents, Pos);
8055   outs() << "  Version:                                   "
8056          << format("0x%" PRIx32, Version) << '\n';
8057   if (Version != 1) {
8058     outs() << "    Skipping section with unknown version\n";
8059     return;
8060   }
8061 
8062   uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
8063   outs() << "  Common encodings array section offset:     "
8064          << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
8065   uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
8066   outs() << "  Number of common encodings in array:       "
8067          << format("0x%" PRIx32, NumCommonEncodings) << '\n';
8068 
8069   uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
8070   outs() << "  Personality function array section offset: "
8071          << format("0x%" PRIx32, PersonalitiesStart) << '\n';
8072   uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
8073   outs() << "  Number of personality functions in array:  "
8074          << format("0x%" PRIx32, NumPersonalities) << '\n';
8075 
8076   uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
8077   outs() << "  Index array section offset:                "
8078          << format("0x%" PRIx32, IndicesStart) << '\n';
8079   uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
8080   outs() << "  Number of indices in array:                "
8081          << format("0x%" PRIx32, NumIndices) << '\n';
8082 
8083   //===----------------------------------
8084   // A shared list of common encodings
8085   //===----------------------------------
8086 
8087   // These occupy indices in the range [0, N] whenever an encoding is referenced
8088   // from a compressed 2nd level index table. In practice the linker only
8089   // creates ~128 of these, so that indices are available to embed encodings in
8090   // the 2nd level index.
8091 
8092   SmallVector<uint32_t, 64> CommonEncodings;
8093   outs() << "  Common encodings: (count = " << NumCommonEncodings << ")\n";
8094   Pos = CommonEncodingsStart;
8095   for (unsigned i = 0; i < NumCommonEncodings; ++i) {
8096     uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
8097     CommonEncodings.push_back(Encoding);
8098 
8099     outs() << "    encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
8100            << '\n';
8101   }
8102 
8103   //===----------------------------------
8104   // Personality functions used in this executable
8105   //===----------------------------------
8106 
8107   // There should be only a handful of these (one per source language,
8108   // roughly). Particularly since they only get 2 bits in the compact encoding.
8109 
8110   outs() << "  Personality functions: (count = " << NumPersonalities << ")\n";
8111   Pos = PersonalitiesStart;
8112   for (unsigned i = 0; i < NumPersonalities; ++i) {
8113     uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
8114     outs() << "    personality[" << i + 1
8115            << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
8116   }
8117 
8118   //===----------------------------------
8119   // The level 1 index entries
8120   //===----------------------------------
8121 
8122   // These specify an approximate place to start searching for the more detailed
8123   // information, sorted by PC.
8124 
8125   struct IndexEntry {
8126     uint32_t FunctionOffset;
8127     uint32_t SecondLevelPageStart;
8128     uint32_t LSDAStart;
8129   };
8130 
8131   SmallVector<IndexEntry, 4> IndexEntries;
8132 
8133   outs() << "  Top level indices: (count = " << NumIndices << ")\n";
8134   Pos = IndicesStart;
8135   for (unsigned i = 0; i < NumIndices; ++i) {
8136     IndexEntry Entry;
8137 
8138     Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
8139     Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
8140     Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
8141     IndexEntries.push_back(Entry);
8142 
8143     outs() << "    [" << i << "]: "
8144            << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
8145            << ", "
8146            << "2nd level page offset="
8147            << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
8148            << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
8149   }
8150 
8151   //===----------------------------------
8152   // Next come the LSDA tables
8153   //===----------------------------------
8154 
8155   // The LSDA layout is rather implicit: it's a contiguous array of entries from
8156   // the first top-level index's LSDAOffset to the last (sentinel).
8157 
8158   outs() << "  LSDA descriptors:\n";
8159   Pos = IndexEntries[0].LSDAStart;
8160   const uint32_t LSDASize = 2 * sizeof(uint32_t);
8161   int NumLSDAs =
8162       (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
8163 
8164   for (int i = 0; i < NumLSDAs; ++i) {
8165     uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
8166     uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
8167     outs() << "    [" << i << "]: "
8168            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8169            << ", "
8170            << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
8171   }
8172 
8173   //===----------------------------------
8174   // Finally, the 2nd level indices
8175   //===----------------------------------
8176 
8177   // Generally these are 4K in size, and have 2 possible forms:
8178   //   + Regular stores up to 511 entries with disparate encodings
8179   //   + Compressed stores up to 1021 entries if few enough compact encoding
8180   //     values are used.
8181   outs() << "  Second level indices:\n";
8182   for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
8183     // The final sentinel top-level index has no associated 2nd level page
8184     if (IndexEntries[i].SecondLevelPageStart == 0)
8185       break;
8186 
8187     outs() << "    Second level index[" << i << "]: "
8188            << "offset in section="
8189            << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
8190            << ", "
8191            << "base function offset="
8192            << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
8193 
8194     Pos = IndexEntries[i].SecondLevelPageStart;
8195     if (Pos + sizeof(uint32_t) > Contents.size()) {
8196       outs() << "warning: invalid offset for second level page: " << Pos << '\n';
8197       continue;
8198     }
8199 
8200     uint32_t Kind =
8201         *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
8202     if (Kind == 2)
8203       printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
8204     else if (Kind == 3)
8205       printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
8206                                            IndexEntries[i].FunctionOffset,
8207                                            CommonEncodings);
8208     else
8209       outs() << "    Skipping 2nd level page with unknown kind " << Kind
8210              << '\n';
8211   }
8212 }
8213 
8214 void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) {
8215   std::map<uint64_t, SymbolRef> Symbols;
8216   for (const SymbolRef &SymRef : Obj->symbols()) {
8217     // Discard any undefined or absolute symbols. They're not going to take part
8218     // in the convenience lookup for unwind info and just take up resources.
8219     auto SectOrErr = SymRef.getSection();
8220     if (!SectOrErr) {
8221       // TODO: Actually report errors helpfully.
8222       consumeError(SectOrErr.takeError());
8223       continue;
8224     }
8225     section_iterator Section = *SectOrErr;
8226     if (Section == Obj->section_end())
8227       continue;
8228 
8229     uint64_t Addr = cantFail(SymRef.getValue());
8230     Symbols.insert(std::make_pair(Addr, SymRef));
8231   }
8232 
8233   for (const SectionRef &Section : Obj->sections()) {
8234     StringRef SectName;
8235     if (Expected<StringRef> NameOrErr = Section.getName())
8236       SectName = *NameOrErr;
8237     else
8238       consumeError(NameOrErr.takeError());
8239 
8240     if (SectName == "__compact_unwind")
8241       printMachOCompactUnwindSection(Obj, Symbols, Section);
8242     else if (SectName == "__unwind_info")
8243       printMachOUnwindInfoSection(Obj, Symbols, Section);
8244   }
8245 }
8246 
8247 static void PrintMachHeader(uint32_t magic, uint32_t cputype,
8248                             uint32_t cpusubtype, uint32_t filetype,
8249                             uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
8250                             bool verbose) {
8251   outs() << "Mach header\n";
8252   outs() << "      magic cputype cpusubtype  caps    filetype ncmds "
8253             "sizeofcmds      flags\n";
8254   if (verbose) {
8255     if (magic == MachO::MH_MAGIC)
8256       outs() << "   MH_MAGIC";
8257     else if (magic == MachO::MH_MAGIC_64)
8258       outs() << "MH_MAGIC_64";
8259     else
8260       outs() << format(" 0x%08" PRIx32, magic);
8261     switch (cputype) {
8262     case MachO::CPU_TYPE_I386:
8263       outs() << "    I386";
8264       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8265       case MachO::CPU_SUBTYPE_I386_ALL:
8266         outs() << "        ALL";
8267         break;
8268       default:
8269         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8270         break;
8271       }
8272       break;
8273     case MachO::CPU_TYPE_X86_64:
8274       outs() << "  X86_64";
8275       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8276       case MachO::CPU_SUBTYPE_X86_64_ALL:
8277         outs() << "        ALL";
8278         break;
8279       case MachO::CPU_SUBTYPE_X86_64_H:
8280         outs() << "    Haswell";
8281         break;
8282       default:
8283         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8284         break;
8285       }
8286       break;
8287     case MachO::CPU_TYPE_ARM:
8288       outs() << "     ARM";
8289       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8290       case MachO::CPU_SUBTYPE_ARM_ALL:
8291         outs() << "        ALL";
8292         break;
8293       case MachO::CPU_SUBTYPE_ARM_V4T:
8294         outs() << "        V4T";
8295         break;
8296       case MachO::CPU_SUBTYPE_ARM_V5TEJ:
8297         outs() << "      V5TEJ";
8298         break;
8299       case MachO::CPU_SUBTYPE_ARM_XSCALE:
8300         outs() << "     XSCALE";
8301         break;
8302       case MachO::CPU_SUBTYPE_ARM_V6:
8303         outs() << "         V6";
8304         break;
8305       case MachO::CPU_SUBTYPE_ARM_V6M:
8306         outs() << "        V6M";
8307         break;
8308       case MachO::CPU_SUBTYPE_ARM_V7:
8309         outs() << "         V7";
8310         break;
8311       case MachO::CPU_SUBTYPE_ARM_V7EM:
8312         outs() << "       V7EM";
8313         break;
8314       case MachO::CPU_SUBTYPE_ARM_V7K:
8315         outs() << "        V7K";
8316         break;
8317       case MachO::CPU_SUBTYPE_ARM_V7M:
8318         outs() << "        V7M";
8319         break;
8320       case MachO::CPU_SUBTYPE_ARM_V7S:
8321         outs() << "        V7S";
8322         break;
8323       default:
8324         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8325         break;
8326       }
8327       break;
8328     case MachO::CPU_TYPE_ARM64:
8329       outs() << "   ARM64";
8330       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8331       case MachO::CPU_SUBTYPE_ARM64_ALL:
8332         outs() << "        ALL";
8333         break;
8334       case MachO::CPU_SUBTYPE_ARM64_V8:
8335         outs() << "         V8";
8336         break;
8337       case MachO::CPU_SUBTYPE_ARM64E:
8338         outs() << "          E";
8339         break;
8340       default:
8341         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8342         break;
8343       }
8344       break;
8345     case MachO::CPU_TYPE_ARM64_32:
8346       outs() << " ARM64_32";
8347       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8348       case MachO::CPU_SUBTYPE_ARM64_32_V8:
8349         outs() << "        V8";
8350         break;
8351       default:
8352         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8353         break;
8354       }
8355       break;
8356     case MachO::CPU_TYPE_POWERPC:
8357       outs() << "     PPC";
8358       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8359       case MachO::CPU_SUBTYPE_POWERPC_ALL:
8360         outs() << "        ALL";
8361         break;
8362       default:
8363         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8364         break;
8365       }
8366       break;
8367     case MachO::CPU_TYPE_POWERPC64:
8368       outs() << "   PPC64";
8369       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8370       case MachO::CPU_SUBTYPE_POWERPC_ALL:
8371         outs() << "        ALL";
8372         break;
8373       default:
8374         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8375         break;
8376       }
8377       break;
8378     default:
8379       outs() << format(" %7d", cputype);
8380       outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8381       break;
8382     }
8383 
8384     if (cputype == MachO::CPU_TYPE_ARM64 &&
8385         MachO::CPU_SUBTYPE_ARM64E_IS_VERSIONED_PTRAUTH_ABI(cpusubtype)) {
8386       const char *Format =
8387           MachO::CPU_SUBTYPE_ARM64E_IS_KERNEL_PTRAUTH_ABI(cpusubtype)
8388               ? " PAK%02d"
8389               : " PAC%02d";
8390       outs() << format(Format,
8391                        MachO::CPU_SUBTYPE_ARM64E_PTRAUTH_VERSION(cpusubtype));
8392     } else if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) ==
8393                MachO::CPU_SUBTYPE_LIB64) {
8394       outs() << " LIB64";
8395     } else {
8396       outs() << format("  0x%02" PRIx32,
8397                        (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8398     }
8399     switch (filetype) {
8400     case MachO::MH_OBJECT:
8401       outs() << "      OBJECT";
8402       break;
8403     case MachO::MH_EXECUTE:
8404       outs() << "     EXECUTE";
8405       break;
8406     case MachO::MH_FVMLIB:
8407       outs() << "      FVMLIB";
8408       break;
8409     case MachO::MH_CORE:
8410       outs() << "        CORE";
8411       break;
8412     case MachO::MH_PRELOAD:
8413       outs() << "     PRELOAD";
8414       break;
8415     case MachO::MH_DYLIB:
8416       outs() << "       DYLIB";
8417       break;
8418     case MachO::MH_DYLIB_STUB:
8419       outs() << "  DYLIB_STUB";
8420       break;
8421     case MachO::MH_DYLINKER:
8422       outs() << "    DYLINKER";
8423       break;
8424     case MachO::MH_BUNDLE:
8425       outs() << "      BUNDLE";
8426       break;
8427     case MachO::MH_DSYM:
8428       outs() << "        DSYM";
8429       break;
8430     case MachO::MH_KEXT_BUNDLE:
8431       outs() << "  KEXTBUNDLE";
8432       break;
8433     case MachO::MH_FILESET:
8434       outs() << "     FILESET";
8435       break;
8436     default:
8437       outs() << format("  %10u", filetype);
8438       break;
8439     }
8440     outs() << format(" %5u", ncmds);
8441     outs() << format(" %10u", sizeofcmds);
8442     uint32_t f = flags;
8443     if (f & MachO::MH_NOUNDEFS) {
8444       outs() << "   NOUNDEFS";
8445       f &= ~MachO::MH_NOUNDEFS;
8446     }
8447     if (f & MachO::MH_INCRLINK) {
8448       outs() << " INCRLINK";
8449       f &= ~MachO::MH_INCRLINK;
8450     }
8451     if (f & MachO::MH_DYLDLINK) {
8452       outs() << " DYLDLINK";
8453       f &= ~MachO::MH_DYLDLINK;
8454     }
8455     if (f & MachO::MH_BINDATLOAD) {
8456       outs() << " BINDATLOAD";
8457       f &= ~MachO::MH_BINDATLOAD;
8458     }
8459     if (f & MachO::MH_PREBOUND) {
8460       outs() << " PREBOUND";
8461       f &= ~MachO::MH_PREBOUND;
8462     }
8463     if (f & MachO::MH_SPLIT_SEGS) {
8464       outs() << " SPLIT_SEGS";
8465       f &= ~MachO::MH_SPLIT_SEGS;
8466     }
8467     if (f & MachO::MH_LAZY_INIT) {
8468       outs() << " LAZY_INIT";
8469       f &= ~MachO::MH_LAZY_INIT;
8470     }
8471     if (f & MachO::MH_TWOLEVEL) {
8472       outs() << " TWOLEVEL";
8473       f &= ~MachO::MH_TWOLEVEL;
8474     }
8475     if (f & MachO::MH_FORCE_FLAT) {
8476       outs() << " FORCE_FLAT";
8477       f &= ~MachO::MH_FORCE_FLAT;
8478     }
8479     if (f & MachO::MH_NOMULTIDEFS) {
8480       outs() << " NOMULTIDEFS";
8481       f &= ~MachO::MH_NOMULTIDEFS;
8482     }
8483     if (f & MachO::MH_NOFIXPREBINDING) {
8484       outs() << " NOFIXPREBINDING";
8485       f &= ~MachO::MH_NOFIXPREBINDING;
8486     }
8487     if (f & MachO::MH_PREBINDABLE) {
8488       outs() << " PREBINDABLE";
8489       f &= ~MachO::MH_PREBINDABLE;
8490     }
8491     if (f & MachO::MH_ALLMODSBOUND) {
8492       outs() << " ALLMODSBOUND";
8493       f &= ~MachO::MH_ALLMODSBOUND;
8494     }
8495     if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
8496       outs() << " SUBSECTIONS_VIA_SYMBOLS";
8497       f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
8498     }
8499     if (f & MachO::MH_CANONICAL) {
8500       outs() << " CANONICAL";
8501       f &= ~MachO::MH_CANONICAL;
8502     }
8503     if (f & MachO::MH_WEAK_DEFINES) {
8504       outs() << " WEAK_DEFINES";
8505       f &= ~MachO::MH_WEAK_DEFINES;
8506     }
8507     if (f & MachO::MH_BINDS_TO_WEAK) {
8508       outs() << " BINDS_TO_WEAK";
8509       f &= ~MachO::MH_BINDS_TO_WEAK;
8510     }
8511     if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
8512       outs() << " ALLOW_STACK_EXECUTION";
8513       f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
8514     }
8515     if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
8516       outs() << " DEAD_STRIPPABLE_DYLIB";
8517       f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
8518     }
8519     if (f & MachO::MH_PIE) {
8520       outs() << " PIE";
8521       f &= ~MachO::MH_PIE;
8522     }
8523     if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
8524       outs() << " NO_REEXPORTED_DYLIBS";
8525       f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
8526     }
8527     if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
8528       outs() << " MH_HAS_TLV_DESCRIPTORS";
8529       f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
8530     }
8531     if (f & MachO::MH_NO_HEAP_EXECUTION) {
8532       outs() << " MH_NO_HEAP_EXECUTION";
8533       f &= ~MachO::MH_NO_HEAP_EXECUTION;
8534     }
8535     if (f & MachO::MH_APP_EXTENSION_SAFE) {
8536       outs() << " APP_EXTENSION_SAFE";
8537       f &= ~MachO::MH_APP_EXTENSION_SAFE;
8538     }
8539     if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
8540       outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO";
8541       f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO;
8542     }
8543     if (f != 0 || flags == 0)
8544       outs() << format(" 0x%08" PRIx32, f);
8545   } else {
8546     outs() << format(" 0x%08" PRIx32, magic);
8547     outs() << format(" %7d", cputype);
8548     outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8549     outs() << format("  0x%02" PRIx32,
8550                      (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8551     outs() << format("  %10u", filetype);
8552     outs() << format(" %5u", ncmds);
8553     outs() << format(" %10u", sizeofcmds);
8554     outs() << format(" 0x%08" PRIx32, flags);
8555   }
8556   outs() << "\n";
8557 }
8558 
8559 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
8560                                 StringRef SegName, uint64_t vmaddr,
8561                                 uint64_t vmsize, uint64_t fileoff,
8562                                 uint64_t filesize, uint32_t maxprot,
8563                                 uint32_t initprot, uint32_t nsects,
8564                                 uint32_t flags, uint32_t object_size,
8565                                 bool verbose) {
8566   uint64_t expected_cmdsize;
8567   if (cmd == MachO::LC_SEGMENT) {
8568     outs() << "      cmd LC_SEGMENT\n";
8569     expected_cmdsize = nsects;
8570     expected_cmdsize *= sizeof(struct MachO::section);
8571     expected_cmdsize += sizeof(struct MachO::segment_command);
8572   } else {
8573     outs() << "      cmd LC_SEGMENT_64\n";
8574     expected_cmdsize = nsects;
8575     expected_cmdsize *= sizeof(struct MachO::section_64);
8576     expected_cmdsize += sizeof(struct MachO::segment_command_64);
8577   }
8578   outs() << "  cmdsize " << cmdsize;
8579   if (cmdsize != expected_cmdsize)
8580     outs() << " Inconsistent size\n";
8581   else
8582     outs() << "\n";
8583   outs() << "  segname " << SegName << "\n";
8584   if (cmd == MachO::LC_SEGMENT_64) {
8585     outs() << "   vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
8586     outs() << "   vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
8587   } else {
8588     outs() << "   vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
8589     outs() << "   vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
8590   }
8591   outs() << "  fileoff " << fileoff;
8592   if (fileoff > object_size)
8593     outs() << " (past end of file)\n";
8594   else
8595     outs() << "\n";
8596   outs() << " filesize " << filesize;
8597   if (fileoff + filesize > object_size)
8598     outs() << " (past end of file)\n";
8599   else
8600     outs() << "\n";
8601   if (verbose) {
8602     if ((maxprot &
8603          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8604            MachO::VM_PROT_EXECUTE)) != 0)
8605       outs() << "  maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
8606     else {
8607       outs() << "  maxprot ";
8608       outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
8609       outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8610       outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8611     }
8612     if ((initprot &
8613          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8614            MachO::VM_PROT_EXECUTE)) != 0)
8615       outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
8616     else {
8617       outs() << " initprot ";
8618       outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
8619       outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8620       outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8621     }
8622   } else {
8623     outs() << "  maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
8624     outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
8625   }
8626   outs() << "   nsects " << nsects << "\n";
8627   if (verbose) {
8628     outs() << "    flags";
8629     if (flags == 0)
8630       outs() << " (none)\n";
8631     else {
8632       if (flags & MachO::SG_HIGHVM) {
8633         outs() << " HIGHVM";
8634         flags &= ~MachO::SG_HIGHVM;
8635       }
8636       if (flags & MachO::SG_FVMLIB) {
8637         outs() << " FVMLIB";
8638         flags &= ~MachO::SG_FVMLIB;
8639       }
8640       if (flags & MachO::SG_NORELOC) {
8641         outs() << " NORELOC";
8642         flags &= ~MachO::SG_NORELOC;
8643       }
8644       if (flags & MachO::SG_PROTECTED_VERSION_1) {
8645         outs() << " PROTECTED_VERSION_1";
8646         flags &= ~MachO::SG_PROTECTED_VERSION_1;
8647       }
8648       if (flags & MachO::SG_READ_ONLY) {
8649         // Apple's otool prints the SG_ prefix for this flag, but not for the
8650         // others.
8651         outs() << " SG_READ_ONLY";
8652         flags &= ~MachO::SG_READ_ONLY;
8653       }
8654       if (flags)
8655         outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
8656       else
8657         outs() << "\n";
8658     }
8659   } else {
8660     outs() << "    flags " << format("0x%" PRIx32, flags) << "\n";
8661   }
8662 }
8663 
8664 static void PrintSection(const char *sectname, const char *segname,
8665                          uint64_t addr, uint64_t size, uint32_t offset,
8666                          uint32_t align, uint32_t reloff, uint32_t nreloc,
8667                          uint32_t flags, uint32_t reserved1, uint32_t reserved2,
8668                          uint32_t cmd, const char *sg_segname,
8669                          uint32_t filetype, uint32_t object_size,
8670                          bool verbose) {
8671   outs() << "Section\n";
8672   outs() << "  sectname " << format("%.16s\n", sectname);
8673   outs() << "   segname " << format("%.16s", segname);
8674   if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
8675     outs() << " (does not match segment)\n";
8676   else
8677     outs() << "\n";
8678   if (cmd == MachO::LC_SEGMENT_64) {
8679     outs() << "      addr " << format("0x%016" PRIx64, addr) << "\n";
8680     outs() << "      size " << format("0x%016" PRIx64, size);
8681   } else {
8682     outs() << "      addr " << format("0x%08" PRIx64, addr) << "\n";
8683     outs() << "      size " << format("0x%08" PRIx64, size);
8684   }
8685   if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
8686     outs() << " (past end of file)\n";
8687   else
8688     outs() << "\n";
8689   outs() << "    offset " << offset;
8690   if (offset > object_size)
8691     outs() << " (past end of file)\n";
8692   else
8693     outs() << "\n";
8694   uint32_t align_shifted = 1 << align;
8695   outs() << "     align 2^" << align << " (" << align_shifted << ")\n";
8696   outs() << "    reloff " << reloff;
8697   if (reloff > object_size)
8698     outs() << " (past end of file)\n";
8699   else
8700     outs() << "\n";
8701   outs() << "    nreloc " << nreloc;
8702   if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
8703     outs() << " (past end of file)\n";
8704   else
8705     outs() << "\n";
8706   uint32_t section_type = flags & MachO::SECTION_TYPE;
8707   if (verbose) {
8708     outs() << "      type";
8709     if (section_type == MachO::S_REGULAR)
8710       outs() << " S_REGULAR\n";
8711     else if (section_type == MachO::S_ZEROFILL)
8712       outs() << " S_ZEROFILL\n";
8713     else if (section_type == MachO::S_CSTRING_LITERALS)
8714       outs() << " S_CSTRING_LITERALS\n";
8715     else if (section_type == MachO::S_4BYTE_LITERALS)
8716       outs() << " S_4BYTE_LITERALS\n";
8717     else if (section_type == MachO::S_8BYTE_LITERALS)
8718       outs() << " S_8BYTE_LITERALS\n";
8719     else if (section_type == MachO::S_16BYTE_LITERALS)
8720       outs() << " S_16BYTE_LITERALS\n";
8721     else if (section_type == MachO::S_LITERAL_POINTERS)
8722       outs() << " S_LITERAL_POINTERS\n";
8723     else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
8724       outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
8725     else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
8726       outs() << " S_LAZY_SYMBOL_POINTERS\n";
8727     else if (section_type == MachO::S_SYMBOL_STUBS)
8728       outs() << " S_SYMBOL_STUBS\n";
8729     else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
8730       outs() << " S_MOD_INIT_FUNC_POINTERS\n";
8731     else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
8732       outs() << " S_MOD_TERM_FUNC_POINTERS\n";
8733     else if (section_type == MachO::S_COALESCED)
8734       outs() << " S_COALESCED\n";
8735     else if (section_type == MachO::S_INTERPOSING)
8736       outs() << " S_INTERPOSING\n";
8737     else if (section_type == MachO::S_DTRACE_DOF)
8738       outs() << " S_DTRACE_DOF\n";
8739     else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
8740       outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
8741     else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
8742       outs() << " S_THREAD_LOCAL_REGULAR\n";
8743     else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
8744       outs() << " S_THREAD_LOCAL_ZEROFILL\n";
8745     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
8746       outs() << " S_THREAD_LOCAL_VARIABLES\n";
8747     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8748       outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
8749     else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
8750       outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
8751     else if (section_type == MachO::S_INIT_FUNC_OFFSETS)
8752       outs() << " S_INIT_FUNC_OFFSETS\n";
8753     else
8754       outs() << format("0x%08" PRIx32, section_type) << "\n";
8755     outs() << "attributes";
8756     uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
8757     if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
8758       outs() << " PURE_INSTRUCTIONS";
8759     if (section_attributes & MachO::S_ATTR_NO_TOC)
8760       outs() << " NO_TOC";
8761     if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
8762       outs() << " STRIP_STATIC_SYMS";
8763     if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
8764       outs() << " NO_DEAD_STRIP";
8765     if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
8766       outs() << " LIVE_SUPPORT";
8767     if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
8768       outs() << " SELF_MODIFYING_CODE";
8769     if (section_attributes & MachO::S_ATTR_DEBUG)
8770       outs() << " DEBUG";
8771     if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
8772       outs() << " SOME_INSTRUCTIONS";
8773     if (section_attributes & MachO::S_ATTR_EXT_RELOC)
8774       outs() << " EXT_RELOC";
8775     if (section_attributes & MachO::S_ATTR_LOC_RELOC)
8776       outs() << " LOC_RELOC";
8777     if (section_attributes == 0)
8778       outs() << " (none)";
8779     outs() << "\n";
8780   } else
8781     outs() << "     flags " << format("0x%08" PRIx32, flags) << "\n";
8782   outs() << " reserved1 " << reserved1;
8783   if (section_type == MachO::S_SYMBOL_STUBS ||
8784       section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
8785       section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
8786       section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
8787       section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8788     outs() << " (index into indirect symbol table)\n";
8789   else
8790     outs() << "\n";
8791   outs() << " reserved2 " << reserved2;
8792   if (section_type == MachO::S_SYMBOL_STUBS)
8793     outs() << " (size of stubs)\n";
8794   else
8795     outs() << "\n";
8796 }
8797 
8798 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
8799                                    uint32_t object_size) {
8800   outs() << "     cmd LC_SYMTAB\n";
8801   outs() << " cmdsize " << st.cmdsize;
8802   if (st.cmdsize != sizeof(struct MachO::symtab_command))
8803     outs() << " Incorrect size\n";
8804   else
8805     outs() << "\n";
8806   outs() << "  symoff " << st.symoff;
8807   if (st.symoff > object_size)
8808     outs() << " (past end of file)\n";
8809   else
8810     outs() << "\n";
8811   outs() << "   nsyms " << st.nsyms;
8812   uint64_t big_size;
8813   if (Is64Bit) {
8814     big_size = st.nsyms;
8815     big_size *= sizeof(struct MachO::nlist_64);
8816     big_size += st.symoff;
8817     if (big_size > object_size)
8818       outs() << " (past end of file)\n";
8819     else
8820       outs() << "\n";
8821   } else {
8822     big_size = st.nsyms;
8823     big_size *= sizeof(struct MachO::nlist);
8824     big_size += st.symoff;
8825     if (big_size > object_size)
8826       outs() << " (past end of file)\n";
8827     else
8828       outs() << "\n";
8829   }
8830   outs() << "  stroff " << st.stroff;
8831   if (st.stroff > object_size)
8832     outs() << " (past end of file)\n";
8833   else
8834     outs() << "\n";
8835   outs() << " strsize " << st.strsize;
8836   big_size = st.stroff;
8837   big_size += st.strsize;
8838   if (big_size > object_size)
8839     outs() << " (past end of file)\n";
8840   else
8841     outs() << "\n";
8842 }
8843 
8844 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
8845                                      uint32_t nsyms, uint32_t object_size,
8846                                      bool Is64Bit) {
8847   outs() << "            cmd LC_DYSYMTAB\n";
8848   outs() << "        cmdsize " << dyst.cmdsize;
8849   if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
8850     outs() << " Incorrect size\n";
8851   else
8852     outs() << "\n";
8853   outs() << "      ilocalsym " << dyst.ilocalsym;
8854   if (dyst.ilocalsym > nsyms)
8855     outs() << " (greater than the number of symbols)\n";
8856   else
8857     outs() << "\n";
8858   outs() << "      nlocalsym " << dyst.nlocalsym;
8859   uint64_t big_size;
8860   big_size = dyst.ilocalsym;
8861   big_size += dyst.nlocalsym;
8862   if (big_size > nsyms)
8863     outs() << " (past the end of the symbol table)\n";
8864   else
8865     outs() << "\n";
8866   outs() << "     iextdefsym " << dyst.iextdefsym;
8867   if (dyst.iextdefsym > nsyms)
8868     outs() << " (greater than the number of symbols)\n";
8869   else
8870     outs() << "\n";
8871   outs() << "     nextdefsym " << dyst.nextdefsym;
8872   big_size = dyst.iextdefsym;
8873   big_size += dyst.nextdefsym;
8874   if (big_size > nsyms)
8875     outs() << " (past the end of the symbol table)\n";
8876   else
8877     outs() << "\n";
8878   outs() << "      iundefsym " << dyst.iundefsym;
8879   if (dyst.iundefsym > nsyms)
8880     outs() << " (greater than the number of symbols)\n";
8881   else
8882     outs() << "\n";
8883   outs() << "      nundefsym " << dyst.nundefsym;
8884   big_size = dyst.iundefsym;
8885   big_size += dyst.nundefsym;
8886   if (big_size > nsyms)
8887     outs() << " (past the end of the symbol table)\n";
8888   else
8889     outs() << "\n";
8890   outs() << "         tocoff " << dyst.tocoff;
8891   if (dyst.tocoff > object_size)
8892     outs() << " (past end of file)\n";
8893   else
8894     outs() << "\n";
8895   outs() << "           ntoc " << dyst.ntoc;
8896   big_size = dyst.ntoc;
8897   big_size *= sizeof(struct MachO::dylib_table_of_contents);
8898   big_size += dyst.tocoff;
8899   if (big_size > object_size)
8900     outs() << " (past end of file)\n";
8901   else
8902     outs() << "\n";
8903   outs() << "      modtaboff " << dyst.modtaboff;
8904   if (dyst.modtaboff > object_size)
8905     outs() << " (past end of file)\n";
8906   else
8907     outs() << "\n";
8908   outs() << "        nmodtab " << dyst.nmodtab;
8909   uint64_t modtabend;
8910   if (Is64Bit) {
8911     modtabend = dyst.nmodtab;
8912     modtabend *= sizeof(struct MachO::dylib_module_64);
8913     modtabend += dyst.modtaboff;
8914   } else {
8915     modtabend = dyst.nmodtab;
8916     modtabend *= sizeof(struct MachO::dylib_module);
8917     modtabend += dyst.modtaboff;
8918   }
8919   if (modtabend > object_size)
8920     outs() << " (past end of file)\n";
8921   else
8922     outs() << "\n";
8923   outs() << "   extrefsymoff " << dyst.extrefsymoff;
8924   if (dyst.extrefsymoff > object_size)
8925     outs() << " (past end of file)\n";
8926   else
8927     outs() << "\n";
8928   outs() << "    nextrefsyms " << dyst.nextrefsyms;
8929   big_size = dyst.nextrefsyms;
8930   big_size *= sizeof(struct MachO::dylib_reference);
8931   big_size += dyst.extrefsymoff;
8932   if (big_size > object_size)
8933     outs() << " (past end of file)\n";
8934   else
8935     outs() << "\n";
8936   outs() << " indirectsymoff " << dyst.indirectsymoff;
8937   if (dyst.indirectsymoff > object_size)
8938     outs() << " (past end of file)\n";
8939   else
8940     outs() << "\n";
8941   outs() << "  nindirectsyms " << dyst.nindirectsyms;
8942   big_size = dyst.nindirectsyms;
8943   big_size *= sizeof(uint32_t);
8944   big_size += dyst.indirectsymoff;
8945   if (big_size > object_size)
8946     outs() << " (past end of file)\n";
8947   else
8948     outs() << "\n";
8949   outs() << "      extreloff " << dyst.extreloff;
8950   if (dyst.extreloff > object_size)
8951     outs() << " (past end of file)\n";
8952   else
8953     outs() << "\n";
8954   outs() << "        nextrel " << dyst.nextrel;
8955   big_size = dyst.nextrel;
8956   big_size *= sizeof(struct MachO::relocation_info);
8957   big_size += dyst.extreloff;
8958   if (big_size > object_size)
8959     outs() << " (past end of file)\n";
8960   else
8961     outs() << "\n";
8962   outs() << "      locreloff " << dyst.locreloff;
8963   if (dyst.locreloff > object_size)
8964     outs() << " (past end of file)\n";
8965   else
8966     outs() << "\n";
8967   outs() << "        nlocrel " << dyst.nlocrel;
8968   big_size = dyst.nlocrel;
8969   big_size *= sizeof(struct MachO::relocation_info);
8970   big_size += dyst.locreloff;
8971   if (big_size > object_size)
8972     outs() << " (past end of file)\n";
8973   else
8974     outs() << "\n";
8975 }
8976 
8977 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
8978                                      uint32_t object_size) {
8979   if (dc.cmd == MachO::LC_DYLD_INFO)
8980     outs() << "            cmd LC_DYLD_INFO\n";
8981   else
8982     outs() << "            cmd LC_DYLD_INFO_ONLY\n";
8983   outs() << "        cmdsize " << dc.cmdsize;
8984   if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
8985     outs() << " Incorrect size\n";
8986   else
8987     outs() << "\n";
8988   outs() << "     rebase_off " << dc.rebase_off;
8989   if (dc.rebase_off > object_size)
8990     outs() << " (past end of file)\n";
8991   else
8992     outs() << "\n";
8993   outs() << "    rebase_size " << dc.rebase_size;
8994   uint64_t big_size;
8995   big_size = dc.rebase_off;
8996   big_size += dc.rebase_size;
8997   if (big_size > object_size)
8998     outs() << " (past end of file)\n";
8999   else
9000     outs() << "\n";
9001   outs() << "       bind_off " << dc.bind_off;
9002   if (dc.bind_off > object_size)
9003     outs() << " (past end of file)\n";
9004   else
9005     outs() << "\n";
9006   outs() << "      bind_size " << dc.bind_size;
9007   big_size = dc.bind_off;
9008   big_size += dc.bind_size;
9009   if (big_size > object_size)
9010     outs() << " (past end of file)\n";
9011   else
9012     outs() << "\n";
9013   outs() << "  weak_bind_off " << dc.weak_bind_off;
9014   if (dc.weak_bind_off > object_size)
9015     outs() << " (past end of file)\n";
9016   else
9017     outs() << "\n";
9018   outs() << " weak_bind_size " << dc.weak_bind_size;
9019   big_size = dc.weak_bind_off;
9020   big_size += dc.weak_bind_size;
9021   if (big_size > object_size)
9022     outs() << " (past end of file)\n";
9023   else
9024     outs() << "\n";
9025   outs() << "  lazy_bind_off " << dc.lazy_bind_off;
9026   if (dc.lazy_bind_off > object_size)
9027     outs() << " (past end of file)\n";
9028   else
9029     outs() << "\n";
9030   outs() << " lazy_bind_size " << dc.lazy_bind_size;
9031   big_size = dc.lazy_bind_off;
9032   big_size += dc.lazy_bind_size;
9033   if (big_size > object_size)
9034     outs() << " (past end of file)\n";
9035   else
9036     outs() << "\n";
9037   outs() << "     export_off " << dc.export_off;
9038   if (dc.export_off > object_size)
9039     outs() << " (past end of file)\n";
9040   else
9041     outs() << "\n";
9042   outs() << "    export_size " << dc.export_size;
9043   big_size = dc.export_off;
9044   big_size += dc.export_size;
9045   if (big_size > object_size)
9046     outs() << " (past end of file)\n";
9047   else
9048     outs() << "\n";
9049 }
9050 
9051 static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
9052                                  const char *Ptr) {
9053   if (dyld.cmd == MachO::LC_ID_DYLINKER)
9054     outs() << "          cmd LC_ID_DYLINKER\n";
9055   else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
9056     outs() << "          cmd LC_LOAD_DYLINKER\n";
9057   else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
9058     outs() << "          cmd LC_DYLD_ENVIRONMENT\n";
9059   else
9060     outs() << "          cmd ?(" << dyld.cmd << ")\n";
9061   outs() << "      cmdsize " << dyld.cmdsize;
9062   if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
9063     outs() << " Incorrect size\n";
9064   else
9065     outs() << "\n";
9066   if (dyld.name >= dyld.cmdsize)
9067     outs() << "         name ?(bad offset " << dyld.name << ")\n";
9068   else {
9069     const char *P = (const char *)(Ptr) + dyld.name;
9070     outs() << "         name " << P << " (offset " << dyld.name << ")\n";
9071   }
9072 }
9073 
9074 static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
9075   outs() << "     cmd LC_UUID\n";
9076   outs() << " cmdsize " << uuid.cmdsize;
9077   if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
9078     outs() << " Incorrect size\n";
9079   else
9080     outs() << "\n";
9081   outs() << "    uuid ";
9082   for (int i = 0; i < 16; ++i) {
9083     outs() << format("%02" PRIX32, uuid.uuid[i]);
9084     if (i == 3 || i == 5 || i == 7 || i == 9)
9085       outs() << "-";
9086   }
9087   outs() << "\n";
9088 }
9089 
9090 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
9091   outs() << "          cmd LC_RPATH\n";
9092   outs() << "      cmdsize " << rpath.cmdsize;
9093   if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
9094     outs() << " Incorrect size\n";
9095   else
9096     outs() << "\n";
9097   if (rpath.path >= rpath.cmdsize)
9098     outs() << "         path ?(bad offset " << rpath.path << ")\n";
9099   else {
9100     const char *P = (const char *)(Ptr) + rpath.path;
9101     outs() << "         path " << P << " (offset " << rpath.path << ")\n";
9102   }
9103 }
9104 
9105 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
9106   StringRef LoadCmdName;
9107   switch (vd.cmd) {
9108   case MachO::LC_VERSION_MIN_MACOSX:
9109     LoadCmdName = "LC_VERSION_MIN_MACOSX";
9110     break;
9111   case MachO::LC_VERSION_MIN_IPHONEOS:
9112     LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
9113     break;
9114   case MachO::LC_VERSION_MIN_TVOS:
9115     LoadCmdName = "LC_VERSION_MIN_TVOS";
9116     break;
9117   case MachO::LC_VERSION_MIN_WATCHOS:
9118     LoadCmdName = "LC_VERSION_MIN_WATCHOS";
9119     break;
9120   default:
9121     llvm_unreachable("Unknown version min load command");
9122   }
9123 
9124   outs() << "      cmd " << LoadCmdName << '\n';
9125   outs() << "  cmdsize " << vd.cmdsize;
9126   if (vd.cmdsize != sizeof(struct MachO::version_min_command))
9127     outs() << " Incorrect size\n";
9128   else
9129     outs() << "\n";
9130   outs() << "  version "
9131          << MachOObjectFile::getVersionMinMajor(vd, false) << "."
9132          << MachOObjectFile::getVersionMinMinor(vd, false);
9133   uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
9134   if (Update != 0)
9135     outs() << "." << Update;
9136   outs() << "\n";
9137   if (vd.sdk == 0)
9138     outs() << "      sdk n/a";
9139   else {
9140     outs() << "      sdk "
9141            << MachOObjectFile::getVersionMinMajor(vd, true) << "."
9142            << MachOObjectFile::getVersionMinMinor(vd, true);
9143   }
9144   Update = MachOObjectFile::getVersionMinUpdate(vd, true);
9145   if (Update != 0)
9146     outs() << "." << Update;
9147   outs() << "\n";
9148 }
9149 
9150 static void PrintNoteLoadCommand(MachO::note_command Nt) {
9151   outs() << "       cmd LC_NOTE\n";
9152   outs() << "   cmdsize " << Nt.cmdsize;
9153   if (Nt.cmdsize != sizeof(struct MachO::note_command))
9154     outs() << " Incorrect size\n";
9155   else
9156     outs() << "\n";
9157   const char *d = Nt.data_owner;
9158   outs() << "data_owner " << format("%.16s\n", d);
9159   outs() << "    offset " << Nt.offset << "\n";
9160   outs() << "      size " << Nt.size << "\n";
9161 }
9162 
9163 static void PrintBuildToolVersion(MachO::build_tool_version bv, bool verbose) {
9164   outs() << "      tool ";
9165   if (verbose)
9166     outs() << MachOObjectFile::getBuildTool(bv.tool);
9167   else
9168     outs() << bv.tool;
9169   outs() << "\n";
9170   outs() << "   version " << MachOObjectFile::getVersionString(bv.version)
9171          << "\n";
9172 }
9173 
9174 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj,
9175                                          MachO::build_version_command bd,
9176                                          bool verbose) {
9177   outs() << "       cmd LC_BUILD_VERSION\n";
9178   outs() << "   cmdsize " << bd.cmdsize;
9179   if (bd.cmdsize !=
9180       sizeof(struct MachO::build_version_command) +
9181           bd.ntools * sizeof(struct MachO::build_tool_version))
9182     outs() << " Incorrect size\n";
9183   else
9184     outs() << "\n";
9185   outs() << "  platform ";
9186   if (verbose)
9187     outs() << MachOObjectFile::getBuildPlatform(bd.platform);
9188   else
9189     outs() << bd.platform;
9190   outs() << "\n";
9191   if (bd.sdk)
9192     outs() << "       sdk " << MachOObjectFile::getVersionString(bd.sdk)
9193            << "\n";
9194   else
9195     outs() << "       sdk n/a\n";
9196   outs() << "     minos " << MachOObjectFile::getVersionString(bd.minos)
9197          << "\n";
9198   outs() << "    ntools " << bd.ntools << "\n";
9199   for (unsigned i = 0; i < bd.ntools; ++i) {
9200     MachO::build_tool_version bv = obj->getBuildToolVersion(i);
9201     PrintBuildToolVersion(bv, verbose);
9202   }
9203 }
9204 
9205 static void PrintSourceVersionCommand(MachO::source_version_command sd) {
9206   outs() << "      cmd LC_SOURCE_VERSION\n";
9207   outs() << "  cmdsize " << sd.cmdsize;
9208   if (sd.cmdsize != sizeof(struct MachO::source_version_command))
9209     outs() << " Incorrect size\n";
9210   else
9211     outs() << "\n";
9212   uint64_t a = (sd.version >> 40) & 0xffffff;
9213   uint64_t b = (sd.version >> 30) & 0x3ff;
9214   uint64_t c = (sd.version >> 20) & 0x3ff;
9215   uint64_t d = (sd.version >> 10) & 0x3ff;
9216   uint64_t e = sd.version & 0x3ff;
9217   outs() << "  version " << a << "." << b;
9218   if (e != 0)
9219     outs() << "." << c << "." << d << "." << e;
9220   else if (d != 0)
9221     outs() << "." << c << "." << d;
9222   else if (c != 0)
9223     outs() << "." << c;
9224   outs() << "\n";
9225 }
9226 
9227 static void PrintEntryPointCommand(MachO::entry_point_command ep) {
9228   outs() << "       cmd LC_MAIN\n";
9229   outs() << "   cmdsize " << ep.cmdsize;
9230   if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
9231     outs() << " Incorrect size\n";
9232   else
9233     outs() << "\n";
9234   outs() << "  entryoff " << ep.entryoff << "\n";
9235   outs() << " stacksize " << ep.stacksize << "\n";
9236 }
9237 
9238 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
9239                                        uint32_t object_size) {
9240   outs() << "          cmd LC_ENCRYPTION_INFO\n";
9241   outs() << "      cmdsize " << ec.cmdsize;
9242   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
9243     outs() << " Incorrect size\n";
9244   else
9245     outs() << "\n";
9246   outs() << "     cryptoff " << ec.cryptoff;
9247   if (ec.cryptoff > object_size)
9248     outs() << " (past end of file)\n";
9249   else
9250     outs() << "\n";
9251   outs() << "    cryptsize " << ec.cryptsize;
9252   if (ec.cryptsize > object_size)
9253     outs() << " (past end of file)\n";
9254   else
9255     outs() << "\n";
9256   outs() << "      cryptid " << ec.cryptid << "\n";
9257 }
9258 
9259 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
9260                                          uint32_t object_size) {
9261   outs() << "          cmd LC_ENCRYPTION_INFO_64\n";
9262   outs() << "      cmdsize " << ec.cmdsize;
9263   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
9264     outs() << " Incorrect size\n";
9265   else
9266     outs() << "\n";
9267   outs() << "     cryptoff " << ec.cryptoff;
9268   if (ec.cryptoff > object_size)
9269     outs() << " (past end of file)\n";
9270   else
9271     outs() << "\n";
9272   outs() << "    cryptsize " << ec.cryptsize;
9273   if (ec.cryptsize > object_size)
9274     outs() << " (past end of file)\n";
9275   else
9276     outs() << "\n";
9277   outs() << "      cryptid " << ec.cryptid << "\n";
9278   outs() << "          pad " << ec.pad << "\n";
9279 }
9280 
9281 static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
9282                                      const char *Ptr) {
9283   outs() << "     cmd LC_LINKER_OPTION\n";
9284   outs() << " cmdsize " << lo.cmdsize;
9285   if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
9286     outs() << " Incorrect size\n";
9287   else
9288     outs() << "\n";
9289   outs() << "   count " << lo.count << "\n";
9290   const char *string = Ptr + sizeof(struct MachO::linker_option_command);
9291   uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
9292   uint32_t i = 0;
9293   while (left > 0) {
9294     while (*string == '\0' && left > 0) {
9295       string++;
9296       left--;
9297     }
9298     if (left > 0) {
9299       i++;
9300       outs() << "  string #" << i << " " << format("%.*s\n", left, string);
9301       uint32_t NullPos = StringRef(string, left).find('\0');
9302       uint32_t len = std::min(NullPos, left) + 1;
9303       string += len;
9304       left -= len;
9305     }
9306   }
9307   if (lo.count != i)
9308     outs() << "   count " << lo.count << " does not match number of strings "
9309            << i << "\n";
9310 }
9311 
9312 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
9313                                      const char *Ptr) {
9314   outs() << "          cmd LC_SUB_FRAMEWORK\n";
9315   outs() << "      cmdsize " << sub.cmdsize;
9316   if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
9317     outs() << " Incorrect size\n";
9318   else
9319     outs() << "\n";
9320   if (sub.umbrella < sub.cmdsize) {
9321     const char *P = Ptr + sub.umbrella;
9322     outs() << "     umbrella " << P << " (offset " << sub.umbrella << ")\n";
9323   } else {
9324     outs() << "     umbrella ?(bad offset " << sub.umbrella << ")\n";
9325   }
9326 }
9327 
9328 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
9329                                     const char *Ptr) {
9330   outs() << "          cmd LC_SUB_UMBRELLA\n";
9331   outs() << "      cmdsize " << sub.cmdsize;
9332   if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
9333     outs() << " Incorrect size\n";
9334   else
9335     outs() << "\n";
9336   if (sub.sub_umbrella < sub.cmdsize) {
9337     const char *P = Ptr + sub.sub_umbrella;
9338     outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
9339   } else {
9340     outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
9341   }
9342 }
9343 
9344 static void PrintSubLibraryCommand(MachO::sub_library_command sub,
9345                                    const char *Ptr) {
9346   outs() << "          cmd LC_SUB_LIBRARY\n";
9347   outs() << "      cmdsize " << sub.cmdsize;
9348   if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
9349     outs() << " Incorrect size\n";
9350   else
9351     outs() << "\n";
9352   if (sub.sub_library < sub.cmdsize) {
9353     const char *P = Ptr + sub.sub_library;
9354     outs() << "  sub_library " << P << " (offset " << sub.sub_library << ")\n";
9355   } else {
9356     outs() << "  sub_library ?(bad offset " << sub.sub_library << ")\n";
9357   }
9358 }
9359 
9360 static void PrintSubClientCommand(MachO::sub_client_command sub,
9361                                   const char *Ptr) {
9362   outs() << "          cmd LC_SUB_CLIENT\n";
9363   outs() << "      cmdsize " << sub.cmdsize;
9364   if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
9365     outs() << " Incorrect size\n";
9366   else
9367     outs() << "\n";
9368   if (sub.client < sub.cmdsize) {
9369     const char *P = Ptr + sub.client;
9370     outs() << "       client " << P << " (offset " << sub.client << ")\n";
9371   } else {
9372     outs() << "       client ?(bad offset " << sub.client << ")\n";
9373   }
9374 }
9375 
9376 static void PrintRoutinesCommand(MachO::routines_command r) {
9377   outs() << "          cmd LC_ROUTINES\n";
9378   outs() << "      cmdsize " << r.cmdsize;
9379   if (r.cmdsize != sizeof(struct MachO::routines_command))
9380     outs() << " Incorrect size\n";
9381   else
9382     outs() << "\n";
9383   outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
9384   outs() << "  init_module " << r.init_module << "\n";
9385   outs() << "    reserved1 " << r.reserved1 << "\n";
9386   outs() << "    reserved2 " << r.reserved2 << "\n";
9387   outs() << "    reserved3 " << r.reserved3 << "\n";
9388   outs() << "    reserved4 " << r.reserved4 << "\n";
9389   outs() << "    reserved5 " << r.reserved5 << "\n";
9390   outs() << "    reserved6 " << r.reserved6 << "\n";
9391 }
9392 
9393 static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
9394   outs() << "          cmd LC_ROUTINES_64\n";
9395   outs() << "      cmdsize " << r.cmdsize;
9396   if (r.cmdsize != sizeof(struct MachO::routines_command_64))
9397     outs() << " Incorrect size\n";
9398   else
9399     outs() << "\n";
9400   outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
9401   outs() << "  init_module " << r.init_module << "\n";
9402   outs() << "    reserved1 " << r.reserved1 << "\n";
9403   outs() << "    reserved2 " << r.reserved2 << "\n";
9404   outs() << "    reserved3 " << r.reserved3 << "\n";
9405   outs() << "    reserved4 " << r.reserved4 << "\n";
9406   outs() << "    reserved5 " << r.reserved5 << "\n";
9407   outs() << "    reserved6 " << r.reserved6 << "\n";
9408 }
9409 
9410 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) {
9411   outs() << "\t    eax " << format("0x%08" PRIx32, cpu32.eax);
9412   outs() << " ebx    " << format("0x%08" PRIx32, cpu32.ebx);
9413   outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx);
9414   outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n";
9415   outs() << "\t    edi " << format("0x%08" PRIx32, cpu32.edi);
9416   outs() << " esi    " << format("0x%08" PRIx32, cpu32.esi);
9417   outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp);
9418   outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n";
9419   outs() << "\t    ss  " << format("0x%08" PRIx32, cpu32.ss);
9420   outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags);
9421   outs() << " eip " << format("0x%08" PRIx32, cpu32.eip);
9422   outs() << " cs  " << format("0x%08" PRIx32, cpu32.cs) << "\n";
9423   outs() << "\t    ds  " << format("0x%08" PRIx32, cpu32.ds);
9424   outs() << " es     " << format("0x%08" PRIx32, cpu32.es);
9425   outs() << " fs  " << format("0x%08" PRIx32, cpu32.fs);
9426   outs() << " gs  " << format("0x%08" PRIx32, cpu32.gs) << "\n";
9427 }
9428 
9429 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
9430   outs() << "   rax  " << format("0x%016" PRIx64, cpu64.rax);
9431   outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
9432   outs() << " rcx  " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
9433   outs() << "   rdx  " << format("0x%016" PRIx64, cpu64.rdx);
9434   outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
9435   outs() << " rsi  " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
9436   outs() << "   rbp  " << format("0x%016" PRIx64, cpu64.rbp);
9437   outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
9438   outs() << " r8   " << format("0x%016" PRIx64, cpu64.r8) << "\n";
9439   outs() << "    r9  " << format("0x%016" PRIx64, cpu64.r9);
9440   outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
9441   outs() << " r11  " << format("0x%016" PRIx64, cpu64.r11) << "\n";
9442   outs() << "   r12  " << format("0x%016" PRIx64, cpu64.r12);
9443   outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
9444   outs() << " r14  " << format("0x%016" PRIx64, cpu64.r14) << "\n";
9445   outs() << "   r15  " << format("0x%016" PRIx64, cpu64.r15);
9446   outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
9447   outs() << "rflags  " << format("0x%016" PRIx64, cpu64.rflags);
9448   outs() << " cs  " << format("0x%016" PRIx64, cpu64.cs);
9449   outs() << " fs   " << format("0x%016" PRIx64, cpu64.fs) << "\n";
9450   outs() << "    gs  " << format("0x%016" PRIx64, cpu64.gs) << "\n";
9451 }
9452 
9453 static void Print_mmst_reg(MachO::mmst_reg_t &r) {
9454   uint32_t f;
9455   outs() << "\t      mmst_reg  ";
9456   for (f = 0; f < 10; f++)
9457     outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
9458   outs() << "\n";
9459   outs() << "\t      mmst_rsrv ";
9460   for (f = 0; f < 6; f++)
9461     outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
9462   outs() << "\n";
9463 }
9464 
9465 static void Print_xmm_reg(MachO::xmm_reg_t &r) {
9466   uint32_t f;
9467   outs() << "\t      xmm_reg ";
9468   for (f = 0; f < 16; f++)
9469     outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
9470   outs() << "\n";
9471 }
9472 
9473 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
9474   outs() << "\t    fpu_reserved[0] " << fpu.fpu_reserved[0];
9475   outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
9476   outs() << "\t    control: invalid " << fpu.fpu_fcw.invalid;
9477   outs() << " denorm " << fpu.fpu_fcw.denorm;
9478   outs() << " zdiv " << fpu.fpu_fcw.zdiv;
9479   outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
9480   outs() << " undfl " << fpu.fpu_fcw.undfl;
9481   outs() << " precis " << fpu.fpu_fcw.precis << "\n";
9482   outs() << "\t\t     pc ";
9483   if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
9484     outs() << "FP_PREC_24B ";
9485   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
9486     outs() << "FP_PREC_53B ";
9487   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
9488     outs() << "FP_PREC_64B ";
9489   else
9490     outs() << fpu.fpu_fcw.pc << " ";
9491   outs() << "rc ";
9492   if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
9493     outs() << "FP_RND_NEAR ";
9494   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
9495     outs() << "FP_RND_DOWN ";
9496   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
9497     outs() << "FP_RND_UP ";
9498   else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
9499     outs() << "FP_CHOP ";
9500   outs() << "\n";
9501   outs() << "\t    status: invalid " << fpu.fpu_fsw.invalid;
9502   outs() << " denorm " << fpu.fpu_fsw.denorm;
9503   outs() << " zdiv " << fpu.fpu_fsw.zdiv;
9504   outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
9505   outs() << " undfl " << fpu.fpu_fsw.undfl;
9506   outs() << " precis " << fpu.fpu_fsw.precis;
9507   outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
9508   outs() << "\t            errsumm " << fpu.fpu_fsw.errsumm;
9509   outs() << " c0 " << fpu.fpu_fsw.c0;
9510   outs() << " c1 " << fpu.fpu_fsw.c1;
9511   outs() << " c2 " << fpu.fpu_fsw.c2;
9512   outs() << " tos " << fpu.fpu_fsw.tos;
9513   outs() << " c3 " << fpu.fpu_fsw.c3;
9514   outs() << " busy " << fpu.fpu_fsw.busy << "\n";
9515   outs() << "\t    fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
9516   outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
9517   outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
9518   outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
9519   outs() << "\t    fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
9520   outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
9521   outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
9522   outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
9523   outs() << "\t    fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
9524   outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
9525   outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
9526   outs() << "\n";
9527   outs() << "\t    fpu_stmm0:\n";
9528   Print_mmst_reg(fpu.fpu_stmm0);
9529   outs() << "\t    fpu_stmm1:\n";
9530   Print_mmst_reg(fpu.fpu_stmm1);
9531   outs() << "\t    fpu_stmm2:\n";
9532   Print_mmst_reg(fpu.fpu_stmm2);
9533   outs() << "\t    fpu_stmm3:\n";
9534   Print_mmst_reg(fpu.fpu_stmm3);
9535   outs() << "\t    fpu_stmm4:\n";
9536   Print_mmst_reg(fpu.fpu_stmm4);
9537   outs() << "\t    fpu_stmm5:\n";
9538   Print_mmst_reg(fpu.fpu_stmm5);
9539   outs() << "\t    fpu_stmm6:\n";
9540   Print_mmst_reg(fpu.fpu_stmm6);
9541   outs() << "\t    fpu_stmm7:\n";
9542   Print_mmst_reg(fpu.fpu_stmm7);
9543   outs() << "\t    fpu_xmm0:\n";
9544   Print_xmm_reg(fpu.fpu_xmm0);
9545   outs() << "\t    fpu_xmm1:\n";
9546   Print_xmm_reg(fpu.fpu_xmm1);
9547   outs() << "\t    fpu_xmm2:\n";
9548   Print_xmm_reg(fpu.fpu_xmm2);
9549   outs() << "\t    fpu_xmm3:\n";
9550   Print_xmm_reg(fpu.fpu_xmm3);
9551   outs() << "\t    fpu_xmm4:\n";
9552   Print_xmm_reg(fpu.fpu_xmm4);
9553   outs() << "\t    fpu_xmm5:\n";
9554   Print_xmm_reg(fpu.fpu_xmm5);
9555   outs() << "\t    fpu_xmm6:\n";
9556   Print_xmm_reg(fpu.fpu_xmm6);
9557   outs() << "\t    fpu_xmm7:\n";
9558   Print_xmm_reg(fpu.fpu_xmm7);
9559   outs() << "\t    fpu_xmm8:\n";
9560   Print_xmm_reg(fpu.fpu_xmm8);
9561   outs() << "\t    fpu_xmm9:\n";
9562   Print_xmm_reg(fpu.fpu_xmm9);
9563   outs() << "\t    fpu_xmm10:\n";
9564   Print_xmm_reg(fpu.fpu_xmm10);
9565   outs() << "\t    fpu_xmm11:\n";
9566   Print_xmm_reg(fpu.fpu_xmm11);
9567   outs() << "\t    fpu_xmm12:\n";
9568   Print_xmm_reg(fpu.fpu_xmm12);
9569   outs() << "\t    fpu_xmm13:\n";
9570   Print_xmm_reg(fpu.fpu_xmm13);
9571   outs() << "\t    fpu_xmm14:\n";
9572   Print_xmm_reg(fpu.fpu_xmm14);
9573   outs() << "\t    fpu_xmm15:\n";
9574   Print_xmm_reg(fpu.fpu_xmm15);
9575   outs() << "\t    fpu_rsrv4:\n";
9576   for (uint32_t f = 0; f < 6; f++) {
9577     outs() << "\t            ";
9578     for (uint32_t g = 0; g < 16; g++)
9579       outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
9580     outs() << "\n";
9581   }
9582   outs() << "\t    fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
9583   outs() << "\n";
9584 }
9585 
9586 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
9587   outs() << "\t    trapno " << format("0x%08" PRIx32, exc64.trapno);
9588   outs() << " err " << format("0x%08" PRIx32, exc64.err);
9589   outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
9590 }
9591 
9592 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
9593   outs() << "\t    r0  " << format("0x%08" PRIx32, cpu32.r[0]);
9594   outs() << " r1     "   << format("0x%08" PRIx32, cpu32.r[1]);
9595   outs() << " r2  "      << format("0x%08" PRIx32, cpu32.r[2]);
9596   outs() << " r3  "      << format("0x%08" PRIx32, cpu32.r[3]) << "\n";
9597   outs() << "\t    r4  " << format("0x%08" PRIx32, cpu32.r[4]);
9598   outs() << " r5     "   << format("0x%08" PRIx32, cpu32.r[5]);
9599   outs() << " r6  "      << format("0x%08" PRIx32, cpu32.r[6]);
9600   outs() << " r7  "      << format("0x%08" PRIx32, cpu32.r[7]) << "\n";
9601   outs() << "\t    r8  " << format("0x%08" PRIx32, cpu32.r[8]);
9602   outs() << " r9     "   << format("0x%08" PRIx32, cpu32.r[9]);
9603   outs() << " r10 "      << format("0x%08" PRIx32, cpu32.r[10]);
9604   outs() << " r11 "      << format("0x%08" PRIx32, cpu32.r[11]) << "\n";
9605   outs() << "\t    r12 " << format("0x%08" PRIx32, cpu32.r[12]);
9606   outs() << " sp     "   << format("0x%08" PRIx32, cpu32.sp);
9607   outs() << " lr  "      << format("0x%08" PRIx32, cpu32.lr);
9608   outs() << " pc  "      << format("0x%08" PRIx32, cpu32.pc) << "\n";
9609   outs() << "\t   cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n";
9610 }
9611 
9612 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
9613   outs() << "\t    x0  " << format("0x%016" PRIx64, cpu64.x[0]);
9614   outs() << " x1  "      << format("0x%016" PRIx64, cpu64.x[1]);
9615   outs() << " x2  "      << format("0x%016" PRIx64, cpu64.x[2]) << "\n";
9616   outs() << "\t    x3  " << format("0x%016" PRIx64, cpu64.x[3]);
9617   outs() << " x4  "      << format("0x%016" PRIx64, cpu64.x[4]);
9618   outs() << " x5  "      << format("0x%016" PRIx64, cpu64.x[5]) << "\n";
9619   outs() << "\t    x6  " << format("0x%016" PRIx64, cpu64.x[6]);
9620   outs() << " x7  "      << format("0x%016" PRIx64, cpu64.x[7]);
9621   outs() << " x8  "      << format("0x%016" PRIx64, cpu64.x[8]) << "\n";
9622   outs() << "\t    x9  " << format("0x%016" PRIx64, cpu64.x[9]);
9623   outs() << " x10 "      << format("0x%016" PRIx64, cpu64.x[10]);
9624   outs() << " x11 "      << format("0x%016" PRIx64, cpu64.x[11]) << "\n";
9625   outs() << "\t    x12 " << format("0x%016" PRIx64, cpu64.x[12]);
9626   outs() << " x13 "      << format("0x%016" PRIx64, cpu64.x[13]);
9627   outs() << " x14 "      << format("0x%016" PRIx64, cpu64.x[14]) << "\n";
9628   outs() << "\t    x15 " << format("0x%016" PRIx64, cpu64.x[15]);
9629   outs() << " x16 "      << format("0x%016" PRIx64, cpu64.x[16]);
9630   outs() << " x17 "      << format("0x%016" PRIx64, cpu64.x[17]) << "\n";
9631   outs() << "\t    x18 " << format("0x%016" PRIx64, cpu64.x[18]);
9632   outs() << " x19 "      << format("0x%016" PRIx64, cpu64.x[19]);
9633   outs() << " x20 "      << format("0x%016" PRIx64, cpu64.x[20]) << "\n";
9634   outs() << "\t    x21 " << format("0x%016" PRIx64, cpu64.x[21]);
9635   outs() << " x22 "      << format("0x%016" PRIx64, cpu64.x[22]);
9636   outs() << " x23 "      << format("0x%016" PRIx64, cpu64.x[23]) << "\n";
9637   outs() << "\t    x24 " << format("0x%016" PRIx64, cpu64.x[24]);
9638   outs() << " x25 "      << format("0x%016" PRIx64, cpu64.x[25]);
9639   outs() << " x26 "      << format("0x%016" PRIx64, cpu64.x[26]) << "\n";
9640   outs() << "\t    x27 " << format("0x%016" PRIx64, cpu64.x[27]);
9641   outs() << " x28 "      << format("0x%016" PRIx64, cpu64.x[28]);
9642   outs() << "  fp "      << format("0x%016" PRIx64, cpu64.fp) << "\n";
9643   outs() << "\t     lr " << format("0x%016" PRIx64, cpu64.lr);
9644   outs() << " sp  "      << format("0x%016" PRIx64, cpu64.sp);
9645   outs() << "  pc "      << format("0x%016" PRIx64, cpu64.pc) << "\n";
9646   outs() << "\t   cpsr " << format("0x%08"  PRIx32, cpu64.cpsr) << "\n";
9647 }
9648 
9649 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
9650                                bool isLittleEndian, uint32_t cputype) {
9651   if (t.cmd == MachO::LC_THREAD)
9652     outs() << "        cmd LC_THREAD\n";
9653   else if (t.cmd == MachO::LC_UNIXTHREAD)
9654     outs() << "        cmd LC_UNIXTHREAD\n";
9655   else
9656     outs() << "        cmd " << t.cmd << " (unknown)\n";
9657   outs() << "    cmdsize " << t.cmdsize;
9658   if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
9659     outs() << " Incorrect size\n";
9660   else
9661     outs() << "\n";
9662 
9663   const char *begin = Ptr + sizeof(struct MachO::thread_command);
9664   const char *end = Ptr + t.cmdsize;
9665   uint32_t flavor, count, left;
9666   if (cputype == MachO::CPU_TYPE_I386) {
9667     while (begin < end) {
9668       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9669         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9670         begin += sizeof(uint32_t);
9671       } else {
9672         flavor = 0;
9673         begin = end;
9674       }
9675       if (isLittleEndian != sys::IsLittleEndianHost)
9676         sys::swapByteOrder(flavor);
9677       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9678         memcpy((char *)&count, begin, sizeof(uint32_t));
9679         begin += sizeof(uint32_t);
9680       } else {
9681         count = 0;
9682         begin = end;
9683       }
9684       if (isLittleEndian != sys::IsLittleEndianHost)
9685         sys::swapByteOrder(count);
9686       if (flavor == MachO::x86_THREAD_STATE32) {
9687         outs() << "     flavor i386_THREAD_STATE\n";
9688         if (count == MachO::x86_THREAD_STATE32_COUNT)
9689           outs() << "      count i386_THREAD_STATE_COUNT\n";
9690         else
9691           outs() << "      count " << count
9692                  << " (not x86_THREAD_STATE32_COUNT)\n";
9693         MachO::x86_thread_state32_t cpu32;
9694         left = end - begin;
9695         if (left >= sizeof(MachO::x86_thread_state32_t)) {
9696           memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t));
9697           begin += sizeof(MachO::x86_thread_state32_t);
9698         } else {
9699           memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t));
9700           memcpy(&cpu32, begin, left);
9701           begin += left;
9702         }
9703         if (isLittleEndian != sys::IsLittleEndianHost)
9704           swapStruct(cpu32);
9705         Print_x86_thread_state32_t(cpu32);
9706       } else if (flavor == MachO::x86_THREAD_STATE) {
9707         outs() << "     flavor x86_THREAD_STATE\n";
9708         if (count == MachO::x86_THREAD_STATE_COUNT)
9709           outs() << "      count x86_THREAD_STATE_COUNT\n";
9710         else
9711           outs() << "      count " << count
9712                  << " (not x86_THREAD_STATE_COUNT)\n";
9713         struct MachO::x86_thread_state_t ts;
9714         left = end - begin;
9715         if (left >= sizeof(MachO::x86_thread_state_t)) {
9716           memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9717           begin += sizeof(MachO::x86_thread_state_t);
9718         } else {
9719           memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9720           memcpy(&ts, begin, left);
9721           begin += left;
9722         }
9723         if (isLittleEndian != sys::IsLittleEndianHost)
9724           swapStruct(ts);
9725         if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) {
9726           outs() << "\t    tsh.flavor x86_THREAD_STATE32 ";
9727           if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT)
9728             outs() << "tsh.count x86_THREAD_STATE32_COUNT\n";
9729           else
9730             outs() << "tsh.count " << ts.tsh.count
9731                    << " (not x86_THREAD_STATE32_COUNT\n";
9732           Print_x86_thread_state32_t(ts.uts.ts32);
9733         } else {
9734           outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9735                  << ts.tsh.count << "\n";
9736         }
9737       } else {
9738         outs() << "     flavor " << flavor << " (unknown)\n";
9739         outs() << "      count " << count << "\n";
9740         outs() << "      state (unknown)\n";
9741         begin += count * sizeof(uint32_t);
9742       }
9743     }
9744   } else if (cputype == MachO::CPU_TYPE_X86_64) {
9745     while (begin < end) {
9746       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9747         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9748         begin += sizeof(uint32_t);
9749       } else {
9750         flavor = 0;
9751         begin = end;
9752       }
9753       if (isLittleEndian != sys::IsLittleEndianHost)
9754         sys::swapByteOrder(flavor);
9755       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9756         memcpy((char *)&count, begin, sizeof(uint32_t));
9757         begin += sizeof(uint32_t);
9758       } else {
9759         count = 0;
9760         begin = end;
9761       }
9762       if (isLittleEndian != sys::IsLittleEndianHost)
9763         sys::swapByteOrder(count);
9764       if (flavor == MachO::x86_THREAD_STATE64) {
9765         outs() << "     flavor x86_THREAD_STATE64\n";
9766         if (count == MachO::x86_THREAD_STATE64_COUNT)
9767           outs() << "      count x86_THREAD_STATE64_COUNT\n";
9768         else
9769           outs() << "      count " << count
9770                  << " (not x86_THREAD_STATE64_COUNT)\n";
9771         MachO::x86_thread_state64_t cpu64;
9772         left = end - begin;
9773         if (left >= sizeof(MachO::x86_thread_state64_t)) {
9774           memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
9775           begin += sizeof(MachO::x86_thread_state64_t);
9776         } else {
9777           memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
9778           memcpy(&cpu64, begin, left);
9779           begin += left;
9780         }
9781         if (isLittleEndian != sys::IsLittleEndianHost)
9782           swapStruct(cpu64);
9783         Print_x86_thread_state64_t(cpu64);
9784       } else if (flavor == MachO::x86_THREAD_STATE) {
9785         outs() << "     flavor x86_THREAD_STATE\n";
9786         if (count == MachO::x86_THREAD_STATE_COUNT)
9787           outs() << "      count x86_THREAD_STATE_COUNT\n";
9788         else
9789           outs() << "      count " << count
9790                  << " (not x86_THREAD_STATE_COUNT)\n";
9791         struct MachO::x86_thread_state_t ts;
9792         left = end - begin;
9793         if (left >= sizeof(MachO::x86_thread_state_t)) {
9794           memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9795           begin += sizeof(MachO::x86_thread_state_t);
9796         } else {
9797           memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9798           memcpy(&ts, begin, left);
9799           begin += left;
9800         }
9801         if (isLittleEndian != sys::IsLittleEndianHost)
9802           swapStruct(ts);
9803         if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
9804           outs() << "\t    tsh.flavor x86_THREAD_STATE64 ";
9805           if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
9806             outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
9807           else
9808             outs() << "tsh.count " << ts.tsh.count
9809                    << " (not x86_THREAD_STATE64_COUNT\n";
9810           Print_x86_thread_state64_t(ts.uts.ts64);
9811         } else {
9812           outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9813                  << ts.tsh.count << "\n";
9814         }
9815       } else if (flavor == MachO::x86_FLOAT_STATE) {
9816         outs() << "     flavor x86_FLOAT_STATE\n";
9817         if (count == MachO::x86_FLOAT_STATE_COUNT)
9818           outs() << "      count x86_FLOAT_STATE_COUNT\n";
9819         else
9820           outs() << "      count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
9821         struct MachO::x86_float_state_t fs;
9822         left = end - begin;
9823         if (left >= sizeof(MachO::x86_float_state_t)) {
9824           memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
9825           begin += sizeof(MachO::x86_float_state_t);
9826         } else {
9827           memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
9828           memcpy(&fs, begin, left);
9829           begin += left;
9830         }
9831         if (isLittleEndian != sys::IsLittleEndianHost)
9832           swapStruct(fs);
9833         if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
9834           outs() << "\t    fsh.flavor x86_FLOAT_STATE64 ";
9835           if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
9836             outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
9837           else
9838             outs() << "fsh.count " << fs.fsh.count
9839                    << " (not x86_FLOAT_STATE64_COUNT\n";
9840           Print_x86_float_state_t(fs.ufs.fs64);
9841         } else {
9842           outs() << "\t    fsh.flavor " << fs.fsh.flavor << "  fsh.count "
9843                  << fs.fsh.count << "\n";
9844         }
9845       } else if (flavor == MachO::x86_EXCEPTION_STATE) {
9846         outs() << "     flavor x86_EXCEPTION_STATE\n";
9847         if (count == MachO::x86_EXCEPTION_STATE_COUNT)
9848           outs() << "      count x86_EXCEPTION_STATE_COUNT\n";
9849         else
9850           outs() << "      count " << count
9851                  << " (not x86_EXCEPTION_STATE_COUNT)\n";
9852         struct MachO::x86_exception_state_t es;
9853         left = end - begin;
9854         if (left >= sizeof(MachO::x86_exception_state_t)) {
9855           memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
9856           begin += sizeof(MachO::x86_exception_state_t);
9857         } else {
9858           memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
9859           memcpy(&es, begin, left);
9860           begin += left;
9861         }
9862         if (isLittleEndian != sys::IsLittleEndianHost)
9863           swapStruct(es);
9864         if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
9865           outs() << "\t    esh.flavor x86_EXCEPTION_STATE64\n";
9866           if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
9867             outs() << "\t    esh.count x86_EXCEPTION_STATE64_COUNT\n";
9868           else
9869             outs() << "\t    esh.count " << es.esh.count
9870                    << " (not x86_EXCEPTION_STATE64_COUNT\n";
9871           Print_x86_exception_state_t(es.ues.es64);
9872         } else {
9873           outs() << "\t    esh.flavor " << es.esh.flavor << "  esh.count "
9874                  << es.esh.count << "\n";
9875         }
9876       } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
9877         outs() << "     flavor x86_EXCEPTION_STATE64\n";
9878         if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
9879           outs() << "      count x86_EXCEPTION_STATE64_COUNT\n";
9880         else
9881           outs() << "      count " << count
9882                  << " (not x86_EXCEPTION_STATE64_COUNT)\n";
9883         struct MachO::x86_exception_state64_t es64;
9884         left = end - begin;
9885         if (left >= sizeof(MachO::x86_exception_state64_t)) {
9886           memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
9887           begin += sizeof(MachO::x86_exception_state64_t);
9888         } else {
9889           memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
9890           memcpy(&es64, begin, left);
9891           begin += left;
9892         }
9893         if (isLittleEndian != sys::IsLittleEndianHost)
9894           swapStruct(es64);
9895         Print_x86_exception_state_t(es64);
9896       } else {
9897         outs() << "     flavor " << flavor << " (unknown)\n";
9898         outs() << "      count " << count << "\n";
9899         outs() << "      state (unknown)\n";
9900         begin += count * sizeof(uint32_t);
9901       }
9902     }
9903   } else if (cputype == MachO::CPU_TYPE_ARM) {
9904     while (begin < end) {
9905       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9906         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9907         begin += sizeof(uint32_t);
9908       } else {
9909         flavor = 0;
9910         begin = end;
9911       }
9912       if (isLittleEndian != sys::IsLittleEndianHost)
9913         sys::swapByteOrder(flavor);
9914       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9915         memcpy((char *)&count, begin, sizeof(uint32_t));
9916         begin += sizeof(uint32_t);
9917       } else {
9918         count = 0;
9919         begin = end;
9920       }
9921       if (isLittleEndian != sys::IsLittleEndianHost)
9922         sys::swapByteOrder(count);
9923       if (flavor == MachO::ARM_THREAD_STATE) {
9924         outs() << "     flavor ARM_THREAD_STATE\n";
9925         if (count == MachO::ARM_THREAD_STATE_COUNT)
9926           outs() << "      count ARM_THREAD_STATE_COUNT\n";
9927         else
9928           outs() << "      count " << count
9929                  << " (not ARM_THREAD_STATE_COUNT)\n";
9930         MachO::arm_thread_state32_t cpu32;
9931         left = end - begin;
9932         if (left >= sizeof(MachO::arm_thread_state32_t)) {
9933           memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t));
9934           begin += sizeof(MachO::arm_thread_state32_t);
9935         } else {
9936           memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t));
9937           memcpy(&cpu32, begin, left);
9938           begin += left;
9939         }
9940         if (isLittleEndian != sys::IsLittleEndianHost)
9941           swapStruct(cpu32);
9942         Print_arm_thread_state32_t(cpu32);
9943       } else {
9944         outs() << "     flavor " << flavor << " (unknown)\n";
9945         outs() << "      count " << count << "\n";
9946         outs() << "      state (unknown)\n";
9947         begin += count * sizeof(uint32_t);
9948       }
9949     }
9950   } else if (cputype == MachO::CPU_TYPE_ARM64 ||
9951              cputype == MachO::CPU_TYPE_ARM64_32) {
9952     while (begin < end) {
9953       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9954         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9955         begin += sizeof(uint32_t);
9956       } else {
9957         flavor = 0;
9958         begin = end;
9959       }
9960       if (isLittleEndian != sys::IsLittleEndianHost)
9961         sys::swapByteOrder(flavor);
9962       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9963         memcpy((char *)&count, begin, sizeof(uint32_t));
9964         begin += sizeof(uint32_t);
9965       } else {
9966         count = 0;
9967         begin = end;
9968       }
9969       if (isLittleEndian != sys::IsLittleEndianHost)
9970         sys::swapByteOrder(count);
9971       if (flavor == MachO::ARM_THREAD_STATE64) {
9972         outs() << "     flavor ARM_THREAD_STATE64\n";
9973         if (count == MachO::ARM_THREAD_STATE64_COUNT)
9974           outs() << "      count ARM_THREAD_STATE64_COUNT\n";
9975         else
9976           outs() << "      count " << count
9977                  << " (not ARM_THREAD_STATE64_COUNT)\n";
9978         MachO::arm_thread_state64_t cpu64;
9979         left = end - begin;
9980         if (left >= sizeof(MachO::arm_thread_state64_t)) {
9981           memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
9982           begin += sizeof(MachO::arm_thread_state64_t);
9983         } else {
9984           memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
9985           memcpy(&cpu64, begin, left);
9986           begin += left;
9987         }
9988         if (isLittleEndian != sys::IsLittleEndianHost)
9989           swapStruct(cpu64);
9990         Print_arm_thread_state64_t(cpu64);
9991       } else {
9992         outs() << "     flavor " << flavor << " (unknown)\n";
9993         outs() << "      count " << count << "\n";
9994         outs() << "      state (unknown)\n";
9995         begin += count * sizeof(uint32_t);
9996       }
9997     }
9998   } else {
9999     while (begin < end) {
10000       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10001         memcpy((char *)&flavor, begin, sizeof(uint32_t));
10002         begin += sizeof(uint32_t);
10003       } else {
10004         flavor = 0;
10005         begin = end;
10006       }
10007       if (isLittleEndian != sys::IsLittleEndianHost)
10008         sys::swapByteOrder(flavor);
10009       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10010         memcpy((char *)&count, begin, sizeof(uint32_t));
10011         begin += sizeof(uint32_t);
10012       } else {
10013         count = 0;
10014         begin = end;
10015       }
10016       if (isLittleEndian != sys::IsLittleEndianHost)
10017         sys::swapByteOrder(count);
10018       outs() << "     flavor " << flavor << "\n";
10019       outs() << "      count " << count << "\n";
10020       outs() << "      state (Unknown cputype/cpusubtype)\n";
10021       begin += count * sizeof(uint32_t);
10022     }
10023   }
10024 }
10025 
10026 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
10027   if (dl.cmd == MachO::LC_ID_DYLIB)
10028     outs() << "          cmd LC_ID_DYLIB\n";
10029   else if (dl.cmd == MachO::LC_LOAD_DYLIB)
10030     outs() << "          cmd LC_LOAD_DYLIB\n";
10031   else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
10032     outs() << "          cmd LC_LOAD_WEAK_DYLIB\n";
10033   else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
10034     outs() << "          cmd LC_REEXPORT_DYLIB\n";
10035   else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
10036     outs() << "          cmd LC_LAZY_LOAD_DYLIB\n";
10037   else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
10038     outs() << "          cmd LC_LOAD_UPWARD_DYLIB\n";
10039   else
10040     outs() << "          cmd " << dl.cmd << " (unknown)\n";
10041   outs() << "      cmdsize " << dl.cmdsize;
10042   if (dl.cmdsize < sizeof(struct MachO::dylib_command))
10043     outs() << " Incorrect size\n";
10044   else
10045     outs() << "\n";
10046   if (dl.dylib.name < dl.cmdsize) {
10047     const char *P = (const char *)(Ptr) + dl.dylib.name;
10048     outs() << "         name " << P << " (offset " << dl.dylib.name << ")\n";
10049   } else {
10050     outs() << "         name ?(bad offset " << dl.dylib.name << ")\n";
10051   }
10052   outs() << "   time stamp " << dl.dylib.timestamp << " ";
10053   time_t t = dl.dylib.timestamp;
10054   outs() << ctime(&t);
10055   outs() << "      current version ";
10056   if (dl.dylib.current_version == 0xffffffff)
10057     outs() << "n/a\n";
10058   else
10059     outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
10060            << ((dl.dylib.current_version >> 8) & 0xff) << "."
10061            << (dl.dylib.current_version & 0xff) << "\n";
10062   outs() << "compatibility version ";
10063   if (dl.dylib.compatibility_version == 0xffffffff)
10064     outs() << "n/a\n";
10065   else
10066     outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
10067            << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
10068            << (dl.dylib.compatibility_version & 0xff) << "\n";
10069 }
10070 
10071 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
10072                                      uint32_t object_size) {
10073   if (ld.cmd == MachO::LC_CODE_SIGNATURE)
10074     outs() << "      cmd LC_CODE_SIGNATURE\n";
10075   else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
10076     outs() << "      cmd LC_SEGMENT_SPLIT_INFO\n";
10077   else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
10078     outs() << "      cmd LC_FUNCTION_STARTS\n";
10079   else if (ld.cmd == MachO::LC_DATA_IN_CODE)
10080     outs() << "      cmd LC_DATA_IN_CODE\n";
10081   else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
10082     outs() << "      cmd LC_DYLIB_CODE_SIGN_DRS\n";
10083   else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
10084     outs() << "      cmd LC_LINKER_OPTIMIZATION_HINT\n";
10085   else if (ld.cmd == MachO::LC_DYLD_EXPORTS_TRIE)
10086     outs() << "      cmd LC_DYLD_EXPORTS_TRIE\n";
10087   else if (ld.cmd == MachO::LC_DYLD_CHAINED_FIXUPS)
10088     outs() << "      cmd LC_DYLD_CHAINED_FIXUPS\n";
10089   else if (ld.cmd == MachO::LC_ATOM_INFO)
10090     outs() << "      cmd LC_ATOM_INFO\n";
10091   else
10092     outs() << "      cmd " << ld.cmd << " (?)\n";
10093   outs() << "  cmdsize " << ld.cmdsize;
10094   if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
10095     outs() << " Incorrect size\n";
10096   else
10097     outs() << "\n";
10098   outs() << "  dataoff " << ld.dataoff;
10099   if (ld.dataoff > object_size)
10100     outs() << " (past end of file)\n";
10101   else
10102     outs() << "\n";
10103   outs() << " datasize " << ld.datasize;
10104   uint64_t big_size = ld.dataoff;
10105   big_size += ld.datasize;
10106   if (big_size > object_size)
10107     outs() << " (past end of file)\n";
10108   else
10109     outs() << "\n";
10110 }
10111 
10112 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
10113                               uint32_t cputype, bool verbose) {
10114   StringRef Buf = Obj->getData();
10115   unsigned Index = 0;
10116   for (const auto &Command : Obj->load_commands()) {
10117     outs() << "Load command " << Index++ << "\n";
10118     if (Command.C.cmd == MachO::LC_SEGMENT) {
10119       MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
10120       const char *sg_segname = SLC.segname;
10121       PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
10122                           SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
10123                           SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
10124                           verbose);
10125       for (unsigned j = 0; j < SLC.nsects; j++) {
10126         MachO::section S = Obj->getSection(Command, j);
10127         PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
10128                      S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
10129                      SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
10130       }
10131     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
10132       MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
10133       const char *sg_segname = SLC_64.segname;
10134       PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
10135                           SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
10136                           SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
10137                           SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
10138       for (unsigned j = 0; j < SLC_64.nsects; j++) {
10139         MachO::section_64 S_64 = Obj->getSection64(Command, j);
10140         PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
10141                      S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
10142                      S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
10143                      sg_segname, filetype, Buf.size(), verbose);
10144       }
10145     } else if (Command.C.cmd == MachO::LC_SYMTAB) {
10146       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10147       PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
10148     } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
10149       MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
10150       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10151       PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
10152                                Obj->is64Bit());
10153     } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
10154                Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
10155       MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
10156       PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
10157     } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
10158                Command.C.cmd == MachO::LC_ID_DYLINKER ||
10159                Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
10160       MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
10161       PrintDyldLoadCommand(Dyld, Command.Ptr);
10162     } else if (Command.C.cmd == MachO::LC_UUID) {
10163       MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
10164       PrintUuidLoadCommand(Uuid);
10165     } else if (Command.C.cmd == MachO::LC_RPATH) {
10166       MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
10167       PrintRpathLoadCommand(Rpath, Command.Ptr);
10168     } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
10169                Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
10170                Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
10171                Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
10172       MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
10173       PrintVersionMinLoadCommand(Vd);
10174     } else if (Command.C.cmd == MachO::LC_NOTE) {
10175       MachO::note_command Nt = Obj->getNoteLoadCommand(Command);
10176       PrintNoteLoadCommand(Nt);
10177     } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) {
10178       MachO::build_version_command Bv =
10179           Obj->getBuildVersionLoadCommand(Command);
10180       PrintBuildVersionLoadCommand(Obj, Bv, verbose);
10181     } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
10182       MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
10183       PrintSourceVersionCommand(Sd);
10184     } else if (Command.C.cmd == MachO::LC_MAIN) {
10185       MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
10186       PrintEntryPointCommand(Ep);
10187     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
10188       MachO::encryption_info_command Ei =
10189           Obj->getEncryptionInfoCommand(Command);
10190       PrintEncryptionInfoCommand(Ei, Buf.size());
10191     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
10192       MachO::encryption_info_command_64 Ei =
10193           Obj->getEncryptionInfoCommand64(Command);
10194       PrintEncryptionInfoCommand64(Ei, Buf.size());
10195     } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
10196       MachO::linker_option_command Lo =
10197           Obj->getLinkerOptionLoadCommand(Command);
10198       PrintLinkerOptionCommand(Lo, Command.Ptr);
10199     } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
10200       MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
10201       PrintSubFrameworkCommand(Sf, Command.Ptr);
10202     } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
10203       MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
10204       PrintSubUmbrellaCommand(Sf, Command.Ptr);
10205     } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
10206       MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
10207       PrintSubLibraryCommand(Sl, Command.Ptr);
10208     } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
10209       MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
10210       PrintSubClientCommand(Sc, Command.Ptr);
10211     } else if (Command.C.cmd == MachO::LC_ROUTINES) {
10212       MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
10213       PrintRoutinesCommand(Rc);
10214     } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
10215       MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
10216       PrintRoutinesCommand64(Rc);
10217     } else if (Command.C.cmd == MachO::LC_THREAD ||
10218                Command.C.cmd == MachO::LC_UNIXTHREAD) {
10219       MachO::thread_command Tc = Obj->getThreadCommand(Command);
10220       PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
10221     } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
10222                Command.C.cmd == MachO::LC_ID_DYLIB ||
10223                Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
10224                Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
10225                Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
10226                Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
10227       MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
10228       PrintDylibCommand(Dl, Command.Ptr);
10229     } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
10230                Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
10231                Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
10232                Command.C.cmd == MachO::LC_DATA_IN_CODE ||
10233                Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
10234                Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT ||
10235                Command.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE ||
10236                Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS ||
10237                Command.C.cmd == MachO::LC_ATOM_INFO) {
10238       MachO::linkedit_data_command Ld =
10239           Obj->getLinkeditDataLoadCommand(Command);
10240       PrintLinkEditDataCommand(Ld, Buf.size());
10241     } else {
10242       outs() << "      cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
10243              << ")\n";
10244       outs() << "  cmdsize " << Command.C.cmdsize << "\n";
10245       // TODO: get and print the raw bytes of the load command.
10246     }
10247     // TODO: print all the other kinds of load commands.
10248   }
10249 }
10250 
10251 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
10252   if (Obj->is64Bit()) {
10253     MachO::mach_header_64 H_64;
10254     H_64 = Obj->getHeader64();
10255     PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
10256                     H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
10257   } else {
10258     MachO::mach_header H;
10259     H = Obj->getHeader();
10260     PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
10261                     H.sizeofcmds, H.flags, verbose);
10262   }
10263 }
10264 
10265 void objdump::printMachOFileHeader(const object::ObjectFile *Obj) {
10266   const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10267   PrintMachHeader(file, Verbose);
10268 }
10269 
10270 void MachODumper::printPrivateHeaders() {
10271   printMachOFileHeader(&Obj);
10272   if (!FirstPrivateHeader)
10273     printMachOLoadCommands(&Obj);
10274 }
10275 
10276 void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) {
10277   const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10278   uint32_t filetype = 0;
10279   uint32_t cputype = 0;
10280   if (file->is64Bit()) {
10281     MachO::mach_header_64 H_64;
10282     H_64 = file->getHeader64();
10283     filetype = H_64.filetype;
10284     cputype = H_64.cputype;
10285   } else {
10286     MachO::mach_header H;
10287     H = file->getHeader();
10288     filetype = H.filetype;
10289     cputype = H.cputype;
10290   }
10291   PrintLoadCommands(file, filetype, cputype, Verbose);
10292 }
10293 
10294 //===----------------------------------------------------------------------===//
10295 // export trie dumping
10296 //===----------------------------------------------------------------------===//
10297 
10298 static void printMachOExportsTrie(const object::MachOObjectFile *Obj) {
10299   uint64_t BaseSegmentAddress = 0;
10300   for (const auto &Command : Obj->load_commands()) {
10301     if (Command.C.cmd == MachO::LC_SEGMENT) {
10302       MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command);
10303       if (Seg.fileoff == 0 && Seg.filesize != 0) {
10304         BaseSegmentAddress = Seg.vmaddr;
10305         break;
10306       }
10307     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
10308       MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command);
10309       if (Seg.fileoff == 0 && Seg.filesize != 0) {
10310         BaseSegmentAddress = Seg.vmaddr;
10311         break;
10312       }
10313     }
10314   }
10315   Error Err = Error::success();
10316   for (const object::ExportEntry &Entry : Obj->exports(Err)) {
10317     uint64_t Flags = Entry.flags();
10318     bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
10319     bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
10320     bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10321                         MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
10322     bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10323                 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
10324     bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
10325     if (ReExport)
10326       outs() << "[re-export] ";
10327     else
10328       outs() << format("0x%08llX  ",
10329                        Entry.address() + BaseSegmentAddress);
10330     outs() << Entry.name();
10331     if (WeakDef || ThreadLocal || Resolver || Abs) {
10332       ListSeparator LS;
10333       outs() << " [";
10334       if (WeakDef)
10335         outs() << LS << "weak_def";
10336       if (ThreadLocal)
10337         outs() << LS << "per-thread";
10338       if (Abs)
10339         outs() << LS << "absolute";
10340       if (Resolver)
10341         outs() << LS << format("resolver=0x%08llX", Entry.other());
10342       outs() << "]";
10343     }
10344     if (ReExport) {
10345       StringRef DylibName = "unknown";
10346       int Ordinal = Entry.other() - 1;
10347       Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
10348       if (Entry.otherName().empty())
10349         outs() << " (from " << DylibName << ")";
10350       else
10351         outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
10352     }
10353     outs() << "\n";
10354   }
10355   if (Err)
10356     reportError(std::move(Err), Obj->getFileName());
10357 }
10358 
10359 //===----------------------------------------------------------------------===//
10360 // rebase table dumping
10361 //===----------------------------------------------------------------------===//
10362 
10363 static void printMachORebaseTable(object::MachOObjectFile *Obj) {
10364   outs() << "segment  section            address     type\n";
10365   Error Err = Error::success();
10366   for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) {
10367     StringRef SegmentName = Entry.segmentName();
10368     StringRef SectionName = Entry.sectionName();
10369     uint64_t Address = Entry.address();
10370 
10371     // Table lines look like: __DATA  __nl_symbol_ptr  0x0000F00C  pointer
10372     outs() << format("%-8s %-18s 0x%08" PRIX64 "  %s\n",
10373                      SegmentName.str().c_str(), SectionName.str().c_str(),
10374                      Address, Entry.typeName().str().c_str());
10375   }
10376   if (Err)
10377     reportError(std::move(Err), Obj->getFileName());
10378 }
10379 
10380 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
10381   StringRef DylibName;
10382   switch (Ordinal) {
10383   case MachO::BIND_SPECIAL_DYLIB_SELF:
10384     return "this-image";
10385   case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
10386     return "main-executable";
10387   case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
10388     return "flat-namespace";
10389   case MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP:
10390     return "weak";
10391   default:
10392     if (Ordinal > 0) {
10393       std::error_code EC =
10394           Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
10395       if (EC)
10396         return "<<bad library ordinal>>";
10397       return DylibName;
10398     }
10399   }
10400   return "<<unknown special ordinal>>";
10401 }
10402 
10403 //===----------------------------------------------------------------------===//
10404 // bind table dumping
10405 //===----------------------------------------------------------------------===//
10406 
10407 static void printMachOBindTable(object::MachOObjectFile *Obj) {
10408   // Build table of sections so names can used in final output.
10409   outs() << "segment  section            address    type       "
10410             "addend dylib            symbol\n";
10411   Error Err = Error::success();
10412   for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) {
10413     StringRef SegmentName = Entry.segmentName();
10414     StringRef SectionName = Entry.sectionName();
10415     uint64_t Address = Entry.address();
10416 
10417     // Table lines look like:
10418     //  __DATA  __got  0x00012010    pointer   0 libSystem ___stack_chk_guard
10419     StringRef Attr;
10420     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
10421       Attr = " (weak_import)";
10422     outs() << left_justify(SegmentName, 8) << " "
10423            << left_justify(SectionName, 18) << " "
10424            << format_hex(Address, 10, true) << " "
10425            << left_justify(Entry.typeName(), 8) << " "
10426            << format_decimal(Entry.addend(), 8) << " "
10427            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10428            << Entry.symbolName() << Attr << "\n";
10429   }
10430   if (Err)
10431     reportError(std::move(Err), Obj->getFileName());
10432 }
10433 
10434 //===----------------------------------------------------------------------===//
10435 // lazy bind table dumping
10436 //===----------------------------------------------------------------------===//
10437 
10438 static void printMachOLazyBindTable(object::MachOObjectFile *Obj) {
10439   outs() << "segment  section            address     "
10440             "dylib            symbol\n";
10441   Error Err = Error::success();
10442   for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) {
10443     StringRef SegmentName = Entry.segmentName();
10444     StringRef SectionName = Entry.sectionName();
10445     uint64_t Address = Entry.address();
10446 
10447     // Table lines look like:
10448     //  __DATA  __got  0x00012010 libSystem ___stack_chk_guard
10449     outs() << left_justify(SegmentName, 8) << " "
10450            << left_justify(SectionName, 18) << " "
10451            << format_hex(Address, 10, true) << " "
10452            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10453            << Entry.symbolName() << "\n";
10454   }
10455   if (Err)
10456     reportError(std::move(Err), Obj->getFileName());
10457 }
10458 
10459 //===----------------------------------------------------------------------===//
10460 // weak bind table dumping
10461 //===----------------------------------------------------------------------===//
10462 
10463 static void printMachOWeakBindTable(object::MachOObjectFile *Obj) {
10464   outs() << "segment  section            address     "
10465             "type       addend   symbol\n";
10466   Error Err = Error::success();
10467   for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) {
10468     // Strong symbols don't have a location to update.
10469     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
10470       outs() << "                                        strong              "
10471              << Entry.symbolName() << "\n";
10472       continue;
10473     }
10474     StringRef SegmentName = Entry.segmentName();
10475     StringRef SectionName = Entry.sectionName();
10476     uint64_t Address = Entry.address();
10477 
10478     // Table lines look like:
10479     // __DATA  __data  0x00001000  pointer    0   _foo
10480     outs() << left_justify(SegmentName, 8) << " "
10481            << left_justify(SectionName, 18) << " "
10482            << format_hex(Address, 10, true) << " "
10483            << left_justify(Entry.typeName(), 8) << " "
10484            << format_decimal(Entry.addend(), 8) << "   " << Entry.symbolName()
10485            << "\n";
10486   }
10487   if (Err)
10488     reportError(std::move(Err), Obj->getFileName());
10489 }
10490 
10491 // get_dyld_bind_info_symbolname() is used for disassembly and passed an
10492 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind
10493 // information for that address. If the address is found its binding symbol
10494 // name is returned.  If not nullptr is returned.
10495 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
10496                                                  struct DisassembleInfo *info) {
10497   if (info->bindtable == nullptr) {
10498     info->bindtable = std::make_unique<SymbolAddressMap>();
10499     Error Err = Error::success();
10500     for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) {
10501       uint64_t Address = Entry.address();
10502       StringRef name = Entry.symbolName();
10503       if (!name.empty())
10504         (*info->bindtable)[Address] = name;
10505     }
10506     if (Err)
10507       reportError(std::move(Err), info->O->getFileName());
10508   }
10509   auto name = info->bindtable->lookup(ReferenceValue);
10510   return !name.empty() ? name.data() : nullptr;
10511 }
10512 
10513 void objdump::printLazyBindTable(ObjectFile *o) {
10514   outs() << "\nLazy bind table:\n";
10515   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10516     printMachOLazyBindTable(MachO);
10517   else
10518     WithColor::error()
10519         << "This operation is only currently supported "
10520            "for Mach-O executable files.\n";
10521 }
10522 
10523 void objdump::printWeakBindTable(ObjectFile *o) {
10524   outs() << "\nWeak bind table:\n";
10525   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10526     printMachOWeakBindTable(MachO);
10527   else
10528     WithColor::error()
10529         << "This operation is only currently supported "
10530            "for Mach-O executable files.\n";
10531 }
10532 
10533 void objdump::printExportsTrie(const ObjectFile *o) {
10534   outs() << "\nExports trie:\n";
10535   if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10536     printMachOExportsTrie(MachO);
10537   else
10538     WithColor::error()
10539         << "This operation is only currently supported "
10540            "for Mach-O executable files.\n";
10541 }
10542 
10543 void objdump::printRebaseTable(ObjectFile *o) {
10544   outs() << "\nRebase table:\n";
10545   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10546     printMachORebaseTable(MachO);
10547   else
10548     WithColor::error()
10549         << "This operation is only currently supported "
10550            "for Mach-O executable files.\n";
10551 }
10552 
10553 void objdump::printBindTable(ObjectFile *o) {
10554   outs() << "\nBind table:\n";
10555   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10556     printMachOBindTable(MachO);
10557   else
10558     WithColor::error()
10559         << "This operation is only currently supported "
10560            "for Mach-O executable files.\n";
10561 }
10562