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/ADT/Triple.h"
21#include "llvm/BinaryFormat/MachO.h"
22#include "llvm/Config/config.h"
23#include "llvm/DebugInfo/DIContext.h"
24#include "llvm/DebugInfo/DWARF/DWARFContext.h"
25#include "llvm/Demangle/Demangle.h"
26#include "llvm/MC/MCAsmInfo.h"
27#include "llvm/MC/MCContext.h"
28#include "llvm/MC/MCDisassembler/MCDisassembler.h"
29#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCInstPrinter.h"
31#include "llvm/MC/MCInstrDesc.h"
32#include "llvm/MC/MCInstrInfo.h"
33#include "llvm/MC/MCRegisterInfo.h"
34#include "llvm/MC/MCSubtargetInfo.h"
35#include "llvm/MC/MCTargetOptions.h"
36#include "llvm/MC/TargetRegistry.h"
37#include "llvm/Object/MachO.h"
38#include "llvm/Object/MachOUniversal.h"
39#include "llvm/Option/ArgList.h"
40#include "llvm/Support/Casting.h"
41#include "llvm/Support/Debug.h"
42#include "llvm/Support/Endian.h"
43#include "llvm/Support/Format.h"
44#include "llvm/Support/FormattedStream.h"
45#include "llvm/Support/GraphWriter.h"
46#include "llvm/Support/LEB128.h"
47#include "llvm/Support/MemoryBuffer.h"
48#include "llvm/Support/TargetSelect.h"
49#include "llvm/Support/ToolOutputFile.h"
50#include "llvm/Support/WithColor.h"
51#include "llvm/Support/raw_ostream.h"
52#include <algorithm>
53#include <cstring>
54#include <system_error>
55
56#ifdef LLVM_HAVE_LIBXAR
57extern "C" {
58#include <xar/xar.h>
59}
60#endif
61
62using namespace llvm;
63using namespace llvm::object;
64using namespace llvm::objdump;
65
66bool objdump::FirstPrivateHeader;
67bool objdump::ExportsTrie;
68bool objdump::Rebase;
69bool objdump::Rpaths;
70bool objdump::Bind;
71bool objdump::LazyBind;
72bool objdump::WeakBind;
73static bool UseDbg;
74static std::string DSYMFile;
75bool objdump::FullLeadingAddr;
76bool objdump::LeadingHeaders;
77bool objdump::UniversalHeaders;
78static bool ArchiveMemberOffsets;
79bool objdump::IndirectSymbols;
80bool objdump::DataInCode;
81FunctionStartsMode objdump::FunctionStartsType =
82    objdump::FunctionStartsMode::None;
83bool objdump::LinkOptHints;
84bool objdump::InfoPlist;
85bool objdump::ChainedFixups;
86bool objdump::DyldInfo;
87bool objdump::DylibsUsed;
88bool objdump::DylibId;
89bool objdump::Verbose;
90bool objdump::ObjcMetaData;
91std::string objdump::DisSymName;
92bool objdump::SymbolicOperands;
93static std::vector<std::string> ArchFlags;
94
95static bool ArchAll = false;
96static std::string ThumbTripleName;
97
98static StringRef ordinalName(const object::MachOObjectFile *, int);
99
100void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) {
101  FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header);
102  ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie);
103  Rebase = InputArgs.hasArg(OBJDUMP_rebase);
104  Rpaths = InputArgs.hasArg(OBJDUMP_rpaths);
105  Bind = InputArgs.hasArg(OBJDUMP_bind);
106  LazyBind = InputArgs.hasArg(OBJDUMP_lazy_bind);
107  WeakBind = InputArgs.hasArg(OBJDUMP_weak_bind);
108  UseDbg = InputArgs.hasArg(OBJDUMP_g);
109  DSYMFile = InputArgs.getLastArgValue(OBJDUMP_dsym_EQ).str();
110  FullLeadingAddr = InputArgs.hasArg(OBJDUMP_full_leading_addr);
111  LeadingHeaders = !InputArgs.hasArg(OBJDUMP_no_leading_headers);
112  UniversalHeaders = InputArgs.hasArg(OBJDUMP_universal_headers);
113  ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets);
114  IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols);
115  DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code);
116  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_function_starts_EQ)) {
117    FunctionStartsType = StringSwitch<FunctionStartsMode>(A->getValue())
118                             .Case("addrs", FunctionStartsMode::Addrs)
119                             .Case("names", FunctionStartsMode::Names)
120                             .Case("both", FunctionStartsMode::Both)
121                             .Default(FunctionStartsMode::None);
122    if (FunctionStartsType == FunctionStartsMode::None)
123      invalidArgValue(A);
124  }
125  LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints);
126  InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist);
127  ChainedFixups = InputArgs.hasArg(OBJDUMP_chained_fixups);
128  DyldInfo = InputArgs.hasArg(OBJDUMP_dyld_info);
129  DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used);
130  DylibId = InputArgs.hasArg(OBJDUMP_dylib_id);
131  Verbose = !InputArgs.hasArg(OBJDUMP_non_verbose);
132  ObjcMetaData = InputArgs.hasArg(OBJDUMP_objc_meta_data);
133  DisSymName = InputArgs.getLastArgValue(OBJDUMP_dis_symname).str();
134  SymbolicOperands = !InputArgs.hasArg(OBJDUMP_no_symbolic_operands);
135  ArchFlags = InputArgs.getAllArgValues(OBJDUMP_arch_EQ);
136}
137
138static const Target *GetTarget(const MachOObjectFile *MachOObj,
139                               const char **McpuDefault,
140                               const Target **ThumbTarget) {
141  // Figure out the target triple.
142  Triple TT(TripleName);
143  if (TripleName.empty()) {
144    TT = MachOObj->getArchTriple(McpuDefault);
145    TripleName = TT.str();
146  }
147
148  if (TT.getArch() == Triple::arm) {
149    // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
150    // that support ARM are also capable of Thumb mode.
151    Triple ThumbTriple = TT;
152    std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
153    ThumbTriple.setArchName(ThumbName);
154    ThumbTripleName = ThumbTriple.str();
155  }
156
157  // Get the target specific parser.
158  std::string Error;
159  const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
160  if (TheTarget && ThumbTripleName.empty())
161    return TheTarget;
162
163  *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
164  if (*ThumbTarget)
165    return TheTarget;
166
167  WithColor::error(errs(), "llvm-objdump") << "unable to get target for '";
168  if (!TheTarget)
169    errs() << TripleName;
170  else
171    errs() << ThumbTripleName;
172  errs() << "', see --version and --triple.\n";
173  return nullptr;
174}
175
176namespace {
177struct SymbolSorter {
178  bool operator()(const SymbolRef &A, const SymbolRef &B) {
179    Expected<SymbolRef::Type> ATypeOrErr = A.getType();
180    if (!ATypeOrErr)
181      reportError(ATypeOrErr.takeError(), A.getObject()->getFileName());
182    SymbolRef::Type AType = *ATypeOrErr;
183    Expected<SymbolRef::Type> BTypeOrErr = B.getType();
184    if (!BTypeOrErr)
185      reportError(BTypeOrErr.takeError(), B.getObject()->getFileName());
186    SymbolRef::Type BType = *BTypeOrErr;
187    uint64_t AAddr =
188        (AType != SymbolRef::ST_Function) ? 0 : cantFail(A.getValue());
189    uint64_t BAddr =
190        (BType != SymbolRef::ST_Function) ? 0 : cantFail(B.getValue());
191    return AAddr < BAddr;
192  }
193};
194} // namespace
195
196// Types for the storted data in code table that is built before disassembly
197// and the predicate function to sort them.
198typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
199typedef std::vector<DiceTableEntry> DiceTable;
200typedef DiceTable::iterator dice_table_iterator;
201
202#ifdef LLVM_HAVE_LIBXAR
203namespace {
204struct ScopedXarFile {
205  xar_t xar;
206  ScopedXarFile(const char *filename, int32_t flags) {
207#pragma clang diagnostic push
208#pragma clang diagnostic ignored "-Wdeprecated-declarations"
209    xar = xar_open(filename, flags);
210#pragma clang diagnostic pop
211  }
212  ~ScopedXarFile() {
213    if (xar)
214      xar_close(xar);
215  }
216  ScopedXarFile(const ScopedXarFile &) = delete;
217  ScopedXarFile &operator=(const ScopedXarFile &) = delete;
218  operator xar_t() { return xar; }
219};
220
221struct ScopedXarIter {
222  xar_iter_t iter;
223  ScopedXarIter() : iter(xar_iter_new()) {}
224  ~ScopedXarIter() {
225    if (iter)
226      xar_iter_free(iter);
227  }
228  ScopedXarIter(const ScopedXarIter &) = delete;
229  ScopedXarIter &operator=(const ScopedXarIter &) = delete;
230  operator xar_iter_t() { return iter; }
231};
232} // namespace
233#endif // defined(LLVM_HAVE_LIBXAR)
234
235// This is used to search for a data in code table entry for the PC being
236// disassembled.  The j parameter has the PC in j.first.  A single data in code
237// table entry can cover many bytes for each of its Kind's.  So if the offset,
238// aka the i.first value, of the data in code table entry plus its Length
239// covers the PC being searched for this will return true.  If not it will
240// return false.
241static bool compareDiceTableEntries(const DiceTableEntry &i,
242                                    const DiceTableEntry &j) {
243  uint16_t Length;
244  i.second.getLength(Length);
245
246  return j.first >= i.first && j.first < i.first + Length;
247}
248
249static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
250                               unsigned short Kind) {
251  uint32_t Value, Size = 1;
252
253  switch (Kind) {
254  default:
255  case MachO::DICE_KIND_DATA:
256    if (Length >= 4) {
257      if (ShowRawInsn)
258        dumpBytes(ArrayRef(bytes, 4), outs());
259      Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
260      outs() << "\t.long " << Value;
261      Size = 4;
262    } else if (Length >= 2) {
263      if (ShowRawInsn)
264        dumpBytes(ArrayRef(bytes, 2), outs());
265      Value = bytes[1] << 8 | bytes[0];
266      outs() << "\t.short " << Value;
267      Size = 2;
268    } else {
269      if (ShowRawInsn)
270        dumpBytes(ArrayRef(bytes, 2), outs());
271      Value = bytes[0];
272      outs() << "\t.byte " << Value;
273      Size = 1;
274    }
275    if (Kind == MachO::DICE_KIND_DATA)
276      outs() << "\t@ KIND_DATA\n";
277    else
278      outs() << "\t@ data in code kind = " << Kind << "\n";
279    break;
280  case MachO::DICE_KIND_JUMP_TABLE8:
281    if (ShowRawInsn)
282      dumpBytes(ArrayRef(bytes, 1), outs());
283    Value = bytes[0];
284    outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
285    Size = 1;
286    break;
287  case MachO::DICE_KIND_JUMP_TABLE16:
288    if (ShowRawInsn)
289      dumpBytes(ArrayRef(bytes, 2), outs());
290    Value = bytes[1] << 8 | bytes[0];
291    outs() << "\t.short " << format("%5u", Value & 0xffff)
292           << "\t@ KIND_JUMP_TABLE16\n";
293    Size = 2;
294    break;
295  case MachO::DICE_KIND_JUMP_TABLE32:
296  case MachO::DICE_KIND_ABS_JUMP_TABLE32:
297    if (ShowRawInsn)
298      dumpBytes(ArrayRef(bytes, 4), outs());
299    Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
300    outs() << "\t.long " << Value;
301    if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
302      outs() << "\t@ KIND_JUMP_TABLE32\n";
303    else
304      outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
305    Size = 4;
306    break;
307  }
308  return Size;
309}
310
311static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
312                                  std::vector<SectionRef> &Sections,
313                                  std::vector<SymbolRef> &Symbols,
314                                  SmallVectorImpl<uint64_t> &FoundFns,
315                                  uint64_t &BaseSegmentAddress) {
316  const StringRef FileName = MachOObj->getFileName();
317  for (const SymbolRef &Symbol : MachOObj->symbols()) {
318    StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
319    if (!SymName.startswith("ltmp"))
320      Symbols.push_back(Symbol);
321  }
322
323  append_range(Sections, MachOObj->sections());
324
325  bool BaseSegmentAddressSet = false;
326  for (const auto &Command : MachOObj->load_commands()) {
327    if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
328      // We found a function starts segment, parse the addresses for later
329      // consumption.
330      MachO::linkedit_data_command LLC =
331          MachOObj->getLinkeditDataLoadCommand(Command);
332
333      MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
334    } else if (Command.C.cmd == MachO::LC_SEGMENT) {
335      MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
336      StringRef SegName = SLC.segname;
337      if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
338        BaseSegmentAddressSet = true;
339        BaseSegmentAddress = SLC.vmaddr;
340      }
341    } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
342      MachO::segment_command_64 SLC = MachOObj->getSegment64LoadCommand(Command);
343      StringRef SegName = SLC.segname;
344      if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
345        BaseSegmentAddressSet = true;
346        BaseSegmentAddress = SLC.vmaddr;
347      }
348    }
349  }
350}
351
352static bool DumpAndSkipDataInCode(uint64_t PC, const uint8_t *bytes,
353                                 DiceTable &Dices, uint64_t &InstSize) {
354  // Check the data in code table here to see if this is data not an
355  // instruction to be disassembled.
356  DiceTable Dice;
357  Dice.push_back(std::make_pair(PC, DiceRef()));
358  dice_table_iterator DTI =
359      std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
360                  compareDiceTableEntries);
361  if (DTI != Dices.end()) {
362    uint16_t Length;
363    DTI->second.getLength(Length);
364    uint16_t Kind;
365    DTI->second.getKind(Kind);
366    InstSize = DumpDataInCode(bytes, Length, Kind);
367    if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
368        (PC == (DTI->first + Length - 1)) && (Length & 1))
369      InstSize++;
370    return true;
371  }
372  return false;
373}
374
375static void printRelocationTargetName(const MachOObjectFile *O,
376                                      const MachO::any_relocation_info &RE,
377                                      raw_string_ostream &Fmt) {
378  // Target of a scattered relocation is an address.  In the interest of
379  // generating pretty output, scan through the symbol table looking for a
380  // symbol that aligns with that address.  If we find one, print it.
381  // Otherwise, we just print the hex address of the target.
382  const StringRef FileName = O->getFileName();
383  if (O->isRelocationScattered(RE)) {
384    uint32_t Val = O->getPlainRelocationSymbolNum(RE);
385
386    for (const SymbolRef &Symbol : O->symbols()) {
387      uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
388      if (Addr != Val)
389        continue;
390      Fmt << unwrapOrError(Symbol.getName(), FileName);
391      return;
392    }
393
394    // If we couldn't find a symbol that this relocation refers to, try
395    // to find a section beginning instead.
396    for (const SectionRef &Section : ToolSectionFilter(*O)) {
397      uint64_t Addr = Section.getAddress();
398      if (Addr != Val)
399        continue;
400      StringRef NameOrErr = unwrapOrError(Section.getName(), O->getFileName());
401      Fmt << NameOrErr;
402      return;
403    }
404
405    Fmt << format("0x%x", Val);
406    return;
407  }
408
409  StringRef S;
410  bool isExtern = O->getPlainRelocationExternal(RE);
411  uint64_t Val = O->getPlainRelocationSymbolNum(RE);
412
413  if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND &&
414      (O->getArch() == Triple::aarch64 || O->getArch() == Triple::aarch64_be)) {
415    Fmt << format("0x%0" PRIx64, Val);
416    return;
417  }
418
419  if (isExtern) {
420    symbol_iterator SI = O->symbol_begin();
421    std::advance(SI, Val);
422    S = unwrapOrError(SI->getName(), FileName);
423  } else {
424    section_iterator SI = O->section_begin();
425    // Adjust for the fact that sections are 1-indexed.
426    if (Val == 0) {
427      Fmt << "0 (?,?)";
428      return;
429    }
430    uint32_t I = Val - 1;
431    while (I != 0 && SI != O->section_end()) {
432      --I;
433      std::advance(SI, 1);
434    }
435    if (SI == O->section_end()) {
436      Fmt << Val << " (?,?)";
437    } else {
438      if (Expected<StringRef> NameOrErr = SI->getName())
439        S = *NameOrErr;
440      else
441        consumeError(NameOrErr.takeError());
442    }
443  }
444
445  Fmt << S;
446}
447
448Error objdump::getMachORelocationValueString(const MachOObjectFile *Obj,
449                                             const RelocationRef &RelRef,
450                                             SmallVectorImpl<char> &Result) {
451  DataRefImpl Rel = RelRef.getRawDataRefImpl();
452  MachO::any_relocation_info RE = Obj->getRelocation(Rel);
453
454  unsigned Arch = Obj->getArch();
455
456  std::string FmtBuf;
457  raw_string_ostream Fmt(FmtBuf);
458  unsigned Type = Obj->getAnyRelocationType(RE);
459  bool IsPCRel = Obj->getAnyRelocationPCRel(RE);
460
461  // Determine any addends that should be displayed with the relocation.
462  // These require decoding the relocation type, which is triple-specific.
463
464  // X86_64 has entirely custom relocation types.
465  if (Arch == Triple::x86_64) {
466    switch (Type) {
467    case MachO::X86_64_RELOC_GOT_LOAD:
468    case MachO::X86_64_RELOC_GOT: {
469      printRelocationTargetName(Obj, RE, Fmt);
470      Fmt << "@GOT";
471      if (IsPCRel)
472        Fmt << "PCREL";
473      break;
474    }
475    case MachO::X86_64_RELOC_SUBTRACTOR: {
476      DataRefImpl RelNext = Rel;
477      Obj->moveRelocationNext(RelNext);
478      MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
479
480      // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
481      // X86_64_RELOC_UNSIGNED.
482      // NOTE: Scattered relocations don't exist on x86_64.
483      unsigned RType = Obj->getAnyRelocationType(RENext);
484      if (RType != MachO::X86_64_RELOC_UNSIGNED)
485        reportError(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after "
486                                        "X86_64_RELOC_SUBTRACTOR.");
487
488      // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
489      // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
490      printRelocationTargetName(Obj, RENext, Fmt);
491      Fmt << "-";
492      printRelocationTargetName(Obj, RE, Fmt);
493      break;
494    }
495    case MachO::X86_64_RELOC_TLV:
496      printRelocationTargetName(Obj, RE, Fmt);
497      Fmt << "@TLV";
498      if (IsPCRel)
499        Fmt << "P";
500      break;
501    case MachO::X86_64_RELOC_SIGNED_1:
502      printRelocationTargetName(Obj, RE, Fmt);
503      Fmt << "-1";
504      break;
505    case MachO::X86_64_RELOC_SIGNED_2:
506      printRelocationTargetName(Obj, RE, Fmt);
507      Fmt << "-2";
508      break;
509    case MachO::X86_64_RELOC_SIGNED_4:
510      printRelocationTargetName(Obj, RE, Fmt);
511      Fmt << "-4";
512      break;
513    default:
514      printRelocationTargetName(Obj, RE, Fmt);
515      break;
516    }
517    // X86 and ARM share some relocation types in common.
518  } else if (Arch == Triple::x86 || Arch == Triple::arm ||
519             Arch == Triple::ppc) {
520    // Generic relocation types...
521    switch (Type) {
522    case MachO::GENERIC_RELOC_PAIR: // prints no info
523      return Error::success();
524    case MachO::GENERIC_RELOC_SECTDIFF: {
525      DataRefImpl RelNext = Rel;
526      Obj->moveRelocationNext(RelNext);
527      MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
528
529      // X86 sect diff's must be followed by a relocation of type
530      // GENERIC_RELOC_PAIR.
531      unsigned RType = Obj->getAnyRelocationType(RENext);
532
533      if (RType != MachO::GENERIC_RELOC_PAIR)
534        reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
535                                        "GENERIC_RELOC_SECTDIFF.");
536
537      printRelocationTargetName(Obj, RE, Fmt);
538      Fmt << "-";
539      printRelocationTargetName(Obj, RENext, Fmt);
540      break;
541    }
542    }
543
544    if (Arch == Triple::x86 || Arch == Triple::ppc) {
545      switch (Type) {
546      case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
547        DataRefImpl RelNext = Rel;
548        Obj->moveRelocationNext(RelNext);
549        MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
550
551        // X86 sect diff's must be followed by a relocation of type
552        // GENERIC_RELOC_PAIR.
553        unsigned RType = Obj->getAnyRelocationType(RENext);
554        if (RType != MachO::GENERIC_RELOC_PAIR)
555          reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
556                                          "GENERIC_RELOC_LOCAL_SECTDIFF.");
557
558        printRelocationTargetName(Obj, RE, Fmt);
559        Fmt << "-";
560        printRelocationTargetName(Obj, RENext, Fmt);
561        break;
562      }
563      case MachO::GENERIC_RELOC_TLV: {
564        printRelocationTargetName(Obj, RE, Fmt);
565        Fmt << "@TLV";
566        if (IsPCRel)
567          Fmt << "P";
568        break;
569      }
570      default:
571        printRelocationTargetName(Obj, RE, Fmt);
572      }
573    } else { // ARM-specific relocations
574      switch (Type) {
575      case MachO::ARM_RELOC_HALF:
576      case MachO::ARM_RELOC_HALF_SECTDIFF: {
577        // Half relocations steal a bit from the length field to encode
578        // whether this is an upper16 or a lower16 relocation.
579        bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1;
580
581        if (isUpper)
582          Fmt << ":upper16:(";
583        else
584          Fmt << ":lower16:(";
585        printRelocationTargetName(Obj, RE, Fmt);
586
587        DataRefImpl RelNext = Rel;
588        Obj->moveRelocationNext(RelNext);
589        MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
590
591        // ARM half relocs must be followed by a relocation of type
592        // ARM_RELOC_PAIR.
593        unsigned RType = Obj->getAnyRelocationType(RENext);
594        if (RType != MachO::ARM_RELOC_PAIR)
595          reportError(Obj->getFileName(), "Expected ARM_RELOC_PAIR after "
596                                          "ARM_RELOC_HALF");
597
598        // NOTE: The half of the target virtual address is stashed in the
599        // address field of the secondary relocation, but we can't reverse
600        // engineer the constant offset from it without decoding the movw/movt
601        // instruction to find the other half in its immediate field.
602
603        // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
604        // symbol/section pointer of the follow-on relocation.
605        if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
606          Fmt << "-";
607          printRelocationTargetName(Obj, RENext, Fmt);
608        }
609
610        Fmt << ")";
611        break;
612      }
613      default: {
614        printRelocationTargetName(Obj, RE, Fmt);
615      }
616      }
617    }
618  } else
619    printRelocationTargetName(Obj, RE, Fmt);
620
621  Fmt.flush();
622  Result.append(FmtBuf.begin(), FmtBuf.end());
623  return Error::success();
624}
625
626static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
627                                     uint32_t n, uint32_t count,
628                                     uint32_t stride, uint64_t addr) {
629  MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
630  uint32_t nindirectsyms = Dysymtab.nindirectsyms;
631  if (n > nindirectsyms)
632    outs() << " (entries start past the end of the indirect symbol "
633              "table) (reserved1 field greater than the table size)";
634  else if (n + count > nindirectsyms)
635    outs() << " (entries extends past the end of the indirect symbol "
636              "table)";
637  outs() << "\n";
638  uint32_t cputype = O->getHeader().cputype;
639  if (cputype & MachO::CPU_ARCH_ABI64)
640    outs() << "address            index";
641  else
642    outs() << "address    index";
643  if (verbose)
644    outs() << " name\n";
645  else
646    outs() << "\n";
647  for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
648    if (cputype & MachO::CPU_ARCH_ABI64)
649      outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
650    else
651      outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
652    MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
653    uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
654    if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
655      outs() << "LOCAL\n";
656      continue;
657    }
658    if (indirect_symbol ==
659        (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
660      outs() << "LOCAL ABSOLUTE\n";
661      continue;
662    }
663    if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
664      outs() << "ABSOLUTE\n";
665      continue;
666    }
667    outs() << format("%5u ", indirect_symbol);
668    if (verbose) {
669      MachO::symtab_command Symtab = O->getSymtabLoadCommand();
670      if (indirect_symbol < Symtab.nsyms) {
671        symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
672        SymbolRef Symbol = *Sym;
673        outs() << unwrapOrError(Symbol.getName(), O->getFileName());
674      } else {
675        outs() << "?";
676      }
677    }
678    outs() << "\n";
679  }
680}
681
682static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
683  for (const auto &Load : O->load_commands()) {
684    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
685      MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
686      for (unsigned J = 0; J < Seg.nsects; ++J) {
687        MachO::section_64 Sec = O->getSection64(Load, J);
688        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
689        if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
690            section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
691            section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
692            section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
693            section_type == MachO::S_SYMBOL_STUBS) {
694          uint32_t stride;
695          if (section_type == MachO::S_SYMBOL_STUBS)
696            stride = Sec.reserved2;
697          else
698            stride = 8;
699          if (stride == 0) {
700            outs() << "Can't print indirect symbols for (" << Sec.segname << ","
701                   << Sec.sectname << ") "
702                   << "(size of stubs in reserved2 field is zero)\n";
703            continue;
704          }
705          uint32_t count = Sec.size / stride;
706          outs() << "Indirect symbols for (" << Sec.segname << ","
707                 << Sec.sectname << ") " << count << " entries";
708          uint32_t n = Sec.reserved1;
709          PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
710        }
711      }
712    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
713      MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
714      for (unsigned J = 0; J < Seg.nsects; ++J) {
715        MachO::section Sec = O->getSection(Load, J);
716        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
717        if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
718            section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
719            section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
720            section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
721            section_type == MachO::S_SYMBOL_STUBS) {
722          uint32_t stride;
723          if (section_type == MachO::S_SYMBOL_STUBS)
724            stride = Sec.reserved2;
725          else
726            stride = 4;
727          if (stride == 0) {
728            outs() << "Can't print indirect symbols for (" << Sec.segname << ","
729                   << Sec.sectname << ") "
730                   << "(size of stubs in reserved2 field is zero)\n";
731            continue;
732          }
733          uint32_t count = Sec.size / stride;
734          outs() << "Indirect symbols for (" << Sec.segname << ","
735                 << Sec.sectname << ") " << count << " entries";
736          uint32_t n = Sec.reserved1;
737          PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
738        }
739      }
740    }
741  }
742}
743
744static void PrintRType(const uint64_t cputype, const unsigned r_type) {
745  static char const *generic_r_types[] = {
746    "VANILLA ", "PAIR    ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV     ",
747    "  6 (?) ", "  7 (?) ", "  8 (?) ", "  9 (?) ", " 10 (?) ", " 11 (?) ",
748    " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
749  };
750  static char const *x86_64_r_types[] = {
751    "UNSIGND ", "SIGNED  ", "BRANCH  ", "GOT_LD  ", "GOT     ", "SUB     ",
752    "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV     ", " 10 (?) ", " 11 (?) ",
753    " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
754  };
755  static char const *arm_r_types[] = {
756    "VANILLA ", "PAIR    ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ",
757    "BR24    ", "T_BR22  ", "T_BR32  ", "HALF    ", "HALFDIF ",
758    " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
759  };
760  static char const *arm64_r_types[] = {
761    "UNSIGND ", "SUB     ", "BR26    ", "PAGE21  ", "PAGOF12 ",
762    "GOTLDP  ", "GOTLDPOF", "PTRTGOT ", "TLVLDP  ", "TLVLDPOF",
763    "ADDEND  ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
764  };
765
766  if (r_type > 0xf){
767    outs() << format("%-7u", r_type) << " ";
768    return;
769  }
770  switch (cputype) {
771    case MachO::CPU_TYPE_I386:
772      outs() << generic_r_types[r_type];
773      break;
774    case MachO::CPU_TYPE_X86_64:
775      outs() << x86_64_r_types[r_type];
776      break;
777    case MachO::CPU_TYPE_ARM:
778      outs() << arm_r_types[r_type];
779      break;
780    case MachO::CPU_TYPE_ARM64:
781    case MachO::CPU_TYPE_ARM64_32:
782      outs() << arm64_r_types[r_type];
783      break;
784    default:
785      outs() << format("%-7u ", r_type);
786  }
787}
788
789static void PrintRLength(const uint64_t cputype, const unsigned r_type,
790                         const unsigned r_length, const bool previous_arm_half){
791  if (cputype == MachO::CPU_TYPE_ARM &&
792      (r_type == MachO::ARM_RELOC_HALF ||
793       r_type == MachO::ARM_RELOC_HALF_SECTDIFF || previous_arm_half == true)) {
794    if ((r_length & 0x1) == 0)
795      outs() << "lo/";
796    else
797      outs() << "hi/";
798    if ((r_length & 0x1) == 0)
799      outs() << "arm ";
800    else
801      outs() << "thm ";
802  } else {
803    switch (r_length) {
804      case 0:
805        outs() << "byte   ";
806        break;
807      case 1:
808        outs() << "word   ";
809        break;
810      case 2:
811        outs() << "long   ";
812        break;
813      case 3:
814        if (cputype == MachO::CPU_TYPE_X86_64)
815          outs() << "quad   ";
816        else
817          outs() << format("?(%2d)  ", r_length);
818        break;
819      default:
820        outs() << format("?(%2d)  ", r_length);
821    }
822  }
823}
824
825static void PrintRelocationEntries(const MachOObjectFile *O,
826                                   const relocation_iterator Begin,
827                                   const relocation_iterator End,
828                                   const uint64_t cputype,
829                                   const bool verbose) {
830  const MachO::symtab_command Symtab = O->getSymtabLoadCommand();
831  bool previous_arm_half = false;
832  bool previous_sectdiff = false;
833  uint32_t sectdiff_r_type = 0;
834
835  for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) {
836    const DataRefImpl Rel = Reloc->getRawDataRefImpl();
837    const MachO::any_relocation_info RE = O->getRelocation(Rel);
838    const unsigned r_type = O->getAnyRelocationType(RE);
839    const bool r_scattered = O->isRelocationScattered(RE);
840    const unsigned r_pcrel = O->getAnyRelocationPCRel(RE);
841    const unsigned r_length = O->getAnyRelocationLength(RE);
842    const unsigned r_address = O->getAnyRelocationAddress(RE);
843    const bool r_extern = (r_scattered ? false :
844                           O->getPlainRelocationExternal(RE));
845    const uint32_t r_value = (r_scattered ?
846                              O->getScatteredRelocationValue(RE) : 0);
847    const unsigned r_symbolnum = (r_scattered ? 0 :
848                                  O->getPlainRelocationSymbolNum(RE));
849
850    if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) {
851      if (verbose) {
852        // scattered: address
853        if ((cputype == MachO::CPU_TYPE_I386 &&
854             r_type == MachO::GENERIC_RELOC_PAIR) ||
855            (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR))
856          outs() << "         ";
857        else
858          outs() << format("%08x ", (unsigned int)r_address);
859
860        // scattered: pcrel
861        if (r_pcrel)
862          outs() << "True  ";
863        else
864          outs() << "False ";
865
866        // scattered: length
867        PrintRLength(cputype, r_type, r_length, previous_arm_half);
868
869        // scattered: extern & type
870        outs() << "n/a    ";
871        PrintRType(cputype, r_type);
872
873        // scattered: scattered & value
874        outs() << format("True      0x%08x", (unsigned int)r_value);
875        if (previous_sectdiff == false) {
876          if ((cputype == MachO::CPU_TYPE_ARM &&
877               r_type == MachO::ARM_RELOC_PAIR))
878            outs() << format(" half = 0x%04x ", (unsigned int)r_address);
879        } else if (cputype == MachO::CPU_TYPE_ARM &&
880                   sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF)
881          outs() << format(" other_half = 0x%04x ", (unsigned int)r_address);
882        if ((cputype == MachO::CPU_TYPE_I386 &&
883             (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
884              r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) ||
885            (cputype == MachO::CPU_TYPE_ARM &&
886             (sectdiff_r_type == MachO::ARM_RELOC_SECTDIFF ||
887              sectdiff_r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
888              sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF))) {
889          previous_sectdiff = true;
890          sectdiff_r_type = r_type;
891        } else {
892          previous_sectdiff = false;
893          sectdiff_r_type = 0;
894        }
895        if (cputype == MachO::CPU_TYPE_ARM &&
896            (r_type == MachO::ARM_RELOC_HALF ||
897             r_type == MachO::ARM_RELOC_HALF_SECTDIFF))
898          previous_arm_half = true;
899        else
900          previous_arm_half = false;
901        outs() << "\n";
902      }
903      else {
904        // scattered: address pcrel length extern type scattered value
905        outs() << format("%08x %1d     %-2d     n/a    %-7d 1         0x%08x\n",
906                         (unsigned int)r_address, r_pcrel, r_length, r_type,
907                         (unsigned int)r_value);
908      }
909    }
910    else {
911      if (verbose) {
912        // plain: address
913        if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)
914          outs() << "         ";
915        else
916          outs() << format("%08x ", (unsigned int)r_address);
917
918        // plain: pcrel
919        if (r_pcrel)
920          outs() << "True  ";
921        else
922          outs() << "False ";
923
924        // plain: length
925        PrintRLength(cputype, r_type, r_length, previous_arm_half);
926
927        if (r_extern) {
928          // plain: extern & type & scattered
929          outs() << "True   ";
930          PrintRType(cputype, r_type);
931          outs() << "False     ";
932
933          // plain: symbolnum/value
934          if (r_symbolnum > Symtab.nsyms)
935            outs() << format("?(%d)\n", r_symbolnum);
936          else {
937            SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum);
938            Expected<StringRef> SymNameNext = Symbol.getName();
939            const char *name = nullptr;
940            if (SymNameNext)
941              name = SymNameNext->data();
942            if (name == nullptr)
943              outs() << format("?(%d)\n", r_symbolnum);
944            else
945              outs() << name << "\n";
946          }
947        }
948        else {
949          // plain: extern & type & scattered
950          outs() << "False  ";
951          PrintRType(cputype, r_type);
952          outs() << "False     ";
953
954          // plain: symbolnum/value
955          if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)
956            outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
957          else if ((cputype == MachO::CPU_TYPE_ARM64 ||
958                    cputype == MachO::CPU_TYPE_ARM64_32) &&
959                   r_type == MachO::ARM64_RELOC_ADDEND)
960            outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
961          else {
962            outs() << format("%d ", r_symbolnum);
963            if (r_symbolnum == MachO::R_ABS)
964              outs() << "R_ABS\n";
965            else {
966              // in this case, r_symbolnum is actually a 1-based section number
967              uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a;
968              if (r_symbolnum > 0 && r_symbolnum <= nsects) {
969                object::DataRefImpl DRI;
970                DRI.d.a = r_symbolnum-1;
971                StringRef SegName = O->getSectionFinalSegmentName(DRI);
972                if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
973                  outs() << "(" << SegName << "," << *NameOrErr << ")\n";
974                else
975                  outs() << "(?,?)\n";
976              }
977              else {
978                outs() << "(?,?)\n";
979              }
980            }
981          }
982        }
983        if (cputype == MachO::CPU_TYPE_ARM &&
984            (r_type == MachO::ARM_RELOC_HALF ||
985             r_type == MachO::ARM_RELOC_HALF_SECTDIFF))
986          previous_arm_half = true;
987        else
988          previous_arm_half = false;
989      }
990      else {
991        // plain: address pcrel length extern type scattered symbolnum/section
992        outs() << format("%08x %1d     %-2d     %1d      %-7d 0         %d\n",
993                         (unsigned int)r_address, r_pcrel, r_length, r_extern,
994                         r_type, r_symbolnum);
995      }
996    }
997  }
998}
999
1000static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
1001  const uint64_t cputype = O->getHeader().cputype;
1002  const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
1003  if (Dysymtab.nextrel != 0) {
1004    outs() << "External relocation information " << Dysymtab.nextrel
1005           << " entries";
1006    outs() << "\naddress  pcrel length extern type    scattered "
1007              "symbolnum/value\n";
1008    PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype,
1009                           verbose);
1010  }
1011  if (Dysymtab.nlocrel != 0) {
1012    outs() << format("Local relocation information %u entries",
1013                     Dysymtab.nlocrel);
1014    outs() << "\naddress  pcrel length extern type    scattered "
1015              "symbolnum/value\n";
1016    PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype,
1017                           verbose);
1018  }
1019  for (const auto &Load : O->load_commands()) {
1020    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1021      const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
1022      for (unsigned J = 0; J < Seg.nsects; ++J) {
1023        const MachO::section_64 Sec = O->getSection64(Load, J);
1024        if (Sec.nreloc != 0) {
1025          DataRefImpl DRI;
1026          DRI.d.a = J;
1027          const StringRef SegName = O->getSectionFinalSegmentName(DRI);
1028          if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
1029            outs() << "Relocation information (" << SegName << "," << *NameOrErr
1030                   << format(") %u entries", Sec.nreloc);
1031          else
1032            outs() << "Relocation information (" << SegName << ",?) "
1033                   << format("%u entries", Sec.nreloc);
1034          outs() << "\naddress  pcrel length extern type    scattered "
1035                    "symbolnum/value\n";
1036          PrintRelocationEntries(O, O->section_rel_begin(DRI),
1037                                 O->section_rel_end(DRI), cputype, verbose);
1038        }
1039      }
1040    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1041      const MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
1042      for (unsigned J = 0; J < Seg.nsects; ++J) {
1043        const MachO::section Sec = O->getSection(Load, J);
1044        if (Sec.nreloc != 0) {
1045          DataRefImpl DRI;
1046          DRI.d.a = J;
1047          const StringRef SegName = O->getSectionFinalSegmentName(DRI);
1048          if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
1049            outs() << "Relocation information (" << SegName << "," << *NameOrErr
1050                   << format(") %u entries", Sec.nreloc);
1051          else
1052            outs() << "Relocation information (" << SegName << ",?) "
1053                   << format("%u entries", Sec.nreloc);
1054          outs() << "\naddress  pcrel length extern type    scattered "
1055                    "symbolnum/value\n";
1056          PrintRelocationEntries(O, O->section_rel_begin(DRI),
1057                                 O->section_rel_end(DRI), cputype, verbose);
1058        }
1059      }
1060    }
1061  }
1062}
1063
1064static void PrintFunctionStarts(MachOObjectFile *O) {
1065  uint64_t BaseSegmentAddress = 0;
1066  for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
1067    if (Command.C.cmd == MachO::LC_SEGMENT) {
1068      MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
1069      if (StringRef(SLC.segname) == "__TEXT") {
1070        BaseSegmentAddress = SLC.vmaddr;
1071        break;
1072      }
1073    } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1074      MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
1075      if (StringRef(SLC.segname) == "__TEXT") {
1076        BaseSegmentAddress = SLC.vmaddr;
1077        break;
1078      }
1079    }
1080  }
1081
1082  SmallVector<uint64_t, 8> FunctionStarts;
1083  for (const MachOObjectFile::LoadCommandInfo &LC : O->load_commands()) {
1084    if (LC.C.cmd == MachO::LC_FUNCTION_STARTS) {
1085      MachO::linkedit_data_command FunctionStartsLC =
1086          O->getLinkeditDataLoadCommand(LC);
1087      O->ReadULEB128s(FunctionStartsLC.dataoff, FunctionStarts);
1088      break;
1089    }
1090  }
1091
1092  DenseMap<uint64_t, StringRef> SymbolNames;
1093  if (FunctionStartsType == FunctionStartsMode::Names ||
1094      FunctionStartsType == FunctionStartsMode::Both) {
1095    for (SymbolRef Sym : O->symbols()) {
1096      if (Expected<uint64_t> Addr = Sym.getAddress()) {
1097        if (Expected<StringRef> Name = Sym.getName()) {
1098          SymbolNames[*Addr] = *Name;
1099        }
1100      }
1101    }
1102  }
1103
1104  for (uint64_t S : FunctionStarts) {
1105    uint64_t Addr = BaseSegmentAddress + S;
1106    if (FunctionStartsType == FunctionStartsMode::Names) {
1107      auto It = SymbolNames.find(Addr);
1108      if (It != SymbolNames.end())
1109        outs() << It->second << "\n";
1110    } else {
1111      if (O->is64Bit())
1112        outs() << format("%016" PRIx64, Addr);
1113      else
1114        outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr));
1115
1116      if (FunctionStartsType == FunctionStartsMode::Both) {
1117        auto It = SymbolNames.find(Addr);
1118        if (It != SymbolNames.end())
1119          outs() << " " << It->second;
1120        else
1121          outs() << " ?";
1122      }
1123      outs() << "\n";
1124    }
1125  }
1126}
1127
1128static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
1129  MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
1130  uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
1131  outs() << "Data in code table (" << nentries << " entries)\n";
1132  outs() << "offset     length kind\n";
1133  for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
1134       ++DI) {
1135    uint32_t Offset;
1136    DI->getOffset(Offset);
1137    outs() << format("0x%08" PRIx32, Offset) << " ";
1138    uint16_t Length;
1139    DI->getLength(Length);
1140    outs() << format("%6u", Length) << " ";
1141    uint16_t Kind;
1142    DI->getKind(Kind);
1143    if (verbose) {
1144      switch (Kind) {
1145      case MachO::DICE_KIND_DATA:
1146        outs() << "DATA";
1147        break;
1148      case MachO::DICE_KIND_JUMP_TABLE8:
1149        outs() << "JUMP_TABLE8";
1150        break;
1151      case MachO::DICE_KIND_JUMP_TABLE16:
1152        outs() << "JUMP_TABLE16";
1153        break;
1154      case MachO::DICE_KIND_JUMP_TABLE32:
1155        outs() << "JUMP_TABLE32";
1156        break;
1157      case MachO::DICE_KIND_ABS_JUMP_TABLE32:
1158        outs() << "ABS_JUMP_TABLE32";
1159        break;
1160      default:
1161        outs() << format("0x%04" PRIx32, Kind);
1162        break;
1163      }
1164    } else
1165      outs() << format("0x%04" PRIx32, Kind);
1166    outs() << "\n";
1167  }
1168}
1169
1170static void PrintLinkOptHints(MachOObjectFile *O) {
1171  MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
1172  const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
1173  uint32_t nloh = LohLC.datasize;
1174  outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
1175  for (uint32_t i = 0; i < nloh;) {
1176    unsigned n;
1177    uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
1178    i += n;
1179    outs() << "    identifier " << identifier << " ";
1180    if (i >= nloh)
1181      return;
1182    switch (identifier) {
1183    case 1:
1184      outs() << "AdrpAdrp\n";
1185      break;
1186    case 2:
1187      outs() << "AdrpLdr\n";
1188      break;
1189    case 3:
1190      outs() << "AdrpAddLdr\n";
1191      break;
1192    case 4:
1193      outs() << "AdrpLdrGotLdr\n";
1194      break;
1195    case 5:
1196      outs() << "AdrpAddStr\n";
1197      break;
1198    case 6:
1199      outs() << "AdrpLdrGotStr\n";
1200      break;
1201    case 7:
1202      outs() << "AdrpAdd\n";
1203      break;
1204    case 8:
1205      outs() << "AdrpLdrGot\n";
1206      break;
1207    default:
1208      outs() << "Unknown identifier value\n";
1209      break;
1210    }
1211    uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
1212    i += n;
1213    outs() << "    narguments " << narguments << "\n";
1214    if (i >= nloh)
1215      return;
1216
1217    for (uint32_t j = 0; j < narguments; j++) {
1218      uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
1219      i += n;
1220      outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
1221      if (i >= nloh)
1222        return;
1223    }
1224  }
1225}
1226
1227static SmallVector<std::string> GetSegmentNames(object::MachOObjectFile *O) {
1228  SmallVector<std::string> Ret;
1229  for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
1230    if (Command.C.cmd == MachO::LC_SEGMENT) {
1231      MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
1232      Ret.push_back(SLC.segname);
1233    } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1234      MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
1235      Ret.push_back(SLC.segname);
1236    }
1237  }
1238  return Ret;
1239}
1240
1241static void
1242PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) {
1243  outs() << "chained fixups header (LC_DYLD_CHAINED_FIXUPS)\n";
1244  outs() << "  fixups_version = " << H.fixups_version << '\n';
1245  outs() << "  starts_offset  = " << H.starts_offset << '\n';
1246  outs() << "  imports_offset = " << H.imports_offset << '\n';
1247  outs() << "  symbols_offset = " << H.symbols_offset << '\n';
1248  outs() << "  imports_count  = " << H.imports_count << '\n';
1249
1250  outs() << "  imports_format = " << H.imports_format;
1251  switch (H.imports_format) {
1252  case llvm::MachO::DYLD_CHAINED_IMPORT:
1253    outs() << " (DYLD_CHAINED_IMPORT)";
1254    break;
1255  case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND:
1256    outs() << " (DYLD_CHAINED_IMPORT_ADDEND)";
1257    break;
1258  case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND64:
1259    outs() << " (DYLD_CHAINED_IMPORT_ADDEND64)";
1260    break;
1261  }
1262  outs() << '\n';
1263
1264  outs() << "  symbols_format = " << H.symbols_format;
1265  if (H.symbols_format == llvm::MachO::DYLD_CHAINED_SYMBOL_ZLIB)
1266    outs() << " (zlib compressed)";
1267  outs() << '\n';
1268}
1269
1270static constexpr std::array<StringRef, 13> PointerFormats{
1271    "DYLD_CHAINED_PTR_ARM64E",
1272    "DYLD_CHAINED_PTR_64",
1273    "DYLD_CHAINED_PTR_32",
1274    "DYLD_CHAINED_PTR_32_CACHE",
1275    "DYLD_CHAINED_PTR_32_FIRMWARE",
1276    "DYLD_CHAINED_PTR_64_OFFSET",
1277    "DYLD_CHAINED_PTR_ARM64E_KERNEL",
1278    "DYLD_CHAINED_PTR_64_KERNEL_CACHE",
1279    "DYLD_CHAINED_PTR_ARM64E_USERLAND",
1280    "DYLD_CHAINED_PTR_ARM64E_FIRMWARE",
1281    "DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE",
1282    "DYLD_CHAINED_PTR_ARM64E_USERLAND24",
1283};
1284
1285static void PrintChainedFixupsSegment(const ChainedFixupsSegment &Segment,
1286                                      StringRef SegName) {
1287  outs() << "chained starts in segment " << Segment.SegIdx << " (" << SegName
1288         << ")\n";
1289  outs() << "  size = " << Segment.Header.size << '\n';
1290  outs() << "  page_size = " << format("0x%0" PRIx16, Segment.Header.page_size)
1291         << '\n';
1292
1293  outs() << "  pointer_format = " << Segment.Header.pointer_format;
1294  if ((Segment.Header.pointer_format - 1) <
1295      MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24)
1296    outs() << " (" << PointerFormats[Segment.Header.pointer_format - 1] << ")";
1297  outs() << '\n';
1298
1299  outs() << "  segment_offset = "
1300         << format("0x%0" PRIx64, Segment.Header.segment_offset) << '\n';
1301  outs() << "  max_valid_pointer = " << Segment.Header.max_valid_pointer
1302         << '\n';
1303  outs() << "  page_count = " << Segment.Header.page_count << '\n';
1304  for (auto [Index, PageStart] : enumerate(Segment.PageStarts)) {
1305    outs() << "    page_start[" << Index << "] = " << PageStart;
1306    // FIXME: Support DYLD_CHAINED_PTR_START_MULTI (32-bit only)
1307    if (PageStart == MachO::DYLD_CHAINED_PTR_START_NONE)
1308      outs() << " (DYLD_CHAINED_PTR_START_NONE)";
1309    outs() << '\n';
1310  }
1311}
1312
1313static void PrintChainedFixupTarget(ChainedFixupTarget &Target, size_t Idx,
1314                                    int Format, MachOObjectFile *O) {
1315  if (Format == MachO::DYLD_CHAINED_IMPORT)
1316    outs() << "dyld chained import";
1317  else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND)
1318    outs() << "dyld chained import addend";
1319  else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND64)
1320    outs() << "dyld chained import addend64";
1321  // FIXME: otool prints the encoded value as well.
1322  outs() << '[' << Idx << "]\n";
1323
1324  outs() << "  lib_ordinal = " << Target.libOrdinal() << " ("
1325         << ordinalName(O, Target.libOrdinal()) << ")\n";
1326  outs() << "  weak_import = " << Target.weakImport() << '\n';
1327  outs() << "  name_offset = " << Target.nameOffset() << " ("
1328         << Target.symbolName() << ")\n";
1329  if (Format != MachO::DYLD_CHAINED_IMPORT)
1330    outs() << "  addend      = " << (int64_t)Target.addend() << '\n';
1331}
1332
1333static void PrintChainedFixups(MachOObjectFile *O) {
1334  // MachOObjectFile::getChainedFixupsHeader() reads LC_DYLD_CHAINED_FIXUPS.
1335  // FIXME: Support chained fixups in __TEXT,__chain_starts section too.
1336  auto ChainedFixupHeader =
1337      unwrapOrError(O->getChainedFixupsHeader(), O->getFileName());
1338  if (!ChainedFixupHeader)
1339    return;
1340
1341  PrintChainedFixupsHeader(*ChainedFixupHeader);
1342
1343  auto [SegCount, Segments] =
1344      unwrapOrError(O->getChainedFixupsSegments(), O->getFileName());
1345
1346  auto SegNames = GetSegmentNames(O);
1347
1348  size_t StartsIdx = 0;
1349  outs() << "chained starts in image\n";
1350  outs() << "  seg_count = " << SegCount << '\n';
1351  for (size_t I = 0; I < SegCount; ++I) {
1352    uint64_t SegOffset = 0;
1353    if (StartsIdx < Segments.size() && I == Segments[StartsIdx].SegIdx) {
1354      SegOffset = Segments[StartsIdx].Offset;
1355      ++StartsIdx;
1356    }
1357
1358    outs() << "    seg_offset[" << I << "] = " << SegOffset << " ("
1359           << SegNames[I] << ")\n";
1360  }
1361
1362  for (const ChainedFixupsSegment &S : Segments)
1363    PrintChainedFixupsSegment(S, SegNames[S.SegIdx]);
1364
1365  auto FixupTargets =
1366      unwrapOrError(O->getDyldChainedFixupTargets(), O->getFileName());
1367
1368  uint32_t ImportsFormat = ChainedFixupHeader->imports_format;
1369  for (auto [Idx, Target] : enumerate(FixupTargets))
1370    PrintChainedFixupTarget(Target, Idx, ImportsFormat, O);
1371}
1372
1373static void PrintDyldInfo(MachOObjectFile *O) {
1374  Error Err = Error::success();
1375
1376  size_t SegmentWidth = strlen("segment");
1377  size_t SectionWidth = strlen("section");
1378  size_t AddressWidth = strlen("address");
1379  size_t AddendWidth = strlen("addend");
1380  size_t DylibWidth = strlen("dylib");
1381  const size_t PointerWidth = 2 + O->getBytesInAddress() * 2;
1382
1383  auto HexLength = [](uint64_t Num) {
1384    return Num ? (size_t)divideCeil(Log2_64(Num), 4) : 1;
1385  };
1386  for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
1387    SegmentWidth = std::max(SegmentWidth, Entry.segmentName().size());
1388    SectionWidth = std::max(SectionWidth, Entry.sectionName().size());
1389    AddressWidth = std::max(AddressWidth, HexLength(Entry.address()) + 2);
1390    if (Entry.isBind()) {
1391      AddendWidth = std::max(AddendWidth, HexLength(Entry.addend()) + 2);
1392      DylibWidth = std::max(DylibWidth, Entry.symbolName().size());
1393    }
1394  }
1395  // Errors will be handled when printing the table.
1396  if (Err)
1397    consumeError(std::move(Err));
1398
1399  outs() << "dyld information:\n";
1400  outs() << left_justify("segment", SegmentWidth) << ' '
1401         << left_justify("section", SectionWidth) << ' '
1402         << left_justify("address", AddressWidth) << ' '
1403         << left_justify("pointer", PointerWidth) << " type   "
1404         << left_justify("addend", AddendWidth) << ' '
1405         << left_justify("dylib", DylibWidth) << " symbol/vm address\n";
1406  for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
1407    outs() << left_justify(Entry.segmentName(), SegmentWidth) << ' '
1408           << left_justify(Entry.sectionName(), SectionWidth) << ' ' << "0x"
1409           << left_justify(utohexstr(Entry.address()), AddressWidth - 2) << ' '
1410           << format_hex(Entry.rawValue(), PointerWidth, true) << ' ';
1411    if (Entry.isBind()) {
1412      outs() << "bind   "
1413             << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2)
1414             << ' ' << left_justify(ordinalName(O, Entry.ordinal()), DylibWidth)
1415             << ' ' << Entry.symbolName();
1416      if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
1417        outs() << " (weak import)";
1418      outs() << '\n';
1419    } else {
1420      assert(Entry.isRebase());
1421      outs() << "rebase";
1422      outs().indent(AddendWidth + DylibWidth + 2);
1423      outs() << format("0x%" PRIX64, Entry.pointerValue()) << '\n';
1424    }
1425  }
1426  if (Err)
1427    reportError(std::move(Err), O->getFileName());
1428
1429  // TODO: Print opcode-based fixups if the object uses those.
1430}
1431
1432static void PrintDylibs(MachOObjectFile *O, bool JustId) {
1433  unsigned Index = 0;
1434  for (const auto &Load : O->load_commands()) {
1435    if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
1436        (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
1437                     Load.C.cmd == MachO::LC_LOAD_DYLIB ||
1438                     Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
1439                     Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
1440                     Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
1441                     Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
1442      MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
1443      if (dl.dylib.name < dl.cmdsize) {
1444        const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
1445        if (JustId)
1446          outs() << p << "\n";
1447        else {
1448          outs() << "\t" << p;
1449          outs() << " (compatibility version "
1450                 << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
1451                 << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
1452                 << (dl.dylib.compatibility_version & 0xff) << ",";
1453          outs() << " current version "
1454                 << ((dl.dylib.current_version >> 16) & 0xffff) << "."
1455                 << ((dl.dylib.current_version >> 8) & 0xff) << "."
1456                 << (dl.dylib.current_version & 0xff);
1457          if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
1458            outs() << ", weak";
1459          if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
1460            outs() << ", reexport";
1461          if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
1462            outs() << ", upward";
1463          if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
1464            outs() << ", lazy";
1465          outs() << ")\n";
1466        }
1467      } else {
1468        outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
1469        if (Load.C.cmd == MachO::LC_ID_DYLIB)
1470          outs() << "LC_ID_DYLIB ";
1471        else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
1472          outs() << "LC_LOAD_DYLIB ";
1473        else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
1474          outs() << "LC_LOAD_WEAK_DYLIB ";
1475        else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
1476          outs() << "LC_LAZY_LOAD_DYLIB ";
1477        else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
1478          outs() << "LC_REEXPORT_DYLIB ";
1479        else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
1480          outs() << "LC_LOAD_UPWARD_DYLIB ";
1481        else
1482          outs() << "LC_??? ";
1483        outs() << "command " << Index++ << "\n";
1484      }
1485    }
1486  }
1487}
1488
1489static void printRpaths(MachOObjectFile *O) {
1490  for (const auto &Command : O->load_commands()) {
1491    if (Command.C.cmd == MachO::LC_RPATH) {
1492      auto Rpath = O->getRpathCommand(Command);
1493      const char *P = (const char *)(Command.Ptr) + Rpath.path;
1494      outs() << P << "\n";
1495    }
1496  }
1497}
1498
1499typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
1500
1501static void CreateSymbolAddressMap(MachOObjectFile *O,
1502                                   SymbolAddressMap *AddrMap) {
1503  // Create a map of symbol addresses to symbol names.
1504  const StringRef FileName = O->getFileName();
1505  for (const SymbolRef &Symbol : O->symbols()) {
1506    SymbolRef::Type ST = unwrapOrError(Symbol.getType(), FileName);
1507    if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
1508        ST == SymbolRef::ST_Other) {
1509      uint64_t Address = cantFail(Symbol.getValue());
1510      StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
1511      if (!SymName.startswith(".objc"))
1512        (*AddrMap)[Address] = SymName;
1513    }
1514  }
1515}
1516
1517// GuessSymbolName is passed the address of what might be a symbol and a
1518// pointer to the SymbolAddressMap.  It returns the name of a symbol
1519// with that address or nullptr if no symbol is found with that address.
1520static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
1521  const char *SymbolName = nullptr;
1522  // A DenseMap can't lookup up some values.
1523  if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
1524    StringRef name = AddrMap->lookup(value);
1525    if (!name.empty())
1526      SymbolName = name.data();
1527  }
1528  return SymbolName;
1529}
1530
1531static void DumpCstringChar(const char c) {
1532  char p[2];
1533  p[0] = c;
1534  p[1] = '\0';
1535  outs().write_escaped(p);
1536}
1537
1538static void DumpCstringSection(MachOObjectFile *O, const char *sect,
1539                               uint32_t sect_size, uint64_t sect_addr,
1540                               bool print_addresses) {
1541  for (uint32_t i = 0; i < sect_size; i++) {
1542    if (print_addresses) {
1543      if (O->is64Bit())
1544        outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1545      else
1546        outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1547    }
1548    for (; i < sect_size && sect[i] != '\0'; i++)
1549      DumpCstringChar(sect[i]);
1550    if (i < sect_size && sect[i] == '\0')
1551      outs() << "\n";
1552  }
1553}
1554
1555static void DumpLiteral4(uint32_t l, float f) {
1556  outs() << format("0x%08" PRIx32, l);
1557  if ((l & 0x7f800000) != 0x7f800000)
1558    outs() << format(" (%.16e)\n", f);
1559  else {
1560    if (l == 0x7f800000)
1561      outs() << " (+Infinity)\n";
1562    else if (l == 0xff800000)
1563      outs() << " (-Infinity)\n";
1564    else if ((l & 0x00400000) == 0x00400000)
1565      outs() << " (non-signaling Not-a-Number)\n";
1566    else
1567      outs() << " (signaling Not-a-Number)\n";
1568  }
1569}
1570
1571static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
1572                                uint32_t sect_size, uint64_t sect_addr,
1573                                bool print_addresses) {
1574  for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
1575    if (print_addresses) {
1576      if (O->is64Bit())
1577        outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1578      else
1579        outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1580    }
1581    float f;
1582    memcpy(&f, sect + i, sizeof(float));
1583    if (O->isLittleEndian() != sys::IsLittleEndianHost)
1584      sys::swapByteOrder(f);
1585    uint32_t l;
1586    memcpy(&l, sect + i, sizeof(uint32_t));
1587    if (O->isLittleEndian() != sys::IsLittleEndianHost)
1588      sys::swapByteOrder(l);
1589    DumpLiteral4(l, f);
1590  }
1591}
1592
1593static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
1594                         double d) {
1595  outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
1596  uint32_t Hi, Lo;
1597  Hi = (O->isLittleEndian()) ? l1 : l0;
1598  Lo = (O->isLittleEndian()) ? l0 : l1;
1599
1600  // Hi is the high word, so this is equivalent to if(isfinite(d))
1601  if ((Hi & 0x7ff00000) != 0x7ff00000)
1602    outs() << format(" (%.16e)\n", d);
1603  else {
1604    if (Hi == 0x7ff00000 && Lo == 0)
1605      outs() << " (+Infinity)\n";
1606    else if (Hi == 0xfff00000 && Lo == 0)
1607      outs() << " (-Infinity)\n";
1608    else if ((Hi & 0x00080000) == 0x00080000)
1609      outs() << " (non-signaling Not-a-Number)\n";
1610    else
1611      outs() << " (signaling Not-a-Number)\n";
1612  }
1613}
1614
1615static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
1616                                uint32_t sect_size, uint64_t sect_addr,
1617                                bool print_addresses) {
1618  for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
1619    if (print_addresses) {
1620      if (O->is64Bit())
1621        outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1622      else
1623        outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1624    }
1625    double d;
1626    memcpy(&d, sect + i, sizeof(double));
1627    if (O->isLittleEndian() != sys::IsLittleEndianHost)
1628      sys::swapByteOrder(d);
1629    uint32_t l0, l1;
1630    memcpy(&l0, sect + i, sizeof(uint32_t));
1631    memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1632    if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1633      sys::swapByteOrder(l0);
1634      sys::swapByteOrder(l1);
1635    }
1636    DumpLiteral8(O, l0, l1, d);
1637  }
1638}
1639
1640static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
1641  outs() << format("0x%08" PRIx32, l0) << " ";
1642  outs() << format("0x%08" PRIx32, l1) << " ";
1643  outs() << format("0x%08" PRIx32, l2) << " ";
1644  outs() << format("0x%08" PRIx32, l3) << "\n";
1645}
1646
1647static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
1648                                 uint32_t sect_size, uint64_t sect_addr,
1649                                 bool print_addresses) {
1650  for (uint32_t i = 0; i < sect_size; i += 16) {
1651    if (print_addresses) {
1652      if (O->is64Bit())
1653        outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1654      else
1655        outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1656    }
1657    uint32_t l0, l1, l2, l3;
1658    memcpy(&l0, sect + i, sizeof(uint32_t));
1659    memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1660    memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
1661    memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
1662    if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1663      sys::swapByteOrder(l0);
1664      sys::swapByteOrder(l1);
1665      sys::swapByteOrder(l2);
1666      sys::swapByteOrder(l3);
1667    }
1668    DumpLiteral16(l0, l1, l2, l3);
1669  }
1670}
1671
1672static void DumpLiteralPointerSection(MachOObjectFile *O,
1673                                      const SectionRef &Section,
1674                                      const char *sect, uint32_t sect_size,
1675                                      uint64_t sect_addr,
1676                                      bool print_addresses) {
1677  // Collect the literal sections in this Mach-O file.
1678  std::vector<SectionRef> LiteralSections;
1679  for (const SectionRef &Section : O->sections()) {
1680    DataRefImpl Ref = Section.getRawDataRefImpl();
1681    uint32_t section_type;
1682    if (O->is64Bit()) {
1683      const MachO::section_64 Sec = O->getSection64(Ref);
1684      section_type = Sec.flags & MachO::SECTION_TYPE;
1685    } else {
1686      const MachO::section Sec = O->getSection(Ref);
1687      section_type = Sec.flags & MachO::SECTION_TYPE;
1688    }
1689    if (section_type == MachO::S_CSTRING_LITERALS ||
1690        section_type == MachO::S_4BYTE_LITERALS ||
1691        section_type == MachO::S_8BYTE_LITERALS ||
1692        section_type == MachO::S_16BYTE_LITERALS)
1693      LiteralSections.push_back(Section);
1694  }
1695
1696  // Set the size of the literal pointer.
1697  uint32_t lp_size = O->is64Bit() ? 8 : 4;
1698
1699  // Collect the external relocation symbols for the literal pointers.
1700  std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1701  for (const RelocationRef &Reloc : Section.relocations()) {
1702    DataRefImpl Rel;
1703    MachO::any_relocation_info RE;
1704    bool isExtern = false;
1705    Rel = Reloc.getRawDataRefImpl();
1706    RE = O->getRelocation(Rel);
1707    isExtern = O->getPlainRelocationExternal(RE);
1708    if (isExtern) {
1709      uint64_t RelocOffset = Reloc.getOffset();
1710      symbol_iterator RelocSym = Reloc.getSymbol();
1711      Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1712    }
1713  }
1714  array_pod_sort(Relocs.begin(), Relocs.end());
1715
1716  // Dump each literal pointer.
1717  for (uint32_t i = 0; i < sect_size; i += lp_size) {
1718    if (print_addresses) {
1719      if (O->is64Bit())
1720        outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1721      else
1722        outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1723    }
1724    uint64_t lp;
1725    if (O->is64Bit()) {
1726      memcpy(&lp, sect + i, sizeof(uint64_t));
1727      if (O->isLittleEndian() != sys::IsLittleEndianHost)
1728        sys::swapByteOrder(lp);
1729    } else {
1730      uint32_t li;
1731      memcpy(&li, sect + i, sizeof(uint32_t));
1732      if (O->isLittleEndian() != sys::IsLittleEndianHost)
1733        sys::swapByteOrder(li);
1734      lp = li;
1735    }
1736
1737    // First look for an external relocation entry for this literal pointer.
1738    auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1739      return P.first == i;
1740    });
1741    if (Reloc != Relocs.end()) {
1742      symbol_iterator RelocSym = Reloc->second;
1743      StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName());
1744      outs() << "external relocation entry for symbol:" << SymName << "\n";
1745      continue;
1746    }
1747
1748    // For local references see what the section the literal pointer points to.
1749    auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
1750      return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
1751    });
1752    if (Sect == LiteralSections.end()) {
1753      outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
1754      continue;
1755    }
1756
1757    uint64_t SectAddress = Sect->getAddress();
1758    uint64_t SectSize = Sect->getSize();
1759
1760    StringRef SectName;
1761    Expected<StringRef> SectNameOrErr = Sect->getName();
1762    if (SectNameOrErr)
1763      SectName = *SectNameOrErr;
1764    else
1765      consumeError(SectNameOrErr.takeError());
1766
1767    DataRefImpl Ref = Sect->getRawDataRefImpl();
1768    StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
1769    outs() << SegmentName << ":" << SectName << ":";
1770
1771    uint32_t section_type;
1772    if (O->is64Bit()) {
1773      const MachO::section_64 Sec = O->getSection64(Ref);
1774      section_type = Sec.flags & MachO::SECTION_TYPE;
1775    } else {
1776      const MachO::section Sec = O->getSection(Ref);
1777      section_type = Sec.flags & MachO::SECTION_TYPE;
1778    }
1779
1780    StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName());
1781
1782    const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
1783
1784    switch (section_type) {
1785    case MachO::S_CSTRING_LITERALS:
1786      for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
1787           i++) {
1788        DumpCstringChar(Contents[i]);
1789      }
1790      outs() << "\n";
1791      break;
1792    case MachO::S_4BYTE_LITERALS:
1793      float f;
1794      memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
1795      uint32_t l;
1796      memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
1797      if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1798        sys::swapByteOrder(f);
1799        sys::swapByteOrder(l);
1800      }
1801      DumpLiteral4(l, f);
1802      break;
1803    case MachO::S_8BYTE_LITERALS: {
1804      double d;
1805      memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
1806      uint32_t l0, l1;
1807      memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1808      memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1809             sizeof(uint32_t));
1810      if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1811        sys::swapByteOrder(f);
1812        sys::swapByteOrder(l0);
1813        sys::swapByteOrder(l1);
1814      }
1815      DumpLiteral8(O, l0, l1, d);
1816      break;
1817    }
1818    case MachO::S_16BYTE_LITERALS: {
1819      uint32_t l0, l1, l2, l3;
1820      memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1821      memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1822             sizeof(uint32_t));
1823      memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
1824             sizeof(uint32_t));
1825      memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
1826             sizeof(uint32_t));
1827      if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1828        sys::swapByteOrder(l0);
1829        sys::swapByteOrder(l1);
1830        sys::swapByteOrder(l2);
1831        sys::swapByteOrder(l3);
1832      }
1833      DumpLiteral16(l0, l1, l2, l3);
1834      break;
1835    }
1836    }
1837  }
1838}
1839
1840static void DumpInitTermPointerSection(MachOObjectFile *O,
1841                                       const SectionRef &Section,
1842                                       const char *sect,
1843                                       uint32_t sect_size, uint64_t sect_addr,
1844                                       SymbolAddressMap *AddrMap,
1845                                       bool verbose) {
1846  uint32_t stride;
1847  stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
1848
1849  // Collect the external relocation symbols for the pointers.
1850  std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1851  for (const RelocationRef &Reloc : Section.relocations()) {
1852    DataRefImpl Rel;
1853    MachO::any_relocation_info RE;
1854    bool isExtern = false;
1855    Rel = Reloc.getRawDataRefImpl();
1856    RE = O->getRelocation(Rel);
1857    isExtern = O->getPlainRelocationExternal(RE);
1858    if (isExtern) {
1859      uint64_t RelocOffset = Reloc.getOffset();
1860      symbol_iterator RelocSym = Reloc.getSymbol();
1861      Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1862    }
1863  }
1864  array_pod_sort(Relocs.begin(), Relocs.end());
1865
1866  for (uint32_t i = 0; i < sect_size; i += stride) {
1867    const char *SymbolName = nullptr;
1868    uint64_t p;
1869    if (O->is64Bit()) {
1870      outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
1871      uint64_t pointer_value;
1872      memcpy(&pointer_value, sect + i, stride);
1873      if (O->isLittleEndian() != sys::IsLittleEndianHost)
1874        sys::swapByteOrder(pointer_value);
1875      outs() << format("0x%016" PRIx64, pointer_value);
1876      p = pointer_value;
1877    } else {
1878      outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
1879      uint32_t pointer_value;
1880      memcpy(&pointer_value, sect + i, stride);
1881      if (O->isLittleEndian() != sys::IsLittleEndianHost)
1882        sys::swapByteOrder(pointer_value);
1883      outs() << format("0x%08" PRIx32, pointer_value);
1884      p = pointer_value;
1885    }
1886    if (verbose) {
1887      // First look for an external relocation entry for this pointer.
1888      auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1889        return P.first == i;
1890      });
1891      if (Reloc != Relocs.end()) {
1892        symbol_iterator RelocSym = Reloc->second;
1893        outs() << " " << unwrapOrError(RelocSym->getName(), O->getFileName());
1894      } else {
1895        SymbolName = GuessSymbolName(p, AddrMap);
1896        if (SymbolName)
1897          outs() << " " << SymbolName;
1898      }
1899    }
1900    outs() << "\n";
1901  }
1902}
1903
1904static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
1905                                   uint32_t size, uint64_t addr) {
1906  uint32_t cputype = O->getHeader().cputype;
1907  if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
1908    uint32_t j;
1909    for (uint32_t i = 0; i < size; i += j, addr += j) {
1910      if (O->is64Bit())
1911        outs() << format("%016" PRIx64, addr) << "\t";
1912      else
1913        outs() << format("%08" PRIx64, addr) << "\t";
1914      for (j = 0; j < 16 && i + j < size; j++) {
1915        uint8_t byte_word = *(sect + i + j);
1916        outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1917      }
1918      outs() << "\n";
1919    }
1920  } else {
1921    uint32_t j;
1922    for (uint32_t i = 0; i < size; i += j, addr += j) {
1923      if (O->is64Bit())
1924        outs() << format("%016" PRIx64, addr) << "\t";
1925      else
1926        outs() << format("%08" PRIx64, addr) << "\t";
1927      for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
1928           j += sizeof(int32_t)) {
1929        if (i + j + sizeof(int32_t) <= size) {
1930          uint32_t long_word;
1931          memcpy(&long_word, sect + i + j, sizeof(int32_t));
1932          if (O->isLittleEndian() != sys::IsLittleEndianHost)
1933            sys::swapByteOrder(long_word);
1934          outs() << format("%08" PRIx32, long_word) << " ";
1935        } else {
1936          for (uint32_t k = 0; i + j + k < size; k++) {
1937            uint8_t byte_word = *(sect + i + j + k);
1938            outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1939          }
1940        }
1941      }
1942      outs() << "\n";
1943    }
1944  }
1945}
1946
1947static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
1948                             StringRef DisSegName, StringRef DisSectName);
1949static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
1950                                uint32_t size, uint32_t addr);
1951#ifdef LLVM_HAVE_LIBXAR
1952static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
1953                                uint32_t size, bool verbose,
1954                                bool PrintXarHeader, bool PrintXarFileHeaders,
1955                                std::string XarMemberName);
1956#endif // defined(LLVM_HAVE_LIBXAR)
1957
1958static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
1959                                bool verbose) {
1960  SymbolAddressMap AddrMap;
1961  if (verbose)
1962    CreateSymbolAddressMap(O, &AddrMap);
1963
1964  for (unsigned i = 0; i < FilterSections.size(); ++i) {
1965    StringRef DumpSection = FilterSections[i];
1966    std::pair<StringRef, StringRef> DumpSegSectName;
1967    DumpSegSectName = DumpSection.split(',');
1968    StringRef DumpSegName, DumpSectName;
1969    if (!DumpSegSectName.second.empty()) {
1970      DumpSegName = DumpSegSectName.first;
1971      DumpSectName = DumpSegSectName.second;
1972    } else {
1973      DumpSegName = "";
1974      DumpSectName = DumpSegSectName.first;
1975    }
1976    for (const SectionRef &Section : O->sections()) {
1977      StringRef SectName;
1978      Expected<StringRef> SecNameOrErr = Section.getName();
1979      if (SecNameOrErr)
1980        SectName = *SecNameOrErr;
1981      else
1982        consumeError(SecNameOrErr.takeError());
1983
1984      if (!DumpSection.empty())
1985        FoundSectionSet.insert(DumpSection);
1986
1987      DataRefImpl Ref = Section.getRawDataRefImpl();
1988      StringRef SegName = O->getSectionFinalSegmentName(Ref);
1989      if ((DumpSegName.empty() || SegName == DumpSegName) &&
1990          (SectName == DumpSectName)) {
1991
1992        uint32_t section_flags;
1993        if (O->is64Bit()) {
1994          const MachO::section_64 Sec = O->getSection64(Ref);
1995          section_flags = Sec.flags;
1996
1997        } else {
1998          const MachO::section Sec = O->getSection(Ref);
1999          section_flags = Sec.flags;
2000        }
2001        uint32_t section_type = section_flags & MachO::SECTION_TYPE;
2002
2003        StringRef BytesStr =
2004            unwrapOrError(Section.getContents(), O->getFileName());
2005        const char *sect = reinterpret_cast<const char *>(BytesStr.data());
2006        uint32_t sect_size = BytesStr.size();
2007        uint64_t sect_addr = Section.getAddress();
2008
2009        if (LeadingHeaders)
2010          outs() << "Contents of (" << SegName << "," << SectName
2011                 << ") section\n";
2012
2013        if (verbose) {
2014          if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
2015              (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
2016            DisassembleMachO(Filename, O, SegName, SectName);
2017            continue;
2018          }
2019          if (SegName == "__TEXT" && SectName == "__info_plist") {
2020            outs() << sect;
2021            continue;
2022          }
2023          if (SegName == "__OBJC" && SectName == "__protocol") {
2024            DumpProtocolSection(O, sect, sect_size, sect_addr);
2025            continue;
2026          }
2027#ifdef LLVM_HAVE_LIBXAR
2028          if (SegName == "__LLVM" && SectName == "__bundle") {
2029            DumpBitcodeSection(O, sect, sect_size, verbose, SymbolicOperands,
2030                               ArchiveHeaders, "");
2031            continue;
2032          }
2033#endif // defined(LLVM_HAVE_LIBXAR)
2034          switch (section_type) {
2035          case MachO::S_REGULAR:
2036            DumpRawSectionContents(O, sect, sect_size, sect_addr);
2037            break;
2038          case MachO::S_ZEROFILL:
2039            outs() << "zerofill section and has no contents in the file\n";
2040            break;
2041          case MachO::S_CSTRING_LITERALS:
2042            DumpCstringSection(O, sect, sect_size, sect_addr, LeadingAddr);
2043            break;
2044          case MachO::S_4BYTE_LITERALS:
2045            DumpLiteral4Section(O, sect, sect_size, sect_addr, LeadingAddr);
2046            break;
2047          case MachO::S_8BYTE_LITERALS:
2048            DumpLiteral8Section(O, sect, sect_size, sect_addr, LeadingAddr);
2049            break;
2050          case MachO::S_16BYTE_LITERALS:
2051            DumpLiteral16Section(O, sect, sect_size, sect_addr, LeadingAddr);
2052            break;
2053          case MachO::S_LITERAL_POINTERS:
2054            DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
2055                                      LeadingAddr);
2056            break;
2057          case MachO::S_MOD_INIT_FUNC_POINTERS:
2058          case MachO::S_MOD_TERM_FUNC_POINTERS:
2059            DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr,
2060                                       &AddrMap, verbose);
2061            break;
2062          default:
2063            outs() << "Unknown section type ("
2064                   << format("0x%08" PRIx32, section_type) << ")\n";
2065            DumpRawSectionContents(O, sect, sect_size, sect_addr);
2066            break;
2067          }
2068        } else {
2069          if (section_type == MachO::S_ZEROFILL)
2070            outs() << "zerofill section and has no contents in the file\n";
2071          else
2072            DumpRawSectionContents(O, sect, sect_size, sect_addr);
2073        }
2074      }
2075    }
2076  }
2077}
2078
2079static void DumpInfoPlistSectionContents(StringRef Filename,
2080                                         MachOObjectFile *O) {
2081  for (const SectionRef &Section : O->sections()) {
2082    StringRef SectName;
2083    Expected<StringRef> SecNameOrErr = Section.getName();
2084    if (SecNameOrErr)
2085      SectName = *SecNameOrErr;
2086    else
2087      consumeError(SecNameOrErr.takeError());
2088
2089    DataRefImpl Ref = Section.getRawDataRefImpl();
2090    StringRef SegName = O->getSectionFinalSegmentName(Ref);
2091    if (SegName == "__TEXT" && SectName == "__info_plist") {
2092      if (LeadingHeaders)
2093        outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
2094      StringRef BytesStr =
2095          unwrapOrError(Section.getContents(), O->getFileName());
2096      const char *sect = reinterpret_cast<const char *>(BytesStr.data());
2097      outs() << format("%.*s", BytesStr.size(), sect) << "\n";
2098      return;
2099    }
2100  }
2101}
2102
2103// checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
2104// and if it is and there is a list of architecture flags is specified then
2105// check to make sure this Mach-O file is one of those architectures or all
2106// architectures were specified.  If not then an error is generated and this
2107// routine returns false.  Else it returns true.
2108static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
2109  auto *MachO = dyn_cast<MachOObjectFile>(O);
2110
2111  if (!MachO || ArchAll || ArchFlags.empty())
2112    return true;
2113
2114  MachO::mach_header H;
2115  MachO::mach_header_64 H_64;
2116  Triple T;
2117  const char *McpuDefault, *ArchFlag;
2118  if (MachO->is64Bit()) {
2119    H_64 = MachO->MachOObjectFile::getHeader64();
2120    T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
2121                                       &McpuDefault, &ArchFlag);
2122  } else {
2123    H = MachO->MachOObjectFile::getHeader();
2124    T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
2125                                       &McpuDefault, &ArchFlag);
2126  }
2127  const std::string ArchFlagName(ArchFlag);
2128  if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
2129    WithColor::error(errs(), "llvm-objdump")
2130        << Filename << ": no architecture specified.\n";
2131    return false;
2132  }
2133  return true;
2134}
2135
2136static void printObjcMetaData(MachOObjectFile *O, bool verbose);
2137
2138// ProcessMachO() is passed a single opened Mach-O file, which may be an
2139// archive member and or in a slice of a universal file.  It prints the
2140// the file name and header info and then processes it according to the
2141// command line options.
2142static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
2143                         StringRef ArchiveMemberName = StringRef(),
2144                         StringRef ArchitectureName = StringRef()) {
2145  // If we are doing some processing here on the Mach-O file print the header
2146  // info.  And don't print it otherwise like in the case of printing the
2147  // UniversalHeaders or ArchiveHeaders.
2148  if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
2149      Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
2150      DataInCode || FunctionStartsType != FunctionStartsMode::None ||
2151      LinkOptHints || ChainedFixups || DyldInfo || DylibsUsed || DylibId ||
2152      Rpaths || ObjcMetaData || (!FilterSections.empty())) {
2153    if (LeadingHeaders) {
2154      outs() << Name;
2155      if (!ArchiveMemberName.empty())
2156        outs() << '(' << ArchiveMemberName << ')';
2157      if (!ArchitectureName.empty())
2158        outs() << " (architecture " << ArchitectureName << ")";
2159      outs() << ":\n";
2160    }
2161  }
2162  // To use the report_error() form with an ArchiveName and FileName set
2163  // these up based on what is passed for Name and ArchiveMemberName.
2164  StringRef ArchiveName;
2165  StringRef FileName;
2166  if (!ArchiveMemberName.empty()) {
2167    ArchiveName = Name;
2168    FileName = ArchiveMemberName;
2169  } else {
2170    ArchiveName = StringRef();
2171    FileName = Name;
2172  }
2173
2174  // If we need the symbol table to do the operation then check it here to
2175  // produce a good error message as to where the Mach-O file comes from in
2176  // the error message.
2177  if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo)
2178    if (Error Err = MachOOF->checkSymbolTable())
2179      reportError(std::move(Err), FileName, ArchiveName, ArchitectureName);
2180
2181  if (DisassembleAll) {
2182    for (const SectionRef &Section : MachOOF->sections()) {
2183      StringRef SectName;
2184      if (Expected<StringRef> NameOrErr = Section.getName())
2185        SectName = *NameOrErr;
2186      else
2187        consumeError(NameOrErr.takeError());
2188
2189      if (SectName.equals("__text")) {
2190        DataRefImpl Ref = Section.getRawDataRefImpl();
2191        StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref);
2192        DisassembleMachO(FileName, MachOOF, SegName, SectName);
2193      }
2194    }
2195  }
2196  else if (Disassemble) {
2197    if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE &&
2198        MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64)
2199      DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text");
2200    else
2201      DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
2202  }
2203  if (IndirectSymbols)
2204    PrintIndirectSymbols(MachOOF, Verbose);
2205  if (DataInCode)
2206    PrintDataInCodeTable(MachOOF, Verbose);
2207  if (FunctionStartsType != FunctionStartsMode::None)
2208    PrintFunctionStarts(MachOOF);
2209  if (LinkOptHints)
2210    PrintLinkOptHints(MachOOF);
2211  if (Relocations)
2212    PrintRelocations(MachOOF, Verbose);
2213  if (SectionHeaders)
2214    printSectionHeaders(*MachOOF);
2215  if (SectionContents)
2216    printSectionContents(MachOOF);
2217  if (!FilterSections.empty())
2218    DumpSectionContents(FileName, MachOOF, Verbose);
2219  if (InfoPlist)
2220    DumpInfoPlistSectionContents(FileName, MachOOF);
2221  if (DyldInfo)
2222    PrintDyldInfo(MachOOF);
2223  if (ChainedFixups)
2224    PrintChainedFixups(MachOOF);
2225  if (DylibsUsed)
2226    PrintDylibs(MachOOF, false);
2227  if (DylibId)
2228    PrintDylibs(MachOOF, true);
2229  if (SymbolTable)
2230    printSymbolTable(*MachOOF, ArchiveName, ArchitectureName);
2231  if (UnwindInfo)
2232    printMachOUnwindInfo(MachOOF);
2233  if (PrivateHeaders) {
2234    printMachOFileHeader(MachOOF);
2235    printMachOLoadCommands(MachOOF);
2236  }
2237  if (FirstPrivateHeader)
2238    printMachOFileHeader(MachOOF);
2239  if (ObjcMetaData)
2240    printObjcMetaData(MachOOF, Verbose);
2241  if (ExportsTrie)
2242    printExportsTrie(MachOOF);
2243  if (Rebase)
2244    printRebaseTable(MachOOF);
2245  if (Rpaths)
2246    printRpaths(MachOOF);
2247  if (Bind)
2248    printBindTable(MachOOF);
2249  if (LazyBind)
2250    printLazyBindTable(MachOOF);
2251  if (WeakBind)
2252    printWeakBindTable(MachOOF);
2253
2254  if (DwarfDumpType != DIDT_Null) {
2255    std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF);
2256    // Dump the complete DWARF structure.
2257    DIDumpOptions DumpOpts;
2258    DumpOpts.DumpType = DwarfDumpType;
2259    DICtx->dump(outs(), DumpOpts);
2260  }
2261}
2262
2263// printUnknownCPUType() helps print_fat_headers for unknown CPU's.
2264static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
2265  outs() << "    cputype (" << cputype << ")\n";
2266  outs() << "    cpusubtype (" << cpusubtype << ")\n";
2267}
2268
2269// printCPUType() helps print_fat_headers by printing the cputype and
2270// pusubtype (symbolically for the one's it knows about).
2271static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
2272  switch (cputype) {
2273  case MachO::CPU_TYPE_I386:
2274    switch (cpusubtype) {
2275    case MachO::CPU_SUBTYPE_I386_ALL:
2276      outs() << "    cputype CPU_TYPE_I386\n";
2277      outs() << "    cpusubtype CPU_SUBTYPE_I386_ALL\n";
2278      break;
2279    default:
2280      printUnknownCPUType(cputype, cpusubtype);
2281      break;
2282    }
2283    break;
2284  case MachO::CPU_TYPE_X86_64:
2285    switch (cpusubtype) {
2286    case MachO::CPU_SUBTYPE_X86_64_ALL:
2287      outs() << "    cputype CPU_TYPE_X86_64\n";
2288      outs() << "    cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
2289      break;
2290    case MachO::CPU_SUBTYPE_X86_64_H:
2291      outs() << "    cputype CPU_TYPE_X86_64\n";
2292      outs() << "    cpusubtype CPU_SUBTYPE_X86_64_H\n";
2293      break;
2294    default:
2295      printUnknownCPUType(cputype, cpusubtype);
2296      break;
2297    }
2298    break;
2299  case MachO::CPU_TYPE_ARM:
2300    switch (cpusubtype) {
2301    case MachO::CPU_SUBTYPE_ARM_ALL:
2302      outs() << "    cputype CPU_TYPE_ARM\n";
2303      outs() << "    cpusubtype CPU_SUBTYPE_ARM_ALL\n";
2304      break;
2305    case MachO::CPU_SUBTYPE_ARM_V4T:
2306      outs() << "    cputype CPU_TYPE_ARM\n";
2307      outs() << "    cpusubtype CPU_SUBTYPE_ARM_V4T\n";
2308      break;
2309    case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2310      outs() << "    cputype CPU_TYPE_ARM\n";
2311      outs() << "    cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
2312      break;
2313    case MachO::CPU_SUBTYPE_ARM_XSCALE:
2314      outs() << "    cputype CPU_TYPE_ARM\n";
2315      outs() << "    cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
2316      break;
2317    case MachO::CPU_SUBTYPE_ARM_V6:
2318      outs() << "    cputype CPU_TYPE_ARM\n";
2319      outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6\n";
2320      break;
2321    case MachO::CPU_SUBTYPE_ARM_V6M:
2322      outs() << "    cputype CPU_TYPE_ARM\n";
2323      outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6M\n";
2324      break;
2325    case MachO::CPU_SUBTYPE_ARM_V7:
2326      outs() << "    cputype CPU_TYPE_ARM\n";
2327      outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7\n";
2328      break;
2329    case MachO::CPU_SUBTYPE_ARM_V7EM:
2330      outs() << "    cputype CPU_TYPE_ARM\n";
2331      outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
2332      break;
2333    case MachO::CPU_SUBTYPE_ARM_V7K:
2334      outs() << "    cputype CPU_TYPE_ARM\n";
2335      outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7K\n";
2336      break;
2337    case MachO::CPU_SUBTYPE_ARM_V7M:
2338      outs() << "    cputype CPU_TYPE_ARM\n";
2339      outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7M\n";
2340      break;
2341    case MachO::CPU_SUBTYPE_ARM_V7S:
2342      outs() << "    cputype CPU_TYPE_ARM\n";
2343      outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7S\n";
2344      break;
2345    default:
2346      printUnknownCPUType(cputype, cpusubtype);
2347      break;
2348    }
2349    break;
2350  case MachO::CPU_TYPE_ARM64:
2351    switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
2352    case MachO::CPU_SUBTYPE_ARM64_ALL:
2353      outs() << "    cputype CPU_TYPE_ARM64\n";
2354      outs() << "    cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
2355      break;
2356    case MachO::CPU_SUBTYPE_ARM64_V8:
2357      outs() << "    cputype CPU_TYPE_ARM64\n";
2358      outs() << "    cpusubtype CPU_SUBTYPE_ARM64_V8\n";
2359      break;
2360    case MachO::CPU_SUBTYPE_ARM64E:
2361      outs() << "    cputype CPU_TYPE_ARM64\n";
2362      outs() << "    cpusubtype CPU_SUBTYPE_ARM64E\n";
2363      break;
2364    default:
2365      printUnknownCPUType(cputype, cpusubtype);
2366      break;
2367    }
2368    break;
2369  case MachO::CPU_TYPE_ARM64_32:
2370    switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
2371    case MachO::CPU_SUBTYPE_ARM64_32_V8:
2372      outs() << "    cputype CPU_TYPE_ARM64_32\n";
2373      outs() << "    cpusubtype CPU_SUBTYPE_ARM64_32_V8\n";
2374      break;
2375    default:
2376      printUnknownCPUType(cputype, cpusubtype);
2377      break;
2378    }
2379    break;
2380  default:
2381    printUnknownCPUType(cputype, cpusubtype);
2382    break;
2383  }
2384}
2385
2386static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
2387                                       bool verbose) {
2388  outs() << "Fat headers\n";
2389  if (verbose) {
2390    if (UB->getMagic() == MachO::FAT_MAGIC)
2391      outs() << "fat_magic FAT_MAGIC\n";
2392    else // UB->getMagic() == MachO::FAT_MAGIC_64
2393      outs() << "fat_magic FAT_MAGIC_64\n";
2394  } else
2395    outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
2396
2397  uint32_t nfat_arch = UB->getNumberOfObjects();
2398  StringRef Buf = UB->getData();
2399  uint64_t size = Buf.size();
2400  uint64_t big_size = sizeof(struct MachO::fat_header) +
2401                      nfat_arch * sizeof(struct MachO::fat_arch);
2402  outs() << "nfat_arch " << UB->getNumberOfObjects();
2403  if (nfat_arch == 0)
2404    outs() << " (malformed, contains zero architecture types)\n";
2405  else if (big_size > size)
2406    outs() << " (malformed, architectures past end of file)\n";
2407  else
2408    outs() << "\n";
2409
2410  for (uint32_t i = 0; i < nfat_arch; ++i) {
2411    MachOUniversalBinary::ObjectForArch OFA(UB, i);
2412    uint32_t cputype = OFA.getCPUType();
2413    uint32_t cpusubtype = OFA.getCPUSubType();
2414    outs() << "architecture ";
2415    for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
2416      MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
2417      uint32_t other_cputype = other_OFA.getCPUType();
2418      uint32_t other_cpusubtype = other_OFA.getCPUSubType();
2419      if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
2420          (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
2421              (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
2422        outs() << "(illegal duplicate architecture) ";
2423        break;
2424      }
2425    }
2426    if (verbose) {
2427      outs() << OFA.getArchFlagName() << "\n";
2428      printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
2429    } else {
2430      outs() << i << "\n";
2431      outs() << "    cputype " << cputype << "\n";
2432      outs() << "    cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
2433             << "\n";
2434    }
2435    if (verbose &&
2436        (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
2437      outs() << "    capabilities CPU_SUBTYPE_LIB64\n";
2438    else
2439      outs() << "    capabilities "
2440             << format("0x%" PRIx32,
2441                       (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
2442    outs() << "    offset " << OFA.getOffset();
2443    if (OFA.getOffset() > size)
2444      outs() << " (past end of file)";
2445    if (OFA.getOffset() % (1ull << OFA.getAlign()) != 0)
2446      outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
2447    outs() << "\n";
2448    outs() << "    size " << OFA.getSize();
2449    big_size = OFA.getOffset() + OFA.getSize();
2450    if (big_size > size)
2451      outs() << " (past end of file)";
2452    outs() << "\n";
2453    outs() << "    align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
2454           << ")\n";
2455  }
2456}
2457
2458static void printArchiveChild(StringRef Filename, const Archive::Child &C,
2459                              size_t ChildIndex, bool verbose,
2460                              bool print_offset,
2461                              StringRef ArchitectureName = StringRef()) {
2462  if (print_offset)
2463    outs() << C.getChildOffset() << "\t";
2464  sys::fs::perms Mode =
2465      unwrapOrError(C.getAccessMode(), getFileNameForError(C, ChildIndex),
2466                    Filename, ArchitectureName);
2467  if (verbose) {
2468    // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
2469    // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
2470    outs() << "-";
2471    outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
2472    outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
2473    outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
2474    outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
2475    outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
2476    outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
2477    outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
2478    outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
2479    outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
2480  } else {
2481    outs() << format("0%o ", Mode);
2482  }
2483
2484  outs() << format("%3d/%-3d %5" PRId64 " ",
2485                   unwrapOrError(C.getUID(), getFileNameForError(C, ChildIndex),
2486                                 Filename, ArchitectureName),
2487                   unwrapOrError(C.getGID(), getFileNameForError(C, ChildIndex),
2488                                 Filename, ArchitectureName),
2489                   unwrapOrError(C.getRawSize(),
2490                                 getFileNameForError(C, ChildIndex), Filename,
2491                                 ArchitectureName));
2492
2493  StringRef RawLastModified = C.getRawLastModified();
2494  if (verbose) {
2495    unsigned Seconds;
2496    if (RawLastModified.getAsInteger(10, Seconds))
2497      outs() << "(date: \"" << RawLastModified
2498             << "\" contains non-decimal chars) ";
2499    else {
2500      // Since cime(3) returns a 26 character string of the form:
2501      // "Sun Sep 16 01:03:52 1973\n\0"
2502      // just print 24 characters.
2503      time_t t = Seconds;
2504      outs() << format("%.24s ", ctime(&t));
2505    }
2506  } else {
2507    outs() << RawLastModified << " ";
2508  }
2509
2510  if (verbose) {
2511    Expected<StringRef> NameOrErr = C.getName();
2512    if (!NameOrErr) {
2513      consumeError(NameOrErr.takeError());
2514      outs() << unwrapOrError(C.getRawName(),
2515                              getFileNameForError(C, ChildIndex), Filename,
2516                              ArchitectureName)
2517             << "\n";
2518    } else {
2519      StringRef Name = NameOrErr.get();
2520      outs() << Name << "\n";
2521    }
2522  } else {
2523    outs() << unwrapOrError(C.getRawName(), getFileNameForError(C, ChildIndex),
2524                            Filename, ArchitectureName)
2525           << "\n";
2526  }
2527}
2528
2529static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
2530                                bool print_offset,
2531                                StringRef ArchitectureName = StringRef()) {
2532  Error Err = Error::success();
2533  size_t I = 0;
2534  for (const auto &C : A->children(Err, false))
2535    printArchiveChild(Filename, C, I++, verbose, print_offset,
2536                      ArchitectureName);
2537
2538  if (Err)
2539    reportError(std::move(Err), Filename, "", ArchitectureName);
2540}
2541
2542static bool ValidateArchFlags() {
2543  // Check for -arch all and verifiy the -arch flags are valid.
2544  for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2545    if (ArchFlags[i] == "all") {
2546      ArchAll = true;
2547    } else {
2548      if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
2549        WithColor::error(errs(), "llvm-objdump")
2550            << "unknown architecture named '" + ArchFlags[i] +
2551                   "'for the -arch option\n";
2552        return false;
2553      }
2554    }
2555  }
2556  return true;
2557}
2558
2559// ParseInputMachO() parses the named Mach-O file in Filename and handles the
2560// -arch flags selecting just those slices as specified by them and also parses
2561// archive files.  Then for each individual Mach-O file ProcessMachO() is
2562// called to process the file based on the command line options.
2563void objdump::parseInputMachO(StringRef Filename) {
2564  if (!ValidateArchFlags())
2565    return;
2566
2567  // Attempt to open the binary.
2568  Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
2569  if (!BinaryOrErr) {
2570    if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError()))
2571      reportError(std::move(E), Filename);
2572    else
2573      outs() << Filename << ": is not an object file\n";
2574    return;
2575  }
2576  Binary &Bin = *BinaryOrErr.get().getBinary();
2577
2578  if (Archive *A = dyn_cast<Archive>(&Bin)) {
2579    outs() << "Archive : " << Filename << "\n";
2580    if (ArchiveHeaders)
2581      printArchiveHeaders(Filename, A, Verbose, ArchiveMemberOffsets);
2582
2583    Error Err = Error::success();
2584    unsigned I = -1;
2585    for (auto &C : A->children(Err)) {
2586      ++I;
2587      Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2588      if (!ChildOrErr) {
2589        if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2590          reportError(std::move(E), getFileNameForError(C, I), Filename);
2591        continue;
2592      }
2593      if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2594        if (!checkMachOAndArchFlags(O, Filename))
2595          return;
2596        ProcessMachO(Filename, O, O->getFileName());
2597      }
2598    }
2599    if (Err)
2600      reportError(std::move(Err), Filename);
2601    return;
2602  }
2603  if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
2604    parseInputMachO(UB);
2605    return;
2606  }
2607  if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
2608    if (!checkMachOAndArchFlags(O, Filename))
2609      return;
2610    if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O))
2611      ProcessMachO(Filename, MachOOF);
2612    else
2613      WithColor::error(errs(), "llvm-objdump")
2614          << Filename << "': "
2615          << "object is not a Mach-O file type.\n";
2616    return;
2617  }
2618  llvm_unreachable("Input object can't be invalid at this point");
2619}
2620
2621void objdump::parseInputMachO(MachOUniversalBinary *UB) {
2622  if (!ValidateArchFlags())
2623    return;
2624
2625  auto Filename = UB->getFileName();
2626
2627  if (UniversalHeaders)
2628    printMachOUniversalHeaders(UB, Verbose);
2629
2630  // If we have a list of architecture flags specified dump only those.
2631  if (!ArchAll && !ArchFlags.empty()) {
2632    // Look for a slice in the universal binary that matches each ArchFlag.
2633    bool ArchFound;
2634    for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2635      ArchFound = false;
2636      for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2637                                                  E = UB->end_objects();
2638            I != E; ++I) {
2639        if (ArchFlags[i] == I->getArchFlagName()) {
2640          ArchFound = true;
2641          Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
2642              I->getAsObjectFile();
2643          std::string ArchitectureName;
2644          if (ArchFlags.size() > 1)
2645            ArchitectureName = I->getArchFlagName();
2646          if (ObjOrErr) {
2647            ObjectFile &O = *ObjOrErr.get();
2648            if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2649              ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2650          } else if (Error E = isNotObjectErrorInvalidFileType(
2651                         ObjOrErr.takeError())) {
2652            reportError(std::move(E), "", Filename, ArchitectureName);
2653            continue;
2654          } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2655                         I->getAsArchive()) {
2656            std::unique_ptr<Archive> &A = *AOrErr;
2657            outs() << "Archive : " << Filename;
2658            if (!ArchitectureName.empty())
2659              outs() << " (architecture " << ArchitectureName << ")";
2660            outs() << "\n";
2661            if (ArchiveHeaders)
2662              printArchiveHeaders(Filename, A.get(), Verbose,
2663                                  ArchiveMemberOffsets, ArchitectureName);
2664            Error Err = Error::success();
2665            unsigned I = -1;
2666            for (auto &C : A->children(Err)) {
2667              ++I;
2668              Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2669              if (!ChildOrErr) {
2670                if (Error E =
2671                        isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2672                  reportError(std::move(E), getFileNameForError(C, I), Filename,
2673                              ArchitectureName);
2674                continue;
2675              }
2676              if (MachOObjectFile *O =
2677                      dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2678                ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
2679            }
2680            if (Err)
2681              reportError(std::move(Err), Filename);
2682          } else {
2683            consumeError(AOrErr.takeError());
2684            reportError(Filename,
2685                        "Mach-O universal file for architecture " +
2686                            StringRef(I->getArchFlagName()) +
2687                            " is not a Mach-O file or an archive file");
2688          }
2689        }
2690      }
2691      if (!ArchFound) {
2692        WithColor::error(errs(), "llvm-objdump")
2693            << "file: " + Filename + " does not contain "
2694            << "architecture: " + ArchFlags[i] + "\n";
2695        return;
2696      }
2697    }
2698    return;
2699  }
2700  // No architecture flags were specified so if this contains a slice that
2701  // matches the host architecture dump only that.
2702  if (!ArchAll) {
2703    for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2704                                                E = UB->end_objects();
2705          I != E; ++I) {
2706      if (MachOObjectFile::getHostArch().getArchName() ==
2707          I->getArchFlagName()) {
2708        Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2709        std::string ArchiveName;
2710        ArchiveName.clear();
2711        if (ObjOrErr) {
2712          ObjectFile &O = *ObjOrErr.get();
2713          if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2714            ProcessMachO(Filename, MachOOF);
2715        } else if (Error E =
2716                       isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2717          reportError(std::move(E), Filename);
2718        } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2719                       I->getAsArchive()) {
2720          std::unique_ptr<Archive> &A = *AOrErr;
2721          outs() << "Archive : " << Filename << "\n";
2722          if (ArchiveHeaders)
2723            printArchiveHeaders(Filename, A.get(), Verbose,
2724                                ArchiveMemberOffsets);
2725          Error Err = Error::success();
2726          unsigned I = -1;
2727          for (auto &C : A->children(Err)) {
2728            ++I;
2729            Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2730            if (!ChildOrErr) {
2731              if (Error E =
2732                      isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2733                reportError(std::move(E), getFileNameForError(C, I), Filename);
2734              continue;
2735            }
2736            if (MachOObjectFile *O =
2737                    dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2738              ProcessMachO(Filename, O, O->getFileName());
2739          }
2740          if (Err)
2741            reportError(std::move(Err), Filename);
2742        } else {
2743          consumeError(AOrErr.takeError());
2744          reportError(Filename, "Mach-O universal file for architecture " +
2745                                    StringRef(I->getArchFlagName()) +
2746                                    " is not a Mach-O file or an archive file");
2747        }
2748        return;
2749      }
2750    }
2751  }
2752  // Either all architectures have been specified or none have been specified
2753  // and this does not contain the host architecture so dump all the slices.
2754  bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2755  for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2756                                              E = UB->end_objects();
2757        I != E; ++I) {
2758    Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2759    std::string ArchitectureName;
2760    if (moreThanOneArch)
2761      ArchitectureName = I->getArchFlagName();
2762    if (ObjOrErr) {
2763      ObjectFile &Obj = *ObjOrErr.get();
2764      if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
2765        ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2766    } else if (Error E =
2767                   isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2768      reportError(std::move(E), Filename, "", ArchitectureName);
2769    } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
2770      std::unique_ptr<Archive> &A = *AOrErr;
2771      outs() << "Archive : " << Filename;
2772      if (!ArchitectureName.empty())
2773        outs() << " (architecture " << ArchitectureName << ")";
2774      outs() << "\n";
2775      if (ArchiveHeaders)
2776        printArchiveHeaders(Filename, A.get(), Verbose, ArchiveMemberOffsets,
2777                            ArchitectureName);
2778      Error Err = Error::success();
2779      unsigned I = -1;
2780      for (auto &C : A->children(Err)) {
2781        ++I;
2782        Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2783        if (!ChildOrErr) {
2784          if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2785            reportError(std::move(E), getFileNameForError(C, I), Filename,
2786                        ArchitectureName);
2787          continue;
2788        }
2789        if (MachOObjectFile *O =
2790                dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2791          if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
2792            ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
2793                          ArchitectureName);
2794        }
2795      }
2796      if (Err)
2797        reportError(std::move(Err), Filename);
2798    } else {
2799      consumeError(AOrErr.takeError());
2800      reportError(Filename, "Mach-O universal file for architecture " +
2801                                StringRef(I->getArchFlagName()) +
2802                                " is not a Mach-O file or an archive file");
2803    }
2804  }
2805}
2806
2807namespace {
2808// The block of info used by the Symbolizer call backs.
2809struct DisassembleInfo {
2810  DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap,
2811                  std::vector<SectionRef> *Sections, bool verbose)
2812    : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}
2813  bool verbose;
2814  MachOObjectFile *O;
2815  SectionRef S;
2816  SymbolAddressMap *AddrMap;
2817  std::vector<SectionRef> *Sections;
2818  const char *class_name = nullptr;
2819  const char *selector_name = nullptr;
2820  std::unique_ptr<char[]> method = nullptr;
2821  char *demangled_name = nullptr;
2822  uint64_t adrp_addr = 0;
2823  uint32_t adrp_inst = 0;
2824  std::unique_ptr<SymbolAddressMap> bindtable;
2825  uint32_t depth = 0;
2826};
2827} // namespace
2828
2829// SymbolizerGetOpInfo() is the operand information call back function.
2830// This is called to get the symbolic information for operand(s) of an
2831// instruction when it is being done.  This routine does this from
2832// the relocation information, symbol table, etc. That block of information
2833// is a pointer to the struct DisassembleInfo that was passed when the
2834// disassembler context was created and passed to back to here when
2835// called back by the disassembler for instruction operands that could have
2836// relocation information. The address of the instruction containing operand is
2837// at the Pc parameter.  The immediate value the operand has is passed in
2838// op_info->Value and is at Offset past the start of the instruction and has a
2839// byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
2840// LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
2841// names and addends of the symbolic expression to add for the operand.  The
2842// value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
2843// information is returned then this function returns 1 else it returns 0.
2844static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
2845                               uint64_t OpSize, uint64_t InstSize, int TagType,
2846                               void *TagBuf) {
2847  struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
2848  struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
2849  uint64_t value = op_info->Value;
2850
2851  // Make sure all fields returned are zero if we don't set them.
2852  memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
2853  op_info->Value = value;
2854
2855  // If the TagType is not the value 1 which it code knows about or if no
2856  // verbose symbolic information is wanted then just return 0, indicating no
2857  // information is being returned.
2858  if (TagType != 1 || !info->verbose)
2859    return 0;
2860
2861  unsigned int Arch = info->O->getArch();
2862  if (Arch == Triple::x86) {
2863    if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0)
2864      return 0;
2865    if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2866      // TODO:
2867      // Search the external relocation entries of a fully linked image
2868      // (if any) for an entry that matches this segment offset.
2869      // uint32_t seg_offset = (Pc + Offset);
2870      return 0;
2871    }
2872    // In MH_OBJECT filetypes search the section's relocation entries (if any)
2873    // for an entry for this section offset.
2874    uint32_t sect_addr = info->S.getAddress();
2875    uint32_t sect_offset = (Pc + Offset) - sect_addr;
2876    bool reloc_found = false;
2877    DataRefImpl Rel;
2878    MachO::any_relocation_info RE;
2879    bool isExtern = false;
2880    SymbolRef Symbol;
2881    bool r_scattered = false;
2882    uint32_t r_value, pair_r_value, r_type;
2883    for (const RelocationRef &Reloc : info->S.relocations()) {
2884      uint64_t RelocOffset = Reloc.getOffset();
2885      if (RelocOffset == sect_offset) {
2886        Rel = Reloc.getRawDataRefImpl();
2887        RE = info->O->getRelocation(Rel);
2888        r_type = info->O->getAnyRelocationType(RE);
2889        r_scattered = info->O->isRelocationScattered(RE);
2890        if (r_scattered) {
2891          r_value = info->O->getScatteredRelocationValue(RE);
2892          if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2893              r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
2894            DataRefImpl RelNext = Rel;
2895            info->O->moveRelocationNext(RelNext);
2896            MachO::any_relocation_info RENext;
2897            RENext = info->O->getRelocation(RelNext);
2898            if (info->O->isRelocationScattered(RENext))
2899              pair_r_value = info->O->getScatteredRelocationValue(RENext);
2900            else
2901              return 0;
2902          }
2903        } else {
2904          isExtern = info->O->getPlainRelocationExternal(RE);
2905          if (isExtern) {
2906            symbol_iterator RelocSym = Reloc.getSymbol();
2907            Symbol = *RelocSym;
2908          }
2909        }
2910        reloc_found = true;
2911        break;
2912      }
2913    }
2914    if (reloc_found && isExtern) {
2915      op_info->AddSymbol.Present = 1;
2916      op_info->AddSymbol.Name =
2917          unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2918      // For i386 extern relocation entries the value in the instruction is
2919      // the offset from the symbol, and value is already set in op_info->Value.
2920      return 1;
2921    }
2922    if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2923                        r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
2924      const char *add = GuessSymbolName(r_value, info->AddrMap);
2925      const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2926      uint32_t offset = value - (r_value - pair_r_value);
2927      op_info->AddSymbol.Present = 1;
2928      if (add != nullptr)
2929        op_info->AddSymbol.Name = add;
2930      else
2931        op_info->AddSymbol.Value = r_value;
2932      op_info->SubtractSymbol.Present = 1;
2933      if (sub != nullptr)
2934        op_info->SubtractSymbol.Name = sub;
2935      else
2936        op_info->SubtractSymbol.Value = pair_r_value;
2937      op_info->Value = offset;
2938      return 1;
2939    }
2940    return 0;
2941  }
2942  if (Arch == Triple::x86_64) {
2943    if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0)
2944      return 0;
2945    // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external
2946    // relocation entries of a linked image (if any) for an entry that matches
2947    // this segment offset.
2948    if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2949      uint64_t seg_offset = Pc + Offset;
2950      bool reloc_found = false;
2951      DataRefImpl Rel;
2952      MachO::any_relocation_info RE;
2953      bool isExtern = false;
2954      SymbolRef Symbol;
2955      for (const RelocationRef &Reloc : info->O->external_relocations()) {
2956        uint64_t RelocOffset = Reloc.getOffset();
2957        if (RelocOffset == seg_offset) {
2958          Rel = Reloc.getRawDataRefImpl();
2959          RE = info->O->getRelocation(Rel);
2960          // external relocation entries should always be external.
2961          isExtern = info->O->getPlainRelocationExternal(RE);
2962          if (isExtern) {
2963            symbol_iterator RelocSym = Reloc.getSymbol();
2964            Symbol = *RelocSym;
2965          }
2966          reloc_found = true;
2967          break;
2968        }
2969      }
2970      if (reloc_found && isExtern) {
2971        // The Value passed in will be adjusted by the Pc if the instruction
2972        // adds the Pc.  But for x86_64 external relocation entries the Value
2973        // is the offset from the external symbol.
2974        if (info->O->getAnyRelocationPCRel(RE))
2975          op_info->Value -= Pc + InstSize;
2976        const char *name =
2977            unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2978        op_info->AddSymbol.Present = 1;
2979        op_info->AddSymbol.Name = name;
2980        return 1;
2981      }
2982      return 0;
2983    }
2984    // In MH_OBJECT filetypes search the section's relocation entries (if any)
2985    // for an entry for this section offset.
2986    uint64_t sect_addr = info->S.getAddress();
2987    uint64_t sect_offset = (Pc + Offset) - sect_addr;
2988    bool reloc_found = false;
2989    DataRefImpl Rel;
2990    MachO::any_relocation_info RE;
2991    bool isExtern = false;
2992    SymbolRef Symbol;
2993    for (const RelocationRef &Reloc : info->S.relocations()) {
2994      uint64_t RelocOffset = Reloc.getOffset();
2995      if (RelocOffset == sect_offset) {
2996        Rel = Reloc.getRawDataRefImpl();
2997        RE = info->O->getRelocation(Rel);
2998        // NOTE: Scattered relocations don't exist on x86_64.
2999        isExtern = info->O->getPlainRelocationExternal(RE);
3000        if (isExtern) {
3001          symbol_iterator RelocSym = Reloc.getSymbol();
3002          Symbol = *RelocSym;
3003        }
3004        reloc_found = true;
3005        break;
3006      }
3007    }
3008    if (reloc_found && isExtern) {
3009      // The Value passed in will be adjusted by the Pc if the instruction
3010      // adds the Pc.  But for x86_64 external relocation entries the Value
3011      // is the offset from the external symbol.
3012      if (info->O->getAnyRelocationPCRel(RE))
3013        op_info->Value -= Pc + InstSize;
3014      const char *name =
3015          unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
3016      unsigned Type = info->O->getAnyRelocationType(RE);
3017      if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
3018        DataRefImpl RelNext = Rel;
3019        info->O->moveRelocationNext(RelNext);
3020        MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
3021        unsigned TypeNext = info->O->getAnyRelocationType(RENext);
3022        bool isExternNext = info->O->getPlainRelocationExternal(RENext);
3023        unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
3024        if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
3025          op_info->SubtractSymbol.Present = 1;
3026          op_info->SubtractSymbol.Name = name;
3027          symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
3028          Symbol = *RelocSymNext;
3029          name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
3030        }
3031      }
3032      // TODO: add the VariantKinds to op_info->VariantKind for relocation types
3033      // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
3034      op_info->AddSymbol.Present = 1;
3035      op_info->AddSymbol.Name = name;
3036      return 1;
3037    }
3038    return 0;
3039  }
3040  if (Arch == Triple::arm) {
3041    if (Offset != 0 || (InstSize != 4 && InstSize != 2))
3042      return 0;
3043    if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
3044      // TODO:
3045      // Search the external relocation entries of a fully linked image
3046      // (if any) for an entry that matches this segment offset.
3047      // uint32_t seg_offset = (Pc + Offset);
3048      return 0;
3049    }
3050    // In MH_OBJECT filetypes search the section's relocation entries (if any)
3051    // for an entry for this section offset.
3052    uint32_t sect_addr = info->S.getAddress();
3053    uint32_t sect_offset = (Pc + Offset) - sect_addr;
3054    DataRefImpl Rel;
3055    MachO::any_relocation_info RE;
3056    bool isExtern = false;
3057    SymbolRef Symbol;
3058    bool r_scattered = false;
3059    uint32_t r_value, pair_r_value, r_type, r_length, other_half;
3060    auto Reloc =
3061        find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
3062          uint64_t RelocOffset = Reloc.getOffset();
3063          return RelocOffset == sect_offset;
3064        });
3065
3066    if (Reloc == info->S.relocations().end())
3067      return 0;
3068
3069    Rel = Reloc->getRawDataRefImpl();
3070    RE = info->O->getRelocation(Rel);
3071    r_length = info->O->getAnyRelocationLength(RE);
3072    r_scattered = info->O->isRelocationScattered(RE);
3073    if (r_scattered) {
3074      r_value = info->O->getScatteredRelocationValue(RE);
3075      r_type = info->O->getScatteredRelocationType(RE);
3076    } else {
3077      r_type = info->O->getAnyRelocationType(RE);
3078      isExtern = info->O->getPlainRelocationExternal(RE);
3079      if (isExtern) {
3080        symbol_iterator RelocSym = Reloc->getSymbol();
3081        Symbol = *RelocSym;
3082      }
3083    }
3084    if (r_type == MachO::ARM_RELOC_HALF ||
3085        r_type == MachO::ARM_RELOC_SECTDIFF ||
3086        r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
3087        r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3088      DataRefImpl RelNext = Rel;
3089      info->O->moveRelocationNext(RelNext);
3090      MachO::any_relocation_info RENext;
3091      RENext = info->O->getRelocation(RelNext);
3092      other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
3093      if (info->O->isRelocationScattered(RENext))
3094        pair_r_value = info->O->getScatteredRelocationValue(RENext);
3095    }
3096
3097    if (isExtern) {
3098      const char *name =
3099          unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
3100      op_info->AddSymbol.Present = 1;
3101      op_info->AddSymbol.Name = name;
3102      switch (r_type) {
3103      case MachO::ARM_RELOC_HALF:
3104        if ((r_length & 0x1) == 1) {
3105          op_info->Value = value << 16 | other_half;
3106          op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3107        } else {
3108          op_info->Value = other_half << 16 | value;
3109          op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3110        }
3111        break;
3112      default:
3113        break;
3114      }
3115      return 1;
3116    }
3117    // If we have a branch that is not an external relocation entry then
3118    // return 0 so the code in tryAddingSymbolicOperand() can use the
3119    // SymbolLookUp call back with the branch target address to look up the
3120    // symbol and possibility add an annotation for a symbol stub.
3121    if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
3122                          r_type == MachO::ARM_THUMB_RELOC_BR22))
3123      return 0;
3124
3125    uint32_t offset = 0;
3126    if (r_type == MachO::ARM_RELOC_HALF ||
3127        r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3128      if ((r_length & 0x1) == 1)
3129        value = value << 16 | other_half;
3130      else
3131        value = other_half << 16 | value;
3132    }
3133    if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
3134                        r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
3135      offset = value - r_value;
3136      value = r_value;
3137    }
3138
3139    if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3140      if ((r_length & 0x1) == 1)
3141        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3142      else
3143        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3144      const char *add = GuessSymbolName(r_value, info->AddrMap);
3145      const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
3146      int32_t offset = value - (r_value - pair_r_value);
3147      op_info->AddSymbol.Present = 1;
3148      if (add != nullptr)
3149        op_info->AddSymbol.Name = add;
3150      else
3151        op_info->AddSymbol.Value = r_value;
3152      op_info->SubtractSymbol.Present = 1;
3153      if (sub != nullptr)
3154        op_info->SubtractSymbol.Name = sub;
3155      else
3156        op_info->SubtractSymbol.Value = pair_r_value;
3157      op_info->Value = offset;
3158      return 1;
3159    }
3160
3161    op_info->AddSymbol.Present = 1;
3162    op_info->Value = offset;
3163    if (r_type == MachO::ARM_RELOC_HALF) {
3164      if ((r_length & 0x1) == 1)
3165        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3166      else
3167        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3168    }
3169    const char *add = GuessSymbolName(value, info->AddrMap);
3170    if (add != nullptr) {
3171      op_info->AddSymbol.Name = add;
3172      return 1;
3173    }
3174    op_info->AddSymbol.Value = value;
3175    return 1;
3176  }
3177  if (Arch == Triple::aarch64) {
3178    if (Offset != 0 || InstSize != 4)
3179      return 0;
3180    if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
3181      // TODO:
3182      // Search the external relocation entries of a fully linked image
3183      // (if any) for an entry that matches this segment offset.
3184      // uint64_t seg_offset = (Pc + Offset);
3185      return 0;
3186    }
3187    // In MH_OBJECT filetypes search the section's relocation entries (if any)
3188    // for an entry for this section offset.
3189    uint64_t sect_addr = info->S.getAddress();
3190    uint64_t sect_offset = (Pc + Offset) - sect_addr;
3191    auto Reloc =
3192        find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
3193          uint64_t RelocOffset = Reloc.getOffset();
3194          return RelocOffset == sect_offset;
3195        });
3196
3197    if (Reloc == info->S.relocations().end())
3198      return 0;
3199
3200    DataRefImpl Rel = Reloc->getRawDataRefImpl();
3201    MachO::any_relocation_info RE = info->O->getRelocation(Rel);
3202    uint32_t r_type = info->O->getAnyRelocationType(RE);
3203    if (r_type == MachO::ARM64_RELOC_ADDEND) {
3204      DataRefImpl RelNext = Rel;
3205      info->O->moveRelocationNext(RelNext);
3206      MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
3207      if (value == 0) {
3208        value = info->O->getPlainRelocationSymbolNum(RENext);
3209        op_info->Value = value;
3210      }
3211    }
3212    // NOTE: Scattered relocations don't exist on arm64.
3213    if (!info->O->getPlainRelocationExternal(RE))
3214      return 0;
3215    const char *name =
3216        unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName())
3217            .data();
3218    op_info->AddSymbol.Present = 1;
3219    op_info->AddSymbol.Name = name;
3220
3221    switch (r_type) {
3222    case MachO::ARM64_RELOC_PAGE21:
3223      /* @page */
3224      op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
3225      break;
3226    case MachO::ARM64_RELOC_PAGEOFF12:
3227      /* @pageoff */
3228      op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
3229      break;
3230    case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
3231      /* @gotpage */
3232      op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
3233      break;
3234    case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
3235      /* @gotpageoff */
3236      op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
3237      break;
3238    case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
3239      /* @tvlppage is not implemented in llvm-mc */
3240      op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
3241      break;
3242    case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
3243      /* @tvlppageoff is not implemented in llvm-mc */
3244      op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
3245      break;
3246    default:
3247    case MachO::ARM64_RELOC_BRANCH26:
3248      op_info->VariantKind = LLVMDisassembler_VariantKind_None;
3249      break;
3250    }
3251    return 1;
3252  }
3253  return 0;
3254}
3255
3256// GuessCstringPointer is passed the address of what might be a pointer to a
3257// literal string in a cstring section.  If that address is in a cstring section
3258// it returns a pointer to that string.  Else it returns nullptr.
3259static const char *GuessCstringPointer(uint64_t ReferenceValue,
3260                                       struct DisassembleInfo *info) {
3261  for (const auto &Load : info->O->load_commands()) {
3262    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3263      MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3264      for (unsigned J = 0; J < Seg.nsects; ++J) {
3265        MachO::section_64 Sec = info->O->getSection64(Load, J);
3266        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3267        if (section_type == MachO::S_CSTRING_LITERALS &&
3268            ReferenceValue >= Sec.addr &&
3269            ReferenceValue < Sec.addr + Sec.size) {
3270          uint64_t sect_offset = ReferenceValue - Sec.addr;
3271          uint64_t object_offset = Sec.offset + sect_offset;
3272          StringRef MachOContents = info->O->getData();
3273          uint64_t object_size = MachOContents.size();
3274          const char *object_addr = (const char *)MachOContents.data();
3275          if (object_offset < object_size) {
3276            const char *name = object_addr + object_offset;
3277            return name;
3278          } else {
3279            return nullptr;
3280          }
3281        }
3282      }
3283    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
3284      MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
3285      for (unsigned J = 0; J < Seg.nsects; ++J) {
3286        MachO::section Sec = info->O->getSection(Load, J);
3287        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3288        if (section_type == MachO::S_CSTRING_LITERALS &&
3289            ReferenceValue >= Sec.addr &&
3290            ReferenceValue < Sec.addr + Sec.size) {
3291          uint64_t sect_offset = ReferenceValue - Sec.addr;
3292          uint64_t object_offset = Sec.offset + sect_offset;
3293          StringRef MachOContents = info->O->getData();
3294          uint64_t object_size = MachOContents.size();
3295          const char *object_addr = (const char *)MachOContents.data();
3296          if (object_offset < object_size) {
3297            const char *name = object_addr + object_offset;
3298            return name;
3299          } else {
3300            return nullptr;
3301          }
3302        }
3303      }
3304    }
3305  }
3306  return nullptr;
3307}
3308
3309// GuessIndirectSymbol returns the name of the indirect symbol for the
3310// ReferenceValue passed in or nullptr.  This is used when ReferenceValue maybe
3311// an address of a symbol stub or a lazy or non-lazy pointer to associate the
3312// symbol name being referenced by the stub or pointer.
3313static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
3314                                       struct DisassembleInfo *info) {
3315  MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
3316  MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
3317  for (const auto &Load : info->O->load_commands()) {
3318    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3319      MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3320      for (unsigned J = 0; J < Seg.nsects; ++J) {
3321        MachO::section_64 Sec = info->O->getSection64(Load, J);
3322        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3323        if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
3324             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
3325             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
3326             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
3327             section_type == MachO::S_SYMBOL_STUBS) &&
3328            ReferenceValue >= Sec.addr &&
3329            ReferenceValue < Sec.addr + Sec.size) {
3330          uint32_t stride;
3331          if (section_type == MachO::S_SYMBOL_STUBS)
3332            stride = Sec.reserved2;
3333          else
3334            stride = 8;
3335          if (stride == 0)
3336            return nullptr;
3337          uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
3338          if (index < Dysymtab.nindirectsyms) {
3339            uint32_t indirect_symbol =
3340                info->O->getIndirectSymbolTableEntry(Dysymtab, index);
3341            if (indirect_symbol < Symtab.nsyms) {
3342              symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
3343              return unwrapOrError(Sym->getName(), info->O->getFileName())
3344                  .data();
3345            }
3346          }
3347        }
3348      }
3349    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
3350      MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
3351      for (unsigned J = 0; J < Seg.nsects; ++J) {
3352        MachO::section Sec = info->O->getSection(Load, J);
3353        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3354        if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
3355             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
3356             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
3357             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
3358             section_type == MachO::S_SYMBOL_STUBS) &&
3359            ReferenceValue >= Sec.addr &&
3360            ReferenceValue < Sec.addr + Sec.size) {
3361          uint32_t stride;
3362          if (section_type == MachO::S_SYMBOL_STUBS)
3363            stride = Sec.reserved2;
3364          else
3365            stride = 4;
3366          if (stride == 0)
3367            return nullptr;
3368          uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
3369          if (index < Dysymtab.nindirectsyms) {
3370            uint32_t indirect_symbol =
3371                info->O->getIndirectSymbolTableEntry(Dysymtab, index);
3372            if (indirect_symbol < Symtab.nsyms) {
3373              symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
3374              return unwrapOrError(Sym->getName(), info->O->getFileName())
3375                  .data();
3376            }
3377          }
3378        }
3379      }
3380    }
3381  }
3382  return nullptr;
3383}
3384
3385// method_reference() is called passing it the ReferenceName that might be
3386// a reference it to an Objective-C method call.  If so then it allocates and
3387// assembles a method call string with the values last seen and saved in
3388// the DisassembleInfo's class_name and selector_name fields.  This is saved
3389// into the method field of the info and any previous string is free'ed.
3390// Then the class_name field in the info is set to nullptr.  The method call
3391// string is set into ReferenceName and ReferenceType is set to
3392// LLVMDisassembler_ReferenceType_Out_Objc_Message.  If this not a method call
3393// then both ReferenceType and ReferenceName are left unchanged.
3394static void method_reference(struct DisassembleInfo *info,
3395                             uint64_t *ReferenceType,
3396                             const char **ReferenceName) {
3397  unsigned int Arch = info->O->getArch();
3398  if (*ReferenceName != nullptr) {
3399    if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
3400      if (info->selector_name != nullptr) {
3401        if (info->class_name != nullptr) {
3402          info->method = std::make_unique<char[]>(
3403              5 + strlen(info->class_name) + strlen(info->selector_name));
3404          char *method = info->method.get();
3405          if (method != nullptr) {
3406            strcpy(method, "+[");
3407            strcat(method, info->class_name);
3408            strcat(method, " ");
3409            strcat(method, info->selector_name);
3410            strcat(method, "]");
3411            *ReferenceName = method;
3412            *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3413          }
3414        } else {
3415          info->method =
3416              std::make_unique<char[]>(9 + strlen(info->selector_name));
3417          char *method = info->method.get();
3418          if (method != nullptr) {
3419            if (Arch == Triple::x86_64)
3420              strcpy(method, "-[%rdi ");
3421            else if (Arch == Triple::aarch64)
3422              strcpy(method, "-[x0 ");
3423            else
3424              strcpy(method, "-[r? ");
3425            strcat(method, info->selector_name);
3426            strcat(method, "]");
3427            *ReferenceName = method;
3428            *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3429          }
3430        }
3431        info->class_name = nullptr;
3432      }
3433    } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
3434      if (info->selector_name != nullptr) {
3435        info->method =
3436            std::make_unique<char[]>(17 + strlen(info->selector_name));
3437        char *method = info->method.get();
3438        if (method != nullptr) {
3439          if (Arch == Triple::x86_64)
3440            strcpy(method, "-[[%rdi super] ");
3441          else if (Arch == Triple::aarch64)
3442            strcpy(method, "-[[x0 super] ");
3443          else
3444            strcpy(method, "-[[r? super] ");
3445          strcat(method, info->selector_name);
3446          strcat(method, "]");
3447          *ReferenceName = method;
3448          *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3449        }
3450        info->class_name = nullptr;
3451      }
3452    }
3453  }
3454}
3455
3456// GuessPointerPointer() is passed the address of what might be a pointer to
3457// a reference to an Objective-C class, selector, message ref or cfstring.
3458// If so the value of the pointer is returned and one of the booleans are set
3459// to true.  If not zero is returned and all the booleans are set to false.
3460static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
3461                                    struct DisassembleInfo *info,
3462                                    bool &classref, bool &selref, bool &msgref,
3463                                    bool &cfstring) {
3464  classref = false;
3465  selref = false;
3466  msgref = false;
3467  cfstring = false;
3468  for (const auto &Load : info->O->load_commands()) {
3469    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3470      MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3471      for (unsigned J = 0; J < Seg.nsects; ++J) {
3472        MachO::section_64 Sec = info->O->getSection64(Load, J);
3473        if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
3474             strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
3475             strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
3476             strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
3477             strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
3478            ReferenceValue >= Sec.addr &&
3479            ReferenceValue < Sec.addr + Sec.size) {
3480          uint64_t sect_offset = ReferenceValue - Sec.addr;
3481          uint64_t object_offset = Sec.offset + sect_offset;
3482          StringRef MachOContents = info->O->getData();
3483          uint64_t object_size = MachOContents.size();
3484          const char *object_addr = (const char *)MachOContents.data();
3485          if (object_offset < object_size) {
3486            uint64_t pointer_value;
3487            memcpy(&pointer_value, object_addr + object_offset,
3488                   sizeof(uint64_t));
3489            if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3490              sys::swapByteOrder(pointer_value);
3491            if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
3492              selref = true;
3493            else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
3494                     strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
3495              classref = true;
3496            else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
3497                     ReferenceValue + 8 < Sec.addr + Sec.size) {
3498              msgref = true;
3499              memcpy(&pointer_value, object_addr + object_offset + 8,
3500                     sizeof(uint64_t));
3501              if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3502                sys::swapByteOrder(pointer_value);
3503            } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
3504              cfstring = true;
3505            return pointer_value;
3506          } else {
3507            return 0;
3508          }
3509        }
3510      }
3511    }
3512    // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
3513  }
3514  return 0;
3515}
3516
3517// get_pointer_64 returns a pointer to the bytes in the object file at the
3518// Address from a section in the Mach-O file.  And indirectly returns the
3519// offset into the section, number of bytes left in the section past the offset
3520// and which section is was being referenced.  If the Address is not in a
3521// section nullptr is returned.
3522static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
3523                                  uint32_t &left, SectionRef &S,
3524                                  DisassembleInfo *info,
3525                                  bool objc_only = false) {
3526  offset = 0;
3527  left = 0;
3528  S = SectionRef();
3529  for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
3530    uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
3531    uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
3532    if (SectSize == 0)
3533      continue;
3534    if (objc_only) {
3535      StringRef SectName;
3536      Expected<StringRef> SecNameOrErr =
3537          ((*(info->Sections))[SectIdx]).getName();
3538      if (SecNameOrErr)
3539        SectName = *SecNameOrErr;
3540      else
3541        consumeError(SecNameOrErr.takeError());
3542
3543      DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
3544      StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
3545      if (SegName != "__OBJC" && SectName != "__cstring")
3546        continue;
3547    }
3548    if (Address >= SectAddress && Address < SectAddress + SectSize) {
3549      S = (*(info->Sections))[SectIdx];
3550      offset = Address - SectAddress;
3551      left = SectSize - offset;
3552      StringRef SectContents = unwrapOrError(
3553          ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName());
3554      return SectContents.data() + offset;
3555    }
3556  }
3557  return nullptr;
3558}
3559
3560static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
3561                                  uint32_t &left, SectionRef &S,
3562                                  DisassembleInfo *info,
3563                                  bool objc_only = false) {
3564  return get_pointer_64(Address, offset, left, S, info, objc_only);
3565}
3566
3567// get_symbol_64() returns the name of a symbol (or nullptr) and the address of
3568// the symbol indirectly through n_value. Based on the relocation information
3569// for the specified section offset in the specified section reference.
3570// If no relocation information is found and a non-zero ReferenceValue for the
3571// symbol is passed, look up that address in the info's AddrMap.
3572static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
3573                                 DisassembleInfo *info, uint64_t &n_value,
3574                                 uint64_t ReferenceValue = 0) {
3575  n_value = 0;
3576  if (!info->verbose)
3577    return nullptr;
3578
3579  // See if there is an external relocation entry at the sect_offset.
3580  bool reloc_found = false;
3581  DataRefImpl Rel;
3582  MachO::any_relocation_info RE;
3583  bool isExtern = false;
3584  SymbolRef Symbol;
3585  for (const RelocationRef &Reloc : S.relocations()) {
3586    uint64_t RelocOffset = Reloc.getOffset();
3587    if (RelocOffset == sect_offset) {
3588      Rel = Reloc.getRawDataRefImpl();
3589      RE = info->O->getRelocation(Rel);
3590      if (info->O->isRelocationScattered(RE))
3591        continue;
3592      isExtern = info->O->getPlainRelocationExternal(RE);
3593      if (isExtern) {
3594        symbol_iterator RelocSym = Reloc.getSymbol();
3595        Symbol = *RelocSym;
3596      }
3597      reloc_found = true;
3598      break;
3599    }
3600  }
3601  // If there is an external relocation entry for a symbol in this section
3602  // at this section_offset then use that symbol's value for the n_value
3603  // and return its name.
3604  const char *SymbolName = nullptr;
3605  if (reloc_found && isExtern) {
3606    n_value = cantFail(Symbol.getValue());
3607    StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName());
3608    if (!Name.empty()) {
3609      SymbolName = Name.data();
3610      return SymbolName;
3611    }
3612  }
3613
3614  // TODO: For fully linked images, look through the external relocation
3615  // entries off the dynamic symtab command. For these the r_offset is from the
3616  // start of the first writeable segment in the Mach-O file.  So the offset
3617  // to this section from that segment is passed to this routine by the caller,
3618  // as the database_offset. Which is the difference of the section's starting
3619  // address and the first writable segment.
3620  //
3621  // NOTE: need add passing the database_offset to this routine.
3622
3623  // We did not find an external relocation entry so look up the ReferenceValue
3624  // as an address of a symbol and if found return that symbol's name.
3625  SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
3626
3627  return SymbolName;
3628}
3629
3630static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
3631                                 DisassembleInfo *info,
3632                                 uint32_t ReferenceValue) {
3633  uint64_t n_value64;
3634  return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
3635}
3636
3637namespace {
3638
3639// These are structs in the Objective-C meta data and read to produce the
3640// comments for disassembly.  While these are part of the ABI they are no
3641// public defintions.  So the are here not in include/llvm/BinaryFormat/MachO.h
3642// .
3643
3644// The cfstring object in a 64-bit Mach-O file.
3645struct cfstring64_t {
3646  uint64_t isa;        // class64_t * (64-bit pointer)
3647  uint64_t flags;      // flag bits
3648  uint64_t characters; // char * (64-bit pointer)
3649  uint64_t length;     // number of non-NULL characters in above
3650};
3651
3652// The class object in a 64-bit Mach-O file.
3653struct class64_t {
3654  uint64_t isa;        // class64_t * (64-bit pointer)
3655  uint64_t superclass; // class64_t * (64-bit pointer)
3656  uint64_t cache;      // Cache (64-bit pointer)
3657  uint64_t vtable;     // IMP * (64-bit pointer)
3658  uint64_t data;       // class_ro64_t * (64-bit pointer)
3659};
3660
3661struct class32_t {
3662  uint32_t isa;        /* class32_t * (32-bit pointer) */
3663  uint32_t superclass; /* class32_t * (32-bit pointer) */
3664  uint32_t cache;      /* Cache (32-bit pointer) */
3665  uint32_t vtable;     /* IMP * (32-bit pointer) */
3666  uint32_t data;       /* class_ro32_t * (32-bit pointer) */
3667};
3668
3669struct class_ro64_t {
3670  uint32_t flags;
3671  uint32_t instanceStart;
3672  uint32_t instanceSize;
3673  uint32_t reserved;
3674  uint64_t ivarLayout;     // const uint8_t * (64-bit pointer)
3675  uint64_t name;           // const char * (64-bit pointer)
3676  uint64_t baseMethods;    // const method_list_t * (64-bit pointer)
3677  uint64_t baseProtocols;  // const protocol_list_t * (64-bit pointer)
3678  uint64_t ivars;          // const ivar_list_t * (64-bit pointer)
3679  uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
3680  uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
3681};
3682
3683struct class_ro32_t {
3684  uint32_t flags;
3685  uint32_t instanceStart;
3686  uint32_t instanceSize;
3687  uint32_t ivarLayout;     /* const uint8_t * (32-bit pointer) */
3688  uint32_t name;           /* const char * (32-bit pointer) */
3689  uint32_t baseMethods;    /* const method_list_t * (32-bit pointer) */
3690  uint32_t baseProtocols;  /* const protocol_list_t * (32-bit pointer) */
3691  uint32_t ivars;          /* const ivar_list_t * (32-bit pointer) */
3692  uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
3693  uint32_t baseProperties; /* const struct objc_property_list *
3694                                                   (32-bit pointer) */
3695};
3696
3697/* Values for class_ro{64,32}_t->flags */
3698#define RO_META (1 << 0)
3699#define RO_ROOT (1 << 1)
3700#define RO_HAS_CXX_STRUCTORS (1 << 2)
3701
3702struct method_list64_t {
3703  uint32_t entsize;
3704  uint32_t count;
3705  /* struct method64_t first;  These structures follow inline */
3706};
3707
3708struct method_list32_t {
3709  uint32_t entsize;
3710  uint32_t count;
3711  /* struct method32_t first;  These structures follow inline */
3712};
3713
3714struct method64_t {
3715  uint64_t name;  /* SEL (64-bit pointer) */
3716  uint64_t types; /* const char * (64-bit pointer) */
3717  uint64_t imp;   /* IMP (64-bit pointer) */
3718};
3719
3720struct method32_t {
3721  uint32_t name;  /* SEL (32-bit pointer) */
3722  uint32_t types; /* const char * (32-bit pointer) */
3723  uint32_t imp;   /* IMP (32-bit pointer) */
3724};
3725
3726struct protocol_list64_t {
3727  uint64_t count; /* uintptr_t (a 64-bit value) */
3728  /* struct protocol64_t * list[0];  These pointers follow inline */
3729};
3730
3731struct protocol_list32_t {
3732  uint32_t count; /* uintptr_t (a 32-bit value) */
3733  /* struct protocol32_t * list[0];  These pointers follow inline */
3734};
3735
3736struct protocol64_t {
3737  uint64_t isa;                     /* id * (64-bit pointer) */
3738  uint64_t name;                    /* const char * (64-bit pointer) */
3739  uint64_t protocols;               /* struct protocol_list64_t *
3740                                                    (64-bit pointer) */
3741  uint64_t instanceMethods;         /* method_list_t * (64-bit pointer) */
3742  uint64_t classMethods;            /* method_list_t * (64-bit pointer) */
3743  uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
3744  uint64_t optionalClassMethods;    /* method_list_t * (64-bit pointer) */
3745  uint64_t instanceProperties;      /* struct objc_property_list *
3746                                                       (64-bit pointer) */
3747};
3748
3749struct protocol32_t {
3750  uint32_t isa;                     /* id * (32-bit pointer) */
3751  uint32_t name;                    /* const char * (32-bit pointer) */
3752  uint32_t protocols;               /* struct protocol_list_t *
3753                                                    (32-bit pointer) */
3754  uint32_t instanceMethods;         /* method_list_t * (32-bit pointer) */
3755  uint32_t classMethods;            /* method_list_t * (32-bit pointer) */
3756  uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
3757  uint32_t optionalClassMethods;    /* method_list_t * (32-bit pointer) */
3758  uint32_t instanceProperties;      /* struct objc_property_list *
3759                                                       (32-bit pointer) */
3760};
3761
3762struct ivar_list64_t {
3763  uint32_t entsize;
3764  uint32_t count;
3765  /* struct ivar64_t first;  These structures follow inline */
3766};
3767
3768struct ivar_list32_t {
3769  uint32_t entsize;
3770  uint32_t count;
3771  /* struct ivar32_t first;  These structures follow inline */
3772};
3773
3774struct ivar64_t {
3775  uint64_t offset; /* uintptr_t * (64-bit pointer) */
3776  uint64_t name;   /* const char * (64-bit pointer) */
3777  uint64_t type;   /* const char * (64-bit pointer) */
3778  uint32_t alignment;
3779  uint32_t size;
3780};
3781
3782struct ivar32_t {
3783  uint32_t offset; /* uintptr_t * (32-bit pointer) */
3784  uint32_t name;   /* const char * (32-bit pointer) */
3785  uint32_t type;   /* const char * (32-bit pointer) */
3786  uint32_t alignment;
3787  uint32_t size;
3788};
3789
3790struct objc_property_list64 {
3791  uint32_t entsize;
3792  uint32_t count;
3793  /* struct objc_property64 first;  These structures follow inline */
3794};
3795
3796struct objc_property_list32 {
3797  uint32_t entsize;
3798  uint32_t count;
3799  /* struct objc_property32 first;  These structures follow inline */
3800};
3801
3802struct objc_property64 {
3803  uint64_t name;       /* const char * (64-bit pointer) */
3804  uint64_t attributes; /* const char * (64-bit pointer) */
3805};
3806
3807struct objc_property32 {
3808  uint32_t name;       /* const char * (32-bit pointer) */
3809  uint32_t attributes; /* const char * (32-bit pointer) */
3810};
3811
3812struct category64_t {
3813  uint64_t name;               /* const char * (64-bit pointer) */
3814  uint64_t cls;                /* struct class_t * (64-bit pointer) */
3815  uint64_t instanceMethods;    /* struct method_list_t * (64-bit pointer) */
3816  uint64_t classMethods;       /* struct method_list_t * (64-bit pointer) */
3817  uint64_t protocols;          /* struct protocol_list_t * (64-bit pointer) */
3818  uint64_t instanceProperties; /* struct objc_property_list *
3819                                  (64-bit pointer) */
3820};
3821
3822struct category32_t {
3823  uint32_t name;               /* const char * (32-bit pointer) */
3824  uint32_t cls;                /* struct class_t * (32-bit pointer) */
3825  uint32_t instanceMethods;    /* struct method_list_t * (32-bit pointer) */
3826  uint32_t classMethods;       /* struct method_list_t * (32-bit pointer) */
3827  uint32_t protocols;          /* struct protocol_list_t * (32-bit pointer) */
3828  uint32_t instanceProperties; /* struct objc_property_list *
3829                                  (32-bit pointer) */
3830};
3831
3832struct objc_image_info64 {
3833  uint32_t version;
3834  uint32_t flags;
3835};
3836struct objc_image_info32 {
3837  uint32_t version;
3838  uint32_t flags;
3839};
3840struct imageInfo_t {
3841  uint32_t version;
3842  uint32_t flags;
3843};
3844/* masks for objc_image_info.flags */
3845#define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
3846#define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
3847#define OBJC_IMAGE_IS_SIMULATED (1 << 5)
3848#define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)
3849
3850struct message_ref64 {
3851  uint64_t imp; /* IMP (64-bit pointer) */
3852  uint64_t sel; /* SEL (64-bit pointer) */
3853};
3854
3855struct message_ref32 {
3856  uint32_t imp; /* IMP (32-bit pointer) */
3857  uint32_t sel; /* SEL (32-bit pointer) */
3858};
3859
3860// Objective-C 1 (32-bit only) meta data structs.
3861
3862struct objc_module_t {
3863  uint32_t version;
3864  uint32_t size;
3865  uint32_t name;   /* char * (32-bit pointer) */
3866  uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
3867};
3868
3869struct objc_symtab_t {
3870  uint32_t sel_ref_cnt;
3871  uint32_t refs; /* SEL * (32-bit pointer) */
3872  uint16_t cls_def_cnt;
3873  uint16_t cat_def_cnt;
3874  // uint32_t defs[1];        /* void * (32-bit pointer) variable size */
3875};
3876
3877struct objc_class_t {
3878  uint32_t isa;         /* struct objc_class * (32-bit pointer) */
3879  uint32_t super_class; /* struct objc_class * (32-bit pointer) */
3880  uint32_t name;        /* const char * (32-bit pointer) */
3881  int32_t version;
3882  int32_t info;
3883  int32_t instance_size;
3884  uint32_t ivars;       /* struct objc_ivar_list * (32-bit pointer) */
3885  uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
3886  uint32_t cache;       /* struct objc_cache * (32-bit pointer) */
3887  uint32_t protocols;   /* struct objc_protocol_list * (32-bit pointer) */
3888};
3889
3890#define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
3891// class is not a metaclass
3892#define CLS_CLASS 0x1
3893// class is a metaclass
3894#define CLS_META 0x2
3895
3896struct objc_category_t {
3897  uint32_t category_name;    /* char * (32-bit pointer) */
3898  uint32_t class_name;       /* char * (32-bit pointer) */
3899  uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
3900  uint32_t class_methods;    /* struct objc_method_list * (32-bit pointer) */
3901  uint32_t protocols;        /* struct objc_protocol_list * (32-bit ptr) */
3902};
3903
3904struct objc_ivar_t {
3905  uint32_t ivar_name; /* char * (32-bit pointer) */
3906  uint32_t ivar_type; /* char * (32-bit pointer) */
3907  int32_t ivar_offset;
3908};
3909
3910struct objc_ivar_list_t {
3911  int32_t ivar_count;
3912  // struct objc_ivar_t ivar_list[1];          /* variable length structure */
3913};
3914
3915struct objc_method_list_t {
3916  uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
3917  int32_t method_count;
3918  // struct objc_method_t method_list[1];      /* variable length structure */
3919};
3920
3921struct objc_method_t {
3922  uint32_t method_name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3923  uint32_t method_types; /* char * (32-bit pointer) */
3924  uint32_t method_imp;   /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
3925                            (32-bit pointer) */
3926};
3927
3928struct objc_protocol_list_t {
3929  uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
3930  int32_t count;
3931  // uint32_t list[1];   /* Protocol *, aka struct objc_protocol_t *
3932  //                        (32-bit pointer) */
3933};
3934
3935struct objc_protocol_t {
3936  uint32_t isa;              /* struct objc_class * (32-bit pointer) */
3937  uint32_t protocol_name;    /* char * (32-bit pointer) */
3938  uint32_t protocol_list;    /* struct objc_protocol_list * (32-bit pointer) */
3939  uint32_t instance_methods; /* struct objc_method_description_list *
3940                                (32-bit pointer) */
3941  uint32_t class_methods;    /* struct objc_method_description_list *
3942                                (32-bit pointer) */
3943};
3944
3945struct objc_method_description_list_t {
3946  int32_t count;
3947  // struct objc_method_description_t list[1];
3948};
3949
3950struct objc_method_description_t {
3951  uint32_t name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3952  uint32_t types; /* char * (32-bit pointer) */
3953};
3954
3955inline void swapStruct(struct cfstring64_t &cfs) {
3956  sys::swapByteOrder(cfs.isa);
3957  sys::swapByteOrder(cfs.flags);
3958  sys::swapByteOrder(cfs.characters);
3959  sys::swapByteOrder(cfs.length);
3960}
3961
3962inline void swapStruct(struct class64_t &c) {
3963  sys::swapByteOrder(c.isa);
3964  sys::swapByteOrder(c.superclass);
3965  sys::swapByteOrder(c.cache);
3966  sys::swapByteOrder(c.vtable);
3967  sys::swapByteOrder(c.data);
3968}
3969
3970inline void swapStruct(struct class32_t &c) {
3971  sys::swapByteOrder(c.isa);
3972  sys::swapByteOrder(c.superclass);
3973  sys::swapByteOrder(c.cache);
3974  sys::swapByteOrder(c.vtable);
3975  sys::swapByteOrder(c.data);
3976}
3977
3978inline void swapStruct(struct class_ro64_t &cro) {
3979  sys::swapByteOrder(cro.flags);
3980  sys::swapByteOrder(cro.instanceStart);
3981  sys::swapByteOrder(cro.instanceSize);
3982  sys::swapByteOrder(cro.reserved);
3983  sys::swapByteOrder(cro.ivarLayout);
3984  sys::swapByteOrder(cro.name);
3985  sys::swapByteOrder(cro.baseMethods);
3986  sys::swapByteOrder(cro.baseProtocols);
3987  sys::swapByteOrder(cro.ivars);
3988  sys::swapByteOrder(cro.weakIvarLayout);
3989  sys::swapByteOrder(cro.baseProperties);
3990}
3991
3992inline void swapStruct(struct class_ro32_t &cro) {
3993  sys::swapByteOrder(cro.flags);
3994  sys::swapByteOrder(cro.instanceStart);
3995  sys::swapByteOrder(cro.instanceSize);
3996  sys::swapByteOrder(cro.ivarLayout);
3997  sys::swapByteOrder(cro.name);
3998  sys::swapByteOrder(cro.baseMethods);
3999  sys::swapByteOrder(cro.baseProtocols);
4000  sys::swapByteOrder(cro.ivars);
4001  sys::swapByteOrder(cro.weakIvarLayout);
4002  sys::swapByteOrder(cro.baseProperties);
4003}
4004
4005inline void swapStruct(struct method_list64_t &ml) {
4006  sys::swapByteOrder(ml.entsize);
4007  sys::swapByteOrder(ml.count);
4008}
4009
4010inline void swapStruct(struct method_list32_t &ml) {
4011  sys::swapByteOrder(ml.entsize);
4012  sys::swapByteOrder(ml.count);
4013}
4014
4015inline void swapStruct(struct method64_t &m) {
4016  sys::swapByteOrder(m.name);
4017  sys::swapByteOrder(m.types);
4018  sys::swapByteOrder(m.imp);
4019}
4020
4021inline void swapStruct(struct method32_t &m) {
4022  sys::swapByteOrder(m.name);
4023  sys::swapByteOrder(m.types);
4024  sys::swapByteOrder(m.imp);
4025}
4026
4027inline void swapStruct(struct protocol_list64_t &pl) {
4028  sys::swapByteOrder(pl.count);
4029}
4030
4031inline void swapStruct(struct protocol_list32_t &pl) {
4032  sys::swapByteOrder(pl.count);
4033}
4034
4035inline void swapStruct(struct protocol64_t &p) {
4036  sys::swapByteOrder(p.isa);
4037  sys::swapByteOrder(p.name);
4038  sys::swapByteOrder(p.protocols);
4039  sys::swapByteOrder(p.instanceMethods);
4040  sys::swapByteOrder(p.classMethods);
4041  sys::swapByteOrder(p.optionalInstanceMethods);
4042  sys::swapByteOrder(p.optionalClassMethods);
4043  sys::swapByteOrder(p.instanceProperties);
4044}
4045
4046inline void swapStruct(struct protocol32_t &p) {
4047  sys::swapByteOrder(p.isa);
4048  sys::swapByteOrder(p.name);
4049  sys::swapByteOrder(p.protocols);
4050  sys::swapByteOrder(p.instanceMethods);
4051  sys::swapByteOrder(p.classMethods);
4052  sys::swapByteOrder(p.optionalInstanceMethods);
4053  sys::swapByteOrder(p.optionalClassMethods);
4054  sys::swapByteOrder(p.instanceProperties);
4055}
4056
4057inline void swapStruct(struct ivar_list64_t &il) {
4058  sys::swapByteOrder(il.entsize);
4059  sys::swapByteOrder(il.count);
4060}
4061
4062inline void swapStruct(struct ivar_list32_t &il) {
4063  sys::swapByteOrder(il.entsize);
4064  sys::swapByteOrder(il.count);
4065}
4066
4067inline void swapStruct(struct ivar64_t &i) {
4068  sys::swapByteOrder(i.offset);
4069  sys::swapByteOrder(i.name);
4070  sys::swapByteOrder(i.type);
4071  sys::swapByteOrder(i.alignment);
4072  sys::swapByteOrder(i.size);
4073}
4074
4075inline void swapStruct(struct ivar32_t &i) {
4076  sys::swapByteOrder(i.offset);
4077  sys::swapByteOrder(i.name);
4078  sys::swapByteOrder(i.type);
4079  sys::swapByteOrder(i.alignment);
4080  sys::swapByteOrder(i.size);
4081}
4082
4083inline void swapStruct(struct objc_property_list64 &pl) {
4084  sys::swapByteOrder(pl.entsize);
4085  sys::swapByteOrder(pl.count);
4086}
4087
4088inline void swapStruct(struct objc_property_list32 &pl) {
4089  sys::swapByteOrder(pl.entsize);
4090  sys::swapByteOrder(pl.count);
4091}
4092
4093inline void swapStruct(struct objc_property64 &op) {
4094  sys::swapByteOrder(op.name);
4095  sys::swapByteOrder(op.attributes);
4096}
4097
4098inline void swapStruct(struct objc_property32 &op) {
4099  sys::swapByteOrder(op.name);
4100  sys::swapByteOrder(op.attributes);
4101}
4102
4103inline void swapStruct(struct category64_t &c) {
4104  sys::swapByteOrder(c.name);
4105  sys::swapByteOrder(c.cls);
4106  sys::swapByteOrder(c.instanceMethods);
4107  sys::swapByteOrder(c.classMethods);
4108  sys::swapByteOrder(c.protocols);
4109  sys::swapByteOrder(c.instanceProperties);
4110}
4111
4112inline void swapStruct(struct category32_t &c) {
4113  sys::swapByteOrder(c.name);
4114  sys::swapByteOrder(c.cls);
4115  sys::swapByteOrder(c.instanceMethods);
4116  sys::swapByteOrder(c.classMethods);
4117  sys::swapByteOrder(c.protocols);
4118  sys::swapByteOrder(c.instanceProperties);
4119}
4120
4121inline void swapStruct(struct objc_image_info64 &o) {
4122  sys::swapByteOrder(o.version);
4123  sys::swapByteOrder(o.flags);
4124}
4125
4126inline void swapStruct(struct objc_image_info32 &o) {
4127  sys::swapByteOrder(o.version);
4128  sys::swapByteOrder(o.flags);
4129}
4130
4131inline void swapStruct(struct imageInfo_t &o) {
4132  sys::swapByteOrder(o.version);
4133  sys::swapByteOrder(o.flags);
4134}
4135
4136inline void swapStruct(struct message_ref64 &mr) {
4137  sys::swapByteOrder(mr.imp);
4138  sys::swapByteOrder(mr.sel);
4139}
4140
4141inline void swapStruct(struct message_ref32 &mr) {
4142  sys::swapByteOrder(mr.imp);
4143  sys::swapByteOrder(mr.sel);
4144}
4145
4146inline void swapStruct(struct objc_module_t &module) {
4147  sys::swapByteOrder(module.version);
4148  sys::swapByteOrder(module.size);
4149  sys::swapByteOrder(module.name);
4150  sys::swapByteOrder(module.symtab);
4151}
4152
4153inline void swapStruct(struct objc_symtab_t &symtab) {
4154  sys::swapByteOrder(symtab.sel_ref_cnt);
4155  sys::swapByteOrder(symtab.refs);
4156  sys::swapByteOrder(symtab.cls_def_cnt);
4157  sys::swapByteOrder(symtab.cat_def_cnt);
4158}
4159
4160inline void swapStruct(struct objc_class_t &objc_class) {
4161  sys::swapByteOrder(objc_class.isa);
4162  sys::swapByteOrder(objc_class.super_class);
4163  sys::swapByteOrder(objc_class.name);
4164  sys::swapByteOrder(objc_class.version);
4165  sys::swapByteOrder(objc_class.info);
4166  sys::swapByteOrder(objc_class.instance_size);
4167  sys::swapByteOrder(objc_class.ivars);
4168  sys::swapByteOrder(objc_class.methodLists);
4169  sys::swapByteOrder(objc_class.cache);
4170  sys::swapByteOrder(objc_class.protocols);
4171}
4172
4173inline void swapStruct(struct objc_category_t &objc_category) {
4174  sys::swapByteOrder(objc_category.category_name);
4175  sys::swapByteOrder(objc_category.class_name);
4176  sys::swapByteOrder(objc_category.instance_methods);
4177  sys::swapByteOrder(objc_category.class_methods);
4178  sys::swapByteOrder(objc_category.protocols);
4179}
4180
4181inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
4182  sys::swapByteOrder(objc_ivar_list.ivar_count);
4183}
4184
4185inline void swapStruct(struct objc_ivar_t &objc_ivar) {
4186  sys::swapByteOrder(objc_ivar.ivar_name);
4187  sys::swapByteOrder(objc_ivar.ivar_type);
4188  sys::swapByteOrder(objc_ivar.ivar_offset);
4189}
4190
4191inline void swapStruct(struct objc_method_list_t &method_list) {
4192  sys::swapByteOrder(method_list.obsolete);
4193  sys::swapByteOrder(method_list.method_count);
4194}
4195
4196inline void swapStruct(struct objc_method_t &method) {
4197  sys::swapByteOrder(method.method_name);
4198  sys::swapByteOrder(method.method_types);
4199  sys::swapByteOrder(method.method_imp);
4200}
4201
4202inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
4203  sys::swapByteOrder(protocol_list.next);
4204  sys::swapByteOrder(protocol_list.count);
4205}
4206
4207inline void swapStruct(struct objc_protocol_t &protocol) {
4208  sys::swapByteOrder(protocol.isa);
4209  sys::swapByteOrder(protocol.protocol_name);
4210  sys::swapByteOrder(protocol.protocol_list);
4211  sys::swapByteOrder(protocol.instance_methods);
4212  sys::swapByteOrder(protocol.class_methods);
4213}
4214
4215inline void swapStruct(struct objc_method_description_list_t &mdl) {
4216  sys::swapByteOrder(mdl.count);
4217}
4218
4219inline void swapStruct(struct objc_method_description_t &md) {
4220  sys::swapByteOrder(md.name);
4221  sys::swapByteOrder(md.types);
4222}
4223
4224} // namespace
4225
4226static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
4227                                                 struct DisassembleInfo *info);
4228
4229// get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
4230// to an Objective-C class and returns the class name.  It is also passed the
4231// address of the pointer, so when the pointer is zero as it can be in an .o
4232// file, that is used to look for an external relocation entry with a symbol
4233// name.
4234static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
4235                                              uint64_t ReferenceValue,
4236                                              struct DisassembleInfo *info) {
4237  const char *r;
4238  uint32_t offset, left;
4239  SectionRef S;
4240
4241  // The pointer_value can be 0 in an object file and have a relocation
4242  // entry for the class symbol at the ReferenceValue (the address of the
4243  // pointer).
4244  if (pointer_value == 0) {
4245    r = get_pointer_64(ReferenceValue, offset, left, S, info);
4246    if (r == nullptr || left < sizeof(uint64_t))
4247      return nullptr;
4248    uint64_t n_value;
4249    const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4250    if (symbol_name == nullptr)
4251      return nullptr;
4252    const char *class_name = strrchr(symbol_name, '$');
4253    if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
4254      return class_name + 2;
4255    else
4256      return nullptr;
4257  }
4258
4259  // The case were the pointer_value is non-zero and points to a class defined
4260  // in this Mach-O file.
4261  r = get_pointer_64(pointer_value, offset, left, S, info);
4262  if (r == nullptr || left < sizeof(struct class64_t))
4263    return nullptr;
4264  struct class64_t c;
4265  memcpy(&c, r, sizeof(struct class64_t));
4266  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4267    swapStruct(c);
4268  if (c.data == 0)
4269    return nullptr;
4270  r = get_pointer_64(c.data, offset, left, S, info);
4271  if (r == nullptr || left < sizeof(struct class_ro64_t))
4272    return nullptr;
4273  struct class_ro64_t cro;
4274  memcpy(&cro, r, sizeof(struct class_ro64_t));
4275  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4276    swapStruct(cro);
4277  if (cro.name == 0)
4278    return nullptr;
4279  const char *name = get_pointer_64(cro.name, offset, left, S, info);
4280  return name;
4281}
4282
4283// get_objc2_64bit_cfstring_name is used for disassembly and is passed a
4284// pointer to a cfstring and returns its name or nullptr.
4285static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
4286                                                 struct DisassembleInfo *info) {
4287  const char *r, *name;
4288  uint32_t offset, left;
4289  SectionRef S;
4290  struct cfstring64_t cfs;
4291  uint64_t cfs_characters;
4292
4293  r = get_pointer_64(ReferenceValue, offset, left, S, info);
4294  if (r == nullptr || left < sizeof(struct cfstring64_t))
4295    return nullptr;
4296  memcpy(&cfs, r, sizeof(struct cfstring64_t));
4297  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4298    swapStruct(cfs);
4299  if (cfs.characters == 0) {
4300    uint64_t n_value;
4301    const char *symbol_name = get_symbol_64(
4302        offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
4303    if (symbol_name == nullptr)
4304      return nullptr;
4305    cfs_characters = n_value;
4306  } else
4307    cfs_characters = cfs.characters;
4308  name = get_pointer_64(cfs_characters, offset, left, S, info);
4309
4310  return name;
4311}
4312
4313// get_objc2_64bit_selref() is used for disassembly and is passed a the address
4314// of a pointer to an Objective-C selector reference when the pointer value is
4315// zero as in a .o file and is likely to have a external relocation entry with
4316// who's symbol's n_value is the real pointer to the selector name.  If that is
4317// the case the real pointer to the selector name is returned else 0 is
4318// returned
4319static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
4320                                       struct DisassembleInfo *info) {
4321  uint32_t offset, left;
4322  SectionRef S;
4323
4324  const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
4325  if (r == nullptr || left < sizeof(uint64_t))
4326    return 0;
4327  uint64_t n_value;
4328  const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4329  if (symbol_name == nullptr)
4330    return 0;
4331  return n_value;
4332}
4333
4334static const SectionRef get_section(MachOObjectFile *O, const char *segname,
4335                                    const char *sectname) {
4336  for (const SectionRef &Section : O->sections()) {
4337    StringRef SectName;
4338    Expected<StringRef> SecNameOrErr = Section.getName();
4339    if (SecNameOrErr)
4340      SectName = *SecNameOrErr;
4341    else
4342      consumeError(SecNameOrErr.takeError());
4343
4344    DataRefImpl Ref = Section.getRawDataRefImpl();
4345    StringRef SegName = O->getSectionFinalSegmentName(Ref);
4346    if (SegName == segname && SectName == sectname)
4347      return Section;
4348  }
4349  return SectionRef();
4350}
4351
4352static void
4353walk_pointer_list_64(const char *listname, const SectionRef S,
4354                     MachOObjectFile *O, struct DisassembleInfo *info,
4355                     void (*func)(uint64_t, struct DisassembleInfo *info)) {
4356  if (S == SectionRef())
4357    return;
4358
4359  StringRef SectName;
4360  Expected<StringRef> SecNameOrErr = S.getName();
4361  if (SecNameOrErr)
4362    SectName = *SecNameOrErr;
4363  else
4364    consumeError(SecNameOrErr.takeError());
4365
4366  DataRefImpl Ref = S.getRawDataRefImpl();
4367  StringRef SegName = O->getSectionFinalSegmentName(Ref);
4368  outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4369
4370  StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4371  const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4372
4373  for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
4374    uint32_t left = S.getSize() - i;
4375    uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
4376    uint64_t p = 0;
4377    memcpy(&p, Contents + i, size);
4378    if (i + sizeof(uint64_t) > S.getSize())
4379      outs() << listname << " list pointer extends past end of (" << SegName
4380             << "," << SectName << ") section\n";
4381    outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
4382
4383    if (O->isLittleEndian() != sys::IsLittleEndianHost)
4384      sys::swapByteOrder(p);
4385
4386    uint64_t n_value = 0;
4387    const char *name = get_symbol_64(i, S, info, n_value, p);
4388    if (name == nullptr)
4389      name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
4390
4391    if (n_value != 0) {
4392      outs() << format("0x%" PRIx64, n_value);
4393      if (p != 0)
4394        outs() << " + " << format("0x%" PRIx64, p);
4395    } else
4396      outs() << format("0x%" PRIx64, p);
4397    if (name != nullptr)
4398      outs() << " " << name;
4399    outs() << "\n";
4400
4401    p += n_value;
4402    if (func)
4403      func(p, info);
4404  }
4405}
4406
4407static void
4408walk_pointer_list_32(const char *listname, const SectionRef S,
4409                     MachOObjectFile *O, struct DisassembleInfo *info,
4410                     void (*func)(uint32_t, struct DisassembleInfo *info)) {
4411  if (S == SectionRef())
4412    return;
4413
4414  StringRef SectName = unwrapOrError(S.getName(), O->getFileName());
4415  DataRefImpl Ref = S.getRawDataRefImpl();
4416  StringRef SegName = O->getSectionFinalSegmentName(Ref);
4417  outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4418
4419  StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4420  const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4421
4422  for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
4423    uint32_t left = S.getSize() - i;
4424    uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
4425    uint32_t p = 0;
4426    memcpy(&p, Contents + i, size);
4427    if (i + sizeof(uint32_t) > S.getSize())
4428      outs() << listname << " list pointer extends past end of (" << SegName
4429             << "," << SectName << ") section\n";
4430    uint32_t Address = S.getAddress() + i;
4431    outs() << format("%08" PRIx32, Address) << " ";
4432
4433    if (O->isLittleEndian() != sys::IsLittleEndianHost)
4434      sys::swapByteOrder(p);
4435    outs() << format("0x%" PRIx32, p);
4436
4437    const char *name = get_symbol_32(i, S, info, p);
4438    if (name != nullptr)
4439      outs() << " " << name;
4440    outs() << "\n";
4441
4442    if (func)
4443      func(p, info);
4444  }
4445}
4446
4447static void print_layout_map(const char *layout_map, uint32_t left) {
4448  if (layout_map == nullptr)
4449    return;
4450  outs() << "                layout map: ";
4451  do {
4452    outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
4453    left--;
4454    layout_map++;
4455  } while (*layout_map != '\0' && left != 0);
4456  outs() << "\n";
4457}
4458
4459static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
4460  uint32_t offset, left;
4461  SectionRef S;
4462  const char *layout_map;
4463
4464  if (p == 0)
4465    return;
4466  layout_map = get_pointer_64(p, offset, left, S, info);
4467  print_layout_map(layout_map, left);
4468}
4469
4470static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
4471  uint32_t offset, left;
4472  SectionRef S;
4473  const char *layout_map;
4474
4475  if (p == 0)
4476    return;
4477  layout_map = get_pointer_32(p, offset, left, S, info);
4478  print_layout_map(layout_map, left);
4479}
4480
4481static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
4482                                  const char *indent) {
4483  struct method_list64_t ml;
4484  struct method64_t m;
4485  const char *r;
4486  uint32_t offset, xoffset, left, i;
4487  SectionRef S, xS;
4488  const char *name, *sym_name;
4489  uint64_t n_value;
4490
4491  r = get_pointer_64(p, offset, left, S, info);
4492  if (r == nullptr)
4493    return;
4494  memset(&ml, '\0', sizeof(struct method_list64_t));
4495  if (left < sizeof(struct method_list64_t)) {
4496    memcpy(&ml, r, left);
4497    outs() << "   (method_list_t entends past the end of the section)\n";
4498  } else
4499    memcpy(&ml, r, sizeof(struct method_list64_t));
4500  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4501    swapStruct(ml);
4502  outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4503  outs() << indent << "\t\t     count " << ml.count << "\n";
4504
4505  p += sizeof(struct method_list64_t);
4506  offset += sizeof(struct method_list64_t);
4507  for (i = 0; i < ml.count; i++) {
4508    r = get_pointer_64(p, offset, left, S, info);
4509    if (r == nullptr)
4510      return;
4511    memset(&m, '\0', sizeof(struct method64_t));
4512    if (left < sizeof(struct method64_t)) {
4513      memcpy(&m, r, left);
4514      outs() << indent << "   (method_t extends past the end of the section)\n";
4515    } else
4516      memcpy(&m, r, sizeof(struct method64_t));
4517    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4518      swapStruct(m);
4519
4520    outs() << indent << "\t\t      name ";
4521    sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
4522                             info, n_value, m.name);
4523    if (n_value != 0) {
4524      if (info->verbose && sym_name != nullptr)
4525        outs() << sym_name;
4526      else
4527        outs() << format("0x%" PRIx64, n_value);
4528      if (m.name != 0)
4529        outs() << " + " << format("0x%" PRIx64, m.name);
4530    } else
4531      outs() << format("0x%" PRIx64, m.name);
4532    name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
4533    if (name != nullptr)
4534      outs() << format(" %.*s", left, name);
4535    outs() << "\n";
4536
4537    outs() << indent << "\t\t     types ";
4538    sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
4539                             info, n_value, m.types);
4540    if (n_value != 0) {
4541      if (info->verbose && sym_name != nullptr)
4542        outs() << sym_name;
4543      else
4544        outs() << format("0x%" PRIx64, n_value);
4545      if (m.types != 0)
4546        outs() << " + " << format("0x%" PRIx64, m.types);
4547    } else
4548      outs() << format("0x%" PRIx64, m.types);
4549    name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
4550    if (name != nullptr)
4551      outs() << format(" %.*s", left, name);
4552    outs() << "\n";
4553
4554    outs() << indent << "\t\t       imp ";
4555    name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
4556                         n_value, m.imp);
4557    if (info->verbose && name == nullptr) {
4558      if (n_value != 0) {
4559        outs() << format("0x%" PRIx64, n_value) << " ";
4560        if (m.imp != 0)
4561          outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
4562      } else
4563        outs() << format("0x%" PRIx64, m.imp) << " ";
4564    }
4565    if (name != nullptr)
4566      outs() << name;
4567    outs() << "\n";
4568
4569    p += sizeof(struct method64_t);
4570    offset += sizeof(struct method64_t);
4571  }
4572}
4573
4574static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
4575                                  const char *indent) {
4576  struct method_list32_t ml;
4577  struct method32_t m;
4578  const char *r, *name;
4579  uint32_t offset, xoffset, left, i;
4580  SectionRef S, xS;
4581
4582  r = get_pointer_32(p, offset, left, S, info);
4583  if (r == nullptr)
4584    return;
4585  memset(&ml, '\0', sizeof(struct method_list32_t));
4586  if (left < sizeof(struct method_list32_t)) {
4587    memcpy(&ml, r, left);
4588    outs() << "   (method_list_t entends past the end of the section)\n";
4589  } else
4590    memcpy(&ml, r, sizeof(struct method_list32_t));
4591  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4592    swapStruct(ml);
4593  outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4594  outs() << indent << "\t\t     count " << ml.count << "\n";
4595
4596  p += sizeof(struct method_list32_t);
4597  offset += sizeof(struct method_list32_t);
4598  for (i = 0; i < ml.count; i++) {
4599    r = get_pointer_32(p, offset, left, S, info);
4600    if (r == nullptr)
4601      return;
4602    memset(&m, '\0', sizeof(struct method32_t));
4603    if (left < sizeof(struct method32_t)) {
4604      memcpy(&ml, r, left);
4605      outs() << indent << "   (method_t entends past the end of the section)\n";
4606    } else
4607      memcpy(&m, r, sizeof(struct method32_t));
4608    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4609      swapStruct(m);
4610
4611    outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
4612    name = get_pointer_32(m.name, xoffset, left, xS, info);
4613    if (name != nullptr)
4614      outs() << format(" %.*s", left, name);
4615    outs() << "\n";
4616
4617    outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
4618    name = get_pointer_32(m.types, xoffset, left, xS, info);
4619    if (name != nullptr)
4620      outs() << format(" %.*s", left, name);
4621    outs() << "\n";
4622
4623    outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
4624    name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
4625                         m.imp);
4626    if (name != nullptr)
4627      outs() << " " << name;
4628    outs() << "\n";
4629
4630    p += sizeof(struct method32_t);
4631    offset += sizeof(struct method32_t);
4632  }
4633}
4634
4635static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
4636  uint32_t offset, left, xleft;
4637  SectionRef S;
4638  struct objc_method_list_t method_list;
4639  struct objc_method_t method;
4640  const char *r, *methods, *name, *SymbolName;
4641  int32_t i;
4642
4643  r = get_pointer_32(p, offset, left, S, info, true);
4644  if (r == nullptr)
4645    return true;
4646
4647  outs() << "\n";
4648  if (left > sizeof(struct objc_method_list_t)) {
4649    memcpy(&method_list, r, sizeof(struct objc_method_list_t));
4650  } else {
4651    outs() << "\t\t objc_method_list extends past end of the section\n";
4652    memset(&method_list, '\0', sizeof(struct objc_method_list_t));
4653    memcpy(&method_list, r, left);
4654  }
4655  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4656    swapStruct(method_list);
4657
4658  outs() << "\t\t         obsolete "
4659         << format("0x%08" PRIx32, method_list.obsolete) << "\n";
4660  outs() << "\t\t     method_count " << method_list.method_count << "\n";
4661
4662  methods = r + sizeof(struct objc_method_list_t);
4663  for (i = 0; i < method_list.method_count; i++) {
4664    if ((i + 1) * sizeof(struct objc_method_t) > left) {
4665      outs() << "\t\t remaining method's extend past the of the section\n";
4666      break;
4667    }
4668    memcpy(&method, methods + i * sizeof(struct objc_method_t),
4669           sizeof(struct objc_method_t));
4670    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4671      swapStruct(method);
4672
4673    outs() << "\t\t      method_name "
4674           << format("0x%08" PRIx32, method.method_name);
4675    if (info->verbose) {
4676      name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
4677      if (name != nullptr)
4678        outs() << format(" %.*s", xleft, name);
4679      else
4680        outs() << " (not in an __OBJC section)";
4681    }
4682    outs() << "\n";
4683
4684    outs() << "\t\t     method_types "
4685           << format("0x%08" PRIx32, method.method_types);
4686    if (info->verbose) {
4687      name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
4688      if (name != nullptr)
4689        outs() << format(" %.*s", xleft, name);
4690      else
4691        outs() << " (not in an __OBJC section)";
4692    }
4693    outs() << "\n";
4694
4695    outs() << "\t\t       method_imp "
4696           << format("0x%08" PRIx32, method.method_imp) << " ";
4697    if (info->verbose) {
4698      SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
4699      if (SymbolName != nullptr)
4700        outs() << SymbolName;
4701    }
4702    outs() << "\n";
4703  }
4704  return false;
4705}
4706
4707static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
4708  struct protocol_list64_t pl;
4709  uint64_t q, n_value;
4710  struct protocol64_t pc;
4711  const char *r;
4712  uint32_t offset, xoffset, left, i;
4713  SectionRef S, xS;
4714  const char *name, *sym_name;
4715
4716  r = get_pointer_64(p, offset, left, S, info);
4717  if (r == nullptr)
4718    return;
4719  memset(&pl, '\0', sizeof(struct protocol_list64_t));
4720  if (left < sizeof(struct protocol_list64_t)) {
4721    memcpy(&pl, r, left);
4722    outs() << "   (protocol_list_t entends past the end of the section)\n";
4723  } else
4724    memcpy(&pl, r, sizeof(struct protocol_list64_t));
4725  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4726    swapStruct(pl);
4727  outs() << "                      count " << pl.count << "\n";
4728
4729  p += sizeof(struct protocol_list64_t);
4730  offset += sizeof(struct protocol_list64_t);
4731  for (i = 0; i < pl.count; i++) {
4732    r = get_pointer_64(p, offset, left, S, info);
4733    if (r == nullptr)
4734      return;
4735    q = 0;
4736    if (left < sizeof(uint64_t)) {
4737      memcpy(&q, r, left);
4738      outs() << "   (protocol_t * entends past the end of the section)\n";
4739    } else
4740      memcpy(&q, r, sizeof(uint64_t));
4741    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4742      sys::swapByteOrder(q);
4743
4744    outs() << "\t\t      list[" << i << "] ";
4745    sym_name = get_symbol_64(offset, S, info, n_value, q);
4746    if (n_value != 0) {
4747      if (info->verbose && sym_name != nullptr)
4748        outs() << sym_name;
4749      else
4750        outs() << format("0x%" PRIx64, n_value);
4751      if (q != 0)
4752        outs() << " + " << format("0x%" PRIx64, q);
4753    } else
4754      outs() << format("0x%" PRIx64, q);
4755    outs() << " (struct protocol_t *)\n";
4756
4757    r = get_pointer_64(q + n_value, offset, left, S, info);
4758    if (r == nullptr)
4759      return;
4760    memset(&pc, '\0', sizeof(struct protocol64_t));
4761    if (left < sizeof(struct protocol64_t)) {
4762      memcpy(&pc, r, left);
4763      outs() << "   (protocol_t entends past the end of the section)\n";
4764    } else
4765      memcpy(&pc, r, sizeof(struct protocol64_t));
4766    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4767      swapStruct(pc);
4768
4769    outs() << "\t\t\t      isa " << format("0x%" PRIx64, pc.isa) << "\n";
4770
4771    outs() << "\t\t\t     name ";
4772    sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
4773                             info, n_value, pc.name);
4774    if (n_value != 0) {
4775      if (info->verbose && sym_name != nullptr)
4776        outs() << sym_name;
4777      else
4778        outs() << format("0x%" PRIx64, n_value);
4779      if (pc.name != 0)
4780        outs() << " + " << format("0x%" PRIx64, pc.name);
4781    } else
4782      outs() << format("0x%" PRIx64, pc.name);
4783    name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
4784    if (name != nullptr)
4785      outs() << format(" %.*s", left, name);
4786    outs() << "\n";
4787
4788    outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
4789
4790    outs() << "\t\t  instanceMethods ";
4791    sym_name =
4792        get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
4793                      S, info, n_value, pc.instanceMethods);
4794    if (n_value != 0) {
4795      if (info->verbose && sym_name != nullptr)
4796        outs() << sym_name;
4797      else
4798        outs() << format("0x%" PRIx64, n_value);
4799      if (pc.instanceMethods != 0)
4800        outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
4801    } else
4802      outs() << format("0x%" PRIx64, pc.instanceMethods);
4803    outs() << " (struct method_list_t *)\n";
4804    if (pc.instanceMethods + n_value != 0)
4805      print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
4806
4807    outs() << "\t\t     classMethods ";
4808    sym_name =
4809        get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
4810                      info, n_value, pc.classMethods);
4811    if (n_value != 0) {
4812      if (info->verbose && sym_name != nullptr)
4813        outs() << sym_name;
4814      else
4815        outs() << format("0x%" PRIx64, n_value);
4816      if (pc.classMethods != 0)
4817        outs() << " + " << format("0x%" PRIx64, pc.classMethods);
4818    } else
4819      outs() << format("0x%" PRIx64, pc.classMethods);
4820    outs() << " (struct method_list_t *)\n";
4821    if (pc.classMethods + n_value != 0)
4822      print_method_list64_t(pc.classMethods + n_value, info, "\t");
4823
4824    outs() << "\t  optionalInstanceMethods "
4825           << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
4826    outs() << "\t     optionalClassMethods "
4827           << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
4828    outs() << "\t       instanceProperties "
4829           << format("0x%" PRIx64, pc.instanceProperties) << "\n";
4830
4831    p += sizeof(uint64_t);
4832    offset += sizeof(uint64_t);
4833  }
4834}
4835
4836static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
4837  struct protocol_list32_t pl;
4838  uint32_t q;
4839  struct protocol32_t pc;
4840  const char *r;
4841  uint32_t offset, xoffset, left, i;
4842  SectionRef S, xS;
4843  const char *name;
4844
4845  r = get_pointer_32(p, offset, left, S, info);
4846  if (r == nullptr)
4847    return;
4848  memset(&pl, '\0', sizeof(struct protocol_list32_t));
4849  if (left < sizeof(struct protocol_list32_t)) {
4850    memcpy(&pl, r, left);
4851    outs() << "   (protocol_list_t entends past the end of the section)\n";
4852  } else
4853    memcpy(&pl, r, sizeof(struct protocol_list32_t));
4854  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4855    swapStruct(pl);
4856  outs() << "                      count " << pl.count << "\n";
4857
4858  p += sizeof(struct protocol_list32_t);
4859  offset += sizeof(struct protocol_list32_t);
4860  for (i = 0; i < pl.count; i++) {
4861    r = get_pointer_32(p, offset, left, S, info);
4862    if (r == nullptr)
4863      return;
4864    q = 0;
4865    if (left < sizeof(uint32_t)) {
4866      memcpy(&q, r, left);
4867      outs() << "   (protocol_t * entends past the end of the section)\n";
4868    } else
4869      memcpy(&q, r, sizeof(uint32_t));
4870    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4871      sys::swapByteOrder(q);
4872    outs() << "\t\t      list[" << i << "] " << format("0x%" PRIx32, q)
4873           << " (struct protocol_t *)\n";
4874    r = get_pointer_32(q, offset, left, S, info);
4875    if (r == nullptr)
4876      return;
4877    memset(&pc, '\0', sizeof(struct protocol32_t));
4878    if (left < sizeof(struct protocol32_t)) {
4879      memcpy(&pc, r, left);
4880      outs() << "   (protocol_t entends past the end of the section)\n";
4881    } else
4882      memcpy(&pc, r, sizeof(struct protocol32_t));
4883    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4884      swapStruct(pc);
4885    outs() << "\t\t\t      isa " << format("0x%" PRIx32, pc.isa) << "\n";
4886    outs() << "\t\t\t     name " << format("0x%" PRIx32, pc.name);
4887    name = get_pointer_32(pc.name, xoffset, left, xS, info);
4888    if (name != nullptr)
4889      outs() << format(" %.*s", left, name);
4890    outs() << "\n";
4891    outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
4892    outs() << "\t\t  instanceMethods "
4893           << format("0x%" PRIx32, pc.instanceMethods)
4894           << " (struct method_list_t *)\n";
4895    if (pc.instanceMethods != 0)
4896      print_method_list32_t(pc.instanceMethods, info, "\t");
4897    outs() << "\t\t     classMethods " << format("0x%" PRIx32, pc.classMethods)
4898           << " (struct method_list_t *)\n";
4899    if (pc.classMethods != 0)
4900      print_method_list32_t(pc.classMethods, info, "\t");
4901    outs() << "\t  optionalInstanceMethods "
4902           << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
4903    outs() << "\t     optionalClassMethods "
4904           << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
4905    outs() << "\t       instanceProperties "
4906           << format("0x%" PRIx32, pc.instanceProperties) << "\n";
4907    p += sizeof(uint32_t);
4908    offset += sizeof(uint32_t);
4909  }
4910}
4911
4912static void print_indent(uint32_t indent) {
4913  for (uint32_t i = 0; i < indent;) {
4914    if (indent - i >= 8) {
4915      outs() << "\t";
4916      i += 8;
4917    } else {
4918      for (uint32_t j = i; j < indent; j++)
4919        outs() << " ";
4920      return;
4921    }
4922  }
4923}
4924
4925static bool print_method_description_list(uint32_t p, uint32_t indent,
4926                                          struct DisassembleInfo *info) {
4927  uint32_t offset, left, xleft;
4928  SectionRef S;
4929  struct objc_method_description_list_t mdl;
4930  struct objc_method_description_t md;
4931  const char *r, *list, *name;
4932  int32_t i;
4933
4934  r = get_pointer_32(p, offset, left, S, info, true);
4935  if (r == nullptr)
4936    return true;
4937
4938  outs() << "\n";
4939  if (left > sizeof(struct objc_method_description_list_t)) {
4940    memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
4941  } else {
4942    print_indent(indent);
4943    outs() << " objc_method_description_list extends past end of the section\n";
4944    memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
4945    memcpy(&mdl, r, left);
4946  }
4947  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4948    swapStruct(mdl);
4949
4950  print_indent(indent);
4951  outs() << "        count " << mdl.count << "\n";
4952
4953  list = r + sizeof(struct objc_method_description_list_t);
4954  for (i = 0; i < mdl.count; i++) {
4955    if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
4956      print_indent(indent);
4957      outs() << " remaining list entries extend past the of the section\n";
4958      break;
4959    }
4960    print_indent(indent);
4961    outs() << "        list[" << i << "]\n";
4962    memcpy(&md, list + i * sizeof(struct objc_method_description_t),
4963           sizeof(struct objc_method_description_t));
4964    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4965      swapStruct(md);
4966
4967    print_indent(indent);
4968    outs() << "             name " << format("0x%08" PRIx32, md.name);
4969    if (info->verbose) {
4970      name = get_pointer_32(md.name, offset, xleft, S, info, true);
4971      if (name != nullptr)
4972        outs() << format(" %.*s", xleft, name);
4973      else
4974        outs() << " (not in an __OBJC section)";
4975    }
4976    outs() << "\n";
4977
4978    print_indent(indent);
4979    outs() << "            types " << format("0x%08" PRIx32, md.types);
4980    if (info->verbose) {
4981      name = get_pointer_32(md.types, offset, xleft, S, info, true);
4982      if (name != nullptr)
4983        outs() << format(" %.*s", xleft, name);
4984      else
4985        outs() << " (not in an __OBJC section)";
4986    }
4987    outs() << "\n";
4988  }
4989  return false;
4990}
4991
4992static bool print_protocol_list(uint32_t p, uint32_t indent,
4993                                struct DisassembleInfo *info);
4994
4995static bool print_protocol(uint32_t p, uint32_t indent,
4996                           struct DisassembleInfo *info) {
4997  uint32_t offset, left;
4998  SectionRef S;
4999  struct objc_protocol_t protocol;
5000  const char *r, *name;
5001
5002  r = get_pointer_32(p, offset, left, S, info, true);
5003  if (r == nullptr)
5004    return true;
5005
5006  outs() << "\n";
5007  if (left >= sizeof(struct objc_protocol_t)) {
5008    memcpy(&protocol, r, sizeof(struct objc_protocol_t));
5009  } else {
5010    print_indent(indent);
5011    outs() << "            Protocol extends past end of the section\n";
5012    memset(&protocol, '\0', sizeof(struct objc_protocol_t));
5013    memcpy(&protocol, r, left);
5014  }
5015  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5016    swapStruct(protocol);
5017
5018  print_indent(indent);
5019  outs() << "              isa " << format("0x%08" PRIx32, protocol.isa)
5020         << "\n";
5021
5022  print_indent(indent);
5023  outs() << "    protocol_name "
5024         << format("0x%08" PRIx32, protocol.protocol_name);
5025  if (info->verbose) {
5026    name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
5027    if (name != nullptr)
5028      outs() << format(" %.*s", left, name);
5029    else
5030      outs() << " (not in an __OBJC section)";
5031  }
5032  outs() << "\n";
5033
5034  print_indent(indent);
5035  outs() << "    protocol_list "
5036         << format("0x%08" PRIx32, protocol.protocol_list);
5037  if (print_protocol_list(protocol.protocol_list, indent + 4, info))
5038    outs() << " (not in an __OBJC section)\n";
5039
5040  print_indent(indent);
5041  outs() << " instance_methods "
5042         << format("0x%08" PRIx32, protocol.instance_methods);
5043  if (print_method_description_list(protocol.instance_methods, indent, info))
5044    outs() << " (not in an __OBJC section)\n";
5045
5046  print_indent(indent);
5047  outs() << "    class_methods "
5048         << format("0x%08" PRIx32, protocol.class_methods);
5049  if (print_method_description_list(protocol.class_methods, indent, info))
5050    outs() << " (not in an __OBJC section)\n";
5051
5052  return false;
5053}
5054
5055static bool print_protocol_list(uint32_t p, uint32_t indent,
5056                                struct DisassembleInfo *info) {
5057  uint32_t offset, left, l;
5058  SectionRef S;
5059  struct objc_protocol_list_t protocol_list;
5060  const char *r, *list;
5061  int32_t i;
5062
5063  r = get_pointer_32(p, offset, left, S, info, true);
5064  if (r == nullptr)
5065    return true;
5066
5067  outs() << "\n";
5068  if (left > sizeof(struct objc_protocol_list_t)) {
5069    memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
5070  } else {
5071    outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
5072    memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
5073    memcpy(&protocol_list, r, left);
5074  }
5075  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5076    swapStruct(protocol_list);
5077
5078  print_indent(indent);
5079  outs() << "         next " << format("0x%08" PRIx32, protocol_list.next)
5080         << "\n";
5081  print_indent(indent);
5082  outs() << "        count " << protocol_list.count << "\n";
5083
5084  list = r + sizeof(struct objc_protocol_list_t);
5085  for (i = 0; i < protocol_list.count; i++) {
5086    if ((i + 1) * sizeof(uint32_t) > left) {
5087      outs() << "\t\t remaining list entries extend past the of the section\n";
5088      break;
5089    }
5090    memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
5091    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5092      sys::swapByteOrder(l);
5093
5094    print_indent(indent);
5095    outs() << "      list[" << i << "] " << format("0x%08" PRIx32, l);
5096    if (print_protocol(l, indent, info))
5097      outs() << "(not in an __OBJC section)\n";
5098  }
5099  return false;
5100}
5101
5102static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
5103  struct ivar_list64_t il;
5104  struct ivar64_t i;
5105  const char *r;
5106  uint32_t offset, xoffset, left, j;
5107  SectionRef S, xS;
5108  const char *name, *sym_name, *ivar_offset_p;
5109  uint64_t ivar_offset, n_value;
5110
5111  r = get_pointer_64(p, offset, left, S, info);
5112  if (r == nullptr)
5113    return;
5114  memset(&il, '\0', sizeof(struct ivar_list64_t));
5115  if (left < sizeof(struct ivar_list64_t)) {
5116    memcpy(&il, r, left);
5117    outs() << "   (ivar_list_t entends past the end of the section)\n";
5118  } else
5119    memcpy(&il, r, sizeof(struct ivar_list64_t));
5120  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5121    swapStruct(il);
5122  outs() << "                    entsize " << il.entsize << "\n";
5123  outs() << "                      count " << il.count << "\n";
5124
5125  p += sizeof(struct ivar_list64_t);
5126  offset += sizeof(struct ivar_list64_t);
5127  for (j = 0; j < il.count; j++) {
5128    r = get_pointer_64(p, offset, left, S, info);
5129    if (r == nullptr)
5130      return;
5131    memset(&i, '\0', sizeof(struct ivar64_t));
5132    if (left < sizeof(struct ivar64_t)) {
5133      memcpy(&i, r, left);
5134      outs() << "   (ivar_t entends past the end of the section)\n";
5135    } else
5136      memcpy(&i, r, sizeof(struct ivar64_t));
5137    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5138      swapStruct(i);
5139
5140    outs() << "\t\t\t   offset ";
5141    sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
5142                             info, n_value, i.offset);
5143    if (n_value != 0) {
5144      if (info->verbose && sym_name != nullptr)
5145        outs() << sym_name;
5146      else
5147        outs() << format("0x%" PRIx64, n_value);
5148      if (i.offset != 0)
5149        outs() << " + " << format("0x%" PRIx64, i.offset);
5150    } else
5151      outs() << format("0x%" PRIx64, i.offset);
5152    ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
5153    if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5154      memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5155      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5156        sys::swapByteOrder(ivar_offset);
5157      outs() << " " << ivar_offset << "\n";
5158    } else
5159      outs() << "\n";
5160
5161    outs() << "\t\t\t     name ";
5162    sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
5163                             n_value, i.name);
5164    if (n_value != 0) {
5165      if (info->verbose && sym_name != nullptr)
5166        outs() << sym_name;
5167      else
5168        outs() << format("0x%" PRIx64, n_value);
5169      if (i.name != 0)
5170        outs() << " + " << format("0x%" PRIx64, i.name);
5171    } else
5172      outs() << format("0x%" PRIx64, i.name);
5173    name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
5174    if (name != nullptr)
5175      outs() << format(" %.*s", left, name);
5176    outs() << "\n";
5177
5178    outs() << "\t\t\t     type ";
5179    sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
5180                             n_value, i.name);
5181    name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
5182    if (n_value != 0) {
5183      if (info->verbose && sym_name != nullptr)
5184        outs() << sym_name;
5185      else
5186        outs() << format("0x%" PRIx64, n_value);
5187      if (i.type != 0)
5188        outs() << " + " << format("0x%" PRIx64, i.type);
5189    } else
5190      outs() << format("0x%" PRIx64, i.type);
5191    if (name != nullptr)
5192      outs() << format(" %.*s", left, name);
5193    outs() << "\n";
5194
5195    outs() << "\t\t\talignment " << i.alignment << "\n";
5196    outs() << "\t\t\t     size " << i.size << "\n";
5197
5198    p += sizeof(struct ivar64_t);
5199    offset += sizeof(struct ivar64_t);
5200  }
5201}
5202
5203static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
5204  struct ivar_list32_t il;
5205  struct ivar32_t i;
5206  const char *r;
5207  uint32_t offset, xoffset, left, j;
5208  SectionRef S, xS;
5209  const char *name, *ivar_offset_p;
5210  uint32_t ivar_offset;
5211
5212  r = get_pointer_32(p, offset, left, S, info);
5213  if (r == nullptr)
5214    return;
5215  memset(&il, '\0', sizeof(struct ivar_list32_t));
5216  if (left < sizeof(struct ivar_list32_t)) {
5217    memcpy(&il, r, left);
5218    outs() << "   (ivar_list_t entends past the end of the section)\n";
5219  } else
5220    memcpy(&il, r, sizeof(struct ivar_list32_t));
5221  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5222    swapStruct(il);
5223  outs() << "                    entsize " << il.entsize << "\n";
5224  outs() << "                      count " << il.count << "\n";
5225
5226  p += sizeof(struct ivar_list32_t);
5227  offset += sizeof(struct ivar_list32_t);
5228  for (j = 0; j < il.count; j++) {
5229    r = get_pointer_32(p, offset, left, S, info);
5230    if (r == nullptr)
5231      return;
5232    memset(&i, '\0', sizeof(struct ivar32_t));
5233    if (left < sizeof(struct ivar32_t)) {
5234      memcpy(&i, r, left);
5235      outs() << "   (ivar_t entends past the end of the section)\n";
5236    } else
5237      memcpy(&i, r, sizeof(struct ivar32_t));
5238    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5239      swapStruct(i);
5240
5241    outs() << "\t\t\t   offset " << format("0x%" PRIx32, i.offset);
5242    ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
5243    if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5244      memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5245      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5246        sys::swapByteOrder(ivar_offset);
5247      outs() << " " << ivar_offset << "\n";
5248    } else
5249      outs() << "\n";
5250
5251    outs() << "\t\t\t     name " << format("0x%" PRIx32, i.name);
5252    name = get_pointer_32(i.name, xoffset, left, xS, info);
5253    if (name != nullptr)
5254      outs() << format(" %.*s", left, name);
5255    outs() << "\n";
5256
5257    outs() << "\t\t\t     type " << format("0x%" PRIx32, i.type);
5258    name = get_pointer_32(i.type, xoffset, left, xS, info);
5259    if (name != nullptr)
5260      outs() << format(" %.*s", left, name);
5261    outs() << "\n";
5262
5263    outs() << "\t\t\talignment " << i.alignment << "\n";
5264    outs() << "\t\t\t     size " << i.size << "\n";
5265
5266    p += sizeof(struct ivar32_t);
5267    offset += sizeof(struct ivar32_t);
5268  }
5269}
5270
5271static void print_objc_property_list64(uint64_t p,
5272                                       struct DisassembleInfo *info) {
5273  struct objc_property_list64 opl;
5274  struct objc_property64 op;
5275  const char *r;
5276  uint32_t offset, xoffset, left, j;
5277  SectionRef S, xS;
5278  const char *name, *sym_name;
5279  uint64_t n_value;
5280
5281  r = get_pointer_64(p, offset, left, S, info);
5282  if (r == nullptr)
5283    return;
5284  memset(&opl, '\0', sizeof(struct objc_property_list64));
5285  if (left < sizeof(struct objc_property_list64)) {
5286    memcpy(&opl, r, left);
5287    outs() << "   (objc_property_list entends past the end of the section)\n";
5288  } else
5289    memcpy(&opl, r, sizeof(struct objc_property_list64));
5290  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5291    swapStruct(opl);
5292  outs() << "                    entsize " << opl.entsize << "\n";
5293  outs() << "                      count " << opl.count << "\n";
5294
5295  p += sizeof(struct objc_property_list64);
5296  offset += sizeof(struct objc_property_list64);
5297  for (j = 0; j < opl.count; j++) {
5298    r = get_pointer_64(p, offset, left, S, info);
5299    if (r == nullptr)
5300      return;
5301    memset(&op, '\0', sizeof(struct objc_property64));
5302    if (left < sizeof(struct objc_property64)) {
5303      memcpy(&op, r, left);
5304      outs() << "   (objc_property entends past the end of the section)\n";
5305    } else
5306      memcpy(&op, r, sizeof(struct objc_property64));
5307    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5308      swapStruct(op);
5309
5310    outs() << "\t\t\t     name ";
5311    sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
5312                             info, n_value, op.name);
5313    if (n_value != 0) {
5314      if (info->verbose && sym_name != nullptr)
5315        outs() << sym_name;
5316      else
5317        outs() << format("0x%" PRIx64, n_value);
5318      if (op.name != 0)
5319        outs() << " + " << format("0x%" PRIx64, op.name);
5320    } else
5321      outs() << format("0x%" PRIx64, op.name);
5322    name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
5323    if (name != nullptr)
5324      outs() << format(" %.*s", left, name);
5325    outs() << "\n";
5326
5327    outs() << "\t\t\tattributes ";
5328    sym_name =
5329        get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
5330                      info, n_value, op.attributes);
5331    if (n_value != 0) {
5332      if (info->verbose && sym_name != nullptr)
5333        outs() << sym_name;
5334      else
5335        outs() << format("0x%" PRIx64, n_value);
5336      if (op.attributes != 0)
5337        outs() << " + " << format("0x%" PRIx64, op.attributes);
5338    } else
5339      outs() << format("0x%" PRIx64, op.attributes);
5340    name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
5341    if (name != nullptr)
5342      outs() << format(" %.*s", left, name);
5343    outs() << "\n";
5344
5345    p += sizeof(struct objc_property64);
5346    offset += sizeof(struct objc_property64);
5347  }
5348}
5349
5350static void print_objc_property_list32(uint32_t p,
5351                                       struct DisassembleInfo *info) {
5352  struct objc_property_list32 opl;
5353  struct objc_property32 op;
5354  const char *r;
5355  uint32_t offset, xoffset, left, j;
5356  SectionRef S, xS;
5357  const char *name;
5358
5359  r = get_pointer_32(p, offset, left, S, info);
5360  if (r == nullptr)
5361    return;
5362  memset(&opl, '\0', sizeof(struct objc_property_list32));
5363  if (left < sizeof(struct objc_property_list32)) {
5364    memcpy(&opl, r, left);
5365    outs() << "   (objc_property_list entends past the end of the section)\n";
5366  } else
5367    memcpy(&opl, r, sizeof(struct objc_property_list32));
5368  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5369    swapStruct(opl);
5370  outs() << "                    entsize " << opl.entsize << "\n";
5371  outs() << "                      count " << opl.count << "\n";
5372
5373  p += sizeof(struct objc_property_list32);
5374  offset += sizeof(struct objc_property_list32);
5375  for (j = 0; j < opl.count; j++) {
5376    r = get_pointer_32(p, offset, left, S, info);
5377    if (r == nullptr)
5378      return;
5379    memset(&op, '\0', sizeof(struct objc_property32));
5380    if (left < sizeof(struct objc_property32)) {
5381      memcpy(&op, r, left);
5382      outs() << "   (objc_property entends past the end of the section)\n";
5383    } else
5384      memcpy(&op, r, sizeof(struct objc_property32));
5385    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5386      swapStruct(op);
5387
5388    outs() << "\t\t\t     name " << format("0x%" PRIx32, op.name);
5389    name = get_pointer_32(op.name, xoffset, left, xS, info);
5390    if (name != nullptr)
5391      outs() << format(" %.*s", left, name);
5392    outs() << "\n";
5393
5394    outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
5395    name = get_pointer_32(op.attributes, xoffset, left, xS, info);
5396    if (name != nullptr)
5397      outs() << format(" %.*s", left, name);
5398    outs() << "\n";
5399
5400    p += sizeof(struct objc_property32);
5401    offset += sizeof(struct objc_property32);
5402  }
5403}
5404
5405static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
5406                               bool &is_meta_class) {
5407  struct class_ro64_t cro;
5408  const char *r;
5409  uint32_t offset, xoffset, left;
5410  SectionRef S, xS;
5411  const char *name, *sym_name;
5412  uint64_t n_value;
5413
5414  r = get_pointer_64(p, offset, left, S, info);
5415  if (r == nullptr || left < sizeof(struct class_ro64_t))
5416    return false;
5417  memcpy(&cro, r, sizeof(struct class_ro64_t));
5418  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5419    swapStruct(cro);
5420  outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5421  if (cro.flags & RO_META)
5422    outs() << " RO_META";
5423  if (cro.flags & RO_ROOT)
5424    outs() << " RO_ROOT";
5425  if (cro.flags & RO_HAS_CXX_STRUCTORS)
5426    outs() << " RO_HAS_CXX_STRUCTORS";
5427  outs() << "\n";
5428  outs() << "            instanceStart " << cro.instanceStart << "\n";
5429  outs() << "             instanceSize " << cro.instanceSize << "\n";
5430  outs() << "                 reserved " << format("0x%" PRIx32, cro.reserved)
5431         << "\n";
5432  outs() << "               ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
5433         << "\n";
5434  print_layout_map64(cro.ivarLayout, info);
5435
5436  outs() << "                     name ";
5437  sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
5438                           info, n_value, cro.name);
5439  if (n_value != 0) {
5440    if (info->verbose && sym_name != nullptr)
5441      outs() << sym_name;
5442    else
5443      outs() << format("0x%" PRIx64, n_value);
5444    if (cro.name != 0)
5445      outs() << " + " << format("0x%" PRIx64, cro.name);
5446  } else
5447    outs() << format("0x%" PRIx64, cro.name);
5448  name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
5449  if (name != nullptr)
5450    outs() << format(" %.*s", left, name);
5451  outs() << "\n";
5452
5453  outs() << "              baseMethods ";
5454  sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
5455                           S, info, n_value, cro.baseMethods);
5456  if (n_value != 0) {
5457    if (info->verbose && sym_name != nullptr)
5458      outs() << sym_name;
5459    else
5460      outs() << format("0x%" PRIx64, n_value);
5461    if (cro.baseMethods != 0)
5462      outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
5463  } else
5464    outs() << format("0x%" PRIx64, cro.baseMethods);
5465  outs() << " (struct method_list_t *)\n";
5466  if (cro.baseMethods + n_value != 0)
5467    print_method_list64_t(cro.baseMethods + n_value, info, "");
5468
5469  outs() << "            baseProtocols ";
5470  sym_name =
5471      get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
5472                    info, n_value, cro.baseProtocols);
5473  if (n_value != 0) {
5474    if (info->verbose && sym_name != nullptr)
5475      outs() << sym_name;
5476    else
5477      outs() << format("0x%" PRIx64, n_value);
5478    if (cro.baseProtocols != 0)
5479      outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
5480  } else
5481    outs() << format("0x%" PRIx64, cro.baseProtocols);
5482  outs() << "\n";
5483  if (cro.baseProtocols + n_value != 0)
5484    print_protocol_list64_t(cro.baseProtocols + n_value, info);
5485
5486  outs() << "                    ivars ";
5487  sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
5488                           info, n_value, cro.ivars);
5489  if (n_value != 0) {
5490    if (info->verbose && sym_name != nullptr)
5491      outs() << sym_name;
5492    else
5493      outs() << format("0x%" PRIx64, n_value);
5494    if (cro.ivars != 0)
5495      outs() << " + " << format("0x%" PRIx64, cro.ivars);
5496  } else
5497    outs() << format("0x%" PRIx64, cro.ivars);
5498  outs() << "\n";
5499  if (cro.ivars + n_value != 0)
5500    print_ivar_list64_t(cro.ivars + n_value, info);
5501
5502  outs() << "           weakIvarLayout ";
5503  sym_name =
5504      get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
5505                    info, n_value, cro.weakIvarLayout);
5506  if (n_value != 0) {
5507    if (info->verbose && sym_name != nullptr)
5508      outs() << sym_name;
5509    else
5510      outs() << format("0x%" PRIx64, n_value);
5511    if (cro.weakIvarLayout != 0)
5512      outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
5513  } else
5514    outs() << format("0x%" PRIx64, cro.weakIvarLayout);
5515  outs() << "\n";
5516  print_layout_map64(cro.weakIvarLayout + n_value, info);
5517
5518  outs() << "           baseProperties ";
5519  sym_name =
5520      get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
5521                    info, n_value, cro.baseProperties);
5522  if (n_value != 0) {
5523    if (info->verbose && sym_name != nullptr)
5524      outs() << sym_name;
5525    else
5526      outs() << format("0x%" PRIx64, n_value);
5527    if (cro.baseProperties != 0)
5528      outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
5529  } else
5530    outs() << format("0x%" PRIx64, cro.baseProperties);
5531  outs() << "\n";
5532  if (cro.baseProperties + n_value != 0)
5533    print_objc_property_list64(cro.baseProperties + n_value, info);
5534
5535  is_meta_class = (cro.flags & RO_META) != 0;
5536  return true;
5537}
5538
5539static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
5540                               bool &is_meta_class) {
5541  struct class_ro32_t cro;
5542  const char *r;
5543  uint32_t offset, xoffset, left;
5544  SectionRef S, xS;
5545  const char *name;
5546
5547  r = get_pointer_32(p, offset, left, S, info);
5548  if (r == nullptr)
5549    return false;
5550  memset(&cro, '\0', sizeof(struct class_ro32_t));
5551  if (left < sizeof(struct class_ro32_t)) {
5552    memcpy(&cro, r, left);
5553    outs() << "   (class_ro_t entends past the end of the section)\n";
5554  } else
5555    memcpy(&cro, r, sizeof(struct class_ro32_t));
5556  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5557    swapStruct(cro);
5558  outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5559  if (cro.flags & RO_META)
5560    outs() << " RO_META";
5561  if (cro.flags & RO_ROOT)
5562    outs() << " RO_ROOT";
5563  if (cro.flags & RO_HAS_CXX_STRUCTORS)
5564    outs() << " RO_HAS_CXX_STRUCTORS";
5565  outs() << "\n";
5566  outs() << "            instanceStart " << cro.instanceStart << "\n";
5567  outs() << "             instanceSize " << cro.instanceSize << "\n";
5568  outs() << "               ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
5569         << "\n";
5570  print_layout_map32(cro.ivarLayout, info);
5571
5572  outs() << "                     name " << format("0x%" PRIx32, cro.name);
5573  name = get_pointer_32(cro.name, xoffset, left, xS, info);
5574  if (name != nullptr)
5575    outs() << format(" %.*s", left, name);
5576  outs() << "\n";
5577
5578  outs() << "              baseMethods "
5579         << format("0x%" PRIx32, cro.baseMethods)
5580         << " (struct method_list_t *)\n";
5581  if (cro.baseMethods != 0)
5582    print_method_list32_t(cro.baseMethods, info, "");
5583
5584  outs() << "            baseProtocols "
5585         << format("0x%" PRIx32, cro.baseProtocols) << "\n";
5586  if (cro.baseProtocols != 0)
5587    print_protocol_list32_t(cro.baseProtocols, info);
5588  outs() << "                    ivars " << format("0x%" PRIx32, cro.ivars)
5589         << "\n";
5590  if (cro.ivars != 0)
5591    print_ivar_list32_t(cro.ivars, info);
5592  outs() << "           weakIvarLayout "
5593         << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
5594  print_layout_map32(cro.weakIvarLayout, info);
5595  outs() << "           baseProperties "
5596         << format("0x%" PRIx32, cro.baseProperties) << "\n";
5597  if (cro.baseProperties != 0)
5598    print_objc_property_list32(cro.baseProperties, info);
5599  is_meta_class = (cro.flags & RO_META) != 0;
5600  return true;
5601}
5602
5603static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
5604  struct class64_t c;
5605  const char *r;
5606  uint32_t offset, left;
5607  SectionRef S;
5608  const char *name;
5609  uint64_t isa_n_value, n_value;
5610
5611  r = get_pointer_64(p, offset, left, S, info);
5612  if (r == nullptr || left < sizeof(struct class64_t))
5613    return;
5614  memcpy(&c, r, sizeof(struct class64_t));
5615  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5616    swapStruct(c);
5617
5618  outs() << "           isa " << format("0x%" PRIx64, c.isa);
5619  name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
5620                       isa_n_value, c.isa);
5621  if (name != nullptr)
5622    outs() << " " << name;
5623  outs() << "\n";
5624
5625  outs() << "    superclass " << format("0x%" PRIx64, c.superclass);
5626  name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
5627                       n_value, c.superclass);
5628  if (name != nullptr)
5629    outs() << " " << name;
5630  else {
5631    name = get_dyld_bind_info_symbolname(S.getAddress() +
5632             offset + offsetof(struct class64_t, superclass), info);
5633    if (name != nullptr)
5634      outs() << " " << name;
5635  }
5636  outs() << "\n";
5637
5638  outs() << "         cache " << format("0x%" PRIx64, c.cache);
5639  name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
5640                       n_value, c.cache);
5641  if (name != nullptr)
5642    outs() << " " << name;
5643  outs() << "\n";
5644
5645  outs() << "        vtable " << format("0x%" PRIx64, c.vtable);
5646  name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
5647                       n_value, c.vtable);
5648  if (name != nullptr)
5649    outs() << " " << name;
5650  outs() << "\n";
5651
5652  name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
5653                       n_value, c.data);
5654  outs() << "          data ";
5655  if (n_value != 0) {
5656    if (info->verbose && name != nullptr)
5657      outs() << name;
5658    else
5659      outs() << format("0x%" PRIx64, n_value);
5660    if (c.data != 0)
5661      outs() << " + " << format("0x%" PRIx64, c.data);
5662  } else
5663    outs() << format("0x%" PRIx64, c.data);
5664  outs() << " (struct class_ro_t *)";
5665
5666  // This is a Swift class if some of the low bits of the pointer are set.
5667  if ((c.data + n_value) & 0x7)
5668    outs() << " Swift class";
5669  outs() << "\n";
5670  bool is_meta_class;
5671  if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
5672    return;
5673
5674  if (!is_meta_class &&
5675      c.isa + isa_n_value != p &&
5676      c.isa + isa_n_value != 0 &&
5677      info->depth < 100) {
5678      info->depth++;
5679      outs() << "Meta Class\n";
5680      print_class64_t(c.isa + isa_n_value, info);
5681  }
5682}
5683
5684static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
5685  struct class32_t c;
5686  const char *r;
5687  uint32_t offset, left;
5688  SectionRef S;
5689  const char *name;
5690
5691  r = get_pointer_32(p, offset, left, S, info);
5692  if (r == nullptr)
5693    return;
5694  memset(&c, '\0', sizeof(struct class32_t));
5695  if (left < sizeof(struct class32_t)) {
5696    memcpy(&c, r, left);
5697    outs() << "   (class_t entends past the end of the section)\n";
5698  } else
5699    memcpy(&c, r, sizeof(struct class32_t));
5700  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5701    swapStruct(c);
5702
5703  outs() << "           isa " << format("0x%" PRIx32, c.isa);
5704  name =
5705      get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
5706  if (name != nullptr)
5707    outs() << " " << name;
5708  outs() << "\n";
5709
5710  outs() << "    superclass " << format("0x%" PRIx32, c.superclass);
5711  name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
5712                       c.superclass);
5713  if (name != nullptr)
5714    outs() << " " << name;
5715  outs() << "\n";
5716
5717  outs() << "         cache " << format("0x%" PRIx32, c.cache);
5718  name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
5719                       c.cache);
5720  if (name != nullptr)
5721    outs() << " " << name;
5722  outs() << "\n";
5723
5724  outs() << "        vtable " << format("0x%" PRIx32, c.vtable);
5725  name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
5726                       c.vtable);
5727  if (name != nullptr)
5728    outs() << " " << name;
5729  outs() << "\n";
5730
5731  name =
5732      get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
5733  outs() << "          data " << format("0x%" PRIx32, c.data)
5734         << " (struct class_ro_t *)";
5735
5736  // This is a Swift class if some of the low bits of the pointer are set.
5737  if (c.data & 0x3)
5738    outs() << " Swift class";
5739  outs() << "\n";
5740  bool is_meta_class;
5741  if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
5742    return;
5743
5744  if (!is_meta_class) {
5745    outs() << "Meta Class\n";
5746    print_class32_t(c.isa, info);
5747  }
5748}
5749
5750static void print_objc_class_t(struct objc_class_t *objc_class,
5751                               struct DisassembleInfo *info) {
5752  uint32_t offset, left, xleft;
5753  const char *name, *p, *ivar_list;
5754  SectionRef S;
5755  int32_t i;
5756  struct objc_ivar_list_t objc_ivar_list;
5757  struct objc_ivar_t ivar;
5758
5759  outs() << "\t\t      isa " << format("0x%08" PRIx32, objc_class->isa);
5760  if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
5761    name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
5762    if (name != nullptr)
5763      outs() << format(" %.*s", left, name);
5764    else
5765      outs() << " (not in an __OBJC section)";
5766  }
5767  outs() << "\n";
5768
5769  outs() << "\t      super_class "
5770         << format("0x%08" PRIx32, objc_class->super_class);
5771  if (info->verbose) {
5772    name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
5773    if (name != nullptr)
5774      outs() << format(" %.*s", left, name);
5775    else
5776      outs() << " (not in an __OBJC section)";
5777  }
5778  outs() << "\n";
5779
5780  outs() << "\t\t     name " << format("0x%08" PRIx32, objc_class->name);
5781  if (info->verbose) {
5782    name = get_pointer_32(objc_class->name, offset, left, S, info, true);
5783    if (name != nullptr)
5784      outs() << format(" %.*s", left, name);
5785    else
5786      outs() << " (not in an __OBJC section)";
5787  }
5788  outs() << "\n";
5789
5790  outs() << "\t\t  version " << format("0x%08" PRIx32, objc_class->version)
5791         << "\n";
5792
5793  outs() << "\t\t     info " << format("0x%08" PRIx32, objc_class->info);
5794  if (info->verbose) {
5795    if (CLS_GETINFO(objc_class, CLS_CLASS))
5796      outs() << " CLS_CLASS";
5797    else if (CLS_GETINFO(objc_class, CLS_META))
5798      outs() << " CLS_META";
5799  }
5800  outs() << "\n";
5801
5802  outs() << "\t    instance_size "
5803         << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
5804
5805  p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
5806  outs() << "\t\t    ivars " << format("0x%08" PRIx32, objc_class->ivars);
5807  if (p != nullptr) {
5808    if (left > sizeof(struct objc_ivar_list_t)) {
5809      outs() << "\n";
5810      memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
5811    } else {
5812      outs() << " (entends past the end of the section)\n";
5813      memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
5814      memcpy(&objc_ivar_list, p, left);
5815    }
5816    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5817      swapStruct(objc_ivar_list);
5818    outs() << "\t\t       ivar_count " << objc_ivar_list.ivar_count << "\n";
5819    ivar_list = p + sizeof(struct objc_ivar_list_t);
5820    for (i = 0; i < objc_ivar_list.ivar_count; i++) {
5821      if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
5822        outs() << "\t\t remaining ivar's extend past the of the section\n";
5823        break;
5824      }
5825      memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
5826             sizeof(struct objc_ivar_t));
5827      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5828        swapStruct(ivar);
5829
5830      outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
5831      if (info->verbose) {
5832        name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
5833        if (name != nullptr)
5834          outs() << format(" %.*s", xleft, name);
5835        else
5836          outs() << " (not in an __OBJC section)";
5837      }
5838      outs() << "\n";
5839
5840      outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
5841      if (info->verbose) {
5842        name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
5843        if (name != nullptr)
5844          outs() << format(" %.*s", xleft, name);
5845        else
5846          outs() << " (not in an __OBJC section)";
5847      }
5848      outs() << "\n";
5849
5850      outs() << "\t\t      ivar_offset "
5851             << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
5852    }
5853  } else {
5854    outs() << " (not in an __OBJC section)\n";
5855  }
5856
5857  outs() << "\t\t  methods " << format("0x%08" PRIx32, objc_class->methodLists);
5858  if (print_method_list(objc_class->methodLists, info))
5859    outs() << " (not in an __OBJC section)\n";
5860
5861  outs() << "\t\t    cache " << format("0x%08" PRIx32, objc_class->cache)
5862         << "\n";
5863
5864  outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
5865  if (print_protocol_list(objc_class->protocols, 16, info))
5866    outs() << " (not in an __OBJC section)\n";
5867}
5868
5869static void print_objc_objc_category_t(struct objc_category_t *objc_category,
5870                                       struct DisassembleInfo *info) {
5871  uint32_t offset, left;
5872  const char *name;
5873  SectionRef S;
5874
5875  outs() << "\t       category name "
5876         << format("0x%08" PRIx32, objc_category->category_name);
5877  if (info->verbose) {
5878    name = get_pointer_32(objc_category->category_name, offset, left, S, info,
5879                          true);
5880    if (name != nullptr)
5881      outs() << format(" %.*s", left, name);
5882    else
5883      outs() << " (not in an __OBJC section)";
5884  }
5885  outs() << "\n";
5886
5887  outs() << "\t\t  class name "
5888         << format("0x%08" PRIx32, objc_category->class_name);
5889  if (info->verbose) {
5890    name =
5891        get_pointer_32(objc_category->class_name, offset, left, S, info, true);
5892    if (name != nullptr)
5893      outs() << format(" %.*s", left, name);
5894    else
5895      outs() << " (not in an __OBJC section)";
5896  }
5897  outs() << "\n";
5898
5899  outs() << "\t    instance methods "
5900         << format("0x%08" PRIx32, objc_category->instance_methods);
5901  if (print_method_list(objc_category->instance_methods, info))
5902    outs() << " (not in an __OBJC section)\n";
5903
5904  outs() << "\t       class methods "
5905         << format("0x%08" PRIx32, objc_category->class_methods);
5906  if (print_method_list(objc_category->class_methods, info))
5907    outs() << " (not in an __OBJC section)\n";
5908}
5909
5910static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
5911  struct category64_t c;
5912  const char *r;
5913  uint32_t offset, xoffset, left;
5914  SectionRef S, xS;
5915  const char *name, *sym_name;
5916  uint64_t n_value;
5917
5918  r = get_pointer_64(p, offset, left, S, info);
5919  if (r == nullptr)
5920    return;
5921  memset(&c, '\0', sizeof(struct category64_t));
5922  if (left < sizeof(struct category64_t)) {
5923    memcpy(&c, r, left);
5924    outs() << "   (category_t entends past the end of the section)\n";
5925  } else
5926    memcpy(&c, r, sizeof(struct category64_t));
5927  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5928    swapStruct(c);
5929
5930  outs() << "              name ";
5931  sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
5932                           info, n_value, c.name);
5933  if (n_value != 0) {
5934    if (info->verbose && sym_name != nullptr)
5935      outs() << sym_name;
5936    else
5937      outs() << format("0x%" PRIx64, n_value);
5938    if (c.name != 0)
5939      outs() << " + " << format("0x%" PRIx64, c.name);
5940  } else
5941    outs() << format("0x%" PRIx64, c.name);
5942  name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
5943  if (name != nullptr)
5944    outs() << format(" %.*s", left, name);
5945  outs() << "\n";
5946
5947  outs() << "               cls ";
5948  sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
5949                           n_value, c.cls);
5950  if (n_value != 0) {
5951    if (info->verbose && sym_name != nullptr)
5952      outs() << sym_name;
5953    else
5954      outs() << format("0x%" PRIx64, n_value);
5955    if (c.cls != 0)
5956      outs() << " + " << format("0x%" PRIx64, c.cls);
5957  } else
5958    outs() << format("0x%" PRIx64, c.cls);
5959  outs() << "\n";
5960  if (c.cls + n_value != 0)
5961    print_class64_t(c.cls + n_value, info);
5962
5963  outs() << "   instanceMethods ";
5964  sym_name =
5965      get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
5966                    info, n_value, c.instanceMethods);
5967  if (n_value != 0) {
5968    if (info->verbose && sym_name != nullptr)
5969      outs() << sym_name;
5970    else
5971      outs() << format("0x%" PRIx64, n_value);
5972    if (c.instanceMethods != 0)
5973      outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
5974  } else
5975    outs() << format("0x%" PRIx64, c.instanceMethods);
5976  outs() << "\n";
5977  if (c.instanceMethods + n_value != 0)
5978    print_method_list64_t(c.instanceMethods + n_value, info, "");
5979
5980  outs() << "      classMethods ";
5981  sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
5982                           S, info, n_value, c.classMethods);
5983  if (n_value != 0) {
5984    if (info->verbose && sym_name != nullptr)
5985      outs() << sym_name;
5986    else
5987      outs() << format("0x%" PRIx64, n_value);
5988    if (c.classMethods != 0)
5989      outs() << " + " << format("0x%" PRIx64, c.classMethods);
5990  } else
5991    outs() << format("0x%" PRIx64, c.classMethods);
5992  outs() << "\n";
5993  if (c.classMethods + n_value != 0)
5994    print_method_list64_t(c.classMethods + n_value, info, "");
5995
5996  outs() << "         protocols ";
5997  sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
5998                           info, n_value, c.protocols);
5999  if (n_value != 0) {
6000    if (info->verbose && sym_name != nullptr)
6001      outs() << sym_name;
6002    else
6003      outs() << format("0x%" PRIx64, n_value);
6004    if (c.protocols != 0)
6005      outs() << " + " << format("0x%" PRIx64, c.protocols);
6006  } else
6007    outs() << format("0x%" PRIx64, c.protocols);
6008  outs() << "\n";
6009  if (c.protocols + n_value != 0)
6010    print_protocol_list64_t(c.protocols + n_value, info);
6011
6012  outs() << "instanceProperties ";
6013  sym_name =
6014      get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
6015                    S, info, n_value, c.instanceProperties);
6016  if (n_value != 0) {
6017    if (info->verbose && sym_name != nullptr)
6018      outs() << sym_name;
6019    else
6020      outs() << format("0x%" PRIx64, n_value);
6021    if (c.instanceProperties != 0)
6022      outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
6023  } else
6024    outs() << format("0x%" PRIx64, c.instanceProperties);
6025  outs() << "\n";
6026  if (c.instanceProperties + n_value != 0)
6027    print_objc_property_list64(c.instanceProperties + n_value, info);
6028}
6029
6030static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
6031  struct category32_t c;
6032  const char *r;
6033  uint32_t offset, left;
6034  SectionRef S, xS;
6035  const char *name;
6036
6037  r = get_pointer_32(p, offset, left, S, info);
6038  if (r == nullptr)
6039    return;
6040  memset(&c, '\0', sizeof(struct category32_t));
6041  if (left < sizeof(struct category32_t)) {
6042    memcpy(&c, r, left);
6043    outs() << "   (category_t entends past the end of the section)\n";
6044  } else
6045    memcpy(&c, r, sizeof(struct category32_t));
6046  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6047    swapStruct(c);
6048
6049  outs() << "              name " << format("0x%" PRIx32, c.name);
6050  name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
6051                       c.name);
6052  if (name)
6053    outs() << " " << name;
6054  outs() << "\n";
6055
6056  outs() << "               cls " << format("0x%" PRIx32, c.cls) << "\n";
6057  if (c.cls != 0)
6058    print_class32_t(c.cls, info);
6059  outs() << "   instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
6060         << "\n";
6061  if (c.instanceMethods != 0)
6062    print_method_list32_t(c.instanceMethods, info, "");
6063  outs() << "      classMethods " << format("0x%" PRIx32, c.classMethods)
6064         << "\n";
6065  if (c.classMethods != 0)
6066    print_method_list32_t(c.classMethods, info, "");
6067  outs() << "         protocols " << format("0x%" PRIx32, c.protocols) << "\n";
6068  if (c.protocols != 0)
6069    print_protocol_list32_t(c.protocols, info);
6070  outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
6071         << "\n";
6072  if (c.instanceProperties != 0)
6073    print_objc_property_list32(c.instanceProperties, info);
6074}
6075
6076static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
6077  uint32_t i, left, offset, xoffset;
6078  uint64_t p, n_value;
6079  struct message_ref64 mr;
6080  const char *name, *sym_name;
6081  const char *r;
6082  SectionRef xS;
6083
6084  if (S == SectionRef())
6085    return;
6086
6087  StringRef SectName;
6088  Expected<StringRef> SecNameOrErr = S.getName();
6089  if (SecNameOrErr)
6090    SectName = *SecNameOrErr;
6091  else
6092    consumeError(SecNameOrErr.takeError());
6093
6094  DataRefImpl Ref = S.getRawDataRefImpl();
6095  StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6096  outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6097  offset = 0;
6098  for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6099    p = S.getAddress() + i;
6100    r = get_pointer_64(p, offset, left, S, info);
6101    if (r == nullptr)
6102      return;
6103    memset(&mr, '\0', sizeof(struct message_ref64));
6104    if (left < sizeof(struct message_ref64)) {
6105      memcpy(&mr, r, left);
6106      outs() << "   (message_ref entends past the end of the section)\n";
6107    } else
6108      memcpy(&mr, r, sizeof(struct message_ref64));
6109    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6110      swapStruct(mr);
6111
6112    outs() << "  imp ";
6113    name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
6114                         n_value, mr.imp);
6115    if (n_value != 0) {
6116      outs() << format("0x%" PRIx64, n_value) << " ";
6117      if (mr.imp != 0)
6118        outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
6119    } else
6120      outs() << format("0x%" PRIx64, mr.imp) << " ";
6121    if (name != nullptr)
6122      outs() << " " << name;
6123    outs() << "\n";
6124
6125    outs() << "  sel ";
6126    sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
6127                             info, n_value, mr.sel);
6128    if (n_value != 0) {
6129      if (info->verbose && sym_name != nullptr)
6130        outs() << sym_name;
6131      else
6132        outs() << format("0x%" PRIx64, n_value);
6133      if (mr.sel != 0)
6134        outs() << " + " << format("0x%" PRIx64, mr.sel);
6135    } else
6136      outs() << format("0x%" PRIx64, mr.sel);
6137    name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
6138    if (name != nullptr)
6139      outs() << format(" %.*s", left, name);
6140    outs() << "\n";
6141
6142    offset += sizeof(struct message_ref64);
6143  }
6144}
6145
6146static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
6147  uint32_t i, left, offset, xoffset, p;
6148  struct message_ref32 mr;
6149  const char *name, *r;
6150  SectionRef xS;
6151
6152  if (S == SectionRef())
6153    return;
6154
6155  StringRef SectName;
6156  Expected<StringRef> SecNameOrErr = S.getName();
6157  if (SecNameOrErr)
6158    SectName = *SecNameOrErr;
6159  else
6160    consumeError(SecNameOrErr.takeError());
6161
6162  DataRefImpl Ref = S.getRawDataRefImpl();
6163  StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6164  outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6165  offset = 0;
6166  for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6167    p = S.getAddress() + i;
6168    r = get_pointer_32(p, offset, left, S, info);
6169    if (r == nullptr)
6170      return;
6171    memset(&mr, '\0', sizeof(struct message_ref32));
6172    if (left < sizeof(struct message_ref32)) {
6173      memcpy(&mr, r, left);
6174      outs() << "   (message_ref entends past the end of the section)\n";
6175    } else
6176      memcpy(&mr, r, sizeof(struct message_ref32));
6177    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6178      swapStruct(mr);
6179
6180    outs() << "  imp " << format("0x%" PRIx32, mr.imp);
6181    name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
6182                         mr.imp);
6183    if (name != nullptr)
6184      outs() << " " << name;
6185    outs() << "\n";
6186
6187    outs() << "  sel " << format("0x%" PRIx32, mr.sel);
6188    name = get_pointer_32(mr.sel, xoffset, left, xS, info);
6189    if (name != nullptr)
6190      outs() << " " << name;
6191    outs() << "\n";
6192
6193    offset += sizeof(struct message_ref32);
6194  }
6195}
6196
6197static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
6198  uint32_t left, offset, swift_version;
6199  uint64_t p;
6200  struct objc_image_info64 o;
6201  const char *r;
6202
6203  if (S == SectionRef())
6204    return;
6205
6206  StringRef SectName;
6207  Expected<StringRef> SecNameOrErr = S.getName();
6208  if (SecNameOrErr)
6209    SectName = *SecNameOrErr;
6210  else
6211    consumeError(SecNameOrErr.takeError());
6212
6213  DataRefImpl Ref = S.getRawDataRefImpl();
6214  StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6215  outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6216  p = S.getAddress();
6217  r = get_pointer_64(p, offset, left, S, info);
6218  if (r == nullptr)
6219    return;
6220  memset(&o, '\0', sizeof(struct objc_image_info64));
6221  if (left < sizeof(struct objc_image_info64)) {
6222    memcpy(&o, r, left);
6223    outs() << "   (objc_image_info entends past the end of the section)\n";
6224  } else
6225    memcpy(&o, r, sizeof(struct objc_image_info64));
6226  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6227    swapStruct(o);
6228  outs() << "  version " << o.version << "\n";
6229  outs() << "    flags " << format("0x%" PRIx32, o.flags);
6230  if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6231    outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6232  if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6233    outs() << " OBJC_IMAGE_SUPPORTS_GC";
6234  if (o.flags & OBJC_IMAGE_IS_SIMULATED)
6235    outs() << " OBJC_IMAGE_IS_SIMULATED";
6236  if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES)
6237    outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
6238  swift_version = (o.flags >> 8) & 0xff;
6239  if (swift_version != 0) {
6240    if (swift_version == 1)
6241      outs() << " Swift 1.0";
6242    else if (swift_version == 2)
6243      outs() << " Swift 1.1";
6244    else if(swift_version == 3)
6245      outs() << " Swift 2.0";
6246    else if(swift_version == 4)
6247      outs() << " Swift 3.0";
6248    else if(swift_version == 5)
6249      outs() << " Swift 4.0";
6250    else if(swift_version == 6)
6251      outs() << " Swift 4.1/Swift 4.2";
6252    else if(swift_version == 7)
6253      outs() << " Swift 5 or later";
6254    else
6255      outs() << " unknown future Swift version (" << swift_version << ")";
6256  }
6257  outs() << "\n";
6258}
6259
6260static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
6261  uint32_t left, offset, swift_version, p;
6262  struct objc_image_info32 o;
6263  const char *r;
6264
6265  if (S == SectionRef())
6266    return;
6267
6268  StringRef SectName;
6269  Expected<StringRef> SecNameOrErr = S.getName();
6270  if (SecNameOrErr)
6271    SectName = *SecNameOrErr;
6272  else
6273    consumeError(SecNameOrErr.takeError());
6274
6275  DataRefImpl Ref = S.getRawDataRefImpl();
6276  StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6277  outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6278  p = S.getAddress();
6279  r = get_pointer_32(p, offset, left, S, info);
6280  if (r == nullptr)
6281    return;
6282  memset(&o, '\0', sizeof(struct objc_image_info32));
6283  if (left < sizeof(struct objc_image_info32)) {
6284    memcpy(&o, r, left);
6285    outs() << "   (objc_image_info entends past the end of the section)\n";
6286  } else
6287    memcpy(&o, r, sizeof(struct objc_image_info32));
6288  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6289    swapStruct(o);
6290  outs() << "  version " << o.version << "\n";
6291  outs() << "    flags " << format("0x%" PRIx32, o.flags);
6292  if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6293    outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6294  if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6295    outs() << " OBJC_IMAGE_SUPPORTS_GC";
6296  swift_version = (o.flags >> 8) & 0xff;
6297  if (swift_version != 0) {
6298    if (swift_version == 1)
6299      outs() << " Swift 1.0";
6300    else if (swift_version == 2)
6301      outs() << " Swift 1.1";
6302    else if(swift_version == 3)
6303      outs() << " Swift 2.0";
6304    else if(swift_version == 4)
6305      outs() << " Swift 3.0";
6306    else if(swift_version == 5)
6307      outs() << " Swift 4.0";
6308    else if(swift_version == 6)
6309      outs() << " Swift 4.1/Swift 4.2";
6310    else if(swift_version == 7)
6311      outs() << " Swift 5 or later";
6312    else
6313      outs() << " unknown future Swift version (" << swift_version << ")";
6314  }
6315  outs() << "\n";
6316}
6317
6318static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
6319  uint32_t left, offset, p;
6320  struct imageInfo_t o;
6321  const char *r;
6322
6323  StringRef SectName;
6324  Expected<StringRef> SecNameOrErr = S.getName();
6325  if (SecNameOrErr)
6326    SectName = *SecNameOrErr;
6327  else
6328    consumeError(SecNameOrErr.takeError());
6329
6330  DataRefImpl Ref = S.getRawDataRefImpl();
6331  StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6332  outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6333  p = S.getAddress();
6334  r = get_pointer_32(p, offset, left, S, info);
6335  if (r == nullptr)
6336    return;
6337  memset(&o, '\0', sizeof(struct imageInfo_t));
6338  if (left < sizeof(struct imageInfo_t)) {
6339    memcpy(&o, r, left);
6340    outs() << " (imageInfo entends past the end of the section)\n";
6341  } else
6342    memcpy(&o, r, sizeof(struct imageInfo_t));
6343  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6344    swapStruct(o);
6345  outs() << "  version " << o.version << "\n";
6346  outs() << "    flags " << format("0x%" PRIx32, o.flags);
6347  if (o.flags & 0x1)
6348    outs() << "  F&C";
6349  if (o.flags & 0x2)
6350    outs() << " GC";
6351  if (o.flags & 0x4)
6352    outs() << " GC-only";
6353  else
6354    outs() << " RR";
6355  outs() << "\n";
6356}
6357
6358static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
6359  SymbolAddressMap AddrMap;
6360  if (verbose)
6361    CreateSymbolAddressMap(O, &AddrMap);
6362
6363  std::vector<SectionRef> Sections;
6364  append_range(Sections, O->sections());
6365
6366  struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6367
6368  SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6369  if (CL == SectionRef())
6370    CL = get_section(O, "__DATA", "__objc_classlist");
6371  if (CL == SectionRef())
6372    CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6373  if (CL == SectionRef())
6374    CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6375  info.S = CL;
6376  walk_pointer_list_64("class", CL, O, &info, print_class64_t);
6377
6378  SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6379  if (CR == SectionRef())
6380    CR = get_section(O, "__DATA", "__objc_classrefs");
6381  if (CR == SectionRef())
6382    CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6383  if (CR == SectionRef())
6384    CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6385  info.S = CR;
6386  walk_pointer_list_64("class refs", CR, O, &info, nullptr);
6387
6388  SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6389  if (SR == SectionRef())
6390    SR = get_section(O, "__DATA", "__objc_superrefs");
6391  if (SR == SectionRef())
6392    SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6393  if (SR == SectionRef())
6394    SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6395  info.S = SR;
6396  walk_pointer_list_64("super refs", SR, O, &info, nullptr);
6397
6398  SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6399  if (CA == SectionRef())
6400    CA = get_section(O, "__DATA", "__objc_catlist");
6401  if (CA == SectionRef())
6402    CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6403  if (CA == SectionRef())
6404    CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6405  info.S = CA;
6406  walk_pointer_list_64("category", CA, O, &info, print_category64_t);
6407
6408  SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6409  if (PL == SectionRef())
6410    PL = get_section(O, "__DATA", "__objc_protolist");
6411  if (PL == SectionRef())
6412    PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6413  if (PL == SectionRef())
6414    PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6415  info.S = PL;
6416  walk_pointer_list_64("protocol", PL, O, &info, nullptr);
6417
6418  SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6419  if (MR == SectionRef())
6420    MR = get_section(O, "__DATA", "__objc_msgrefs");
6421  if (MR == SectionRef())
6422    MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6423  if (MR == SectionRef())
6424    MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6425  info.S = MR;
6426  print_message_refs64(MR, &info);
6427
6428  SectionRef II = get_section(O, "__OBJC2", "__image_info");
6429  if (II == SectionRef())
6430    II = get_section(O, "__DATA", "__objc_imageinfo");
6431  if (II == SectionRef())
6432    II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6433  if (II == SectionRef())
6434    II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6435  info.S = II;
6436  print_image_info64(II, &info);
6437}
6438
6439static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6440  SymbolAddressMap AddrMap;
6441  if (verbose)
6442    CreateSymbolAddressMap(O, &AddrMap);
6443
6444  std::vector<SectionRef> Sections;
6445  append_range(Sections, O->sections());
6446
6447  struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6448
6449  SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6450  if (CL == SectionRef())
6451    CL = get_section(O, "__DATA", "__objc_classlist");
6452  if (CL == SectionRef())
6453    CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6454  if (CL == SectionRef())
6455    CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6456  info.S = CL;
6457  walk_pointer_list_32("class", CL, O, &info, print_class32_t);
6458
6459  SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6460  if (CR == SectionRef())
6461    CR = get_section(O, "__DATA", "__objc_classrefs");
6462  if (CR == SectionRef())
6463    CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6464  if (CR == SectionRef())
6465    CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6466  info.S = CR;
6467  walk_pointer_list_32("class refs", CR, O, &info, nullptr);
6468
6469  SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6470  if (SR == SectionRef())
6471    SR = get_section(O, "__DATA", "__objc_superrefs");
6472  if (SR == SectionRef())
6473    SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6474  if (SR == SectionRef())
6475    SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6476  info.S = SR;
6477  walk_pointer_list_32("super refs", SR, O, &info, nullptr);
6478
6479  SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6480  if (CA == SectionRef())
6481    CA = get_section(O, "__DATA", "__objc_catlist");
6482  if (CA == SectionRef())
6483    CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6484  if (CA == SectionRef())
6485    CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6486  info.S = CA;
6487  walk_pointer_list_32("category", CA, O, &info, print_category32_t);
6488
6489  SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6490  if (PL == SectionRef())
6491    PL = get_section(O, "__DATA", "__objc_protolist");
6492  if (PL == SectionRef())
6493    PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6494  if (PL == SectionRef())
6495    PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6496  info.S = PL;
6497  walk_pointer_list_32("protocol", PL, O, &info, nullptr);
6498
6499  SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6500  if (MR == SectionRef())
6501    MR = get_section(O, "__DATA", "__objc_msgrefs");
6502  if (MR == SectionRef())
6503    MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6504  if (MR == SectionRef())
6505    MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6506  info.S = MR;
6507  print_message_refs32(MR, &info);
6508
6509  SectionRef II = get_section(O, "__OBJC2", "__image_info");
6510  if (II == SectionRef())
6511    II = get_section(O, "__DATA", "__objc_imageinfo");
6512  if (II == SectionRef())
6513    II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6514  if (II == SectionRef())
6515    II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6516  info.S = II;
6517  print_image_info32(II, &info);
6518}
6519
6520static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6521  uint32_t i, j, p, offset, xoffset, left, defs_left, def;
6522  const char *r, *name, *defs;
6523  struct objc_module_t module;
6524  SectionRef S, xS;
6525  struct objc_symtab_t symtab;
6526  struct objc_class_t objc_class;
6527  struct objc_category_t objc_category;
6528
6529  outs() << "Objective-C segment\n";
6530  S = get_section(O, "__OBJC", "__module_info");
6531  if (S == SectionRef())
6532    return false;
6533
6534  SymbolAddressMap AddrMap;
6535  if (verbose)
6536    CreateSymbolAddressMap(O, &AddrMap);
6537
6538  std::vector<SectionRef> Sections;
6539  append_range(Sections, O->sections());
6540
6541  struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6542
6543  for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
6544    p = S.getAddress() + i;
6545    r = get_pointer_32(p, offset, left, S, &info, true);
6546    if (r == nullptr)
6547      return true;
6548    memset(&module, '\0', sizeof(struct objc_module_t));
6549    if (left < sizeof(struct objc_module_t)) {
6550      memcpy(&module, r, left);
6551      outs() << "   (module extends past end of __module_info section)\n";
6552    } else
6553      memcpy(&module, r, sizeof(struct objc_module_t));
6554    if (O->isLittleEndian() != sys::IsLittleEndianHost)
6555      swapStruct(module);
6556
6557    outs() << "Module " << format("0x%" PRIx32, p) << "\n";
6558    outs() << "    version " << module.version << "\n";
6559    outs() << "       size " << module.size << "\n";
6560    outs() << "       name ";
6561    name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
6562    if (name != nullptr)
6563      outs() << format("%.*s", left, name);
6564    else
6565      outs() << format("0x%08" PRIx32, module.name)
6566             << "(not in an __OBJC section)";
6567    outs() << "\n";
6568
6569    r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
6570    if (module.symtab == 0 || r == nullptr) {
6571      outs() << "     symtab " << format("0x%08" PRIx32, module.symtab)
6572             << " (not in an __OBJC section)\n";
6573      continue;
6574    }
6575    outs() << "     symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
6576    memset(&symtab, '\0', sizeof(struct objc_symtab_t));
6577    defs_left = 0;
6578    defs = nullptr;
6579    if (left < sizeof(struct objc_symtab_t)) {
6580      memcpy(&symtab, r, left);
6581      outs() << "\tsymtab extends past end of an __OBJC section)\n";
6582    } else {
6583      memcpy(&symtab, r, sizeof(struct objc_symtab_t));
6584      if (left > sizeof(struct objc_symtab_t)) {
6585        defs_left = left - sizeof(struct objc_symtab_t);
6586        defs = r + sizeof(struct objc_symtab_t);
6587      }
6588    }
6589    if (O->isLittleEndian() != sys::IsLittleEndianHost)
6590      swapStruct(symtab);
6591
6592    outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
6593    r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
6594    outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
6595    if (r == nullptr)
6596      outs() << " (not in an __OBJC section)";
6597    outs() << "\n";
6598    outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
6599    outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
6600    if (symtab.cls_def_cnt > 0)
6601      outs() << "\tClass Definitions\n";
6602    for (j = 0; j < symtab.cls_def_cnt; j++) {
6603      if ((j + 1) * sizeof(uint32_t) > defs_left) {
6604        outs() << "\t(remaining class defs entries entends past the end of the "
6605               << "section)\n";
6606        break;
6607      }
6608      memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
6609      if (O->isLittleEndian() != sys::IsLittleEndianHost)
6610        sys::swapByteOrder(def);
6611
6612      r = get_pointer_32(def, xoffset, left, xS, &info, true);
6613      outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
6614      if (r != nullptr) {
6615        if (left > sizeof(struct objc_class_t)) {
6616          outs() << "\n";
6617          memcpy(&objc_class, r, sizeof(struct objc_class_t));
6618        } else {
6619          outs() << " (entends past the end of the section)\n";
6620          memset(&objc_class, '\0', sizeof(struct objc_class_t));
6621          memcpy(&objc_class, r, left);
6622        }
6623        if (O->isLittleEndian() != sys::IsLittleEndianHost)
6624          swapStruct(objc_class);
6625        print_objc_class_t(&objc_class, &info);
6626      } else {
6627        outs() << "(not in an __OBJC section)\n";
6628      }
6629
6630      if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
6631        outs() << "\tMeta Class";
6632        r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
6633        if (r != nullptr) {
6634          if (left > sizeof(struct objc_class_t)) {
6635            outs() << "\n";
6636            memcpy(&objc_class, r, sizeof(struct objc_class_t));
6637          } else {
6638            outs() << " (entends past the end of the section)\n";
6639            memset(&objc_class, '\0', sizeof(struct objc_class_t));
6640            memcpy(&objc_class, r, left);
6641          }
6642          if (O->isLittleEndian() != sys::IsLittleEndianHost)
6643            swapStruct(objc_class);
6644          print_objc_class_t(&objc_class, &info);
6645        } else {
6646          outs() << "(not in an __OBJC section)\n";
6647        }
6648      }
6649    }
6650    if (symtab.cat_def_cnt > 0)
6651      outs() << "\tCategory Definitions\n";
6652    for (j = 0; j < symtab.cat_def_cnt; j++) {
6653      if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
6654        outs() << "\t(remaining category defs entries entends past the end of "
6655               << "the section)\n";
6656        break;
6657      }
6658      memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
6659             sizeof(uint32_t));
6660      if (O->isLittleEndian() != sys::IsLittleEndianHost)
6661        sys::swapByteOrder(def);
6662
6663      r = get_pointer_32(def, xoffset, left, xS, &info, true);
6664      outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
6665             << format("0x%08" PRIx32, def);
6666      if (r != nullptr) {
6667        if (left > sizeof(struct objc_category_t)) {
6668          outs() << "\n";
6669          memcpy(&objc_category, r, sizeof(struct objc_category_t));
6670        } else {
6671          outs() << " (entends past the end of the section)\n";
6672          memset(&objc_category, '\0', sizeof(struct objc_category_t));
6673          memcpy(&objc_category, r, left);
6674        }
6675        if (O->isLittleEndian() != sys::IsLittleEndianHost)
6676          swapStruct(objc_category);
6677        print_objc_objc_category_t(&objc_category, &info);
6678      } else {
6679        outs() << "(not in an __OBJC section)\n";
6680      }
6681    }
6682  }
6683  const SectionRef II = get_section(O, "__OBJC", "__image_info");
6684  if (II != SectionRef())
6685    print_image_info(II, &info);
6686
6687  return true;
6688}
6689
6690static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
6691                                uint32_t size, uint32_t addr) {
6692  SymbolAddressMap AddrMap;
6693  CreateSymbolAddressMap(O, &AddrMap);
6694
6695  std::vector<SectionRef> Sections;
6696  append_range(Sections, O->sections());
6697
6698  struct DisassembleInfo info(O, &AddrMap, &Sections, true);
6699
6700  const char *p;
6701  struct objc_protocol_t protocol;
6702  uint32_t left, paddr;
6703  for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
6704    memset(&protocol, '\0', sizeof(struct objc_protocol_t));
6705    left = size - (p - sect);
6706    if (left < sizeof(struct objc_protocol_t)) {
6707      outs() << "Protocol extends past end of __protocol section\n";
6708      memcpy(&protocol, p, left);
6709    } else
6710      memcpy(&protocol, p, sizeof(struct objc_protocol_t));
6711    if (O->isLittleEndian() != sys::IsLittleEndianHost)
6712      swapStruct(protocol);
6713    paddr = addr + (p - sect);
6714    outs() << "Protocol " << format("0x%" PRIx32, paddr);
6715    if (print_protocol(paddr, 0, &info))
6716      outs() << "(not in an __OBJC section)\n";
6717  }
6718}
6719
6720#ifdef LLVM_HAVE_LIBXAR
6721static inline void swapStruct(struct xar_header &xar) {
6722  sys::swapByteOrder(xar.magic);
6723  sys::swapByteOrder(xar.size);
6724  sys::swapByteOrder(xar.version);
6725  sys::swapByteOrder(xar.toc_length_compressed);
6726  sys::swapByteOrder(xar.toc_length_uncompressed);
6727  sys::swapByteOrder(xar.cksum_alg);
6728}
6729
6730static void PrintModeVerbose(uint32_t mode) {
6731  switch(mode & S_IFMT){
6732  case S_IFDIR:
6733    outs() << "d";
6734    break;
6735  case S_IFCHR:
6736    outs() << "c";
6737    break;
6738  case S_IFBLK:
6739    outs() << "b";
6740    break;
6741  case S_IFREG:
6742    outs() << "-";
6743    break;
6744  case S_IFLNK:
6745    outs() << "l";
6746    break;
6747  case S_IFSOCK:
6748    outs() << "s";
6749    break;
6750  default:
6751    outs() << "?";
6752    break;
6753  }
6754
6755  /* owner permissions */
6756  if(mode & S_IREAD)
6757    outs() << "r";
6758  else
6759    outs() << "-";
6760  if(mode & S_IWRITE)
6761    outs() << "w";
6762  else
6763    outs() << "-";
6764  if(mode & S_ISUID)
6765    outs() << "s";
6766  else if(mode & S_IEXEC)
6767    outs() << "x";
6768  else
6769    outs() << "-";
6770
6771  /* group permissions */
6772  if(mode & (S_IREAD >> 3))
6773    outs() << "r";
6774  else
6775    outs() << "-";
6776  if(mode & (S_IWRITE >> 3))
6777    outs() << "w";
6778  else
6779    outs() << "-";
6780  if(mode & S_ISGID)
6781    outs() << "s";
6782  else if(mode & (S_IEXEC >> 3))
6783    outs() << "x";
6784  else
6785    outs() << "-";
6786
6787  /* other permissions */
6788  if(mode & (S_IREAD >> 6))
6789    outs() << "r";
6790  else
6791    outs() << "-";
6792  if(mode & (S_IWRITE >> 6))
6793    outs() << "w";
6794  else
6795    outs() << "-";
6796  if(mode & S_ISVTX)
6797    outs() << "t";
6798  else if(mode & (S_IEXEC >> 6))
6799    outs() << "x";
6800  else
6801    outs() << "-";
6802}
6803
6804static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
6805  xar_file_t xf;
6806  const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
6807  char *endp;
6808  uint32_t mode_value;
6809
6810  ScopedXarIter xi;
6811  if (!xi) {
6812    WithColor::error(errs(), "llvm-objdump")
6813        << "can't obtain an xar iterator for xar archive " << XarFilename
6814        << "\n";
6815    return;
6816  }
6817
6818  // Go through the xar's files.
6819  for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
6820    ScopedXarIter xp;
6821    if(!xp){
6822      WithColor::error(errs(), "llvm-objdump")
6823          << "can't obtain an xar iterator for xar archive " << XarFilename
6824          << "\n";
6825      return;
6826    }
6827    type = nullptr;
6828    mode = nullptr;
6829    user = nullptr;
6830    group = nullptr;
6831    size = nullptr;
6832    mtime = nullptr;
6833    name = nullptr;
6834    for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
6835      const char *val = nullptr;
6836      xar_prop_get(xf, key, &val);
6837#if 0 // Useful for debugging.
6838      outs() << "key: " << key << " value: " << val << "\n";
6839#endif
6840      if(strcmp(key, "type") == 0)
6841        type = val;
6842      if(strcmp(key, "mode") == 0)
6843        mode = val;
6844      if(strcmp(key, "user") == 0)
6845        user = val;
6846      if(strcmp(key, "group") == 0)
6847        group = val;
6848      if(strcmp(key, "data/size") == 0)
6849        size = val;
6850      if(strcmp(key, "mtime") == 0)
6851        mtime = val;
6852      if(strcmp(key, "name") == 0)
6853        name = val;
6854    }
6855    if(mode != nullptr){
6856      mode_value = strtoul(mode, &endp, 8);
6857      if(*endp != '\0')
6858        outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
6859      if(strcmp(type, "file") == 0)
6860        mode_value |= S_IFREG;
6861      PrintModeVerbose(mode_value);
6862      outs() << " ";
6863    }
6864    if(user != nullptr)
6865      outs() << format("%10s/", user);
6866    if(group != nullptr)
6867      outs() << format("%-10s ", group);
6868    if(size != nullptr)
6869      outs() << format("%7s ", size);
6870    if(mtime != nullptr){
6871      for(m = mtime; *m != 'T' && *m != '\0'; m++)
6872        outs() << *m;
6873      if(*m == 'T')
6874        m++;
6875      outs() << " ";
6876      for( ; *m != 'Z' && *m != '\0'; m++)
6877        outs() << *m;
6878      outs() << " ";
6879    }
6880    if(name != nullptr)
6881      outs() << name;
6882    outs() << "\n";
6883  }
6884}
6885
6886static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
6887                                uint32_t size, bool verbose,
6888                                bool PrintXarHeader, bool PrintXarFileHeaders,
6889                                std::string XarMemberName) {
6890  if(size < sizeof(struct xar_header)) {
6891    outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
6892              "of struct xar_header)\n";
6893    return;
6894  }
6895  struct xar_header XarHeader;
6896  memcpy(&XarHeader, sect, sizeof(struct xar_header));
6897  if (sys::IsLittleEndianHost)
6898    swapStruct(XarHeader);
6899  if (PrintXarHeader) {
6900    if (!XarMemberName.empty())
6901      outs() << "In xar member " << XarMemberName << ": ";
6902    else
6903      outs() << "For (__LLVM,__bundle) section: ";
6904    outs() << "xar header\n";
6905    if (XarHeader.magic == XAR_HEADER_MAGIC)
6906      outs() << "                  magic XAR_HEADER_MAGIC\n";
6907    else
6908      outs() << "                  magic "
6909             << format_hex(XarHeader.magic, 10, true)
6910             << " (not XAR_HEADER_MAGIC)\n";
6911    outs() << "                   size " << XarHeader.size << "\n";
6912    outs() << "                version " << XarHeader.version << "\n";
6913    outs() << "  toc_length_compressed " << XarHeader.toc_length_compressed
6914           << "\n";
6915    outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
6916           << "\n";
6917    outs() << "              cksum_alg ";
6918    switch (XarHeader.cksum_alg) {
6919      case XAR_CKSUM_NONE:
6920        outs() << "XAR_CKSUM_NONE\n";
6921        break;
6922      case XAR_CKSUM_SHA1:
6923        outs() << "XAR_CKSUM_SHA1\n";
6924        break;
6925      case XAR_CKSUM_MD5:
6926        outs() << "XAR_CKSUM_MD5\n";
6927        break;
6928#ifdef XAR_CKSUM_SHA256
6929      case XAR_CKSUM_SHA256:
6930        outs() << "XAR_CKSUM_SHA256\n";
6931        break;
6932#endif
6933#ifdef XAR_CKSUM_SHA512
6934      case XAR_CKSUM_SHA512:
6935        outs() << "XAR_CKSUM_SHA512\n";
6936        break;
6937#endif
6938      default:
6939        outs() << XarHeader.cksum_alg << "\n";
6940    }
6941  }
6942
6943  SmallString<128> XarFilename;
6944  int FD;
6945  std::error_code XarEC =
6946      sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
6947  if (XarEC) {
6948    WithColor::error(errs(), "llvm-objdump") << XarEC.message() << "\n";
6949    return;
6950  }
6951  ToolOutputFile XarFile(XarFilename, FD);
6952  raw_fd_ostream &XarOut = XarFile.os();
6953  StringRef XarContents(sect, size);
6954  XarOut << XarContents;
6955  XarOut.close();
6956  if (XarOut.has_error())
6957    return;
6958
6959  ScopedXarFile xar(XarFilename.c_str(), READ);
6960  if (!xar) {
6961    WithColor::error(errs(), "llvm-objdump")
6962        << "can't create temporary xar archive " << XarFilename << "\n";
6963    return;
6964  }
6965
6966  SmallString<128> TocFilename;
6967  std::error_code TocEC =
6968      sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
6969  if (TocEC) {
6970    WithColor::error(errs(), "llvm-objdump") << TocEC.message() << "\n";
6971    return;
6972  }
6973  xar_serialize(xar, TocFilename.c_str());
6974
6975  if (PrintXarFileHeaders) {
6976    if (!XarMemberName.empty())
6977      outs() << "In xar member " << XarMemberName << ": ";
6978    else
6979      outs() << "For (__LLVM,__bundle) section: ";
6980    outs() << "xar archive files:\n";
6981    PrintXarFilesSummary(XarFilename.c_str(), xar);
6982  }
6983
6984  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
6985    MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
6986  if (std::error_code EC = FileOrErr.getError()) {
6987    WithColor::error(errs(), "llvm-objdump") << EC.message() << "\n";
6988    return;
6989  }
6990  std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
6991
6992  if (!XarMemberName.empty())
6993    outs() << "In xar member " << XarMemberName << ": ";
6994  else
6995    outs() << "For (__LLVM,__bundle) section: ";
6996  outs() << "xar table of contents:\n";
6997  outs() << Buffer->getBuffer() << "\n";
6998
6999  // TODO: Go through the xar's files.
7000  ScopedXarIter xi;
7001  if(!xi){
7002    WithColor::error(errs(), "llvm-objdump")
7003        << "can't obtain an xar iterator for xar archive "
7004        << XarFilename.c_str() << "\n";
7005    return;
7006  }
7007  for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
7008    const char *key;
7009    const char *member_name, *member_type, *member_size_string;
7010    size_t member_size;
7011
7012    ScopedXarIter xp;
7013    if(!xp){
7014      WithColor::error(errs(), "llvm-objdump")
7015          << "can't obtain an xar iterator for xar archive "
7016          << XarFilename.c_str() << "\n";
7017      return;
7018    }
7019    member_name = NULL;
7020    member_type = NULL;
7021    member_size_string = NULL;
7022    for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
7023      const char *val = nullptr;
7024      xar_prop_get(xf, key, &val);
7025#if 0 // Useful for debugging.
7026      outs() << "key: " << key << " value: " << val << "\n";
7027#endif
7028      if (strcmp(key, "name") == 0)
7029        member_name = val;
7030      if (strcmp(key, "type") == 0)
7031        member_type = val;
7032      if (strcmp(key, "data/size") == 0)
7033        member_size_string = val;
7034    }
7035    /*
7036     * If we find a file with a name, date/size and type properties
7037     * and with the type being "file" see if that is a xar file.
7038     */
7039    if (member_name != NULL && member_type != NULL &&
7040        strcmp(member_type, "file") == 0 &&
7041        member_size_string != NULL){
7042      // Extract the file into a buffer.
7043      char *endptr;
7044      member_size = strtoul(member_size_string, &endptr, 10);
7045      if (*endptr == '\0' && member_size != 0) {
7046        char *buffer;
7047        if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
7048#if 0 // Useful for debugging.
7049          outs() << "xar member: " << member_name << " extracted\n";
7050#endif
7051          // Set the XarMemberName we want to see printed in the header.
7052          std::string OldXarMemberName;
7053          // If XarMemberName is already set this is nested. So
7054          // save the old name and create the nested name.
7055          if (!XarMemberName.empty()) {
7056            OldXarMemberName = XarMemberName;
7057            XarMemberName =
7058                (Twine("[") + XarMemberName + "]" + member_name).str();
7059          } else {
7060            OldXarMemberName = "";
7061            XarMemberName = member_name;
7062          }
7063          // See if this is could be a xar file (nested).
7064          if (member_size >= sizeof(struct xar_header)) {
7065#if 0 // Useful for debugging.
7066            outs() << "could be a xar file: " << member_name << "\n";
7067#endif
7068            memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
7069            if (sys::IsLittleEndianHost)
7070              swapStruct(XarHeader);
7071            if (XarHeader.magic == XAR_HEADER_MAGIC)
7072              DumpBitcodeSection(O, buffer, member_size, verbose,
7073                                 PrintXarHeader, PrintXarFileHeaders,
7074                                 XarMemberName);
7075          }
7076          XarMemberName = OldXarMemberName;
7077          delete buffer;
7078        }
7079      }
7080    }
7081  }
7082}
7083#endif // defined(LLVM_HAVE_LIBXAR)
7084
7085static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
7086  if (O->is64Bit())
7087    printObjc2_64bit_MetaData(O, verbose);
7088  else {
7089    MachO::mach_header H;
7090    H = O->getHeader();
7091    if (H.cputype == MachO::CPU_TYPE_ARM)
7092      printObjc2_32bit_MetaData(O, verbose);
7093    else {
7094      // This is the 32-bit non-arm cputype case.  Which is normally
7095      // the first Objective-C ABI.  But it may be the case of a
7096      // binary for the iOS simulator which is the second Objective-C
7097      // ABI.  In that case printObjc1_32bit_MetaData() will determine that
7098      // and return false.
7099      if (!printObjc1_32bit_MetaData(O, verbose))
7100        printObjc2_32bit_MetaData(O, verbose);
7101    }
7102  }
7103}
7104
7105// GuessLiteralPointer returns a string which for the item in the Mach-O file
7106// for the address passed in as ReferenceValue for printing as a comment with
7107// the instruction and also returns the corresponding type of that item
7108// indirectly through ReferenceType.
7109//
7110// If ReferenceValue is an address of literal cstring then a pointer to the
7111// cstring is returned and ReferenceType is set to
7112// LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
7113//
7114// If ReferenceValue is an address of an Objective-C CFString, Selector ref or
7115// Class ref that name is returned and the ReferenceType is set accordingly.
7116//
7117// Lastly, literals which are Symbol address in a literal pool are looked for
7118// and if found the symbol name is returned and ReferenceType is set to
7119// LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
7120//
7121// If there is no item in the Mach-O file for the address passed in as
7122// ReferenceValue nullptr is returned and ReferenceType is unchanged.
7123static const char *GuessLiteralPointer(uint64_t ReferenceValue,
7124                                       uint64_t ReferencePC,
7125                                       uint64_t *ReferenceType,
7126                                       struct DisassembleInfo *info) {
7127  // First see if there is an external relocation entry at the ReferencePC.
7128  if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
7129    uint64_t sect_addr = info->S.getAddress();
7130    uint64_t sect_offset = ReferencePC - sect_addr;
7131    bool reloc_found = false;
7132    DataRefImpl Rel;
7133    MachO::any_relocation_info RE;
7134    bool isExtern = false;
7135    SymbolRef Symbol;
7136    for (const RelocationRef &Reloc : info->S.relocations()) {
7137      uint64_t RelocOffset = Reloc.getOffset();
7138      if (RelocOffset == sect_offset) {
7139        Rel = Reloc.getRawDataRefImpl();
7140        RE = info->O->getRelocation(Rel);
7141        if (info->O->isRelocationScattered(RE))
7142          continue;
7143        isExtern = info->O->getPlainRelocationExternal(RE);
7144        if (isExtern) {
7145          symbol_iterator RelocSym = Reloc.getSymbol();
7146          Symbol = *RelocSym;
7147        }
7148        reloc_found = true;
7149        break;
7150      }
7151    }
7152    // If there is an external relocation entry for a symbol in a section
7153    // then used that symbol's value for the value of the reference.
7154    if (reloc_found && isExtern) {
7155      if (info->O->getAnyRelocationPCRel(RE)) {
7156        unsigned Type = info->O->getAnyRelocationType(RE);
7157        if (Type == MachO::X86_64_RELOC_SIGNED) {
7158          ReferenceValue = cantFail(Symbol.getValue());
7159        }
7160      }
7161    }
7162  }
7163
7164  // Look for literals such as Objective-C CFStrings refs, Selector refs,
7165  // Message refs and Class refs.
7166  bool classref, selref, msgref, cfstring;
7167  uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
7168                                               selref, msgref, cfstring);
7169  if (classref && pointer_value == 0) {
7170    // Note the ReferenceValue is a pointer into the __objc_classrefs section.
7171    // And the pointer_value in that section is typically zero as it will be
7172    // set by dyld as part of the "bind information".
7173    const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
7174    if (name != nullptr) {
7175      *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
7176      const char *class_name = strrchr(name, '$');
7177      if (class_name != nullptr && class_name[1] == '_' &&
7178          class_name[2] != '\0') {
7179        info->class_name = class_name + 2;
7180        return name;
7181      }
7182    }
7183  }
7184
7185  if (classref) {
7186    *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
7187    const char *name =
7188        get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
7189    if (name != nullptr)
7190      info->class_name = name;
7191    else
7192      name = "bad class ref";
7193    return name;
7194  }
7195
7196  if (cfstring) {
7197    *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
7198    const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
7199    return name;
7200  }
7201
7202  if (selref && pointer_value == 0)
7203    pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
7204
7205  if (pointer_value != 0)
7206    ReferenceValue = pointer_value;
7207
7208  const char *name = GuessCstringPointer(ReferenceValue, info);
7209  if (name) {
7210    if (pointer_value != 0 && selref) {
7211      *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
7212      info->selector_name = name;
7213    } else if (pointer_value != 0 && msgref) {
7214      info->class_name = nullptr;
7215      *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
7216      info->selector_name = name;
7217    } else
7218      *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
7219    return name;
7220  }
7221
7222  // Lastly look for an indirect symbol with this ReferenceValue which is in
7223  // a literal pool.  If found return that symbol name.
7224  name = GuessIndirectSymbol(ReferenceValue, info);
7225  if (name) {
7226    *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
7227    return name;
7228  }
7229
7230  return nullptr;
7231}
7232
7233// SymbolizerSymbolLookUp is the symbol lookup function passed when creating
7234// the Symbolizer.  It looks up the ReferenceValue using the info passed via the
7235// pointer to the struct DisassembleInfo that was passed when MCSymbolizer
7236// is created and returns the symbol name that matches the ReferenceValue or
7237// nullptr if none.  The ReferenceType is passed in for the IN type of
7238// reference the instruction is making from the values in defined in the header
7239// "llvm-c/Disassembler.h".  On return the ReferenceType can set to a specific
7240// Out type and the ReferenceName will also be set which is added as a comment
7241// to the disassembled instruction.
7242//
7243// If the symbol name is a C++ mangled name then the demangled name is
7244// returned through ReferenceName and ReferenceType is set to
7245// LLVMDisassembler_ReferenceType_DeMangled_Name .
7246//
7247// When this is called to get a symbol name for a branch target then the
7248// ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
7249// SymbolValue will be looked for in the indirect symbol table to determine if
7250// it is an address for a symbol stub.  If so then the symbol name for that
7251// stub is returned indirectly through ReferenceName and then ReferenceType is
7252// set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
7253//
7254// When this is called with an value loaded via a PC relative load then
7255// ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
7256// SymbolValue is checked to be an address of literal pointer, symbol pointer,
7257// or an Objective-C meta data reference.  If so the output ReferenceType is
7258// set to correspond to that as well as setting the ReferenceName.
7259static const char *SymbolizerSymbolLookUp(void *DisInfo,
7260                                          uint64_t ReferenceValue,
7261                                          uint64_t *ReferenceType,
7262                                          uint64_t ReferencePC,
7263                                          const char **ReferenceName) {
7264  struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
7265  // If no verbose symbolic information is wanted then just return nullptr.
7266  if (!info->verbose) {
7267    *ReferenceName = nullptr;
7268    *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7269    return nullptr;
7270  }
7271
7272  const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
7273
7274  if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
7275    *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
7276    if (*ReferenceName != nullptr) {
7277      method_reference(info, ReferenceType, ReferenceName);
7278      if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
7279        *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
7280    } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
7281      if (info->demangled_name != nullptr)
7282        free(info->demangled_name);
7283      int status;
7284      info->demangled_name =
7285          itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
7286      if (info->demangled_name != nullptr) {
7287        *ReferenceName = info->demangled_name;
7288        *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
7289      } else
7290        *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7291    } else
7292      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7293  } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
7294    *ReferenceName =
7295        GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7296    if (*ReferenceName)
7297      method_reference(info, ReferenceType, ReferenceName);
7298    else
7299      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7300    // If this is arm64 and the reference is an adrp instruction save the
7301    // instruction, passed in ReferenceValue and the address of the instruction
7302    // for use later if we see and add immediate instruction.
7303  } else if (info->O->getArch() == Triple::aarch64 &&
7304             *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
7305    info->adrp_inst = ReferenceValue;
7306    info->adrp_addr = ReferencePC;
7307    SymbolName = nullptr;
7308    *ReferenceName = nullptr;
7309    *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7310    // If this is arm64 and reference is an add immediate instruction and we
7311    // have
7312    // seen an adrp instruction just before it and the adrp's Xd register
7313    // matches
7314    // this add's Xn register reconstruct the value being referenced and look to
7315    // see if it is a literal pointer.  Note the add immediate instruction is
7316    // passed in ReferenceValue.
7317  } else if (info->O->getArch() == Triple::aarch64 &&
7318             *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
7319             ReferencePC - 4 == info->adrp_addr &&
7320             (info->adrp_inst & 0x9f000000) == 0x90000000 &&
7321             (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
7322    uint32_t addxri_inst;
7323    uint64_t adrp_imm, addxri_imm;
7324
7325    adrp_imm =
7326        ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
7327    if (info->adrp_inst & 0x0200000)
7328      adrp_imm |= 0xfffffffffc000000LL;
7329
7330    addxri_inst = ReferenceValue;
7331    addxri_imm = (addxri_inst >> 10) & 0xfff;
7332    if (((addxri_inst >> 22) & 0x3) == 1)
7333      addxri_imm <<= 12;
7334
7335    ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
7336                     (adrp_imm << 12) + addxri_imm;
7337
7338    *ReferenceName =
7339        GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7340    if (*ReferenceName == nullptr)
7341      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7342    // If this is arm64 and the reference is a load register instruction and we
7343    // have seen an adrp instruction just before it and the adrp's Xd register
7344    // matches this add's Xn register reconstruct the value being referenced and
7345    // look to see if it is a literal pointer.  Note the load register
7346    // instruction is passed in ReferenceValue.
7347  } else if (info->O->getArch() == Triple::aarch64 &&
7348             *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
7349             ReferencePC - 4 == info->adrp_addr &&
7350             (info->adrp_inst & 0x9f000000) == 0x90000000 &&
7351             (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
7352    uint32_t ldrxui_inst;
7353    uint64_t adrp_imm, ldrxui_imm;
7354
7355    adrp_imm =
7356        ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
7357    if (info->adrp_inst & 0x0200000)
7358      adrp_imm |= 0xfffffffffc000000LL;
7359
7360    ldrxui_inst = ReferenceValue;
7361    ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
7362
7363    ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
7364                     (adrp_imm << 12) + (ldrxui_imm << 3);
7365
7366    *ReferenceName =
7367        GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7368    if (*ReferenceName == nullptr)
7369      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7370  }
7371  // If this arm64 and is an load register (PC-relative) instruction the
7372  // ReferenceValue is the PC plus the immediate value.
7373  else if (info->O->getArch() == Triple::aarch64 &&
7374           (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
7375            *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
7376    *ReferenceName =
7377        GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7378    if (*ReferenceName == nullptr)
7379      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7380  } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
7381    if (info->demangled_name != nullptr)
7382      free(info->demangled_name);
7383    int status;
7384    info->demangled_name =
7385        itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
7386    if (info->demangled_name != nullptr) {
7387      *ReferenceName = info->demangled_name;
7388      *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
7389    }
7390  }
7391  else {
7392    *ReferenceName = nullptr;
7393    *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7394  }
7395
7396  return SymbolName;
7397}
7398
7399/// Emits the comments that are stored in the CommentStream.
7400/// Each comment in the CommentStream must end with a newline.
7401static void emitComments(raw_svector_ostream &CommentStream,
7402                         SmallString<128> &CommentsToEmit,
7403                         formatted_raw_ostream &FormattedOS,
7404                         const MCAsmInfo &MAI) {
7405  // Flush the stream before taking its content.
7406  StringRef Comments = CommentsToEmit.str();
7407  // Get the default information for printing a comment.
7408  StringRef CommentBegin = MAI.getCommentString();
7409  unsigned CommentColumn = MAI.getCommentColumn();
7410  ListSeparator LS("\n");
7411  while (!Comments.empty()) {
7412    FormattedOS << LS;
7413    // Emit a line of comments.
7414    FormattedOS.PadToColumn(CommentColumn);
7415    size_t Position = Comments.find('\n');
7416    FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
7417    // Move after the newline character.
7418    Comments = Comments.substr(Position + 1);
7419  }
7420  FormattedOS.flush();
7421
7422  // Tell the comment stream that the vector changed underneath it.
7423  CommentsToEmit.clear();
7424}
7425
7426const MachOObjectFile *
7427objdump::getMachODSymObject(const MachOObjectFile *MachOOF, StringRef Filename,
7428                            std::unique_ptr<Binary> &DSYMBinary,
7429                            std::unique_ptr<MemoryBuffer> &DSYMBuf) {
7430  const MachOObjectFile *DbgObj = MachOOF;
7431  std::string DSYMPath;
7432
7433  // Auto-detect w/o --dsym.
7434  if (DSYMFile.empty()) {
7435    sys::fs::file_status DSYMStatus;
7436    Twine FilenameDSYM = Filename + ".dSYM";
7437    if (!status(FilenameDSYM, DSYMStatus)) {
7438      if (sys::fs::is_directory(DSYMStatus)) {
7439        SmallString<1024> Path;
7440        FilenameDSYM.toVector(Path);
7441        sys::path::append(Path, "Contents", "Resources", "DWARF",
7442                          sys::path::filename(Filename));
7443        DSYMPath = std::string(Path);
7444      } else if (sys::fs::is_regular_file(DSYMStatus)) {
7445        DSYMPath = FilenameDSYM.str();
7446      }
7447    }
7448  }
7449
7450  if (DSYMPath.empty() && !DSYMFile.empty()) {
7451    // If DSYMPath is a .dSYM directory, append the Mach-O file.
7452    if (sys::fs::is_directory(DSYMFile) &&
7453        sys::path::extension(DSYMFile) == ".dSYM") {
7454      SmallString<128> ShortName(sys::path::filename(DSYMFile));
7455      sys::path::replace_extension(ShortName, "");
7456      SmallString<1024> FullPath(DSYMFile);
7457      sys::path::append(FullPath, "Contents", "Resources", "DWARF", ShortName);
7458      DSYMPath = FullPath.str();
7459    } else {
7460      DSYMPath = DSYMFile;
7461    }
7462  }
7463
7464  if (!DSYMPath.empty()) {
7465    // Load the file.
7466    ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
7467        MemoryBuffer::getFileOrSTDIN(DSYMPath);
7468    if (std::error_code EC = BufOrErr.getError()) {
7469      reportError(errorCodeToError(EC), DSYMPath);
7470      return nullptr;
7471    }
7472
7473    // We need to keep the file alive, because we're replacing DbgObj with it.
7474    DSYMBuf = std::move(BufOrErr.get());
7475
7476    Expected<std::unique_ptr<Binary>> BinaryOrErr =
7477        createBinary(DSYMBuf.get()->getMemBufferRef());
7478    if (!BinaryOrErr) {
7479      reportError(BinaryOrErr.takeError(), DSYMPath);
7480      return nullptr;
7481    }
7482
7483    // We need to keep the Binary alive with the buffer
7484    DSYMBinary = std::move(BinaryOrErr.get());
7485    if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) {
7486      // this is a Mach-O object file, use it
7487      if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) {
7488        DbgObj = MachDSYM;
7489      } else {
7490        WithColor::error(errs(), "llvm-objdump")
7491            << DSYMPath << " is not a Mach-O file type.\n";
7492        return nullptr;
7493      }
7494    } else if (auto *UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())) {
7495      // this is a Universal Binary, find a Mach-O for this architecture
7496      uint32_t CPUType, CPUSubType;
7497      const char *ArchFlag;
7498      if (MachOOF->is64Bit()) {
7499        const MachO::mach_header_64 H_64 = MachOOF->getHeader64();
7500        CPUType = H_64.cputype;
7501        CPUSubType = H_64.cpusubtype;
7502      } else {
7503        const MachO::mach_header H = MachOOF->getHeader();
7504        CPUType = H.cputype;
7505        CPUSubType = H.cpusubtype;
7506      }
7507      Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr,
7508                                                &ArchFlag);
7509      Expected<std::unique_ptr<MachOObjectFile>> MachDSYM =
7510          UB->getMachOObjectForArch(ArchFlag);
7511      if (!MachDSYM) {
7512        reportError(MachDSYM.takeError(), DSYMPath);
7513        return nullptr;
7514      }
7515
7516      // We need to keep the Binary alive with the buffer
7517      DbgObj = &*MachDSYM.get();
7518      DSYMBinary = std::move(*MachDSYM);
7519    } else {
7520      WithColor::error(errs(), "llvm-objdump")
7521          << DSYMPath << " is not a Mach-O or Universal file type.\n";
7522      return nullptr;
7523    }
7524  }
7525  return DbgObj;
7526}
7527
7528static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
7529                             StringRef DisSegName, StringRef DisSectName) {
7530  const char *McpuDefault = nullptr;
7531  const Target *ThumbTarget = nullptr;
7532  const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
7533  if (!TheTarget) {
7534    // GetTarget prints out stuff.
7535    return;
7536  }
7537  std::string MachOMCPU;
7538  if (MCPU.empty() && McpuDefault)
7539    MachOMCPU = McpuDefault;
7540  else
7541    MachOMCPU = MCPU;
7542
7543#define CHECK_TARGET_INFO_CREATION(NAME)                                       \
7544  do {                                                                         \
7545    if (!NAME) {                                                               \
7546      WithColor::error(errs(), "llvm-objdump")                                 \
7547          << "couldn't initialize disassembler for target " << TripleName      \
7548          << '\n';                                                             \
7549      return;                                                                  \
7550    }                                                                          \
7551  } while (false)
7552#define CHECK_THUMB_TARGET_INFO_CREATION(NAME)                                 \
7553  do {                                                                         \
7554    if (!NAME) {                                                               \
7555      WithColor::error(errs(), "llvm-objdump")                                 \
7556          << "couldn't initialize disassembler for target " << ThumbTripleName \
7557          << '\n';                                                             \
7558      return;                                                                  \
7559    }                                                                          \
7560  } while (false)
7561
7562  std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
7563  CHECK_TARGET_INFO_CREATION(InstrInfo);
7564  std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
7565  if (ThumbTarget) {
7566    ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
7567    CHECK_THUMB_TARGET_INFO_CREATION(ThumbInstrInfo);
7568  }
7569
7570  // Package up features to be passed to target/subtarget
7571  std::string FeaturesStr;
7572  if (!MAttrs.empty()) {
7573    SubtargetFeatures Features;
7574    for (unsigned i = 0; i != MAttrs.size(); ++i)
7575      Features.AddFeature(MAttrs[i]);
7576    FeaturesStr = Features.getString();
7577  }
7578
7579  MCTargetOptions MCOptions;
7580  // Set up disassembler.
7581  std::unique_ptr<const MCRegisterInfo> MRI(
7582      TheTarget->createMCRegInfo(TripleName));
7583  CHECK_TARGET_INFO_CREATION(MRI);
7584  std::unique_ptr<const MCAsmInfo> AsmInfo(
7585      TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
7586  CHECK_TARGET_INFO_CREATION(AsmInfo);
7587  std::unique_ptr<const MCSubtargetInfo> STI(
7588      TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
7589  CHECK_TARGET_INFO_CREATION(STI);
7590  MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
7591  std::unique_ptr<MCDisassembler> DisAsm(
7592      TheTarget->createMCDisassembler(*STI, Ctx));
7593  CHECK_TARGET_INFO_CREATION(DisAsm);
7594  std::unique_ptr<MCSymbolizer> Symbolizer;
7595  struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
7596  std::unique_ptr<MCRelocationInfo> RelInfo(
7597      TheTarget->createMCRelocationInfo(TripleName, Ctx));
7598  if (RelInfo) {
7599    Symbolizer.reset(TheTarget->createMCSymbolizer(
7600        TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7601        &SymbolizerInfo, &Ctx, std::move(RelInfo)));
7602    DisAsm->setSymbolizer(std::move(Symbolizer));
7603  }
7604  int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
7605  std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
7606      Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
7607  CHECK_TARGET_INFO_CREATION(IP);
7608  // Set the display preference for hex vs. decimal immediates.
7609  IP->setPrintImmHex(PrintImmHex);
7610  // Comment stream and backing vector.
7611  SmallString<128> CommentsToEmit;
7612  raw_svector_ostream CommentStream(CommentsToEmit);
7613  // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
7614  // if it is done then arm64 comments for string literals don't get printed
7615  // and some constant get printed instead and not setting it causes intel
7616  // (32-bit and 64-bit) comments printed with different spacing before the
7617  // comment causing different diffs with the 'C' disassembler library API.
7618  // IP->setCommentStream(CommentStream);
7619
7620  // Set up separate thumb disassembler if needed.
7621  std::unique_ptr<const MCRegisterInfo> ThumbMRI;
7622  std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
7623  std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
7624  std::unique_ptr<MCDisassembler> ThumbDisAsm;
7625  std::unique_ptr<MCInstPrinter> ThumbIP;
7626  std::unique_ptr<MCContext> ThumbCtx;
7627  std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
7628  struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
7629  std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
7630  if (ThumbTarget) {
7631    ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
7632    CHECK_THUMB_TARGET_INFO_CREATION(ThumbMRI);
7633    ThumbAsmInfo.reset(
7634        ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions));
7635    CHECK_THUMB_TARGET_INFO_CREATION(ThumbAsmInfo);
7636    ThumbSTI.reset(
7637        ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
7638                                           FeaturesStr));
7639    CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI);
7640    ThumbCtx.reset(new MCContext(Triple(ThumbTripleName), ThumbAsmInfo.get(),
7641                                 ThumbMRI.get(), ThumbSTI.get()));
7642    ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
7643    CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm);
7644    MCContext *PtrThumbCtx = ThumbCtx.get();
7645    ThumbRelInfo.reset(
7646        ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
7647    if (ThumbRelInfo) {
7648      ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
7649          ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7650          &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
7651      ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
7652    }
7653    int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
7654    ThumbIP.reset(ThumbTarget->createMCInstPrinter(
7655        Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
7656        *ThumbInstrInfo, *ThumbMRI));
7657    CHECK_THUMB_TARGET_INFO_CREATION(ThumbIP);
7658    // Set the display preference for hex vs. decimal immediates.
7659    ThumbIP->setPrintImmHex(PrintImmHex);
7660  }
7661
7662#undef CHECK_TARGET_INFO_CREATION
7663#undef CHECK_THUMB_TARGET_INFO_CREATION
7664
7665  MachO::mach_header Header = MachOOF->getHeader();
7666
7667  // FIXME: Using the -cfg command line option, this code used to be able to
7668  // annotate relocations with the referenced symbol's name, and if this was
7669  // inside a __[cf]string section, the data it points to. This is now replaced
7670  // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
7671  std::vector<SectionRef> Sections;
7672  std::vector<SymbolRef> Symbols;
7673  SmallVector<uint64_t, 8> FoundFns;
7674  uint64_t BaseSegmentAddress = 0;
7675
7676  getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
7677                        BaseSegmentAddress);
7678
7679  // Sort the symbols by address, just in case they didn't come in that way.
7680  llvm::stable_sort(Symbols, SymbolSorter());
7681
7682  // Build a data in code table that is sorted on by the address of each entry.
7683  uint64_t BaseAddress = 0;
7684  if (Header.filetype == MachO::MH_OBJECT)
7685    BaseAddress = Sections[0].getAddress();
7686  else
7687    BaseAddress = BaseSegmentAddress;
7688  DiceTable Dices;
7689  for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
7690       DI != DE; ++DI) {
7691    uint32_t Offset;
7692    DI->getOffset(Offset);
7693    Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
7694  }
7695  array_pod_sort(Dices.begin(), Dices.end());
7696
7697  // Try to find debug info and set up the DIContext for it.
7698  std::unique_ptr<DIContext> diContext;
7699  std::unique_ptr<Binary> DSYMBinary;
7700  std::unique_ptr<MemoryBuffer> DSYMBuf;
7701  if (UseDbg) {
7702    // If separate DSym file path was specified, parse it as a macho file,
7703    // get the sections and supply it to the section name parsing machinery.
7704    if (const ObjectFile *DbgObj =
7705            getMachODSymObject(MachOOF, Filename, DSYMBinary, DSYMBuf)) {
7706      // Setup the DIContext
7707      diContext = DWARFContext::create(*DbgObj);
7708    } else {
7709      return;
7710    }
7711  }
7712
7713  if (FilterSections.empty())
7714    outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
7715
7716  for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
7717    Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName();
7718    if (!SecNameOrErr) {
7719      consumeError(SecNameOrErr.takeError());
7720      continue;
7721    }
7722    if (*SecNameOrErr != DisSectName)
7723      continue;
7724
7725    DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
7726
7727    StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
7728    if (SegmentName != DisSegName)
7729      continue;
7730
7731    StringRef BytesStr =
7732        unwrapOrError(Sections[SectIdx].getContents(), Filename);
7733    ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr);
7734    uint64_t SectAddress = Sections[SectIdx].getAddress();
7735
7736    bool symbolTableWorked = false;
7737
7738    // Create a map of symbol addresses to symbol names for use by
7739    // the SymbolizerSymbolLookUp() routine.
7740    SymbolAddressMap AddrMap;
7741    bool DisSymNameFound = false;
7742    for (const SymbolRef &Symbol : MachOOF->symbols()) {
7743      SymbolRef::Type ST =
7744          unwrapOrError(Symbol.getType(), MachOOF->getFileName());
7745      if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
7746          ST == SymbolRef::ST_Other) {
7747        uint64_t Address = cantFail(Symbol.getValue());
7748        StringRef SymName =
7749            unwrapOrError(Symbol.getName(), MachOOF->getFileName());
7750        AddrMap[Address] = SymName;
7751        if (!DisSymName.empty() && DisSymName == SymName)
7752          DisSymNameFound = true;
7753      }
7754    }
7755    if (!DisSymName.empty() && !DisSymNameFound) {
7756      outs() << "Can't find -dis-symname: " << DisSymName << "\n";
7757      return;
7758    }
7759    // Set up the block of info used by the Symbolizer call backs.
7760    SymbolizerInfo.verbose = SymbolicOperands;
7761    SymbolizerInfo.O = MachOOF;
7762    SymbolizerInfo.S = Sections[SectIdx];
7763    SymbolizerInfo.AddrMap = &AddrMap;
7764    SymbolizerInfo.Sections = &Sections;
7765    // Same for the ThumbSymbolizer
7766    ThumbSymbolizerInfo.verbose = SymbolicOperands;
7767    ThumbSymbolizerInfo.O = MachOOF;
7768    ThumbSymbolizerInfo.S = Sections[SectIdx];
7769    ThumbSymbolizerInfo.AddrMap = &AddrMap;
7770    ThumbSymbolizerInfo.Sections = &Sections;
7771
7772    unsigned int Arch = MachOOF->getArch();
7773
7774    // Skip all symbols if this is a stubs file.
7775    if (Bytes.empty())
7776      return;
7777
7778    // If the section has symbols but no symbol at the start of the section
7779    // these are used to make sure the bytes before the first symbol are
7780    // disassembled.
7781    bool FirstSymbol = true;
7782    bool FirstSymbolAtSectionStart = true;
7783
7784    // Disassemble symbol by symbol.
7785    for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
7786      StringRef SymName =
7787          unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName());
7788      SymbolRef::Type ST =
7789          unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName());
7790      if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
7791        continue;
7792
7793      // Make sure the symbol is defined in this section.
7794      bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
7795      if (!containsSym) {
7796        if (!DisSymName.empty() && DisSymName == SymName) {
7797          outs() << "-dis-symname: " << DisSymName << " not in the section\n";
7798          return;
7799        }
7800        continue;
7801      }
7802      // The __mh_execute_header is special and we need to deal with that fact
7803      // this symbol is before the start of the (__TEXT,__text) section and at the
7804      // address of the start of the __TEXT segment.  This is because this symbol
7805      // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
7806      // start of the section in a standard MH_EXECUTE filetype.
7807      if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
7808        outs() << "-dis-symname: __mh_execute_header not in any section\n";
7809        return;
7810      }
7811      // When this code is trying to disassemble a symbol at a time and in the
7812      // case there is only the __mh_execute_header symbol left as in a stripped
7813      // executable, we need to deal with this by ignoring this symbol so the
7814      // whole section is disassembled and this symbol is then not displayed.
7815      if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
7816          SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
7817          SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
7818        continue;
7819
7820      // If we are only disassembling one symbol see if this is that symbol.
7821      if (!DisSymName.empty() && DisSymName != SymName)
7822        continue;
7823
7824      // Start at the address of the symbol relative to the section's address.
7825      uint64_t SectSize = Sections[SectIdx].getSize();
7826      uint64_t Start = cantFail(Symbols[SymIdx].getValue());
7827      uint64_t SectionAddress = Sections[SectIdx].getAddress();
7828      Start -= SectionAddress;
7829
7830      if (Start > SectSize) {
7831        outs() << "section data ends, " << SymName
7832               << " lies outside valid range\n";
7833        return;
7834      }
7835
7836      // Stop disassembling either at the beginning of the next symbol or at
7837      // the end of the section.
7838      bool containsNextSym = false;
7839      uint64_t NextSym = 0;
7840      uint64_t NextSymIdx = SymIdx + 1;
7841      while (Symbols.size() > NextSymIdx) {
7842        SymbolRef::Type NextSymType = unwrapOrError(
7843            Symbols[NextSymIdx].getType(), MachOOF->getFileName());
7844        if (NextSymType == SymbolRef::ST_Function) {
7845          containsNextSym =
7846              Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
7847          NextSym = cantFail(Symbols[NextSymIdx].getValue());
7848          NextSym -= SectionAddress;
7849          break;
7850        }
7851        ++NextSymIdx;
7852      }
7853
7854      uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
7855      uint64_t Size;
7856
7857      symbolTableWorked = true;
7858
7859      DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
7860      uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb));
7861      bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb;
7862
7863      // We only need the dedicated Thumb target if there's a real choice
7864      // (i.e. we're not targeting M-class) and the function is Thumb.
7865      bool UseThumbTarget = IsThumb && ThumbTarget;
7866
7867      // If we are not specifying a symbol to start disassembly with and this
7868      // is the first symbol in the section but not at the start of the section
7869      // then move the disassembly index to the start of the section and
7870      // don't print the symbol name just yet.  This is so the bytes before the
7871      // first symbol are disassembled.
7872      uint64_t SymbolStart = Start;
7873      if (DisSymName.empty() && FirstSymbol && Start != 0) {
7874        FirstSymbolAtSectionStart = false;
7875        Start = 0;
7876      }
7877      else
7878        outs() << SymName << ":\n";
7879
7880      DILineInfo lastLine;
7881      for (uint64_t Index = Start; Index < End; Index += Size) {
7882        MCInst Inst;
7883
7884        // If this is the first symbol in the section and it was not at the
7885        // start of the section, see if we are at its Index now and if so print
7886        // the symbol name.
7887        if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart)
7888          outs() << SymName << ":\n";
7889
7890        uint64_t PC = SectAddress + Index;
7891        if (LeadingAddr) {
7892          if (FullLeadingAddr) {
7893            if (MachOOF->is64Bit())
7894              outs() << format("%016" PRIx64, PC);
7895            else
7896              outs() << format("%08" PRIx64, PC);
7897          } else {
7898            outs() << format("%8" PRIx64 ":", PC);
7899          }
7900        }
7901        if (ShowRawInsn || Arch == Triple::arm)
7902          outs() << "\t";
7903
7904        if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size))
7905          continue;
7906
7907        SmallVector<char, 64> AnnotationsBytes;
7908        raw_svector_ostream Annotations(AnnotationsBytes);
7909
7910        bool gotInst;
7911        if (UseThumbTarget)
7912          gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
7913                                                PC, Annotations);
7914        else
7915          gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
7916                                           Annotations);
7917        if (gotInst) {
7918          if (ShowRawInsn || Arch == Triple::arm) {
7919            dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs());
7920          }
7921          formatted_raw_ostream FormattedOS(outs());
7922          StringRef AnnotationsStr = Annotations.str();
7923          if (UseThumbTarget)
7924            ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI,
7925                               FormattedOS);
7926          else
7927            IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS);
7928          emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
7929
7930          // Print debug info.
7931          if (diContext) {
7932            DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx});
7933            // Print valid line info if it changed.
7934            if (dli != lastLine && dli.Line != 0)
7935              outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
7936                     << dli.Column;
7937            lastLine = dli;
7938          }
7939          outs() << "\n";
7940        } else {
7941          if (MachOOF->getArchTriple().isX86()) {
7942            outs() << format("\t.byte 0x%02x #bad opcode\n",
7943                             *(Bytes.data() + Index) & 0xff);
7944            Size = 1; // skip exactly one illegible byte and move on.
7945          } else if (Arch == Triple::aarch64 ||
7946                     (Arch == Triple::arm && !IsThumb)) {
7947            uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7948                              (*(Bytes.data() + Index + 1) & 0xff) << 8 |
7949                              (*(Bytes.data() + Index + 2) & 0xff) << 16 |
7950                              (*(Bytes.data() + Index + 3) & 0xff) << 24;
7951            outs() << format("\t.long\t0x%08x\n", opcode);
7952            Size = 4;
7953          } else if (Arch == Triple::arm) {
7954            assert(IsThumb && "ARM mode should have been dealt with above");
7955            uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7956                              (*(Bytes.data() + Index + 1) & 0xff) << 8;
7957            outs() << format("\t.short\t0x%04x\n", opcode);
7958            Size = 2;
7959          } else{
7960            WithColor::warning(errs(), "llvm-objdump")
7961                << "invalid instruction encoding\n";
7962            if (Size == 0)
7963              Size = 1; // skip illegible bytes
7964          }
7965        }
7966      }
7967      // Now that we are done disassembled the first symbol set the bool that
7968      // were doing this to false.
7969      FirstSymbol = false;
7970    }
7971    if (!symbolTableWorked) {
7972      // Reading the symbol table didn't work, disassemble the whole section.
7973      uint64_t SectAddress = Sections[SectIdx].getAddress();
7974      uint64_t SectSize = Sections[SectIdx].getSize();
7975      uint64_t InstSize;
7976      for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
7977        MCInst Inst;
7978
7979        uint64_t PC = SectAddress + Index;
7980
7981        if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize))
7982          continue;
7983
7984        SmallVector<char, 64> AnnotationsBytes;
7985        raw_svector_ostream Annotations(AnnotationsBytes);
7986        if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
7987                                   Annotations)) {
7988          if (LeadingAddr) {
7989            if (FullLeadingAddr) {
7990              if (MachOOF->is64Bit())
7991                outs() << format("%016" PRIx64, PC);
7992              else
7993                outs() << format("%08" PRIx64, PC);
7994            } else {
7995              outs() << format("%8" PRIx64 ":", PC);
7996            }
7997          }
7998          if (ShowRawInsn || Arch == Triple::arm) {
7999            outs() << "\t";
8000            dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs());
8001          }
8002          StringRef AnnotationsStr = Annotations.str();
8003          IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs());
8004          outs() << "\n";
8005        } else {
8006          if (MachOOF->getArchTriple().isX86()) {
8007            outs() << format("\t.byte 0x%02x #bad opcode\n",
8008                             *(Bytes.data() + Index) & 0xff);
8009            InstSize = 1; // skip exactly one illegible byte and move on.
8010          } else {
8011            WithColor::warning(errs(), "llvm-objdump")
8012                << "invalid instruction encoding\n";
8013            if (InstSize == 0)
8014              InstSize = 1; // skip illegible bytes
8015          }
8016        }
8017      }
8018    }
8019    // The TripleName's need to be reset if we are called again for a different
8020    // architecture.
8021    TripleName = "";
8022    ThumbTripleName = "";
8023
8024    if (SymbolizerInfo.demangled_name != nullptr)
8025      free(SymbolizerInfo.demangled_name);
8026    if (ThumbSymbolizerInfo.demangled_name != nullptr)
8027      free(ThumbSymbolizerInfo.demangled_name);
8028  }
8029}
8030
8031//===----------------------------------------------------------------------===//
8032// __compact_unwind section dumping
8033//===----------------------------------------------------------------------===//
8034
8035namespace {
8036
8037template <typename T>
8038static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
8039  using llvm::support::little;
8040  using llvm::support::unaligned;
8041
8042  if (Offset + sizeof(T) > Contents.size()) {
8043    outs() << "warning: attempt to read past end of buffer\n";
8044    return T();
8045  }
8046
8047  uint64_t Val =
8048      support::endian::read<T, little, unaligned>(Contents.data() + Offset);
8049  return Val;
8050}
8051
8052template <typename T>
8053static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
8054  T Val = read<T>(Contents, Offset);
8055  Offset += sizeof(T);
8056  return Val;
8057}
8058
8059struct CompactUnwindEntry {
8060  uint32_t OffsetInSection;
8061
8062  uint64_t FunctionAddr;
8063  uint32_t Length;
8064  uint32_t CompactEncoding;
8065  uint64_t PersonalityAddr;
8066  uint64_t LSDAAddr;
8067
8068  RelocationRef FunctionReloc;
8069  RelocationRef PersonalityReloc;
8070  RelocationRef LSDAReloc;
8071
8072  CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
8073      : OffsetInSection(Offset) {
8074    if (Is64)
8075      read<uint64_t>(Contents, Offset);
8076    else
8077      read<uint32_t>(Contents, Offset);
8078  }
8079
8080private:
8081  template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
8082    FunctionAddr = readNext<UIntPtr>(Contents, Offset);
8083    Length = readNext<uint32_t>(Contents, Offset);
8084    CompactEncoding = readNext<uint32_t>(Contents, Offset);
8085    PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
8086    LSDAAddr = readNext<UIntPtr>(Contents, Offset);
8087  }
8088};
8089}
8090
8091/// Given a relocation from __compact_unwind, consisting of the RelocationRef
8092/// and data being relocated, determine the best base Name and Addend to use for
8093/// display purposes.
8094///
8095/// 1. An Extern relocation will directly reference a symbol (and the data is
8096///    then already an addend), so use that.
8097/// 2. Otherwise the data is an offset in the object file's layout; try to find
8098//     a symbol before it in the same section, and use the offset from there.
8099/// 3. Finally, if all that fails, fall back to an offset from the start of the
8100///    referenced section.
8101static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
8102                                      std::map<uint64_t, SymbolRef> &Symbols,
8103                                      const RelocationRef &Reloc, uint64_t Addr,
8104                                      StringRef &Name, uint64_t &Addend) {
8105  if (Reloc.getSymbol() != Obj->symbol_end()) {
8106    Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName());
8107    Addend = Addr;
8108    return;
8109  }
8110
8111  auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
8112  SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
8113
8114  uint64_t SectionAddr = RelocSection.getAddress();
8115
8116  auto Sym = Symbols.upper_bound(Addr);
8117  if (Sym == Symbols.begin()) {
8118    // The first symbol in the object is after this reference, the best we can
8119    // do is section-relative notation.
8120    if (Expected<StringRef> NameOrErr = RelocSection.getName())
8121      Name = *NameOrErr;
8122    else
8123      consumeError(NameOrErr.takeError());
8124
8125    Addend = Addr - SectionAddr;
8126    return;
8127  }
8128
8129  // Go back one so that SymbolAddress <= Addr.
8130  --Sym;
8131
8132  section_iterator SymSection =
8133      unwrapOrError(Sym->second.getSection(), Obj->getFileName());
8134  if (RelocSection == *SymSection) {
8135    // There's a valid symbol in the same section before this reference.
8136    Name = unwrapOrError(Sym->second.getName(), Obj->getFileName());
8137    Addend = Addr - Sym->first;
8138    return;
8139  }
8140
8141  // There is a symbol before this reference, but it's in a different
8142  // section. Probably not helpful to mention it, so use the section name.
8143  if (Expected<StringRef> NameOrErr = RelocSection.getName())
8144    Name = *NameOrErr;
8145  else
8146    consumeError(NameOrErr.takeError());
8147
8148  Addend = Addr - SectionAddr;
8149}
8150
8151static void printUnwindRelocDest(const MachOObjectFile *Obj,
8152                                 std::map<uint64_t, SymbolRef> &Symbols,
8153                                 const RelocationRef &Reloc, uint64_t Addr) {
8154  StringRef Name;
8155  uint64_t Addend;
8156
8157  if (!Reloc.getObject())
8158    return;
8159
8160  findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
8161
8162  outs() << Name;
8163  if (Addend)
8164    outs() << " + " << format("0x%" PRIx64, Addend);
8165}
8166
8167static void
8168printMachOCompactUnwindSection(const MachOObjectFile *Obj,
8169                               std::map<uint64_t, SymbolRef> &Symbols,
8170                               const SectionRef &CompactUnwind) {
8171
8172  if (!Obj->isLittleEndian()) {
8173    outs() << "Skipping big-endian __compact_unwind section\n";
8174    return;
8175  }
8176
8177  bool Is64 = Obj->is64Bit();
8178  uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
8179  uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
8180
8181  StringRef Contents =
8182      unwrapOrError(CompactUnwind.getContents(), Obj->getFileName());
8183  SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
8184
8185  // First populate the initial raw offsets, encodings and so on from the entry.
8186  for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
8187    CompactUnwindEntry Entry(Contents, Offset, Is64);
8188    CompactUnwinds.push_back(Entry);
8189  }
8190
8191  // Next we need to look at the relocations to find out what objects are
8192  // actually being referred to.
8193  for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
8194    uint64_t RelocAddress = Reloc.getOffset();
8195
8196    uint32_t EntryIdx = RelocAddress / EntrySize;
8197    uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
8198    CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
8199
8200    if (OffsetInEntry == 0)
8201      Entry.FunctionReloc = Reloc;
8202    else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
8203      Entry.PersonalityReloc = Reloc;
8204    else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
8205      Entry.LSDAReloc = Reloc;
8206    else {
8207      outs() << "Invalid relocation in __compact_unwind section\n";
8208      return;
8209    }
8210  }
8211
8212  // Finally, we're ready to print the data we've gathered.
8213  outs() << "Contents of __compact_unwind section:\n";
8214  for (auto &Entry : CompactUnwinds) {
8215    outs() << "  Entry at offset "
8216           << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
8217
8218    // 1. Start of the region this entry applies to.
8219    outs() << "    start:                " << format("0x%" PRIx64,
8220                                                     Entry.FunctionAddr) << ' ';
8221    printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
8222    outs() << '\n';
8223
8224    // 2. Length of the region this entry applies to.
8225    outs() << "    length:               " << format("0x%" PRIx32, Entry.Length)
8226           << '\n';
8227    // 3. The 32-bit compact encoding.
8228    outs() << "    compact encoding:     "
8229           << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
8230
8231    // 4. The personality function, if present.
8232    if (Entry.PersonalityReloc.getObject()) {
8233      outs() << "    personality function: "
8234             << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
8235      printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
8236                           Entry.PersonalityAddr);
8237      outs() << '\n';
8238    }
8239
8240    // 5. This entry's language-specific data area.
8241    if (Entry.LSDAReloc.getObject()) {
8242      outs() << "    LSDA:                 " << format("0x%" PRIx64,
8243                                                       Entry.LSDAAddr) << ' ';
8244      printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
8245      outs() << '\n';
8246    }
8247  }
8248}
8249
8250//===----------------------------------------------------------------------===//
8251// __unwind_info section dumping
8252//===----------------------------------------------------------------------===//
8253
8254static void printRegularSecondLevelUnwindPage(StringRef PageData) {
8255  ptrdiff_t Pos = 0;
8256  uint32_t Kind = readNext<uint32_t>(PageData, Pos);
8257  (void)Kind;
8258  assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
8259
8260  uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
8261  uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
8262
8263  Pos = EntriesStart;
8264  for (unsigned i = 0; i < NumEntries; ++i) {
8265    uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
8266    uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
8267
8268    outs() << "      [" << i << "]: "
8269           << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8270           << ", "
8271           << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
8272  }
8273}
8274
8275static void printCompressedSecondLevelUnwindPage(
8276    StringRef PageData, uint32_t FunctionBase,
8277    const SmallVectorImpl<uint32_t> &CommonEncodings) {
8278  ptrdiff_t Pos = 0;
8279  uint32_t Kind = readNext<uint32_t>(PageData, Pos);
8280  (void)Kind;
8281  assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
8282
8283  uint32_t NumCommonEncodings = CommonEncodings.size();
8284  uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
8285  uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
8286
8287  uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos);
8288  uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos);
8289  SmallVector<uint32_t, 64> PageEncodings;
8290  if (NumPageEncodings) {
8291    outs() << "      Page encodings: (count = " << NumPageEncodings << ")\n";
8292    Pos = PageEncodingsStart;
8293    for (unsigned i = 0; i < NumPageEncodings; ++i) {
8294      uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
8295      PageEncodings.push_back(Encoding);
8296      outs() << "        encoding[" << (i + NumCommonEncodings)
8297             << "]: " << format("0x%08" PRIx32, Encoding) << '\n';
8298    }
8299  }
8300
8301  Pos = EntriesStart;
8302  for (unsigned i = 0; i < NumEntries; ++i) {
8303    uint32_t Entry = readNext<uint32_t>(PageData, Pos);
8304    uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
8305    uint32_t EncodingIdx = Entry >> 24;
8306
8307    uint32_t Encoding;
8308    if (EncodingIdx < NumCommonEncodings)
8309      Encoding = CommonEncodings[EncodingIdx];
8310    else
8311      Encoding = PageEncodings[EncodingIdx - NumCommonEncodings];
8312
8313    outs() << "      [" << i << "]: "
8314           << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8315           << ", "
8316           << "encoding[" << EncodingIdx
8317           << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
8318  }
8319}
8320
8321static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
8322                                        std::map<uint64_t, SymbolRef> &Symbols,
8323                                        const SectionRef &UnwindInfo) {
8324
8325  if (!Obj->isLittleEndian()) {
8326    outs() << "Skipping big-endian __unwind_info section\n";
8327    return;
8328  }
8329
8330  outs() << "Contents of __unwind_info section:\n";
8331
8332  StringRef Contents =
8333      unwrapOrError(UnwindInfo.getContents(), Obj->getFileName());
8334  ptrdiff_t Pos = 0;
8335
8336  //===----------------------------------
8337  // Section header
8338  //===----------------------------------
8339
8340  uint32_t Version = readNext<uint32_t>(Contents, Pos);
8341  outs() << "  Version:                                   "
8342         << format("0x%" PRIx32, Version) << '\n';
8343  if (Version != 1) {
8344    outs() << "    Skipping section with unknown version\n";
8345    return;
8346  }
8347
8348  uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
8349  outs() << "  Common encodings array section offset:     "
8350         << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
8351  uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
8352  outs() << "  Number of common encodings in array:       "
8353         << format("0x%" PRIx32, NumCommonEncodings) << '\n';
8354
8355  uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
8356  outs() << "  Personality function array section offset: "
8357         << format("0x%" PRIx32, PersonalitiesStart) << '\n';
8358  uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
8359  outs() << "  Number of personality functions in array:  "
8360         << format("0x%" PRIx32, NumPersonalities) << '\n';
8361
8362  uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
8363  outs() << "  Index array section offset:                "
8364         << format("0x%" PRIx32, IndicesStart) << '\n';
8365  uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
8366  outs() << "  Number of indices in array:                "
8367         << format("0x%" PRIx32, NumIndices) << '\n';
8368
8369  //===----------------------------------
8370  // A shared list of common encodings
8371  //===----------------------------------
8372
8373  // These occupy indices in the range [0, N] whenever an encoding is referenced
8374  // from a compressed 2nd level index table. In practice the linker only
8375  // creates ~128 of these, so that indices are available to embed encodings in
8376  // the 2nd level index.
8377
8378  SmallVector<uint32_t, 64> CommonEncodings;
8379  outs() << "  Common encodings: (count = " << NumCommonEncodings << ")\n";
8380  Pos = CommonEncodingsStart;
8381  for (unsigned i = 0; i < NumCommonEncodings; ++i) {
8382    uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
8383    CommonEncodings.push_back(Encoding);
8384
8385    outs() << "    encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
8386           << '\n';
8387  }
8388
8389  //===----------------------------------
8390  // Personality functions used in this executable
8391  //===----------------------------------
8392
8393  // There should be only a handful of these (one per source language,
8394  // roughly). Particularly since they only get 2 bits in the compact encoding.
8395
8396  outs() << "  Personality functions: (count = " << NumPersonalities << ")\n";
8397  Pos = PersonalitiesStart;
8398  for (unsigned i = 0; i < NumPersonalities; ++i) {
8399    uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
8400    outs() << "    personality[" << i + 1
8401           << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
8402  }
8403
8404  //===----------------------------------
8405  // The level 1 index entries
8406  //===----------------------------------
8407
8408  // These specify an approximate place to start searching for the more detailed
8409  // information, sorted by PC.
8410
8411  struct IndexEntry {
8412    uint32_t FunctionOffset;
8413    uint32_t SecondLevelPageStart;
8414    uint32_t LSDAStart;
8415  };
8416
8417  SmallVector<IndexEntry, 4> IndexEntries;
8418
8419  outs() << "  Top level indices: (count = " << NumIndices << ")\n";
8420  Pos = IndicesStart;
8421  for (unsigned i = 0; i < NumIndices; ++i) {
8422    IndexEntry Entry;
8423
8424    Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
8425    Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
8426    Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
8427    IndexEntries.push_back(Entry);
8428
8429    outs() << "    [" << i << "]: "
8430           << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
8431           << ", "
8432           << "2nd level page offset="
8433           << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
8434           << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
8435  }
8436
8437  //===----------------------------------
8438  // Next come the LSDA tables
8439  //===----------------------------------
8440
8441  // The LSDA layout is rather implicit: it's a contiguous array of entries from
8442  // the first top-level index's LSDAOffset to the last (sentinel).
8443
8444  outs() << "  LSDA descriptors:\n";
8445  Pos = IndexEntries[0].LSDAStart;
8446  const uint32_t LSDASize = 2 * sizeof(uint32_t);
8447  int NumLSDAs =
8448      (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
8449
8450  for (int i = 0; i < NumLSDAs; ++i) {
8451    uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
8452    uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
8453    outs() << "    [" << i << "]: "
8454           << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8455           << ", "
8456           << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
8457  }
8458
8459  //===----------------------------------
8460  // Finally, the 2nd level indices
8461  //===----------------------------------
8462
8463  // Generally these are 4K in size, and have 2 possible forms:
8464  //   + Regular stores up to 511 entries with disparate encodings
8465  //   + Compressed stores up to 1021 entries if few enough compact encoding
8466  //     values are used.
8467  outs() << "  Second level indices:\n";
8468  for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
8469    // The final sentinel top-level index has no associated 2nd level page
8470    if (IndexEntries[i].SecondLevelPageStart == 0)
8471      break;
8472
8473    outs() << "    Second level index[" << i << "]: "
8474           << "offset in section="
8475           << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
8476           << ", "
8477           << "base function offset="
8478           << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
8479
8480    Pos = IndexEntries[i].SecondLevelPageStart;
8481    if (Pos + sizeof(uint32_t) > Contents.size()) {
8482      outs() << "warning: invalid offset for second level page: " << Pos << '\n';
8483      continue;
8484    }
8485
8486    uint32_t Kind =
8487        *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
8488    if (Kind == 2)
8489      printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
8490    else if (Kind == 3)
8491      printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
8492                                           IndexEntries[i].FunctionOffset,
8493                                           CommonEncodings);
8494    else
8495      outs() << "    Skipping 2nd level page with unknown kind " << Kind
8496             << '\n';
8497  }
8498}
8499
8500void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) {
8501  std::map<uint64_t, SymbolRef> Symbols;
8502  for (const SymbolRef &SymRef : Obj->symbols()) {
8503    // Discard any undefined or absolute symbols. They're not going to take part
8504    // in the convenience lookup for unwind info and just take up resources.
8505    auto SectOrErr = SymRef.getSection();
8506    if (!SectOrErr) {
8507      // TODO: Actually report errors helpfully.
8508      consumeError(SectOrErr.takeError());
8509      continue;
8510    }
8511    section_iterator Section = *SectOrErr;
8512    if (Section == Obj->section_end())
8513      continue;
8514
8515    uint64_t Addr = cantFail(SymRef.getValue());
8516    Symbols.insert(std::make_pair(Addr, SymRef));
8517  }
8518
8519  for (const SectionRef &Section : Obj->sections()) {
8520    StringRef SectName;
8521    if (Expected<StringRef> NameOrErr = Section.getName())
8522      SectName = *NameOrErr;
8523    else
8524      consumeError(NameOrErr.takeError());
8525
8526    if (SectName == "__compact_unwind")
8527      printMachOCompactUnwindSection(Obj, Symbols, Section);
8528    else if (SectName == "__unwind_info")
8529      printMachOUnwindInfoSection(Obj, Symbols, Section);
8530  }
8531}
8532
8533static void PrintMachHeader(uint32_t magic, uint32_t cputype,
8534                            uint32_t cpusubtype, uint32_t filetype,
8535                            uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
8536                            bool verbose) {
8537  outs() << "Mach header\n";
8538  outs() << "      magic cputype cpusubtype  caps    filetype ncmds "
8539            "sizeofcmds      flags\n";
8540  if (verbose) {
8541    if (magic == MachO::MH_MAGIC)
8542      outs() << "   MH_MAGIC";
8543    else if (magic == MachO::MH_MAGIC_64)
8544      outs() << "MH_MAGIC_64";
8545    else
8546      outs() << format(" 0x%08" PRIx32, magic);
8547    switch (cputype) {
8548    case MachO::CPU_TYPE_I386:
8549      outs() << "    I386";
8550      switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8551      case MachO::CPU_SUBTYPE_I386_ALL:
8552        outs() << "        ALL";
8553        break;
8554      default:
8555        outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8556        break;
8557      }
8558      break;
8559    case MachO::CPU_TYPE_X86_64:
8560      outs() << "  X86_64";
8561      switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8562      case MachO::CPU_SUBTYPE_X86_64_ALL:
8563        outs() << "        ALL";
8564        break;
8565      case MachO::CPU_SUBTYPE_X86_64_H:
8566        outs() << "    Haswell";
8567        break;
8568      default:
8569        outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8570        break;
8571      }
8572      break;
8573    case MachO::CPU_TYPE_ARM:
8574      outs() << "     ARM";
8575      switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8576      case MachO::CPU_SUBTYPE_ARM_ALL:
8577        outs() << "        ALL";
8578        break;
8579      case MachO::CPU_SUBTYPE_ARM_V4T:
8580        outs() << "        V4T";
8581        break;
8582      case MachO::CPU_SUBTYPE_ARM_V5TEJ:
8583        outs() << "      V5TEJ";
8584        break;
8585      case MachO::CPU_SUBTYPE_ARM_XSCALE:
8586        outs() << "     XSCALE";
8587        break;
8588      case MachO::CPU_SUBTYPE_ARM_V6:
8589        outs() << "         V6";
8590        break;
8591      case MachO::CPU_SUBTYPE_ARM_V6M:
8592        outs() << "        V6M";
8593        break;
8594      case MachO::CPU_SUBTYPE_ARM_V7:
8595        outs() << "         V7";
8596        break;
8597      case MachO::CPU_SUBTYPE_ARM_V7EM:
8598        outs() << "       V7EM";
8599        break;
8600      case MachO::CPU_SUBTYPE_ARM_V7K:
8601        outs() << "        V7K";
8602        break;
8603      case MachO::CPU_SUBTYPE_ARM_V7M:
8604        outs() << "        V7M";
8605        break;
8606      case MachO::CPU_SUBTYPE_ARM_V7S:
8607        outs() << "        V7S";
8608        break;
8609      default:
8610        outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8611        break;
8612      }
8613      break;
8614    case MachO::CPU_TYPE_ARM64:
8615      outs() << "   ARM64";
8616      switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8617      case MachO::CPU_SUBTYPE_ARM64_ALL:
8618        outs() << "        ALL";
8619        break;
8620      case MachO::CPU_SUBTYPE_ARM64_V8:
8621        outs() << "         V8";
8622        break;
8623      case MachO::CPU_SUBTYPE_ARM64E:
8624        outs() << "          E";
8625        break;
8626      default:
8627        outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8628        break;
8629      }
8630      break;
8631    case MachO::CPU_TYPE_ARM64_32:
8632      outs() << " ARM64_32";
8633      switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8634      case MachO::CPU_SUBTYPE_ARM64_32_V8:
8635        outs() << "        V8";
8636        break;
8637      default:
8638        outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8639        break;
8640      }
8641      break;
8642    case MachO::CPU_TYPE_POWERPC:
8643      outs() << "     PPC";
8644      switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8645      case MachO::CPU_SUBTYPE_POWERPC_ALL:
8646        outs() << "        ALL";
8647        break;
8648      default:
8649        outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8650        break;
8651      }
8652      break;
8653    case MachO::CPU_TYPE_POWERPC64:
8654      outs() << "   PPC64";
8655      switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8656      case MachO::CPU_SUBTYPE_POWERPC_ALL:
8657        outs() << "        ALL";
8658        break;
8659      default:
8660        outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8661        break;
8662      }
8663      break;
8664    default:
8665      outs() << format(" %7d", cputype);
8666      outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8667      break;
8668    }
8669    if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
8670      outs() << " LIB64";
8671    } else {
8672      outs() << format("  0x%02" PRIx32,
8673                       (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8674    }
8675    switch (filetype) {
8676    case MachO::MH_OBJECT:
8677      outs() << "      OBJECT";
8678      break;
8679    case MachO::MH_EXECUTE:
8680      outs() << "     EXECUTE";
8681      break;
8682    case MachO::MH_FVMLIB:
8683      outs() << "      FVMLIB";
8684      break;
8685    case MachO::MH_CORE:
8686      outs() << "        CORE";
8687      break;
8688    case MachO::MH_PRELOAD:
8689      outs() << "     PRELOAD";
8690      break;
8691    case MachO::MH_DYLIB:
8692      outs() << "       DYLIB";
8693      break;
8694    case MachO::MH_DYLIB_STUB:
8695      outs() << "  DYLIB_STUB";
8696      break;
8697    case MachO::MH_DYLINKER:
8698      outs() << "    DYLINKER";
8699      break;
8700    case MachO::MH_BUNDLE:
8701      outs() << "      BUNDLE";
8702      break;
8703    case MachO::MH_DSYM:
8704      outs() << "        DSYM";
8705      break;
8706    case MachO::MH_KEXT_BUNDLE:
8707      outs() << "  KEXTBUNDLE";
8708      break;
8709    case MachO::MH_FILESET:
8710      outs() << "     FILESET";
8711      break;
8712    default:
8713      outs() << format("  %10u", filetype);
8714      break;
8715    }
8716    outs() << format(" %5u", ncmds);
8717    outs() << format(" %10u", sizeofcmds);
8718    uint32_t f = flags;
8719    if (f & MachO::MH_NOUNDEFS) {
8720      outs() << "   NOUNDEFS";
8721      f &= ~MachO::MH_NOUNDEFS;
8722    }
8723    if (f & MachO::MH_INCRLINK) {
8724      outs() << " INCRLINK";
8725      f &= ~MachO::MH_INCRLINK;
8726    }
8727    if (f & MachO::MH_DYLDLINK) {
8728      outs() << " DYLDLINK";
8729      f &= ~MachO::MH_DYLDLINK;
8730    }
8731    if (f & MachO::MH_BINDATLOAD) {
8732      outs() << " BINDATLOAD";
8733      f &= ~MachO::MH_BINDATLOAD;
8734    }
8735    if (f & MachO::MH_PREBOUND) {
8736      outs() << " PREBOUND";
8737      f &= ~MachO::MH_PREBOUND;
8738    }
8739    if (f & MachO::MH_SPLIT_SEGS) {
8740      outs() << " SPLIT_SEGS";
8741      f &= ~MachO::MH_SPLIT_SEGS;
8742    }
8743    if (f & MachO::MH_LAZY_INIT) {
8744      outs() << " LAZY_INIT";
8745      f &= ~MachO::MH_LAZY_INIT;
8746    }
8747    if (f & MachO::MH_TWOLEVEL) {
8748      outs() << " TWOLEVEL";
8749      f &= ~MachO::MH_TWOLEVEL;
8750    }
8751    if (f & MachO::MH_FORCE_FLAT) {
8752      outs() << " FORCE_FLAT";
8753      f &= ~MachO::MH_FORCE_FLAT;
8754    }
8755    if (f & MachO::MH_NOMULTIDEFS) {
8756      outs() << " NOMULTIDEFS";
8757      f &= ~MachO::MH_NOMULTIDEFS;
8758    }
8759    if (f & MachO::MH_NOFIXPREBINDING) {
8760      outs() << " NOFIXPREBINDING";
8761      f &= ~MachO::MH_NOFIXPREBINDING;
8762    }
8763    if (f & MachO::MH_PREBINDABLE) {
8764      outs() << " PREBINDABLE";
8765      f &= ~MachO::MH_PREBINDABLE;
8766    }
8767    if (f & MachO::MH_ALLMODSBOUND) {
8768      outs() << " ALLMODSBOUND";
8769      f &= ~MachO::MH_ALLMODSBOUND;
8770    }
8771    if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
8772      outs() << " SUBSECTIONS_VIA_SYMBOLS";
8773      f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
8774    }
8775    if (f & MachO::MH_CANONICAL) {
8776      outs() << " CANONICAL";
8777      f &= ~MachO::MH_CANONICAL;
8778    }
8779    if (f & MachO::MH_WEAK_DEFINES) {
8780      outs() << " WEAK_DEFINES";
8781      f &= ~MachO::MH_WEAK_DEFINES;
8782    }
8783    if (f & MachO::MH_BINDS_TO_WEAK) {
8784      outs() << " BINDS_TO_WEAK";
8785      f &= ~MachO::MH_BINDS_TO_WEAK;
8786    }
8787    if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
8788      outs() << " ALLOW_STACK_EXECUTION";
8789      f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
8790    }
8791    if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
8792      outs() << " DEAD_STRIPPABLE_DYLIB";
8793      f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
8794    }
8795    if (f & MachO::MH_PIE) {
8796      outs() << " PIE";
8797      f &= ~MachO::MH_PIE;
8798    }
8799    if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
8800      outs() << " NO_REEXPORTED_DYLIBS";
8801      f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
8802    }
8803    if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
8804      outs() << " MH_HAS_TLV_DESCRIPTORS";
8805      f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
8806    }
8807    if (f & MachO::MH_NO_HEAP_EXECUTION) {
8808      outs() << " MH_NO_HEAP_EXECUTION";
8809      f &= ~MachO::MH_NO_HEAP_EXECUTION;
8810    }
8811    if (f & MachO::MH_APP_EXTENSION_SAFE) {
8812      outs() << " APP_EXTENSION_SAFE";
8813      f &= ~MachO::MH_APP_EXTENSION_SAFE;
8814    }
8815    if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
8816      outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO";
8817      f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO;
8818    }
8819    if (f != 0 || flags == 0)
8820      outs() << format(" 0x%08" PRIx32, f);
8821  } else {
8822    outs() << format(" 0x%08" PRIx32, magic);
8823    outs() << format(" %7d", cputype);
8824    outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8825    outs() << format("  0x%02" PRIx32,
8826                     (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8827    outs() << format("  %10u", filetype);
8828    outs() << format(" %5u", ncmds);
8829    outs() << format(" %10u", sizeofcmds);
8830    outs() << format(" 0x%08" PRIx32, flags);
8831  }
8832  outs() << "\n";
8833}
8834
8835static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
8836                                StringRef SegName, uint64_t vmaddr,
8837                                uint64_t vmsize, uint64_t fileoff,
8838                                uint64_t filesize, uint32_t maxprot,
8839                                uint32_t initprot, uint32_t nsects,
8840                                uint32_t flags, uint32_t object_size,
8841                                bool verbose) {
8842  uint64_t expected_cmdsize;
8843  if (cmd == MachO::LC_SEGMENT) {
8844    outs() << "      cmd LC_SEGMENT\n";
8845    expected_cmdsize = nsects;
8846    expected_cmdsize *= sizeof(struct MachO::section);
8847    expected_cmdsize += sizeof(struct MachO::segment_command);
8848  } else {
8849    outs() << "      cmd LC_SEGMENT_64\n";
8850    expected_cmdsize = nsects;
8851    expected_cmdsize *= sizeof(struct MachO::section_64);
8852    expected_cmdsize += sizeof(struct MachO::segment_command_64);
8853  }
8854  outs() << "  cmdsize " << cmdsize;
8855  if (cmdsize != expected_cmdsize)
8856    outs() << " Inconsistent size\n";
8857  else
8858    outs() << "\n";
8859  outs() << "  segname " << SegName << "\n";
8860  if (cmd == MachO::LC_SEGMENT_64) {
8861    outs() << "   vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
8862    outs() << "   vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
8863  } else {
8864    outs() << "   vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
8865    outs() << "   vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
8866  }
8867  outs() << "  fileoff " << fileoff;
8868  if (fileoff > object_size)
8869    outs() << " (past end of file)\n";
8870  else
8871    outs() << "\n";
8872  outs() << " filesize " << filesize;
8873  if (fileoff + filesize > object_size)
8874    outs() << " (past end of file)\n";
8875  else
8876    outs() << "\n";
8877  if (verbose) {
8878    if ((maxprot &
8879         ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8880           MachO::VM_PROT_EXECUTE)) != 0)
8881      outs() << "  maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
8882    else {
8883      outs() << "  maxprot ";
8884      outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
8885      outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8886      outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8887    }
8888    if ((initprot &
8889         ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8890           MachO::VM_PROT_EXECUTE)) != 0)
8891      outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
8892    else {
8893      outs() << " initprot ";
8894      outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
8895      outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8896      outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8897    }
8898  } else {
8899    outs() << "  maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
8900    outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
8901  }
8902  outs() << "   nsects " << nsects << "\n";
8903  if (verbose) {
8904    outs() << "    flags";
8905    if (flags == 0)
8906      outs() << " (none)\n";
8907    else {
8908      if (flags & MachO::SG_HIGHVM) {
8909        outs() << " HIGHVM";
8910        flags &= ~MachO::SG_HIGHVM;
8911      }
8912      if (flags & MachO::SG_FVMLIB) {
8913        outs() << " FVMLIB";
8914        flags &= ~MachO::SG_FVMLIB;
8915      }
8916      if (flags & MachO::SG_NORELOC) {
8917        outs() << " NORELOC";
8918        flags &= ~MachO::SG_NORELOC;
8919      }
8920      if (flags & MachO::SG_PROTECTED_VERSION_1) {
8921        outs() << " PROTECTED_VERSION_1";
8922        flags &= ~MachO::SG_PROTECTED_VERSION_1;
8923      }
8924      if (flags & MachO::SG_READ_ONLY) {
8925        // Apple's otool prints the SG_ prefix for this flag, but not for the
8926        // others.
8927        outs() << " SG_READ_ONLY";
8928        flags &= ~MachO::SG_READ_ONLY;
8929      }
8930      if (flags)
8931        outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
8932      else
8933        outs() << "\n";
8934    }
8935  } else {
8936    outs() << "    flags " << format("0x%" PRIx32, flags) << "\n";
8937  }
8938}
8939
8940static void PrintSection(const char *sectname, const char *segname,
8941                         uint64_t addr, uint64_t size, uint32_t offset,
8942                         uint32_t align, uint32_t reloff, uint32_t nreloc,
8943                         uint32_t flags, uint32_t reserved1, uint32_t reserved2,
8944                         uint32_t cmd, const char *sg_segname,
8945                         uint32_t filetype, uint32_t object_size,
8946                         bool verbose) {
8947  outs() << "Section\n";
8948  outs() << "  sectname " << format("%.16s\n", sectname);
8949  outs() << "   segname " << format("%.16s", segname);
8950  if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
8951    outs() << " (does not match segment)\n";
8952  else
8953    outs() << "\n";
8954  if (cmd == MachO::LC_SEGMENT_64) {
8955    outs() << "      addr " << format("0x%016" PRIx64, addr) << "\n";
8956    outs() << "      size " << format("0x%016" PRIx64, size);
8957  } else {
8958    outs() << "      addr " << format("0x%08" PRIx64, addr) << "\n";
8959    outs() << "      size " << format("0x%08" PRIx64, size);
8960  }
8961  if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
8962    outs() << " (past end of file)\n";
8963  else
8964    outs() << "\n";
8965  outs() << "    offset " << offset;
8966  if (offset > object_size)
8967    outs() << " (past end of file)\n";
8968  else
8969    outs() << "\n";
8970  uint32_t align_shifted = 1 << align;
8971  outs() << "     align 2^" << align << " (" << align_shifted << ")\n";
8972  outs() << "    reloff " << reloff;
8973  if (reloff > object_size)
8974    outs() << " (past end of file)\n";
8975  else
8976    outs() << "\n";
8977  outs() << "    nreloc " << nreloc;
8978  if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
8979    outs() << " (past end of file)\n";
8980  else
8981    outs() << "\n";
8982  uint32_t section_type = flags & MachO::SECTION_TYPE;
8983  if (verbose) {
8984    outs() << "      type";
8985    if (section_type == MachO::S_REGULAR)
8986      outs() << " S_REGULAR\n";
8987    else if (section_type == MachO::S_ZEROFILL)
8988      outs() << " S_ZEROFILL\n";
8989    else if (section_type == MachO::S_CSTRING_LITERALS)
8990      outs() << " S_CSTRING_LITERALS\n";
8991    else if (section_type == MachO::S_4BYTE_LITERALS)
8992      outs() << " S_4BYTE_LITERALS\n";
8993    else if (section_type == MachO::S_8BYTE_LITERALS)
8994      outs() << " S_8BYTE_LITERALS\n";
8995    else if (section_type == MachO::S_16BYTE_LITERALS)
8996      outs() << " S_16BYTE_LITERALS\n";
8997    else if (section_type == MachO::S_LITERAL_POINTERS)
8998      outs() << " S_LITERAL_POINTERS\n";
8999    else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
9000      outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
9001    else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
9002      outs() << " S_LAZY_SYMBOL_POINTERS\n";
9003    else if (section_type == MachO::S_SYMBOL_STUBS)
9004      outs() << " S_SYMBOL_STUBS\n";
9005    else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
9006      outs() << " S_MOD_INIT_FUNC_POINTERS\n";
9007    else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
9008      outs() << " S_MOD_TERM_FUNC_POINTERS\n";
9009    else if (section_type == MachO::S_COALESCED)
9010      outs() << " S_COALESCED\n";
9011    else if (section_type == MachO::S_INTERPOSING)
9012      outs() << " S_INTERPOSING\n";
9013    else if (section_type == MachO::S_DTRACE_DOF)
9014      outs() << " S_DTRACE_DOF\n";
9015    else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
9016      outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
9017    else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
9018      outs() << " S_THREAD_LOCAL_REGULAR\n";
9019    else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
9020      outs() << " S_THREAD_LOCAL_ZEROFILL\n";
9021    else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
9022      outs() << " S_THREAD_LOCAL_VARIABLES\n";
9023    else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
9024      outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
9025    else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
9026      outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
9027    else if (section_type == MachO::S_INIT_FUNC_OFFSETS)
9028      outs() << " S_INIT_FUNC_OFFSETS\n";
9029    else
9030      outs() << format("0x%08" PRIx32, section_type) << "\n";
9031    outs() << "attributes";
9032    uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
9033    if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
9034      outs() << " PURE_INSTRUCTIONS";
9035    if (section_attributes & MachO::S_ATTR_NO_TOC)
9036      outs() << " NO_TOC";
9037    if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
9038      outs() << " STRIP_STATIC_SYMS";
9039    if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
9040      outs() << " NO_DEAD_STRIP";
9041    if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
9042      outs() << " LIVE_SUPPORT";
9043    if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
9044      outs() << " SELF_MODIFYING_CODE";
9045    if (section_attributes & MachO::S_ATTR_DEBUG)
9046      outs() << " DEBUG";
9047    if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
9048      outs() << " SOME_INSTRUCTIONS";
9049    if (section_attributes & MachO::S_ATTR_EXT_RELOC)
9050      outs() << " EXT_RELOC";
9051    if (section_attributes & MachO::S_ATTR_LOC_RELOC)
9052      outs() << " LOC_RELOC";
9053    if (section_attributes == 0)
9054      outs() << " (none)";
9055    outs() << "\n";
9056  } else
9057    outs() << "     flags " << format("0x%08" PRIx32, flags) << "\n";
9058  outs() << " reserved1 " << reserved1;
9059  if (section_type == MachO::S_SYMBOL_STUBS ||
9060      section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
9061      section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
9062      section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
9063      section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
9064    outs() << " (index into indirect symbol table)\n";
9065  else
9066    outs() << "\n";
9067  outs() << " reserved2 " << reserved2;
9068  if (section_type == MachO::S_SYMBOL_STUBS)
9069    outs() << " (size of stubs)\n";
9070  else
9071    outs() << "\n";
9072}
9073
9074static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
9075                                   uint32_t object_size) {
9076  outs() << "     cmd LC_SYMTAB\n";
9077  outs() << " cmdsize " << st.cmdsize;
9078  if (st.cmdsize != sizeof(struct MachO::symtab_command))
9079    outs() << " Incorrect size\n";
9080  else
9081    outs() << "\n";
9082  outs() << "  symoff " << st.symoff;
9083  if (st.symoff > object_size)
9084    outs() << " (past end of file)\n";
9085  else
9086    outs() << "\n";
9087  outs() << "   nsyms " << st.nsyms;
9088  uint64_t big_size;
9089  if (Is64Bit) {
9090    big_size = st.nsyms;
9091    big_size *= sizeof(struct MachO::nlist_64);
9092    big_size += st.symoff;
9093    if (big_size > object_size)
9094      outs() << " (past end of file)\n";
9095    else
9096      outs() << "\n";
9097  } else {
9098    big_size = st.nsyms;
9099    big_size *= sizeof(struct MachO::nlist);
9100    big_size += st.symoff;
9101    if (big_size > object_size)
9102      outs() << " (past end of file)\n";
9103    else
9104      outs() << "\n";
9105  }
9106  outs() << "  stroff " << st.stroff;
9107  if (st.stroff > object_size)
9108    outs() << " (past end of file)\n";
9109  else
9110    outs() << "\n";
9111  outs() << " strsize " << st.strsize;
9112  big_size = st.stroff;
9113  big_size += st.strsize;
9114  if (big_size > object_size)
9115    outs() << " (past end of file)\n";
9116  else
9117    outs() << "\n";
9118}
9119
9120static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
9121                                     uint32_t nsyms, uint32_t object_size,
9122                                     bool Is64Bit) {
9123  outs() << "            cmd LC_DYSYMTAB\n";
9124  outs() << "        cmdsize " << dyst.cmdsize;
9125  if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
9126    outs() << " Incorrect size\n";
9127  else
9128    outs() << "\n";
9129  outs() << "      ilocalsym " << dyst.ilocalsym;
9130  if (dyst.ilocalsym > nsyms)
9131    outs() << " (greater than the number of symbols)\n";
9132  else
9133    outs() << "\n";
9134  outs() << "      nlocalsym " << dyst.nlocalsym;
9135  uint64_t big_size;
9136  big_size = dyst.ilocalsym;
9137  big_size += dyst.nlocalsym;
9138  if (big_size > nsyms)
9139    outs() << " (past the end of the symbol table)\n";
9140  else
9141    outs() << "\n";
9142  outs() << "     iextdefsym " << dyst.iextdefsym;
9143  if (dyst.iextdefsym > nsyms)
9144    outs() << " (greater than the number of symbols)\n";
9145  else
9146    outs() << "\n";
9147  outs() << "     nextdefsym " << dyst.nextdefsym;
9148  big_size = dyst.iextdefsym;
9149  big_size += dyst.nextdefsym;
9150  if (big_size > nsyms)
9151    outs() << " (past the end of the symbol table)\n";
9152  else
9153    outs() << "\n";
9154  outs() << "      iundefsym " << dyst.iundefsym;
9155  if (dyst.iundefsym > nsyms)
9156    outs() << " (greater than the number of symbols)\n";
9157  else
9158    outs() << "\n";
9159  outs() << "      nundefsym " << dyst.nundefsym;
9160  big_size = dyst.iundefsym;
9161  big_size += dyst.nundefsym;
9162  if (big_size > nsyms)
9163    outs() << " (past the end of the symbol table)\n";
9164  else
9165    outs() << "\n";
9166  outs() << "         tocoff " << dyst.tocoff;
9167  if (dyst.tocoff > object_size)
9168    outs() << " (past end of file)\n";
9169  else
9170    outs() << "\n";
9171  outs() << "           ntoc " << dyst.ntoc;
9172  big_size = dyst.ntoc;
9173  big_size *= sizeof(struct MachO::dylib_table_of_contents);
9174  big_size += dyst.tocoff;
9175  if (big_size > object_size)
9176    outs() << " (past end of file)\n";
9177  else
9178    outs() << "\n";
9179  outs() << "      modtaboff " << dyst.modtaboff;
9180  if (dyst.modtaboff > object_size)
9181    outs() << " (past end of file)\n";
9182  else
9183    outs() << "\n";
9184  outs() << "        nmodtab " << dyst.nmodtab;
9185  uint64_t modtabend;
9186  if (Is64Bit) {
9187    modtabend = dyst.nmodtab;
9188    modtabend *= sizeof(struct MachO::dylib_module_64);
9189    modtabend += dyst.modtaboff;
9190  } else {
9191    modtabend = dyst.nmodtab;
9192    modtabend *= sizeof(struct MachO::dylib_module);
9193    modtabend += dyst.modtaboff;
9194  }
9195  if (modtabend > object_size)
9196    outs() << " (past end of file)\n";
9197  else
9198    outs() << "\n";
9199  outs() << "   extrefsymoff " << dyst.extrefsymoff;
9200  if (dyst.extrefsymoff > object_size)
9201    outs() << " (past end of file)\n";
9202  else
9203    outs() << "\n";
9204  outs() << "    nextrefsyms " << dyst.nextrefsyms;
9205  big_size = dyst.nextrefsyms;
9206  big_size *= sizeof(struct MachO::dylib_reference);
9207  big_size += dyst.extrefsymoff;
9208  if (big_size > object_size)
9209    outs() << " (past end of file)\n";
9210  else
9211    outs() << "\n";
9212  outs() << " indirectsymoff " << dyst.indirectsymoff;
9213  if (dyst.indirectsymoff > object_size)
9214    outs() << " (past end of file)\n";
9215  else
9216    outs() << "\n";
9217  outs() << "  nindirectsyms " << dyst.nindirectsyms;
9218  big_size = dyst.nindirectsyms;
9219  big_size *= sizeof(uint32_t);
9220  big_size += dyst.indirectsymoff;
9221  if (big_size > object_size)
9222    outs() << " (past end of file)\n";
9223  else
9224    outs() << "\n";
9225  outs() << "      extreloff " << dyst.extreloff;
9226  if (dyst.extreloff > object_size)
9227    outs() << " (past end of file)\n";
9228  else
9229    outs() << "\n";
9230  outs() << "        nextrel " << dyst.nextrel;
9231  big_size = dyst.nextrel;
9232  big_size *= sizeof(struct MachO::relocation_info);
9233  big_size += dyst.extreloff;
9234  if (big_size > object_size)
9235    outs() << " (past end of file)\n";
9236  else
9237    outs() << "\n";
9238  outs() << "      locreloff " << dyst.locreloff;
9239  if (dyst.locreloff > object_size)
9240    outs() << " (past end of file)\n";
9241  else
9242    outs() << "\n";
9243  outs() << "        nlocrel " << dyst.nlocrel;
9244  big_size = dyst.nlocrel;
9245  big_size *= sizeof(struct MachO::relocation_info);
9246  big_size += dyst.locreloff;
9247  if (big_size > object_size)
9248    outs() << " (past end of file)\n";
9249  else
9250    outs() << "\n";
9251}
9252
9253static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
9254                                     uint32_t object_size) {
9255  if (dc.cmd == MachO::LC_DYLD_INFO)
9256    outs() << "            cmd LC_DYLD_INFO\n";
9257  else
9258    outs() << "            cmd LC_DYLD_INFO_ONLY\n";
9259  outs() << "        cmdsize " << dc.cmdsize;
9260  if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
9261    outs() << " Incorrect size\n";
9262  else
9263    outs() << "\n";
9264  outs() << "     rebase_off " << dc.rebase_off;
9265  if (dc.rebase_off > object_size)
9266    outs() << " (past end of file)\n";
9267  else
9268    outs() << "\n";
9269  outs() << "    rebase_size " << dc.rebase_size;
9270  uint64_t big_size;
9271  big_size = dc.rebase_off;
9272  big_size += dc.rebase_size;
9273  if (big_size > object_size)
9274    outs() << " (past end of file)\n";
9275  else
9276    outs() << "\n";
9277  outs() << "       bind_off " << dc.bind_off;
9278  if (dc.bind_off > object_size)
9279    outs() << " (past end of file)\n";
9280  else
9281    outs() << "\n";
9282  outs() << "      bind_size " << dc.bind_size;
9283  big_size = dc.bind_off;
9284  big_size += dc.bind_size;
9285  if (big_size > object_size)
9286    outs() << " (past end of file)\n";
9287  else
9288    outs() << "\n";
9289  outs() << "  weak_bind_off " << dc.weak_bind_off;
9290  if (dc.weak_bind_off > object_size)
9291    outs() << " (past end of file)\n";
9292  else
9293    outs() << "\n";
9294  outs() << " weak_bind_size " << dc.weak_bind_size;
9295  big_size = dc.weak_bind_off;
9296  big_size += dc.weak_bind_size;
9297  if (big_size > object_size)
9298    outs() << " (past end of file)\n";
9299  else
9300    outs() << "\n";
9301  outs() << "  lazy_bind_off " << dc.lazy_bind_off;
9302  if (dc.lazy_bind_off > object_size)
9303    outs() << " (past end of file)\n";
9304  else
9305    outs() << "\n";
9306  outs() << " lazy_bind_size " << dc.lazy_bind_size;
9307  big_size = dc.lazy_bind_off;
9308  big_size += dc.lazy_bind_size;
9309  if (big_size > object_size)
9310    outs() << " (past end of file)\n";
9311  else
9312    outs() << "\n";
9313  outs() << "     export_off " << dc.export_off;
9314  if (dc.export_off > object_size)
9315    outs() << " (past end of file)\n";
9316  else
9317    outs() << "\n";
9318  outs() << "    export_size " << dc.export_size;
9319  big_size = dc.export_off;
9320  big_size += dc.export_size;
9321  if (big_size > object_size)
9322    outs() << " (past end of file)\n";
9323  else
9324    outs() << "\n";
9325}
9326
9327static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
9328                                 const char *Ptr) {
9329  if (dyld.cmd == MachO::LC_ID_DYLINKER)
9330    outs() << "          cmd LC_ID_DYLINKER\n";
9331  else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
9332    outs() << "          cmd LC_LOAD_DYLINKER\n";
9333  else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
9334    outs() << "          cmd LC_DYLD_ENVIRONMENT\n";
9335  else
9336    outs() << "          cmd ?(" << dyld.cmd << ")\n";
9337  outs() << "      cmdsize " << dyld.cmdsize;
9338  if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
9339    outs() << " Incorrect size\n";
9340  else
9341    outs() << "\n";
9342  if (dyld.name >= dyld.cmdsize)
9343    outs() << "         name ?(bad offset " << dyld.name << ")\n";
9344  else {
9345    const char *P = (const char *)(Ptr) + dyld.name;
9346    outs() << "         name " << P << " (offset " << dyld.name << ")\n";
9347  }
9348}
9349
9350static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
9351  outs() << "     cmd LC_UUID\n";
9352  outs() << " cmdsize " << uuid.cmdsize;
9353  if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
9354    outs() << " Incorrect size\n";
9355  else
9356    outs() << "\n";
9357  outs() << "    uuid ";
9358  for (int i = 0; i < 16; ++i) {
9359    outs() << format("%02" PRIX32, uuid.uuid[i]);
9360    if (i == 3 || i == 5 || i == 7 || i == 9)
9361      outs() << "-";
9362  }
9363  outs() << "\n";
9364}
9365
9366static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
9367  outs() << "          cmd LC_RPATH\n";
9368  outs() << "      cmdsize " << rpath.cmdsize;
9369  if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
9370    outs() << " Incorrect size\n";
9371  else
9372    outs() << "\n";
9373  if (rpath.path >= rpath.cmdsize)
9374    outs() << "         path ?(bad offset " << rpath.path << ")\n";
9375  else {
9376    const char *P = (const char *)(Ptr) + rpath.path;
9377    outs() << "         path " << P << " (offset " << rpath.path << ")\n";
9378  }
9379}
9380
9381static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
9382  StringRef LoadCmdName;
9383  switch (vd.cmd) {
9384  case MachO::LC_VERSION_MIN_MACOSX:
9385    LoadCmdName = "LC_VERSION_MIN_MACOSX";
9386    break;
9387  case MachO::LC_VERSION_MIN_IPHONEOS:
9388    LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
9389    break;
9390  case MachO::LC_VERSION_MIN_TVOS:
9391    LoadCmdName = "LC_VERSION_MIN_TVOS";
9392    break;
9393  case MachO::LC_VERSION_MIN_WATCHOS:
9394    LoadCmdName = "LC_VERSION_MIN_WATCHOS";
9395    break;
9396  default:
9397    llvm_unreachable("Unknown version min load command");
9398  }
9399
9400  outs() << "      cmd " << LoadCmdName << '\n';
9401  outs() << "  cmdsize " << vd.cmdsize;
9402  if (vd.cmdsize != sizeof(struct MachO::version_min_command))
9403    outs() << " Incorrect size\n";
9404  else
9405    outs() << "\n";
9406  outs() << "  version "
9407         << MachOObjectFile::getVersionMinMajor(vd, false) << "."
9408         << MachOObjectFile::getVersionMinMinor(vd, false);
9409  uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
9410  if (Update != 0)
9411    outs() << "." << Update;
9412  outs() << "\n";
9413  if (vd.sdk == 0)
9414    outs() << "      sdk n/a";
9415  else {
9416    outs() << "      sdk "
9417           << MachOObjectFile::getVersionMinMajor(vd, true) << "."
9418           << MachOObjectFile::getVersionMinMinor(vd, true);
9419  }
9420  Update = MachOObjectFile::getVersionMinUpdate(vd, true);
9421  if (Update != 0)
9422    outs() << "." << Update;
9423  outs() << "\n";
9424}
9425
9426static void PrintNoteLoadCommand(MachO::note_command Nt) {
9427  outs() << "       cmd LC_NOTE\n";
9428  outs() << "   cmdsize " << Nt.cmdsize;
9429  if (Nt.cmdsize != sizeof(struct MachO::note_command))
9430    outs() << " Incorrect size\n";
9431  else
9432    outs() << "\n";
9433  const char *d = Nt.data_owner;
9434  outs() << "data_owner " << format("%.16s\n", d);
9435  outs() << "    offset " << Nt.offset << "\n";
9436  outs() << "      size " << Nt.size << "\n";
9437}
9438
9439static void PrintBuildToolVersion(MachO::build_tool_version bv, bool verbose) {
9440  outs() << "      tool ";
9441  if (verbose)
9442    outs() << MachOObjectFile::getBuildTool(bv.tool);
9443  else
9444    outs() << bv.tool;
9445  outs() << "\n";
9446  outs() << "   version " << MachOObjectFile::getVersionString(bv.version)
9447         << "\n";
9448}
9449
9450static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj,
9451                                         MachO::build_version_command bd,
9452                                         bool verbose) {
9453  outs() << "       cmd LC_BUILD_VERSION\n";
9454  outs() << "   cmdsize " << bd.cmdsize;
9455  if (bd.cmdsize !=
9456      sizeof(struct MachO::build_version_command) +
9457          bd.ntools * sizeof(struct MachO::build_tool_version))
9458    outs() << " Incorrect size\n";
9459  else
9460    outs() << "\n";
9461  outs() << "  platform ";
9462  if (verbose)
9463    outs() << MachOObjectFile::getBuildPlatform(bd.platform);
9464  else
9465    outs() << bd.platform;
9466  outs() << "\n";
9467  if (bd.sdk)
9468    outs() << "       sdk " << MachOObjectFile::getVersionString(bd.sdk)
9469           << "\n";
9470  else
9471    outs() << "       sdk n/a\n";
9472  outs() << "     minos " << MachOObjectFile::getVersionString(bd.minos)
9473         << "\n";
9474  outs() << "    ntools " << bd.ntools << "\n";
9475  for (unsigned i = 0; i < bd.ntools; ++i) {
9476    MachO::build_tool_version bv = obj->getBuildToolVersion(i);
9477    PrintBuildToolVersion(bv, verbose);
9478  }
9479}
9480
9481static void PrintSourceVersionCommand(MachO::source_version_command sd) {
9482  outs() << "      cmd LC_SOURCE_VERSION\n";
9483  outs() << "  cmdsize " << sd.cmdsize;
9484  if (sd.cmdsize != sizeof(struct MachO::source_version_command))
9485    outs() << " Incorrect size\n";
9486  else
9487    outs() << "\n";
9488  uint64_t a = (sd.version >> 40) & 0xffffff;
9489  uint64_t b = (sd.version >> 30) & 0x3ff;
9490  uint64_t c = (sd.version >> 20) & 0x3ff;
9491  uint64_t d = (sd.version >> 10) & 0x3ff;
9492  uint64_t e = sd.version & 0x3ff;
9493  outs() << "  version " << a << "." << b;
9494  if (e != 0)
9495    outs() << "." << c << "." << d << "." << e;
9496  else if (d != 0)
9497    outs() << "." << c << "." << d;
9498  else if (c != 0)
9499    outs() << "." << c;
9500  outs() << "\n";
9501}
9502
9503static void PrintEntryPointCommand(MachO::entry_point_command ep) {
9504  outs() << "       cmd LC_MAIN\n";
9505  outs() << "   cmdsize " << ep.cmdsize;
9506  if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
9507    outs() << " Incorrect size\n";
9508  else
9509    outs() << "\n";
9510  outs() << "  entryoff " << ep.entryoff << "\n";
9511  outs() << " stacksize " << ep.stacksize << "\n";
9512}
9513
9514static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
9515                                       uint32_t object_size) {
9516  outs() << "          cmd LC_ENCRYPTION_INFO\n";
9517  outs() << "      cmdsize " << ec.cmdsize;
9518  if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
9519    outs() << " Incorrect size\n";
9520  else
9521    outs() << "\n";
9522  outs() << "     cryptoff " << ec.cryptoff;
9523  if (ec.cryptoff > object_size)
9524    outs() << " (past end of file)\n";
9525  else
9526    outs() << "\n";
9527  outs() << "    cryptsize " << ec.cryptsize;
9528  if (ec.cryptsize > object_size)
9529    outs() << " (past end of file)\n";
9530  else
9531    outs() << "\n";
9532  outs() << "      cryptid " << ec.cryptid << "\n";
9533}
9534
9535static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
9536                                         uint32_t object_size) {
9537  outs() << "          cmd LC_ENCRYPTION_INFO_64\n";
9538  outs() << "      cmdsize " << ec.cmdsize;
9539  if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
9540    outs() << " Incorrect size\n";
9541  else
9542    outs() << "\n";
9543  outs() << "     cryptoff " << ec.cryptoff;
9544  if (ec.cryptoff > object_size)
9545    outs() << " (past end of file)\n";
9546  else
9547    outs() << "\n";
9548  outs() << "    cryptsize " << ec.cryptsize;
9549  if (ec.cryptsize > object_size)
9550    outs() << " (past end of file)\n";
9551  else
9552    outs() << "\n";
9553  outs() << "      cryptid " << ec.cryptid << "\n";
9554  outs() << "          pad " << ec.pad << "\n";
9555}
9556
9557static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
9558                                     const char *Ptr) {
9559  outs() << "     cmd LC_LINKER_OPTION\n";
9560  outs() << " cmdsize " << lo.cmdsize;
9561  if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
9562    outs() << " Incorrect size\n";
9563  else
9564    outs() << "\n";
9565  outs() << "   count " << lo.count << "\n";
9566  const char *string = Ptr + sizeof(struct MachO::linker_option_command);
9567  uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
9568  uint32_t i = 0;
9569  while (left > 0) {
9570    while (*string == '\0' && left > 0) {
9571      string++;
9572      left--;
9573    }
9574    if (left > 0) {
9575      i++;
9576      outs() << "  string #" << i << " " << format("%.*s\n", left, string);
9577      uint32_t NullPos = StringRef(string, left).find('\0');
9578      uint32_t len = std::min(NullPos, left) + 1;
9579      string += len;
9580      left -= len;
9581    }
9582  }
9583  if (lo.count != i)
9584    outs() << "   count " << lo.count << " does not match number of strings "
9585           << i << "\n";
9586}
9587
9588static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
9589                                     const char *Ptr) {
9590  outs() << "          cmd LC_SUB_FRAMEWORK\n";
9591  outs() << "      cmdsize " << sub.cmdsize;
9592  if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
9593    outs() << " Incorrect size\n";
9594  else
9595    outs() << "\n";
9596  if (sub.umbrella < sub.cmdsize) {
9597    const char *P = Ptr + sub.umbrella;
9598    outs() << "     umbrella " << P << " (offset " << sub.umbrella << ")\n";
9599  } else {
9600    outs() << "     umbrella ?(bad offset " << sub.umbrella << ")\n";
9601  }
9602}
9603
9604static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
9605                                    const char *Ptr) {
9606  outs() << "          cmd LC_SUB_UMBRELLA\n";
9607  outs() << "      cmdsize " << sub.cmdsize;
9608  if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
9609    outs() << " Incorrect size\n";
9610  else
9611    outs() << "\n";
9612  if (sub.sub_umbrella < sub.cmdsize) {
9613    const char *P = Ptr + sub.sub_umbrella;
9614    outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
9615  } else {
9616    outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
9617  }
9618}
9619
9620static void PrintSubLibraryCommand(MachO::sub_library_command sub,
9621                                   const char *Ptr) {
9622  outs() << "          cmd LC_SUB_LIBRARY\n";
9623  outs() << "      cmdsize " << sub.cmdsize;
9624  if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
9625    outs() << " Incorrect size\n";
9626  else
9627    outs() << "\n";
9628  if (sub.sub_library < sub.cmdsize) {
9629    const char *P = Ptr + sub.sub_library;
9630    outs() << "  sub_library " << P << " (offset " << sub.sub_library << ")\n";
9631  } else {
9632    outs() << "  sub_library ?(bad offset " << sub.sub_library << ")\n";
9633  }
9634}
9635
9636static void PrintSubClientCommand(MachO::sub_client_command sub,
9637                                  const char *Ptr) {
9638  outs() << "          cmd LC_SUB_CLIENT\n";
9639  outs() << "      cmdsize " << sub.cmdsize;
9640  if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
9641    outs() << " Incorrect size\n";
9642  else
9643    outs() << "\n";
9644  if (sub.client < sub.cmdsize) {
9645    const char *P = Ptr + sub.client;
9646    outs() << "       client " << P << " (offset " << sub.client << ")\n";
9647  } else {
9648    outs() << "       client ?(bad offset " << sub.client << ")\n";
9649  }
9650}
9651
9652static void PrintRoutinesCommand(MachO::routines_command r) {
9653  outs() << "          cmd LC_ROUTINES\n";
9654  outs() << "      cmdsize " << r.cmdsize;
9655  if (r.cmdsize != sizeof(struct MachO::routines_command))
9656    outs() << " Incorrect size\n";
9657  else
9658    outs() << "\n";
9659  outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
9660  outs() << "  init_module " << r.init_module << "\n";
9661  outs() << "    reserved1 " << r.reserved1 << "\n";
9662  outs() << "    reserved2 " << r.reserved2 << "\n";
9663  outs() << "    reserved3 " << r.reserved3 << "\n";
9664  outs() << "    reserved4 " << r.reserved4 << "\n";
9665  outs() << "    reserved5 " << r.reserved5 << "\n";
9666  outs() << "    reserved6 " << r.reserved6 << "\n";
9667}
9668
9669static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
9670  outs() << "          cmd LC_ROUTINES_64\n";
9671  outs() << "      cmdsize " << r.cmdsize;
9672  if (r.cmdsize != sizeof(struct MachO::routines_command_64))
9673    outs() << " Incorrect size\n";
9674  else
9675    outs() << "\n";
9676  outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
9677  outs() << "  init_module " << r.init_module << "\n";
9678  outs() << "    reserved1 " << r.reserved1 << "\n";
9679  outs() << "    reserved2 " << r.reserved2 << "\n";
9680  outs() << "    reserved3 " << r.reserved3 << "\n";
9681  outs() << "    reserved4 " << r.reserved4 << "\n";
9682  outs() << "    reserved5 " << r.reserved5 << "\n";
9683  outs() << "    reserved6 " << r.reserved6 << "\n";
9684}
9685
9686static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) {
9687  outs() << "\t    eax " << format("0x%08" PRIx32, cpu32.eax);
9688  outs() << " ebx    " << format("0x%08" PRIx32, cpu32.ebx);
9689  outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx);
9690  outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n";
9691  outs() << "\t    edi " << format("0x%08" PRIx32, cpu32.edi);
9692  outs() << " esi    " << format("0x%08" PRIx32, cpu32.esi);
9693  outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp);
9694  outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n";
9695  outs() << "\t    ss  " << format("0x%08" PRIx32, cpu32.ss);
9696  outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags);
9697  outs() << " eip " << format("0x%08" PRIx32, cpu32.eip);
9698  outs() << " cs  " << format("0x%08" PRIx32, cpu32.cs) << "\n";
9699  outs() << "\t    ds  " << format("0x%08" PRIx32, cpu32.ds);
9700  outs() << " es     " << format("0x%08" PRIx32, cpu32.es);
9701  outs() << " fs  " << format("0x%08" PRIx32, cpu32.fs);
9702  outs() << " gs  " << format("0x%08" PRIx32, cpu32.gs) << "\n";
9703}
9704
9705static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
9706  outs() << "   rax  " << format("0x%016" PRIx64, cpu64.rax);
9707  outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
9708  outs() << " rcx  " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
9709  outs() << "   rdx  " << format("0x%016" PRIx64, cpu64.rdx);
9710  outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
9711  outs() << " rsi  " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
9712  outs() << "   rbp  " << format("0x%016" PRIx64, cpu64.rbp);
9713  outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
9714  outs() << " r8   " << format("0x%016" PRIx64, cpu64.r8) << "\n";
9715  outs() << "    r9  " << format("0x%016" PRIx64, cpu64.r9);
9716  outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
9717  outs() << " r11  " << format("0x%016" PRIx64, cpu64.r11) << "\n";
9718  outs() << "   r12  " << format("0x%016" PRIx64, cpu64.r12);
9719  outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
9720  outs() << " r14  " << format("0x%016" PRIx64, cpu64.r14) << "\n";
9721  outs() << "   r15  " << format("0x%016" PRIx64, cpu64.r15);
9722  outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
9723  outs() << "rflags  " << format("0x%016" PRIx64, cpu64.rflags);
9724  outs() << " cs  " << format("0x%016" PRIx64, cpu64.cs);
9725  outs() << " fs   " << format("0x%016" PRIx64, cpu64.fs) << "\n";
9726  outs() << "    gs  " << format("0x%016" PRIx64, cpu64.gs) << "\n";
9727}
9728
9729static void Print_mmst_reg(MachO::mmst_reg_t &r) {
9730  uint32_t f;
9731  outs() << "\t      mmst_reg  ";
9732  for (f = 0; f < 10; f++)
9733    outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
9734  outs() << "\n";
9735  outs() << "\t      mmst_rsrv ";
9736  for (f = 0; f < 6; f++)
9737    outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
9738  outs() << "\n";
9739}
9740
9741static void Print_xmm_reg(MachO::xmm_reg_t &r) {
9742  uint32_t f;
9743  outs() << "\t      xmm_reg ";
9744  for (f = 0; f < 16; f++)
9745    outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
9746  outs() << "\n";
9747}
9748
9749static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
9750  outs() << "\t    fpu_reserved[0] " << fpu.fpu_reserved[0];
9751  outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
9752  outs() << "\t    control: invalid " << fpu.fpu_fcw.invalid;
9753  outs() << " denorm " << fpu.fpu_fcw.denorm;
9754  outs() << " zdiv " << fpu.fpu_fcw.zdiv;
9755  outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
9756  outs() << " undfl " << fpu.fpu_fcw.undfl;
9757  outs() << " precis " << fpu.fpu_fcw.precis << "\n";
9758  outs() << "\t\t     pc ";
9759  if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
9760    outs() << "FP_PREC_24B ";
9761  else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
9762    outs() << "FP_PREC_53B ";
9763  else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
9764    outs() << "FP_PREC_64B ";
9765  else
9766    outs() << fpu.fpu_fcw.pc << " ";
9767  outs() << "rc ";
9768  if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
9769    outs() << "FP_RND_NEAR ";
9770  else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
9771    outs() << "FP_RND_DOWN ";
9772  else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
9773    outs() << "FP_RND_UP ";
9774  else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
9775    outs() << "FP_CHOP ";
9776  outs() << "\n";
9777  outs() << "\t    status: invalid " << fpu.fpu_fsw.invalid;
9778  outs() << " denorm " << fpu.fpu_fsw.denorm;
9779  outs() << " zdiv " << fpu.fpu_fsw.zdiv;
9780  outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
9781  outs() << " undfl " << fpu.fpu_fsw.undfl;
9782  outs() << " precis " << fpu.fpu_fsw.precis;
9783  outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
9784  outs() << "\t            errsumm " << fpu.fpu_fsw.errsumm;
9785  outs() << " c0 " << fpu.fpu_fsw.c0;
9786  outs() << " c1 " << fpu.fpu_fsw.c1;
9787  outs() << " c2 " << fpu.fpu_fsw.c2;
9788  outs() << " tos " << fpu.fpu_fsw.tos;
9789  outs() << " c3 " << fpu.fpu_fsw.c3;
9790  outs() << " busy " << fpu.fpu_fsw.busy << "\n";
9791  outs() << "\t    fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
9792  outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
9793  outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
9794  outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
9795  outs() << "\t    fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
9796  outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
9797  outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
9798  outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
9799  outs() << "\t    fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
9800  outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
9801  outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
9802  outs() << "\n";
9803  outs() << "\t    fpu_stmm0:\n";
9804  Print_mmst_reg(fpu.fpu_stmm0);
9805  outs() << "\t    fpu_stmm1:\n";
9806  Print_mmst_reg(fpu.fpu_stmm1);
9807  outs() << "\t    fpu_stmm2:\n";
9808  Print_mmst_reg(fpu.fpu_stmm2);
9809  outs() << "\t    fpu_stmm3:\n";
9810  Print_mmst_reg(fpu.fpu_stmm3);
9811  outs() << "\t    fpu_stmm4:\n";
9812  Print_mmst_reg(fpu.fpu_stmm4);
9813  outs() << "\t    fpu_stmm5:\n";
9814  Print_mmst_reg(fpu.fpu_stmm5);
9815  outs() << "\t    fpu_stmm6:\n";
9816  Print_mmst_reg(fpu.fpu_stmm6);
9817  outs() << "\t    fpu_stmm7:\n";
9818  Print_mmst_reg(fpu.fpu_stmm7);
9819  outs() << "\t    fpu_xmm0:\n";
9820  Print_xmm_reg(fpu.fpu_xmm0);
9821  outs() << "\t    fpu_xmm1:\n";
9822  Print_xmm_reg(fpu.fpu_xmm1);
9823  outs() << "\t    fpu_xmm2:\n";
9824  Print_xmm_reg(fpu.fpu_xmm2);
9825  outs() << "\t    fpu_xmm3:\n";
9826  Print_xmm_reg(fpu.fpu_xmm3);
9827  outs() << "\t    fpu_xmm4:\n";
9828  Print_xmm_reg(fpu.fpu_xmm4);
9829  outs() << "\t    fpu_xmm5:\n";
9830  Print_xmm_reg(fpu.fpu_xmm5);
9831  outs() << "\t    fpu_xmm6:\n";
9832  Print_xmm_reg(fpu.fpu_xmm6);
9833  outs() << "\t    fpu_xmm7:\n";
9834  Print_xmm_reg(fpu.fpu_xmm7);
9835  outs() << "\t    fpu_xmm8:\n";
9836  Print_xmm_reg(fpu.fpu_xmm8);
9837  outs() << "\t    fpu_xmm9:\n";
9838  Print_xmm_reg(fpu.fpu_xmm9);
9839  outs() << "\t    fpu_xmm10:\n";
9840  Print_xmm_reg(fpu.fpu_xmm10);
9841  outs() << "\t    fpu_xmm11:\n";
9842  Print_xmm_reg(fpu.fpu_xmm11);
9843  outs() << "\t    fpu_xmm12:\n";
9844  Print_xmm_reg(fpu.fpu_xmm12);
9845  outs() << "\t    fpu_xmm13:\n";
9846  Print_xmm_reg(fpu.fpu_xmm13);
9847  outs() << "\t    fpu_xmm14:\n";
9848  Print_xmm_reg(fpu.fpu_xmm14);
9849  outs() << "\t    fpu_xmm15:\n";
9850  Print_xmm_reg(fpu.fpu_xmm15);
9851  outs() << "\t    fpu_rsrv4:\n";
9852  for (uint32_t f = 0; f < 6; f++) {
9853    outs() << "\t            ";
9854    for (uint32_t g = 0; g < 16; g++)
9855      outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
9856    outs() << "\n";
9857  }
9858  outs() << "\t    fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
9859  outs() << "\n";
9860}
9861
9862static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
9863  outs() << "\t    trapno " << format("0x%08" PRIx32, exc64.trapno);
9864  outs() << " err " << format("0x%08" PRIx32, exc64.err);
9865  outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
9866}
9867
9868static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
9869  outs() << "\t    r0  " << format("0x%08" PRIx32, cpu32.r[0]);
9870  outs() << " r1     "   << format("0x%08" PRIx32, cpu32.r[1]);
9871  outs() << " r2  "      << format("0x%08" PRIx32, cpu32.r[2]);
9872  outs() << " r3  "      << format("0x%08" PRIx32, cpu32.r[3]) << "\n";
9873  outs() << "\t    r4  " << format("0x%08" PRIx32, cpu32.r[4]);
9874  outs() << " r5     "   << format("0x%08" PRIx32, cpu32.r[5]);
9875  outs() << " r6  "      << format("0x%08" PRIx32, cpu32.r[6]);
9876  outs() << " r7  "      << format("0x%08" PRIx32, cpu32.r[7]) << "\n";
9877  outs() << "\t    r8  " << format("0x%08" PRIx32, cpu32.r[8]);
9878  outs() << " r9     "   << format("0x%08" PRIx32, cpu32.r[9]);
9879  outs() << " r10 "      << format("0x%08" PRIx32, cpu32.r[10]);
9880  outs() << " r11 "      << format("0x%08" PRIx32, cpu32.r[11]) << "\n";
9881  outs() << "\t    r12 " << format("0x%08" PRIx32, cpu32.r[12]);
9882  outs() << " sp     "   << format("0x%08" PRIx32, cpu32.sp);
9883  outs() << " lr  "      << format("0x%08" PRIx32, cpu32.lr);
9884  outs() << " pc  "      << format("0x%08" PRIx32, cpu32.pc) << "\n";
9885  outs() << "\t   cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n";
9886}
9887
9888static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
9889  outs() << "\t    x0  " << format("0x%016" PRIx64, cpu64.x[0]);
9890  outs() << " x1  "      << format("0x%016" PRIx64, cpu64.x[1]);
9891  outs() << " x2  "      << format("0x%016" PRIx64, cpu64.x[2]) << "\n";
9892  outs() << "\t    x3  " << format("0x%016" PRIx64, cpu64.x[3]);
9893  outs() << " x4  "      << format("0x%016" PRIx64, cpu64.x[4]);
9894  outs() << " x5  "      << format("0x%016" PRIx64, cpu64.x[5]) << "\n";
9895  outs() << "\t    x6  " << format("0x%016" PRIx64, cpu64.x[6]);
9896  outs() << " x7  "      << format("0x%016" PRIx64, cpu64.x[7]);
9897  outs() << " x8  "      << format("0x%016" PRIx64, cpu64.x[8]) << "\n";
9898  outs() << "\t    x9  " << format("0x%016" PRIx64, cpu64.x[9]);
9899  outs() << " x10 "      << format("0x%016" PRIx64, cpu64.x[10]);
9900  outs() << " x11 "      << format("0x%016" PRIx64, cpu64.x[11]) << "\n";
9901  outs() << "\t    x12 " << format("0x%016" PRIx64, cpu64.x[12]);
9902  outs() << " x13 "      << format("0x%016" PRIx64, cpu64.x[13]);
9903  outs() << " x14 "      << format("0x%016" PRIx64, cpu64.x[14]) << "\n";
9904  outs() << "\t    x15 " << format("0x%016" PRIx64, cpu64.x[15]);
9905  outs() << " x16 "      << format("0x%016" PRIx64, cpu64.x[16]);
9906  outs() << " x17 "      << format("0x%016" PRIx64, cpu64.x[17]) << "\n";
9907  outs() << "\t    x18 " << format("0x%016" PRIx64, cpu64.x[18]);
9908  outs() << " x19 "      << format("0x%016" PRIx64, cpu64.x[19]);
9909  outs() << " x20 "      << format("0x%016" PRIx64, cpu64.x[20]) << "\n";
9910  outs() << "\t    x21 " << format("0x%016" PRIx64, cpu64.x[21]);
9911  outs() << " x22 "      << format("0x%016" PRIx64, cpu64.x[22]);
9912  outs() << " x23 "      << format("0x%016" PRIx64, cpu64.x[23]) << "\n";
9913  outs() << "\t    x24 " << format("0x%016" PRIx64, cpu64.x[24]);
9914  outs() << " x25 "      << format("0x%016" PRIx64, cpu64.x[25]);
9915  outs() << " x26 "      << format("0x%016" PRIx64, cpu64.x[26]) << "\n";
9916  outs() << "\t    x27 " << format("0x%016" PRIx64, cpu64.x[27]);
9917  outs() << " x28 "      << format("0x%016" PRIx64, cpu64.x[28]);
9918  outs() << "  fp "      << format("0x%016" PRIx64, cpu64.fp) << "\n";
9919  outs() << "\t     lr " << format("0x%016" PRIx64, cpu64.lr);
9920  outs() << " sp  "      << format("0x%016" PRIx64, cpu64.sp);
9921  outs() << "  pc "      << format("0x%016" PRIx64, cpu64.pc) << "\n";
9922  outs() << "\t   cpsr " << format("0x%08"  PRIx32, cpu64.cpsr) << "\n";
9923}
9924
9925static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
9926                               bool isLittleEndian, uint32_t cputype) {
9927  if (t.cmd == MachO::LC_THREAD)
9928    outs() << "        cmd LC_THREAD\n";
9929  else if (t.cmd == MachO::LC_UNIXTHREAD)
9930    outs() << "        cmd LC_UNIXTHREAD\n";
9931  else
9932    outs() << "        cmd " << t.cmd << " (unknown)\n";
9933  outs() << "    cmdsize " << t.cmdsize;
9934  if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
9935    outs() << " Incorrect size\n";
9936  else
9937    outs() << "\n";
9938
9939  const char *begin = Ptr + sizeof(struct MachO::thread_command);
9940  const char *end = Ptr + t.cmdsize;
9941  uint32_t flavor, count, left;
9942  if (cputype == MachO::CPU_TYPE_I386) {
9943    while (begin < end) {
9944      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9945        memcpy((char *)&flavor, begin, sizeof(uint32_t));
9946        begin += sizeof(uint32_t);
9947      } else {
9948        flavor = 0;
9949        begin = end;
9950      }
9951      if (isLittleEndian != sys::IsLittleEndianHost)
9952        sys::swapByteOrder(flavor);
9953      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9954        memcpy((char *)&count, begin, sizeof(uint32_t));
9955        begin += sizeof(uint32_t);
9956      } else {
9957        count = 0;
9958        begin = end;
9959      }
9960      if (isLittleEndian != sys::IsLittleEndianHost)
9961        sys::swapByteOrder(count);
9962      if (flavor == MachO::x86_THREAD_STATE32) {
9963        outs() << "     flavor i386_THREAD_STATE\n";
9964        if (count == MachO::x86_THREAD_STATE32_COUNT)
9965          outs() << "      count i386_THREAD_STATE_COUNT\n";
9966        else
9967          outs() << "      count " << count
9968                 << " (not x86_THREAD_STATE32_COUNT)\n";
9969        MachO::x86_thread_state32_t cpu32;
9970        left = end - begin;
9971        if (left >= sizeof(MachO::x86_thread_state32_t)) {
9972          memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t));
9973          begin += sizeof(MachO::x86_thread_state32_t);
9974        } else {
9975          memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t));
9976          memcpy(&cpu32, begin, left);
9977          begin += left;
9978        }
9979        if (isLittleEndian != sys::IsLittleEndianHost)
9980          swapStruct(cpu32);
9981        Print_x86_thread_state32_t(cpu32);
9982      } else if (flavor == MachO::x86_THREAD_STATE) {
9983        outs() << "     flavor x86_THREAD_STATE\n";
9984        if (count == MachO::x86_THREAD_STATE_COUNT)
9985          outs() << "      count x86_THREAD_STATE_COUNT\n";
9986        else
9987          outs() << "      count " << count
9988                 << " (not x86_THREAD_STATE_COUNT)\n";
9989        struct MachO::x86_thread_state_t ts;
9990        left = end - begin;
9991        if (left >= sizeof(MachO::x86_thread_state_t)) {
9992          memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9993          begin += sizeof(MachO::x86_thread_state_t);
9994        } else {
9995          memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9996          memcpy(&ts, begin, left);
9997          begin += left;
9998        }
9999        if (isLittleEndian != sys::IsLittleEndianHost)
10000          swapStruct(ts);
10001        if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) {
10002          outs() << "\t    tsh.flavor x86_THREAD_STATE32 ";
10003          if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT)
10004            outs() << "tsh.count x86_THREAD_STATE32_COUNT\n";
10005          else
10006            outs() << "tsh.count " << ts.tsh.count
10007                   << " (not x86_THREAD_STATE32_COUNT\n";
10008          Print_x86_thread_state32_t(ts.uts.ts32);
10009        } else {
10010          outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
10011                 << ts.tsh.count << "\n";
10012        }
10013      } else {
10014        outs() << "     flavor " << flavor << " (unknown)\n";
10015        outs() << "      count " << count << "\n";
10016        outs() << "      state (unknown)\n";
10017        begin += count * sizeof(uint32_t);
10018      }
10019    }
10020  } else if (cputype == MachO::CPU_TYPE_X86_64) {
10021    while (begin < end) {
10022      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10023        memcpy((char *)&flavor, begin, sizeof(uint32_t));
10024        begin += sizeof(uint32_t);
10025      } else {
10026        flavor = 0;
10027        begin = end;
10028      }
10029      if (isLittleEndian != sys::IsLittleEndianHost)
10030        sys::swapByteOrder(flavor);
10031      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10032        memcpy((char *)&count, begin, sizeof(uint32_t));
10033        begin += sizeof(uint32_t);
10034      } else {
10035        count = 0;
10036        begin = end;
10037      }
10038      if (isLittleEndian != sys::IsLittleEndianHost)
10039        sys::swapByteOrder(count);
10040      if (flavor == MachO::x86_THREAD_STATE64) {
10041        outs() << "     flavor x86_THREAD_STATE64\n";
10042        if (count == MachO::x86_THREAD_STATE64_COUNT)
10043          outs() << "      count x86_THREAD_STATE64_COUNT\n";
10044        else
10045          outs() << "      count " << count
10046                 << " (not x86_THREAD_STATE64_COUNT)\n";
10047        MachO::x86_thread_state64_t cpu64;
10048        left = end - begin;
10049        if (left >= sizeof(MachO::x86_thread_state64_t)) {
10050          memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
10051          begin += sizeof(MachO::x86_thread_state64_t);
10052        } else {
10053          memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
10054          memcpy(&cpu64, begin, left);
10055          begin += left;
10056        }
10057        if (isLittleEndian != sys::IsLittleEndianHost)
10058          swapStruct(cpu64);
10059        Print_x86_thread_state64_t(cpu64);
10060      } else if (flavor == MachO::x86_THREAD_STATE) {
10061        outs() << "     flavor x86_THREAD_STATE\n";
10062        if (count == MachO::x86_THREAD_STATE_COUNT)
10063          outs() << "      count x86_THREAD_STATE_COUNT\n";
10064        else
10065          outs() << "      count " << count
10066                 << " (not x86_THREAD_STATE_COUNT)\n";
10067        struct MachO::x86_thread_state_t ts;
10068        left = end - begin;
10069        if (left >= sizeof(MachO::x86_thread_state_t)) {
10070          memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
10071          begin += sizeof(MachO::x86_thread_state_t);
10072        } else {
10073          memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
10074          memcpy(&ts, begin, left);
10075          begin += left;
10076        }
10077        if (isLittleEndian != sys::IsLittleEndianHost)
10078          swapStruct(ts);
10079        if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
10080          outs() << "\t    tsh.flavor x86_THREAD_STATE64 ";
10081          if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
10082            outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
10083          else
10084            outs() << "tsh.count " << ts.tsh.count
10085                   << " (not x86_THREAD_STATE64_COUNT\n";
10086          Print_x86_thread_state64_t(ts.uts.ts64);
10087        } else {
10088          outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
10089                 << ts.tsh.count << "\n";
10090        }
10091      } else if (flavor == MachO::x86_FLOAT_STATE) {
10092        outs() << "     flavor x86_FLOAT_STATE\n";
10093        if (count == MachO::x86_FLOAT_STATE_COUNT)
10094          outs() << "      count x86_FLOAT_STATE_COUNT\n";
10095        else
10096          outs() << "      count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
10097        struct MachO::x86_float_state_t fs;
10098        left = end - begin;
10099        if (left >= sizeof(MachO::x86_float_state_t)) {
10100          memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
10101          begin += sizeof(MachO::x86_float_state_t);
10102        } else {
10103          memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
10104          memcpy(&fs, begin, left);
10105          begin += left;
10106        }
10107        if (isLittleEndian != sys::IsLittleEndianHost)
10108          swapStruct(fs);
10109        if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
10110          outs() << "\t    fsh.flavor x86_FLOAT_STATE64 ";
10111          if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
10112            outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
10113          else
10114            outs() << "fsh.count " << fs.fsh.count
10115                   << " (not x86_FLOAT_STATE64_COUNT\n";
10116          Print_x86_float_state_t(fs.ufs.fs64);
10117        } else {
10118          outs() << "\t    fsh.flavor " << fs.fsh.flavor << "  fsh.count "
10119                 << fs.fsh.count << "\n";
10120        }
10121      } else if (flavor == MachO::x86_EXCEPTION_STATE) {
10122        outs() << "     flavor x86_EXCEPTION_STATE\n";
10123        if (count == MachO::x86_EXCEPTION_STATE_COUNT)
10124          outs() << "      count x86_EXCEPTION_STATE_COUNT\n";
10125        else
10126          outs() << "      count " << count
10127                 << " (not x86_EXCEPTION_STATE_COUNT)\n";
10128        struct MachO::x86_exception_state_t es;
10129        left = end - begin;
10130        if (left >= sizeof(MachO::x86_exception_state_t)) {
10131          memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
10132          begin += sizeof(MachO::x86_exception_state_t);
10133        } else {
10134          memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
10135          memcpy(&es, begin, left);
10136          begin += left;
10137        }
10138        if (isLittleEndian != sys::IsLittleEndianHost)
10139          swapStruct(es);
10140        if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
10141          outs() << "\t    esh.flavor x86_EXCEPTION_STATE64\n";
10142          if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
10143            outs() << "\t    esh.count x86_EXCEPTION_STATE64_COUNT\n";
10144          else
10145            outs() << "\t    esh.count " << es.esh.count
10146                   << " (not x86_EXCEPTION_STATE64_COUNT\n";
10147          Print_x86_exception_state_t(es.ues.es64);
10148        } else {
10149          outs() << "\t    esh.flavor " << es.esh.flavor << "  esh.count "
10150                 << es.esh.count << "\n";
10151        }
10152      } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
10153        outs() << "     flavor x86_EXCEPTION_STATE64\n";
10154        if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
10155          outs() << "      count x86_EXCEPTION_STATE64_COUNT\n";
10156        else
10157          outs() << "      count " << count
10158                 << " (not x86_EXCEPTION_STATE64_COUNT)\n";
10159        struct MachO::x86_exception_state64_t es64;
10160        left = end - begin;
10161        if (left >= sizeof(MachO::x86_exception_state64_t)) {
10162          memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
10163          begin += sizeof(MachO::x86_exception_state64_t);
10164        } else {
10165          memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
10166          memcpy(&es64, begin, left);
10167          begin += left;
10168        }
10169        if (isLittleEndian != sys::IsLittleEndianHost)
10170          swapStruct(es64);
10171        Print_x86_exception_state_t(es64);
10172      } else {
10173        outs() << "     flavor " << flavor << " (unknown)\n";
10174        outs() << "      count " << count << "\n";
10175        outs() << "      state (unknown)\n";
10176        begin += count * sizeof(uint32_t);
10177      }
10178    }
10179  } else if (cputype == MachO::CPU_TYPE_ARM) {
10180    while (begin < end) {
10181      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10182        memcpy((char *)&flavor, begin, sizeof(uint32_t));
10183        begin += sizeof(uint32_t);
10184      } else {
10185        flavor = 0;
10186        begin = end;
10187      }
10188      if (isLittleEndian != sys::IsLittleEndianHost)
10189        sys::swapByteOrder(flavor);
10190      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10191        memcpy((char *)&count, begin, sizeof(uint32_t));
10192        begin += sizeof(uint32_t);
10193      } else {
10194        count = 0;
10195        begin = end;
10196      }
10197      if (isLittleEndian != sys::IsLittleEndianHost)
10198        sys::swapByteOrder(count);
10199      if (flavor == MachO::ARM_THREAD_STATE) {
10200        outs() << "     flavor ARM_THREAD_STATE\n";
10201        if (count == MachO::ARM_THREAD_STATE_COUNT)
10202          outs() << "      count ARM_THREAD_STATE_COUNT\n";
10203        else
10204          outs() << "      count " << count
10205                 << " (not ARM_THREAD_STATE_COUNT)\n";
10206        MachO::arm_thread_state32_t cpu32;
10207        left = end - begin;
10208        if (left >= sizeof(MachO::arm_thread_state32_t)) {
10209          memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t));
10210          begin += sizeof(MachO::arm_thread_state32_t);
10211        } else {
10212          memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t));
10213          memcpy(&cpu32, begin, left);
10214          begin += left;
10215        }
10216        if (isLittleEndian != sys::IsLittleEndianHost)
10217          swapStruct(cpu32);
10218        Print_arm_thread_state32_t(cpu32);
10219      } else {
10220        outs() << "     flavor " << flavor << " (unknown)\n";
10221        outs() << "      count " << count << "\n";
10222        outs() << "      state (unknown)\n";
10223        begin += count * sizeof(uint32_t);
10224      }
10225    }
10226  } else if (cputype == MachO::CPU_TYPE_ARM64 ||
10227             cputype == MachO::CPU_TYPE_ARM64_32) {
10228    while (begin < end) {
10229      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10230        memcpy((char *)&flavor, begin, sizeof(uint32_t));
10231        begin += sizeof(uint32_t);
10232      } else {
10233        flavor = 0;
10234        begin = end;
10235      }
10236      if (isLittleEndian != sys::IsLittleEndianHost)
10237        sys::swapByteOrder(flavor);
10238      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10239        memcpy((char *)&count, begin, sizeof(uint32_t));
10240        begin += sizeof(uint32_t);
10241      } else {
10242        count = 0;
10243        begin = end;
10244      }
10245      if (isLittleEndian != sys::IsLittleEndianHost)
10246        sys::swapByteOrder(count);
10247      if (flavor == MachO::ARM_THREAD_STATE64) {
10248        outs() << "     flavor ARM_THREAD_STATE64\n";
10249        if (count == MachO::ARM_THREAD_STATE64_COUNT)
10250          outs() << "      count ARM_THREAD_STATE64_COUNT\n";
10251        else
10252          outs() << "      count " << count
10253                 << " (not ARM_THREAD_STATE64_COUNT)\n";
10254        MachO::arm_thread_state64_t cpu64;
10255        left = end - begin;
10256        if (left >= sizeof(MachO::arm_thread_state64_t)) {
10257          memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
10258          begin += sizeof(MachO::arm_thread_state64_t);
10259        } else {
10260          memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
10261          memcpy(&cpu64, begin, left);
10262          begin += left;
10263        }
10264        if (isLittleEndian != sys::IsLittleEndianHost)
10265          swapStruct(cpu64);
10266        Print_arm_thread_state64_t(cpu64);
10267      } else {
10268        outs() << "     flavor " << flavor << " (unknown)\n";
10269        outs() << "      count " << count << "\n";
10270        outs() << "      state (unknown)\n";
10271        begin += count * sizeof(uint32_t);
10272      }
10273    }
10274  } else {
10275    while (begin < end) {
10276      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10277        memcpy((char *)&flavor, begin, sizeof(uint32_t));
10278        begin += sizeof(uint32_t);
10279      } else {
10280        flavor = 0;
10281        begin = end;
10282      }
10283      if (isLittleEndian != sys::IsLittleEndianHost)
10284        sys::swapByteOrder(flavor);
10285      if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
10286        memcpy((char *)&count, begin, sizeof(uint32_t));
10287        begin += sizeof(uint32_t);
10288      } else {
10289        count = 0;
10290        begin = end;
10291      }
10292      if (isLittleEndian != sys::IsLittleEndianHost)
10293        sys::swapByteOrder(count);
10294      outs() << "     flavor " << flavor << "\n";
10295      outs() << "      count " << count << "\n";
10296      outs() << "      state (Unknown cputype/cpusubtype)\n";
10297      begin += count * sizeof(uint32_t);
10298    }
10299  }
10300}
10301
10302static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
10303  if (dl.cmd == MachO::LC_ID_DYLIB)
10304    outs() << "          cmd LC_ID_DYLIB\n";
10305  else if (dl.cmd == MachO::LC_LOAD_DYLIB)
10306    outs() << "          cmd LC_LOAD_DYLIB\n";
10307  else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
10308    outs() << "          cmd LC_LOAD_WEAK_DYLIB\n";
10309  else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
10310    outs() << "          cmd LC_REEXPORT_DYLIB\n";
10311  else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
10312    outs() << "          cmd LC_LAZY_LOAD_DYLIB\n";
10313  else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
10314    outs() << "          cmd LC_LOAD_UPWARD_DYLIB\n";
10315  else
10316    outs() << "          cmd " << dl.cmd << " (unknown)\n";
10317  outs() << "      cmdsize " << dl.cmdsize;
10318  if (dl.cmdsize < sizeof(struct MachO::dylib_command))
10319    outs() << " Incorrect size\n";
10320  else
10321    outs() << "\n";
10322  if (dl.dylib.name < dl.cmdsize) {
10323    const char *P = (const char *)(Ptr) + dl.dylib.name;
10324    outs() << "         name " << P << " (offset " << dl.dylib.name << ")\n";
10325  } else {
10326    outs() << "         name ?(bad offset " << dl.dylib.name << ")\n";
10327  }
10328  outs() << "   time stamp " << dl.dylib.timestamp << " ";
10329  time_t t = dl.dylib.timestamp;
10330  outs() << ctime(&t);
10331  outs() << "      current version ";
10332  if (dl.dylib.current_version == 0xffffffff)
10333    outs() << "n/a\n";
10334  else
10335    outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
10336           << ((dl.dylib.current_version >> 8) & 0xff) << "."
10337           << (dl.dylib.current_version & 0xff) << "\n";
10338  outs() << "compatibility version ";
10339  if (dl.dylib.compatibility_version == 0xffffffff)
10340    outs() << "n/a\n";
10341  else
10342    outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
10343           << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
10344           << (dl.dylib.compatibility_version & 0xff) << "\n";
10345}
10346
10347static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
10348                                     uint32_t object_size) {
10349  if (ld.cmd == MachO::LC_CODE_SIGNATURE)
10350    outs() << "      cmd LC_CODE_SIGNATURE\n";
10351  else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
10352    outs() << "      cmd LC_SEGMENT_SPLIT_INFO\n";
10353  else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
10354    outs() << "      cmd LC_FUNCTION_STARTS\n";
10355  else if (ld.cmd == MachO::LC_DATA_IN_CODE)
10356    outs() << "      cmd LC_DATA_IN_CODE\n";
10357  else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
10358    outs() << "      cmd LC_DYLIB_CODE_SIGN_DRS\n";
10359  else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
10360    outs() << "      cmd LC_LINKER_OPTIMIZATION_HINT\n";
10361  else if (ld.cmd == MachO::LC_DYLD_EXPORTS_TRIE)
10362    outs() << "      cmd LC_DYLD_EXPORTS_TRIE\n";
10363  else if (ld.cmd == MachO::LC_DYLD_CHAINED_FIXUPS)
10364    outs() << "      cmd LC_DYLD_CHAINED_FIXUPS\n";
10365  else
10366    outs() << "      cmd " << ld.cmd << " (?)\n";
10367  outs() << "  cmdsize " << ld.cmdsize;
10368  if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
10369    outs() << " Incorrect size\n";
10370  else
10371    outs() << "\n";
10372  outs() << "  dataoff " << ld.dataoff;
10373  if (ld.dataoff > object_size)
10374    outs() << " (past end of file)\n";
10375  else
10376    outs() << "\n";
10377  outs() << " datasize " << ld.datasize;
10378  uint64_t big_size = ld.dataoff;
10379  big_size += ld.datasize;
10380  if (big_size > object_size)
10381    outs() << " (past end of file)\n";
10382  else
10383    outs() << "\n";
10384}
10385
10386static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
10387                              uint32_t cputype, bool verbose) {
10388  StringRef Buf = Obj->getData();
10389  unsigned Index = 0;
10390  for (const auto &Command : Obj->load_commands()) {
10391    outs() << "Load command " << Index++ << "\n";
10392    if (Command.C.cmd == MachO::LC_SEGMENT) {
10393      MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
10394      const char *sg_segname = SLC.segname;
10395      PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
10396                          SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
10397                          SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
10398                          verbose);
10399      for (unsigned j = 0; j < SLC.nsects; j++) {
10400        MachO::section S = Obj->getSection(Command, j);
10401        PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
10402                     S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
10403                     SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
10404      }
10405    } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
10406      MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
10407      const char *sg_segname = SLC_64.segname;
10408      PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
10409                          SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
10410                          SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
10411                          SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
10412      for (unsigned j = 0; j < SLC_64.nsects; j++) {
10413        MachO::section_64 S_64 = Obj->getSection64(Command, j);
10414        PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
10415                     S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
10416                     S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
10417                     sg_segname, filetype, Buf.size(), verbose);
10418      }
10419    } else if (Command.C.cmd == MachO::LC_SYMTAB) {
10420      MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10421      PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
10422    } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
10423      MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
10424      MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10425      PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
10426                               Obj->is64Bit());
10427    } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
10428               Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
10429      MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
10430      PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
10431    } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
10432               Command.C.cmd == MachO::LC_ID_DYLINKER ||
10433               Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
10434      MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
10435      PrintDyldLoadCommand(Dyld, Command.Ptr);
10436    } else if (Command.C.cmd == MachO::LC_UUID) {
10437      MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
10438      PrintUuidLoadCommand(Uuid);
10439    } else if (Command.C.cmd == MachO::LC_RPATH) {
10440      MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
10441      PrintRpathLoadCommand(Rpath, Command.Ptr);
10442    } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
10443               Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
10444               Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
10445               Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
10446      MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
10447      PrintVersionMinLoadCommand(Vd);
10448    } else if (Command.C.cmd == MachO::LC_NOTE) {
10449      MachO::note_command Nt = Obj->getNoteLoadCommand(Command);
10450      PrintNoteLoadCommand(Nt);
10451    } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) {
10452      MachO::build_version_command Bv =
10453          Obj->getBuildVersionLoadCommand(Command);
10454      PrintBuildVersionLoadCommand(Obj, Bv, verbose);
10455    } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
10456      MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
10457      PrintSourceVersionCommand(Sd);
10458    } else if (Command.C.cmd == MachO::LC_MAIN) {
10459      MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
10460      PrintEntryPointCommand(Ep);
10461    } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
10462      MachO::encryption_info_command Ei =
10463          Obj->getEncryptionInfoCommand(Command);
10464      PrintEncryptionInfoCommand(Ei, Buf.size());
10465    } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
10466      MachO::encryption_info_command_64 Ei =
10467          Obj->getEncryptionInfoCommand64(Command);
10468      PrintEncryptionInfoCommand64(Ei, Buf.size());
10469    } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
10470      MachO::linker_option_command Lo =
10471          Obj->getLinkerOptionLoadCommand(Command);
10472      PrintLinkerOptionCommand(Lo, Command.Ptr);
10473    } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
10474      MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
10475      PrintSubFrameworkCommand(Sf, Command.Ptr);
10476    } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
10477      MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
10478      PrintSubUmbrellaCommand(Sf, Command.Ptr);
10479    } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
10480      MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
10481      PrintSubLibraryCommand(Sl, Command.Ptr);
10482    } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
10483      MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
10484      PrintSubClientCommand(Sc, Command.Ptr);
10485    } else if (Command.C.cmd == MachO::LC_ROUTINES) {
10486      MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
10487      PrintRoutinesCommand(Rc);
10488    } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
10489      MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
10490      PrintRoutinesCommand64(Rc);
10491    } else if (Command.C.cmd == MachO::LC_THREAD ||
10492               Command.C.cmd == MachO::LC_UNIXTHREAD) {
10493      MachO::thread_command Tc = Obj->getThreadCommand(Command);
10494      PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
10495    } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
10496               Command.C.cmd == MachO::LC_ID_DYLIB ||
10497               Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
10498               Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
10499               Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
10500               Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
10501      MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
10502      PrintDylibCommand(Dl, Command.Ptr);
10503    } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
10504               Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
10505               Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
10506               Command.C.cmd == MachO::LC_DATA_IN_CODE ||
10507               Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
10508               Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT ||
10509               Command.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE ||
10510               Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) {
10511      MachO::linkedit_data_command Ld =
10512          Obj->getLinkeditDataLoadCommand(Command);
10513      PrintLinkEditDataCommand(Ld, Buf.size());
10514    } else {
10515      outs() << "      cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
10516             << ")\n";
10517      outs() << "  cmdsize " << Command.C.cmdsize << "\n";
10518      // TODO: get and print the raw bytes of the load command.
10519    }
10520    // TODO: print all the other kinds of load commands.
10521  }
10522}
10523
10524static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
10525  if (Obj->is64Bit()) {
10526    MachO::mach_header_64 H_64;
10527    H_64 = Obj->getHeader64();
10528    PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
10529                    H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
10530  } else {
10531    MachO::mach_header H;
10532    H = Obj->getHeader();
10533    PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
10534                    H.sizeofcmds, H.flags, verbose);
10535  }
10536}
10537
10538void objdump::printMachOFileHeader(const object::ObjectFile *Obj) {
10539  const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10540  PrintMachHeader(file, Verbose);
10541}
10542
10543void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) {
10544  const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10545  uint32_t filetype = 0;
10546  uint32_t cputype = 0;
10547  if (file->is64Bit()) {
10548    MachO::mach_header_64 H_64;
10549    H_64 = file->getHeader64();
10550    filetype = H_64.filetype;
10551    cputype = H_64.cputype;
10552  } else {
10553    MachO::mach_header H;
10554    H = file->getHeader();
10555    filetype = H.filetype;
10556    cputype = H.cputype;
10557  }
10558  PrintLoadCommands(file, filetype, cputype, Verbose);
10559}
10560
10561//===----------------------------------------------------------------------===//
10562// export trie dumping
10563//===----------------------------------------------------------------------===//
10564
10565static void printMachOExportsTrie(const object::MachOObjectFile *Obj) {
10566  uint64_t BaseSegmentAddress = 0;
10567  for (const auto &Command : Obj->load_commands()) {
10568    if (Command.C.cmd == MachO::LC_SEGMENT) {
10569      MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command);
10570      if (Seg.fileoff == 0 && Seg.filesize != 0) {
10571        BaseSegmentAddress = Seg.vmaddr;
10572        break;
10573      }
10574    } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
10575      MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command);
10576      if (Seg.fileoff == 0 && Seg.filesize != 0) {
10577        BaseSegmentAddress = Seg.vmaddr;
10578        break;
10579      }
10580    }
10581  }
10582  Error Err = Error::success();
10583  for (const object::ExportEntry &Entry : Obj->exports(Err)) {
10584    uint64_t Flags = Entry.flags();
10585    bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
10586    bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
10587    bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10588                        MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
10589    bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10590                MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
10591    bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
10592    if (ReExport)
10593      outs() << "[re-export] ";
10594    else
10595      outs() << format("0x%08llX  ",
10596                       Entry.address() + BaseSegmentAddress);
10597    outs() << Entry.name();
10598    if (WeakDef || ThreadLocal || Resolver || Abs) {
10599      ListSeparator LS;
10600      outs() << " [";
10601      if (WeakDef)
10602        outs() << LS << "weak_def";
10603      if (ThreadLocal)
10604        outs() << LS << "per-thread";
10605      if (Abs)
10606        outs() << LS << "absolute";
10607      if (Resolver)
10608        outs() << LS << format("resolver=0x%08llX", Entry.other());
10609      outs() << "]";
10610    }
10611    if (ReExport) {
10612      StringRef DylibName = "unknown";
10613      int Ordinal = Entry.other() - 1;
10614      Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
10615      if (Entry.otherName().empty())
10616        outs() << " (from " << DylibName << ")";
10617      else
10618        outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
10619    }
10620    outs() << "\n";
10621  }
10622  if (Err)
10623    reportError(std::move(Err), Obj->getFileName());
10624}
10625
10626//===----------------------------------------------------------------------===//
10627// rebase table dumping
10628//===----------------------------------------------------------------------===//
10629
10630static void printMachORebaseTable(object::MachOObjectFile *Obj) {
10631  outs() << "segment  section            address     type\n";
10632  Error Err = Error::success();
10633  for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) {
10634    StringRef SegmentName = Entry.segmentName();
10635    StringRef SectionName = Entry.sectionName();
10636    uint64_t Address = Entry.address();
10637
10638    // Table lines look like: __DATA  __nl_symbol_ptr  0x0000F00C  pointer
10639    outs() << format("%-8s %-18s 0x%08" PRIX64 "  %s\n",
10640                     SegmentName.str().c_str(), SectionName.str().c_str(),
10641                     Address, Entry.typeName().str().c_str());
10642  }
10643  if (Err)
10644    reportError(std::move(Err), Obj->getFileName());
10645}
10646
10647static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
10648  StringRef DylibName;
10649  switch (Ordinal) {
10650  case MachO::BIND_SPECIAL_DYLIB_SELF:
10651    return "this-image";
10652  case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
10653    return "main-executable";
10654  case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
10655    return "flat-namespace";
10656  case MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP:
10657    return "weak";
10658  default:
10659    if (Ordinal > 0) {
10660      std::error_code EC =
10661          Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
10662      if (EC)
10663        return "<<bad library ordinal>>";
10664      return DylibName;
10665    }
10666  }
10667  return "<<unknown special ordinal>>";
10668}
10669
10670//===----------------------------------------------------------------------===//
10671// bind table dumping
10672//===----------------------------------------------------------------------===//
10673
10674static void printMachOBindTable(object::MachOObjectFile *Obj) {
10675  // Build table of sections so names can used in final output.
10676  outs() << "segment  section            address    type       "
10677            "addend dylib            symbol\n";
10678  Error Err = Error::success();
10679  for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) {
10680    StringRef SegmentName = Entry.segmentName();
10681    StringRef SectionName = Entry.sectionName();
10682    uint64_t Address = Entry.address();
10683
10684    // Table lines look like:
10685    //  __DATA  __got  0x00012010    pointer   0 libSystem ___stack_chk_guard
10686    StringRef Attr;
10687    if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
10688      Attr = " (weak_import)";
10689    outs() << left_justify(SegmentName, 8) << " "
10690           << left_justify(SectionName, 18) << " "
10691           << format_hex(Address, 10, true) << " "
10692           << left_justify(Entry.typeName(), 8) << " "
10693           << format_decimal(Entry.addend(), 8) << " "
10694           << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10695           << Entry.symbolName() << Attr << "\n";
10696  }
10697  if (Err)
10698    reportError(std::move(Err), Obj->getFileName());
10699}
10700
10701//===----------------------------------------------------------------------===//
10702// lazy bind table dumping
10703//===----------------------------------------------------------------------===//
10704
10705static void printMachOLazyBindTable(object::MachOObjectFile *Obj) {
10706  outs() << "segment  section            address     "
10707            "dylib            symbol\n";
10708  Error Err = Error::success();
10709  for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) {
10710    StringRef SegmentName = Entry.segmentName();
10711    StringRef SectionName = Entry.sectionName();
10712    uint64_t Address = Entry.address();
10713
10714    // Table lines look like:
10715    //  __DATA  __got  0x00012010 libSystem ___stack_chk_guard
10716    outs() << left_justify(SegmentName, 8) << " "
10717           << left_justify(SectionName, 18) << " "
10718           << format_hex(Address, 10, true) << " "
10719           << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10720           << Entry.symbolName() << "\n";
10721  }
10722  if (Err)
10723    reportError(std::move(Err), Obj->getFileName());
10724}
10725
10726//===----------------------------------------------------------------------===//
10727// weak bind table dumping
10728//===----------------------------------------------------------------------===//
10729
10730static void printMachOWeakBindTable(object::MachOObjectFile *Obj) {
10731  outs() << "segment  section            address     "
10732            "type       addend   symbol\n";
10733  Error Err = Error::success();
10734  for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) {
10735    // Strong symbols don't have a location to update.
10736    if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
10737      outs() << "                                        strong              "
10738             << Entry.symbolName() << "\n";
10739      continue;
10740    }
10741    StringRef SegmentName = Entry.segmentName();
10742    StringRef SectionName = Entry.sectionName();
10743    uint64_t Address = Entry.address();
10744
10745    // Table lines look like:
10746    // __DATA  __data  0x00001000  pointer    0   _foo
10747    outs() << left_justify(SegmentName, 8) << " "
10748           << left_justify(SectionName, 18) << " "
10749           << format_hex(Address, 10, true) << " "
10750           << left_justify(Entry.typeName(), 8) << " "
10751           << format_decimal(Entry.addend(), 8) << "   " << Entry.symbolName()
10752           << "\n";
10753  }
10754  if (Err)
10755    reportError(std::move(Err), Obj->getFileName());
10756}
10757
10758// get_dyld_bind_info_symbolname() is used for disassembly and passed an
10759// address, ReferenceValue, in the Mach-O file and looks in the dyld bind
10760// information for that address. If the address is found its binding symbol
10761// name is returned.  If not nullptr is returned.
10762static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
10763                                                 struct DisassembleInfo *info) {
10764  if (info->bindtable == nullptr) {
10765    info->bindtable = std::make_unique<SymbolAddressMap>();
10766    Error Err = Error::success();
10767    for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) {
10768      uint64_t Address = Entry.address();
10769      StringRef name = Entry.symbolName();
10770      if (!name.empty())
10771        (*info->bindtable)[Address] = name;
10772    }
10773    if (Err)
10774      reportError(std::move(Err), info->O->getFileName());
10775  }
10776  auto name = info->bindtable->lookup(ReferenceValue);
10777  return !name.empty() ? name.data() : nullptr;
10778}
10779
10780void objdump::printLazyBindTable(ObjectFile *o) {
10781  outs() << "\nLazy bind table:\n";
10782  if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10783    printMachOLazyBindTable(MachO);
10784  else
10785    WithColor::error()
10786        << "This operation is only currently supported "
10787           "for Mach-O executable files.\n";
10788}
10789
10790void objdump::printWeakBindTable(ObjectFile *o) {
10791  outs() << "\nWeak bind table:\n";
10792  if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10793    printMachOWeakBindTable(MachO);
10794  else
10795    WithColor::error()
10796        << "This operation is only currently supported "
10797           "for Mach-O executable files.\n";
10798}
10799
10800void objdump::printExportsTrie(const ObjectFile *o) {
10801  outs() << "\nExports trie:\n";
10802  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10803    printMachOExportsTrie(MachO);
10804  else
10805    WithColor::error()
10806        << "This operation is only currently supported "
10807           "for Mach-O executable files.\n";
10808}
10809
10810void objdump::printRebaseTable(ObjectFile *o) {
10811  outs() << "\nRebase table:\n";
10812  if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10813    printMachORebaseTable(MachO);
10814  else
10815    WithColor::error()
10816        << "This operation is only currently supported "
10817           "for Mach-O executable files.\n";
10818}
10819
10820void objdump::printBindTable(ObjectFile *o) {
10821  outs() << "\nBind table:\n";
10822  if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10823    printMachOBindTable(MachO);
10824  else
10825    WithColor::error()
10826        << "This operation is only currently supported "
10827           "for Mach-O executable files.\n";
10828}
10829