xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1  //===-- MachODump.cpp - Object file dumping utility for llvm --------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file implements the MachO-specific dumper for llvm-objdump.
10  //
11  //===----------------------------------------------------------------------===//
12  
13  #include "MachODump.h"
14  
15  #include "ObjdumpOptID.h"
16  #include "llvm-objdump.h"
17  #include "llvm-c/Disassembler.h"
18  #include "llvm/ADT/STLExtras.h"
19  #include "llvm/ADT/StringExtras.h"
20  #include "llvm/BinaryFormat/MachO.h"
21  #include "llvm/Config/config.h"
22  #include "llvm/DebugInfo/DIContext.h"
23  #include "llvm/DebugInfo/DWARF/DWARFContext.h"
24  #include "llvm/Demangle/Demangle.h"
25  #include "llvm/MC/MCAsmInfo.h"
26  #include "llvm/MC/MCContext.h"
27  #include "llvm/MC/MCDisassembler/MCDisassembler.h"
28  #include "llvm/MC/MCInst.h"
29  #include "llvm/MC/MCInstPrinter.h"
30  #include "llvm/MC/MCInstrDesc.h"
31  #include "llvm/MC/MCInstrInfo.h"
32  #include "llvm/MC/MCRegisterInfo.h"
33  #include "llvm/MC/MCSubtargetInfo.h"
34  #include "llvm/MC/MCTargetOptions.h"
35  #include "llvm/MC/TargetRegistry.h"
36  #include "llvm/Object/MachO.h"
37  #include "llvm/Object/MachOUniversal.h"
38  #include "llvm/Option/ArgList.h"
39  #include "llvm/Support/Casting.h"
40  #include "llvm/Support/Debug.h"
41  #include "llvm/Support/Endian.h"
42  #include "llvm/Support/Format.h"
43  #include "llvm/Support/FormattedStream.h"
44  #include "llvm/Support/GraphWriter.h"
45  #include "llvm/Support/LEB128.h"
46  #include "llvm/Support/MemoryBuffer.h"
47  #include "llvm/Support/TargetSelect.h"
48  #include "llvm/Support/ToolOutputFile.h"
49  #include "llvm/Support/WithColor.h"
50  #include "llvm/Support/raw_ostream.h"
51  #include "llvm/TargetParser/Triple.h"
52  #include <algorithm>
53  #include <cstring>
54  #include <system_error>
55  
56  using namespace llvm;
57  using namespace llvm::object;
58  using namespace llvm::objdump;
59  
60  bool objdump::FirstPrivateHeader;
61  bool objdump::ExportsTrie;
62  bool objdump::Rebase;
63  bool objdump::Rpaths;
64  bool objdump::Bind;
65  bool objdump::LazyBind;
66  bool objdump::WeakBind;
67  static bool UseDbg;
68  static std::string DSYMFile;
69  bool objdump::FullLeadingAddr;
70  bool objdump::LeadingHeaders;
71  bool objdump::UniversalHeaders;
72  static bool ArchiveMemberOffsets;
73  bool objdump::IndirectSymbols;
74  bool objdump::DataInCode;
75  FunctionStartsMode objdump::FunctionStartsType =
76      objdump::FunctionStartsMode::None;
77  bool objdump::LinkOptHints;
78  bool objdump::InfoPlist;
79  bool objdump::ChainedFixups;
80  bool objdump::DyldInfo;
81  bool objdump::DylibsUsed;
82  bool objdump::DylibId;
83  bool objdump::Verbose;
84  bool objdump::ObjcMetaData;
85  std::string objdump::DisSymName;
86  bool objdump::SymbolicOperands;
87  static std::vector<std::string> ArchFlags;
88  
89  static bool ArchAll = false;
90  static std::string ThumbTripleName;
91  
92  static StringRef ordinalName(const object::MachOObjectFile *, int);
93  
parseMachOOptions(const llvm::opt::InputArgList & InputArgs)94  void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) {
95    FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header);
96    ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie);
97    Rebase = InputArgs.hasArg(OBJDUMP_rebase);
98    Rpaths = InputArgs.hasArg(OBJDUMP_rpaths);
99    Bind = InputArgs.hasArg(OBJDUMP_bind);
100    LazyBind = InputArgs.hasArg(OBJDUMP_lazy_bind);
101    WeakBind = InputArgs.hasArg(OBJDUMP_weak_bind);
102    UseDbg = InputArgs.hasArg(OBJDUMP_g);
103    DSYMFile = InputArgs.getLastArgValue(OBJDUMP_dsym_EQ).str();
104    FullLeadingAddr = InputArgs.hasArg(OBJDUMP_full_leading_addr);
105    LeadingHeaders = !InputArgs.hasArg(OBJDUMP_no_leading_headers);
106    UniversalHeaders = InputArgs.hasArg(OBJDUMP_universal_headers);
107    ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets);
108    IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols);
109    DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code);
110    if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_function_starts_EQ)) {
111      FunctionStartsType = StringSwitch<FunctionStartsMode>(A->getValue())
112                               .Case("addrs", FunctionStartsMode::Addrs)
113                               .Case("names", FunctionStartsMode::Names)
114                               .Case("both", FunctionStartsMode::Both)
115                               .Default(FunctionStartsMode::None);
116      if (FunctionStartsType == FunctionStartsMode::None)
117        invalidArgValue(A);
118    }
119    LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints);
120    InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist);
121    ChainedFixups = InputArgs.hasArg(OBJDUMP_chained_fixups);
122    DyldInfo = InputArgs.hasArg(OBJDUMP_dyld_info);
123    DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used);
124    DylibId = InputArgs.hasArg(OBJDUMP_dylib_id);
125    Verbose = !InputArgs.hasArg(OBJDUMP_non_verbose);
126    ObjcMetaData = InputArgs.hasArg(OBJDUMP_objc_meta_data);
127    DisSymName = InputArgs.getLastArgValue(OBJDUMP_dis_symname).str();
128    SymbolicOperands = !InputArgs.hasArg(OBJDUMP_no_symbolic_operands);
129    ArchFlags = InputArgs.getAllArgValues(OBJDUMP_arch_EQ);
130  }
131  
GetTarget(const MachOObjectFile * MachOObj,const char ** McpuDefault,const Target ** ThumbTarget)132  static const Target *GetTarget(const MachOObjectFile *MachOObj,
133                                 const char **McpuDefault,
134                                 const Target **ThumbTarget) {
135    // Figure out the target triple.
136    Triple TT(TripleName);
137    if (TripleName.empty()) {
138      TT = MachOObj->getArchTriple(McpuDefault);
139      TripleName = TT.str();
140    }
141  
142    if (TT.getArch() == Triple::arm) {
143      // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
144      // that support ARM are also capable of Thumb mode.
145      Triple ThumbTriple = TT;
146      std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
147      ThumbTriple.setArchName(ThumbName);
148      ThumbTripleName = ThumbTriple.str();
149    }
150  
151    // Get the target specific parser.
152    std::string Error;
153    const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
154    if (TheTarget && ThumbTripleName.empty())
155      return TheTarget;
156  
157    *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
158    if (*ThumbTarget)
159      return TheTarget;
160  
161    WithColor::error(errs(), "llvm-objdump") << "unable to get target for '";
162    if (!TheTarget)
163      errs() << TripleName;
164    else
165      errs() << ThumbTripleName;
166    errs() << "', see --version and --triple.\n";
167    return nullptr;
168  }
169  
170  namespace {
171  struct SymbolSorter {
operator ()__anon061faff00111::SymbolSorter172    bool operator()(const SymbolRef &A, const SymbolRef &B) {
173      Expected<SymbolRef::Type> ATypeOrErr = A.getType();
174      if (!ATypeOrErr)
175        reportError(ATypeOrErr.takeError(), A.getObject()->getFileName());
176      SymbolRef::Type AType = *ATypeOrErr;
177      Expected<SymbolRef::Type> BTypeOrErr = B.getType();
178      if (!BTypeOrErr)
179        reportError(BTypeOrErr.takeError(), B.getObject()->getFileName());
180      SymbolRef::Type BType = *BTypeOrErr;
181      uint64_t AAddr =
182          (AType != SymbolRef::ST_Function) ? 0 : cantFail(A.getValue());
183      uint64_t BAddr =
184          (BType != SymbolRef::ST_Function) ? 0 : cantFail(B.getValue());
185      return AAddr < BAddr;
186    }
187  };
188  
189  class MachODumper : public Dumper {
190    const object::MachOObjectFile &Obj;
191  
192  public:
MachODumper(const object::MachOObjectFile & O)193    MachODumper(const object::MachOObjectFile &O) : Dumper(O), Obj(O) {}
194    void printPrivateHeaders() override;
195  };
196  } // namespace
197  
198  std::unique_ptr<Dumper>
createMachODumper(const object::MachOObjectFile & Obj)199  objdump::createMachODumper(const object::MachOObjectFile &Obj) {
200    return std::make_unique<MachODumper>(Obj);
201  }
202  
203  // Types for the storted data in code table that is built before disassembly
204  // and the predicate function to sort them.
205  typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
206  typedef std::vector<DiceTableEntry> DiceTable;
207  typedef DiceTable::iterator dice_table_iterator;
208  
209  // This is used to search for a data in code table entry for the PC being
210  // disassembled.  The j parameter has the PC in j.first.  A single data in code
211  // table entry can cover many bytes for each of its Kind's.  So if the offset,
212  // aka the i.first value, of the data in code table entry plus its Length
213  // covers the PC being searched for this will return true.  If not it will
214  // return false.
compareDiceTableEntries(const DiceTableEntry & i,const DiceTableEntry & j)215  static bool compareDiceTableEntries(const DiceTableEntry &i,
216                                      const DiceTableEntry &j) {
217    uint16_t Length;
218    i.second.getLength(Length);
219  
220    return j.first >= i.first && j.first < i.first + Length;
221  }
222  
DumpDataInCode(const uint8_t * bytes,uint64_t Length,unsigned short Kind)223  static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
224                                 unsigned short Kind) {
225    uint32_t Value, Size = 1;
226  
227    switch (Kind) {
228    default:
229    case MachO::DICE_KIND_DATA:
230      if (Length >= 4) {
231        if (ShowRawInsn)
232          dumpBytes(ArrayRef(bytes, 4), outs());
233        Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
234        outs() << "\t.long " << Value;
235        Size = 4;
236      } else if (Length >= 2) {
237        if (ShowRawInsn)
238          dumpBytes(ArrayRef(bytes, 2), outs());
239        Value = bytes[1] << 8 | bytes[0];
240        outs() << "\t.short " << Value;
241        Size = 2;
242      } else {
243        if (ShowRawInsn)
244          dumpBytes(ArrayRef(bytes, 2), outs());
245        Value = bytes[0];
246        outs() << "\t.byte " << Value;
247        Size = 1;
248      }
249      if (Kind == MachO::DICE_KIND_DATA)
250        outs() << "\t@ KIND_DATA\n";
251      else
252        outs() << "\t@ data in code kind = " << Kind << "\n";
253      break;
254    case MachO::DICE_KIND_JUMP_TABLE8:
255      if (ShowRawInsn)
256        dumpBytes(ArrayRef(bytes, 1), outs());
257      Value = bytes[0];
258      outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
259      Size = 1;
260      break;
261    case MachO::DICE_KIND_JUMP_TABLE16:
262      if (ShowRawInsn)
263        dumpBytes(ArrayRef(bytes, 2), outs());
264      Value = bytes[1] << 8 | bytes[0];
265      outs() << "\t.short " << format("%5u", Value & 0xffff)
266             << "\t@ KIND_JUMP_TABLE16\n";
267      Size = 2;
268      break;
269    case MachO::DICE_KIND_JUMP_TABLE32:
270    case MachO::DICE_KIND_ABS_JUMP_TABLE32:
271      if (ShowRawInsn)
272        dumpBytes(ArrayRef(bytes, 4), outs());
273      Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
274      outs() << "\t.long " << Value;
275      if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
276        outs() << "\t@ KIND_JUMP_TABLE32\n";
277      else
278        outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
279      Size = 4;
280      break;
281    }
282    return Size;
283  }
284  
getSectionsAndSymbols(MachOObjectFile * MachOObj,std::vector<SectionRef> & Sections,std::vector<SymbolRef> & Symbols,SmallVectorImpl<uint64_t> & FoundFns,uint64_t & BaseSegmentAddress)285  static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
286                                    std::vector<SectionRef> &Sections,
287                                    std::vector<SymbolRef> &Symbols,
288                                    SmallVectorImpl<uint64_t> &FoundFns,
289                                    uint64_t &BaseSegmentAddress) {
290    const StringRef FileName = MachOObj->getFileName();
291    for (const SymbolRef &Symbol : MachOObj->symbols()) {
292      StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
293      if (!SymName.starts_with("ltmp"))
294        Symbols.push_back(Symbol);
295    }
296  
297    append_range(Sections, MachOObj->sections());
298  
299    bool BaseSegmentAddressSet = false;
300    for (const auto &Command : MachOObj->load_commands()) {
301      if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
302        // We found a function starts segment, parse the addresses for later
303        // consumption.
304        MachO::linkedit_data_command LLC =
305            MachOObj->getLinkeditDataLoadCommand(Command);
306  
307        MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
308      } else if (Command.C.cmd == MachO::LC_SEGMENT) {
309        MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
310        StringRef SegName = SLC.segname;
311        if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
312          BaseSegmentAddressSet = true;
313          BaseSegmentAddress = SLC.vmaddr;
314        }
315      } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
316        MachO::segment_command_64 SLC = MachOObj->getSegment64LoadCommand(Command);
317        StringRef SegName = SLC.segname;
318        if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
319          BaseSegmentAddressSet = true;
320          BaseSegmentAddress = SLC.vmaddr;
321        }
322      }
323    }
324  }
325  
DumpAndSkipDataInCode(uint64_t PC,const uint8_t * bytes,DiceTable & Dices,uint64_t & InstSize)326  static bool DumpAndSkipDataInCode(uint64_t PC, const uint8_t *bytes,
327                                   DiceTable &Dices, uint64_t &InstSize) {
328    // Check the data in code table here to see if this is data not an
329    // instruction to be disassembled.
330    DiceTable Dice;
331    Dice.push_back(std::make_pair(PC, DiceRef()));
332    dice_table_iterator DTI =
333        std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
334                    compareDiceTableEntries);
335    if (DTI != Dices.end()) {
336      uint16_t Length;
337      DTI->second.getLength(Length);
338      uint16_t Kind;
339      DTI->second.getKind(Kind);
340      InstSize = DumpDataInCode(bytes, Length, Kind);
341      if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
342          (PC == (DTI->first + Length - 1)) && (Length & 1))
343        InstSize++;
344      return true;
345    }
346    return false;
347  }
348  
printRelocationTargetName(const MachOObjectFile * O,const MachO::any_relocation_info & RE,raw_string_ostream & Fmt)349  static void printRelocationTargetName(const MachOObjectFile *O,
350                                        const MachO::any_relocation_info &RE,
351                                        raw_string_ostream &Fmt) {
352    // Target of a scattered relocation is an address.  In the interest of
353    // generating pretty output, scan through the symbol table looking for a
354    // symbol that aligns with that address.  If we find one, print it.
355    // Otherwise, we just print the hex address of the target.
356    const StringRef FileName = O->getFileName();
357    if (O->isRelocationScattered(RE)) {
358      uint32_t Val = O->getPlainRelocationSymbolNum(RE);
359  
360      for (const SymbolRef &Symbol : O->symbols()) {
361        uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
362        if (Addr != Val)
363          continue;
364        Fmt << unwrapOrError(Symbol.getName(), FileName);
365        return;
366      }
367  
368      // If we couldn't find a symbol that this relocation refers to, try
369      // to find a section beginning instead.
370      for (const SectionRef &Section : ToolSectionFilter(*O)) {
371        uint64_t Addr = Section.getAddress();
372        if (Addr != Val)
373          continue;
374        StringRef NameOrErr = unwrapOrError(Section.getName(), O->getFileName());
375        Fmt << NameOrErr;
376        return;
377      }
378  
379      Fmt << format("0x%x", Val);
380      return;
381    }
382  
383    StringRef S;
384    bool isExtern = O->getPlainRelocationExternal(RE);
385    uint64_t Val = O->getPlainRelocationSymbolNum(RE);
386  
387    if (O->getAnyRelocationType(RE) == MachO::ARM64_RELOC_ADDEND &&
388        (O->getArch() == Triple::aarch64 || O->getArch() == Triple::aarch64_be)) {
389      Fmt << format("0x%0" PRIx64, Val);
390      return;
391    }
392  
393    if (isExtern) {
394      symbol_iterator SI = O->symbol_begin();
395      std::advance(SI, Val);
396      S = unwrapOrError(SI->getName(), FileName);
397    } else {
398      section_iterator SI = O->section_begin();
399      // Adjust for the fact that sections are 1-indexed.
400      if (Val == 0) {
401        Fmt << "0 (?,?)";
402        return;
403      }
404      uint32_t I = Val - 1;
405      while (I != 0 && SI != O->section_end()) {
406        --I;
407        std::advance(SI, 1);
408      }
409      if (SI == O->section_end()) {
410        Fmt << Val << " (?,?)";
411      } else {
412        if (Expected<StringRef> NameOrErr = SI->getName())
413          S = *NameOrErr;
414        else
415          consumeError(NameOrErr.takeError());
416      }
417    }
418  
419    Fmt << S;
420  }
421  
getMachORelocationValueString(const MachOObjectFile * Obj,const RelocationRef & RelRef,SmallVectorImpl<char> & Result)422  Error objdump::getMachORelocationValueString(const MachOObjectFile *Obj,
423                                               const RelocationRef &RelRef,
424                                               SmallVectorImpl<char> &Result) {
425    DataRefImpl Rel = RelRef.getRawDataRefImpl();
426    MachO::any_relocation_info RE = Obj->getRelocation(Rel);
427  
428    unsigned Arch = Obj->getArch();
429  
430    std::string FmtBuf;
431    raw_string_ostream Fmt(FmtBuf);
432    unsigned Type = Obj->getAnyRelocationType(RE);
433    bool IsPCRel = Obj->getAnyRelocationPCRel(RE);
434  
435    // Determine any addends that should be displayed with the relocation.
436    // These require decoding the relocation type, which is triple-specific.
437  
438    // X86_64 has entirely custom relocation types.
439    if (Arch == Triple::x86_64) {
440      switch (Type) {
441      case MachO::X86_64_RELOC_GOT_LOAD:
442      case MachO::X86_64_RELOC_GOT: {
443        printRelocationTargetName(Obj, RE, Fmt);
444        Fmt << "@GOT";
445        if (IsPCRel)
446          Fmt << "PCREL";
447        break;
448      }
449      case MachO::X86_64_RELOC_SUBTRACTOR: {
450        DataRefImpl RelNext = Rel;
451        Obj->moveRelocationNext(RelNext);
452        MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
453  
454        // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type
455        // X86_64_RELOC_UNSIGNED.
456        // NOTE: Scattered relocations don't exist on x86_64.
457        unsigned RType = Obj->getAnyRelocationType(RENext);
458        if (RType != MachO::X86_64_RELOC_UNSIGNED)
459          reportError(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after "
460                                          "X86_64_RELOC_SUBTRACTOR.");
461  
462        // The X86_64_RELOC_UNSIGNED contains the minuend symbol;
463        // X86_64_RELOC_SUBTRACTOR contains the subtrahend.
464        printRelocationTargetName(Obj, RENext, Fmt);
465        Fmt << "-";
466        printRelocationTargetName(Obj, RE, Fmt);
467        break;
468      }
469      case MachO::X86_64_RELOC_TLV:
470        printRelocationTargetName(Obj, RE, Fmt);
471        Fmt << "@TLV";
472        if (IsPCRel)
473          Fmt << "P";
474        break;
475      case MachO::X86_64_RELOC_SIGNED_1:
476        printRelocationTargetName(Obj, RE, Fmt);
477        Fmt << "-1";
478        break;
479      case MachO::X86_64_RELOC_SIGNED_2:
480        printRelocationTargetName(Obj, RE, Fmt);
481        Fmt << "-2";
482        break;
483      case MachO::X86_64_RELOC_SIGNED_4:
484        printRelocationTargetName(Obj, RE, Fmt);
485        Fmt << "-4";
486        break;
487      default:
488        printRelocationTargetName(Obj, RE, Fmt);
489        break;
490      }
491      // X86 and ARM share some relocation types in common.
492    } else if (Arch == Triple::x86 || Arch == Triple::arm ||
493               Arch == Triple::ppc) {
494      // Generic relocation types...
495      switch (Type) {
496      case MachO::GENERIC_RELOC_PAIR: // prints no info
497        return Error::success();
498      case MachO::GENERIC_RELOC_SECTDIFF: {
499        DataRefImpl RelNext = Rel;
500        Obj->moveRelocationNext(RelNext);
501        MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
502  
503        // X86 sect diff's must be followed by a relocation of type
504        // GENERIC_RELOC_PAIR.
505        unsigned RType = Obj->getAnyRelocationType(RENext);
506  
507        if (RType != MachO::GENERIC_RELOC_PAIR)
508          reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
509                                          "GENERIC_RELOC_SECTDIFF.");
510  
511        printRelocationTargetName(Obj, RE, Fmt);
512        Fmt << "-";
513        printRelocationTargetName(Obj, RENext, Fmt);
514        break;
515      }
516      }
517  
518      if (Arch == Triple::x86 || Arch == Triple::ppc) {
519        switch (Type) {
520        case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
521          DataRefImpl RelNext = Rel;
522          Obj->moveRelocationNext(RelNext);
523          MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
524  
525          // X86 sect diff's must be followed by a relocation of type
526          // GENERIC_RELOC_PAIR.
527          unsigned RType = Obj->getAnyRelocationType(RENext);
528          if (RType != MachO::GENERIC_RELOC_PAIR)
529            reportError(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after "
530                                            "GENERIC_RELOC_LOCAL_SECTDIFF.");
531  
532          printRelocationTargetName(Obj, RE, Fmt);
533          Fmt << "-";
534          printRelocationTargetName(Obj, RENext, Fmt);
535          break;
536        }
537        case MachO::GENERIC_RELOC_TLV: {
538          printRelocationTargetName(Obj, RE, Fmt);
539          Fmt << "@TLV";
540          if (IsPCRel)
541            Fmt << "P";
542          break;
543        }
544        default:
545          printRelocationTargetName(Obj, RE, Fmt);
546        }
547      } else { // ARM-specific relocations
548        switch (Type) {
549        case MachO::ARM_RELOC_HALF:
550        case MachO::ARM_RELOC_HALF_SECTDIFF: {
551          // Half relocations steal a bit from the length field to encode
552          // whether this is an upper16 or a lower16 relocation.
553          bool isUpper = (Obj->getAnyRelocationLength(RE) & 0x1) == 1;
554  
555          if (isUpper)
556            Fmt << ":upper16:(";
557          else
558            Fmt << ":lower16:(";
559          printRelocationTargetName(Obj, RE, Fmt);
560  
561          DataRefImpl RelNext = Rel;
562          Obj->moveRelocationNext(RelNext);
563          MachO::any_relocation_info RENext = Obj->getRelocation(RelNext);
564  
565          // ARM half relocs must be followed by a relocation of type
566          // ARM_RELOC_PAIR.
567          unsigned RType = Obj->getAnyRelocationType(RENext);
568          if (RType != MachO::ARM_RELOC_PAIR)
569            reportError(Obj->getFileName(), "Expected ARM_RELOC_PAIR after "
570                                            "ARM_RELOC_HALF");
571  
572          // NOTE: The half of the target virtual address is stashed in the
573          // address field of the secondary relocation, but we can't reverse
574          // engineer the constant offset from it without decoding the movw/movt
575          // instruction to find the other half in its immediate field.
576  
577          // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
578          // symbol/section pointer of the follow-on relocation.
579          if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
580            Fmt << "-";
581            printRelocationTargetName(Obj, RENext, Fmt);
582          }
583  
584          Fmt << ")";
585          break;
586        }
587        default: {
588          printRelocationTargetName(Obj, RE, Fmt);
589        }
590        }
591      }
592    } else
593      printRelocationTargetName(Obj, RE, Fmt);
594  
595    Fmt.flush();
596    Result.append(FmtBuf.begin(), FmtBuf.end());
597    return Error::success();
598  }
599  
PrintIndirectSymbolTable(MachOObjectFile * O,bool verbose,uint32_t n,uint32_t count,uint32_t stride,uint64_t addr)600  static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
601                                       uint32_t n, uint32_t count,
602                                       uint32_t stride, uint64_t addr) {
603    MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
604    uint32_t nindirectsyms = Dysymtab.nindirectsyms;
605    if (n > nindirectsyms)
606      outs() << " (entries start past the end of the indirect symbol "
607                "table) (reserved1 field greater than the table size)";
608    else if (n + count > nindirectsyms)
609      outs() << " (entries extends past the end of the indirect symbol "
610                "table)";
611    outs() << "\n";
612    uint32_t cputype = O->getHeader().cputype;
613    if (cputype & MachO::CPU_ARCH_ABI64)
614      outs() << "address            index";
615    else
616      outs() << "address    index";
617    if (verbose)
618      outs() << " name\n";
619    else
620      outs() << "\n";
621    for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
622      if (cputype & MachO::CPU_ARCH_ABI64)
623        outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
624      else
625        outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
626      MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
627      uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
628      if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
629        outs() << "LOCAL\n";
630        continue;
631      }
632      if (indirect_symbol ==
633          (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
634        outs() << "LOCAL ABSOLUTE\n";
635        continue;
636      }
637      if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
638        outs() << "ABSOLUTE\n";
639        continue;
640      }
641      outs() << format("%5u ", indirect_symbol);
642      if (verbose) {
643        MachO::symtab_command Symtab = O->getSymtabLoadCommand();
644        if (indirect_symbol < Symtab.nsyms) {
645          symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
646          SymbolRef Symbol = *Sym;
647          outs() << unwrapOrError(Symbol.getName(), O->getFileName());
648        } else {
649          outs() << "?";
650        }
651      }
652      outs() << "\n";
653    }
654  }
655  
PrintIndirectSymbols(MachOObjectFile * O,bool verbose)656  static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
657    for (const auto &Load : O->load_commands()) {
658      if (Load.C.cmd == MachO::LC_SEGMENT_64) {
659        MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
660        for (unsigned J = 0; J < Seg.nsects; ++J) {
661          MachO::section_64 Sec = O->getSection64(Load, J);
662          uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
663          if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
664              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
665              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
666              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
667              section_type == MachO::S_SYMBOL_STUBS) {
668            uint32_t stride;
669            if (section_type == MachO::S_SYMBOL_STUBS)
670              stride = Sec.reserved2;
671            else
672              stride = 8;
673            if (stride == 0) {
674              outs() << "Can't print indirect symbols for (" << Sec.segname << ","
675                     << Sec.sectname << ") "
676                     << "(size of stubs in reserved2 field is zero)\n";
677              continue;
678            }
679            uint32_t count = Sec.size / stride;
680            outs() << "Indirect symbols for (" << Sec.segname << ","
681                   << Sec.sectname << ") " << count << " entries";
682            uint32_t n = Sec.reserved1;
683            PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
684          }
685        }
686      } else if (Load.C.cmd == MachO::LC_SEGMENT) {
687        MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
688        for (unsigned J = 0; J < Seg.nsects; ++J) {
689          MachO::section Sec = O->getSection(Load, J);
690          uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
691          if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
692              section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
693              section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
694              section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
695              section_type == MachO::S_SYMBOL_STUBS) {
696            uint32_t stride;
697            if (section_type == MachO::S_SYMBOL_STUBS)
698              stride = Sec.reserved2;
699            else
700              stride = 4;
701            if (stride == 0) {
702              outs() << "Can't print indirect symbols for (" << Sec.segname << ","
703                     << Sec.sectname << ") "
704                     << "(size of stubs in reserved2 field is zero)\n";
705              continue;
706            }
707            uint32_t count = Sec.size / stride;
708            outs() << "Indirect symbols for (" << Sec.segname << ","
709                   << Sec.sectname << ") " << count << " entries";
710            uint32_t n = Sec.reserved1;
711            PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
712          }
713        }
714      }
715    }
716  }
717  
PrintRType(const uint64_t cputype,const unsigned r_type)718  static void PrintRType(const uint64_t cputype, const unsigned r_type) {
719    static char const *generic_r_types[] = {
720      "VANILLA ", "PAIR    ", "SECTDIF ", "PBLAPTR ", "LOCSDIF ", "TLV     ",
721      "  6 (?) ", "  7 (?) ", "  8 (?) ", "  9 (?) ", " 10 (?) ", " 11 (?) ",
722      " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
723    };
724    static char const *x86_64_r_types[] = {
725      "UNSIGND ", "SIGNED  ", "BRANCH  ", "GOT_LD  ", "GOT     ", "SUB     ",
726      "SIGNED1 ", "SIGNED2 ", "SIGNED4 ", "TLV     ", " 10 (?) ", " 11 (?) ",
727      " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
728    };
729    static char const *arm_r_types[] = {
730      "VANILLA ", "PAIR    ", "SECTDIFF", "LOCSDIF ", "PBLAPTR ",
731      "BR24    ", "T_BR22  ", "T_BR32  ", "HALF    ", "HALFDIF ",
732      " 10 (?) ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
733    };
734    static char const *arm64_r_types[] = {
735      "UNSIGND ", "SUB     ", "BR26    ", "PAGE21  ", "PAGOF12 ",
736      "GOTLDP  ", "GOTLDPOF", "PTRTGOT ", "TLVLDP  ", "TLVLDPOF",
737      "ADDEND  ", " 11 (?) ", " 12 (?) ", " 13 (?) ", " 14 (?) ", " 15 (?) "
738    };
739  
740    if (r_type > 0xf){
741      outs() << format("%-7u", r_type) << " ";
742      return;
743    }
744    switch (cputype) {
745      case MachO::CPU_TYPE_I386:
746        outs() << generic_r_types[r_type];
747        break;
748      case MachO::CPU_TYPE_X86_64:
749        outs() << x86_64_r_types[r_type];
750        break;
751      case MachO::CPU_TYPE_ARM:
752        outs() << arm_r_types[r_type];
753        break;
754      case MachO::CPU_TYPE_ARM64:
755      case MachO::CPU_TYPE_ARM64_32:
756        outs() << arm64_r_types[r_type];
757        break;
758      default:
759        outs() << format("%-7u ", r_type);
760    }
761  }
762  
PrintRLength(const uint64_t cputype,const unsigned r_type,const unsigned r_length,const bool previous_arm_half)763  static void PrintRLength(const uint64_t cputype, const unsigned r_type,
764                           const unsigned r_length, const bool previous_arm_half){
765    if (cputype == MachO::CPU_TYPE_ARM &&
766        (r_type == MachO::ARM_RELOC_HALF ||
767         r_type == MachO::ARM_RELOC_HALF_SECTDIFF || previous_arm_half == true)) {
768      if ((r_length & 0x1) == 0)
769        outs() << "lo/";
770      else
771        outs() << "hi/";
772      if ((r_length & 0x1) == 0)
773        outs() << "arm ";
774      else
775        outs() << "thm ";
776    } else {
777      switch (r_length) {
778        case 0:
779          outs() << "byte   ";
780          break;
781        case 1:
782          outs() << "word   ";
783          break;
784        case 2:
785          outs() << "long   ";
786          break;
787        case 3:
788          if (cputype == MachO::CPU_TYPE_X86_64)
789            outs() << "quad   ";
790          else
791            outs() << format("?(%2d)  ", r_length);
792          break;
793        default:
794          outs() << format("?(%2d)  ", r_length);
795      }
796    }
797  }
798  
PrintRelocationEntries(const MachOObjectFile * O,const relocation_iterator Begin,const relocation_iterator End,const uint64_t cputype,const bool verbose)799  static void PrintRelocationEntries(const MachOObjectFile *O,
800                                     const relocation_iterator Begin,
801                                     const relocation_iterator End,
802                                     const uint64_t cputype,
803                                     const bool verbose) {
804    const MachO::symtab_command Symtab = O->getSymtabLoadCommand();
805    bool previous_arm_half = false;
806    bool previous_sectdiff = false;
807    uint32_t sectdiff_r_type = 0;
808  
809    for (relocation_iterator Reloc = Begin; Reloc != End; ++Reloc) {
810      const DataRefImpl Rel = Reloc->getRawDataRefImpl();
811      const MachO::any_relocation_info RE = O->getRelocation(Rel);
812      const unsigned r_type = O->getAnyRelocationType(RE);
813      const bool r_scattered = O->isRelocationScattered(RE);
814      const unsigned r_pcrel = O->getAnyRelocationPCRel(RE);
815      const unsigned r_length = O->getAnyRelocationLength(RE);
816      const unsigned r_address = O->getAnyRelocationAddress(RE);
817      const bool r_extern = (r_scattered ? false :
818                             O->getPlainRelocationExternal(RE));
819      const uint32_t r_value = (r_scattered ?
820                                O->getScatteredRelocationValue(RE) : 0);
821      const unsigned r_symbolnum = (r_scattered ? 0 :
822                                    O->getPlainRelocationSymbolNum(RE));
823  
824      if (r_scattered && cputype != MachO::CPU_TYPE_X86_64) {
825        if (verbose) {
826          // scattered: address
827          if ((cputype == MachO::CPU_TYPE_I386 &&
828               r_type == MachO::GENERIC_RELOC_PAIR) ||
829              (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR))
830            outs() << "         ";
831          else
832            outs() << format("%08x ", (unsigned int)r_address);
833  
834          // scattered: pcrel
835          if (r_pcrel)
836            outs() << "True  ";
837          else
838            outs() << "False ";
839  
840          // scattered: length
841          PrintRLength(cputype, r_type, r_length, previous_arm_half);
842  
843          // scattered: extern & type
844          outs() << "n/a    ";
845          PrintRType(cputype, r_type);
846  
847          // scattered: scattered & value
848          outs() << format("True      0x%08x", (unsigned int)r_value);
849          if (previous_sectdiff == false) {
850            if ((cputype == MachO::CPU_TYPE_ARM &&
851                 r_type == MachO::ARM_RELOC_PAIR))
852              outs() << format(" half = 0x%04x ", (unsigned int)r_address);
853          } else if (cputype == MachO::CPU_TYPE_ARM &&
854                     sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF)
855            outs() << format(" other_half = 0x%04x ", (unsigned int)r_address);
856          if ((cputype == MachO::CPU_TYPE_I386 &&
857               (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
858                r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) ||
859              (cputype == MachO::CPU_TYPE_ARM &&
860               (sectdiff_r_type == MachO::ARM_RELOC_SECTDIFF ||
861                sectdiff_r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
862                sectdiff_r_type == MachO::ARM_RELOC_HALF_SECTDIFF))) {
863            previous_sectdiff = true;
864            sectdiff_r_type = r_type;
865          } else {
866            previous_sectdiff = false;
867            sectdiff_r_type = 0;
868          }
869          if (cputype == MachO::CPU_TYPE_ARM &&
870              (r_type == MachO::ARM_RELOC_HALF ||
871               r_type == MachO::ARM_RELOC_HALF_SECTDIFF))
872            previous_arm_half = true;
873          else
874            previous_arm_half = false;
875          outs() << "\n";
876        }
877        else {
878          // scattered: address pcrel length extern type scattered value
879          outs() << format("%08x %1d     %-2d     n/a    %-7d 1         0x%08x\n",
880                           (unsigned int)r_address, r_pcrel, r_length, r_type,
881                           (unsigned int)r_value);
882        }
883      }
884      else {
885        if (verbose) {
886          // plain: address
887          if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)
888            outs() << "         ";
889          else
890            outs() << format("%08x ", (unsigned int)r_address);
891  
892          // plain: pcrel
893          if (r_pcrel)
894            outs() << "True  ";
895          else
896            outs() << "False ";
897  
898          // plain: length
899          PrintRLength(cputype, r_type, r_length, previous_arm_half);
900  
901          if (r_extern) {
902            // plain: extern & type & scattered
903            outs() << "True   ";
904            PrintRType(cputype, r_type);
905            outs() << "False     ";
906  
907            // plain: symbolnum/value
908            if (r_symbolnum > Symtab.nsyms)
909              outs() << format("?(%d)\n", r_symbolnum);
910            else {
911              SymbolRef Symbol = *O->getSymbolByIndex(r_symbolnum);
912              Expected<StringRef> SymNameNext = Symbol.getName();
913              const char *name = nullptr;
914              if (SymNameNext)
915                name = SymNameNext->data();
916              if (name == nullptr)
917                outs() << format("?(%d)\n", r_symbolnum);
918              else
919                outs() << name << "\n";
920            }
921          }
922          else {
923            // plain: extern & type & scattered
924            outs() << "False  ";
925            PrintRType(cputype, r_type);
926            outs() << "False     ";
927  
928            // plain: symbolnum/value
929            if (cputype == MachO::CPU_TYPE_ARM && r_type == MachO::ARM_RELOC_PAIR)
930              outs() << format("other_half = 0x%04x\n", (unsigned int)r_address);
931            else if ((cputype == MachO::CPU_TYPE_ARM64 ||
932                      cputype == MachO::CPU_TYPE_ARM64_32) &&
933                     r_type == MachO::ARM64_RELOC_ADDEND)
934              outs() << format("addend = 0x%06x\n", (unsigned int)r_symbolnum);
935            else {
936              outs() << format("%d ", r_symbolnum);
937              if (r_symbolnum == MachO::R_ABS)
938                outs() << "R_ABS\n";
939              else {
940                // in this case, r_symbolnum is actually a 1-based section number
941                uint32_t nsects = O->section_end()->getRawDataRefImpl().d.a;
942                if (r_symbolnum > 0 && r_symbolnum <= nsects) {
943                  object::DataRefImpl DRI;
944                  DRI.d.a = r_symbolnum-1;
945                  StringRef SegName = O->getSectionFinalSegmentName(DRI);
946                  if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
947                    outs() << "(" << SegName << "," << *NameOrErr << ")\n";
948                  else
949                    outs() << "(?,?)\n";
950                }
951                else {
952                  outs() << "(?,?)\n";
953                }
954              }
955            }
956          }
957          if (cputype == MachO::CPU_TYPE_ARM &&
958              (r_type == MachO::ARM_RELOC_HALF ||
959               r_type == MachO::ARM_RELOC_HALF_SECTDIFF))
960            previous_arm_half = true;
961          else
962            previous_arm_half = false;
963        }
964        else {
965          // plain: address pcrel length extern type scattered symbolnum/section
966          outs() << format("%08x %1d     %-2d     %1d      %-7d 0         %d\n",
967                           (unsigned int)r_address, r_pcrel, r_length, r_extern,
968                           r_type, r_symbolnum);
969        }
970      }
971    }
972  }
973  
PrintRelocations(const MachOObjectFile * O,const bool verbose)974  static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
975    const uint64_t cputype = O->getHeader().cputype;
976    const MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
977    if (Dysymtab.nextrel != 0) {
978      outs() << "External relocation information " << Dysymtab.nextrel
979             << " entries";
980      outs() << "\naddress  pcrel length extern type    scattered "
981                "symbolnum/value\n";
982      PrintRelocationEntries(O, O->extrel_begin(), O->extrel_end(), cputype,
983                             verbose);
984    }
985    if (Dysymtab.nlocrel != 0) {
986      outs() << format("Local relocation information %u entries",
987                       Dysymtab.nlocrel);
988      outs() << "\naddress  pcrel length extern type    scattered "
989                "symbolnum/value\n";
990      PrintRelocationEntries(O, O->locrel_begin(), O->locrel_end(), cputype,
991                             verbose);
992    }
993    for (const auto &Load : O->load_commands()) {
994      if (Load.C.cmd == MachO::LC_SEGMENT_64) {
995        const MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
996        for (unsigned J = 0; J < Seg.nsects; ++J) {
997          const MachO::section_64 Sec = O->getSection64(Load, J);
998          if (Sec.nreloc != 0) {
999            DataRefImpl DRI;
1000            DRI.d.a = J;
1001            const StringRef SegName = O->getSectionFinalSegmentName(DRI);
1002            if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
1003              outs() << "Relocation information (" << SegName << "," << *NameOrErr
1004                     << format(") %u entries", Sec.nreloc);
1005            else
1006              outs() << "Relocation information (" << SegName << ",?) "
1007                     << format("%u entries", Sec.nreloc);
1008            outs() << "\naddress  pcrel length extern type    scattered "
1009                      "symbolnum/value\n";
1010            PrintRelocationEntries(O, O->section_rel_begin(DRI),
1011                                   O->section_rel_end(DRI), cputype, verbose);
1012          }
1013        }
1014      } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1015        const MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
1016        for (unsigned J = 0; J < Seg.nsects; ++J) {
1017          const MachO::section Sec = O->getSection(Load, J);
1018          if (Sec.nreloc != 0) {
1019            DataRefImpl DRI;
1020            DRI.d.a = J;
1021            const StringRef SegName = O->getSectionFinalSegmentName(DRI);
1022            if (Expected<StringRef> NameOrErr = O->getSectionName(DRI))
1023              outs() << "Relocation information (" << SegName << "," << *NameOrErr
1024                     << format(") %u entries", Sec.nreloc);
1025            else
1026              outs() << "Relocation information (" << SegName << ",?) "
1027                     << format("%u entries", Sec.nreloc);
1028            outs() << "\naddress  pcrel length extern type    scattered "
1029                      "symbolnum/value\n";
1030            PrintRelocationEntries(O, O->section_rel_begin(DRI),
1031                                   O->section_rel_end(DRI), cputype, verbose);
1032          }
1033        }
1034      }
1035    }
1036  }
1037  
PrintFunctionStarts(MachOObjectFile * O)1038  static void PrintFunctionStarts(MachOObjectFile *O) {
1039    uint64_t BaseSegmentAddress = 0;
1040    for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
1041      if (Command.C.cmd == MachO::LC_SEGMENT) {
1042        MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
1043        if (StringRef(SLC.segname) == "__TEXT") {
1044          BaseSegmentAddress = SLC.vmaddr;
1045          break;
1046        }
1047      } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1048        MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
1049        if (StringRef(SLC.segname) == "__TEXT") {
1050          BaseSegmentAddress = SLC.vmaddr;
1051          break;
1052        }
1053      }
1054    }
1055  
1056    SmallVector<uint64_t, 8> FunctionStarts;
1057    for (const MachOObjectFile::LoadCommandInfo &LC : O->load_commands()) {
1058      if (LC.C.cmd == MachO::LC_FUNCTION_STARTS) {
1059        MachO::linkedit_data_command FunctionStartsLC =
1060            O->getLinkeditDataLoadCommand(LC);
1061        O->ReadULEB128s(FunctionStartsLC.dataoff, FunctionStarts);
1062        break;
1063      }
1064    }
1065  
1066    DenseMap<uint64_t, StringRef> SymbolNames;
1067    if (FunctionStartsType == FunctionStartsMode::Names ||
1068        FunctionStartsType == FunctionStartsMode::Both) {
1069      for (SymbolRef Sym : O->symbols()) {
1070        if (Expected<uint64_t> Addr = Sym.getAddress()) {
1071          if (Expected<StringRef> Name = Sym.getName()) {
1072            SymbolNames[*Addr] = *Name;
1073          }
1074        }
1075      }
1076    }
1077  
1078    for (uint64_t S : FunctionStarts) {
1079      uint64_t Addr = BaseSegmentAddress + S;
1080      if (FunctionStartsType == FunctionStartsMode::Names) {
1081        auto It = SymbolNames.find(Addr);
1082        if (It != SymbolNames.end())
1083          outs() << It->second << "\n";
1084      } else {
1085        if (O->is64Bit())
1086          outs() << format("%016" PRIx64, Addr);
1087        else
1088          outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr));
1089  
1090        if (FunctionStartsType == FunctionStartsMode::Both) {
1091          auto It = SymbolNames.find(Addr);
1092          if (It != SymbolNames.end())
1093            outs() << " " << It->second;
1094          else
1095            outs() << " ?";
1096        }
1097        outs() << "\n";
1098      }
1099    }
1100  }
1101  
PrintDataInCodeTable(MachOObjectFile * O,bool verbose)1102  static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
1103    MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
1104    uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
1105    outs() << "Data in code table (" << nentries << " entries)\n";
1106    outs() << "offset     length kind\n";
1107    for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
1108         ++DI) {
1109      uint32_t Offset;
1110      DI->getOffset(Offset);
1111      outs() << format("0x%08" PRIx32, Offset) << " ";
1112      uint16_t Length;
1113      DI->getLength(Length);
1114      outs() << format("%6u", Length) << " ";
1115      uint16_t Kind;
1116      DI->getKind(Kind);
1117      if (verbose) {
1118        switch (Kind) {
1119        case MachO::DICE_KIND_DATA:
1120          outs() << "DATA";
1121          break;
1122        case MachO::DICE_KIND_JUMP_TABLE8:
1123          outs() << "JUMP_TABLE8";
1124          break;
1125        case MachO::DICE_KIND_JUMP_TABLE16:
1126          outs() << "JUMP_TABLE16";
1127          break;
1128        case MachO::DICE_KIND_JUMP_TABLE32:
1129          outs() << "JUMP_TABLE32";
1130          break;
1131        case MachO::DICE_KIND_ABS_JUMP_TABLE32:
1132          outs() << "ABS_JUMP_TABLE32";
1133          break;
1134        default:
1135          outs() << format("0x%04" PRIx32, Kind);
1136          break;
1137        }
1138      } else
1139        outs() << format("0x%04" PRIx32, Kind);
1140      outs() << "\n";
1141    }
1142  }
1143  
PrintLinkOptHints(MachOObjectFile * O)1144  static void PrintLinkOptHints(MachOObjectFile *O) {
1145    MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
1146    const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
1147    uint32_t nloh = LohLC.datasize;
1148    outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
1149    for (uint32_t i = 0; i < nloh;) {
1150      unsigned n;
1151      uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
1152      i += n;
1153      outs() << "    identifier " << identifier << " ";
1154      if (i >= nloh)
1155        return;
1156      switch (identifier) {
1157      case 1:
1158        outs() << "AdrpAdrp\n";
1159        break;
1160      case 2:
1161        outs() << "AdrpLdr\n";
1162        break;
1163      case 3:
1164        outs() << "AdrpAddLdr\n";
1165        break;
1166      case 4:
1167        outs() << "AdrpLdrGotLdr\n";
1168        break;
1169      case 5:
1170        outs() << "AdrpAddStr\n";
1171        break;
1172      case 6:
1173        outs() << "AdrpLdrGotStr\n";
1174        break;
1175      case 7:
1176        outs() << "AdrpAdd\n";
1177        break;
1178      case 8:
1179        outs() << "AdrpLdrGot\n";
1180        break;
1181      default:
1182        outs() << "Unknown identifier value\n";
1183        break;
1184      }
1185      uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
1186      i += n;
1187      outs() << "    narguments " << narguments << "\n";
1188      if (i >= nloh)
1189        return;
1190  
1191      for (uint32_t j = 0; j < narguments; j++) {
1192        uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
1193        i += n;
1194        outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
1195        if (i >= nloh)
1196          return;
1197      }
1198    }
1199  }
1200  
GetSegmentNames(object::MachOObjectFile * O)1201  static SmallVector<std::string> GetSegmentNames(object::MachOObjectFile *O) {
1202    SmallVector<std::string> Ret;
1203    for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
1204      if (Command.C.cmd == MachO::LC_SEGMENT) {
1205        MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
1206        Ret.push_back(SLC.segname);
1207      } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1208        MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
1209        Ret.push_back(SLC.segname);
1210      }
1211    }
1212    return Ret;
1213  }
1214  
1215  static void
PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header & H)1216  PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) {
1217    outs() << "chained fixups header (LC_DYLD_CHAINED_FIXUPS)\n";
1218    outs() << "  fixups_version = " << H.fixups_version << '\n';
1219    outs() << "  starts_offset  = " << H.starts_offset << '\n';
1220    outs() << "  imports_offset = " << H.imports_offset << '\n';
1221    outs() << "  symbols_offset = " << H.symbols_offset << '\n';
1222    outs() << "  imports_count  = " << H.imports_count << '\n';
1223  
1224    outs() << "  imports_format = " << H.imports_format;
1225    switch (H.imports_format) {
1226    case llvm::MachO::DYLD_CHAINED_IMPORT:
1227      outs() << " (DYLD_CHAINED_IMPORT)";
1228      break;
1229    case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND:
1230      outs() << " (DYLD_CHAINED_IMPORT_ADDEND)";
1231      break;
1232    case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND64:
1233      outs() << " (DYLD_CHAINED_IMPORT_ADDEND64)";
1234      break;
1235    }
1236    outs() << '\n';
1237  
1238    outs() << "  symbols_format = " << H.symbols_format;
1239    if (H.symbols_format == llvm::MachO::DYLD_CHAINED_SYMBOL_ZLIB)
1240      outs() << " (zlib compressed)";
1241    outs() << '\n';
1242  }
1243  
1244  static constexpr std::array<StringRef, 13> PointerFormats{
1245      "DYLD_CHAINED_PTR_ARM64E",
1246      "DYLD_CHAINED_PTR_64",
1247      "DYLD_CHAINED_PTR_32",
1248      "DYLD_CHAINED_PTR_32_CACHE",
1249      "DYLD_CHAINED_PTR_32_FIRMWARE",
1250      "DYLD_CHAINED_PTR_64_OFFSET",
1251      "DYLD_CHAINED_PTR_ARM64E_KERNEL",
1252      "DYLD_CHAINED_PTR_64_KERNEL_CACHE",
1253      "DYLD_CHAINED_PTR_ARM64E_USERLAND",
1254      "DYLD_CHAINED_PTR_ARM64E_FIRMWARE",
1255      "DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE",
1256      "DYLD_CHAINED_PTR_ARM64E_USERLAND24",
1257  };
1258  
PrintChainedFixupsSegment(const ChainedFixupsSegment & Segment,StringRef SegName)1259  static void PrintChainedFixupsSegment(const ChainedFixupsSegment &Segment,
1260                                        StringRef SegName) {
1261    outs() << "chained starts in segment " << Segment.SegIdx << " (" << SegName
1262           << ")\n";
1263    outs() << "  size = " << Segment.Header.size << '\n';
1264    outs() << "  page_size = " << format("0x%0" PRIx16, Segment.Header.page_size)
1265           << '\n';
1266  
1267    outs() << "  pointer_format = " << Segment.Header.pointer_format;
1268    if ((Segment.Header.pointer_format - 1) <
1269        MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24)
1270      outs() << " (" << PointerFormats[Segment.Header.pointer_format - 1] << ")";
1271    outs() << '\n';
1272  
1273    outs() << "  segment_offset = "
1274           << format("0x%0" PRIx64, Segment.Header.segment_offset) << '\n';
1275    outs() << "  max_valid_pointer = " << Segment.Header.max_valid_pointer
1276           << '\n';
1277    outs() << "  page_count = " << Segment.Header.page_count << '\n';
1278    for (auto [Index, PageStart] : enumerate(Segment.PageStarts)) {
1279      outs() << "    page_start[" << Index << "] = " << PageStart;
1280      // FIXME: Support DYLD_CHAINED_PTR_START_MULTI (32-bit only)
1281      if (PageStart == MachO::DYLD_CHAINED_PTR_START_NONE)
1282        outs() << " (DYLD_CHAINED_PTR_START_NONE)";
1283      outs() << '\n';
1284    }
1285  }
1286  
PrintChainedFixupTarget(ChainedFixupTarget & Target,size_t Idx,int Format,MachOObjectFile * O)1287  static void PrintChainedFixupTarget(ChainedFixupTarget &Target, size_t Idx,
1288                                      int Format, MachOObjectFile *O) {
1289    if (Format == MachO::DYLD_CHAINED_IMPORT)
1290      outs() << "dyld chained import";
1291    else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND)
1292      outs() << "dyld chained import addend";
1293    else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND64)
1294      outs() << "dyld chained import addend64";
1295    // FIXME: otool prints the encoded value as well.
1296    outs() << '[' << Idx << "]\n";
1297  
1298    outs() << "  lib_ordinal = " << Target.libOrdinal() << " ("
1299           << ordinalName(O, Target.libOrdinal()) << ")\n";
1300    outs() << "  weak_import = " << Target.weakImport() << '\n';
1301    outs() << "  name_offset = " << Target.nameOffset() << " ("
1302           << Target.symbolName() << ")\n";
1303    if (Format != MachO::DYLD_CHAINED_IMPORT)
1304      outs() << "  addend      = " << (int64_t)Target.addend() << '\n';
1305  }
1306  
PrintChainedFixups(MachOObjectFile * O)1307  static void PrintChainedFixups(MachOObjectFile *O) {
1308    // MachOObjectFile::getChainedFixupsHeader() reads LC_DYLD_CHAINED_FIXUPS.
1309    // FIXME: Support chained fixups in __TEXT,__chain_starts section too.
1310    auto ChainedFixupHeader =
1311        unwrapOrError(O->getChainedFixupsHeader(), O->getFileName());
1312    if (!ChainedFixupHeader)
1313      return;
1314  
1315    PrintChainedFixupsHeader(*ChainedFixupHeader);
1316  
1317    auto [SegCount, Segments] =
1318        unwrapOrError(O->getChainedFixupsSegments(), O->getFileName());
1319  
1320    auto SegNames = GetSegmentNames(O);
1321  
1322    size_t StartsIdx = 0;
1323    outs() << "chained starts in image\n";
1324    outs() << "  seg_count = " << SegCount << '\n';
1325    for (size_t I = 0; I < SegCount; ++I) {
1326      uint64_t SegOffset = 0;
1327      if (StartsIdx < Segments.size() && I == Segments[StartsIdx].SegIdx) {
1328        SegOffset = Segments[StartsIdx].Offset;
1329        ++StartsIdx;
1330      }
1331  
1332      outs() << "    seg_offset[" << I << "] = " << SegOffset << " ("
1333             << SegNames[I] << ")\n";
1334    }
1335  
1336    for (const ChainedFixupsSegment &S : Segments)
1337      PrintChainedFixupsSegment(S, SegNames[S.SegIdx]);
1338  
1339    auto FixupTargets =
1340        unwrapOrError(O->getDyldChainedFixupTargets(), O->getFileName());
1341  
1342    uint32_t ImportsFormat = ChainedFixupHeader->imports_format;
1343    for (auto [Idx, Target] : enumerate(FixupTargets))
1344      PrintChainedFixupTarget(Target, Idx, ImportsFormat, O);
1345  }
1346  
PrintDyldInfo(MachOObjectFile * O)1347  static void PrintDyldInfo(MachOObjectFile *O) {
1348    Error Err = Error::success();
1349  
1350    size_t SegmentWidth = strlen("segment");
1351    size_t SectionWidth = strlen("section");
1352    size_t AddressWidth = strlen("address");
1353    size_t AddendWidth = strlen("addend");
1354    size_t DylibWidth = strlen("dylib");
1355    const size_t PointerWidth = 2 + O->getBytesInAddress() * 2;
1356  
1357    auto HexLength = [](uint64_t Num) {
1358      return Num ? (size_t)divideCeil(Log2_64(Num), 4) : 1;
1359    };
1360    for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
1361      SegmentWidth = std::max(SegmentWidth, Entry.segmentName().size());
1362      SectionWidth = std::max(SectionWidth, Entry.sectionName().size());
1363      AddressWidth = std::max(AddressWidth, HexLength(Entry.address()) + 2);
1364      if (Entry.isBind()) {
1365        AddendWidth = std::max(AddendWidth, HexLength(Entry.addend()) + 2);
1366        DylibWidth = std::max(DylibWidth, Entry.symbolName().size());
1367      }
1368    }
1369    // Errors will be handled when printing the table.
1370    if (Err)
1371      consumeError(std::move(Err));
1372  
1373    outs() << "dyld information:\n";
1374    outs() << left_justify("segment", SegmentWidth) << ' '
1375           << left_justify("section", SectionWidth) << ' '
1376           << left_justify("address", AddressWidth) << ' '
1377           << left_justify("pointer", PointerWidth) << " type   "
1378           << left_justify("addend", AddendWidth) << ' '
1379           << left_justify("dylib", DylibWidth) << " symbol/vm address\n";
1380    for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
1381      outs() << left_justify(Entry.segmentName(), SegmentWidth) << ' '
1382             << left_justify(Entry.sectionName(), SectionWidth) << ' ' << "0x"
1383             << left_justify(utohexstr(Entry.address()), AddressWidth - 2) << ' '
1384             << format_hex(Entry.rawValue(), PointerWidth, true) << ' ';
1385      if (Entry.isBind()) {
1386        outs() << "bind   "
1387               << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2)
1388               << ' ' << left_justify(ordinalName(O, Entry.ordinal()), DylibWidth)
1389               << ' ' << Entry.symbolName();
1390        if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
1391          outs() << " (weak import)";
1392        outs() << '\n';
1393      } else {
1394        assert(Entry.isRebase());
1395        outs() << "rebase";
1396        outs().indent(AddendWidth + DylibWidth + 2);
1397        outs() << format("0x%" PRIX64, Entry.pointerValue()) << '\n';
1398      }
1399    }
1400    if (Err)
1401      reportError(std::move(Err), O->getFileName());
1402  
1403    // TODO: Print opcode-based fixups if the object uses those.
1404  }
1405  
PrintDylibs(MachOObjectFile * O,bool JustId)1406  static void PrintDylibs(MachOObjectFile *O, bool JustId) {
1407    unsigned Index = 0;
1408    for (const auto &Load : O->load_commands()) {
1409      if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
1410          (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
1411                       Load.C.cmd == MachO::LC_LOAD_DYLIB ||
1412                       Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
1413                       Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
1414                       Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
1415                       Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
1416        MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
1417        if (dl.dylib.name < dl.cmdsize) {
1418          const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
1419          if (JustId)
1420            outs() << p << "\n";
1421          else {
1422            outs() << "\t" << p;
1423            outs() << " (compatibility version "
1424                   << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
1425                   << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
1426                   << (dl.dylib.compatibility_version & 0xff) << ",";
1427            outs() << " current version "
1428                   << ((dl.dylib.current_version >> 16) & 0xffff) << "."
1429                   << ((dl.dylib.current_version >> 8) & 0xff) << "."
1430                   << (dl.dylib.current_version & 0xff);
1431            if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
1432              outs() << ", weak";
1433            if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
1434              outs() << ", reexport";
1435            if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
1436              outs() << ", upward";
1437            if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
1438              outs() << ", lazy";
1439            outs() << ")\n";
1440          }
1441        } else {
1442          outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
1443          if (Load.C.cmd == MachO::LC_ID_DYLIB)
1444            outs() << "LC_ID_DYLIB ";
1445          else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
1446            outs() << "LC_LOAD_DYLIB ";
1447          else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
1448            outs() << "LC_LOAD_WEAK_DYLIB ";
1449          else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
1450            outs() << "LC_LAZY_LOAD_DYLIB ";
1451          else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
1452            outs() << "LC_REEXPORT_DYLIB ";
1453          else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
1454            outs() << "LC_LOAD_UPWARD_DYLIB ";
1455          else
1456            outs() << "LC_??? ";
1457          outs() << "command " << Index++ << "\n";
1458        }
1459      }
1460    }
1461  }
1462  
printRpaths(MachOObjectFile * O)1463  static void printRpaths(MachOObjectFile *O) {
1464    for (const auto &Command : O->load_commands()) {
1465      if (Command.C.cmd == MachO::LC_RPATH) {
1466        auto Rpath = O->getRpathCommand(Command);
1467        const char *P = (const char *)(Command.Ptr) + Rpath.path;
1468        outs() << P << "\n";
1469      }
1470    }
1471  }
1472  
1473  typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
1474  
CreateSymbolAddressMap(MachOObjectFile * O,SymbolAddressMap * AddrMap)1475  static void CreateSymbolAddressMap(MachOObjectFile *O,
1476                                     SymbolAddressMap *AddrMap) {
1477    // Create a map of symbol addresses to symbol names.
1478    const StringRef FileName = O->getFileName();
1479    for (const SymbolRef &Symbol : O->symbols()) {
1480      SymbolRef::Type ST = unwrapOrError(Symbol.getType(), FileName);
1481      if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
1482          ST == SymbolRef::ST_Other) {
1483        uint64_t Address = cantFail(Symbol.getValue());
1484        StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
1485        if (!SymName.starts_with(".objc"))
1486          (*AddrMap)[Address] = SymName;
1487      }
1488    }
1489  }
1490  
1491  // GuessSymbolName is passed the address of what might be a symbol and a
1492  // pointer to the SymbolAddressMap.  It returns the name of a symbol
1493  // with that address or nullptr if no symbol is found with that address.
GuessSymbolName(uint64_t value,SymbolAddressMap * AddrMap)1494  static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
1495    const char *SymbolName = nullptr;
1496    // A DenseMap can't lookup up some values.
1497    if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
1498      StringRef name = AddrMap->lookup(value);
1499      if (!name.empty())
1500        SymbolName = name.data();
1501    }
1502    return SymbolName;
1503  }
1504  
DumpCstringChar(const char c)1505  static void DumpCstringChar(const char c) {
1506    char p[2];
1507    p[0] = c;
1508    p[1] = '\0';
1509    outs().write_escaped(p);
1510  }
1511  
DumpCstringSection(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1512  static void DumpCstringSection(MachOObjectFile *O, const char *sect,
1513                                 uint32_t sect_size, uint64_t sect_addr,
1514                                 bool print_addresses) {
1515    for (uint32_t i = 0; i < sect_size; i++) {
1516      if (print_addresses) {
1517        if (O->is64Bit())
1518          outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1519        else
1520          outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1521      }
1522      for (; i < sect_size && sect[i] != '\0'; i++)
1523        DumpCstringChar(sect[i]);
1524      if (i < sect_size && sect[i] == '\0')
1525        outs() << "\n";
1526    }
1527  }
1528  
DumpLiteral4(uint32_t l,float f)1529  static void DumpLiteral4(uint32_t l, float f) {
1530    outs() << format("0x%08" PRIx32, l);
1531    if ((l & 0x7f800000) != 0x7f800000)
1532      outs() << format(" (%.16e)\n", f);
1533    else {
1534      if (l == 0x7f800000)
1535        outs() << " (+Infinity)\n";
1536      else if (l == 0xff800000)
1537        outs() << " (-Infinity)\n";
1538      else if ((l & 0x00400000) == 0x00400000)
1539        outs() << " (non-signaling Not-a-Number)\n";
1540      else
1541        outs() << " (signaling Not-a-Number)\n";
1542    }
1543  }
1544  
DumpLiteral4Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1545  static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
1546                                  uint32_t sect_size, uint64_t sect_addr,
1547                                  bool print_addresses) {
1548    for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
1549      if (print_addresses) {
1550        if (O->is64Bit())
1551          outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1552        else
1553          outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1554      }
1555      float f;
1556      memcpy(&f, sect + i, sizeof(float));
1557      if (O->isLittleEndian() != sys::IsLittleEndianHost)
1558        sys::swapByteOrder(f);
1559      uint32_t l;
1560      memcpy(&l, sect + i, sizeof(uint32_t));
1561      if (O->isLittleEndian() != sys::IsLittleEndianHost)
1562        sys::swapByteOrder(l);
1563      DumpLiteral4(l, f);
1564    }
1565  }
1566  
DumpLiteral8(MachOObjectFile * O,uint32_t l0,uint32_t l1,double d)1567  static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
1568                           double d) {
1569    outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
1570    uint32_t Hi, Lo;
1571    Hi = (O->isLittleEndian()) ? l1 : l0;
1572    Lo = (O->isLittleEndian()) ? l0 : l1;
1573  
1574    // Hi is the high word, so this is equivalent to if(isfinite(d))
1575    if ((Hi & 0x7ff00000) != 0x7ff00000)
1576      outs() << format(" (%.16e)\n", d);
1577    else {
1578      if (Hi == 0x7ff00000 && Lo == 0)
1579        outs() << " (+Infinity)\n";
1580      else if (Hi == 0xfff00000 && Lo == 0)
1581        outs() << " (-Infinity)\n";
1582      else if ((Hi & 0x00080000) == 0x00080000)
1583        outs() << " (non-signaling Not-a-Number)\n";
1584      else
1585        outs() << " (signaling Not-a-Number)\n";
1586    }
1587  }
1588  
DumpLiteral8Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1589  static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
1590                                  uint32_t sect_size, uint64_t sect_addr,
1591                                  bool print_addresses) {
1592    for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
1593      if (print_addresses) {
1594        if (O->is64Bit())
1595          outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1596        else
1597          outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1598      }
1599      double d;
1600      memcpy(&d, sect + i, sizeof(double));
1601      if (O->isLittleEndian() != sys::IsLittleEndianHost)
1602        sys::swapByteOrder(d);
1603      uint32_t l0, l1;
1604      memcpy(&l0, sect + i, sizeof(uint32_t));
1605      memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1606      if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1607        sys::swapByteOrder(l0);
1608        sys::swapByteOrder(l1);
1609      }
1610      DumpLiteral8(O, l0, l1, d);
1611    }
1612  }
1613  
DumpLiteral16(uint32_t l0,uint32_t l1,uint32_t l2,uint32_t l3)1614  static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
1615    outs() << format("0x%08" PRIx32, l0) << " ";
1616    outs() << format("0x%08" PRIx32, l1) << " ";
1617    outs() << format("0x%08" PRIx32, l2) << " ";
1618    outs() << format("0x%08" PRIx32, l3) << "\n";
1619  }
1620  
DumpLiteral16Section(MachOObjectFile * O,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1621  static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
1622                                   uint32_t sect_size, uint64_t sect_addr,
1623                                   bool print_addresses) {
1624    for (uint32_t i = 0; i < sect_size; i += 16) {
1625      if (print_addresses) {
1626        if (O->is64Bit())
1627          outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1628        else
1629          outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1630      }
1631      uint32_t l0, l1, l2, l3;
1632      memcpy(&l0, sect + i, sizeof(uint32_t));
1633      memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
1634      memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
1635      memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
1636      if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1637        sys::swapByteOrder(l0);
1638        sys::swapByteOrder(l1);
1639        sys::swapByteOrder(l2);
1640        sys::swapByteOrder(l3);
1641      }
1642      DumpLiteral16(l0, l1, l2, l3);
1643    }
1644  }
1645  
DumpLiteralPointerSection(MachOObjectFile * O,const SectionRef & Section,const char * sect,uint32_t sect_size,uint64_t sect_addr,bool print_addresses)1646  static void DumpLiteralPointerSection(MachOObjectFile *O,
1647                                        const SectionRef &Section,
1648                                        const char *sect, uint32_t sect_size,
1649                                        uint64_t sect_addr,
1650                                        bool print_addresses) {
1651    // Collect the literal sections in this Mach-O file.
1652    std::vector<SectionRef> LiteralSections;
1653    for (const SectionRef &Section : O->sections()) {
1654      DataRefImpl Ref = Section.getRawDataRefImpl();
1655      uint32_t section_type;
1656      if (O->is64Bit()) {
1657        const MachO::section_64 Sec = O->getSection64(Ref);
1658        section_type = Sec.flags & MachO::SECTION_TYPE;
1659      } else {
1660        const MachO::section Sec = O->getSection(Ref);
1661        section_type = Sec.flags & MachO::SECTION_TYPE;
1662      }
1663      if (section_type == MachO::S_CSTRING_LITERALS ||
1664          section_type == MachO::S_4BYTE_LITERALS ||
1665          section_type == MachO::S_8BYTE_LITERALS ||
1666          section_type == MachO::S_16BYTE_LITERALS)
1667        LiteralSections.push_back(Section);
1668    }
1669  
1670    // Set the size of the literal pointer.
1671    uint32_t lp_size = O->is64Bit() ? 8 : 4;
1672  
1673    // Collect the external relocation symbols for the literal pointers.
1674    std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1675    for (const RelocationRef &Reloc : Section.relocations()) {
1676      DataRefImpl Rel;
1677      MachO::any_relocation_info RE;
1678      bool isExtern = false;
1679      Rel = Reloc.getRawDataRefImpl();
1680      RE = O->getRelocation(Rel);
1681      isExtern = O->getPlainRelocationExternal(RE);
1682      if (isExtern) {
1683        uint64_t RelocOffset = Reloc.getOffset();
1684        symbol_iterator RelocSym = Reloc.getSymbol();
1685        Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1686      }
1687    }
1688    array_pod_sort(Relocs.begin(), Relocs.end());
1689  
1690    // Dump each literal pointer.
1691    for (uint32_t i = 0; i < sect_size; i += lp_size) {
1692      if (print_addresses) {
1693        if (O->is64Bit())
1694          outs() << format("%016" PRIx64, sect_addr + i) << "  ";
1695        else
1696          outs() << format("%08" PRIx64, sect_addr + i) << "  ";
1697      }
1698      uint64_t lp;
1699      if (O->is64Bit()) {
1700        memcpy(&lp, sect + i, sizeof(uint64_t));
1701        if (O->isLittleEndian() != sys::IsLittleEndianHost)
1702          sys::swapByteOrder(lp);
1703      } else {
1704        uint32_t li;
1705        memcpy(&li, sect + i, sizeof(uint32_t));
1706        if (O->isLittleEndian() != sys::IsLittleEndianHost)
1707          sys::swapByteOrder(li);
1708        lp = li;
1709      }
1710  
1711      // First look for an external relocation entry for this literal pointer.
1712      auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1713        return P.first == i;
1714      });
1715      if (Reloc != Relocs.end()) {
1716        symbol_iterator RelocSym = Reloc->second;
1717        StringRef SymName = unwrapOrError(RelocSym->getName(), O->getFileName());
1718        outs() << "external relocation entry for symbol:" << SymName << "\n";
1719        continue;
1720      }
1721  
1722      // For local references see what the section the literal pointer points to.
1723      auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
1724        return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
1725      });
1726      if (Sect == LiteralSections.end()) {
1727        outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
1728        continue;
1729      }
1730  
1731      uint64_t SectAddress = Sect->getAddress();
1732      uint64_t SectSize = Sect->getSize();
1733  
1734      StringRef SectName;
1735      Expected<StringRef> SectNameOrErr = Sect->getName();
1736      if (SectNameOrErr)
1737        SectName = *SectNameOrErr;
1738      else
1739        consumeError(SectNameOrErr.takeError());
1740  
1741      DataRefImpl Ref = Sect->getRawDataRefImpl();
1742      StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
1743      outs() << SegmentName << ":" << SectName << ":";
1744  
1745      uint32_t section_type;
1746      if (O->is64Bit()) {
1747        const MachO::section_64 Sec = O->getSection64(Ref);
1748        section_type = Sec.flags & MachO::SECTION_TYPE;
1749      } else {
1750        const MachO::section Sec = O->getSection(Ref);
1751        section_type = Sec.flags & MachO::SECTION_TYPE;
1752      }
1753  
1754      StringRef BytesStr = unwrapOrError(Sect->getContents(), O->getFileName());
1755  
1756      const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
1757  
1758      switch (section_type) {
1759      case MachO::S_CSTRING_LITERALS:
1760        for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
1761             i++) {
1762          DumpCstringChar(Contents[i]);
1763        }
1764        outs() << "\n";
1765        break;
1766      case MachO::S_4BYTE_LITERALS:
1767        float f;
1768        memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
1769        uint32_t l;
1770        memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
1771        if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1772          sys::swapByteOrder(f);
1773          sys::swapByteOrder(l);
1774        }
1775        DumpLiteral4(l, f);
1776        break;
1777      case MachO::S_8BYTE_LITERALS: {
1778        double d;
1779        memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
1780        uint32_t l0, l1;
1781        memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1782        memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1783               sizeof(uint32_t));
1784        if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1785          sys::swapByteOrder(f);
1786          sys::swapByteOrder(l0);
1787          sys::swapByteOrder(l1);
1788        }
1789        DumpLiteral8(O, l0, l1, d);
1790        break;
1791      }
1792      case MachO::S_16BYTE_LITERALS: {
1793        uint32_t l0, l1, l2, l3;
1794        memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
1795        memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
1796               sizeof(uint32_t));
1797        memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
1798               sizeof(uint32_t));
1799        memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
1800               sizeof(uint32_t));
1801        if (O->isLittleEndian() != sys::IsLittleEndianHost) {
1802          sys::swapByteOrder(l0);
1803          sys::swapByteOrder(l1);
1804          sys::swapByteOrder(l2);
1805          sys::swapByteOrder(l3);
1806        }
1807        DumpLiteral16(l0, l1, l2, l3);
1808        break;
1809      }
1810      }
1811    }
1812  }
1813  
DumpInitTermPointerSection(MachOObjectFile * O,const SectionRef & Section,const char * sect,uint32_t sect_size,uint64_t sect_addr,SymbolAddressMap * AddrMap,bool verbose)1814  static void DumpInitTermPointerSection(MachOObjectFile *O,
1815                                         const SectionRef &Section,
1816                                         const char *sect,
1817                                         uint32_t sect_size, uint64_t sect_addr,
1818                                         SymbolAddressMap *AddrMap,
1819                                         bool verbose) {
1820    uint32_t stride;
1821    stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
1822  
1823    // Collect the external relocation symbols for the pointers.
1824    std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
1825    for (const RelocationRef &Reloc : Section.relocations()) {
1826      DataRefImpl Rel;
1827      MachO::any_relocation_info RE;
1828      bool isExtern = false;
1829      Rel = Reloc.getRawDataRefImpl();
1830      RE = O->getRelocation(Rel);
1831      isExtern = O->getPlainRelocationExternal(RE);
1832      if (isExtern) {
1833        uint64_t RelocOffset = Reloc.getOffset();
1834        symbol_iterator RelocSym = Reloc.getSymbol();
1835        Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
1836      }
1837    }
1838    array_pod_sort(Relocs.begin(), Relocs.end());
1839  
1840    for (uint32_t i = 0; i < sect_size; i += stride) {
1841      const char *SymbolName = nullptr;
1842      uint64_t p;
1843      if (O->is64Bit()) {
1844        outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
1845        uint64_t pointer_value;
1846        memcpy(&pointer_value, sect + i, stride);
1847        if (O->isLittleEndian() != sys::IsLittleEndianHost)
1848          sys::swapByteOrder(pointer_value);
1849        outs() << format("0x%016" PRIx64, pointer_value);
1850        p = pointer_value;
1851      } else {
1852        outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
1853        uint32_t pointer_value;
1854        memcpy(&pointer_value, sect + i, stride);
1855        if (O->isLittleEndian() != sys::IsLittleEndianHost)
1856          sys::swapByteOrder(pointer_value);
1857        outs() << format("0x%08" PRIx32, pointer_value);
1858        p = pointer_value;
1859      }
1860      if (verbose) {
1861        // First look for an external relocation entry for this pointer.
1862        auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
1863          return P.first == i;
1864        });
1865        if (Reloc != Relocs.end()) {
1866          symbol_iterator RelocSym = Reloc->second;
1867          outs() << " " << unwrapOrError(RelocSym->getName(), O->getFileName());
1868        } else {
1869          SymbolName = GuessSymbolName(p, AddrMap);
1870          if (SymbolName)
1871            outs() << " " << SymbolName;
1872        }
1873      }
1874      outs() << "\n";
1875    }
1876  }
1877  
DumpRawSectionContents(MachOObjectFile * O,const char * sect,uint32_t size,uint64_t addr)1878  static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
1879                                     uint32_t size, uint64_t addr) {
1880    uint32_t cputype = O->getHeader().cputype;
1881    if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
1882      uint32_t j;
1883      for (uint32_t i = 0; i < size; i += j, addr += j) {
1884        if (O->is64Bit())
1885          outs() << format("%016" PRIx64, addr) << "\t";
1886        else
1887          outs() << format("%08" PRIx64, addr) << "\t";
1888        for (j = 0; j < 16 && i + j < size; j++) {
1889          uint8_t byte_word = *(sect + i + j);
1890          outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1891        }
1892        outs() << "\n";
1893      }
1894    } else {
1895      uint32_t j;
1896      for (uint32_t i = 0; i < size; i += j, addr += j) {
1897        if (O->is64Bit())
1898          outs() << format("%016" PRIx64, addr) << "\t";
1899        else
1900          outs() << format("%08" PRIx64, addr) << "\t";
1901        for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
1902             j += sizeof(int32_t)) {
1903          if (i + j + sizeof(int32_t) <= size) {
1904            uint32_t long_word;
1905            memcpy(&long_word, sect + i + j, sizeof(int32_t));
1906            if (O->isLittleEndian() != sys::IsLittleEndianHost)
1907              sys::swapByteOrder(long_word);
1908            outs() << format("%08" PRIx32, long_word) << " ";
1909          } else {
1910            for (uint32_t k = 0; i + j + k < size; k++) {
1911              uint8_t byte_word = *(sect + i + j + k);
1912              outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
1913            }
1914          }
1915        }
1916        outs() << "\n";
1917      }
1918    }
1919  }
1920  
1921  static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
1922                               StringRef DisSegName, StringRef DisSectName);
1923  static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
1924                                  uint32_t size, uint32_t addr);
DumpSectionContents(StringRef Filename,MachOObjectFile * O,bool verbose)1925  static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
1926                                  bool verbose) {
1927    SymbolAddressMap AddrMap;
1928    if (verbose)
1929      CreateSymbolAddressMap(O, &AddrMap);
1930  
1931    for (unsigned i = 0; i < FilterSections.size(); ++i) {
1932      StringRef DumpSection = FilterSections[i];
1933      std::pair<StringRef, StringRef> DumpSegSectName;
1934      DumpSegSectName = DumpSection.split(',');
1935      StringRef DumpSegName, DumpSectName;
1936      if (!DumpSegSectName.second.empty()) {
1937        DumpSegName = DumpSegSectName.first;
1938        DumpSectName = DumpSegSectName.second;
1939      } else {
1940        DumpSegName = "";
1941        DumpSectName = DumpSegSectName.first;
1942      }
1943      for (const SectionRef &Section : O->sections()) {
1944        StringRef SectName;
1945        Expected<StringRef> SecNameOrErr = Section.getName();
1946        if (SecNameOrErr)
1947          SectName = *SecNameOrErr;
1948        else
1949          consumeError(SecNameOrErr.takeError());
1950  
1951        if (!DumpSection.empty())
1952          FoundSectionSet.insert(DumpSection);
1953  
1954        DataRefImpl Ref = Section.getRawDataRefImpl();
1955        StringRef SegName = O->getSectionFinalSegmentName(Ref);
1956        if ((DumpSegName.empty() || SegName == DumpSegName) &&
1957            (SectName == DumpSectName)) {
1958  
1959          uint32_t section_flags;
1960          if (O->is64Bit()) {
1961            const MachO::section_64 Sec = O->getSection64(Ref);
1962            section_flags = Sec.flags;
1963  
1964          } else {
1965            const MachO::section Sec = O->getSection(Ref);
1966            section_flags = Sec.flags;
1967          }
1968          uint32_t section_type = section_flags & MachO::SECTION_TYPE;
1969  
1970          StringRef BytesStr =
1971              unwrapOrError(Section.getContents(), O->getFileName());
1972          const char *sect = reinterpret_cast<const char *>(BytesStr.data());
1973          uint32_t sect_size = BytesStr.size();
1974          uint64_t sect_addr = Section.getAddress();
1975  
1976          if (LeadingHeaders)
1977            outs() << "Contents of (" << SegName << "," << SectName
1978                   << ") section\n";
1979  
1980          if (verbose) {
1981            if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
1982                (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
1983              DisassembleMachO(Filename, O, SegName, SectName);
1984              continue;
1985            }
1986            if (SegName == "__TEXT" && SectName == "__info_plist") {
1987              outs() << sect;
1988              continue;
1989            }
1990            if (SegName == "__OBJC" && SectName == "__protocol") {
1991              DumpProtocolSection(O, sect, sect_size, sect_addr);
1992              continue;
1993            }
1994            switch (section_type) {
1995            case MachO::S_REGULAR:
1996              DumpRawSectionContents(O, sect, sect_size, sect_addr);
1997              break;
1998            case MachO::S_ZEROFILL:
1999              outs() << "zerofill section and has no contents in the file\n";
2000              break;
2001            case MachO::S_CSTRING_LITERALS:
2002              DumpCstringSection(O, sect, sect_size, sect_addr, LeadingAddr);
2003              break;
2004            case MachO::S_4BYTE_LITERALS:
2005              DumpLiteral4Section(O, sect, sect_size, sect_addr, LeadingAddr);
2006              break;
2007            case MachO::S_8BYTE_LITERALS:
2008              DumpLiteral8Section(O, sect, sect_size, sect_addr, LeadingAddr);
2009              break;
2010            case MachO::S_16BYTE_LITERALS:
2011              DumpLiteral16Section(O, sect, sect_size, sect_addr, LeadingAddr);
2012              break;
2013            case MachO::S_LITERAL_POINTERS:
2014              DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
2015                                        LeadingAddr);
2016              break;
2017            case MachO::S_MOD_INIT_FUNC_POINTERS:
2018            case MachO::S_MOD_TERM_FUNC_POINTERS:
2019              DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr,
2020                                         &AddrMap, verbose);
2021              break;
2022            default:
2023              outs() << "Unknown section type ("
2024                     << format("0x%08" PRIx32, section_type) << ")\n";
2025              DumpRawSectionContents(O, sect, sect_size, sect_addr);
2026              break;
2027            }
2028          } else {
2029            if (section_type == MachO::S_ZEROFILL)
2030              outs() << "zerofill section and has no contents in the file\n";
2031            else
2032              DumpRawSectionContents(O, sect, sect_size, sect_addr);
2033          }
2034        }
2035      }
2036    }
2037  }
2038  
DumpInfoPlistSectionContents(StringRef Filename,MachOObjectFile * O)2039  static void DumpInfoPlistSectionContents(StringRef Filename,
2040                                           MachOObjectFile *O) {
2041    for (const SectionRef &Section : O->sections()) {
2042      StringRef SectName;
2043      Expected<StringRef> SecNameOrErr = Section.getName();
2044      if (SecNameOrErr)
2045        SectName = *SecNameOrErr;
2046      else
2047        consumeError(SecNameOrErr.takeError());
2048  
2049      DataRefImpl Ref = Section.getRawDataRefImpl();
2050      StringRef SegName = O->getSectionFinalSegmentName(Ref);
2051      if (SegName == "__TEXT" && SectName == "__info_plist") {
2052        if (LeadingHeaders)
2053          outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
2054        StringRef BytesStr =
2055            unwrapOrError(Section.getContents(), O->getFileName());
2056        const char *sect = reinterpret_cast<const char *>(BytesStr.data());
2057        outs() << format("%.*s", BytesStr.size(), sect) << "\n";
2058        return;
2059      }
2060    }
2061  }
2062  
2063  // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
2064  // and if it is and there is a list of architecture flags is specified then
2065  // check to make sure this Mach-O file is one of those architectures or all
2066  // architectures were specified.  If not then an error is generated and this
2067  // routine returns false.  Else it returns true.
checkMachOAndArchFlags(ObjectFile * O,StringRef Filename)2068  static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
2069    auto *MachO = dyn_cast<MachOObjectFile>(O);
2070  
2071    if (!MachO || ArchAll || ArchFlags.empty())
2072      return true;
2073  
2074    MachO::mach_header H;
2075    MachO::mach_header_64 H_64;
2076    Triple T;
2077    const char *McpuDefault, *ArchFlag;
2078    if (MachO->is64Bit()) {
2079      H_64 = MachO->MachOObjectFile::getHeader64();
2080      T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
2081                                         &McpuDefault, &ArchFlag);
2082    } else {
2083      H = MachO->MachOObjectFile::getHeader();
2084      T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
2085                                         &McpuDefault, &ArchFlag);
2086    }
2087    const std::string ArchFlagName(ArchFlag);
2088    if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
2089      WithColor::error(errs(), "llvm-objdump")
2090          << Filename << ": no architecture specified.\n";
2091      return false;
2092    }
2093    return true;
2094  }
2095  
2096  static void printObjcMetaData(MachOObjectFile *O, bool verbose);
2097  
2098  // ProcessMachO() is passed a single opened Mach-O file, which may be an
2099  // archive member and or in a slice of a universal file.  It prints the
2100  // the file name and header info and then processes it according to the
2101  // command line options.
ProcessMachO(StringRef Name,MachOObjectFile * MachOOF,StringRef ArchiveMemberName=StringRef (),StringRef ArchitectureName=StringRef ())2102  static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
2103                           StringRef ArchiveMemberName = StringRef(),
2104                           StringRef ArchitectureName = StringRef()) {
2105    std::unique_ptr<Dumper> D = createMachODumper(*MachOOF);
2106  
2107    // If we are doing some processing here on the Mach-O file print the header
2108    // info.  And don't print it otherwise like in the case of printing the
2109    // UniversalHeaders or ArchiveHeaders.
2110    if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
2111        Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
2112        DataInCode || FunctionStartsType != FunctionStartsMode::None ||
2113        LinkOptHints || ChainedFixups || DyldInfo || DylibsUsed || DylibId ||
2114        Rpaths || ObjcMetaData || (!FilterSections.empty())) {
2115      if (LeadingHeaders) {
2116        outs() << Name;
2117        if (!ArchiveMemberName.empty())
2118          outs() << '(' << ArchiveMemberName << ')';
2119        if (!ArchitectureName.empty())
2120          outs() << " (architecture " << ArchitectureName << ")";
2121        outs() << ":\n";
2122      }
2123    }
2124    // To use the report_error() form with an ArchiveName and FileName set
2125    // these up based on what is passed for Name and ArchiveMemberName.
2126    StringRef ArchiveName;
2127    StringRef FileName;
2128    if (!ArchiveMemberName.empty()) {
2129      ArchiveName = Name;
2130      FileName = ArchiveMemberName;
2131    } else {
2132      ArchiveName = StringRef();
2133      FileName = Name;
2134    }
2135  
2136    // If we need the symbol table to do the operation then check it here to
2137    // produce a good error message as to where the Mach-O file comes from in
2138    // the error message.
2139    if (Disassemble || IndirectSymbols || !FilterSections.empty() || UnwindInfo)
2140      if (Error Err = MachOOF->checkSymbolTable())
2141        reportError(std::move(Err), FileName, ArchiveName, ArchitectureName);
2142  
2143    if (DisassembleAll) {
2144      for (const SectionRef &Section : MachOOF->sections()) {
2145        StringRef SectName;
2146        if (Expected<StringRef> NameOrErr = Section.getName())
2147          SectName = *NameOrErr;
2148        else
2149          consumeError(NameOrErr.takeError());
2150  
2151        if (SectName == "__text") {
2152          DataRefImpl Ref = Section.getRawDataRefImpl();
2153          StringRef SegName = MachOOF->getSectionFinalSegmentName(Ref);
2154          DisassembleMachO(FileName, MachOOF, SegName, SectName);
2155        }
2156      }
2157    }
2158    else if (Disassemble) {
2159      if (MachOOF->getHeader().filetype == MachO::MH_KEXT_BUNDLE &&
2160          MachOOF->getHeader().cputype == MachO::CPU_TYPE_ARM64)
2161        DisassembleMachO(FileName, MachOOF, "__TEXT_EXEC", "__text");
2162      else
2163        DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
2164    }
2165    if (IndirectSymbols)
2166      PrintIndirectSymbols(MachOOF, Verbose);
2167    if (DataInCode)
2168      PrintDataInCodeTable(MachOOF, Verbose);
2169    if (FunctionStartsType != FunctionStartsMode::None)
2170      PrintFunctionStarts(MachOOF);
2171    if (LinkOptHints)
2172      PrintLinkOptHints(MachOOF);
2173    if (Relocations)
2174      PrintRelocations(MachOOF, Verbose);
2175    if (SectionHeaders)
2176      printSectionHeaders(*MachOOF);
2177    if (SectionContents)
2178      printSectionContents(MachOOF);
2179    if (!FilterSections.empty())
2180      DumpSectionContents(FileName, MachOOF, Verbose);
2181    if (InfoPlist)
2182      DumpInfoPlistSectionContents(FileName, MachOOF);
2183    if (DyldInfo)
2184      PrintDyldInfo(MachOOF);
2185    if (ChainedFixups)
2186      PrintChainedFixups(MachOOF);
2187    if (DylibsUsed)
2188      PrintDylibs(MachOOF, false);
2189    if (DylibId)
2190      PrintDylibs(MachOOF, true);
2191    if (SymbolTable)
2192      D->printSymbolTable(ArchiveName, ArchitectureName);
2193    if (UnwindInfo)
2194      printMachOUnwindInfo(MachOOF);
2195    if (PrivateHeaders) {
2196      printMachOFileHeader(MachOOF);
2197      printMachOLoadCommands(MachOOF);
2198    }
2199    if (FirstPrivateHeader)
2200      printMachOFileHeader(MachOOF);
2201    if (ObjcMetaData)
2202      printObjcMetaData(MachOOF, Verbose);
2203    if (ExportsTrie)
2204      printExportsTrie(MachOOF);
2205    if (Rebase)
2206      printRebaseTable(MachOOF);
2207    if (Rpaths)
2208      printRpaths(MachOOF);
2209    if (Bind)
2210      printBindTable(MachOOF);
2211    if (LazyBind)
2212      printLazyBindTable(MachOOF);
2213    if (WeakBind)
2214      printWeakBindTable(MachOOF);
2215  
2216    if (DwarfDumpType != DIDT_Null) {
2217      std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF);
2218      // Dump the complete DWARF structure.
2219      DIDumpOptions DumpOpts;
2220      DumpOpts.DumpType = DwarfDumpType;
2221      DICtx->dump(outs(), DumpOpts);
2222    }
2223  }
2224  
2225  // printUnknownCPUType() helps print_fat_headers for unknown CPU's.
printUnknownCPUType(uint32_t cputype,uint32_t cpusubtype)2226  static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
2227    outs() << "    cputype (" << cputype << ")\n";
2228    outs() << "    cpusubtype (" << cpusubtype << ")\n";
2229  }
2230  
2231  // printCPUType() helps print_fat_headers by printing the cputype and
2232  // pusubtype (symbolically for the one's it knows about).
printCPUType(uint32_t cputype,uint32_t cpusubtype)2233  static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
2234    switch (cputype) {
2235    case MachO::CPU_TYPE_I386:
2236      switch (cpusubtype) {
2237      case MachO::CPU_SUBTYPE_I386_ALL:
2238        outs() << "    cputype CPU_TYPE_I386\n";
2239        outs() << "    cpusubtype CPU_SUBTYPE_I386_ALL\n";
2240        break;
2241      default:
2242        printUnknownCPUType(cputype, cpusubtype);
2243        break;
2244      }
2245      break;
2246    case MachO::CPU_TYPE_X86_64:
2247      switch (cpusubtype) {
2248      case MachO::CPU_SUBTYPE_X86_64_ALL:
2249        outs() << "    cputype CPU_TYPE_X86_64\n";
2250        outs() << "    cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
2251        break;
2252      case MachO::CPU_SUBTYPE_X86_64_H:
2253        outs() << "    cputype CPU_TYPE_X86_64\n";
2254        outs() << "    cpusubtype CPU_SUBTYPE_X86_64_H\n";
2255        break;
2256      default:
2257        printUnknownCPUType(cputype, cpusubtype);
2258        break;
2259      }
2260      break;
2261    case MachO::CPU_TYPE_ARM:
2262      switch (cpusubtype) {
2263      case MachO::CPU_SUBTYPE_ARM_ALL:
2264        outs() << "    cputype CPU_TYPE_ARM\n";
2265        outs() << "    cpusubtype CPU_SUBTYPE_ARM_ALL\n";
2266        break;
2267      case MachO::CPU_SUBTYPE_ARM_V4T:
2268        outs() << "    cputype CPU_TYPE_ARM\n";
2269        outs() << "    cpusubtype CPU_SUBTYPE_ARM_V4T\n";
2270        break;
2271      case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2272        outs() << "    cputype CPU_TYPE_ARM\n";
2273        outs() << "    cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
2274        break;
2275      case MachO::CPU_SUBTYPE_ARM_XSCALE:
2276        outs() << "    cputype CPU_TYPE_ARM\n";
2277        outs() << "    cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
2278        break;
2279      case MachO::CPU_SUBTYPE_ARM_V6:
2280        outs() << "    cputype CPU_TYPE_ARM\n";
2281        outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6\n";
2282        break;
2283      case MachO::CPU_SUBTYPE_ARM_V6M:
2284        outs() << "    cputype CPU_TYPE_ARM\n";
2285        outs() << "    cpusubtype CPU_SUBTYPE_ARM_V6M\n";
2286        break;
2287      case MachO::CPU_SUBTYPE_ARM_V7:
2288        outs() << "    cputype CPU_TYPE_ARM\n";
2289        outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7\n";
2290        break;
2291      case MachO::CPU_SUBTYPE_ARM_V7EM:
2292        outs() << "    cputype CPU_TYPE_ARM\n";
2293        outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
2294        break;
2295      case MachO::CPU_SUBTYPE_ARM_V7K:
2296        outs() << "    cputype CPU_TYPE_ARM\n";
2297        outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7K\n";
2298        break;
2299      case MachO::CPU_SUBTYPE_ARM_V7M:
2300        outs() << "    cputype CPU_TYPE_ARM\n";
2301        outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7M\n";
2302        break;
2303      case MachO::CPU_SUBTYPE_ARM_V7S:
2304        outs() << "    cputype CPU_TYPE_ARM\n";
2305        outs() << "    cpusubtype CPU_SUBTYPE_ARM_V7S\n";
2306        break;
2307      default:
2308        printUnknownCPUType(cputype, cpusubtype);
2309        break;
2310      }
2311      break;
2312    case MachO::CPU_TYPE_ARM64:
2313      switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
2314      case MachO::CPU_SUBTYPE_ARM64_ALL:
2315        outs() << "    cputype CPU_TYPE_ARM64\n";
2316        outs() << "    cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
2317        break;
2318      case MachO::CPU_SUBTYPE_ARM64_V8:
2319        outs() << "    cputype CPU_TYPE_ARM64\n";
2320        outs() << "    cpusubtype CPU_SUBTYPE_ARM64_V8\n";
2321        break;
2322      case MachO::CPU_SUBTYPE_ARM64E:
2323        outs() << "    cputype CPU_TYPE_ARM64\n";
2324        outs() << "    cpusubtype CPU_SUBTYPE_ARM64E\n";
2325        break;
2326      default:
2327        printUnknownCPUType(cputype, cpusubtype);
2328        break;
2329      }
2330      break;
2331    case MachO::CPU_TYPE_ARM64_32:
2332      switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
2333      case MachO::CPU_SUBTYPE_ARM64_32_V8:
2334        outs() << "    cputype CPU_TYPE_ARM64_32\n";
2335        outs() << "    cpusubtype CPU_SUBTYPE_ARM64_32_V8\n";
2336        break;
2337      default:
2338        printUnknownCPUType(cputype, cpusubtype);
2339        break;
2340      }
2341      break;
2342    default:
2343      printUnknownCPUType(cputype, cpusubtype);
2344      break;
2345    }
2346  }
2347  
printMachOUniversalHeaders(const object::MachOUniversalBinary * UB,bool verbose)2348  static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
2349                                         bool verbose) {
2350    outs() << "Fat headers\n";
2351    if (verbose) {
2352      if (UB->getMagic() == MachO::FAT_MAGIC)
2353        outs() << "fat_magic FAT_MAGIC\n";
2354      else // UB->getMagic() == MachO::FAT_MAGIC_64
2355        outs() << "fat_magic FAT_MAGIC_64\n";
2356    } else
2357      outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
2358  
2359    uint32_t nfat_arch = UB->getNumberOfObjects();
2360    StringRef Buf = UB->getData();
2361    uint64_t size = Buf.size();
2362    uint64_t big_size = sizeof(struct MachO::fat_header) +
2363                        nfat_arch * sizeof(struct MachO::fat_arch);
2364    outs() << "nfat_arch " << UB->getNumberOfObjects();
2365    if (nfat_arch == 0)
2366      outs() << " (malformed, contains zero architecture types)\n";
2367    else if (big_size > size)
2368      outs() << " (malformed, architectures past end of file)\n";
2369    else
2370      outs() << "\n";
2371  
2372    for (uint32_t i = 0; i < nfat_arch; ++i) {
2373      MachOUniversalBinary::ObjectForArch OFA(UB, i);
2374      uint32_t cputype = OFA.getCPUType();
2375      uint32_t cpusubtype = OFA.getCPUSubType();
2376      outs() << "architecture ";
2377      for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
2378        MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
2379        uint32_t other_cputype = other_OFA.getCPUType();
2380        uint32_t other_cpusubtype = other_OFA.getCPUSubType();
2381        if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
2382            (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
2383                (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
2384          outs() << "(illegal duplicate architecture) ";
2385          break;
2386        }
2387      }
2388      if (verbose) {
2389        outs() << OFA.getArchFlagName() << "\n";
2390        printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
2391      } else {
2392        outs() << i << "\n";
2393        outs() << "    cputype " << cputype << "\n";
2394        outs() << "    cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
2395               << "\n";
2396      }
2397      if (verbose &&
2398          (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
2399        outs() << "    capabilities CPU_SUBTYPE_LIB64\n";
2400      else
2401        outs() << "    capabilities "
2402               << format("0x%" PRIx32,
2403                         (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
2404      outs() << "    offset " << OFA.getOffset();
2405      if (OFA.getOffset() > size)
2406        outs() << " (past end of file)";
2407      if (OFA.getOffset() % (1ull << OFA.getAlign()) != 0)
2408        outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
2409      outs() << "\n";
2410      outs() << "    size " << OFA.getSize();
2411      big_size = OFA.getOffset() + OFA.getSize();
2412      if (big_size > size)
2413        outs() << " (past end of file)";
2414      outs() << "\n";
2415      outs() << "    align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
2416             << ")\n";
2417    }
2418  }
2419  
printArchiveChild(StringRef Filename,const Archive::Child & C,size_t ChildIndex,bool verbose,bool print_offset,StringRef ArchitectureName=StringRef ())2420  static void printArchiveChild(StringRef Filename, const Archive::Child &C,
2421                                size_t ChildIndex, bool verbose,
2422                                bool print_offset,
2423                                StringRef ArchitectureName = StringRef()) {
2424    if (print_offset)
2425      outs() << C.getChildOffset() << "\t";
2426    sys::fs::perms Mode =
2427        unwrapOrError(C.getAccessMode(), getFileNameForError(C, ChildIndex),
2428                      Filename, ArchitectureName);
2429    if (verbose) {
2430      // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
2431      // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
2432      outs() << "-";
2433      outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
2434      outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
2435      outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
2436      outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
2437      outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
2438      outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
2439      outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
2440      outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
2441      outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
2442    } else {
2443      outs() << format("0%o ", Mode);
2444    }
2445  
2446    outs() << format("%3d/%-3d %5" PRId64 " ",
2447                     unwrapOrError(C.getUID(), getFileNameForError(C, ChildIndex),
2448                                   Filename, ArchitectureName),
2449                     unwrapOrError(C.getGID(), getFileNameForError(C, ChildIndex),
2450                                   Filename, ArchitectureName),
2451                     unwrapOrError(C.getRawSize(),
2452                                   getFileNameForError(C, ChildIndex), Filename,
2453                                   ArchitectureName));
2454  
2455    StringRef RawLastModified = C.getRawLastModified();
2456    if (verbose) {
2457      unsigned Seconds;
2458      if (RawLastModified.getAsInteger(10, Seconds))
2459        outs() << "(date: \"" << RawLastModified
2460               << "\" contains non-decimal chars) ";
2461      else {
2462        // Since cime(3) returns a 26 character string of the form:
2463        // "Sun Sep 16 01:03:52 1973\n\0"
2464        // just print 24 characters.
2465        time_t t = Seconds;
2466        outs() << format("%.24s ", ctime(&t));
2467      }
2468    } else {
2469      outs() << RawLastModified << " ";
2470    }
2471  
2472    if (verbose) {
2473      Expected<StringRef> NameOrErr = C.getName();
2474      if (!NameOrErr) {
2475        consumeError(NameOrErr.takeError());
2476        outs() << unwrapOrError(C.getRawName(),
2477                                getFileNameForError(C, ChildIndex), Filename,
2478                                ArchitectureName)
2479               << "\n";
2480      } else {
2481        StringRef Name = NameOrErr.get();
2482        outs() << Name << "\n";
2483      }
2484    } else {
2485      outs() << unwrapOrError(C.getRawName(), getFileNameForError(C, ChildIndex),
2486                              Filename, ArchitectureName)
2487             << "\n";
2488    }
2489  }
2490  
printArchiveHeaders(StringRef Filename,Archive * A,bool verbose,bool print_offset,StringRef ArchitectureName=StringRef ())2491  static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
2492                                  bool print_offset,
2493                                  StringRef ArchitectureName = StringRef()) {
2494    Error Err = Error::success();
2495    size_t I = 0;
2496    for (const auto &C : A->children(Err, false))
2497      printArchiveChild(Filename, C, I++, verbose, print_offset,
2498                        ArchitectureName);
2499  
2500    if (Err)
2501      reportError(std::move(Err), Filename, "", ArchitectureName);
2502  }
2503  
ValidateArchFlags()2504  static bool ValidateArchFlags() {
2505    // Check for -arch all and verifiy the -arch flags are valid.
2506    for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2507      if (ArchFlags[i] == "all") {
2508        ArchAll = true;
2509      } else {
2510        if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
2511          WithColor::error(errs(), "llvm-objdump")
2512              << "unknown architecture named '" + ArchFlags[i] +
2513                     "'for the -arch option\n";
2514          return false;
2515        }
2516      }
2517    }
2518    return true;
2519  }
2520  
2521  // ParseInputMachO() parses the named Mach-O file in Filename and handles the
2522  // -arch flags selecting just those slices as specified by them and also parses
2523  // archive files.  Then for each individual Mach-O file ProcessMachO() is
2524  // called to process the file based on the command line options.
parseInputMachO(StringRef Filename)2525  void objdump::parseInputMachO(StringRef Filename) {
2526    if (!ValidateArchFlags())
2527      return;
2528  
2529    // Attempt to open the binary.
2530    Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
2531    if (!BinaryOrErr) {
2532      if (Error E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError()))
2533        reportError(std::move(E), Filename);
2534      else
2535        outs() << Filename << ": is not an object file\n";
2536      return;
2537    }
2538    Binary &Bin = *BinaryOrErr.get().getBinary();
2539  
2540    if (Archive *A = dyn_cast<Archive>(&Bin)) {
2541      outs() << "Archive : " << Filename << "\n";
2542      if (ArchiveHeaders)
2543        printArchiveHeaders(Filename, A, Verbose, ArchiveMemberOffsets);
2544  
2545      Error Err = Error::success();
2546      unsigned I = -1;
2547      for (auto &C : A->children(Err)) {
2548        ++I;
2549        Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2550        if (!ChildOrErr) {
2551          if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2552            reportError(std::move(E), getFileNameForError(C, I), Filename);
2553          continue;
2554        }
2555        if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2556          if (!checkMachOAndArchFlags(O, Filename))
2557            return;
2558          ProcessMachO(Filename, O, O->getFileName());
2559        }
2560      }
2561      if (Err)
2562        reportError(std::move(Err), Filename);
2563      return;
2564    }
2565    if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
2566      parseInputMachO(UB);
2567      return;
2568    }
2569    if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
2570      if (!checkMachOAndArchFlags(O, Filename))
2571        return;
2572      if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O))
2573        ProcessMachO(Filename, MachOOF);
2574      else
2575        WithColor::error(errs(), "llvm-objdump")
2576            << Filename << "': "
2577            << "object is not a Mach-O file type.\n";
2578      return;
2579    }
2580    llvm_unreachable("Input object can't be invalid at this point");
2581  }
2582  
parseInputMachO(MachOUniversalBinary * UB)2583  void objdump::parseInputMachO(MachOUniversalBinary *UB) {
2584    if (!ValidateArchFlags())
2585      return;
2586  
2587    auto Filename = UB->getFileName();
2588  
2589    if (UniversalHeaders)
2590      printMachOUniversalHeaders(UB, Verbose);
2591  
2592    // If we have a list of architecture flags specified dump only those.
2593    if (!ArchAll && !ArchFlags.empty()) {
2594      // Look for a slice in the universal binary that matches each ArchFlag.
2595      bool ArchFound;
2596      for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2597        ArchFound = false;
2598        for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2599                                                    E = UB->end_objects();
2600              I != E; ++I) {
2601          if (ArchFlags[i] == I->getArchFlagName()) {
2602            ArchFound = true;
2603            Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
2604                I->getAsObjectFile();
2605            std::string ArchitectureName;
2606            if (ArchFlags.size() > 1)
2607              ArchitectureName = I->getArchFlagName();
2608            if (ObjOrErr) {
2609              ObjectFile &O = *ObjOrErr.get();
2610              if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2611                ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2612            } else if (Error E = isNotObjectErrorInvalidFileType(
2613                           ObjOrErr.takeError())) {
2614              reportError(std::move(E), "", Filename, ArchitectureName);
2615              continue;
2616            } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2617                           I->getAsArchive()) {
2618              std::unique_ptr<Archive> &A = *AOrErr;
2619              outs() << "Archive : " << Filename;
2620              if (!ArchitectureName.empty())
2621                outs() << " (architecture " << ArchitectureName << ")";
2622              outs() << "\n";
2623              if (ArchiveHeaders)
2624                printArchiveHeaders(Filename, A.get(), Verbose,
2625                                    ArchiveMemberOffsets, ArchitectureName);
2626              Error Err = Error::success();
2627              unsigned I = -1;
2628              for (auto &C : A->children(Err)) {
2629                ++I;
2630                Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2631                if (!ChildOrErr) {
2632                  if (Error E =
2633                          isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2634                    reportError(std::move(E), getFileNameForError(C, I), Filename,
2635                                ArchitectureName);
2636                  continue;
2637                }
2638                if (MachOObjectFile *O =
2639                        dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2640                  ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
2641              }
2642              if (Err)
2643                reportError(std::move(Err), Filename);
2644            } else {
2645              consumeError(AOrErr.takeError());
2646              reportError(Filename,
2647                          "Mach-O universal file for architecture " +
2648                              StringRef(I->getArchFlagName()) +
2649                              " is not a Mach-O file or an archive file");
2650            }
2651          }
2652        }
2653        if (!ArchFound) {
2654          WithColor::error(errs(), "llvm-objdump")
2655              << "file: " + Filename + " does not contain "
2656              << "architecture: " + ArchFlags[i] + "\n";
2657          return;
2658        }
2659      }
2660      return;
2661    }
2662    // No architecture flags were specified so if this contains a slice that
2663    // matches the host architecture dump only that.
2664    if (!ArchAll) {
2665      for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2666                                                  E = UB->end_objects();
2667            I != E; ++I) {
2668        if (MachOObjectFile::getHostArch().getArchName() ==
2669            I->getArchFlagName()) {
2670          Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2671          std::string ArchiveName;
2672          ArchiveName.clear();
2673          if (ObjOrErr) {
2674            ObjectFile &O = *ObjOrErr.get();
2675            if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
2676              ProcessMachO(Filename, MachOOF);
2677          } else if (Error E =
2678                         isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2679            reportError(std::move(E), Filename);
2680          } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2681                         I->getAsArchive()) {
2682            std::unique_ptr<Archive> &A = *AOrErr;
2683            outs() << "Archive : " << Filename << "\n";
2684            if (ArchiveHeaders)
2685              printArchiveHeaders(Filename, A.get(), Verbose,
2686                                  ArchiveMemberOffsets);
2687            Error Err = Error::success();
2688            unsigned I = -1;
2689            for (auto &C : A->children(Err)) {
2690              ++I;
2691              Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2692              if (!ChildOrErr) {
2693                if (Error E =
2694                        isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2695                  reportError(std::move(E), getFileNameForError(C, I), Filename);
2696                continue;
2697              }
2698              if (MachOObjectFile *O =
2699                      dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
2700                ProcessMachO(Filename, O, O->getFileName());
2701            }
2702            if (Err)
2703              reportError(std::move(Err), Filename);
2704          } else {
2705            consumeError(AOrErr.takeError());
2706            reportError(Filename, "Mach-O universal file for architecture " +
2707                                      StringRef(I->getArchFlagName()) +
2708                                      " is not a Mach-O file or an archive file");
2709          }
2710          return;
2711        }
2712      }
2713    }
2714    // Either all architectures have been specified or none have been specified
2715    // and this does not contain the host architecture so dump all the slices.
2716    bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2717    for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2718                                                E = UB->end_objects();
2719          I != E; ++I) {
2720      Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2721      std::string ArchitectureName;
2722      if (moreThanOneArch)
2723        ArchitectureName = I->getArchFlagName();
2724      if (ObjOrErr) {
2725        ObjectFile &Obj = *ObjOrErr.get();
2726        if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
2727          ProcessMachO(Filename, MachOOF, "", ArchitectureName);
2728      } else if (Error E =
2729                     isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2730        reportError(std::move(E), Filename, "", ArchitectureName);
2731      } else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
2732        std::unique_ptr<Archive> &A = *AOrErr;
2733        outs() << "Archive : " << Filename;
2734        if (!ArchitectureName.empty())
2735          outs() << " (architecture " << ArchitectureName << ")";
2736        outs() << "\n";
2737        if (ArchiveHeaders)
2738          printArchiveHeaders(Filename, A.get(), Verbose, ArchiveMemberOffsets,
2739                              ArchitectureName);
2740        Error Err = Error::success();
2741        unsigned I = -1;
2742        for (auto &C : A->children(Err)) {
2743          ++I;
2744          Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
2745          if (!ChildOrErr) {
2746            if (Error E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2747              reportError(std::move(E), getFileNameForError(C, I), Filename,
2748                          ArchitectureName);
2749            continue;
2750          }
2751          if (MachOObjectFile *O =
2752                  dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
2753            if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
2754              ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
2755                            ArchitectureName);
2756          }
2757        }
2758        if (Err)
2759          reportError(std::move(Err), Filename);
2760      } else {
2761        consumeError(AOrErr.takeError());
2762        reportError(Filename, "Mach-O universal file for architecture " +
2763                                  StringRef(I->getArchFlagName()) +
2764                                  " is not a Mach-O file or an archive file");
2765      }
2766    }
2767  }
2768  
2769  namespace {
2770  // The block of info used by the Symbolizer call backs.
2771  struct DisassembleInfo {
DisassembleInfo__anon061faff00611::DisassembleInfo2772    DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap,
2773                    std::vector<SectionRef> *Sections, bool verbose)
2774      : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}
2775    bool verbose;
2776    MachOObjectFile *O;
2777    SectionRef S;
2778    SymbolAddressMap *AddrMap;
2779    std::vector<SectionRef> *Sections;
2780    const char *class_name = nullptr;
2781    const char *selector_name = nullptr;
2782    std::unique_ptr<char[]> method = nullptr;
2783    char *demangled_name = nullptr;
2784    uint64_t adrp_addr = 0;
2785    uint32_t adrp_inst = 0;
2786    std::unique_ptr<SymbolAddressMap> bindtable;
2787    uint32_t depth = 0;
2788  };
2789  } // namespace
2790  
2791  // SymbolizerGetOpInfo() is the operand information call back function.
2792  // This is called to get the symbolic information for operand(s) of an
2793  // instruction when it is being done.  This routine does this from
2794  // the relocation information, symbol table, etc. That block of information
2795  // is a pointer to the struct DisassembleInfo that was passed when the
2796  // disassembler context was created and passed to back to here when
2797  // called back by the disassembler for instruction operands that could have
2798  // relocation information. The address of the instruction containing operand is
2799  // at the Pc parameter.  The immediate value the operand has is passed in
2800  // op_info->Value and is at Offset past the start of the instruction and has a
2801  // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
2802  // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
2803  // names and addends of the symbolic expression to add for the operand.  The
2804  // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
2805  // information is returned then this function returns 1 else it returns 0.
SymbolizerGetOpInfo(void * DisInfo,uint64_t Pc,uint64_t Offset,uint64_t OpSize,uint64_t InstSize,int TagType,void * TagBuf)2806  static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
2807                                 uint64_t OpSize, uint64_t InstSize, int TagType,
2808                                 void *TagBuf) {
2809    struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
2810    struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
2811    uint64_t value = op_info->Value;
2812  
2813    // Make sure all fields returned are zero if we don't set them.
2814    memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
2815    op_info->Value = value;
2816  
2817    // If the TagType is not the value 1 which it code knows about or if no
2818    // verbose symbolic information is wanted then just return 0, indicating no
2819    // information is being returned.
2820    if (TagType != 1 || !info->verbose)
2821      return 0;
2822  
2823    unsigned int Arch = info->O->getArch();
2824    if (Arch == Triple::x86) {
2825      if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0)
2826        return 0;
2827      if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2828        // TODO:
2829        // Search the external relocation entries of a fully linked image
2830        // (if any) for an entry that matches this segment offset.
2831        // uint32_t seg_offset = (Pc + Offset);
2832        return 0;
2833      }
2834      // In MH_OBJECT filetypes search the section's relocation entries (if any)
2835      // for an entry for this section offset.
2836      uint32_t sect_addr = info->S.getAddress();
2837      uint32_t sect_offset = (Pc + Offset) - sect_addr;
2838      bool reloc_found = false;
2839      DataRefImpl Rel;
2840      MachO::any_relocation_info RE;
2841      bool isExtern = false;
2842      SymbolRef Symbol;
2843      bool r_scattered = false;
2844      uint32_t r_value, pair_r_value, r_type;
2845      for (const RelocationRef &Reloc : info->S.relocations()) {
2846        uint64_t RelocOffset = Reloc.getOffset();
2847        if (RelocOffset == sect_offset) {
2848          Rel = Reloc.getRawDataRefImpl();
2849          RE = info->O->getRelocation(Rel);
2850          r_type = info->O->getAnyRelocationType(RE);
2851          r_scattered = info->O->isRelocationScattered(RE);
2852          if (r_scattered) {
2853            r_value = info->O->getScatteredRelocationValue(RE);
2854            if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2855                r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
2856              DataRefImpl RelNext = Rel;
2857              info->O->moveRelocationNext(RelNext);
2858              MachO::any_relocation_info RENext;
2859              RENext = info->O->getRelocation(RelNext);
2860              if (info->O->isRelocationScattered(RENext))
2861                pair_r_value = info->O->getScatteredRelocationValue(RENext);
2862              else
2863                return 0;
2864            }
2865          } else {
2866            isExtern = info->O->getPlainRelocationExternal(RE);
2867            if (isExtern) {
2868              symbol_iterator RelocSym = Reloc.getSymbol();
2869              Symbol = *RelocSym;
2870            }
2871          }
2872          reloc_found = true;
2873          break;
2874        }
2875      }
2876      if (reloc_found && isExtern) {
2877        op_info->AddSymbol.Present = 1;
2878        op_info->AddSymbol.Name =
2879            unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2880        // For i386 extern relocation entries the value in the instruction is
2881        // the offset from the symbol, and value is already set in op_info->Value.
2882        return 1;
2883      }
2884      if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
2885                          r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
2886        const char *add = GuessSymbolName(r_value, info->AddrMap);
2887        const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
2888        uint32_t offset = value - (r_value - pair_r_value);
2889        op_info->AddSymbol.Present = 1;
2890        if (add != nullptr)
2891          op_info->AddSymbol.Name = add;
2892        else
2893          op_info->AddSymbol.Value = r_value;
2894        op_info->SubtractSymbol.Present = 1;
2895        if (sub != nullptr)
2896          op_info->SubtractSymbol.Name = sub;
2897        else
2898          op_info->SubtractSymbol.Value = pair_r_value;
2899        op_info->Value = offset;
2900        return 1;
2901      }
2902      return 0;
2903    }
2904    if (Arch == Triple::x86_64) {
2905      if (OpSize != 1 && OpSize != 2 && OpSize != 4 && OpSize != 0)
2906        return 0;
2907      // For non MH_OBJECT types, like MH_KEXT_BUNDLE, Search the external
2908      // relocation entries of a linked image (if any) for an entry that matches
2909      // this segment offset.
2910      if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
2911        uint64_t seg_offset = Pc + Offset;
2912        bool reloc_found = false;
2913        DataRefImpl Rel;
2914        MachO::any_relocation_info RE;
2915        bool isExtern = false;
2916        SymbolRef Symbol;
2917        for (const RelocationRef &Reloc : info->O->external_relocations()) {
2918          uint64_t RelocOffset = Reloc.getOffset();
2919          if (RelocOffset == seg_offset) {
2920            Rel = Reloc.getRawDataRefImpl();
2921            RE = info->O->getRelocation(Rel);
2922            // external relocation entries should always be external.
2923            isExtern = info->O->getPlainRelocationExternal(RE);
2924            if (isExtern) {
2925              symbol_iterator RelocSym = Reloc.getSymbol();
2926              Symbol = *RelocSym;
2927            }
2928            reloc_found = true;
2929            break;
2930          }
2931        }
2932        if (reloc_found && isExtern) {
2933          // The Value passed in will be adjusted by the Pc if the instruction
2934          // adds the Pc.  But for x86_64 external relocation entries the Value
2935          // is the offset from the external symbol.
2936          if (info->O->getAnyRelocationPCRel(RE))
2937            op_info->Value -= Pc + InstSize;
2938          const char *name =
2939              unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2940          op_info->AddSymbol.Present = 1;
2941          op_info->AddSymbol.Name = name;
2942          return 1;
2943        }
2944        return 0;
2945      }
2946      // In MH_OBJECT filetypes search the section's relocation entries (if any)
2947      // for an entry for this section offset.
2948      uint64_t sect_addr = info->S.getAddress();
2949      uint64_t sect_offset = (Pc + Offset) - sect_addr;
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->S.relocations()) {
2956        uint64_t RelocOffset = Reloc.getOffset();
2957        if (RelocOffset == sect_offset) {
2958          Rel = Reloc.getRawDataRefImpl();
2959          RE = info->O->getRelocation(Rel);
2960          // NOTE: Scattered relocations don't exist on x86_64.
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        unsigned Type = info->O->getAnyRelocationType(RE);
2979        if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
2980          DataRefImpl RelNext = Rel;
2981          info->O->moveRelocationNext(RelNext);
2982          MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
2983          unsigned TypeNext = info->O->getAnyRelocationType(RENext);
2984          bool isExternNext = info->O->getPlainRelocationExternal(RENext);
2985          unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
2986          if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
2987            op_info->SubtractSymbol.Present = 1;
2988            op_info->SubtractSymbol.Name = name;
2989            symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
2990            Symbol = *RelocSymNext;
2991            name = unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
2992          }
2993        }
2994        // TODO: add the VariantKinds to op_info->VariantKind for relocation types
2995        // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
2996        op_info->AddSymbol.Present = 1;
2997        op_info->AddSymbol.Name = name;
2998        return 1;
2999      }
3000      return 0;
3001    }
3002    if (Arch == Triple::arm) {
3003      if (Offset != 0 || (InstSize != 4 && InstSize != 2))
3004        return 0;
3005      if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
3006        // TODO:
3007        // Search the external relocation entries of a fully linked image
3008        // (if any) for an entry that matches this segment offset.
3009        // uint32_t seg_offset = (Pc + Offset);
3010        return 0;
3011      }
3012      // In MH_OBJECT filetypes search the section's relocation entries (if any)
3013      // for an entry for this section offset.
3014      uint32_t sect_addr = info->S.getAddress();
3015      uint32_t sect_offset = (Pc + Offset) - sect_addr;
3016      DataRefImpl Rel;
3017      MachO::any_relocation_info RE;
3018      bool isExtern = false;
3019      SymbolRef Symbol;
3020      bool r_scattered = false;
3021      uint32_t r_value, pair_r_value, r_type, r_length, other_half;
3022      auto Reloc =
3023          find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
3024            uint64_t RelocOffset = Reloc.getOffset();
3025            return RelocOffset == sect_offset;
3026          });
3027  
3028      if (Reloc == info->S.relocations().end())
3029        return 0;
3030  
3031      Rel = Reloc->getRawDataRefImpl();
3032      RE = info->O->getRelocation(Rel);
3033      r_length = info->O->getAnyRelocationLength(RE);
3034      r_scattered = info->O->isRelocationScattered(RE);
3035      if (r_scattered) {
3036        r_value = info->O->getScatteredRelocationValue(RE);
3037        r_type = info->O->getScatteredRelocationType(RE);
3038      } else {
3039        r_type = info->O->getAnyRelocationType(RE);
3040        isExtern = info->O->getPlainRelocationExternal(RE);
3041        if (isExtern) {
3042          symbol_iterator RelocSym = Reloc->getSymbol();
3043          Symbol = *RelocSym;
3044        }
3045      }
3046      if (r_type == MachO::ARM_RELOC_HALF ||
3047          r_type == MachO::ARM_RELOC_SECTDIFF ||
3048          r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
3049          r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3050        DataRefImpl RelNext = Rel;
3051        info->O->moveRelocationNext(RelNext);
3052        MachO::any_relocation_info RENext;
3053        RENext = info->O->getRelocation(RelNext);
3054        other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
3055        if (info->O->isRelocationScattered(RENext))
3056          pair_r_value = info->O->getScatteredRelocationValue(RENext);
3057      }
3058  
3059      if (isExtern) {
3060        const char *name =
3061            unwrapOrError(Symbol.getName(), info->O->getFileName()).data();
3062        op_info->AddSymbol.Present = 1;
3063        op_info->AddSymbol.Name = name;
3064        switch (r_type) {
3065        case MachO::ARM_RELOC_HALF:
3066          if ((r_length & 0x1) == 1) {
3067            op_info->Value = value << 16 | other_half;
3068            op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3069          } else {
3070            op_info->Value = other_half << 16 | value;
3071            op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3072          }
3073          break;
3074        default:
3075          break;
3076        }
3077        return 1;
3078      }
3079      // If we have a branch that is not an external relocation entry then
3080      // return 0 so the code in tryAddingSymbolicOperand() can use the
3081      // SymbolLookUp call back with the branch target address to look up the
3082      // symbol and possibility add an annotation for a symbol stub.
3083      if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
3084                            r_type == MachO::ARM_THUMB_RELOC_BR22))
3085        return 0;
3086  
3087      uint32_t offset = 0;
3088      if (r_type == MachO::ARM_RELOC_HALF ||
3089          r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3090        if ((r_length & 0x1) == 1)
3091          value = value << 16 | other_half;
3092        else
3093          value = other_half << 16 | value;
3094      }
3095      if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
3096                          r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
3097        offset = value - r_value;
3098        value = r_value;
3099      }
3100  
3101      if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
3102        if ((r_length & 0x1) == 1)
3103          op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3104        else
3105          op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3106        const char *add = GuessSymbolName(r_value, info->AddrMap);
3107        const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
3108        int32_t offset = value - (r_value - pair_r_value);
3109        op_info->AddSymbol.Present = 1;
3110        if (add != nullptr)
3111          op_info->AddSymbol.Name = add;
3112        else
3113          op_info->AddSymbol.Value = r_value;
3114        op_info->SubtractSymbol.Present = 1;
3115        if (sub != nullptr)
3116          op_info->SubtractSymbol.Name = sub;
3117        else
3118          op_info->SubtractSymbol.Value = pair_r_value;
3119        op_info->Value = offset;
3120        return 1;
3121      }
3122  
3123      op_info->AddSymbol.Present = 1;
3124      op_info->Value = offset;
3125      if (r_type == MachO::ARM_RELOC_HALF) {
3126        if ((r_length & 0x1) == 1)
3127          op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
3128        else
3129          op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
3130      }
3131      const char *add = GuessSymbolName(value, info->AddrMap);
3132      if (add != nullptr) {
3133        op_info->AddSymbol.Name = add;
3134        return 1;
3135      }
3136      op_info->AddSymbol.Value = value;
3137      return 1;
3138    }
3139    if (Arch == Triple::aarch64) {
3140      if (Offset != 0 || InstSize != 4)
3141        return 0;
3142      if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
3143        // TODO:
3144        // Search the external relocation entries of a fully linked image
3145        // (if any) for an entry that matches this segment offset.
3146        // uint64_t seg_offset = (Pc + Offset);
3147        return 0;
3148      }
3149      // In MH_OBJECT filetypes search the section's relocation entries (if any)
3150      // for an entry for this section offset.
3151      uint64_t sect_addr = info->S.getAddress();
3152      uint64_t sect_offset = (Pc + Offset) - sect_addr;
3153      auto Reloc =
3154          find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
3155            uint64_t RelocOffset = Reloc.getOffset();
3156            return RelocOffset == sect_offset;
3157          });
3158  
3159      if (Reloc == info->S.relocations().end())
3160        return 0;
3161  
3162      DataRefImpl Rel = Reloc->getRawDataRefImpl();
3163      MachO::any_relocation_info RE = info->O->getRelocation(Rel);
3164      uint32_t r_type = info->O->getAnyRelocationType(RE);
3165      if (r_type == MachO::ARM64_RELOC_ADDEND) {
3166        DataRefImpl RelNext = Rel;
3167        info->O->moveRelocationNext(RelNext);
3168        MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
3169        if (value == 0) {
3170          value = info->O->getPlainRelocationSymbolNum(RENext);
3171          op_info->Value = value;
3172        }
3173      }
3174      // NOTE: Scattered relocations don't exist on arm64.
3175      if (!info->O->getPlainRelocationExternal(RE))
3176        return 0;
3177      const char *name =
3178          unwrapOrError(Reloc->getSymbol()->getName(), info->O->getFileName())
3179              .data();
3180      op_info->AddSymbol.Present = 1;
3181      op_info->AddSymbol.Name = name;
3182  
3183      switch (r_type) {
3184      case MachO::ARM64_RELOC_PAGE21:
3185        /* @page */
3186        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
3187        break;
3188      case MachO::ARM64_RELOC_PAGEOFF12:
3189        /* @pageoff */
3190        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
3191        break;
3192      case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
3193        /* @gotpage */
3194        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
3195        break;
3196      case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
3197        /* @gotpageoff */
3198        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
3199        break;
3200      case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
3201        /* @tvlppage is not implemented in llvm-mc */
3202        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
3203        break;
3204      case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
3205        /* @tvlppageoff is not implemented in llvm-mc */
3206        op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
3207        break;
3208      default:
3209      case MachO::ARM64_RELOC_BRANCH26:
3210        op_info->VariantKind = LLVMDisassembler_VariantKind_None;
3211        break;
3212      }
3213      return 1;
3214    }
3215    return 0;
3216  }
3217  
3218  // GuessCstringPointer is passed the address of what might be a pointer to a
3219  // literal string in a cstring section.  If that address is in a cstring section
3220  // it returns a pointer to that string.  Else it returns nullptr.
GuessCstringPointer(uint64_t ReferenceValue,struct DisassembleInfo * info)3221  static const char *GuessCstringPointer(uint64_t ReferenceValue,
3222                                         struct DisassembleInfo *info) {
3223    for (const auto &Load : info->O->load_commands()) {
3224      if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3225        MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3226        for (unsigned J = 0; J < Seg.nsects; ++J) {
3227          MachO::section_64 Sec = info->O->getSection64(Load, J);
3228          uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3229          if (section_type == MachO::S_CSTRING_LITERALS &&
3230              ReferenceValue >= Sec.addr &&
3231              ReferenceValue < Sec.addr + Sec.size) {
3232            uint64_t sect_offset = ReferenceValue - Sec.addr;
3233            uint64_t object_offset = Sec.offset + sect_offset;
3234            StringRef MachOContents = info->O->getData();
3235            uint64_t object_size = MachOContents.size();
3236            const char *object_addr = (const char *)MachOContents.data();
3237            if (object_offset < object_size) {
3238              const char *name = object_addr + object_offset;
3239              return name;
3240            } else {
3241              return nullptr;
3242            }
3243          }
3244        }
3245      } else if (Load.C.cmd == MachO::LC_SEGMENT) {
3246        MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
3247        for (unsigned J = 0; J < Seg.nsects; ++J) {
3248          MachO::section Sec = info->O->getSection(Load, J);
3249          uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3250          if (section_type == MachO::S_CSTRING_LITERALS &&
3251              ReferenceValue >= Sec.addr &&
3252              ReferenceValue < Sec.addr + Sec.size) {
3253            uint64_t sect_offset = ReferenceValue - Sec.addr;
3254            uint64_t object_offset = Sec.offset + sect_offset;
3255            StringRef MachOContents = info->O->getData();
3256            uint64_t object_size = MachOContents.size();
3257            const char *object_addr = (const char *)MachOContents.data();
3258            if (object_offset < object_size) {
3259              const char *name = object_addr + object_offset;
3260              return name;
3261            } else {
3262              return nullptr;
3263            }
3264          }
3265        }
3266      }
3267    }
3268    return nullptr;
3269  }
3270  
3271  // GuessIndirectSymbol returns the name of the indirect symbol for the
3272  // ReferenceValue passed in or nullptr.  This is used when ReferenceValue maybe
3273  // an address of a symbol stub or a lazy or non-lazy pointer to associate the
3274  // symbol name being referenced by the stub or pointer.
GuessIndirectSymbol(uint64_t ReferenceValue,struct DisassembleInfo * info)3275  static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
3276                                         struct DisassembleInfo *info) {
3277    MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
3278    MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
3279    for (const auto &Load : info->O->load_commands()) {
3280      if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3281        MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3282        for (unsigned J = 0; J < Seg.nsects; ++J) {
3283          MachO::section_64 Sec = info->O->getSection64(Load, J);
3284          uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3285          if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
3286               section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
3287               section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
3288               section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
3289               section_type == MachO::S_SYMBOL_STUBS) &&
3290              ReferenceValue >= Sec.addr &&
3291              ReferenceValue < Sec.addr + Sec.size) {
3292            uint32_t stride;
3293            if (section_type == MachO::S_SYMBOL_STUBS)
3294              stride = Sec.reserved2;
3295            else
3296              stride = 8;
3297            if (stride == 0)
3298              return nullptr;
3299            uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
3300            if (index < Dysymtab.nindirectsyms) {
3301              uint32_t indirect_symbol =
3302                  info->O->getIndirectSymbolTableEntry(Dysymtab, index);
3303              if (indirect_symbol < Symtab.nsyms) {
3304                symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
3305                return unwrapOrError(Sym->getName(), info->O->getFileName())
3306                    .data();
3307              }
3308            }
3309          }
3310        }
3311      } else if (Load.C.cmd == MachO::LC_SEGMENT) {
3312        MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
3313        for (unsigned J = 0; J < Seg.nsects; ++J) {
3314          MachO::section Sec = info->O->getSection(Load, J);
3315          uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
3316          if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
3317               section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
3318               section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
3319               section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
3320               section_type == MachO::S_SYMBOL_STUBS) &&
3321              ReferenceValue >= Sec.addr &&
3322              ReferenceValue < Sec.addr + Sec.size) {
3323            uint32_t stride;
3324            if (section_type == MachO::S_SYMBOL_STUBS)
3325              stride = Sec.reserved2;
3326            else
3327              stride = 4;
3328            if (stride == 0)
3329              return nullptr;
3330            uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
3331            if (index < Dysymtab.nindirectsyms) {
3332              uint32_t indirect_symbol =
3333                  info->O->getIndirectSymbolTableEntry(Dysymtab, index);
3334              if (indirect_symbol < Symtab.nsyms) {
3335                symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
3336                return unwrapOrError(Sym->getName(), info->O->getFileName())
3337                    .data();
3338              }
3339            }
3340          }
3341        }
3342      }
3343    }
3344    return nullptr;
3345  }
3346  
3347  // method_reference() is called passing it the ReferenceName that might be
3348  // a reference it to an Objective-C method call.  If so then it allocates and
3349  // assembles a method call string with the values last seen and saved in
3350  // the DisassembleInfo's class_name and selector_name fields.  This is saved
3351  // into the method field of the info and any previous string is free'ed.
3352  // Then the class_name field in the info is set to nullptr.  The method call
3353  // string is set into ReferenceName and ReferenceType is set to
3354  // LLVMDisassembler_ReferenceType_Out_Objc_Message.  If this not a method call
3355  // then both ReferenceType and ReferenceName are left unchanged.
method_reference(struct DisassembleInfo * info,uint64_t * ReferenceType,const char ** ReferenceName)3356  static void method_reference(struct DisassembleInfo *info,
3357                               uint64_t *ReferenceType,
3358                               const char **ReferenceName) {
3359    unsigned int Arch = info->O->getArch();
3360    if (*ReferenceName != nullptr) {
3361      if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
3362        if (info->selector_name != nullptr) {
3363          if (info->class_name != nullptr) {
3364            info->method = std::make_unique<char[]>(
3365                5 + strlen(info->class_name) + strlen(info->selector_name));
3366            char *method = info->method.get();
3367            if (method != nullptr) {
3368              strcpy(method, "+[");
3369              strcat(method, info->class_name);
3370              strcat(method, " ");
3371              strcat(method, info->selector_name);
3372              strcat(method, "]");
3373              *ReferenceName = method;
3374              *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3375            }
3376          } else {
3377            info->method =
3378                std::make_unique<char[]>(9 + strlen(info->selector_name));
3379            char *method = info->method.get();
3380            if (method != nullptr) {
3381              if (Arch == Triple::x86_64)
3382                strcpy(method, "-[%rdi ");
3383              else if (Arch == Triple::aarch64)
3384                strcpy(method, "-[x0 ");
3385              else
3386                strcpy(method, "-[r? ");
3387              strcat(method, info->selector_name);
3388              strcat(method, "]");
3389              *ReferenceName = method;
3390              *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3391            }
3392          }
3393          info->class_name = nullptr;
3394        }
3395      } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
3396        if (info->selector_name != nullptr) {
3397          info->method =
3398              std::make_unique<char[]>(17 + strlen(info->selector_name));
3399          char *method = info->method.get();
3400          if (method != nullptr) {
3401            if (Arch == Triple::x86_64)
3402              strcpy(method, "-[[%rdi super] ");
3403            else if (Arch == Triple::aarch64)
3404              strcpy(method, "-[[x0 super] ");
3405            else
3406              strcpy(method, "-[[r? super] ");
3407            strcat(method, info->selector_name);
3408            strcat(method, "]");
3409            *ReferenceName = method;
3410            *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
3411          }
3412          info->class_name = nullptr;
3413        }
3414      }
3415    }
3416  }
3417  
3418  // GuessPointerPointer() is passed the address of what might be a pointer to
3419  // a reference to an Objective-C class, selector, message ref or cfstring.
3420  // If so the value of the pointer is returned and one of the booleans are set
3421  // to true.  If not zero is returned and all the booleans are set to false.
GuessPointerPointer(uint64_t ReferenceValue,struct DisassembleInfo * info,bool & classref,bool & selref,bool & msgref,bool & cfstring)3422  static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
3423                                      struct DisassembleInfo *info,
3424                                      bool &classref, bool &selref, bool &msgref,
3425                                      bool &cfstring) {
3426    classref = false;
3427    selref = false;
3428    msgref = false;
3429    cfstring = false;
3430    for (const auto &Load : info->O->load_commands()) {
3431      if (Load.C.cmd == MachO::LC_SEGMENT_64) {
3432        MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
3433        for (unsigned J = 0; J < Seg.nsects; ++J) {
3434          MachO::section_64 Sec = info->O->getSection64(Load, J);
3435          if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
3436               strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
3437               strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
3438               strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
3439               strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
3440              ReferenceValue >= Sec.addr &&
3441              ReferenceValue < Sec.addr + Sec.size) {
3442            uint64_t sect_offset = ReferenceValue - Sec.addr;
3443            uint64_t object_offset = Sec.offset + sect_offset;
3444            StringRef MachOContents = info->O->getData();
3445            uint64_t object_size = MachOContents.size();
3446            const char *object_addr = (const char *)MachOContents.data();
3447            if (object_offset < object_size) {
3448              uint64_t pointer_value;
3449              memcpy(&pointer_value, object_addr + object_offset,
3450                     sizeof(uint64_t));
3451              if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3452                sys::swapByteOrder(pointer_value);
3453              if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
3454                selref = true;
3455              else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
3456                       strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
3457                classref = true;
3458              else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
3459                       ReferenceValue + 8 < Sec.addr + Sec.size) {
3460                msgref = true;
3461                memcpy(&pointer_value, object_addr + object_offset + 8,
3462                       sizeof(uint64_t));
3463                if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
3464                  sys::swapByteOrder(pointer_value);
3465              } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
3466                cfstring = true;
3467              return pointer_value;
3468            } else {
3469              return 0;
3470            }
3471          }
3472        }
3473      }
3474      // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
3475    }
3476    return 0;
3477  }
3478  
3479  // get_pointer_64 returns a pointer to the bytes in the object file at the
3480  // Address from a section in the Mach-O file.  And indirectly returns the
3481  // offset into the section, number of bytes left in the section past the offset
3482  // and which section is was being referenced.  If the Address is not in a
3483  // section nullptr is returned.
get_pointer_64(uint64_t Address,uint32_t & offset,uint32_t & left,SectionRef & S,DisassembleInfo * info,bool objc_only=false)3484  static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
3485                                    uint32_t &left, SectionRef &S,
3486                                    DisassembleInfo *info,
3487                                    bool objc_only = false) {
3488    offset = 0;
3489    left = 0;
3490    S = SectionRef();
3491    for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
3492      uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
3493      uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
3494      if (SectSize == 0)
3495        continue;
3496      if (objc_only) {
3497        StringRef SectName;
3498        Expected<StringRef> SecNameOrErr =
3499            ((*(info->Sections))[SectIdx]).getName();
3500        if (SecNameOrErr)
3501          SectName = *SecNameOrErr;
3502        else
3503          consumeError(SecNameOrErr.takeError());
3504  
3505        DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
3506        StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
3507        if (SegName != "__OBJC" && SectName != "__cstring")
3508          continue;
3509      }
3510      if (Address >= SectAddress && Address < SectAddress + SectSize) {
3511        S = (*(info->Sections))[SectIdx];
3512        offset = Address - SectAddress;
3513        left = SectSize - offset;
3514        StringRef SectContents = unwrapOrError(
3515            ((*(info->Sections))[SectIdx]).getContents(), info->O->getFileName());
3516        return SectContents.data() + offset;
3517      }
3518    }
3519    return nullptr;
3520  }
3521  
get_pointer_32(uint32_t Address,uint32_t & offset,uint32_t & left,SectionRef & S,DisassembleInfo * info,bool objc_only=false)3522  static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
3523                                    uint32_t &left, SectionRef &S,
3524                                    DisassembleInfo *info,
3525                                    bool objc_only = false) {
3526    return get_pointer_64(Address, offset, left, S, info, objc_only);
3527  }
3528  
3529  // get_symbol_64() returns the name of a symbol (or nullptr) and the address of
3530  // the symbol indirectly through n_value. Based on the relocation information
3531  // for the specified section offset in the specified section reference.
3532  // If no relocation information is found and a non-zero ReferenceValue for the
3533  // symbol is passed, look up that address in the info's AddrMap.
get_symbol_64(uint32_t sect_offset,SectionRef S,DisassembleInfo * info,uint64_t & n_value,uint64_t ReferenceValue=0)3534  static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
3535                                   DisassembleInfo *info, uint64_t &n_value,
3536                                   uint64_t ReferenceValue = 0) {
3537    n_value = 0;
3538    if (!info->verbose)
3539      return nullptr;
3540  
3541    // See if there is an external relocation entry at the sect_offset.
3542    bool reloc_found = false;
3543    DataRefImpl Rel;
3544    MachO::any_relocation_info RE;
3545    bool isExtern = false;
3546    SymbolRef Symbol;
3547    for (const RelocationRef &Reloc : S.relocations()) {
3548      uint64_t RelocOffset = Reloc.getOffset();
3549      if (RelocOffset == sect_offset) {
3550        Rel = Reloc.getRawDataRefImpl();
3551        RE = info->O->getRelocation(Rel);
3552        if (info->O->isRelocationScattered(RE))
3553          continue;
3554        isExtern = info->O->getPlainRelocationExternal(RE);
3555        if (isExtern) {
3556          symbol_iterator RelocSym = Reloc.getSymbol();
3557          Symbol = *RelocSym;
3558        }
3559        reloc_found = true;
3560        break;
3561      }
3562    }
3563    // If there is an external relocation entry for a symbol in this section
3564    // at this section_offset then use that symbol's value for the n_value
3565    // and return its name.
3566    const char *SymbolName = nullptr;
3567    if (reloc_found && isExtern) {
3568      n_value = cantFail(Symbol.getValue());
3569      StringRef Name = unwrapOrError(Symbol.getName(), info->O->getFileName());
3570      if (!Name.empty()) {
3571        SymbolName = Name.data();
3572        return SymbolName;
3573      }
3574    }
3575  
3576    // TODO: For fully linked images, look through the external relocation
3577    // entries off the dynamic symtab command. For these the r_offset is from the
3578    // start of the first writeable segment in the Mach-O file.  So the offset
3579    // to this section from that segment is passed to this routine by the caller,
3580    // as the database_offset. Which is the difference of the section's starting
3581    // address and the first writable segment.
3582    //
3583    // NOTE: need add passing the database_offset to this routine.
3584  
3585    // We did not find an external relocation entry so look up the ReferenceValue
3586    // as an address of a symbol and if found return that symbol's name.
3587    SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
3588  
3589    return SymbolName;
3590  }
3591  
get_symbol_32(uint32_t sect_offset,SectionRef S,DisassembleInfo * info,uint32_t ReferenceValue)3592  static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
3593                                   DisassembleInfo *info,
3594                                   uint32_t ReferenceValue) {
3595    uint64_t n_value64;
3596    return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
3597  }
3598  
3599  namespace {
3600  
3601  // These are structs in the Objective-C meta data and read to produce the
3602  // comments for disassembly.  While these are part of the ABI they are no
3603  // public defintions.  So the are here not in include/llvm/BinaryFormat/MachO.h
3604  // .
3605  
3606  // The cfstring object in a 64-bit Mach-O file.
3607  struct cfstring64_t {
3608    uint64_t isa;        // class64_t * (64-bit pointer)
3609    uint64_t flags;      // flag bits
3610    uint64_t characters; // char * (64-bit pointer)
3611    uint64_t length;     // number of non-NULL characters in above
3612  };
3613  
3614  // The class object in a 64-bit Mach-O file.
3615  struct class64_t {
3616    uint64_t isa;        // class64_t * (64-bit pointer)
3617    uint64_t superclass; // class64_t * (64-bit pointer)
3618    uint64_t cache;      // Cache (64-bit pointer)
3619    uint64_t vtable;     // IMP * (64-bit pointer)
3620    uint64_t data;       // class_ro64_t * (64-bit pointer)
3621  };
3622  
3623  struct class32_t {
3624    uint32_t isa;        /* class32_t * (32-bit pointer) */
3625    uint32_t superclass; /* class32_t * (32-bit pointer) */
3626    uint32_t cache;      /* Cache (32-bit pointer) */
3627    uint32_t vtable;     /* IMP * (32-bit pointer) */
3628    uint32_t data;       /* class_ro32_t * (32-bit pointer) */
3629  };
3630  
3631  struct class_ro64_t {
3632    uint32_t flags;
3633    uint32_t instanceStart;
3634    uint32_t instanceSize;
3635    uint32_t reserved;
3636    uint64_t ivarLayout;     // const uint8_t * (64-bit pointer)
3637    uint64_t name;           // const char * (64-bit pointer)
3638    uint64_t baseMethods;    // const method_list_t * (64-bit pointer)
3639    uint64_t baseProtocols;  // const protocol_list_t * (64-bit pointer)
3640    uint64_t ivars;          // const ivar_list_t * (64-bit pointer)
3641    uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
3642    uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
3643  };
3644  
3645  struct class_ro32_t {
3646    uint32_t flags;
3647    uint32_t instanceStart;
3648    uint32_t instanceSize;
3649    uint32_t ivarLayout;     /* const uint8_t * (32-bit pointer) */
3650    uint32_t name;           /* const char * (32-bit pointer) */
3651    uint32_t baseMethods;    /* const method_list_t * (32-bit pointer) */
3652    uint32_t baseProtocols;  /* const protocol_list_t * (32-bit pointer) */
3653    uint32_t ivars;          /* const ivar_list_t * (32-bit pointer) */
3654    uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
3655    uint32_t baseProperties; /* const struct objc_property_list *
3656                                                     (32-bit pointer) */
3657  };
3658  
3659  /* Values for class_ro{64,32}_t->flags */
3660  #define RO_META (1 << 0)
3661  #define RO_ROOT (1 << 1)
3662  #define RO_HAS_CXX_STRUCTORS (1 << 2)
3663  
3664  /* Values for method_list{64,32}_t->entsize */
3665  #define ML_HAS_RELATIVE_PTRS (1 << 31)
3666  #define ML_ENTSIZE_MASK 0xFFFF
3667  
3668  struct method_list64_t {
3669    uint32_t entsize;
3670    uint32_t count;
3671    /* struct method64_t first;  These structures follow inline */
3672  };
3673  
3674  struct method_list32_t {
3675    uint32_t entsize;
3676    uint32_t count;
3677    /* struct method32_t first;  These structures follow inline */
3678  };
3679  
3680  struct method64_t {
3681    uint64_t name;  /* SEL (64-bit pointer) */
3682    uint64_t types; /* const char * (64-bit pointer) */
3683    uint64_t imp;   /* IMP (64-bit pointer) */
3684  };
3685  
3686  struct method32_t {
3687    uint32_t name;  /* SEL (32-bit pointer) */
3688    uint32_t types; /* const char * (32-bit pointer) */
3689    uint32_t imp;   /* IMP (32-bit pointer) */
3690  };
3691  
3692  struct method_relative_t {
3693    int32_t name;  /* SEL (32-bit relative) */
3694    int32_t types; /* const char * (32-bit relative) */
3695    int32_t imp;   /* IMP (32-bit relative) */
3696  };
3697  
3698  struct protocol_list64_t {
3699    uint64_t count; /* uintptr_t (a 64-bit value) */
3700    /* struct protocol64_t * list[0];  These pointers follow inline */
3701  };
3702  
3703  struct protocol_list32_t {
3704    uint32_t count; /* uintptr_t (a 32-bit value) */
3705    /* struct protocol32_t * list[0];  These pointers follow inline */
3706  };
3707  
3708  struct protocol64_t {
3709    uint64_t isa;                     /* id * (64-bit pointer) */
3710    uint64_t name;                    /* const char * (64-bit pointer) */
3711    uint64_t protocols;               /* struct protocol_list64_t *
3712                                                      (64-bit pointer) */
3713    uint64_t instanceMethods;         /* method_list_t * (64-bit pointer) */
3714    uint64_t classMethods;            /* method_list_t * (64-bit pointer) */
3715    uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
3716    uint64_t optionalClassMethods;    /* method_list_t * (64-bit pointer) */
3717    uint64_t instanceProperties;      /* struct objc_property_list *
3718                                                         (64-bit pointer) */
3719  };
3720  
3721  struct protocol32_t {
3722    uint32_t isa;                     /* id * (32-bit pointer) */
3723    uint32_t name;                    /* const char * (32-bit pointer) */
3724    uint32_t protocols;               /* struct protocol_list_t *
3725                                                      (32-bit pointer) */
3726    uint32_t instanceMethods;         /* method_list_t * (32-bit pointer) */
3727    uint32_t classMethods;            /* method_list_t * (32-bit pointer) */
3728    uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
3729    uint32_t optionalClassMethods;    /* method_list_t * (32-bit pointer) */
3730    uint32_t instanceProperties;      /* struct objc_property_list *
3731                                                         (32-bit pointer) */
3732  };
3733  
3734  struct ivar_list64_t {
3735    uint32_t entsize;
3736    uint32_t count;
3737    /* struct ivar64_t first;  These structures follow inline */
3738  };
3739  
3740  struct ivar_list32_t {
3741    uint32_t entsize;
3742    uint32_t count;
3743    /* struct ivar32_t first;  These structures follow inline */
3744  };
3745  
3746  struct ivar64_t {
3747    uint64_t offset; /* uintptr_t * (64-bit pointer) */
3748    uint64_t name;   /* const char * (64-bit pointer) */
3749    uint64_t type;   /* const char * (64-bit pointer) */
3750    uint32_t alignment;
3751    uint32_t size;
3752  };
3753  
3754  struct ivar32_t {
3755    uint32_t offset; /* uintptr_t * (32-bit pointer) */
3756    uint32_t name;   /* const char * (32-bit pointer) */
3757    uint32_t type;   /* const char * (32-bit pointer) */
3758    uint32_t alignment;
3759    uint32_t size;
3760  };
3761  
3762  struct objc_property_list64 {
3763    uint32_t entsize;
3764    uint32_t count;
3765    /* struct objc_property64 first;  These structures follow inline */
3766  };
3767  
3768  struct objc_property_list32 {
3769    uint32_t entsize;
3770    uint32_t count;
3771    /* struct objc_property32 first;  These structures follow inline */
3772  };
3773  
3774  struct objc_property64 {
3775    uint64_t name;       /* const char * (64-bit pointer) */
3776    uint64_t attributes; /* const char * (64-bit pointer) */
3777  };
3778  
3779  struct objc_property32 {
3780    uint32_t name;       /* const char * (32-bit pointer) */
3781    uint32_t attributes; /* const char * (32-bit pointer) */
3782  };
3783  
3784  struct category64_t {
3785    uint64_t name;               /* const char * (64-bit pointer) */
3786    uint64_t cls;                /* struct class_t * (64-bit pointer) */
3787    uint64_t instanceMethods;    /* struct method_list_t * (64-bit pointer) */
3788    uint64_t classMethods;       /* struct method_list_t * (64-bit pointer) */
3789    uint64_t protocols;          /* struct protocol_list_t * (64-bit pointer) */
3790    uint64_t instanceProperties; /* struct objc_property_list *
3791                                    (64-bit pointer) */
3792  };
3793  
3794  struct category32_t {
3795    uint32_t name;               /* const char * (32-bit pointer) */
3796    uint32_t cls;                /* struct class_t * (32-bit pointer) */
3797    uint32_t instanceMethods;    /* struct method_list_t * (32-bit pointer) */
3798    uint32_t classMethods;       /* struct method_list_t * (32-bit pointer) */
3799    uint32_t protocols;          /* struct protocol_list_t * (32-bit pointer) */
3800    uint32_t instanceProperties; /* struct objc_property_list *
3801                                    (32-bit pointer) */
3802  };
3803  
3804  struct objc_image_info64 {
3805    uint32_t version;
3806    uint32_t flags;
3807  };
3808  struct objc_image_info32 {
3809    uint32_t version;
3810    uint32_t flags;
3811  };
3812  struct imageInfo_t {
3813    uint32_t version;
3814    uint32_t flags;
3815  };
3816  /* masks for objc_image_info.flags */
3817  #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
3818  #define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
3819  #define OBJC_IMAGE_IS_SIMULATED (1 << 5)
3820  #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)
3821  
3822  struct message_ref64 {
3823    uint64_t imp; /* IMP (64-bit pointer) */
3824    uint64_t sel; /* SEL (64-bit pointer) */
3825  };
3826  
3827  struct message_ref32 {
3828    uint32_t imp; /* IMP (32-bit pointer) */
3829    uint32_t sel; /* SEL (32-bit pointer) */
3830  };
3831  
3832  // Objective-C 1 (32-bit only) meta data structs.
3833  
3834  struct objc_module_t {
3835    uint32_t version;
3836    uint32_t size;
3837    uint32_t name;   /* char * (32-bit pointer) */
3838    uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
3839  };
3840  
3841  struct objc_symtab_t {
3842    uint32_t sel_ref_cnt;
3843    uint32_t refs; /* SEL * (32-bit pointer) */
3844    uint16_t cls_def_cnt;
3845    uint16_t cat_def_cnt;
3846    // uint32_t defs[1];        /* void * (32-bit pointer) variable size */
3847  };
3848  
3849  struct objc_class_t {
3850    uint32_t isa;         /* struct objc_class * (32-bit pointer) */
3851    uint32_t super_class; /* struct objc_class * (32-bit pointer) */
3852    uint32_t name;        /* const char * (32-bit pointer) */
3853    int32_t version;
3854    int32_t info;
3855    int32_t instance_size;
3856    uint32_t ivars;       /* struct objc_ivar_list * (32-bit pointer) */
3857    uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
3858    uint32_t cache;       /* struct objc_cache * (32-bit pointer) */
3859    uint32_t protocols;   /* struct objc_protocol_list * (32-bit pointer) */
3860  };
3861  
3862  #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
3863  // class is not a metaclass
3864  #define CLS_CLASS 0x1
3865  // class is a metaclass
3866  #define CLS_META 0x2
3867  
3868  struct objc_category_t {
3869    uint32_t category_name;    /* char * (32-bit pointer) */
3870    uint32_t class_name;       /* char * (32-bit pointer) */
3871    uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
3872    uint32_t class_methods;    /* struct objc_method_list * (32-bit pointer) */
3873    uint32_t protocols;        /* struct objc_protocol_list * (32-bit ptr) */
3874  };
3875  
3876  struct objc_ivar_t {
3877    uint32_t ivar_name; /* char * (32-bit pointer) */
3878    uint32_t ivar_type; /* char * (32-bit pointer) */
3879    int32_t ivar_offset;
3880  };
3881  
3882  struct objc_ivar_list_t {
3883    int32_t ivar_count;
3884    // struct objc_ivar_t ivar_list[1];          /* variable length structure */
3885  };
3886  
3887  struct objc_method_list_t {
3888    uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
3889    int32_t method_count;
3890    // struct objc_method_t method_list[1];      /* variable length structure */
3891  };
3892  
3893  struct objc_method_t {
3894    uint32_t method_name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3895    uint32_t method_types; /* char * (32-bit pointer) */
3896    uint32_t method_imp;   /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
3897                              (32-bit pointer) */
3898  };
3899  
3900  struct objc_protocol_list_t {
3901    uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
3902    int32_t count;
3903    // uint32_t list[1];   /* Protocol *, aka struct objc_protocol_t *
3904    //                        (32-bit pointer) */
3905  };
3906  
3907  struct objc_protocol_t {
3908    uint32_t isa;              /* struct objc_class * (32-bit pointer) */
3909    uint32_t protocol_name;    /* char * (32-bit pointer) */
3910    uint32_t protocol_list;    /* struct objc_protocol_list * (32-bit pointer) */
3911    uint32_t instance_methods; /* struct objc_method_description_list *
3912                                  (32-bit pointer) */
3913    uint32_t class_methods;    /* struct objc_method_description_list *
3914                                  (32-bit pointer) */
3915  };
3916  
3917  struct objc_method_description_list_t {
3918    int32_t count;
3919    // struct objc_method_description_t list[1];
3920  };
3921  
3922  struct objc_method_description_t {
3923    uint32_t name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3924    uint32_t types; /* char * (32-bit pointer) */
3925  };
3926  
swapStruct(struct cfstring64_t & cfs)3927  inline void swapStruct(struct cfstring64_t &cfs) {
3928    sys::swapByteOrder(cfs.isa);
3929    sys::swapByteOrder(cfs.flags);
3930    sys::swapByteOrder(cfs.characters);
3931    sys::swapByteOrder(cfs.length);
3932  }
3933  
swapStruct(struct class64_t & c)3934  inline void swapStruct(struct class64_t &c) {
3935    sys::swapByteOrder(c.isa);
3936    sys::swapByteOrder(c.superclass);
3937    sys::swapByteOrder(c.cache);
3938    sys::swapByteOrder(c.vtable);
3939    sys::swapByteOrder(c.data);
3940  }
3941  
swapStruct(struct class32_t & c)3942  inline void swapStruct(struct class32_t &c) {
3943    sys::swapByteOrder(c.isa);
3944    sys::swapByteOrder(c.superclass);
3945    sys::swapByteOrder(c.cache);
3946    sys::swapByteOrder(c.vtable);
3947    sys::swapByteOrder(c.data);
3948  }
3949  
swapStruct(struct class_ro64_t & cro)3950  inline void swapStruct(struct class_ro64_t &cro) {
3951    sys::swapByteOrder(cro.flags);
3952    sys::swapByteOrder(cro.instanceStart);
3953    sys::swapByteOrder(cro.instanceSize);
3954    sys::swapByteOrder(cro.reserved);
3955    sys::swapByteOrder(cro.ivarLayout);
3956    sys::swapByteOrder(cro.name);
3957    sys::swapByteOrder(cro.baseMethods);
3958    sys::swapByteOrder(cro.baseProtocols);
3959    sys::swapByteOrder(cro.ivars);
3960    sys::swapByteOrder(cro.weakIvarLayout);
3961    sys::swapByteOrder(cro.baseProperties);
3962  }
3963  
swapStruct(struct class_ro32_t & cro)3964  inline void swapStruct(struct class_ro32_t &cro) {
3965    sys::swapByteOrder(cro.flags);
3966    sys::swapByteOrder(cro.instanceStart);
3967    sys::swapByteOrder(cro.instanceSize);
3968    sys::swapByteOrder(cro.ivarLayout);
3969    sys::swapByteOrder(cro.name);
3970    sys::swapByteOrder(cro.baseMethods);
3971    sys::swapByteOrder(cro.baseProtocols);
3972    sys::swapByteOrder(cro.ivars);
3973    sys::swapByteOrder(cro.weakIvarLayout);
3974    sys::swapByteOrder(cro.baseProperties);
3975  }
3976  
swapStruct(struct method_list64_t & ml)3977  inline void swapStruct(struct method_list64_t &ml) {
3978    sys::swapByteOrder(ml.entsize);
3979    sys::swapByteOrder(ml.count);
3980  }
3981  
swapStruct(struct method_list32_t & ml)3982  inline void swapStruct(struct method_list32_t &ml) {
3983    sys::swapByteOrder(ml.entsize);
3984    sys::swapByteOrder(ml.count);
3985  }
3986  
swapStruct(struct method64_t & m)3987  inline void swapStruct(struct method64_t &m) {
3988    sys::swapByteOrder(m.name);
3989    sys::swapByteOrder(m.types);
3990    sys::swapByteOrder(m.imp);
3991  }
3992  
swapStruct(struct method32_t & m)3993  inline void swapStruct(struct method32_t &m) {
3994    sys::swapByteOrder(m.name);
3995    sys::swapByteOrder(m.types);
3996    sys::swapByteOrder(m.imp);
3997  }
3998  
swapStruct(struct method_relative_t & m)3999  inline void swapStruct(struct method_relative_t &m) {
4000    sys::swapByteOrder(m.name);
4001    sys::swapByteOrder(m.types);
4002    sys::swapByteOrder(m.imp);
4003  }
4004  
swapStruct(struct protocol_list64_t & pl)4005  inline void swapStruct(struct protocol_list64_t &pl) {
4006    sys::swapByteOrder(pl.count);
4007  }
4008  
swapStruct(struct protocol_list32_t & pl)4009  inline void swapStruct(struct protocol_list32_t &pl) {
4010    sys::swapByteOrder(pl.count);
4011  }
4012  
swapStruct(struct protocol64_t & p)4013  inline void swapStruct(struct protocol64_t &p) {
4014    sys::swapByteOrder(p.isa);
4015    sys::swapByteOrder(p.name);
4016    sys::swapByteOrder(p.protocols);
4017    sys::swapByteOrder(p.instanceMethods);
4018    sys::swapByteOrder(p.classMethods);
4019    sys::swapByteOrder(p.optionalInstanceMethods);
4020    sys::swapByteOrder(p.optionalClassMethods);
4021    sys::swapByteOrder(p.instanceProperties);
4022  }
4023  
swapStruct(struct protocol32_t & p)4024  inline void swapStruct(struct protocol32_t &p) {
4025    sys::swapByteOrder(p.isa);
4026    sys::swapByteOrder(p.name);
4027    sys::swapByteOrder(p.protocols);
4028    sys::swapByteOrder(p.instanceMethods);
4029    sys::swapByteOrder(p.classMethods);
4030    sys::swapByteOrder(p.optionalInstanceMethods);
4031    sys::swapByteOrder(p.optionalClassMethods);
4032    sys::swapByteOrder(p.instanceProperties);
4033  }
4034  
swapStruct(struct ivar_list64_t & il)4035  inline void swapStruct(struct ivar_list64_t &il) {
4036    sys::swapByteOrder(il.entsize);
4037    sys::swapByteOrder(il.count);
4038  }
4039  
swapStruct(struct ivar_list32_t & il)4040  inline void swapStruct(struct ivar_list32_t &il) {
4041    sys::swapByteOrder(il.entsize);
4042    sys::swapByteOrder(il.count);
4043  }
4044  
swapStruct(struct ivar64_t & i)4045  inline void swapStruct(struct ivar64_t &i) {
4046    sys::swapByteOrder(i.offset);
4047    sys::swapByteOrder(i.name);
4048    sys::swapByteOrder(i.type);
4049    sys::swapByteOrder(i.alignment);
4050    sys::swapByteOrder(i.size);
4051  }
4052  
swapStruct(struct ivar32_t & i)4053  inline void swapStruct(struct ivar32_t &i) {
4054    sys::swapByteOrder(i.offset);
4055    sys::swapByteOrder(i.name);
4056    sys::swapByteOrder(i.type);
4057    sys::swapByteOrder(i.alignment);
4058    sys::swapByteOrder(i.size);
4059  }
4060  
swapStruct(struct objc_property_list64 & pl)4061  inline void swapStruct(struct objc_property_list64 &pl) {
4062    sys::swapByteOrder(pl.entsize);
4063    sys::swapByteOrder(pl.count);
4064  }
4065  
swapStruct(struct objc_property_list32 & pl)4066  inline void swapStruct(struct objc_property_list32 &pl) {
4067    sys::swapByteOrder(pl.entsize);
4068    sys::swapByteOrder(pl.count);
4069  }
4070  
swapStruct(struct objc_property64 & op)4071  inline void swapStruct(struct objc_property64 &op) {
4072    sys::swapByteOrder(op.name);
4073    sys::swapByteOrder(op.attributes);
4074  }
4075  
swapStruct(struct objc_property32 & op)4076  inline void swapStruct(struct objc_property32 &op) {
4077    sys::swapByteOrder(op.name);
4078    sys::swapByteOrder(op.attributes);
4079  }
4080  
swapStruct(struct category64_t & c)4081  inline void swapStruct(struct category64_t &c) {
4082    sys::swapByteOrder(c.name);
4083    sys::swapByteOrder(c.cls);
4084    sys::swapByteOrder(c.instanceMethods);
4085    sys::swapByteOrder(c.classMethods);
4086    sys::swapByteOrder(c.protocols);
4087    sys::swapByteOrder(c.instanceProperties);
4088  }
4089  
swapStruct(struct category32_t & c)4090  inline void swapStruct(struct category32_t &c) {
4091    sys::swapByteOrder(c.name);
4092    sys::swapByteOrder(c.cls);
4093    sys::swapByteOrder(c.instanceMethods);
4094    sys::swapByteOrder(c.classMethods);
4095    sys::swapByteOrder(c.protocols);
4096    sys::swapByteOrder(c.instanceProperties);
4097  }
4098  
swapStruct(struct objc_image_info64 & o)4099  inline void swapStruct(struct objc_image_info64 &o) {
4100    sys::swapByteOrder(o.version);
4101    sys::swapByteOrder(o.flags);
4102  }
4103  
swapStruct(struct objc_image_info32 & o)4104  inline void swapStruct(struct objc_image_info32 &o) {
4105    sys::swapByteOrder(o.version);
4106    sys::swapByteOrder(o.flags);
4107  }
4108  
swapStruct(struct imageInfo_t & o)4109  inline void swapStruct(struct imageInfo_t &o) {
4110    sys::swapByteOrder(o.version);
4111    sys::swapByteOrder(o.flags);
4112  }
4113  
swapStruct(struct message_ref64 & mr)4114  inline void swapStruct(struct message_ref64 &mr) {
4115    sys::swapByteOrder(mr.imp);
4116    sys::swapByteOrder(mr.sel);
4117  }
4118  
swapStruct(struct message_ref32 & mr)4119  inline void swapStruct(struct message_ref32 &mr) {
4120    sys::swapByteOrder(mr.imp);
4121    sys::swapByteOrder(mr.sel);
4122  }
4123  
swapStruct(struct objc_module_t & module)4124  inline void swapStruct(struct objc_module_t &module) {
4125    sys::swapByteOrder(module.version);
4126    sys::swapByteOrder(module.size);
4127    sys::swapByteOrder(module.name);
4128    sys::swapByteOrder(module.symtab);
4129  }
4130  
swapStruct(struct objc_symtab_t & symtab)4131  inline void swapStruct(struct objc_symtab_t &symtab) {
4132    sys::swapByteOrder(symtab.sel_ref_cnt);
4133    sys::swapByteOrder(symtab.refs);
4134    sys::swapByteOrder(symtab.cls_def_cnt);
4135    sys::swapByteOrder(symtab.cat_def_cnt);
4136  }
4137  
swapStruct(struct objc_class_t & objc_class)4138  inline void swapStruct(struct objc_class_t &objc_class) {
4139    sys::swapByteOrder(objc_class.isa);
4140    sys::swapByteOrder(objc_class.super_class);
4141    sys::swapByteOrder(objc_class.name);
4142    sys::swapByteOrder(objc_class.version);
4143    sys::swapByteOrder(objc_class.info);
4144    sys::swapByteOrder(objc_class.instance_size);
4145    sys::swapByteOrder(objc_class.ivars);
4146    sys::swapByteOrder(objc_class.methodLists);
4147    sys::swapByteOrder(objc_class.cache);
4148    sys::swapByteOrder(objc_class.protocols);
4149  }
4150  
swapStruct(struct objc_category_t & objc_category)4151  inline void swapStruct(struct objc_category_t &objc_category) {
4152    sys::swapByteOrder(objc_category.category_name);
4153    sys::swapByteOrder(objc_category.class_name);
4154    sys::swapByteOrder(objc_category.instance_methods);
4155    sys::swapByteOrder(objc_category.class_methods);
4156    sys::swapByteOrder(objc_category.protocols);
4157  }
4158  
swapStruct(struct objc_ivar_list_t & objc_ivar_list)4159  inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
4160    sys::swapByteOrder(objc_ivar_list.ivar_count);
4161  }
4162  
swapStruct(struct objc_ivar_t & objc_ivar)4163  inline void swapStruct(struct objc_ivar_t &objc_ivar) {
4164    sys::swapByteOrder(objc_ivar.ivar_name);
4165    sys::swapByteOrder(objc_ivar.ivar_type);
4166    sys::swapByteOrder(objc_ivar.ivar_offset);
4167  }
4168  
swapStruct(struct objc_method_list_t & method_list)4169  inline void swapStruct(struct objc_method_list_t &method_list) {
4170    sys::swapByteOrder(method_list.obsolete);
4171    sys::swapByteOrder(method_list.method_count);
4172  }
4173  
swapStruct(struct objc_method_t & method)4174  inline void swapStruct(struct objc_method_t &method) {
4175    sys::swapByteOrder(method.method_name);
4176    sys::swapByteOrder(method.method_types);
4177    sys::swapByteOrder(method.method_imp);
4178  }
4179  
swapStruct(struct objc_protocol_list_t & protocol_list)4180  inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
4181    sys::swapByteOrder(protocol_list.next);
4182    sys::swapByteOrder(protocol_list.count);
4183  }
4184  
swapStruct(struct objc_protocol_t & protocol)4185  inline void swapStruct(struct objc_protocol_t &protocol) {
4186    sys::swapByteOrder(protocol.isa);
4187    sys::swapByteOrder(protocol.protocol_name);
4188    sys::swapByteOrder(protocol.protocol_list);
4189    sys::swapByteOrder(protocol.instance_methods);
4190    sys::swapByteOrder(protocol.class_methods);
4191  }
4192  
swapStruct(struct objc_method_description_list_t & mdl)4193  inline void swapStruct(struct objc_method_description_list_t &mdl) {
4194    sys::swapByteOrder(mdl.count);
4195  }
4196  
swapStruct(struct objc_method_description_t & md)4197  inline void swapStruct(struct objc_method_description_t &md) {
4198    sys::swapByteOrder(md.name);
4199    sys::swapByteOrder(md.types);
4200  }
4201  
4202  } // namespace
4203  
4204  static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
4205                                                   struct DisassembleInfo *info);
4206  
4207  // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
4208  // to an Objective-C class and returns the class name.  It is also passed the
4209  // address of the pointer, so when the pointer is zero as it can be in an .o
4210  // file, that is used to look for an external relocation entry with a symbol
4211  // name.
get_objc2_64bit_class_name(uint64_t pointer_value,uint64_t ReferenceValue,struct DisassembleInfo * info)4212  static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
4213                                                uint64_t ReferenceValue,
4214                                                struct DisassembleInfo *info) {
4215    const char *r;
4216    uint32_t offset, left;
4217    SectionRef S;
4218  
4219    // The pointer_value can be 0 in an object file and have a relocation
4220    // entry for the class symbol at the ReferenceValue (the address of the
4221    // pointer).
4222    if (pointer_value == 0) {
4223      r = get_pointer_64(ReferenceValue, offset, left, S, info);
4224      if (r == nullptr || left < sizeof(uint64_t))
4225        return nullptr;
4226      uint64_t n_value;
4227      const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4228      if (symbol_name == nullptr)
4229        return nullptr;
4230      const char *class_name = strrchr(symbol_name, '$');
4231      if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
4232        return class_name + 2;
4233      else
4234        return nullptr;
4235    }
4236  
4237    // The case were the pointer_value is non-zero and points to a class defined
4238    // in this Mach-O file.
4239    r = get_pointer_64(pointer_value, offset, left, S, info);
4240    if (r == nullptr || left < sizeof(struct class64_t))
4241      return nullptr;
4242    struct class64_t c;
4243    memcpy(&c, r, sizeof(struct class64_t));
4244    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4245      swapStruct(c);
4246    if (c.data == 0)
4247      return nullptr;
4248    r = get_pointer_64(c.data, offset, left, S, info);
4249    if (r == nullptr || left < sizeof(struct class_ro64_t))
4250      return nullptr;
4251    struct class_ro64_t cro;
4252    memcpy(&cro, r, sizeof(struct class_ro64_t));
4253    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4254      swapStruct(cro);
4255    if (cro.name == 0)
4256      return nullptr;
4257    const char *name = get_pointer_64(cro.name, offset, left, S, info);
4258    return name;
4259  }
4260  
4261  // get_objc2_64bit_cfstring_name is used for disassembly and is passed a
4262  // pointer to a cfstring and returns its name or nullptr.
get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,struct DisassembleInfo * info)4263  static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
4264                                                   struct DisassembleInfo *info) {
4265    const char *r, *name;
4266    uint32_t offset, left;
4267    SectionRef S;
4268    struct cfstring64_t cfs;
4269    uint64_t cfs_characters;
4270  
4271    r = get_pointer_64(ReferenceValue, offset, left, S, info);
4272    if (r == nullptr || left < sizeof(struct cfstring64_t))
4273      return nullptr;
4274    memcpy(&cfs, r, sizeof(struct cfstring64_t));
4275    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4276      swapStruct(cfs);
4277    if (cfs.characters == 0) {
4278      uint64_t n_value;
4279      const char *symbol_name = get_symbol_64(
4280          offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
4281      if (symbol_name == nullptr)
4282        return nullptr;
4283      cfs_characters = n_value;
4284    } else
4285      cfs_characters = cfs.characters;
4286    name = get_pointer_64(cfs_characters, offset, left, S, info);
4287  
4288    return name;
4289  }
4290  
4291  // get_objc2_64bit_selref() is used for disassembly and is passed a the address
4292  // of a pointer to an Objective-C selector reference when the pointer value is
4293  // zero as in a .o file and is likely to have a external relocation entry with
4294  // who's symbol's n_value is the real pointer to the selector name.  If that is
4295  // the case the real pointer to the selector name is returned else 0 is
4296  // returned
get_objc2_64bit_selref(uint64_t ReferenceValue,struct DisassembleInfo * info)4297  static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
4298                                         struct DisassembleInfo *info) {
4299    uint32_t offset, left;
4300    SectionRef S;
4301  
4302    const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
4303    if (r == nullptr || left < sizeof(uint64_t))
4304      return 0;
4305    uint64_t n_value;
4306    const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4307    if (symbol_name == nullptr)
4308      return 0;
4309    return n_value;
4310  }
4311  
get_section(MachOObjectFile * O,const char * segname,const char * sectname)4312  static const SectionRef get_section(MachOObjectFile *O, const char *segname,
4313                                      const char *sectname) {
4314    for (const SectionRef &Section : O->sections()) {
4315      StringRef SectName;
4316      Expected<StringRef> SecNameOrErr = Section.getName();
4317      if (SecNameOrErr)
4318        SectName = *SecNameOrErr;
4319      else
4320        consumeError(SecNameOrErr.takeError());
4321  
4322      DataRefImpl Ref = Section.getRawDataRefImpl();
4323      StringRef SegName = O->getSectionFinalSegmentName(Ref);
4324      if (SegName == segname && SectName == sectname)
4325        return Section;
4326    }
4327    return SectionRef();
4328  }
4329  
4330  static void
walk_pointer_list_64(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint64_t,struct DisassembleInfo * info))4331  walk_pointer_list_64(const char *listname, const SectionRef S,
4332                       MachOObjectFile *O, struct DisassembleInfo *info,
4333                       void (*func)(uint64_t, struct DisassembleInfo *info)) {
4334    if (S == SectionRef())
4335      return;
4336  
4337    StringRef SectName;
4338    Expected<StringRef> SecNameOrErr = S.getName();
4339    if (SecNameOrErr)
4340      SectName = *SecNameOrErr;
4341    else
4342      consumeError(SecNameOrErr.takeError());
4343  
4344    DataRefImpl Ref = S.getRawDataRefImpl();
4345    StringRef SegName = O->getSectionFinalSegmentName(Ref);
4346    outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4347  
4348    StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4349    const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4350  
4351    for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
4352      uint32_t left = S.getSize() - i;
4353      uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
4354      uint64_t p = 0;
4355      memcpy(&p, Contents + i, size);
4356      if (i + sizeof(uint64_t) > S.getSize())
4357        outs() << listname << " list pointer extends past end of (" << SegName
4358               << "," << SectName << ") section\n";
4359      outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
4360  
4361      if (O->isLittleEndian() != sys::IsLittleEndianHost)
4362        sys::swapByteOrder(p);
4363  
4364      uint64_t n_value = 0;
4365      const char *name = get_symbol_64(i, S, info, n_value, p);
4366      if (name == nullptr)
4367        name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
4368  
4369      if (n_value != 0) {
4370        outs() << format("0x%" PRIx64, n_value);
4371        if (p != 0)
4372          outs() << " + " << format("0x%" PRIx64, p);
4373      } else
4374        outs() << format("0x%" PRIx64, p);
4375      if (name != nullptr)
4376        outs() << " " << name;
4377      outs() << "\n";
4378  
4379      p += n_value;
4380      if (func)
4381        func(p, info);
4382    }
4383  }
4384  
4385  static void
walk_pointer_list_32(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint32_t,struct DisassembleInfo * info))4386  walk_pointer_list_32(const char *listname, const SectionRef S,
4387                       MachOObjectFile *O, struct DisassembleInfo *info,
4388                       void (*func)(uint32_t, struct DisassembleInfo *info)) {
4389    if (S == SectionRef())
4390      return;
4391  
4392    StringRef SectName = unwrapOrError(S.getName(), O->getFileName());
4393    DataRefImpl Ref = S.getRawDataRefImpl();
4394    StringRef SegName = O->getSectionFinalSegmentName(Ref);
4395    outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4396  
4397    StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4398    const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4399  
4400    for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
4401      uint32_t left = S.getSize() - i;
4402      uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
4403      uint32_t p = 0;
4404      memcpy(&p, Contents + i, size);
4405      if (i + sizeof(uint32_t) > S.getSize())
4406        outs() << listname << " list pointer extends past end of (" << SegName
4407               << "," << SectName << ") section\n";
4408      uint32_t Address = S.getAddress() + i;
4409      outs() << format("%08" PRIx32, Address) << " ";
4410  
4411      if (O->isLittleEndian() != sys::IsLittleEndianHost)
4412        sys::swapByteOrder(p);
4413      outs() << format("0x%" PRIx32, p);
4414  
4415      const char *name = get_symbol_32(i, S, info, p);
4416      if (name != nullptr)
4417        outs() << " " << name;
4418      outs() << "\n";
4419  
4420      if (func)
4421        func(p, info);
4422    }
4423  }
4424  
print_layout_map(const char * layout_map,uint32_t left)4425  static void print_layout_map(const char *layout_map, uint32_t left) {
4426    if (layout_map == nullptr)
4427      return;
4428    outs() << "                layout map: ";
4429    do {
4430      outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
4431      left--;
4432      layout_map++;
4433    } while (*layout_map != '\0' && left != 0);
4434    outs() << "\n";
4435  }
4436  
print_layout_map64(uint64_t p,struct DisassembleInfo * info)4437  static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
4438    uint32_t offset, left;
4439    SectionRef S;
4440    const char *layout_map;
4441  
4442    if (p == 0)
4443      return;
4444    layout_map = get_pointer_64(p, offset, left, S, info);
4445    print_layout_map(layout_map, left);
4446  }
4447  
print_layout_map32(uint32_t p,struct DisassembleInfo * info)4448  static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
4449    uint32_t offset, left;
4450    SectionRef S;
4451    const char *layout_map;
4452  
4453    if (p == 0)
4454      return;
4455    layout_map = get_pointer_32(p, offset, left, S, info);
4456    print_layout_map(layout_map, left);
4457  }
4458  
print_relative_method_list(uint32_t structSizeAndFlags,uint32_t structCount,uint64_t p,struct DisassembleInfo * info,const char * indent,uint32_t pointerBits)4459  static void print_relative_method_list(uint32_t structSizeAndFlags,
4460                                         uint32_t structCount, uint64_t p,
4461                                         struct DisassembleInfo *info,
4462                                         const char *indent,
4463                                         uint32_t pointerBits) {
4464    struct method_relative_t m;
4465    const char *r, *name;
4466    uint32_t offset, xoffset, left, i;
4467    SectionRef S, xS;
4468  
4469    assert(((structSizeAndFlags & ML_HAS_RELATIVE_PTRS) != 0) &&
4470           "expected structSizeAndFlags to have ML_HAS_RELATIVE_PTRS flag");
4471  
4472    outs() << indent << "\t\t   entsize "
4473           << (structSizeAndFlags & ML_ENTSIZE_MASK) << " (relative) \n";
4474    outs() << indent << "\t\t     count " << structCount << "\n";
4475  
4476    for (i = 0; i < structCount; i++) {
4477      r = get_pointer_64(p, offset, left, S, info);
4478      memset(&m, '\0', sizeof(struct method_relative_t));
4479      if (left < sizeof(struct method_relative_t)) {
4480        memcpy(&m, r, left);
4481        outs() << indent << "   (method_t extends past the end of the section)\n";
4482      } else
4483        memcpy(&m, r, sizeof(struct method_relative_t));
4484      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4485        swapStruct(m);
4486  
4487      outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
4488      uint64_t relNameRefVA = p + offsetof(struct method_relative_t, name);
4489      uint64_t absNameRefVA = relNameRefVA + m.name;
4490      outs() << " (" << format("0x%" PRIx32, absNameRefVA) << ")";
4491  
4492      // since this is a relative list, absNameRefVA is the address of the
4493      // __objc_selrefs entry, so a pointer, not the actual name
4494      const char *nameRefPtr =
4495          get_pointer_64(absNameRefVA, xoffset, left, xS, info);
4496      if (nameRefPtr) {
4497        uint32_t pointerSize = pointerBits / CHAR_BIT;
4498        if (left < pointerSize)
4499          outs() << indent << " (nameRefPtr extends past the end of the section)";
4500        else {
4501          if (pointerSize == 64) {
4502            uint64_t nameOff_64 = *reinterpret_cast<const uint64_t *>(nameRefPtr);
4503            if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4504              sys::swapByteOrder(nameOff_64);
4505            name = get_pointer_64(nameOff_64, xoffset, left, xS, info);
4506          } else {
4507            uint32_t nameOff_32 = *reinterpret_cast<const uint32_t *>(nameRefPtr);
4508            if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4509              sys::swapByteOrder(nameOff_32);
4510            name = get_pointer_32(nameOff_32, xoffset, left, xS, info);
4511          }
4512          if (name != nullptr)
4513            outs() << format(" %.*s", left, name);
4514        }
4515      }
4516      outs() << "\n";
4517  
4518      outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
4519      uint64_t relTypesVA = p + offsetof(struct method_relative_t, types);
4520      uint64_t absTypesVA = relTypesVA + m.types;
4521      outs() << " (" << format("0x%" PRIx32, absTypesVA) << ")";
4522      name = get_pointer_32(absTypesVA, xoffset, left, xS, info);
4523      if (name != nullptr)
4524        outs() << format(" %.*s", left, name);
4525      outs() << "\n";
4526  
4527      outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
4528      uint64_t relImpVA = p + offsetof(struct method_relative_t, imp);
4529      uint64_t absImpVA = relImpVA + m.imp;
4530      outs() << " (" << format("0x%" PRIx32, absImpVA) << ")";
4531      name = GuessSymbolName(absImpVA, info->AddrMap);
4532      if (name != nullptr)
4533        outs() << " " << name;
4534      outs() << "\n";
4535  
4536      p += sizeof(struct method_relative_t);
4537      offset += sizeof(struct method_relative_t);
4538    }
4539  }
4540  
print_method_list64_t(uint64_t p,struct DisassembleInfo * info,const char * indent)4541  static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
4542                                    const char *indent) {
4543    struct method_list64_t ml;
4544    struct method64_t m;
4545    const char *r;
4546    uint32_t offset, xoffset, left, i;
4547    SectionRef S, xS;
4548    const char *name, *sym_name;
4549    uint64_t n_value;
4550  
4551    r = get_pointer_64(p, offset, left, S, info);
4552    if (r == nullptr)
4553      return;
4554    memset(&ml, '\0', sizeof(struct method_list64_t));
4555    if (left < sizeof(struct method_list64_t)) {
4556      memcpy(&ml, r, left);
4557      outs() << "   (method_list_t entends past the end of the section)\n";
4558    } else
4559      memcpy(&ml, r, sizeof(struct method_list64_t));
4560    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4561      swapStruct(ml);
4562    p += sizeof(struct method_list64_t);
4563  
4564    if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) {
4565      print_relative_method_list(ml.entsize, ml.count, p, info, indent,
4566                                 /*pointerBits=*/64);
4567      return;
4568    }
4569  
4570    outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4571    outs() << indent << "\t\t     count " << ml.count << "\n";
4572  
4573    offset += sizeof(struct method_list64_t);
4574    for (i = 0; i < ml.count; i++) {
4575      r = get_pointer_64(p, offset, left, S, info);
4576      if (r == nullptr)
4577        return;
4578      memset(&m, '\0', sizeof(struct method64_t));
4579      if (left < sizeof(struct method64_t)) {
4580        memcpy(&m, r, left);
4581        outs() << indent << "   (method_t extends past the end of the section)\n";
4582      } else
4583        memcpy(&m, r, sizeof(struct method64_t));
4584      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4585        swapStruct(m);
4586  
4587      outs() << indent << "\t\t      name ";
4588      sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
4589                               info, n_value, m.name);
4590      if (n_value != 0) {
4591        if (info->verbose && sym_name != nullptr)
4592          outs() << sym_name;
4593        else
4594          outs() << format("0x%" PRIx64, n_value);
4595        if (m.name != 0)
4596          outs() << " + " << format("0x%" PRIx64, m.name);
4597      } else
4598        outs() << format("0x%" PRIx64, m.name);
4599      name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
4600      if (name != nullptr)
4601        outs() << format(" %.*s", left, name);
4602      outs() << "\n";
4603  
4604      outs() << indent << "\t\t     types ";
4605      sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
4606                               info, n_value, m.types);
4607      if (n_value != 0) {
4608        if (info->verbose && sym_name != nullptr)
4609          outs() << sym_name;
4610        else
4611          outs() << format("0x%" PRIx64, n_value);
4612        if (m.types != 0)
4613          outs() << " + " << format("0x%" PRIx64, m.types);
4614      } else
4615        outs() << format("0x%" PRIx64, m.types);
4616      name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
4617      if (name != nullptr)
4618        outs() << format(" %.*s", left, name);
4619      outs() << "\n";
4620  
4621      outs() << indent << "\t\t       imp ";
4622      name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
4623                           n_value, m.imp);
4624      if (info->verbose && name == nullptr) {
4625        if (n_value != 0) {
4626          outs() << format("0x%" PRIx64, n_value) << " ";
4627          if (m.imp != 0)
4628            outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
4629        } else
4630          outs() << format("0x%" PRIx64, m.imp) << " ";
4631      }
4632      if (name != nullptr)
4633        outs() << name;
4634      outs() << "\n";
4635  
4636      p += sizeof(struct method64_t);
4637      offset += sizeof(struct method64_t);
4638    }
4639  }
4640  
print_method_list32_t(uint64_t p,struct DisassembleInfo * info,const char * indent)4641  static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
4642                                    const char *indent) {
4643    struct method_list32_t ml;
4644    struct method32_t m;
4645    const char *r, *name;
4646    uint32_t offset, xoffset, left, i;
4647    SectionRef S, xS;
4648  
4649    r = get_pointer_32(p, offset, left, S, info);
4650    if (r == nullptr)
4651      return;
4652    memset(&ml, '\0', sizeof(struct method_list32_t));
4653    if (left < sizeof(struct method_list32_t)) {
4654      memcpy(&ml, r, left);
4655      outs() << "   (method_list_t entends past the end of the section)\n";
4656    } else
4657      memcpy(&ml, r, sizeof(struct method_list32_t));
4658    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4659      swapStruct(ml);
4660    p += sizeof(struct method_list32_t);
4661  
4662    if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) {
4663      print_relative_method_list(ml.entsize, ml.count, p, info, indent,
4664                                 /*pointerBits=*/32);
4665      return;
4666    }
4667  
4668    outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4669    outs() << indent << "\t\t     count " << ml.count << "\n";
4670  
4671    offset += sizeof(struct method_list32_t);
4672    for (i = 0; i < ml.count; i++) {
4673      r = get_pointer_32(p, offset, left, S, info);
4674      if (r == nullptr)
4675        return;
4676      memset(&m, '\0', sizeof(struct method32_t));
4677      if (left < sizeof(struct method32_t)) {
4678        memcpy(&ml, r, left);
4679        outs() << indent << "   (method_t entends past the end of the section)\n";
4680      } else
4681        memcpy(&m, r, sizeof(struct method32_t));
4682      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4683        swapStruct(m);
4684  
4685      outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
4686      name = get_pointer_32(m.name, xoffset, left, xS, info);
4687      if (name != nullptr)
4688        outs() << format(" %.*s", left, name);
4689      outs() << "\n";
4690  
4691      outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
4692      name = get_pointer_32(m.types, xoffset, left, xS, info);
4693      if (name != nullptr)
4694        outs() << format(" %.*s", left, name);
4695      outs() << "\n";
4696  
4697      outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
4698      name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
4699                           m.imp);
4700      if (name != nullptr)
4701        outs() << " " << name;
4702      outs() << "\n";
4703  
4704      p += sizeof(struct method32_t);
4705      offset += sizeof(struct method32_t);
4706    }
4707  }
4708  
print_method_list(uint32_t p,struct DisassembleInfo * info)4709  static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
4710    uint32_t offset, left, xleft;
4711    SectionRef S;
4712    struct objc_method_list_t method_list;
4713    struct objc_method_t method;
4714    const char *r, *methods, *name, *SymbolName;
4715    int32_t i;
4716  
4717    r = get_pointer_32(p, offset, left, S, info, true);
4718    if (r == nullptr)
4719      return true;
4720  
4721    outs() << "\n";
4722    if (left > sizeof(struct objc_method_list_t)) {
4723      memcpy(&method_list, r, sizeof(struct objc_method_list_t));
4724    } else {
4725      outs() << "\t\t objc_method_list extends past end of the section\n";
4726      memset(&method_list, '\0', sizeof(struct objc_method_list_t));
4727      memcpy(&method_list, r, left);
4728    }
4729    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4730      swapStruct(method_list);
4731  
4732    outs() << "\t\t         obsolete "
4733           << format("0x%08" PRIx32, method_list.obsolete) << "\n";
4734    outs() << "\t\t     method_count " << method_list.method_count << "\n";
4735  
4736    methods = r + sizeof(struct objc_method_list_t);
4737    for (i = 0; i < method_list.method_count; i++) {
4738      if ((i + 1) * sizeof(struct objc_method_t) > left) {
4739        outs() << "\t\t remaining method's extend past the of the section\n";
4740        break;
4741      }
4742      memcpy(&method, methods + i * sizeof(struct objc_method_t),
4743             sizeof(struct objc_method_t));
4744      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4745        swapStruct(method);
4746  
4747      outs() << "\t\t      method_name "
4748             << format("0x%08" PRIx32, method.method_name);
4749      if (info->verbose) {
4750        name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
4751        if (name != nullptr)
4752          outs() << format(" %.*s", xleft, name);
4753        else
4754          outs() << " (not in an __OBJC section)";
4755      }
4756      outs() << "\n";
4757  
4758      outs() << "\t\t     method_types "
4759             << format("0x%08" PRIx32, method.method_types);
4760      if (info->verbose) {
4761        name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
4762        if (name != nullptr)
4763          outs() << format(" %.*s", xleft, name);
4764        else
4765          outs() << " (not in an __OBJC section)";
4766      }
4767      outs() << "\n";
4768  
4769      outs() << "\t\t       method_imp "
4770             << format("0x%08" PRIx32, method.method_imp) << " ";
4771      if (info->verbose) {
4772        SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
4773        if (SymbolName != nullptr)
4774          outs() << SymbolName;
4775      }
4776      outs() << "\n";
4777    }
4778    return false;
4779  }
4780  
print_protocol_list64_t(uint64_t p,struct DisassembleInfo * info)4781  static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
4782    struct protocol_list64_t pl;
4783    uint64_t q, n_value;
4784    struct protocol64_t pc;
4785    const char *r;
4786    uint32_t offset, xoffset, left, i;
4787    SectionRef S, xS;
4788    const char *name, *sym_name;
4789  
4790    r = get_pointer_64(p, offset, left, S, info);
4791    if (r == nullptr)
4792      return;
4793    memset(&pl, '\0', sizeof(struct protocol_list64_t));
4794    if (left < sizeof(struct protocol_list64_t)) {
4795      memcpy(&pl, r, left);
4796      outs() << "   (protocol_list_t entends past the end of the section)\n";
4797    } else
4798      memcpy(&pl, r, sizeof(struct protocol_list64_t));
4799    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4800      swapStruct(pl);
4801    outs() << "                      count " << pl.count << "\n";
4802  
4803    p += sizeof(struct protocol_list64_t);
4804    offset += sizeof(struct protocol_list64_t);
4805    for (i = 0; i < pl.count; i++) {
4806      r = get_pointer_64(p, offset, left, S, info);
4807      if (r == nullptr)
4808        return;
4809      q = 0;
4810      if (left < sizeof(uint64_t)) {
4811        memcpy(&q, r, left);
4812        outs() << "   (protocol_t * entends past the end of the section)\n";
4813      } else
4814        memcpy(&q, r, sizeof(uint64_t));
4815      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4816        sys::swapByteOrder(q);
4817  
4818      outs() << "\t\t      list[" << i << "] ";
4819      sym_name = get_symbol_64(offset, S, info, n_value, q);
4820      if (n_value != 0) {
4821        if (info->verbose && sym_name != nullptr)
4822          outs() << sym_name;
4823        else
4824          outs() << format("0x%" PRIx64, n_value);
4825        if (q != 0)
4826          outs() << " + " << format("0x%" PRIx64, q);
4827      } else
4828        outs() << format("0x%" PRIx64, q);
4829      outs() << " (struct protocol_t *)\n";
4830  
4831      r = get_pointer_64(q + n_value, offset, left, S, info);
4832      if (r == nullptr)
4833        return;
4834      memset(&pc, '\0', sizeof(struct protocol64_t));
4835      if (left < sizeof(struct protocol64_t)) {
4836        memcpy(&pc, r, left);
4837        outs() << "   (protocol_t entends past the end of the section)\n";
4838      } else
4839        memcpy(&pc, r, sizeof(struct protocol64_t));
4840      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4841        swapStruct(pc);
4842  
4843      outs() << "\t\t\t      isa " << format("0x%" PRIx64, pc.isa) << "\n";
4844  
4845      outs() << "\t\t\t     name ";
4846      sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
4847                               info, n_value, pc.name);
4848      if (n_value != 0) {
4849        if (info->verbose && sym_name != nullptr)
4850          outs() << sym_name;
4851        else
4852          outs() << format("0x%" PRIx64, n_value);
4853        if (pc.name != 0)
4854          outs() << " + " << format("0x%" PRIx64, pc.name);
4855      } else
4856        outs() << format("0x%" PRIx64, pc.name);
4857      name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
4858      if (name != nullptr)
4859        outs() << format(" %.*s", left, name);
4860      outs() << "\n";
4861  
4862      outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
4863  
4864      outs() << "\t\t  instanceMethods ";
4865      sym_name =
4866          get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
4867                        S, info, n_value, pc.instanceMethods);
4868      if (n_value != 0) {
4869        if (info->verbose && sym_name != nullptr)
4870          outs() << sym_name;
4871        else
4872          outs() << format("0x%" PRIx64, n_value);
4873        if (pc.instanceMethods != 0)
4874          outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
4875      } else
4876        outs() << format("0x%" PRIx64, pc.instanceMethods);
4877      outs() << " (struct method_list_t *)\n";
4878      if (pc.instanceMethods + n_value != 0)
4879        print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
4880  
4881      outs() << "\t\t     classMethods ";
4882      sym_name =
4883          get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
4884                        info, n_value, pc.classMethods);
4885      if (n_value != 0) {
4886        if (info->verbose && sym_name != nullptr)
4887          outs() << sym_name;
4888        else
4889          outs() << format("0x%" PRIx64, n_value);
4890        if (pc.classMethods != 0)
4891          outs() << " + " << format("0x%" PRIx64, pc.classMethods);
4892      } else
4893        outs() << format("0x%" PRIx64, pc.classMethods);
4894      outs() << " (struct method_list_t *)\n";
4895      if (pc.classMethods + n_value != 0)
4896        print_method_list64_t(pc.classMethods + n_value, info, "\t");
4897  
4898      outs() << "\t  optionalInstanceMethods "
4899             << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
4900      outs() << "\t     optionalClassMethods "
4901             << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
4902      outs() << "\t       instanceProperties "
4903             << format("0x%" PRIx64, pc.instanceProperties) << "\n";
4904  
4905      p += sizeof(uint64_t);
4906      offset += sizeof(uint64_t);
4907    }
4908  }
4909  
print_protocol_list32_t(uint32_t p,struct DisassembleInfo * info)4910  static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
4911    struct protocol_list32_t pl;
4912    uint32_t q;
4913    struct protocol32_t pc;
4914    const char *r;
4915    uint32_t offset, xoffset, left, i;
4916    SectionRef S, xS;
4917    const char *name;
4918  
4919    r = get_pointer_32(p, offset, left, S, info);
4920    if (r == nullptr)
4921      return;
4922    memset(&pl, '\0', sizeof(struct protocol_list32_t));
4923    if (left < sizeof(struct protocol_list32_t)) {
4924      memcpy(&pl, r, left);
4925      outs() << "   (protocol_list_t entends past the end of the section)\n";
4926    } else
4927      memcpy(&pl, r, sizeof(struct protocol_list32_t));
4928    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4929      swapStruct(pl);
4930    outs() << "                      count " << pl.count << "\n";
4931  
4932    p += sizeof(struct protocol_list32_t);
4933    offset += sizeof(struct protocol_list32_t);
4934    for (i = 0; i < pl.count; i++) {
4935      r = get_pointer_32(p, offset, left, S, info);
4936      if (r == nullptr)
4937        return;
4938      q = 0;
4939      if (left < sizeof(uint32_t)) {
4940        memcpy(&q, r, left);
4941        outs() << "   (protocol_t * entends past the end of the section)\n";
4942      } else
4943        memcpy(&q, r, sizeof(uint32_t));
4944      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4945        sys::swapByteOrder(q);
4946      outs() << "\t\t      list[" << i << "] " << format("0x%" PRIx32, q)
4947             << " (struct protocol_t *)\n";
4948      r = get_pointer_32(q, offset, left, S, info);
4949      if (r == nullptr)
4950        return;
4951      memset(&pc, '\0', sizeof(struct protocol32_t));
4952      if (left < sizeof(struct protocol32_t)) {
4953        memcpy(&pc, r, left);
4954        outs() << "   (protocol_t entends past the end of the section)\n";
4955      } else
4956        memcpy(&pc, r, sizeof(struct protocol32_t));
4957      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4958        swapStruct(pc);
4959      outs() << "\t\t\t      isa " << format("0x%" PRIx32, pc.isa) << "\n";
4960      outs() << "\t\t\t     name " << format("0x%" PRIx32, pc.name);
4961      name = get_pointer_32(pc.name, xoffset, left, xS, info);
4962      if (name != nullptr)
4963        outs() << format(" %.*s", left, name);
4964      outs() << "\n";
4965      outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
4966      outs() << "\t\t  instanceMethods "
4967             << format("0x%" PRIx32, pc.instanceMethods)
4968             << " (struct method_list_t *)\n";
4969      if (pc.instanceMethods != 0)
4970        print_method_list32_t(pc.instanceMethods, info, "\t");
4971      outs() << "\t\t     classMethods " << format("0x%" PRIx32, pc.classMethods)
4972             << " (struct method_list_t *)\n";
4973      if (pc.classMethods != 0)
4974        print_method_list32_t(pc.classMethods, info, "\t");
4975      outs() << "\t  optionalInstanceMethods "
4976             << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
4977      outs() << "\t     optionalClassMethods "
4978             << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
4979      outs() << "\t       instanceProperties "
4980             << format("0x%" PRIx32, pc.instanceProperties) << "\n";
4981      p += sizeof(uint32_t);
4982      offset += sizeof(uint32_t);
4983    }
4984  }
4985  
print_indent(uint32_t indent)4986  static void print_indent(uint32_t indent) {
4987    for (uint32_t i = 0; i < indent;) {
4988      if (indent - i >= 8) {
4989        outs() << "\t";
4990        i += 8;
4991      } else {
4992        for (uint32_t j = i; j < indent; j++)
4993          outs() << " ";
4994        return;
4995      }
4996    }
4997  }
4998  
print_method_description_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)4999  static bool print_method_description_list(uint32_t p, uint32_t indent,
5000                                            struct DisassembleInfo *info) {
5001    uint32_t offset, left, xleft;
5002    SectionRef S;
5003    struct objc_method_description_list_t mdl;
5004    struct objc_method_description_t md;
5005    const char *r, *list, *name;
5006    int32_t i;
5007  
5008    r = get_pointer_32(p, offset, left, S, info, true);
5009    if (r == nullptr)
5010      return true;
5011  
5012    outs() << "\n";
5013    if (left > sizeof(struct objc_method_description_list_t)) {
5014      memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
5015    } else {
5016      print_indent(indent);
5017      outs() << " objc_method_description_list extends past end of the section\n";
5018      memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
5019      memcpy(&mdl, r, left);
5020    }
5021    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5022      swapStruct(mdl);
5023  
5024    print_indent(indent);
5025    outs() << "        count " << mdl.count << "\n";
5026  
5027    list = r + sizeof(struct objc_method_description_list_t);
5028    for (i = 0; i < mdl.count; i++) {
5029      if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
5030        print_indent(indent);
5031        outs() << " remaining list entries extend past the of the section\n";
5032        break;
5033      }
5034      print_indent(indent);
5035      outs() << "        list[" << i << "]\n";
5036      memcpy(&md, list + i * sizeof(struct objc_method_description_t),
5037             sizeof(struct objc_method_description_t));
5038      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5039        swapStruct(md);
5040  
5041      print_indent(indent);
5042      outs() << "             name " << format("0x%08" PRIx32, md.name);
5043      if (info->verbose) {
5044        name = get_pointer_32(md.name, offset, xleft, S, info, true);
5045        if (name != nullptr)
5046          outs() << format(" %.*s", xleft, name);
5047        else
5048          outs() << " (not in an __OBJC section)";
5049      }
5050      outs() << "\n";
5051  
5052      print_indent(indent);
5053      outs() << "            types " << format("0x%08" PRIx32, md.types);
5054      if (info->verbose) {
5055        name = get_pointer_32(md.types, offset, xleft, S, info, true);
5056        if (name != nullptr)
5057          outs() << format(" %.*s", xleft, name);
5058        else
5059          outs() << " (not in an __OBJC section)";
5060      }
5061      outs() << "\n";
5062    }
5063    return false;
5064  }
5065  
5066  static bool print_protocol_list(uint32_t p, uint32_t indent,
5067                                  struct DisassembleInfo *info);
5068  
print_protocol(uint32_t p,uint32_t indent,struct DisassembleInfo * info)5069  static bool print_protocol(uint32_t p, uint32_t indent,
5070                             struct DisassembleInfo *info) {
5071    uint32_t offset, left;
5072    SectionRef S;
5073    struct objc_protocol_t protocol;
5074    const char *r, *name;
5075  
5076    r = get_pointer_32(p, offset, left, S, info, true);
5077    if (r == nullptr)
5078      return true;
5079  
5080    outs() << "\n";
5081    if (left >= sizeof(struct objc_protocol_t)) {
5082      memcpy(&protocol, r, sizeof(struct objc_protocol_t));
5083    } else {
5084      print_indent(indent);
5085      outs() << "            Protocol extends past end of the section\n";
5086      memset(&protocol, '\0', sizeof(struct objc_protocol_t));
5087      memcpy(&protocol, r, left);
5088    }
5089    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5090      swapStruct(protocol);
5091  
5092    print_indent(indent);
5093    outs() << "              isa " << format("0x%08" PRIx32, protocol.isa)
5094           << "\n";
5095  
5096    print_indent(indent);
5097    outs() << "    protocol_name "
5098           << format("0x%08" PRIx32, protocol.protocol_name);
5099    if (info->verbose) {
5100      name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
5101      if (name != nullptr)
5102        outs() << format(" %.*s", left, name);
5103      else
5104        outs() << " (not in an __OBJC section)";
5105    }
5106    outs() << "\n";
5107  
5108    print_indent(indent);
5109    outs() << "    protocol_list "
5110           << format("0x%08" PRIx32, protocol.protocol_list);
5111    if (print_protocol_list(protocol.protocol_list, indent + 4, info))
5112      outs() << " (not in an __OBJC section)\n";
5113  
5114    print_indent(indent);
5115    outs() << " instance_methods "
5116           << format("0x%08" PRIx32, protocol.instance_methods);
5117    if (print_method_description_list(protocol.instance_methods, indent, info))
5118      outs() << " (not in an __OBJC section)\n";
5119  
5120    print_indent(indent);
5121    outs() << "    class_methods "
5122           << format("0x%08" PRIx32, protocol.class_methods);
5123    if (print_method_description_list(protocol.class_methods, indent, info))
5124      outs() << " (not in an __OBJC section)\n";
5125  
5126    return false;
5127  }
5128  
print_protocol_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)5129  static bool print_protocol_list(uint32_t p, uint32_t indent,
5130                                  struct DisassembleInfo *info) {
5131    uint32_t offset, left, l;
5132    SectionRef S;
5133    struct objc_protocol_list_t protocol_list;
5134    const char *r, *list;
5135    int32_t i;
5136  
5137    r = get_pointer_32(p, offset, left, S, info, true);
5138    if (r == nullptr)
5139      return true;
5140  
5141    outs() << "\n";
5142    if (left > sizeof(struct objc_protocol_list_t)) {
5143      memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
5144    } else {
5145      outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
5146      memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
5147      memcpy(&protocol_list, r, left);
5148    }
5149    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5150      swapStruct(protocol_list);
5151  
5152    print_indent(indent);
5153    outs() << "         next " << format("0x%08" PRIx32, protocol_list.next)
5154           << "\n";
5155    print_indent(indent);
5156    outs() << "        count " << protocol_list.count << "\n";
5157  
5158    list = r + sizeof(struct objc_protocol_list_t);
5159    for (i = 0; i < protocol_list.count; i++) {
5160      if ((i + 1) * sizeof(uint32_t) > left) {
5161        outs() << "\t\t remaining list entries extend past the of the section\n";
5162        break;
5163      }
5164      memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
5165      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5166        sys::swapByteOrder(l);
5167  
5168      print_indent(indent);
5169      outs() << "      list[" << i << "] " << format("0x%08" PRIx32, l);
5170      if (print_protocol(l, indent, info))
5171        outs() << "(not in an __OBJC section)\n";
5172    }
5173    return false;
5174  }
5175  
print_ivar_list64_t(uint64_t p,struct DisassembleInfo * info)5176  static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
5177    struct ivar_list64_t il;
5178    struct ivar64_t i;
5179    const char *r;
5180    uint32_t offset, xoffset, left, j;
5181    SectionRef S, xS;
5182    const char *name, *sym_name, *ivar_offset_p;
5183    uint64_t ivar_offset, n_value;
5184  
5185    r = get_pointer_64(p, offset, left, S, info);
5186    if (r == nullptr)
5187      return;
5188    memset(&il, '\0', sizeof(struct ivar_list64_t));
5189    if (left < sizeof(struct ivar_list64_t)) {
5190      memcpy(&il, r, left);
5191      outs() << "   (ivar_list_t entends past the end of the section)\n";
5192    } else
5193      memcpy(&il, r, sizeof(struct ivar_list64_t));
5194    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5195      swapStruct(il);
5196    outs() << "                    entsize " << il.entsize << "\n";
5197    outs() << "                      count " << il.count << "\n";
5198  
5199    p += sizeof(struct ivar_list64_t);
5200    offset += sizeof(struct ivar_list64_t);
5201    for (j = 0; j < il.count; j++) {
5202      r = get_pointer_64(p, offset, left, S, info);
5203      if (r == nullptr)
5204        return;
5205      memset(&i, '\0', sizeof(struct ivar64_t));
5206      if (left < sizeof(struct ivar64_t)) {
5207        memcpy(&i, r, left);
5208        outs() << "   (ivar_t entends past the end of the section)\n";
5209      } else
5210        memcpy(&i, r, sizeof(struct ivar64_t));
5211      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5212        swapStruct(i);
5213  
5214      outs() << "\t\t\t   offset ";
5215      sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
5216                               info, n_value, i.offset);
5217      if (n_value != 0) {
5218        if (info->verbose && sym_name != nullptr)
5219          outs() << sym_name;
5220        else
5221          outs() << format("0x%" PRIx64, n_value);
5222        if (i.offset != 0)
5223          outs() << " + " << format("0x%" PRIx64, i.offset);
5224      } else
5225        outs() << format("0x%" PRIx64, i.offset);
5226      ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
5227      if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5228        memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5229        if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5230          sys::swapByteOrder(ivar_offset);
5231        outs() << " " << ivar_offset << "\n";
5232      } else
5233        outs() << "\n";
5234  
5235      outs() << "\t\t\t     name ";
5236      sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
5237                               n_value, i.name);
5238      if (n_value != 0) {
5239        if (info->verbose && sym_name != nullptr)
5240          outs() << sym_name;
5241        else
5242          outs() << format("0x%" PRIx64, n_value);
5243        if (i.name != 0)
5244          outs() << " + " << format("0x%" PRIx64, i.name);
5245      } else
5246        outs() << format("0x%" PRIx64, i.name);
5247      name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
5248      if (name != nullptr)
5249        outs() << format(" %.*s", left, name);
5250      outs() << "\n";
5251  
5252      outs() << "\t\t\t     type ";
5253      sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
5254                               n_value, i.name);
5255      name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
5256      if (n_value != 0) {
5257        if (info->verbose && sym_name != nullptr)
5258          outs() << sym_name;
5259        else
5260          outs() << format("0x%" PRIx64, n_value);
5261        if (i.type != 0)
5262          outs() << " + " << format("0x%" PRIx64, i.type);
5263      } else
5264        outs() << format("0x%" PRIx64, i.type);
5265      if (name != nullptr)
5266        outs() << format(" %.*s", left, name);
5267      outs() << "\n";
5268  
5269      outs() << "\t\t\talignment " << i.alignment << "\n";
5270      outs() << "\t\t\t     size " << i.size << "\n";
5271  
5272      p += sizeof(struct ivar64_t);
5273      offset += sizeof(struct ivar64_t);
5274    }
5275  }
5276  
print_ivar_list32_t(uint32_t p,struct DisassembleInfo * info)5277  static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
5278    struct ivar_list32_t il;
5279    struct ivar32_t i;
5280    const char *r;
5281    uint32_t offset, xoffset, left, j;
5282    SectionRef S, xS;
5283    const char *name, *ivar_offset_p;
5284    uint32_t ivar_offset;
5285  
5286    r = get_pointer_32(p, offset, left, S, info);
5287    if (r == nullptr)
5288      return;
5289    memset(&il, '\0', sizeof(struct ivar_list32_t));
5290    if (left < sizeof(struct ivar_list32_t)) {
5291      memcpy(&il, r, left);
5292      outs() << "   (ivar_list_t entends past the end of the section)\n";
5293    } else
5294      memcpy(&il, r, sizeof(struct ivar_list32_t));
5295    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5296      swapStruct(il);
5297    outs() << "                    entsize " << il.entsize << "\n";
5298    outs() << "                      count " << il.count << "\n";
5299  
5300    p += sizeof(struct ivar_list32_t);
5301    offset += sizeof(struct ivar_list32_t);
5302    for (j = 0; j < il.count; j++) {
5303      r = get_pointer_32(p, offset, left, S, info);
5304      if (r == nullptr)
5305        return;
5306      memset(&i, '\0', sizeof(struct ivar32_t));
5307      if (left < sizeof(struct ivar32_t)) {
5308        memcpy(&i, r, left);
5309        outs() << "   (ivar_t entends past the end of the section)\n";
5310      } else
5311        memcpy(&i, r, sizeof(struct ivar32_t));
5312      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5313        swapStruct(i);
5314  
5315      outs() << "\t\t\t   offset " << format("0x%" PRIx32, i.offset);
5316      ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
5317      if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5318        memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5319        if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5320          sys::swapByteOrder(ivar_offset);
5321        outs() << " " << ivar_offset << "\n";
5322      } else
5323        outs() << "\n";
5324  
5325      outs() << "\t\t\t     name " << format("0x%" PRIx32, i.name);
5326      name = get_pointer_32(i.name, xoffset, left, xS, info);
5327      if (name != nullptr)
5328        outs() << format(" %.*s", left, name);
5329      outs() << "\n";
5330  
5331      outs() << "\t\t\t     type " << format("0x%" PRIx32, i.type);
5332      name = get_pointer_32(i.type, xoffset, left, xS, info);
5333      if (name != nullptr)
5334        outs() << format(" %.*s", left, name);
5335      outs() << "\n";
5336  
5337      outs() << "\t\t\talignment " << i.alignment << "\n";
5338      outs() << "\t\t\t     size " << i.size << "\n";
5339  
5340      p += sizeof(struct ivar32_t);
5341      offset += sizeof(struct ivar32_t);
5342    }
5343  }
5344  
print_objc_property_list64(uint64_t p,struct DisassembleInfo * info)5345  static void print_objc_property_list64(uint64_t p,
5346                                         struct DisassembleInfo *info) {
5347    struct objc_property_list64 opl;
5348    struct objc_property64 op;
5349    const char *r;
5350    uint32_t offset, xoffset, left, j;
5351    SectionRef S, xS;
5352    const char *name, *sym_name;
5353    uint64_t n_value;
5354  
5355    r = get_pointer_64(p, offset, left, S, info);
5356    if (r == nullptr)
5357      return;
5358    memset(&opl, '\0', sizeof(struct objc_property_list64));
5359    if (left < sizeof(struct objc_property_list64)) {
5360      memcpy(&opl, r, left);
5361      outs() << "   (objc_property_list entends past the end of the section)\n";
5362    } else
5363      memcpy(&opl, r, sizeof(struct objc_property_list64));
5364    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5365      swapStruct(opl);
5366    outs() << "                    entsize " << opl.entsize << "\n";
5367    outs() << "                      count " << opl.count << "\n";
5368  
5369    p += sizeof(struct objc_property_list64);
5370    offset += sizeof(struct objc_property_list64);
5371    for (j = 0; j < opl.count; j++) {
5372      r = get_pointer_64(p, offset, left, S, info);
5373      if (r == nullptr)
5374        return;
5375      memset(&op, '\0', sizeof(struct objc_property64));
5376      if (left < sizeof(struct objc_property64)) {
5377        memcpy(&op, r, left);
5378        outs() << "   (objc_property entends past the end of the section)\n";
5379      } else
5380        memcpy(&op, r, sizeof(struct objc_property64));
5381      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5382        swapStruct(op);
5383  
5384      outs() << "\t\t\t     name ";
5385      sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
5386                               info, n_value, op.name);
5387      if (n_value != 0) {
5388        if (info->verbose && sym_name != nullptr)
5389          outs() << sym_name;
5390        else
5391          outs() << format("0x%" PRIx64, n_value);
5392        if (op.name != 0)
5393          outs() << " + " << format("0x%" PRIx64, op.name);
5394      } else
5395        outs() << format("0x%" PRIx64, op.name);
5396      name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
5397      if (name != nullptr)
5398        outs() << format(" %.*s", left, name);
5399      outs() << "\n";
5400  
5401      outs() << "\t\t\tattributes ";
5402      sym_name =
5403          get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
5404                        info, n_value, op.attributes);
5405      if (n_value != 0) {
5406        if (info->verbose && sym_name != nullptr)
5407          outs() << sym_name;
5408        else
5409          outs() << format("0x%" PRIx64, n_value);
5410        if (op.attributes != 0)
5411          outs() << " + " << format("0x%" PRIx64, op.attributes);
5412      } else
5413        outs() << format("0x%" PRIx64, op.attributes);
5414      name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
5415      if (name != nullptr)
5416        outs() << format(" %.*s", left, name);
5417      outs() << "\n";
5418  
5419      p += sizeof(struct objc_property64);
5420      offset += sizeof(struct objc_property64);
5421    }
5422  }
5423  
print_objc_property_list32(uint32_t p,struct DisassembleInfo * info)5424  static void print_objc_property_list32(uint32_t p,
5425                                         struct DisassembleInfo *info) {
5426    struct objc_property_list32 opl;
5427    struct objc_property32 op;
5428    const char *r;
5429    uint32_t offset, xoffset, left, j;
5430    SectionRef S, xS;
5431    const char *name;
5432  
5433    r = get_pointer_32(p, offset, left, S, info);
5434    if (r == nullptr)
5435      return;
5436    memset(&opl, '\0', sizeof(struct objc_property_list32));
5437    if (left < sizeof(struct objc_property_list32)) {
5438      memcpy(&opl, r, left);
5439      outs() << "   (objc_property_list entends past the end of the section)\n";
5440    } else
5441      memcpy(&opl, r, sizeof(struct objc_property_list32));
5442    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5443      swapStruct(opl);
5444    outs() << "                    entsize " << opl.entsize << "\n";
5445    outs() << "                      count " << opl.count << "\n";
5446  
5447    p += sizeof(struct objc_property_list32);
5448    offset += sizeof(struct objc_property_list32);
5449    for (j = 0; j < opl.count; j++) {
5450      r = get_pointer_32(p, offset, left, S, info);
5451      if (r == nullptr)
5452        return;
5453      memset(&op, '\0', sizeof(struct objc_property32));
5454      if (left < sizeof(struct objc_property32)) {
5455        memcpy(&op, r, left);
5456        outs() << "   (objc_property entends past the end of the section)\n";
5457      } else
5458        memcpy(&op, r, sizeof(struct objc_property32));
5459      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5460        swapStruct(op);
5461  
5462      outs() << "\t\t\t     name " << format("0x%" PRIx32, op.name);
5463      name = get_pointer_32(op.name, xoffset, left, xS, info);
5464      if (name != nullptr)
5465        outs() << format(" %.*s", left, name);
5466      outs() << "\n";
5467  
5468      outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
5469      name = get_pointer_32(op.attributes, xoffset, left, xS, info);
5470      if (name != nullptr)
5471        outs() << format(" %.*s", left, name);
5472      outs() << "\n";
5473  
5474      p += sizeof(struct objc_property32);
5475      offset += sizeof(struct objc_property32);
5476    }
5477  }
5478  
print_class_ro64_t(uint64_t p,struct DisassembleInfo * info,bool & is_meta_class)5479  static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
5480                                 bool &is_meta_class) {
5481    struct class_ro64_t cro;
5482    const char *r;
5483    uint32_t offset, xoffset, left;
5484    SectionRef S, xS;
5485    const char *name, *sym_name;
5486    uint64_t n_value;
5487  
5488    r = get_pointer_64(p, offset, left, S, info);
5489    if (r == nullptr || left < sizeof(struct class_ro64_t))
5490      return false;
5491    memcpy(&cro, r, sizeof(struct class_ro64_t));
5492    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5493      swapStruct(cro);
5494    outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5495    if (cro.flags & RO_META)
5496      outs() << " RO_META";
5497    if (cro.flags & RO_ROOT)
5498      outs() << " RO_ROOT";
5499    if (cro.flags & RO_HAS_CXX_STRUCTORS)
5500      outs() << " RO_HAS_CXX_STRUCTORS";
5501    outs() << "\n";
5502    outs() << "            instanceStart " << cro.instanceStart << "\n";
5503    outs() << "             instanceSize " << cro.instanceSize << "\n";
5504    outs() << "                 reserved " << format("0x%" PRIx32, cro.reserved)
5505           << "\n";
5506    outs() << "               ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
5507           << "\n";
5508    print_layout_map64(cro.ivarLayout, info);
5509  
5510    outs() << "                     name ";
5511    sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
5512                             info, n_value, cro.name);
5513    if (n_value != 0) {
5514      if (info->verbose && sym_name != nullptr)
5515        outs() << sym_name;
5516      else
5517        outs() << format("0x%" PRIx64, n_value);
5518      if (cro.name != 0)
5519        outs() << " + " << format("0x%" PRIx64, cro.name);
5520    } else
5521      outs() << format("0x%" PRIx64, cro.name);
5522    name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
5523    if (name != nullptr)
5524      outs() << format(" %.*s", left, name);
5525    outs() << "\n";
5526  
5527    outs() << "              baseMethods ";
5528    sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
5529                             S, info, n_value, cro.baseMethods);
5530    if (n_value != 0) {
5531      if (info->verbose && sym_name != nullptr)
5532        outs() << sym_name;
5533      else
5534        outs() << format("0x%" PRIx64, n_value);
5535      if (cro.baseMethods != 0)
5536        outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
5537    } else
5538      outs() << format("0x%" PRIx64, cro.baseMethods);
5539    outs() << " (struct method_list_t *)\n";
5540    if (cro.baseMethods + n_value != 0)
5541      print_method_list64_t(cro.baseMethods + n_value, info, "");
5542  
5543    outs() << "            baseProtocols ";
5544    sym_name =
5545        get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
5546                      info, n_value, cro.baseProtocols);
5547    if (n_value != 0) {
5548      if (info->verbose && sym_name != nullptr)
5549        outs() << sym_name;
5550      else
5551        outs() << format("0x%" PRIx64, n_value);
5552      if (cro.baseProtocols != 0)
5553        outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
5554    } else
5555      outs() << format("0x%" PRIx64, cro.baseProtocols);
5556    outs() << "\n";
5557    if (cro.baseProtocols + n_value != 0)
5558      print_protocol_list64_t(cro.baseProtocols + n_value, info);
5559  
5560    outs() << "                    ivars ";
5561    sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
5562                             info, n_value, cro.ivars);
5563    if (n_value != 0) {
5564      if (info->verbose && sym_name != nullptr)
5565        outs() << sym_name;
5566      else
5567        outs() << format("0x%" PRIx64, n_value);
5568      if (cro.ivars != 0)
5569        outs() << " + " << format("0x%" PRIx64, cro.ivars);
5570    } else
5571      outs() << format("0x%" PRIx64, cro.ivars);
5572    outs() << "\n";
5573    if (cro.ivars + n_value != 0)
5574      print_ivar_list64_t(cro.ivars + n_value, info);
5575  
5576    outs() << "           weakIvarLayout ";
5577    sym_name =
5578        get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
5579                      info, n_value, cro.weakIvarLayout);
5580    if (n_value != 0) {
5581      if (info->verbose && sym_name != nullptr)
5582        outs() << sym_name;
5583      else
5584        outs() << format("0x%" PRIx64, n_value);
5585      if (cro.weakIvarLayout != 0)
5586        outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
5587    } else
5588      outs() << format("0x%" PRIx64, cro.weakIvarLayout);
5589    outs() << "\n";
5590    print_layout_map64(cro.weakIvarLayout + n_value, info);
5591  
5592    outs() << "           baseProperties ";
5593    sym_name =
5594        get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
5595                      info, n_value, cro.baseProperties);
5596    if (n_value != 0) {
5597      if (info->verbose && sym_name != nullptr)
5598        outs() << sym_name;
5599      else
5600        outs() << format("0x%" PRIx64, n_value);
5601      if (cro.baseProperties != 0)
5602        outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
5603    } else
5604      outs() << format("0x%" PRIx64, cro.baseProperties);
5605    outs() << "\n";
5606    if (cro.baseProperties + n_value != 0)
5607      print_objc_property_list64(cro.baseProperties + n_value, info);
5608  
5609    is_meta_class = (cro.flags & RO_META) != 0;
5610    return true;
5611  }
5612  
print_class_ro32_t(uint32_t p,struct DisassembleInfo * info,bool & is_meta_class)5613  static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
5614                                 bool &is_meta_class) {
5615    struct class_ro32_t cro;
5616    const char *r;
5617    uint32_t offset, xoffset, left;
5618    SectionRef S, xS;
5619    const char *name;
5620  
5621    r = get_pointer_32(p, offset, left, S, info);
5622    if (r == nullptr)
5623      return false;
5624    memset(&cro, '\0', sizeof(struct class_ro32_t));
5625    if (left < sizeof(struct class_ro32_t)) {
5626      memcpy(&cro, r, left);
5627      outs() << "   (class_ro_t entends past the end of the section)\n";
5628    } else
5629      memcpy(&cro, r, sizeof(struct class_ro32_t));
5630    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5631      swapStruct(cro);
5632    outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5633    if (cro.flags & RO_META)
5634      outs() << " RO_META";
5635    if (cro.flags & RO_ROOT)
5636      outs() << " RO_ROOT";
5637    if (cro.flags & RO_HAS_CXX_STRUCTORS)
5638      outs() << " RO_HAS_CXX_STRUCTORS";
5639    outs() << "\n";
5640    outs() << "            instanceStart " << cro.instanceStart << "\n";
5641    outs() << "             instanceSize " << cro.instanceSize << "\n";
5642    outs() << "               ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
5643           << "\n";
5644    print_layout_map32(cro.ivarLayout, info);
5645  
5646    outs() << "                     name " << format("0x%" PRIx32, cro.name);
5647    name = get_pointer_32(cro.name, xoffset, left, xS, info);
5648    if (name != nullptr)
5649      outs() << format(" %.*s", left, name);
5650    outs() << "\n";
5651  
5652    outs() << "              baseMethods "
5653           << format("0x%" PRIx32, cro.baseMethods)
5654           << " (struct method_list_t *)\n";
5655    if (cro.baseMethods != 0)
5656      print_method_list32_t(cro.baseMethods, info, "");
5657  
5658    outs() << "            baseProtocols "
5659           << format("0x%" PRIx32, cro.baseProtocols) << "\n";
5660    if (cro.baseProtocols != 0)
5661      print_protocol_list32_t(cro.baseProtocols, info);
5662    outs() << "                    ivars " << format("0x%" PRIx32, cro.ivars)
5663           << "\n";
5664    if (cro.ivars != 0)
5665      print_ivar_list32_t(cro.ivars, info);
5666    outs() << "           weakIvarLayout "
5667           << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
5668    print_layout_map32(cro.weakIvarLayout, info);
5669    outs() << "           baseProperties "
5670           << format("0x%" PRIx32, cro.baseProperties) << "\n";
5671    if (cro.baseProperties != 0)
5672      print_objc_property_list32(cro.baseProperties, info);
5673    is_meta_class = (cro.flags & RO_META) != 0;
5674    return true;
5675  }
5676  
print_class64_t(uint64_t p,struct DisassembleInfo * info)5677  static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
5678    struct class64_t c;
5679    const char *r;
5680    uint32_t offset, left;
5681    SectionRef S;
5682    const char *name;
5683    uint64_t isa_n_value, n_value;
5684  
5685    r = get_pointer_64(p, offset, left, S, info);
5686    if (r == nullptr || left < sizeof(struct class64_t))
5687      return;
5688    memcpy(&c, r, sizeof(struct class64_t));
5689    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5690      swapStruct(c);
5691  
5692    outs() << "           isa " << format("0x%" PRIx64, c.isa);
5693    name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
5694                         isa_n_value, c.isa);
5695    if (name != nullptr)
5696      outs() << " " << name;
5697    outs() << "\n";
5698  
5699    outs() << "    superclass " << format("0x%" PRIx64, c.superclass);
5700    name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
5701                         n_value, c.superclass);
5702    if (name != nullptr)
5703      outs() << " " << name;
5704    else {
5705      name = get_dyld_bind_info_symbolname(S.getAddress() +
5706               offset + offsetof(struct class64_t, superclass), info);
5707      if (name != nullptr)
5708        outs() << " " << name;
5709    }
5710    outs() << "\n";
5711  
5712    outs() << "         cache " << format("0x%" PRIx64, c.cache);
5713    name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
5714                         n_value, c.cache);
5715    if (name != nullptr)
5716      outs() << " " << name;
5717    outs() << "\n";
5718  
5719    outs() << "        vtable " << format("0x%" PRIx64, c.vtable);
5720    name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
5721                         n_value, c.vtable);
5722    if (name != nullptr)
5723      outs() << " " << name;
5724    outs() << "\n";
5725  
5726    name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
5727                         n_value, c.data);
5728    outs() << "          data ";
5729    if (n_value != 0) {
5730      if (info->verbose && name != nullptr)
5731        outs() << name;
5732      else
5733        outs() << format("0x%" PRIx64, n_value);
5734      if (c.data != 0)
5735        outs() << " + " << format("0x%" PRIx64, c.data);
5736    } else
5737      outs() << format("0x%" PRIx64, c.data);
5738    outs() << " (struct class_ro_t *)";
5739  
5740    // This is a Swift class if some of the low bits of the pointer are set.
5741    if ((c.data + n_value) & 0x7)
5742      outs() << " Swift class";
5743    outs() << "\n";
5744    bool is_meta_class;
5745    if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
5746      return;
5747  
5748    if (!is_meta_class &&
5749        c.isa + isa_n_value != p &&
5750        c.isa + isa_n_value != 0 &&
5751        info->depth < 100) {
5752        info->depth++;
5753        outs() << "Meta Class\n";
5754        print_class64_t(c.isa + isa_n_value, info);
5755    }
5756  }
5757  
print_class32_t(uint32_t p,struct DisassembleInfo * info)5758  static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
5759    struct class32_t c;
5760    const char *r;
5761    uint32_t offset, left;
5762    SectionRef S;
5763    const char *name;
5764  
5765    r = get_pointer_32(p, offset, left, S, info);
5766    if (r == nullptr)
5767      return;
5768    memset(&c, '\0', sizeof(struct class32_t));
5769    if (left < sizeof(struct class32_t)) {
5770      memcpy(&c, r, left);
5771      outs() << "   (class_t entends past the end of the section)\n";
5772    } else
5773      memcpy(&c, r, sizeof(struct class32_t));
5774    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5775      swapStruct(c);
5776  
5777    outs() << "           isa " << format("0x%" PRIx32, c.isa);
5778    name =
5779        get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
5780    if (name != nullptr)
5781      outs() << " " << name;
5782    outs() << "\n";
5783  
5784    outs() << "    superclass " << format("0x%" PRIx32, c.superclass);
5785    name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
5786                         c.superclass);
5787    if (name != nullptr)
5788      outs() << " " << name;
5789    outs() << "\n";
5790  
5791    outs() << "         cache " << format("0x%" PRIx32, c.cache);
5792    name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
5793                         c.cache);
5794    if (name != nullptr)
5795      outs() << " " << name;
5796    outs() << "\n";
5797  
5798    outs() << "        vtable " << format("0x%" PRIx32, c.vtable);
5799    name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
5800                         c.vtable);
5801    if (name != nullptr)
5802      outs() << " " << name;
5803    outs() << "\n";
5804  
5805    name =
5806        get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
5807    outs() << "          data " << format("0x%" PRIx32, c.data)
5808           << " (struct class_ro_t *)";
5809  
5810    // This is a Swift class if some of the low bits of the pointer are set.
5811    if (c.data & 0x3)
5812      outs() << " Swift class";
5813    outs() << "\n";
5814    bool is_meta_class;
5815    if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
5816      return;
5817  
5818    if (!is_meta_class) {
5819      outs() << "Meta Class\n";
5820      print_class32_t(c.isa, info);
5821    }
5822  }
5823  
print_objc_class_t(struct objc_class_t * objc_class,struct DisassembleInfo * info)5824  static void print_objc_class_t(struct objc_class_t *objc_class,
5825                                 struct DisassembleInfo *info) {
5826    uint32_t offset, left, xleft;
5827    const char *name, *p, *ivar_list;
5828    SectionRef S;
5829    int32_t i;
5830    struct objc_ivar_list_t objc_ivar_list;
5831    struct objc_ivar_t ivar;
5832  
5833    outs() << "\t\t      isa " << format("0x%08" PRIx32, objc_class->isa);
5834    if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
5835      name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
5836      if (name != nullptr)
5837        outs() << format(" %.*s", left, name);
5838      else
5839        outs() << " (not in an __OBJC section)";
5840    }
5841    outs() << "\n";
5842  
5843    outs() << "\t      super_class "
5844           << format("0x%08" PRIx32, objc_class->super_class);
5845    if (info->verbose) {
5846      name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
5847      if (name != nullptr)
5848        outs() << format(" %.*s", left, name);
5849      else
5850        outs() << " (not in an __OBJC section)";
5851    }
5852    outs() << "\n";
5853  
5854    outs() << "\t\t     name " << format("0x%08" PRIx32, objc_class->name);
5855    if (info->verbose) {
5856      name = get_pointer_32(objc_class->name, offset, left, S, info, true);
5857      if (name != nullptr)
5858        outs() << format(" %.*s", left, name);
5859      else
5860        outs() << " (not in an __OBJC section)";
5861    }
5862    outs() << "\n";
5863  
5864    outs() << "\t\t  version " << format("0x%08" PRIx32, objc_class->version)
5865           << "\n";
5866  
5867    outs() << "\t\t     info " << format("0x%08" PRIx32, objc_class->info);
5868    if (info->verbose) {
5869      if (CLS_GETINFO(objc_class, CLS_CLASS))
5870        outs() << " CLS_CLASS";
5871      else if (CLS_GETINFO(objc_class, CLS_META))
5872        outs() << " CLS_META";
5873    }
5874    outs() << "\n";
5875  
5876    outs() << "\t    instance_size "
5877           << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
5878  
5879    p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
5880    outs() << "\t\t    ivars " << format("0x%08" PRIx32, objc_class->ivars);
5881    if (p != nullptr) {
5882      if (left > sizeof(struct objc_ivar_list_t)) {
5883        outs() << "\n";
5884        memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
5885      } else {
5886        outs() << " (entends past the end of the section)\n";
5887        memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
5888        memcpy(&objc_ivar_list, p, left);
5889      }
5890      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5891        swapStruct(objc_ivar_list);
5892      outs() << "\t\t       ivar_count " << objc_ivar_list.ivar_count << "\n";
5893      ivar_list = p + sizeof(struct objc_ivar_list_t);
5894      for (i = 0; i < objc_ivar_list.ivar_count; i++) {
5895        if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
5896          outs() << "\t\t remaining ivar's extend past the of the section\n";
5897          break;
5898        }
5899        memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
5900               sizeof(struct objc_ivar_t));
5901        if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5902          swapStruct(ivar);
5903  
5904        outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
5905        if (info->verbose) {
5906          name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
5907          if (name != nullptr)
5908            outs() << format(" %.*s", xleft, name);
5909          else
5910            outs() << " (not in an __OBJC section)";
5911        }
5912        outs() << "\n";
5913  
5914        outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
5915        if (info->verbose) {
5916          name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
5917          if (name != nullptr)
5918            outs() << format(" %.*s", xleft, name);
5919          else
5920            outs() << " (not in an __OBJC section)";
5921        }
5922        outs() << "\n";
5923  
5924        outs() << "\t\t      ivar_offset "
5925               << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
5926      }
5927    } else {
5928      outs() << " (not in an __OBJC section)\n";
5929    }
5930  
5931    outs() << "\t\t  methods " << format("0x%08" PRIx32, objc_class->methodLists);
5932    if (print_method_list(objc_class->methodLists, info))
5933      outs() << " (not in an __OBJC section)\n";
5934  
5935    outs() << "\t\t    cache " << format("0x%08" PRIx32, objc_class->cache)
5936           << "\n";
5937  
5938    outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
5939    if (print_protocol_list(objc_class->protocols, 16, info))
5940      outs() << " (not in an __OBJC section)\n";
5941  }
5942  
print_objc_objc_category_t(struct objc_category_t * objc_category,struct DisassembleInfo * info)5943  static void print_objc_objc_category_t(struct objc_category_t *objc_category,
5944                                         struct DisassembleInfo *info) {
5945    uint32_t offset, left;
5946    const char *name;
5947    SectionRef S;
5948  
5949    outs() << "\t       category name "
5950           << format("0x%08" PRIx32, objc_category->category_name);
5951    if (info->verbose) {
5952      name = get_pointer_32(objc_category->category_name, offset, left, S, info,
5953                            true);
5954      if (name != nullptr)
5955        outs() << format(" %.*s", left, name);
5956      else
5957        outs() << " (not in an __OBJC section)";
5958    }
5959    outs() << "\n";
5960  
5961    outs() << "\t\t  class name "
5962           << format("0x%08" PRIx32, objc_category->class_name);
5963    if (info->verbose) {
5964      name =
5965          get_pointer_32(objc_category->class_name, offset, left, S, info, true);
5966      if (name != nullptr)
5967        outs() << format(" %.*s", left, name);
5968      else
5969        outs() << " (not in an __OBJC section)";
5970    }
5971    outs() << "\n";
5972  
5973    outs() << "\t    instance methods "
5974           << format("0x%08" PRIx32, objc_category->instance_methods);
5975    if (print_method_list(objc_category->instance_methods, info))
5976      outs() << " (not in an __OBJC section)\n";
5977  
5978    outs() << "\t       class methods "
5979           << format("0x%08" PRIx32, objc_category->class_methods);
5980    if (print_method_list(objc_category->class_methods, info))
5981      outs() << " (not in an __OBJC section)\n";
5982  }
5983  
print_category64_t(uint64_t p,struct DisassembleInfo * info)5984  static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
5985    struct category64_t c;
5986    const char *r;
5987    uint32_t offset, xoffset, left;
5988    SectionRef S, xS;
5989    const char *name, *sym_name;
5990    uint64_t n_value;
5991  
5992    r = get_pointer_64(p, offset, left, S, info);
5993    if (r == nullptr)
5994      return;
5995    memset(&c, '\0', sizeof(struct category64_t));
5996    if (left < sizeof(struct category64_t)) {
5997      memcpy(&c, r, left);
5998      outs() << "   (category_t entends past the end of the section)\n";
5999    } else
6000      memcpy(&c, r, sizeof(struct category64_t));
6001    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6002      swapStruct(c);
6003  
6004    outs() << "              name ";
6005    sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
6006                             info, n_value, c.name);
6007    if (n_value != 0) {
6008      if (info->verbose && sym_name != nullptr)
6009        outs() << sym_name;
6010      else
6011        outs() << format("0x%" PRIx64, n_value);
6012      if (c.name != 0)
6013        outs() << " + " << format("0x%" PRIx64, c.name);
6014    } else
6015      outs() << format("0x%" PRIx64, c.name);
6016    name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
6017    if (name != nullptr)
6018      outs() << format(" %.*s", left, name);
6019    outs() << "\n";
6020  
6021    outs() << "               cls ";
6022    sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
6023                             n_value, c.cls);
6024    if (n_value != 0) {
6025      if (info->verbose && sym_name != nullptr)
6026        outs() << sym_name;
6027      else
6028        outs() << format("0x%" PRIx64, n_value);
6029      if (c.cls != 0)
6030        outs() << " + " << format("0x%" PRIx64, c.cls);
6031    } else
6032      outs() << format("0x%" PRIx64, c.cls);
6033    outs() << "\n";
6034    if (c.cls + n_value != 0)
6035      print_class64_t(c.cls + n_value, info);
6036  
6037    outs() << "   instanceMethods ";
6038    sym_name =
6039        get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
6040                      info, n_value, c.instanceMethods);
6041    if (n_value != 0) {
6042      if (info->verbose && sym_name != nullptr)
6043        outs() << sym_name;
6044      else
6045        outs() << format("0x%" PRIx64, n_value);
6046      if (c.instanceMethods != 0)
6047        outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
6048    } else
6049      outs() << format("0x%" PRIx64, c.instanceMethods);
6050    outs() << "\n";
6051    if (c.instanceMethods + n_value != 0)
6052      print_method_list64_t(c.instanceMethods + n_value, info, "");
6053  
6054    outs() << "      classMethods ";
6055    sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
6056                             S, info, n_value, c.classMethods);
6057    if (n_value != 0) {
6058      if (info->verbose && sym_name != nullptr)
6059        outs() << sym_name;
6060      else
6061        outs() << format("0x%" PRIx64, n_value);
6062      if (c.classMethods != 0)
6063        outs() << " + " << format("0x%" PRIx64, c.classMethods);
6064    } else
6065      outs() << format("0x%" PRIx64, c.classMethods);
6066    outs() << "\n";
6067    if (c.classMethods + n_value != 0)
6068      print_method_list64_t(c.classMethods + n_value, info, "");
6069  
6070    outs() << "         protocols ";
6071    sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
6072                             info, n_value, c.protocols);
6073    if (n_value != 0) {
6074      if (info->verbose && sym_name != nullptr)
6075        outs() << sym_name;
6076      else
6077        outs() << format("0x%" PRIx64, n_value);
6078      if (c.protocols != 0)
6079        outs() << " + " << format("0x%" PRIx64, c.protocols);
6080    } else
6081      outs() << format("0x%" PRIx64, c.protocols);
6082    outs() << "\n";
6083    if (c.protocols + n_value != 0)
6084      print_protocol_list64_t(c.protocols + n_value, info);
6085  
6086    outs() << "instanceProperties ";
6087    sym_name =
6088        get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
6089                      S, info, n_value, c.instanceProperties);
6090    if (n_value != 0) {
6091      if (info->verbose && sym_name != nullptr)
6092        outs() << sym_name;
6093      else
6094        outs() << format("0x%" PRIx64, n_value);
6095      if (c.instanceProperties != 0)
6096        outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
6097    } else
6098      outs() << format("0x%" PRIx64, c.instanceProperties);
6099    outs() << "\n";
6100    if (c.instanceProperties + n_value != 0)
6101      print_objc_property_list64(c.instanceProperties + n_value, info);
6102  }
6103  
print_category32_t(uint32_t p,struct DisassembleInfo * info)6104  static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
6105    struct category32_t c;
6106    const char *r;
6107    uint32_t offset, left;
6108    SectionRef S, xS;
6109    const char *name;
6110  
6111    r = get_pointer_32(p, offset, left, S, info);
6112    if (r == nullptr)
6113      return;
6114    memset(&c, '\0', sizeof(struct category32_t));
6115    if (left < sizeof(struct category32_t)) {
6116      memcpy(&c, r, left);
6117      outs() << "   (category_t entends past the end of the section)\n";
6118    } else
6119      memcpy(&c, r, sizeof(struct category32_t));
6120    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6121      swapStruct(c);
6122  
6123    outs() << "              name " << format("0x%" PRIx32, c.name);
6124    name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
6125                         c.name);
6126    if (name)
6127      outs() << " " << name;
6128    outs() << "\n";
6129  
6130    outs() << "               cls " << format("0x%" PRIx32, c.cls) << "\n";
6131    if (c.cls != 0)
6132      print_class32_t(c.cls, info);
6133    outs() << "   instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
6134           << "\n";
6135    if (c.instanceMethods != 0)
6136      print_method_list32_t(c.instanceMethods, info, "");
6137    outs() << "      classMethods " << format("0x%" PRIx32, c.classMethods)
6138           << "\n";
6139    if (c.classMethods != 0)
6140      print_method_list32_t(c.classMethods, info, "");
6141    outs() << "         protocols " << format("0x%" PRIx32, c.protocols) << "\n";
6142    if (c.protocols != 0)
6143      print_protocol_list32_t(c.protocols, info);
6144    outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
6145           << "\n";
6146    if (c.instanceProperties != 0)
6147      print_objc_property_list32(c.instanceProperties, info);
6148  }
6149  
print_message_refs64(SectionRef S,struct DisassembleInfo * info)6150  static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
6151    uint32_t i, left, offset, xoffset;
6152    uint64_t p, n_value;
6153    struct message_ref64 mr;
6154    const char *name, *sym_name;
6155    const char *r;
6156    SectionRef xS;
6157  
6158    if (S == SectionRef())
6159      return;
6160  
6161    StringRef SectName;
6162    Expected<StringRef> SecNameOrErr = S.getName();
6163    if (SecNameOrErr)
6164      SectName = *SecNameOrErr;
6165    else
6166      consumeError(SecNameOrErr.takeError());
6167  
6168    DataRefImpl Ref = S.getRawDataRefImpl();
6169    StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6170    outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6171    offset = 0;
6172    for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6173      p = S.getAddress() + i;
6174      r = get_pointer_64(p, offset, left, S, info);
6175      if (r == nullptr)
6176        return;
6177      memset(&mr, '\0', sizeof(struct message_ref64));
6178      if (left < sizeof(struct message_ref64)) {
6179        memcpy(&mr, r, left);
6180        outs() << "   (message_ref entends past the end of the section)\n";
6181      } else
6182        memcpy(&mr, r, sizeof(struct message_ref64));
6183      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6184        swapStruct(mr);
6185  
6186      outs() << "  imp ";
6187      name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
6188                           n_value, mr.imp);
6189      if (n_value != 0) {
6190        outs() << format("0x%" PRIx64, n_value) << " ";
6191        if (mr.imp != 0)
6192          outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
6193      } else
6194        outs() << format("0x%" PRIx64, mr.imp) << " ";
6195      if (name != nullptr)
6196        outs() << " " << name;
6197      outs() << "\n";
6198  
6199      outs() << "  sel ";
6200      sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
6201                               info, n_value, mr.sel);
6202      if (n_value != 0) {
6203        if (info->verbose && sym_name != nullptr)
6204          outs() << sym_name;
6205        else
6206          outs() << format("0x%" PRIx64, n_value);
6207        if (mr.sel != 0)
6208          outs() << " + " << format("0x%" PRIx64, mr.sel);
6209      } else
6210        outs() << format("0x%" PRIx64, mr.sel);
6211      name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
6212      if (name != nullptr)
6213        outs() << format(" %.*s", left, name);
6214      outs() << "\n";
6215  
6216      offset += sizeof(struct message_ref64);
6217    }
6218  }
6219  
print_message_refs32(SectionRef S,struct DisassembleInfo * info)6220  static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
6221    uint32_t i, left, offset, xoffset, p;
6222    struct message_ref32 mr;
6223    const char *name, *r;
6224    SectionRef xS;
6225  
6226    if (S == SectionRef())
6227      return;
6228  
6229    StringRef SectName;
6230    Expected<StringRef> SecNameOrErr = S.getName();
6231    if (SecNameOrErr)
6232      SectName = *SecNameOrErr;
6233    else
6234      consumeError(SecNameOrErr.takeError());
6235  
6236    DataRefImpl Ref = S.getRawDataRefImpl();
6237    StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6238    outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6239    offset = 0;
6240    for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6241      p = S.getAddress() + i;
6242      r = get_pointer_32(p, offset, left, S, info);
6243      if (r == nullptr)
6244        return;
6245      memset(&mr, '\0', sizeof(struct message_ref32));
6246      if (left < sizeof(struct message_ref32)) {
6247        memcpy(&mr, r, left);
6248        outs() << "   (message_ref entends past the end of the section)\n";
6249      } else
6250        memcpy(&mr, r, sizeof(struct message_ref32));
6251      if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6252        swapStruct(mr);
6253  
6254      outs() << "  imp " << format("0x%" PRIx32, mr.imp);
6255      name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
6256                           mr.imp);
6257      if (name != nullptr)
6258        outs() << " " << name;
6259      outs() << "\n";
6260  
6261      outs() << "  sel " << format("0x%" PRIx32, mr.sel);
6262      name = get_pointer_32(mr.sel, xoffset, left, xS, info);
6263      if (name != nullptr)
6264        outs() << " " << name;
6265      outs() << "\n";
6266  
6267      offset += sizeof(struct message_ref32);
6268    }
6269  }
6270  
print_image_info64(SectionRef S,struct DisassembleInfo * info)6271  static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
6272    uint32_t left, offset, swift_version;
6273    uint64_t p;
6274    struct objc_image_info64 o;
6275    const char *r;
6276  
6277    if (S == SectionRef())
6278      return;
6279  
6280    StringRef SectName;
6281    Expected<StringRef> SecNameOrErr = S.getName();
6282    if (SecNameOrErr)
6283      SectName = *SecNameOrErr;
6284    else
6285      consumeError(SecNameOrErr.takeError());
6286  
6287    DataRefImpl Ref = S.getRawDataRefImpl();
6288    StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6289    outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6290    p = S.getAddress();
6291    r = get_pointer_64(p, offset, left, S, info);
6292    if (r == nullptr)
6293      return;
6294    memset(&o, '\0', sizeof(struct objc_image_info64));
6295    if (left < sizeof(struct objc_image_info64)) {
6296      memcpy(&o, r, left);
6297      outs() << "   (objc_image_info entends past the end of the section)\n";
6298    } else
6299      memcpy(&o, r, sizeof(struct objc_image_info64));
6300    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6301      swapStruct(o);
6302    outs() << "  version " << o.version << "\n";
6303    outs() << "    flags " << format("0x%" PRIx32, o.flags);
6304    if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6305      outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6306    if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6307      outs() << " OBJC_IMAGE_SUPPORTS_GC";
6308    if (o.flags & OBJC_IMAGE_IS_SIMULATED)
6309      outs() << " OBJC_IMAGE_IS_SIMULATED";
6310    if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES)
6311      outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
6312    swift_version = (o.flags >> 8) & 0xff;
6313    if (swift_version != 0) {
6314      if (swift_version == 1)
6315        outs() << " Swift 1.0";
6316      else if (swift_version == 2)
6317        outs() << " Swift 1.1";
6318      else if(swift_version == 3)
6319        outs() << " Swift 2.0";
6320      else if(swift_version == 4)
6321        outs() << " Swift 3.0";
6322      else if(swift_version == 5)
6323        outs() << " Swift 4.0";
6324      else if(swift_version == 6)
6325        outs() << " Swift 4.1/Swift 4.2";
6326      else if(swift_version == 7)
6327        outs() << " Swift 5 or later";
6328      else
6329        outs() << " unknown future Swift version (" << swift_version << ")";
6330    }
6331    outs() << "\n";
6332  }
6333  
print_image_info32(SectionRef S,struct DisassembleInfo * info)6334  static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
6335    uint32_t left, offset, swift_version, p;
6336    struct objc_image_info32 o;
6337    const char *r;
6338  
6339    if (S == SectionRef())
6340      return;
6341  
6342    StringRef SectName;
6343    Expected<StringRef> SecNameOrErr = S.getName();
6344    if (SecNameOrErr)
6345      SectName = *SecNameOrErr;
6346    else
6347      consumeError(SecNameOrErr.takeError());
6348  
6349    DataRefImpl Ref = S.getRawDataRefImpl();
6350    StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6351    outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6352    p = S.getAddress();
6353    r = get_pointer_32(p, offset, left, S, info);
6354    if (r == nullptr)
6355      return;
6356    memset(&o, '\0', sizeof(struct objc_image_info32));
6357    if (left < sizeof(struct objc_image_info32)) {
6358      memcpy(&o, r, left);
6359      outs() << "   (objc_image_info entends past the end of the section)\n";
6360    } else
6361      memcpy(&o, r, sizeof(struct objc_image_info32));
6362    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6363      swapStruct(o);
6364    outs() << "  version " << o.version << "\n";
6365    outs() << "    flags " << format("0x%" PRIx32, o.flags);
6366    if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6367      outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6368    if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6369      outs() << " OBJC_IMAGE_SUPPORTS_GC";
6370    swift_version = (o.flags >> 8) & 0xff;
6371    if (swift_version != 0) {
6372      if (swift_version == 1)
6373        outs() << " Swift 1.0";
6374      else if (swift_version == 2)
6375        outs() << " Swift 1.1";
6376      else if(swift_version == 3)
6377        outs() << " Swift 2.0";
6378      else if(swift_version == 4)
6379        outs() << " Swift 3.0";
6380      else if(swift_version == 5)
6381        outs() << " Swift 4.0";
6382      else if(swift_version == 6)
6383        outs() << " Swift 4.1/Swift 4.2";
6384      else if(swift_version == 7)
6385        outs() << " Swift 5 or later";
6386      else
6387        outs() << " unknown future Swift version (" << swift_version << ")";
6388    }
6389    outs() << "\n";
6390  }
6391  
print_image_info(SectionRef S,struct DisassembleInfo * info)6392  static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
6393    uint32_t left, offset, p;
6394    struct imageInfo_t o;
6395    const char *r;
6396  
6397    StringRef SectName;
6398    Expected<StringRef> SecNameOrErr = S.getName();
6399    if (SecNameOrErr)
6400      SectName = *SecNameOrErr;
6401    else
6402      consumeError(SecNameOrErr.takeError());
6403  
6404    DataRefImpl Ref = S.getRawDataRefImpl();
6405    StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6406    outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6407    p = S.getAddress();
6408    r = get_pointer_32(p, offset, left, S, info);
6409    if (r == nullptr)
6410      return;
6411    memset(&o, '\0', sizeof(struct imageInfo_t));
6412    if (left < sizeof(struct imageInfo_t)) {
6413      memcpy(&o, r, left);
6414      outs() << " (imageInfo entends past the end of the section)\n";
6415    } else
6416      memcpy(&o, r, sizeof(struct imageInfo_t));
6417    if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6418      swapStruct(o);
6419    outs() << "  version " << o.version << "\n";
6420    outs() << "    flags " << format("0x%" PRIx32, o.flags);
6421    if (o.flags & 0x1)
6422      outs() << "  F&C";
6423    if (o.flags & 0x2)
6424      outs() << " GC";
6425    if (o.flags & 0x4)
6426      outs() << " GC-only";
6427    else
6428      outs() << " RR";
6429    outs() << "\n";
6430  }
6431  
printObjc2_64bit_MetaData(MachOObjectFile * O,bool verbose)6432  static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
6433    SymbolAddressMap AddrMap;
6434    if (verbose)
6435      CreateSymbolAddressMap(O, &AddrMap);
6436  
6437    std::vector<SectionRef> Sections;
6438    append_range(Sections, O->sections());
6439  
6440    struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6441  
6442    SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6443    if (CL == SectionRef())
6444      CL = get_section(O, "__DATA", "__objc_classlist");
6445    if (CL == SectionRef())
6446      CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6447    if (CL == SectionRef())
6448      CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6449    info.S = CL;
6450    walk_pointer_list_64("class", CL, O, &info, print_class64_t);
6451  
6452    SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6453    if (CR == SectionRef())
6454      CR = get_section(O, "__DATA", "__objc_classrefs");
6455    if (CR == SectionRef())
6456      CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6457    if (CR == SectionRef())
6458      CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6459    info.S = CR;
6460    walk_pointer_list_64("class refs", CR, O, &info, nullptr);
6461  
6462    SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6463    if (SR == SectionRef())
6464      SR = get_section(O, "__DATA", "__objc_superrefs");
6465    if (SR == SectionRef())
6466      SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6467    if (SR == SectionRef())
6468      SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6469    info.S = SR;
6470    walk_pointer_list_64("super refs", SR, O, &info, nullptr);
6471  
6472    SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6473    if (CA == SectionRef())
6474      CA = get_section(O, "__DATA", "__objc_catlist");
6475    if (CA == SectionRef())
6476      CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6477    if (CA == SectionRef())
6478      CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6479    info.S = CA;
6480    walk_pointer_list_64("category", CA, O, &info, print_category64_t);
6481  
6482    SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6483    if (PL == SectionRef())
6484      PL = get_section(O, "__DATA", "__objc_protolist");
6485    if (PL == SectionRef())
6486      PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6487    if (PL == SectionRef())
6488      PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6489    info.S = PL;
6490    walk_pointer_list_64("protocol", PL, O, &info, nullptr);
6491  
6492    SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6493    if (MR == SectionRef())
6494      MR = get_section(O, "__DATA", "__objc_msgrefs");
6495    if (MR == SectionRef())
6496      MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6497    if (MR == SectionRef())
6498      MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6499    info.S = MR;
6500    print_message_refs64(MR, &info);
6501  
6502    SectionRef II = get_section(O, "__OBJC2", "__image_info");
6503    if (II == SectionRef())
6504      II = get_section(O, "__DATA", "__objc_imageinfo");
6505    if (II == SectionRef())
6506      II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6507    if (II == SectionRef())
6508      II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6509    info.S = II;
6510    print_image_info64(II, &info);
6511  }
6512  
printObjc2_32bit_MetaData(MachOObjectFile * O,bool verbose)6513  static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6514    SymbolAddressMap AddrMap;
6515    if (verbose)
6516      CreateSymbolAddressMap(O, &AddrMap);
6517  
6518    std::vector<SectionRef> Sections;
6519    append_range(Sections, O->sections());
6520  
6521    struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6522  
6523    SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6524    if (CL == SectionRef())
6525      CL = get_section(O, "__DATA", "__objc_classlist");
6526    if (CL == SectionRef())
6527      CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6528    if (CL == SectionRef())
6529      CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6530    info.S = CL;
6531    walk_pointer_list_32("class", CL, O, &info, print_class32_t);
6532  
6533    SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6534    if (CR == SectionRef())
6535      CR = get_section(O, "__DATA", "__objc_classrefs");
6536    if (CR == SectionRef())
6537      CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6538    if (CR == SectionRef())
6539      CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6540    info.S = CR;
6541    walk_pointer_list_32("class refs", CR, O, &info, nullptr);
6542  
6543    SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6544    if (SR == SectionRef())
6545      SR = get_section(O, "__DATA", "__objc_superrefs");
6546    if (SR == SectionRef())
6547      SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6548    if (SR == SectionRef())
6549      SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6550    info.S = SR;
6551    walk_pointer_list_32("super refs", SR, O, &info, nullptr);
6552  
6553    SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6554    if (CA == SectionRef())
6555      CA = get_section(O, "__DATA", "__objc_catlist");
6556    if (CA == SectionRef())
6557      CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6558    if (CA == SectionRef())
6559      CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6560    info.S = CA;
6561    walk_pointer_list_32("category", CA, O, &info, print_category32_t);
6562  
6563    SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6564    if (PL == SectionRef())
6565      PL = get_section(O, "__DATA", "__objc_protolist");
6566    if (PL == SectionRef())
6567      PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6568    if (PL == SectionRef())
6569      PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6570    info.S = PL;
6571    walk_pointer_list_32("protocol", PL, O, &info, nullptr);
6572  
6573    SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6574    if (MR == SectionRef())
6575      MR = get_section(O, "__DATA", "__objc_msgrefs");
6576    if (MR == SectionRef())
6577      MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6578    if (MR == SectionRef())
6579      MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6580    info.S = MR;
6581    print_message_refs32(MR, &info);
6582  
6583    SectionRef II = get_section(O, "__OBJC2", "__image_info");
6584    if (II == SectionRef())
6585      II = get_section(O, "__DATA", "__objc_imageinfo");
6586    if (II == SectionRef())
6587      II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6588    if (II == SectionRef())
6589      II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6590    info.S = II;
6591    print_image_info32(II, &info);
6592  }
6593  
printObjc1_32bit_MetaData(MachOObjectFile * O,bool verbose)6594  static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6595    uint32_t i, j, p, offset, xoffset, left, defs_left, def;
6596    const char *r, *name, *defs;
6597    struct objc_module_t module;
6598    SectionRef S, xS;
6599    struct objc_symtab_t symtab;
6600    struct objc_class_t objc_class;
6601    struct objc_category_t objc_category;
6602  
6603    outs() << "Objective-C segment\n";
6604    S = get_section(O, "__OBJC", "__module_info");
6605    if (S == SectionRef())
6606      return false;
6607  
6608    SymbolAddressMap AddrMap;
6609    if (verbose)
6610      CreateSymbolAddressMap(O, &AddrMap);
6611  
6612    std::vector<SectionRef> Sections;
6613    append_range(Sections, O->sections());
6614  
6615    struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6616  
6617    for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
6618      p = S.getAddress() + i;
6619      r = get_pointer_32(p, offset, left, S, &info, true);
6620      if (r == nullptr)
6621        return true;
6622      memset(&module, '\0', sizeof(struct objc_module_t));
6623      if (left < sizeof(struct objc_module_t)) {
6624        memcpy(&module, r, left);
6625        outs() << "   (module extends past end of __module_info section)\n";
6626      } else
6627        memcpy(&module, r, sizeof(struct objc_module_t));
6628      if (O->isLittleEndian() != sys::IsLittleEndianHost)
6629        swapStruct(module);
6630  
6631      outs() << "Module " << format("0x%" PRIx32, p) << "\n";
6632      outs() << "    version " << module.version << "\n";
6633      outs() << "       size " << module.size << "\n";
6634      outs() << "       name ";
6635      name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
6636      if (name != nullptr)
6637        outs() << format("%.*s", left, name);
6638      else
6639        outs() << format("0x%08" PRIx32, module.name)
6640               << "(not in an __OBJC section)";
6641      outs() << "\n";
6642  
6643      r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
6644      if (module.symtab == 0 || r == nullptr) {
6645        outs() << "     symtab " << format("0x%08" PRIx32, module.symtab)
6646               << " (not in an __OBJC section)\n";
6647        continue;
6648      }
6649      outs() << "     symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
6650      memset(&symtab, '\0', sizeof(struct objc_symtab_t));
6651      defs_left = 0;
6652      defs = nullptr;
6653      if (left < sizeof(struct objc_symtab_t)) {
6654        memcpy(&symtab, r, left);
6655        outs() << "\tsymtab extends past end of an __OBJC section)\n";
6656      } else {
6657        memcpy(&symtab, r, sizeof(struct objc_symtab_t));
6658        if (left > sizeof(struct objc_symtab_t)) {
6659          defs_left = left - sizeof(struct objc_symtab_t);
6660          defs = r + sizeof(struct objc_symtab_t);
6661        }
6662      }
6663      if (O->isLittleEndian() != sys::IsLittleEndianHost)
6664        swapStruct(symtab);
6665  
6666      outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
6667      r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
6668      outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
6669      if (r == nullptr)
6670        outs() << " (not in an __OBJC section)";
6671      outs() << "\n";
6672      outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
6673      outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
6674      if (symtab.cls_def_cnt > 0)
6675        outs() << "\tClass Definitions\n";
6676      for (j = 0; j < symtab.cls_def_cnt; j++) {
6677        if ((j + 1) * sizeof(uint32_t) > defs_left) {
6678          outs() << "\t(remaining class defs entries entends past the end of the "
6679                 << "section)\n";
6680          break;
6681        }
6682        memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
6683        if (O->isLittleEndian() != sys::IsLittleEndianHost)
6684          sys::swapByteOrder(def);
6685  
6686        r = get_pointer_32(def, xoffset, left, xS, &info, true);
6687        outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
6688        if (r != nullptr) {
6689          if (left > sizeof(struct objc_class_t)) {
6690            outs() << "\n";
6691            memcpy(&objc_class, r, sizeof(struct objc_class_t));
6692          } else {
6693            outs() << " (entends past the end of the section)\n";
6694            memset(&objc_class, '\0', sizeof(struct objc_class_t));
6695            memcpy(&objc_class, r, left);
6696          }
6697          if (O->isLittleEndian() != sys::IsLittleEndianHost)
6698            swapStruct(objc_class);
6699          print_objc_class_t(&objc_class, &info);
6700        } else {
6701          outs() << "(not in an __OBJC section)\n";
6702        }
6703  
6704        if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
6705          outs() << "\tMeta Class";
6706          r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
6707          if (r != nullptr) {
6708            if (left > sizeof(struct objc_class_t)) {
6709              outs() << "\n";
6710              memcpy(&objc_class, r, sizeof(struct objc_class_t));
6711            } else {
6712              outs() << " (entends past the end of the section)\n";
6713              memset(&objc_class, '\0', sizeof(struct objc_class_t));
6714              memcpy(&objc_class, r, left);
6715            }
6716            if (O->isLittleEndian() != sys::IsLittleEndianHost)
6717              swapStruct(objc_class);
6718            print_objc_class_t(&objc_class, &info);
6719          } else {
6720            outs() << "(not in an __OBJC section)\n";
6721          }
6722        }
6723      }
6724      if (symtab.cat_def_cnt > 0)
6725        outs() << "\tCategory Definitions\n";
6726      for (j = 0; j < symtab.cat_def_cnt; j++) {
6727        if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
6728          outs() << "\t(remaining category defs entries entends past the end of "
6729                 << "the section)\n";
6730          break;
6731        }
6732        memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
6733               sizeof(uint32_t));
6734        if (O->isLittleEndian() != sys::IsLittleEndianHost)
6735          sys::swapByteOrder(def);
6736  
6737        r = get_pointer_32(def, xoffset, left, xS, &info, true);
6738        outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
6739               << format("0x%08" PRIx32, def);
6740        if (r != nullptr) {
6741          if (left > sizeof(struct objc_category_t)) {
6742            outs() << "\n";
6743            memcpy(&objc_category, r, sizeof(struct objc_category_t));
6744          } else {
6745            outs() << " (entends past the end of the section)\n";
6746            memset(&objc_category, '\0', sizeof(struct objc_category_t));
6747            memcpy(&objc_category, r, left);
6748          }
6749          if (O->isLittleEndian() != sys::IsLittleEndianHost)
6750            swapStruct(objc_category);
6751          print_objc_objc_category_t(&objc_category, &info);
6752        } else {
6753          outs() << "(not in an __OBJC section)\n";
6754        }
6755      }
6756    }
6757    const SectionRef II = get_section(O, "__OBJC", "__image_info");
6758    if (II != SectionRef())
6759      print_image_info(II, &info);
6760  
6761    return true;
6762  }
6763  
DumpProtocolSection(MachOObjectFile * O,const char * sect,uint32_t size,uint32_t addr)6764  static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
6765                                  uint32_t size, uint32_t addr) {
6766    SymbolAddressMap AddrMap;
6767    CreateSymbolAddressMap(O, &AddrMap);
6768  
6769    std::vector<SectionRef> Sections;
6770    append_range(Sections, O->sections());
6771  
6772    struct DisassembleInfo info(O, &AddrMap, &Sections, true);
6773  
6774    const char *p;
6775    struct objc_protocol_t protocol;
6776    uint32_t left, paddr;
6777    for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
6778      memset(&protocol, '\0', sizeof(struct objc_protocol_t));
6779      left = size - (p - sect);
6780      if (left < sizeof(struct objc_protocol_t)) {
6781        outs() << "Protocol extends past end of __protocol section\n";
6782        memcpy(&protocol, p, left);
6783      } else
6784        memcpy(&protocol, p, sizeof(struct objc_protocol_t));
6785      if (O->isLittleEndian() != sys::IsLittleEndianHost)
6786        swapStruct(protocol);
6787      paddr = addr + (p - sect);
6788      outs() << "Protocol " << format("0x%" PRIx32, paddr);
6789      if (print_protocol(paddr, 0, &info))
6790        outs() << "(not in an __OBJC section)\n";
6791    }
6792  }
6793  
printObjcMetaData(MachOObjectFile * O,bool verbose)6794  static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
6795    if (O->is64Bit())
6796      printObjc2_64bit_MetaData(O, verbose);
6797    else {
6798      MachO::mach_header H;
6799      H = O->getHeader();
6800      if (H.cputype == MachO::CPU_TYPE_ARM)
6801        printObjc2_32bit_MetaData(O, verbose);
6802      else {
6803        // This is the 32-bit non-arm cputype case.  Which is normally
6804        // the first Objective-C ABI.  But it may be the case of a
6805        // binary for the iOS simulator which is the second Objective-C
6806        // ABI.  In that case printObjc1_32bit_MetaData() will determine that
6807        // and return false.
6808        if (!printObjc1_32bit_MetaData(O, verbose))
6809          printObjc2_32bit_MetaData(O, verbose);
6810      }
6811    }
6812  }
6813  
6814  // GuessLiteralPointer returns a string which for the item in the Mach-O file
6815  // for the address passed in as ReferenceValue for printing as a comment with
6816  // the instruction and also returns the corresponding type of that item
6817  // indirectly through ReferenceType.
6818  //
6819  // If ReferenceValue is an address of literal cstring then a pointer to the
6820  // cstring is returned and ReferenceType is set to
6821  // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
6822  //
6823  // If ReferenceValue is an address of an Objective-C CFString, Selector ref or
6824  // Class ref that name is returned and the ReferenceType is set accordingly.
6825  //
6826  // Lastly, literals which are Symbol address in a literal pool are looked for
6827  // and if found the symbol name is returned and ReferenceType is set to
6828  // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
6829  //
6830  // If there is no item in the Mach-O file for the address passed in as
6831  // ReferenceValue nullptr is returned and ReferenceType is unchanged.
GuessLiteralPointer(uint64_t ReferenceValue,uint64_t ReferencePC,uint64_t * ReferenceType,struct DisassembleInfo * info)6832  static const char *GuessLiteralPointer(uint64_t ReferenceValue,
6833                                         uint64_t ReferencePC,
6834                                         uint64_t *ReferenceType,
6835                                         struct DisassembleInfo *info) {
6836    // First see if there is an external relocation entry at the ReferencePC.
6837    if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
6838      uint64_t sect_addr = info->S.getAddress();
6839      uint64_t sect_offset = ReferencePC - sect_addr;
6840      bool reloc_found = false;
6841      DataRefImpl Rel;
6842      MachO::any_relocation_info RE;
6843      bool isExtern = false;
6844      SymbolRef Symbol;
6845      for (const RelocationRef &Reloc : info->S.relocations()) {
6846        uint64_t RelocOffset = Reloc.getOffset();
6847        if (RelocOffset == sect_offset) {
6848          Rel = Reloc.getRawDataRefImpl();
6849          RE = info->O->getRelocation(Rel);
6850          if (info->O->isRelocationScattered(RE))
6851            continue;
6852          isExtern = info->O->getPlainRelocationExternal(RE);
6853          if (isExtern) {
6854            symbol_iterator RelocSym = Reloc.getSymbol();
6855            Symbol = *RelocSym;
6856          }
6857          reloc_found = true;
6858          break;
6859        }
6860      }
6861      // If there is an external relocation entry for a symbol in a section
6862      // then used that symbol's value for the value of the reference.
6863      if (reloc_found && isExtern) {
6864        if (info->O->getAnyRelocationPCRel(RE)) {
6865          unsigned Type = info->O->getAnyRelocationType(RE);
6866          if (Type == MachO::X86_64_RELOC_SIGNED) {
6867            ReferenceValue = cantFail(Symbol.getValue());
6868          }
6869        }
6870      }
6871    }
6872  
6873    // Look for literals such as Objective-C CFStrings refs, Selector refs,
6874    // Message refs and Class refs.
6875    bool classref, selref, msgref, cfstring;
6876    uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
6877                                                 selref, msgref, cfstring);
6878    if (classref && pointer_value == 0) {
6879      // Note the ReferenceValue is a pointer into the __objc_classrefs section.
6880      // And the pointer_value in that section is typically zero as it will be
6881      // set by dyld as part of the "bind information".
6882      const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
6883      if (name != nullptr) {
6884        *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6885        const char *class_name = strrchr(name, '$');
6886        if (class_name != nullptr && class_name[1] == '_' &&
6887            class_name[2] != '\0') {
6888          info->class_name = class_name + 2;
6889          return name;
6890        }
6891      }
6892    }
6893  
6894    if (classref) {
6895      *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6896      const char *name =
6897          get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
6898      if (name != nullptr)
6899        info->class_name = name;
6900      else
6901        name = "bad class ref";
6902      return name;
6903    }
6904  
6905    if (cfstring) {
6906      *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
6907      const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
6908      return name;
6909    }
6910  
6911    if (selref && pointer_value == 0)
6912      pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
6913  
6914    if (pointer_value != 0)
6915      ReferenceValue = pointer_value;
6916  
6917    const char *name = GuessCstringPointer(ReferenceValue, info);
6918    if (name) {
6919      if (pointer_value != 0 && selref) {
6920        *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
6921        info->selector_name = name;
6922      } else if (pointer_value != 0 && msgref) {
6923        info->class_name = nullptr;
6924        *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
6925        info->selector_name = name;
6926      } else
6927        *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
6928      return name;
6929    }
6930  
6931    // Lastly look for an indirect symbol with this ReferenceValue which is in
6932    // a literal pool.  If found return that symbol name.
6933    name = GuessIndirectSymbol(ReferenceValue, info);
6934    if (name) {
6935      *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
6936      return name;
6937    }
6938  
6939    return nullptr;
6940  }
6941  
6942  // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
6943  // the Symbolizer.  It looks up the ReferenceValue using the info passed via the
6944  // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
6945  // is created and returns the symbol name that matches the ReferenceValue or
6946  // nullptr if none.  The ReferenceType is passed in for the IN type of
6947  // reference the instruction is making from the values in defined in the header
6948  // "llvm-c/Disassembler.h".  On return the ReferenceType can set to a specific
6949  // Out type and the ReferenceName will also be set which is added as a comment
6950  // to the disassembled instruction.
6951  //
6952  // If the symbol name is a C++ mangled name then the demangled name is
6953  // returned through ReferenceName and ReferenceType is set to
6954  // LLVMDisassembler_ReferenceType_DeMangled_Name .
6955  //
6956  // When this is called to get a symbol name for a branch target then the
6957  // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
6958  // SymbolValue will be looked for in the indirect symbol table to determine if
6959  // it is an address for a symbol stub.  If so then the symbol name for that
6960  // stub is returned indirectly through ReferenceName and then ReferenceType is
6961  // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
6962  //
6963  // When this is called with an value loaded via a PC relative load then
6964  // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
6965  // SymbolValue is checked to be an address of literal pointer, symbol pointer,
6966  // or an Objective-C meta data reference.  If so the output ReferenceType is
6967  // set to correspond to that as well as setting the ReferenceName.
SymbolizerSymbolLookUp(void * DisInfo,uint64_t ReferenceValue,uint64_t * ReferenceType,uint64_t ReferencePC,const char ** ReferenceName)6968  static const char *SymbolizerSymbolLookUp(void *DisInfo,
6969                                            uint64_t ReferenceValue,
6970                                            uint64_t *ReferenceType,
6971                                            uint64_t ReferencePC,
6972                                            const char **ReferenceName) {
6973    struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
6974    // If no verbose symbolic information is wanted then just return nullptr.
6975    if (!info->verbose) {
6976      *ReferenceName = nullptr;
6977      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6978      return nullptr;
6979    }
6980  
6981    const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
6982  
6983    if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
6984      *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
6985      if (*ReferenceName != nullptr) {
6986        method_reference(info, ReferenceType, ReferenceName);
6987        if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
6988          *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
6989      } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6990        if (info->demangled_name != nullptr)
6991          free(info->demangled_name);
6992        info->demangled_name = itaniumDemangle(SymbolName + 1);
6993        if (info->demangled_name != nullptr) {
6994          *ReferenceName = info->demangled_name;
6995          *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
6996        } else
6997          *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6998      } else
6999        *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7000    } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
7001      *ReferenceName =
7002          GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7003      if (*ReferenceName)
7004        method_reference(info, ReferenceType, ReferenceName);
7005      else
7006        *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7007      // If this is arm64 and the reference is an adrp instruction save the
7008      // instruction, passed in ReferenceValue and the address of the instruction
7009      // for use later if we see and add immediate instruction.
7010    } else if (info->O->getArch() == Triple::aarch64 &&
7011               *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
7012      info->adrp_inst = ReferenceValue;
7013      info->adrp_addr = ReferencePC;
7014      SymbolName = nullptr;
7015      *ReferenceName = nullptr;
7016      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7017      // If this is arm64 and reference is an add immediate instruction and we
7018      // have
7019      // seen an adrp instruction just before it and the adrp's Xd register
7020      // matches
7021      // this add's Xn register reconstruct the value being referenced and look to
7022      // see if it is a literal pointer.  Note the add immediate instruction is
7023      // passed in ReferenceValue.
7024    } else if (info->O->getArch() == Triple::aarch64 &&
7025               *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
7026               ReferencePC - 4 == info->adrp_addr &&
7027               (info->adrp_inst & 0x9f000000) == 0x90000000 &&
7028               (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
7029      uint32_t addxri_inst;
7030      uint64_t adrp_imm, addxri_imm;
7031  
7032      adrp_imm =
7033          ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
7034      if (info->adrp_inst & 0x0200000)
7035        adrp_imm |= 0xfffffffffc000000LL;
7036  
7037      addxri_inst = ReferenceValue;
7038      addxri_imm = (addxri_inst >> 10) & 0xfff;
7039      if (((addxri_inst >> 22) & 0x3) == 1)
7040        addxri_imm <<= 12;
7041  
7042      ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
7043                       (adrp_imm << 12) + addxri_imm;
7044  
7045      *ReferenceName =
7046          GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7047      if (*ReferenceName == nullptr)
7048        *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7049      // If this is arm64 and the reference is a load register instruction and we
7050      // have seen an adrp instruction just before it and the adrp's Xd register
7051      // matches this add's Xn register reconstruct the value being referenced and
7052      // look to see if it is a literal pointer.  Note the load register
7053      // instruction is passed in ReferenceValue.
7054    } else if (info->O->getArch() == Triple::aarch64 &&
7055               *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
7056               ReferencePC - 4 == info->adrp_addr &&
7057               (info->adrp_inst & 0x9f000000) == 0x90000000 &&
7058               (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
7059      uint32_t ldrxui_inst;
7060      uint64_t adrp_imm, ldrxui_imm;
7061  
7062      adrp_imm =
7063          ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
7064      if (info->adrp_inst & 0x0200000)
7065        adrp_imm |= 0xfffffffffc000000LL;
7066  
7067      ldrxui_inst = ReferenceValue;
7068      ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
7069  
7070      ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
7071                       (adrp_imm << 12) + (ldrxui_imm << 3);
7072  
7073      *ReferenceName =
7074          GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7075      if (*ReferenceName == nullptr)
7076        *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7077    }
7078    // If this arm64 and is an load register (PC-relative) instruction the
7079    // ReferenceValue is the PC plus the immediate value.
7080    else if (info->O->getArch() == Triple::aarch64 &&
7081             (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
7082              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
7083      *ReferenceName =
7084          GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
7085      if (*ReferenceName == nullptr)
7086        *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7087    } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
7088      if (info->demangled_name != nullptr)
7089        free(info->demangled_name);
7090      info->demangled_name = itaniumDemangle(SymbolName + 1);
7091      if (info->demangled_name != nullptr) {
7092        *ReferenceName = info->demangled_name;
7093        *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
7094      }
7095    }
7096    else {
7097      *ReferenceName = nullptr;
7098      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
7099    }
7100  
7101    return SymbolName;
7102  }
7103  
7104  /// Emits the comments that are stored in the CommentStream.
7105  /// Each comment in the CommentStream must end with a newline.
emitComments(raw_svector_ostream & CommentStream,SmallString<128> & CommentsToEmit,formatted_raw_ostream & FormattedOS,const MCAsmInfo & MAI)7106  static void emitComments(raw_svector_ostream &CommentStream,
7107                           SmallString<128> &CommentsToEmit,
7108                           formatted_raw_ostream &FormattedOS,
7109                           const MCAsmInfo &MAI) {
7110    // Flush the stream before taking its content.
7111    StringRef Comments = CommentsToEmit.str();
7112    // Get the default information for printing a comment.
7113    StringRef CommentBegin = MAI.getCommentString();
7114    unsigned CommentColumn = MAI.getCommentColumn();
7115    ListSeparator LS("\n");
7116    while (!Comments.empty()) {
7117      FormattedOS << LS;
7118      // Emit a line of comments.
7119      FormattedOS.PadToColumn(CommentColumn);
7120      size_t Position = Comments.find('\n');
7121      FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
7122      // Move after the newline character.
7123      Comments = Comments.substr(Position + 1);
7124    }
7125    FormattedOS.flush();
7126  
7127    // Tell the comment stream that the vector changed underneath it.
7128    CommentsToEmit.clear();
7129  }
7130  
7131  const MachOObjectFile *
getMachODSymObject(const MachOObjectFile * MachOOF,StringRef Filename,std::unique_ptr<Binary> & DSYMBinary,std::unique_ptr<MemoryBuffer> & DSYMBuf)7132  objdump::getMachODSymObject(const MachOObjectFile *MachOOF, StringRef Filename,
7133                              std::unique_ptr<Binary> &DSYMBinary,
7134                              std::unique_ptr<MemoryBuffer> &DSYMBuf) {
7135    const MachOObjectFile *DbgObj = MachOOF;
7136    std::string DSYMPath;
7137  
7138    // Auto-detect w/o --dsym.
7139    if (DSYMFile.empty()) {
7140      sys::fs::file_status DSYMStatus;
7141      Twine FilenameDSYM = Filename + ".dSYM";
7142      if (!status(FilenameDSYM, DSYMStatus)) {
7143        if (sys::fs::is_directory(DSYMStatus)) {
7144          SmallString<1024> Path;
7145          FilenameDSYM.toVector(Path);
7146          sys::path::append(Path, "Contents", "Resources", "DWARF",
7147                            sys::path::filename(Filename));
7148          DSYMPath = std::string(Path);
7149        } else if (sys::fs::is_regular_file(DSYMStatus)) {
7150          DSYMPath = FilenameDSYM.str();
7151        }
7152      }
7153    }
7154  
7155    if (DSYMPath.empty() && !DSYMFile.empty()) {
7156      // If DSYMPath is a .dSYM directory, append the Mach-O file.
7157      if (sys::fs::is_directory(DSYMFile) &&
7158          sys::path::extension(DSYMFile) == ".dSYM") {
7159        SmallString<128> ShortName(sys::path::filename(DSYMFile));
7160        sys::path::replace_extension(ShortName, "");
7161        SmallString<1024> FullPath(DSYMFile);
7162        sys::path::append(FullPath, "Contents", "Resources", "DWARF", ShortName);
7163        DSYMPath = FullPath.str();
7164      } else {
7165        DSYMPath = DSYMFile;
7166      }
7167    }
7168  
7169    if (!DSYMPath.empty()) {
7170      // Load the file.
7171      ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
7172          MemoryBuffer::getFileOrSTDIN(DSYMPath);
7173      if (std::error_code EC = BufOrErr.getError()) {
7174        reportError(errorCodeToError(EC), DSYMPath);
7175        return nullptr;
7176      }
7177  
7178      // We need to keep the file alive, because we're replacing DbgObj with it.
7179      DSYMBuf = std::move(BufOrErr.get());
7180  
7181      Expected<std::unique_ptr<Binary>> BinaryOrErr =
7182          createBinary(DSYMBuf->getMemBufferRef());
7183      if (!BinaryOrErr) {
7184        reportError(BinaryOrErr.takeError(), DSYMPath);
7185        return nullptr;
7186      }
7187  
7188      // We need to keep the Binary alive with the buffer
7189      DSYMBinary = std::move(BinaryOrErr.get());
7190      if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) {
7191        // this is a Mach-O object file, use it
7192        if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) {
7193          DbgObj = MachDSYM;
7194        } else {
7195          WithColor::error(errs(), "llvm-objdump")
7196              << DSYMPath << " is not a Mach-O file type.\n";
7197          return nullptr;
7198        }
7199      } else if (auto *UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())) {
7200        // this is a Universal Binary, find a Mach-O for this architecture
7201        uint32_t CPUType, CPUSubType;
7202        const char *ArchFlag;
7203        if (MachOOF->is64Bit()) {
7204          const MachO::mach_header_64 H_64 = MachOOF->getHeader64();
7205          CPUType = H_64.cputype;
7206          CPUSubType = H_64.cpusubtype;
7207        } else {
7208          const MachO::mach_header H = MachOOF->getHeader();
7209          CPUType = H.cputype;
7210          CPUSubType = H.cpusubtype;
7211        }
7212        Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr,
7213                                                  &ArchFlag);
7214        Expected<std::unique_ptr<MachOObjectFile>> MachDSYM =
7215            UB->getMachOObjectForArch(ArchFlag);
7216        if (!MachDSYM) {
7217          reportError(MachDSYM.takeError(), DSYMPath);
7218          return nullptr;
7219        }
7220  
7221        // We need to keep the Binary alive with the buffer
7222        DbgObj = &*MachDSYM.get();
7223        DSYMBinary = std::move(*MachDSYM);
7224      } else {
7225        WithColor::error(errs(), "llvm-objdump")
7226            << DSYMPath << " is not a Mach-O or Universal file type.\n";
7227        return nullptr;
7228      }
7229    }
7230    return DbgObj;
7231  }
7232  
DisassembleMachO(StringRef Filename,MachOObjectFile * MachOOF,StringRef DisSegName,StringRef DisSectName)7233  static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
7234                               StringRef DisSegName, StringRef DisSectName) {
7235    const char *McpuDefault = nullptr;
7236    const Target *ThumbTarget = nullptr;
7237    const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
7238    if (!TheTarget) {
7239      // GetTarget prints out stuff.
7240      return;
7241    }
7242    std::string MachOMCPU;
7243    if (MCPU.empty() && McpuDefault)
7244      MachOMCPU = McpuDefault;
7245    else
7246      MachOMCPU = MCPU;
7247  
7248  #define CHECK_TARGET_INFO_CREATION(NAME)                                       \
7249    do {                                                                         \
7250      if (!NAME) {                                                               \
7251        WithColor::error(errs(), "llvm-objdump")                                 \
7252            << "couldn't initialize disassembler for target " << TripleName      \
7253            << '\n';                                                             \
7254        return;                                                                  \
7255      }                                                                          \
7256    } while (false)
7257  #define CHECK_THUMB_TARGET_INFO_CREATION(NAME)                                 \
7258    do {                                                                         \
7259      if (!NAME) {                                                               \
7260        WithColor::error(errs(), "llvm-objdump")                                 \
7261            << "couldn't initialize disassembler for target " << ThumbTripleName \
7262            << '\n';                                                             \
7263        return;                                                                  \
7264      }                                                                          \
7265    } while (false)
7266  
7267    std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
7268    CHECK_TARGET_INFO_CREATION(InstrInfo);
7269    std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
7270    if (ThumbTarget) {
7271      ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
7272      CHECK_THUMB_TARGET_INFO_CREATION(ThumbInstrInfo);
7273    }
7274  
7275    // Package up features to be passed to target/subtarget
7276    std::string FeaturesStr;
7277    if (!MAttrs.empty()) {
7278      SubtargetFeatures Features;
7279      for (unsigned i = 0; i != MAttrs.size(); ++i)
7280        Features.AddFeature(MAttrs[i]);
7281      FeaturesStr = Features.getString();
7282    }
7283  
7284    MCTargetOptions MCOptions;
7285    // Set up disassembler.
7286    std::unique_ptr<const MCRegisterInfo> MRI(
7287        TheTarget->createMCRegInfo(TripleName));
7288    CHECK_TARGET_INFO_CREATION(MRI);
7289    std::unique_ptr<const MCAsmInfo> AsmInfo(
7290        TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
7291    CHECK_TARGET_INFO_CREATION(AsmInfo);
7292    std::unique_ptr<const MCSubtargetInfo> STI(
7293        TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
7294    CHECK_TARGET_INFO_CREATION(STI);
7295    MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
7296    std::unique_ptr<MCDisassembler> DisAsm(
7297        TheTarget->createMCDisassembler(*STI, Ctx));
7298    CHECK_TARGET_INFO_CREATION(DisAsm);
7299    std::unique_ptr<MCSymbolizer> Symbolizer;
7300    struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
7301    std::unique_ptr<MCRelocationInfo> RelInfo(
7302        TheTarget->createMCRelocationInfo(TripleName, Ctx));
7303    if (RelInfo) {
7304      Symbolizer.reset(TheTarget->createMCSymbolizer(
7305          TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7306          &SymbolizerInfo, &Ctx, std::move(RelInfo)));
7307      DisAsm->setSymbolizer(std::move(Symbolizer));
7308    }
7309    int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
7310    std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
7311        Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
7312    CHECK_TARGET_INFO_CREATION(IP);
7313    // Set the display preference for hex vs. decimal immediates.
7314    IP->setPrintImmHex(PrintImmHex);
7315    // Comment stream and backing vector.
7316    SmallString<128> CommentsToEmit;
7317    raw_svector_ostream CommentStream(CommentsToEmit);
7318    // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
7319    // if it is done then arm64 comments for string literals don't get printed
7320    // and some constant get printed instead and not setting it causes intel
7321    // (32-bit and 64-bit) comments printed with different spacing before the
7322    // comment causing different diffs with the 'C' disassembler library API.
7323    // IP->setCommentStream(CommentStream);
7324  
7325    // Set up separate thumb disassembler if needed.
7326    std::unique_ptr<const MCRegisterInfo> ThumbMRI;
7327    std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
7328    std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
7329    std::unique_ptr<MCDisassembler> ThumbDisAsm;
7330    std::unique_ptr<MCInstPrinter> ThumbIP;
7331    std::unique_ptr<MCContext> ThumbCtx;
7332    std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
7333    struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
7334    std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
7335    if (ThumbTarget) {
7336      ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
7337      CHECK_THUMB_TARGET_INFO_CREATION(ThumbMRI);
7338      ThumbAsmInfo.reset(
7339          ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions));
7340      CHECK_THUMB_TARGET_INFO_CREATION(ThumbAsmInfo);
7341      ThumbSTI.reset(
7342          ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
7343                                             FeaturesStr));
7344      CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI);
7345      ThumbCtx.reset(new MCContext(Triple(ThumbTripleName), ThumbAsmInfo.get(),
7346                                   ThumbMRI.get(), ThumbSTI.get()));
7347      ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
7348      CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm);
7349      MCContext *PtrThumbCtx = ThumbCtx.get();
7350      ThumbRelInfo.reset(
7351          ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
7352      if (ThumbRelInfo) {
7353        ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
7354            ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7355            &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
7356        ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
7357      }
7358      int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
7359      ThumbIP.reset(ThumbTarget->createMCInstPrinter(
7360          Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
7361          *ThumbInstrInfo, *ThumbMRI));
7362      CHECK_THUMB_TARGET_INFO_CREATION(ThumbIP);
7363      // Set the display preference for hex vs. decimal immediates.
7364      ThumbIP->setPrintImmHex(PrintImmHex);
7365    }
7366  
7367  #undef CHECK_TARGET_INFO_CREATION
7368  #undef CHECK_THUMB_TARGET_INFO_CREATION
7369  
7370    MachO::mach_header Header = MachOOF->getHeader();
7371  
7372    // FIXME: Using the -cfg command line option, this code used to be able to
7373    // annotate relocations with the referenced symbol's name, and if this was
7374    // inside a __[cf]string section, the data it points to. This is now replaced
7375    // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
7376    std::vector<SectionRef> Sections;
7377    std::vector<SymbolRef> Symbols;
7378    SmallVector<uint64_t, 8> FoundFns;
7379    uint64_t BaseSegmentAddress = 0;
7380  
7381    getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
7382                          BaseSegmentAddress);
7383  
7384    // Sort the symbols by address, just in case they didn't come in that way.
7385    llvm::stable_sort(Symbols, SymbolSorter());
7386  
7387    // Build a data in code table that is sorted on by the address of each entry.
7388    uint64_t BaseAddress = 0;
7389    if (Header.filetype == MachO::MH_OBJECT)
7390      BaseAddress = Sections[0].getAddress();
7391    else
7392      BaseAddress = BaseSegmentAddress;
7393    DiceTable Dices;
7394    for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
7395         DI != DE; ++DI) {
7396      uint32_t Offset;
7397      DI->getOffset(Offset);
7398      Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
7399    }
7400    array_pod_sort(Dices.begin(), Dices.end());
7401  
7402    // Try to find debug info and set up the DIContext for it.
7403    std::unique_ptr<DIContext> diContext;
7404    std::unique_ptr<Binary> DSYMBinary;
7405    std::unique_ptr<MemoryBuffer> DSYMBuf;
7406    if (UseDbg) {
7407      // If separate DSym file path was specified, parse it as a macho file,
7408      // get the sections and supply it to the section name parsing machinery.
7409      if (const ObjectFile *DbgObj =
7410              getMachODSymObject(MachOOF, Filename, DSYMBinary, DSYMBuf)) {
7411        // Setup the DIContext
7412        diContext = DWARFContext::create(*DbgObj);
7413      } else {
7414        return;
7415      }
7416    }
7417  
7418    if (FilterSections.empty())
7419      outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
7420  
7421    for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
7422      Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName();
7423      if (!SecNameOrErr) {
7424        consumeError(SecNameOrErr.takeError());
7425        continue;
7426      }
7427      if (*SecNameOrErr != DisSectName)
7428        continue;
7429  
7430      DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
7431  
7432      StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
7433      if (SegmentName != DisSegName)
7434        continue;
7435  
7436      StringRef BytesStr =
7437          unwrapOrError(Sections[SectIdx].getContents(), Filename);
7438      ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr);
7439      uint64_t SectAddress = Sections[SectIdx].getAddress();
7440  
7441      bool symbolTableWorked = false;
7442  
7443      // Create a map of symbol addresses to symbol names for use by
7444      // the SymbolizerSymbolLookUp() routine.
7445      SymbolAddressMap AddrMap;
7446      bool DisSymNameFound = false;
7447      for (const SymbolRef &Symbol : MachOOF->symbols()) {
7448        SymbolRef::Type ST =
7449            unwrapOrError(Symbol.getType(), MachOOF->getFileName());
7450        if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
7451            ST == SymbolRef::ST_Other) {
7452          uint64_t Address = cantFail(Symbol.getValue());
7453          StringRef SymName =
7454              unwrapOrError(Symbol.getName(), MachOOF->getFileName());
7455          AddrMap[Address] = SymName;
7456          if (!DisSymName.empty() && DisSymName == SymName)
7457            DisSymNameFound = true;
7458        }
7459      }
7460      if (!DisSymName.empty() && !DisSymNameFound) {
7461        outs() << "Can't find -dis-symname: " << DisSymName << "\n";
7462        return;
7463      }
7464      // Set up the block of info used by the Symbolizer call backs.
7465      SymbolizerInfo.verbose = SymbolicOperands;
7466      SymbolizerInfo.O = MachOOF;
7467      SymbolizerInfo.S = Sections[SectIdx];
7468      SymbolizerInfo.AddrMap = &AddrMap;
7469      SymbolizerInfo.Sections = &Sections;
7470      // Same for the ThumbSymbolizer
7471      ThumbSymbolizerInfo.verbose = SymbolicOperands;
7472      ThumbSymbolizerInfo.O = MachOOF;
7473      ThumbSymbolizerInfo.S = Sections[SectIdx];
7474      ThumbSymbolizerInfo.AddrMap = &AddrMap;
7475      ThumbSymbolizerInfo.Sections = &Sections;
7476  
7477      unsigned int Arch = MachOOF->getArch();
7478  
7479      // Skip all symbols if this is a stubs file.
7480      if (Bytes.empty())
7481        return;
7482  
7483      // If the section has symbols but no symbol at the start of the section
7484      // these are used to make sure the bytes before the first symbol are
7485      // disassembled.
7486      bool FirstSymbol = true;
7487      bool FirstSymbolAtSectionStart = true;
7488  
7489      // Disassemble symbol by symbol.
7490      for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
7491        StringRef SymName =
7492            unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName());
7493        SymbolRef::Type ST =
7494            unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName());
7495        if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
7496          continue;
7497  
7498        // Make sure the symbol is defined in this section.
7499        bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
7500        if (!containsSym) {
7501          if (!DisSymName.empty() && DisSymName == SymName) {
7502            outs() << "-dis-symname: " << DisSymName << " not in the section\n";
7503            return;
7504          }
7505          continue;
7506        }
7507        // The __mh_execute_header is special and we need to deal with that fact
7508        // this symbol is before the start of the (__TEXT,__text) section and at the
7509        // address of the start of the __TEXT segment.  This is because this symbol
7510        // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
7511        // start of the section in a standard MH_EXECUTE filetype.
7512        if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
7513          outs() << "-dis-symname: __mh_execute_header not in any section\n";
7514          return;
7515        }
7516        // When this code is trying to disassemble a symbol at a time and in the
7517        // case there is only the __mh_execute_header symbol left as in a stripped
7518        // executable, we need to deal with this by ignoring this symbol so the
7519        // whole section is disassembled and this symbol is then not displayed.
7520        if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
7521            SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
7522            SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
7523          continue;
7524  
7525        // If we are only disassembling one symbol see if this is that symbol.
7526        if (!DisSymName.empty() && DisSymName != SymName)
7527          continue;
7528  
7529        // Start at the address of the symbol relative to the section's address.
7530        uint64_t SectSize = Sections[SectIdx].getSize();
7531        uint64_t Start = cantFail(Symbols[SymIdx].getValue());
7532        uint64_t SectionAddress = Sections[SectIdx].getAddress();
7533        Start -= SectionAddress;
7534  
7535        if (Start > SectSize) {
7536          outs() << "section data ends, " << SymName
7537                 << " lies outside valid range\n";
7538          return;
7539        }
7540  
7541        // Stop disassembling either at the beginning of the next symbol or at
7542        // the end of the section.
7543        bool containsNextSym = false;
7544        uint64_t NextSym = 0;
7545        uint64_t NextSymIdx = SymIdx + 1;
7546        while (Symbols.size() > NextSymIdx) {
7547          SymbolRef::Type NextSymType = unwrapOrError(
7548              Symbols[NextSymIdx].getType(), MachOOF->getFileName());
7549          if (NextSymType == SymbolRef::ST_Function) {
7550            containsNextSym =
7551                Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
7552            NextSym = cantFail(Symbols[NextSymIdx].getValue());
7553            NextSym -= SectionAddress;
7554            break;
7555          }
7556          ++NextSymIdx;
7557        }
7558  
7559        uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
7560        uint64_t Size;
7561  
7562        symbolTableWorked = true;
7563  
7564        DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
7565        uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb));
7566        bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb;
7567  
7568        // We only need the dedicated Thumb target if there's a real choice
7569        // (i.e. we're not targeting M-class) and the function is Thumb.
7570        bool UseThumbTarget = IsThumb && ThumbTarget;
7571  
7572        // If we are not specifying a symbol to start disassembly with and this
7573        // is the first symbol in the section but not at the start of the section
7574        // then move the disassembly index to the start of the section and
7575        // don't print the symbol name just yet.  This is so the bytes before the
7576        // first symbol are disassembled.
7577        uint64_t SymbolStart = Start;
7578        if (DisSymName.empty() && FirstSymbol && Start != 0) {
7579          FirstSymbolAtSectionStart = false;
7580          Start = 0;
7581        }
7582        else
7583          outs() << SymName << ":\n";
7584  
7585        DILineInfo lastLine;
7586        for (uint64_t Index = Start; Index < End; Index += Size) {
7587          MCInst Inst;
7588  
7589          // If this is the first symbol in the section and it was not at the
7590          // start of the section, see if we are at its Index now and if so print
7591          // the symbol name.
7592          if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart)
7593            outs() << SymName << ":\n";
7594  
7595          uint64_t PC = SectAddress + Index;
7596          if (LeadingAddr) {
7597            if (FullLeadingAddr) {
7598              if (MachOOF->is64Bit())
7599                outs() << format("%016" PRIx64, PC);
7600              else
7601                outs() << format("%08" PRIx64, PC);
7602            } else {
7603              outs() << format("%8" PRIx64 ":", PC);
7604            }
7605          }
7606          if (ShowRawInsn || Arch == Triple::arm)
7607            outs() << "\t";
7608  
7609          if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size))
7610            continue;
7611  
7612          SmallVector<char, 64> AnnotationsBytes;
7613          raw_svector_ostream Annotations(AnnotationsBytes);
7614  
7615          bool gotInst;
7616          if (UseThumbTarget)
7617            gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
7618                                                  PC, Annotations);
7619          else
7620            gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
7621                                             Annotations);
7622          if (gotInst) {
7623            if (ShowRawInsn || Arch == Triple::arm) {
7624              dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs());
7625            }
7626            formatted_raw_ostream FormattedOS(outs());
7627            StringRef AnnotationsStr = Annotations.str();
7628            if (UseThumbTarget)
7629              ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI,
7630                                 FormattedOS);
7631            else
7632              IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS);
7633            emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
7634  
7635            // Print debug info.
7636            if (diContext) {
7637              DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx});
7638              // Print valid line info if it changed.
7639              if (dli != lastLine && dli.Line != 0)
7640                outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
7641                       << dli.Column;
7642              lastLine = dli;
7643            }
7644            outs() << "\n";
7645          } else {
7646            if (MachOOF->getArchTriple().isX86()) {
7647              outs() << format("\t.byte 0x%02x #bad opcode\n",
7648                               *(Bytes.data() + Index) & 0xff);
7649              Size = 1; // skip exactly one illegible byte and move on.
7650            } else if (Arch == Triple::aarch64 ||
7651                       (Arch == Triple::arm && !IsThumb)) {
7652              uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7653                                (*(Bytes.data() + Index + 1) & 0xff) << 8 |
7654                                (*(Bytes.data() + Index + 2) & 0xff) << 16 |
7655                                (*(Bytes.data() + Index + 3) & 0xff) << 24;
7656              outs() << format("\t.long\t0x%08x\n", opcode);
7657              Size = 4;
7658            } else if (Arch == Triple::arm) {
7659              assert(IsThumb && "ARM mode should have been dealt with above");
7660              uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7661                                (*(Bytes.data() + Index + 1) & 0xff) << 8;
7662              outs() << format("\t.short\t0x%04x\n", opcode);
7663              Size = 2;
7664            } else{
7665              WithColor::warning(errs(), "llvm-objdump")
7666                  << "invalid instruction encoding\n";
7667              if (Size == 0)
7668                Size = 1; // skip illegible bytes
7669            }
7670          }
7671        }
7672        // Now that we are done disassembled the first symbol set the bool that
7673        // were doing this to false.
7674        FirstSymbol = false;
7675      }
7676      if (!symbolTableWorked) {
7677        // Reading the symbol table didn't work, disassemble the whole section.
7678        uint64_t SectAddress = Sections[SectIdx].getAddress();
7679        uint64_t SectSize = Sections[SectIdx].getSize();
7680        uint64_t InstSize;
7681        for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
7682          MCInst Inst;
7683  
7684          uint64_t PC = SectAddress + Index;
7685  
7686          if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize))
7687            continue;
7688  
7689          SmallVector<char, 64> AnnotationsBytes;
7690          raw_svector_ostream Annotations(AnnotationsBytes);
7691          if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
7692                                     Annotations)) {
7693            if (LeadingAddr) {
7694              if (FullLeadingAddr) {
7695                if (MachOOF->is64Bit())
7696                  outs() << format("%016" PRIx64, PC);
7697                else
7698                  outs() << format("%08" PRIx64, PC);
7699              } else {
7700                outs() << format("%8" PRIx64 ":", PC);
7701              }
7702            }
7703            if (ShowRawInsn || Arch == Triple::arm) {
7704              outs() << "\t";
7705              dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs());
7706            }
7707            StringRef AnnotationsStr = Annotations.str();
7708            IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs());
7709            outs() << "\n";
7710          } else {
7711            if (MachOOF->getArchTriple().isX86()) {
7712              outs() << format("\t.byte 0x%02x #bad opcode\n",
7713                               *(Bytes.data() + Index) & 0xff);
7714              InstSize = 1; // skip exactly one illegible byte and move on.
7715            } else {
7716              WithColor::warning(errs(), "llvm-objdump")
7717                  << "invalid instruction encoding\n";
7718              if (InstSize == 0)
7719                InstSize = 1; // skip illegible bytes
7720            }
7721          }
7722        }
7723      }
7724      // The TripleName's need to be reset if we are called again for a different
7725      // architecture.
7726      TripleName = "";
7727      ThumbTripleName = "";
7728  
7729      if (SymbolizerInfo.demangled_name != nullptr)
7730        free(SymbolizerInfo.demangled_name);
7731      if (ThumbSymbolizerInfo.demangled_name != nullptr)
7732        free(ThumbSymbolizerInfo.demangled_name);
7733    }
7734  }
7735  
7736  //===----------------------------------------------------------------------===//
7737  // __compact_unwind section dumping
7738  //===----------------------------------------------------------------------===//
7739  
7740  namespace {
7741  
7742  template <typename T>
read(StringRef Contents,ptrdiff_t Offset)7743  static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
7744    if (Offset + sizeof(T) > Contents.size()) {
7745      outs() << "warning: attempt to read past end of buffer\n";
7746      return T();
7747    }
7748  
7749    uint64_t Val = support::endian::read<T, llvm::endianness::little>(
7750        Contents.data() + Offset);
7751    return Val;
7752  }
7753  
7754  template <typename T>
readNext(StringRef Contents,ptrdiff_t & Offset)7755  static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
7756    T Val = read<T>(Contents, Offset);
7757    Offset += sizeof(T);
7758    return Val;
7759  }
7760  
7761  struct CompactUnwindEntry {
7762    uint32_t OffsetInSection;
7763  
7764    uint64_t FunctionAddr;
7765    uint32_t Length;
7766    uint32_t CompactEncoding;
7767    uint64_t PersonalityAddr;
7768    uint64_t LSDAAddr;
7769  
7770    RelocationRef FunctionReloc;
7771    RelocationRef PersonalityReloc;
7772    RelocationRef LSDAReloc;
7773  
CompactUnwindEntry__anon061faff00a11::CompactUnwindEntry7774    CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
7775        : OffsetInSection(Offset) {
7776      if (Is64)
7777        read<uint64_t>(Contents, Offset);
7778      else
7779        read<uint32_t>(Contents, Offset);
7780    }
7781  
7782  private:
read__anon061faff00a11::CompactUnwindEntry7783    template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
7784      FunctionAddr = readNext<UIntPtr>(Contents, Offset);
7785      Length = readNext<uint32_t>(Contents, Offset);
7786      CompactEncoding = readNext<uint32_t>(Contents, Offset);
7787      PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
7788      LSDAAddr = readNext<UIntPtr>(Contents, Offset);
7789    }
7790  };
7791  }
7792  
7793  /// Given a relocation from __compact_unwind, consisting of the RelocationRef
7794  /// and data being relocated, determine the best base Name and Addend to use for
7795  /// display purposes.
7796  ///
7797  /// 1. An Extern relocation will directly reference a symbol (and the data is
7798  ///    then already an addend), so use that.
7799  /// 2. Otherwise the data is an offset in the object file's layout; try to find
7800  //     a symbol before it in the same section, and use the offset from there.
7801  /// 3. Finally, if all that fails, fall back to an offset from the start of the
7802  ///    referenced section.
findUnwindRelocNameAddend(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr,StringRef & Name,uint64_t & Addend)7803  static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
7804                                        std::map<uint64_t, SymbolRef> &Symbols,
7805                                        const RelocationRef &Reloc, uint64_t Addr,
7806                                        StringRef &Name, uint64_t &Addend) {
7807    if (Reloc.getSymbol() != Obj->symbol_end()) {
7808      Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName());
7809      Addend = Addr;
7810      return;
7811    }
7812  
7813    auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
7814    SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
7815  
7816    uint64_t SectionAddr = RelocSection.getAddress();
7817  
7818    auto Sym = Symbols.upper_bound(Addr);
7819    if (Sym == Symbols.begin()) {
7820      // The first symbol in the object is after this reference, the best we can
7821      // do is section-relative notation.
7822      if (Expected<StringRef> NameOrErr = RelocSection.getName())
7823        Name = *NameOrErr;
7824      else
7825        consumeError(NameOrErr.takeError());
7826  
7827      Addend = Addr - SectionAddr;
7828      return;
7829    }
7830  
7831    // Go back one so that SymbolAddress <= Addr.
7832    --Sym;
7833  
7834    section_iterator SymSection =
7835        unwrapOrError(Sym->second.getSection(), Obj->getFileName());
7836    if (RelocSection == *SymSection) {
7837      // There's a valid symbol in the same section before this reference.
7838      Name = unwrapOrError(Sym->second.getName(), Obj->getFileName());
7839      Addend = Addr - Sym->first;
7840      return;
7841    }
7842  
7843    // There is a symbol before this reference, but it's in a different
7844    // section. Probably not helpful to mention it, so use the section name.
7845    if (Expected<StringRef> NameOrErr = RelocSection.getName())
7846      Name = *NameOrErr;
7847    else
7848      consumeError(NameOrErr.takeError());
7849  
7850    Addend = Addr - SectionAddr;
7851  }
7852  
printUnwindRelocDest(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr)7853  static void printUnwindRelocDest(const MachOObjectFile *Obj,
7854                                   std::map<uint64_t, SymbolRef> &Symbols,
7855                                   const RelocationRef &Reloc, uint64_t Addr) {
7856    StringRef Name;
7857    uint64_t Addend;
7858  
7859    if (!Reloc.getObject())
7860      return;
7861  
7862    findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
7863  
7864    outs() << Name;
7865    if (Addend)
7866      outs() << " + " << format("0x%" PRIx64, Addend);
7867  }
7868  
7869  static void
printMachOCompactUnwindSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & CompactUnwind)7870  printMachOCompactUnwindSection(const MachOObjectFile *Obj,
7871                                 std::map<uint64_t, SymbolRef> &Symbols,
7872                                 const SectionRef &CompactUnwind) {
7873  
7874    if (!Obj->isLittleEndian()) {
7875      outs() << "Skipping big-endian __compact_unwind section\n";
7876      return;
7877    }
7878  
7879    bool Is64 = Obj->is64Bit();
7880    uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
7881    uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
7882  
7883    StringRef Contents =
7884        unwrapOrError(CompactUnwind.getContents(), Obj->getFileName());
7885    SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
7886  
7887    // First populate the initial raw offsets, encodings and so on from the entry.
7888    for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
7889      CompactUnwindEntry Entry(Contents, Offset, Is64);
7890      CompactUnwinds.push_back(Entry);
7891    }
7892  
7893    // Next we need to look at the relocations to find out what objects are
7894    // actually being referred to.
7895    for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
7896      uint64_t RelocAddress = Reloc.getOffset();
7897  
7898      uint32_t EntryIdx = RelocAddress / EntrySize;
7899      uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
7900      CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
7901  
7902      if (OffsetInEntry == 0)
7903        Entry.FunctionReloc = Reloc;
7904      else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
7905        Entry.PersonalityReloc = Reloc;
7906      else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
7907        Entry.LSDAReloc = Reloc;
7908      else {
7909        outs() << "Invalid relocation in __compact_unwind section\n";
7910        return;
7911      }
7912    }
7913  
7914    // Finally, we're ready to print the data we've gathered.
7915    outs() << "Contents of __compact_unwind section:\n";
7916    for (auto &Entry : CompactUnwinds) {
7917      outs() << "  Entry at offset "
7918             << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
7919  
7920      // 1. Start of the region this entry applies to.
7921      outs() << "    start:                " << format("0x%" PRIx64,
7922                                                       Entry.FunctionAddr) << ' ';
7923      printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
7924      outs() << '\n';
7925  
7926      // 2. Length of the region this entry applies to.
7927      outs() << "    length:               " << format("0x%" PRIx32, Entry.Length)
7928             << '\n';
7929      // 3. The 32-bit compact encoding.
7930      outs() << "    compact encoding:     "
7931             << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
7932  
7933      // 4. The personality function, if present.
7934      if (Entry.PersonalityReloc.getObject()) {
7935        outs() << "    personality function: "
7936               << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
7937        printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
7938                             Entry.PersonalityAddr);
7939        outs() << '\n';
7940      }
7941  
7942      // 5. This entry's language-specific data area.
7943      if (Entry.LSDAReloc.getObject()) {
7944        outs() << "    LSDA:                 " << format("0x%" PRIx64,
7945                                                         Entry.LSDAAddr) << ' ';
7946        printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
7947        outs() << '\n';
7948      }
7949    }
7950  }
7951  
7952  //===----------------------------------------------------------------------===//
7953  // __unwind_info section dumping
7954  //===----------------------------------------------------------------------===//
7955  
printRegularSecondLevelUnwindPage(StringRef PageData)7956  static void printRegularSecondLevelUnwindPage(StringRef PageData) {
7957    ptrdiff_t Pos = 0;
7958    uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7959    (void)Kind;
7960    assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
7961  
7962    uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7963    uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7964  
7965    Pos = EntriesStart;
7966    for (unsigned i = 0; i < NumEntries; ++i) {
7967      uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
7968      uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
7969  
7970      outs() << "      [" << i << "]: "
7971             << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7972             << ", "
7973             << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
7974    }
7975  }
7976  
printCompressedSecondLevelUnwindPage(StringRef PageData,uint32_t FunctionBase,const SmallVectorImpl<uint32_t> & CommonEncodings)7977  static void printCompressedSecondLevelUnwindPage(
7978      StringRef PageData, uint32_t FunctionBase,
7979      const SmallVectorImpl<uint32_t> &CommonEncodings) {
7980    ptrdiff_t Pos = 0;
7981    uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7982    (void)Kind;
7983    assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
7984  
7985    uint32_t NumCommonEncodings = CommonEncodings.size();
7986    uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7987    uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7988  
7989    uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos);
7990    uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos);
7991    SmallVector<uint32_t, 64> PageEncodings;
7992    if (NumPageEncodings) {
7993      outs() << "      Page encodings: (count = " << NumPageEncodings << ")\n";
7994      Pos = PageEncodingsStart;
7995      for (unsigned i = 0; i < NumPageEncodings; ++i) {
7996        uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
7997        PageEncodings.push_back(Encoding);
7998        outs() << "        encoding[" << (i + NumCommonEncodings)
7999               << "]: " << format("0x%08" PRIx32, Encoding) << '\n';
8000      }
8001    }
8002  
8003    Pos = EntriesStart;
8004    for (unsigned i = 0; i < NumEntries; ++i) {
8005      uint32_t Entry = readNext<uint32_t>(PageData, Pos);
8006      uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
8007      uint32_t EncodingIdx = Entry >> 24;
8008  
8009      uint32_t Encoding;
8010      if (EncodingIdx < NumCommonEncodings)
8011        Encoding = CommonEncodings[EncodingIdx];
8012      else
8013        Encoding = PageEncodings[EncodingIdx - NumCommonEncodings];
8014  
8015      outs() << "      [" << i << "]: "
8016             << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8017             << ", "
8018             << "encoding[" << EncodingIdx
8019             << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
8020    }
8021  }
8022  
printMachOUnwindInfoSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & UnwindInfo)8023  static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
8024                                          std::map<uint64_t, SymbolRef> &Symbols,
8025                                          const SectionRef &UnwindInfo) {
8026  
8027    if (!Obj->isLittleEndian()) {
8028      outs() << "Skipping big-endian __unwind_info section\n";
8029      return;
8030    }
8031  
8032    outs() << "Contents of __unwind_info section:\n";
8033  
8034    StringRef Contents =
8035        unwrapOrError(UnwindInfo.getContents(), Obj->getFileName());
8036    ptrdiff_t Pos = 0;
8037  
8038    //===----------------------------------
8039    // Section header
8040    //===----------------------------------
8041  
8042    uint32_t Version = readNext<uint32_t>(Contents, Pos);
8043    outs() << "  Version:                                   "
8044           << format("0x%" PRIx32, Version) << '\n';
8045    if (Version != 1) {
8046      outs() << "    Skipping section with unknown version\n";
8047      return;
8048    }
8049  
8050    uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
8051    outs() << "  Common encodings array section offset:     "
8052           << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
8053    uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
8054    outs() << "  Number of common encodings in array:       "
8055           << format("0x%" PRIx32, NumCommonEncodings) << '\n';
8056  
8057    uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
8058    outs() << "  Personality function array section offset: "
8059           << format("0x%" PRIx32, PersonalitiesStart) << '\n';
8060    uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
8061    outs() << "  Number of personality functions in array:  "
8062           << format("0x%" PRIx32, NumPersonalities) << '\n';
8063  
8064    uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
8065    outs() << "  Index array section offset:                "
8066           << format("0x%" PRIx32, IndicesStart) << '\n';
8067    uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
8068    outs() << "  Number of indices in array:                "
8069           << format("0x%" PRIx32, NumIndices) << '\n';
8070  
8071    //===----------------------------------
8072    // A shared list of common encodings
8073    //===----------------------------------
8074  
8075    // These occupy indices in the range [0, N] whenever an encoding is referenced
8076    // from a compressed 2nd level index table. In practice the linker only
8077    // creates ~128 of these, so that indices are available to embed encodings in
8078    // the 2nd level index.
8079  
8080    SmallVector<uint32_t, 64> CommonEncodings;
8081    outs() << "  Common encodings: (count = " << NumCommonEncodings << ")\n";
8082    Pos = CommonEncodingsStart;
8083    for (unsigned i = 0; i < NumCommonEncodings; ++i) {
8084      uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
8085      CommonEncodings.push_back(Encoding);
8086  
8087      outs() << "    encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
8088             << '\n';
8089    }
8090  
8091    //===----------------------------------
8092    // Personality functions used in this executable
8093    //===----------------------------------
8094  
8095    // There should be only a handful of these (one per source language,
8096    // roughly). Particularly since they only get 2 bits in the compact encoding.
8097  
8098    outs() << "  Personality functions: (count = " << NumPersonalities << ")\n";
8099    Pos = PersonalitiesStart;
8100    for (unsigned i = 0; i < NumPersonalities; ++i) {
8101      uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
8102      outs() << "    personality[" << i + 1
8103             << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
8104    }
8105  
8106    //===----------------------------------
8107    // The level 1 index entries
8108    //===----------------------------------
8109  
8110    // These specify an approximate place to start searching for the more detailed
8111    // information, sorted by PC.
8112  
8113    struct IndexEntry {
8114      uint32_t FunctionOffset;
8115      uint32_t SecondLevelPageStart;
8116      uint32_t LSDAStart;
8117    };
8118  
8119    SmallVector<IndexEntry, 4> IndexEntries;
8120  
8121    outs() << "  Top level indices: (count = " << NumIndices << ")\n";
8122    Pos = IndicesStart;
8123    for (unsigned i = 0; i < NumIndices; ++i) {
8124      IndexEntry Entry;
8125  
8126      Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
8127      Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
8128      Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
8129      IndexEntries.push_back(Entry);
8130  
8131      outs() << "    [" << i << "]: "
8132             << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
8133             << ", "
8134             << "2nd level page offset="
8135             << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
8136             << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
8137    }
8138  
8139    //===----------------------------------
8140    // Next come the LSDA tables
8141    //===----------------------------------
8142  
8143    // The LSDA layout is rather implicit: it's a contiguous array of entries from
8144    // the first top-level index's LSDAOffset to the last (sentinel).
8145  
8146    outs() << "  LSDA descriptors:\n";
8147    Pos = IndexEntries[0].LSDAStart;
8148    const uint32_t LSDASize = 2 * sizeof(uint32_t);
8149    int NumLSDAs =
8150        (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
8151  
8152    for (int i = 0; i < NumLSDAs; ++i) {
8153      uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
8154      uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
8155      outs() << "    [" << i << "]: "
8156             << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8157             << ", "
8158             << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
8159    }
8160  
8161    //===----------------------------------
8162    // Finally, the 2nd level indices
8163    //===----------------------------------
8164  
8165    // Generally these are 4K in size, and have 2 possible forms:
8166    //   + Regular stores up to 511 entries with disparate encodings
8167    //   + Compressed stores up to 1021 entries if few enough compact encoding
8168    //     values are used.
8169    outs() << "  Second level indices:\n";
8170    for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
8171      // The final sentinel top-level index has no associated 2nd level page
8172      if (IndexEntries[i].SecondLevelPageStart == 0)
8173        break;
8174  
8175      outs() << "    Second level index[" << i << "]: "
8176             << "offset in section="
8177             << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
8178             << ", "
8179             << "base function offset="
8180             << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
8181  
8182      Pos = IndexEntries[i].SecondLevelPageStart;
8183      if (Pos + sizeof(uint32_t) > Contents.size()) {
8184        outs() << "warning: invalid offset for second level page: " << Pos << '\n';
8185        continue;
8186      }
8187  
8188      uint32_t Kind =
8189          *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
8190      if (Kind == 2)
8191        printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
8192      else if (Kind == 3)
8193        printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
8194                                             IndexEntries[i].FunctionOffset,
8195                                             CommonEncodings);
8196      else
8197        outs() << "    Skipping 2nd level page with unknown kind " << Kind
8198               << '\n';
8199    }
8200  }
8201  
printMachOUnwindInfo(const MachOObjectFile * Obj)8202  void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) {
8203    std::map<uint64_t, SymbolRef> Symbols;
8204    for (const SymbolRef &SymRef : Obj->symbols()) {
8205      // Discard any undefined or absolute symbols. They're not going to take part
8206      // in the convenience lookup for unwind info and just take up resources.
8207      auto SectOrErr = SymRef.getSection();
8208      if (!SectOrErr) {
8209        // TODO: Actually report errors helpfully.
8210        consumeError(SectOrErr.takeError());
8211        continue;
8212      }
8213      section_iterator Section = *SectOrErr;
8214      if (Section == Obj->section_end())
8215        continue;
8216  
8217      uint64_t Addr = cantFail(SymRef.getValue());
8218      Symbols.insert(std::make_pair(Addr, SymRef));
8219    }
8220  
8221    for (const SectionRef &Section : Obj->sections()) {
8222      StringRef SectName;
8223      if (Expected<StringRef> NameOrErr = Section.getName())
8224        SectName = *NameOrErr;
8225      else
8226        consumeError(NameOrErr.takeError());
8227  
8228      if (SectName == "__compact_unwind")
8229        printMachOCompactUnwindSection(Obj, Symbols, Section);
8230      else if (SectName == "__unwind_info")
8231        printMachOUnwindInfoSection(Obj, Symbols, Section);
8232    }
8233  }
8234  
PrintMachHeader(uint32_t magic,uint32_t cputype,uint32_t cpusubtype,uint32_t filetype,uint32_t ncmds,uint32_t sizeofcmds,uint32_t flags,bool verbose)8235  static void PrintMachHeader(uint32_t magic, uint32_t cputype,
8236                              uint32_t cpusubtype, uint32_t filetype,
8237                              uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
8238                              bool verbose) {
8239    outs() << "Mach header\n";
8240    outs() << "      magic cputype cpusubtype  caps    filetype ncmds "
8241              "sizeofcmds      flags\n";
8242    if (verbose) {
8243      if (magic == MachO::MH_MAGIC)
8244        outs() << "   MH_MAGIC";
8245      else if (magic == MachO::MH_MAGIC_64)
8246        outs() << "MH_MAGIC_64";
8247      else
8248        outs() << format(" 0x%08" PRIx32, magic);
8249      switch (cputype) {
8250      case MachO::CPU_TYPE_I386:
8251        outs() << "    I386";
8252        switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8253        case MachO::CPU_SUBTYPE_I386_ALL:
8254          outs() << "        ALL";
8255          break;
8256        default:
8257          outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8258          break;
8259        }
8260        break;
8261      case MachO::CPU_TYPE_X86_64:
8262        outs() << "  X86_64";
8263        switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8264        case MachO::CPU_SUBTYPE_X86_64_ALL:
8265          outs() << "        ALL";
8266          break;
8267        case MachO::CPU_SUBTYPE_X86_64_H:
8268          outs() << "    Haswell";
8269          break;
8270        default:
8271          outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8272          break;
8273        }
8274        break;
8275      case MachO::CPU_TYPE_ARM:
8276        outs() << "     ARM";
8277        switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8278        case MachO::CPU_SUBTYPE_ARM_ALL:
8279          outs() << "        ALL";
8280          break;
8281        case MachO::CPU_SUBTYPE_ARM_V4T:
8282          outs() << "        V4T";
8283          break;
8284        case MachO::CPU_SUBTYPE_ARM_V5TEJ:
8285          outs() << "      V5TEJ";
8286          break;
8287        case MachO::CPU_SUBTYPE_ARM_XSCALE:
8288          outs() << "     XSCALE";
8289          break;
8290        case MachO::CPU_SUBTYPE_ARM_V6:
8291          outs() << "         V6";
8292          break;
8293        case MachO::CPU_SUBTYPE_ARM_V6M:
8294          outs() << "        V6M";
8295          break;
8296        case MachO::CPU_SUBTYPE_ARM_V7:
8297          outs() << "         V7";
8298          break;
8299        case MachO::CPU_SUBTYPE_ARM_V7EM:
8300          outs() << "       V7EM";
8301          break;
8302        case MachO::CPU_SUBTYPE_ARM_V7K:
8303          outs() << "        V7K";
8304          break;
8305        case MachO::CPU_SUBTYPE_ARM_V7M:
8306          outs() << "        V7M";
8307          break;
8308        case MachO::CPU_SUBTYPE_ARM_V7S:
8309          outs() << "        V7S";
8310          break;
8311        default:
8312          outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8313          break;
8314        }
8315        break;
8316      case MachO::CPU_TYPE_ARM64:
8317        outs() << "   ARM64";
8318        switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8319        case MachO::CPU_SUBTYPE_ARM64_ALL:
8320          outs() << "        ALL";
8321          break;
8322        case MachO::CPU_SUBTYPE_ARM64_V8:
8323          outs() << "         V8";
8324          break;
8325        case MachO::CPU_SUBTYPE_ARM64E:
8326          outs() << "          E";
8327          break;
8328        default:
8329          outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8330          break;
8331        }
8332        break;
8333      case MachO::CPU_TYPE_ARM64_32:
8334        outs() << " ARM64_32";
8335        switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8336        case MachO::CPU_SUBTYPE_ARM64_32_V8:
8337          outs() << "        V8";
8338          break;
8339        default:
8340          outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8341          break;
8342        }
8343        break;
8344      case MachO::CPU_TYPE_POWERPC:
8345        outs() << "     PPC";
8346        switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8347        case MachO::CPU_SUBTYPE_POWERPC_ALL:
8348          outs() << "        ALL";
8349          break;
8350        default:
8351          outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8352          break;
8353        }
8354        break;
8355      case MachO::CPU_TYPE_POWERPC64:
8356        outs() << "   PPC64";
8357        switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8358        case MachO::CPU_SUBTYPE_POWERPC_ALL:
8359          outs() << "        ALL";
8360          break;
8361        default:
8362          outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8363          break;
8364        }
8365        break;
8366      default:
8367        outs() << format(" %7d", cputype);
8368        outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8369        break;
8370      }
8371      if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
8372        outs() << " LIB64";
8373      } else {
8374        outs() << format("  0x%02" PRIx32,
8375                         (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8376      }
8377      switch (filetype) {
8378      case MachO::MH_OBJECT:
8379        outs() << "      OBJECT";
8380        break;
8381      case MachO::MH_EXECUTE:
8382        outs() << "     EXECUTE";
8383        break;
8384      case MachO::MH_FVMLIB:
8385        outs() << "      FVMLIB";
8386        break;
8387      case MachO::MH_CORE:
8388        outs() << "        CORE";
8389        break;
8390      case MachO::MH_PRELOAD:
8391        outs() << "     PRELOAD";
8392        break;
8393      case MachO::MH_DYLIB:
8394        outs() << "       DYLIB";
8395        break;
8396      case MachO::MH_DYLIB_STUB:
8397        outs() << "  DYLIB_STUB";
8398        break;
8399      case MachO::MH_DYLINKER:
8400        outs() << "    DYLINKER";
8401        break;
8402      case MachO::MH_BUNDLE:
8403        outs() << "      BUNDLE";
8404        break;
8405      case MachO::MH_DSYM:
8406        outs() << "        DSYM";
8407        break;
8408      case MachO::MH_KEXT_BUNDLE:
8409        outs() << "  KEXTBUNDLE";
8410        break;
8411      case MachO::MH_FILESET:
8412        outs() << "     FILESET";
8413        break;
8414      default:
8415        outs() << format("  %10u", filetype);
8416        break;
8417      }
8418      outs() << format(" %5u", ncmds);
8419      outs() << format(" %10u", sizeofcmds);
8420      uint32_t f = flags;
8421      if (f & MachO::MH_NOUNDEFS) {
8422        outs() << "   NOUNDEFS";
8423        f &= ~MachO::MH_NOUNDEFS;
8424      }
8425      if (f & MachO::MH_INCRLINK) {
8426        outs() << " INCRLINK";
8427        f &= ~MachO::MH_INCRLINK;
8428      }
8429      if (f & MachO::MH_DYLDLINK) {
8430        outs() << " DYLDLINK";
8431        f &= ~MachO::MH_DYLDLINK;
8432      }
8433      if (f & MachO::MH_BINDATLOAD) {
8434        outs() << " BINDATLOAD";
8435        f &= ~MachO::MH_BINDATLOAD;
8436      }
8437      if (f & MachO::MH_PREBOUND) {
8438        outs() << " PREBOUND";
8439        f &= ~MachO::MH_PREBOUND;
8440      }
8441      if (f & MachO::MH_SPLIT_SEGS) {
8442        outs() << " SPLIT_SEGS";
8443        f &= ~MachO::MH_SPLIT_SEGS;
8444      }
8445      if (f & MachO::MH_LAZY_INIT) {
8446        outs() << " LAZY_INIT";
8447        f &= ~MachO::MH_LAZY_INIT;
8448      }
8449      if (f & MachO::MH_TWOLEVEL) {
8450        outs() << " TWOLEVEL";
8451        f &= ~MachO::MH_TWOLEVEL;
8452      }
8453      if (f & MachO::MH_FORCE_FLAT) {
8454        outs() << " FORCE_FLAT";
8455        f &= ~MachO::MH_FORCE_FLAT;
8456      }
8457      if (f & MachO::MH_NOMULTIDEFS) {
8458        outs() << " NOMULTIDEFS";
8459        f &= ~MachO::MH_NOMULTIDEFS;
8460      }
8461      if (f & MachO::MH_NOFIXPREBINDING) {
8462        outs() << " NOFIXPREBINDING";
8463        f &= ~MachO::MH_NOFIXPREBINDING;
8464      }
8465      if (f & MachO::MH_PREBINDABLE) {
8466        outs() << " PREBINDABLE";
8467        f &= ~MachO::MH_PREBINDABLE;
8468      }
8469      if (f & MachO::MH_ALLMODSBOUND) {
8470        outs() << " ALLMODSBOUND";
8471        f &= ~MachO::MH_ALLMODSBOUND;
8472      }
8473      if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
8474        outs() << " SUBSECTIONS_VIA_SYMBOLS";
8475        f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
8476      }
8477      if (f & MachO::MH_CANONICAL) {
8478        outs() << " CANONICAL";
8479        f &= ~MachO::MH_CANONICAL;
8480      }
8481      if (f & MachO::MH_WEAK_DEFINES) {
8482        outs() << " WEAK_DEFINES";
8483        f &= ~MachO::MH_WEAK_DEFINES;
8484      }
8485      if (f & MachO::MH_BINDS_TO_WEAK) {
8486        outs() << " BINDS_TO_WEAK";
8487        f &= ~MachO::MH_BINDS_TO_WEAK;
8488      }
8489      if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
8490        outs() << " ALLOW_STACK_EXECUTION";
8491        f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
8492      }
8493      if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
8494        outs() << " DEAD_STRIPPABLE_DYLIB";
8495        f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
8496      }
8497      if (f & MachO::MH_PIE) {
8498        outs() << " PIE";
8499        f &= ~MachO::MH_PIE;
8500      }
8501      if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
8502        outs() << " NO_REEXPORTED_DYLIBS";
8503        f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
8504      }
8505      if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
8506        outs() << " MH_HAS_TLV_DESCRIPTORS";
8507        f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
8508      }
8509      if (f & MachO::MH_NO_HEAP_EXECUTION) {
8510        outs() << " MH_NO_HEAP_EXECUTION";
8511        f &= ~MachO::MH_NO_HEAP_EXECUTION;
8512      }
8513      if (f & MachO::MH_APP_EXTENSION_SAFE) {
8514        outs() << " APP_EXTENSION_SAFE";
8515        f &= ~MachO::MH_APP_EXTENSION_SAFE;
8516      }
8517      if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
8518        outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO";
8519        f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO;
8520      }
8521      if (f != 0 || flags == 0)
8522        outs() << format(" 0x%08" PRIx32, f);
8523    } else {
8524      outs() << format(" 0x%08" PRIx32, magic);
8525      outs() << format(" %7d", cputype);
8526      outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8527      outs() << format("  0x%02" PRIx32,
8528                       (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8529      outs() << format("  %10u", filetype);
8530      outs() << format(" %5u", ncmds);
8531      outs() << format(" %10u", sizeofcmds);
8532      outs() << format(" 0x%08" PRIx32, flags);
8533    }
8534    outs() << "\n";
8535  }
8536  
PrintSegmentCommand(uint32_t cmd,uint32_t cmdsize,StringRef SegName,uint64_t vmaddr,uint64_t vmsize,uint64_t fileoff,uint64_t filesize,uint32_t maxprot,uint32_t initprot,uint32_t nsects,uint32_t flags,uint32_t object_size,bool verbose)8537  static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
8538                                  StringRef SegName, uint64_t vmaddr,
8539                                  uint64_t vmsize, uint64_t fileoff,
8540                                  uint64_t filesize, uint32_t maxprot,
8541                                  uint32_t initprot, uint32_t nsects,
8542                                  uint32_t flags, uint32_t object_size,
8543                                  bool verbose) {
8544    uint64_t expected_cmdsize;
8545    if (cmd == MachO::LC_SEGMENT) {
8546      outs() << "      cmd LC_SEGMENT\n";
8547      expected_cmdsize = nsects;
8548      expected_cmdsize *= sizeof(struct MachO::section);
8549      expected_cmdsize += sizeof(struct MachO::segment_command);
8550    } else {
8551      outs() << "      cmd LC_SEGMENT_64\n";
8552      expected_cmdsize = nsects;
8553      expected_cmdsize *= sizeof(struct MachO::section_64);
8554      expected_cmdsize += sizeof(struct MachO::segment_command_64);
8555    }
8556    outs() << "  cmdsize " << cmdsize;
8557    if (cmdsize != expected_cmdsize)
8558      outs() << " Inconsistent size\n";
8559    else
8560      outs() << "\n";
8561    outs() << "  segname " << SegName << "\n";
8562    if (cmd == MachO::LC_SEGMENT_64) {
8563      outs() << "   vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
8564      outs() << "   vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
8565    } else {
8566      outs() << "   vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
8567      outs() << "   vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
8568    }
8569    outs() << "  fileoff " << fileoff;
8570    if (fileoff > object_size)
8571      outs() << " (past end of file)\n";
8572    else
8573      outs() << "\n";
8574    outs() << " filesize " << filesize;
8575    if (fileoff + filesize > object_size)
8576      outs() << " (past end of file)\n";
8577    else
8578      outs() << "\n";
8579    if (verbose) {
8580      if ((maxprot &
8581           ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8582             MachO::VM_PROT_EXECUTE)) != 0)
8583        outs() << "  maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
8584      else {
8585        outs() << "  maxprot ";
8586        outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
8587        outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8588        outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8589      }
8590      if ((initprot &
8591           ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8592             MachO::VM_PROT_EXECUTE)) != 0)
8593        outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
8594      else {
8595        outs() << " initprot ";
8596        outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
8597        outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8598        outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8599      }
8600    } else {
8601      outs() << "  maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
8602      outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
8603    }
8604    outs() << "   nsects " << nsects << "\n";
8605    if (verbose) {
8606      outs() << "    flags";
8607      if (flags == 0)
8608        outs() << " (none)\n";
8609      else {
8610        if (flags & MachO::SG_HIGHVM) {
8611          outs() << " HIGHVM";
8612          flags &= ~MachO::SG_HIGHVM;
8613        }
8614        if (flags & MachO::SG_FVMLIB) {
8615          outs() << " FVMLIB";
8616          flags &= ~MachO::SG_FVMLIB;
8617        }
8618        if (flags & MachO::SG_NORELOC) {
8619          outs() << " NORELOC";
8620          flags &= ~MachO::SG_NORELOC;
8621        }
8622        if (flags & MachO::SG_PROTECTED_VERSION_1) {
8623          outs() << " PROTECTED_VERSION_1";
8624          flags &= ~MachO::SG_PROTECTED_VERSION_1;
8625        }
8626        if (flags & MachO::SG_READ_ONLY) {
8627          // Apple's otool prints the SG_ prefix for this flag, but not for the
8628          // others.
8629          outs() << " SG_READ_ONLY";
8630          flags &= ~MachO::SG_READ_ONLY;
8631        }
8632        if (flags)
8633          outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
8634        else
8635          outs() << "\n";
8636      }
8637    } else {
8638      outs() << "    flags " << format("0x%" PRIx32, flags) << "\n";
8639    }
8640  }
8641  
PrintSection(const char * sectname,const char * segname,uint64_t addr,uint64_t size,uint32_t offset,uint32_t align,uint32_t reloff,uint32_t nreloc,uint32_t flags,uint32_t reserved1,uint32_t reserved2,uint32_t cmd,const char * sg_segname,uint32_t filetype,uint32_t object_size,bool verbose)8642  static void PrintSection(const char *sectname, const char *segname,
8643                           uint64_t addr, uint64_t size, uint32_t offset,
8644                           uint32_t align, uint32_t reloff, uint32_t nreloc,
8645                           uint32_t flags, uint32_t reserved1, uint32_t reserved2,
8646                           uint32_t cmd, const char *sg_segname,
8647                           uint32_t filetype, uint32_t object_size,
8648                           bool verbose) {
8649    outs() << "Section\n";
8650    outs() << "  sectname " << format("%.16s\n", sectname);
8651    outs() << "   segname " << format("%.16s", segname);
8652    if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
8653      outs() << " (does not match segment)\n";
8654    else
8655      outs() << "\n";
8656    if (cmd == MachO::LC_SEGMENT_64) {
8657      outs() << "      addr " << format("0x%016" PRIx64, addr) << "\n";
8658      outs() << "      size " << format("0x%016" PRIx64, size);
8659    } else {
8660      outs() << "      addr " << format("0x%08" PRIx64, addr) << "\n";
8661      outs() << "      size " << format("0x%08" PRIx64, size);
8662    }
8663    if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
8664      outs() << " (past end of file)\n";
8665    else
8666      outs() << "\n";
8667    outs() << "    offset " << offset;
8668    if (offset > object_size)
8669      outs() << " (past end of file)\n";
8670    else
8671      outs() << "\n";
8672    uint32_t align_shifted = 1 << align;
8673    outs() << "     align 2^" << align << " (" << align_shifted << ")\n";
8674    outs() << "    reloff " << reloff;
8675    if (reloff > object_size)
8676      outs() << " (past end of file)\n";
8677    else
8678      outs() << "\n";
8679    outs() << "    nreloc " << nreloc;
8680    if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
8681      outs() << " (past end of file)\n";
8682    else
8683      outs() << "\n";
8684    uint32_t section_type = flags & MachO::SECTION_TYPE;
8685    if (verbose) {
8686      outs() << "      type";
8687      if (section_type == MachO::S_REGULAR)
8688        outs() << " S_REGULAR\n";
8689      else if (section_type == MachO::S_ZEROFILL)
8690        outs() << " S_ZEROFILL\n";
8691      else if (section_type == MachO::S_CSTRING_LITERALS)
8692        outs() << " S_CSTRING_LITERALS\n";
8693      else if (section_type == MachO::S_4BYTE_LITERALS)
8694        outs() << " S_4BYTE_LITERALS\n";
8695      else if (section_type == MachO::S_8BYTE_LITERALS)
8696        outs() << " S_8BYTE_LITERALS\n";
8697      else if (section_type == MachO::S_16BYTE_LITERALS)
8698        outs() << " S_16BYTE_LITERALS\n";
8699      else if (section_type == MachO::S_LITERAL_POINTERS)
8700        outs() << " S_LITERAL_POINTERS\n";
8701      else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
8702        outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
8703      else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
8704        outs() << " S_LAZY_SYMBOL_POINTERS\n";
8705      else if (section_type == MachO::S_SYMBOL_STUBS)
8706        outs() << " S_SYMBOL_STUBS\n";
8707      else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
8708        outs() << " S_MOD_INIT_FUNC_POINTERS\n";
8709      else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
8710        outs() << " S_MOD_TERM_FUNC_POINTERS\n";
8711      else if (section_type == MachO::S_COALESCED)
8712        outs() << " S_COALESCED\n";
8713      else if (section_type == MachO::S_INTERPOSING)
8714        outs() << " S_INTERPOSING\n";
8715      else if (section_type == MachO::S_DTRACE_DOF)
8716        outs() << " S_DTRACE_DOF\n";
8717      else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
8718        outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
8719      else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
8720        outs() << " S_THREAD_LOCAL_REGULAR\n";
8721      else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
8722        outs() << " S_THREAD_LOCAL_ZEROFILL\n";
8723      else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
8724        outs() << " S_THREAD_LOCAL_VARIABLES\n";
8725      else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8726        outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
8727      else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
8728        outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
8729      else if (section_type == MachO::S_INIT_FUNC_OFFSETS)
8730        outs() << " S_INIT_FUNC_OFFSETS\n";
8731      else
8732        outs() << format("0x%08" PRIx32, section_type) << "\n";
8733      outs() << "attributes";
8734      uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
8735      if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
8736        outs() << " PURE_INSTRUCTIONS";
8737      if (section_attributes & MachO::S_ATTR_NO_TOC)
8738        outs() << " NO_TOC";
8739      if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
8740        outs() << " STRIP_STATIC_SYMS";
8741      if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
8742        outs() << " NO_DEAD_STRIP";
8743      if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
8744        outs() << " LIVE_SUPPORT";
8745      if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
8746        outs() << " SELF_MODIFYING_CODE";
8747      if (section_attributes & MachO::S_ATTR_DEBUG)
8748        outs() << " DEBUG";
8749      if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
8750        outs() << " SOME_INSTRUCTIONS";
8751      if (section_attributes & MachO::S_ATTR_EXT_RELOC)
8752        outs() << " EXT_RELOC";
8753      if (section_attributes & MachO::S_ATTR_LOC_RELOC)
8754        outs() << " LOC_RELOC";
8755      if (section_attributes == 0)
8756        outs() << " (none)";
8757      outs() << "\n";
8758    } else
8759      outs() << "     flags " << format("0x%08" PRIx32, flags) << "\n";
8760    outs() << " reserved1 " << reserved1;
8761    if (section_type == MachO::S_SYMBOL_STUBS ||
8762        section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
8763        section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
8764        section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
8765        section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8766      outs() << " (index into indirect symbol table)\n";
8767    else
8768      outs() << "\n";
8769    outs() << " reserved2 " << reserved2;
8770    if (section_type == MachO::S_SYMBOL_STUBS)
8771      outs() << " (size of stubs)\n";
8772    else
8773      outs() << "\n";
8774  }
8775  
PrintSymtabLoadCommand(MachO::symtab_command st,bool Is64Bit,uint32_t object_size)8776  static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
8777                                     uint32_t object_size) {
8778    outs() << "     cmd LC_SYMTAB\n";
8779    outs() << " cmdsize " << st.cmdsize;
8780    if (st.cmdsize != sizeof(struct MachO::symtab_command))
8781      outs() << " Incorrect size\n";
8782    else
8783      outs() << "\n";
8784    outs() << "  symoff " << st.symoff;
8785    if (st.symoff > object_size)
8786      outs() << " (past end of file)\n";
8787    else
8788      outs() << "\n";
8789    outs() << "   nsyms " << st.nsyms;
8790    uint64_t big_size;
8791    if (Is64Bit) {
8792      big_size = st.nsyms;
8793      big_size *= sizeof(struct MachO::nlist_64);
8794      big_size += st.symoff;
8795      if (big_size > object_size)
8796        outs() << " (past end of file)\n";
8797      else
8798        outs() << "\n";
8799    } else {
8800      big_size = st.nsyms;
8801      big_size *= sizeof(struct MachO::nlist);
8802      big_size += st.symoff;
8803      if (big_size > object_size)
8804        outs() << " (past end of file)\n";
8805      else
8806        outs() << "\n";
8807    }
8808    outs() << "  stroff " << st.stroff;
8809    if (st.stroff > object_size)
8810      outs() << " (past end of file)\n";
8811    else
8812      outs() << "\n";
8813    outs() << " strsize " << st.strsize;
8814    big_size = st.stroff;
8815    big_size += st.strsize;
8816    if (big_size > object_size)
8817      outs() << " (past end of file)\n";
8818    else
8819      outs() << "\n";
8820  }
8821  
PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,uint32_t nsyms,uint32_t object_size,bool Is64Bit)8822  static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
8823                                       uint32_t nsyms, uint32_t object_size,
8824                                       bool Is64Bit) {
8825    outs() << "            cmd LC_DYSYMTAB\n";
8826    outs() << "        cmdsize " << dyst.cmdsize;
8827    if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
8828      outs() << " Incorrect size\n";
8829    else
8830      outs() << "\n";
8831    outs() << "      ilocalsym " << dyst.ilocalsym;
8832    if (dyst.ilocalsym > nsyms)
8833      outs() << " (greater than the number of symbols)\n";
8834    else
8835      outs() << "\n";
8836    outs() << "      nlocalsym " << dyst.nlocalsym;
8837    uint64_t big_size;
8838    big_size = dyst.ilocalsym;
8839    big_size += dyst.nlocalsym;
8840    if (big_size > nsyms)
8841      outs() << " (past the end of the symbol table)\n";
8842    else
8843      outs() << "\n";
8844    outs() << "     iextdefsym " << dyst.iextdefsym;
8845    if (dyst.iextdefsym > nsyms)
8846      outs() << " (greater than the number of symbols)\n";
8847    else
8848      outs() << "\n";
8849    outs() << "     nextdefsym " << dyst.nextdefsym;
8850    big_size = dyst.iextdefsym;
8851    big_size += dyst.nextdefsym;
8852    if (big_size > nsyms)
8853      outs() << " (past the end of the symbol table)\n";
8854    else
8855      outs() << "\n";
8856    outs() << "      iundefsym " << dyst.iundefsym;
8857    if (dyst.iundefsym > nsyms)
8858      outs() << " (greater than the number of symbols)\n";
8859    else
8860      outs() << "\n";
8861    outs() << "      nundefsym " << dyst.nundefsym;
8862    big_size = dyst.iundefsym;
8863    big_size += dyst.nundefsym;
8864    if (big_size > nsyms)
8865      outs() << " (past the end of the symbol table)\n";
8866    else
8867      outs() << "\n";
8868    outs() << "         tocoff " << dyst.tocoff;
8869    if (dyst.tocoff > object_size)
8870      outs() << " (past end of file)\n";
8871    else
8872      outs() << "\n";
8873    outs() << "           ntoc " << dyst.ntoc;
8874    big_size = dyst.ntoc;
8875    big_size *= sizeof(struct MachO::dylib_table_of_contents);
8876    big_size += dyst.tocoff;
8877    if (big_size > object_size)
8878      outs() << " (past end of file)\n";
8879    else
8880      outs() << "\n";
8881    outs() << "      modtaboff " << dyst.modtaboff;
8882    if (dyst.modtaboff > object_size)
8883      outs() << " (past end of file)\n";
8884    else
8885      outs() << "\n";
8886    outs() << "        nmodtab " << dyst.nmodtab;
8887    uint64_t modtabend;
8888    if (Is64Bit) {
8889      modtabend = dyst.nmodtab;
8890      modtabend *= sizeof(struct MachO::dylib_module_64);
8891      modtabend += dyst.modtaboff;
8892    } else {
8893      modtabend = dyst.nmodtab;
8894      modtabend *= sizeof(struct MachO::dylib_module);
8895      modtabend += dyst.modtaboff;
8896    }
8897    if (modtabend > object_size)
8898      outs() << " (past end of file)\n";
8899    else
8900      outs() << "\n";
8901    outs() << "   extrefsymoff " << dyst.extrefsymoff;
8902    if (dyst.extrefsymoff > object_size)
8903      outs() << " (past end of file)\n";
8904    else
8905      outs() << "\n";
8906    outs() << "    nextrefsyms " << dyst.nextrefsyms;
8907    big_size = dyst.nextrefsyms;
8908    big_size *= sizeof(struct MachO::dylib_reference);
8909    big_size += dyst.extrefsymoff;
8910    if (big_size > object_size)
8911      outs() << " (past end of file)\n";
8912    else
8913      outs() << "\n";
8914    outs() << " indirectsymoff " << dyst.indirectsymoff;
8915    if (dyst.indirectsymoff > object_size)
8916      outs() << " (past end of file)\n";
8917    else
8918      outs() << "\n";
8919    outs() << "  nindirectsyms " << dyst.nindirectsyms;
8920    big_size = dyst.nindirectsyms;
8921    big_size *= sizeof(uint32_t);
8922    big_size += dyst.indirectsymoff;
8923    if (big_size > object_size)
8924      outs() << " (past end of file)\n";
8925    else
8926      outs() << "\n";
8927    outs() << "      extreloff " << dyst.extreloff;
8928    if (dyst.extreloff > object_size)
8929      outs() << " (past end of file)\n";
8930    else
8931      outs() << "\n";
8932    outs() << "        nextrel " << dyst.nextrel;
8933    big_size = dyst.nextrel;
8934    big_size *= sizeof(struct MachO::relocation_info);
8935    big_size += dyst.extreloff;
8936    if (big_size > object_size)
8937      outs() << " (past end of file)\n";
8938    else
8939      outs() << "\n";
8940    outs() << "      locreloff " << dyst.locreloff;
8941    if (dyst.locreloff > object_size)
8942      outs() << " (past end of file)\n";
8943    else
8944      outs() << "\n";
8945    outs() << "        nlocrel " << dyst.nlocrel;
8946    big_size = dyst.nlocrel;
8947    big_size *= sizeof(struct MachO::relocation_info);
8948    big_size += dyst.locreloff;
8949    if (big_size > object_size)
8950      outs() << " (past end of file)\n";
8951    else
8952      outs() << "\n";
8953  }
8954  
PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,uint32_t object_size)8955  static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
8956                                       uint32_t object_size) {
8957    if (dc.cmd == MachO::LC_DYLD_INFO)
8958      outs() << "            cmd LC_DYLD_INFO\n";
8959    else
8960      outs() << "            cmd LC_DYLD_INFO_ONLY\n";
8961    outs() << "        cmdsize " << dc.cmdsize;
8962    if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
8963      outs() << " Incorrect size\n";
8964    else
8965      outs() << "\n";
8966    outs() << "     rebase_off " << dc.rebase_off;
8967    if (dc.rebase_off > object_size)
8968      outs() << " (past end of file)\n";
8969    else
8970      outs() << "\n";
8971    outs() << "    rebase_size " << dc.rebase_size;
8972    uint64_t big_size;
8973    big_size = dc.rebase_off;
8974    big_size += dc.rebase_size;
8975    if (big_size > object_size)
8976      outs() << " (past end of file)\n";
8977    else
8978      outs() << "\n";
8979    outs() << "       bind_off " << dc.bind_off;
8980    if (dc.bind_off > object_size)
8981      outs() << " (past end of file)\n";
8982    else
8983      outs() << "\n";
8984    outs() << "      bind_size " << dc.bind_size;
8985    big_size = dc.bind_off;
8986    big_size += dc.bind_size;
8987    if (big_size > object_size)
8988      outs() << " (past end of file)\n";
8989    else
8990      outs() << "\n";
8991    outs() << "  weak_bind_off " << dc.weak_bind_off;
8992    if (dc.weak_bind_off > object_size)
8993      outs() << " (past end of file)\n";
8994    else
8995      outs() << "\n";
8996    outs() << " weak_bind_size " << dc.weak_bind_size;
8997    big_size = dc.weak_bind_off;
8998    big_size += dc.weak_bind_size;
8999    if (big_size > object_size)
9000      outs() << " (past end of file)\n";
9001    else
9002      outs() << "\n";
9003    outs() << "  lazy_bind_off " << dc.lazy_bind_off;
9004    if (dc.lazy_bind_off > object_size)
9005      outs() << " (past end of file)\n";
9006    else
9007      outs() << "\n";
9008    outs() << " lazy_bind_size " << dc.lazy_bind_size;
9009    big_size = dc.lazy_bind_off;
9010    big_size += dc.lazy_bind_size;
9011    if (big_size > object_size)
9012      outs() << " (past end of file)\n";
9013    else
9014      outs() << "\n";
9015    outs() << "     export_off " << dc.export_off;
9016    if (dc.export_off > object_size)
9017      outs() << " (past end of file)\n";
9018    else
9019      outs() << "\n";
9020    outs() << "    export_size " << dc.export_size;
9021    big_size = dc.export_off;
9022    big_size += dc.export_size;
9023    if (big_size > object_size)
9024      outs() << " (past end of file)\n";
9025    else
9026      outs() << "\n";
9027  }
9028  
PrintDyldLoadCommand(MachO::dylinker_command dyld,const char * Ptr)9029  static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
9030                                   const char *Ptr) {
9031    if (dyld.cmd == MachO::LC_ID_DYLINKER)
9032      outs() << "          cmd LC_ID_DYLINKER\n";
9033    else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
9034      outs() << "          cmd LC_LOAD_DYLINKER\n";
9035    else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
9036      outs() << "          cmd LC_DYLD_ENVIRONMENT\n";
9037    else
9038      outs() << "          cmd ?(" << dyld.cmd << ")\n";
9039    outs() << "      cmdsize " << dyld.cmdsize;
9040    if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
9041      outs() << " Incorrect size\n";
9042    else
9043      outs() << "\n";
9044    if (dyld.name >= dyld.cmdsize)
9045      outs() << "         name ?(bad offset " << dyld.name << ")\n";
9046    else {
9047      const char *P = (const char *)(Ptr) + dyld.name;
9048      outs() << "         name " << P << " (offset " << dyld.name << ")\n";
9049    }
9050  }
9051  
PrintUuidLoadCommand(MachO::uuid_command uuid)9052  static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
9053    outs() << "     cmd LC_UUID\n";
9054    outs() << " cmdsize " << uuid.cmdsize;
9055    if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
9056      outs() << " Incorrect size\n";
9057    else
9058      outs() << "\n";
9059    outs() << "    uuid ";
9060    for (int i = 0; i < 16; ++i) {
9061      outs() << format("%02" PRIX32, uuid.uuid[i]);
9062      if (i == 3 || i == 5 || i == 7 || i == 9)
9063        outs() << "-";
9064    }
9065    outs() << "\n";
9066  }
9067  
PrintRpathLoadCommand(MachO::rpath_command rpath,const char * Ptr)9068  static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
9069    outs() << "          cmd LC_RPATH\n";
9070    outs() << "      cmdsize " << rpath.cmdsize;
9071    if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
9072      outs() << " Incorrect size\n";
9073    else
9074      outs() << "\n";
9075    if (rpath.path >= rpath.cmdsize)
9076      outs() << "         path ?(bad offset " << rpath.path << ")\n";
9077    else {
9078      const char *P = (const char *)(Ptr) + rpath.path;
9079      outs() << "         path " << P << " (offset " << rpath.path << ")\n";
9080    }
9081  }
9082  
PrintVersionMinLoadCommand(MachO::version_min_command vd)9083  static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
9084    StringRef LoadCmdName;
9085    switch (vd.cmd) {
9086    case MachO::LC_VERSION_MIN_MACOSX:
9087      LoadCmdName = "LC_VERSION_MIN_MACOSX";
9088      break;
9089    case MachO::LC_VERSION_MIN_IPHONEOS:
9090      LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
9091      break;
9092    case MachO::LC_VERSION_MIN_TVOS:
9093      LoadCmdName = "LC_VERSION_MIN_TVOS";
9094      break;
9095    case MachO::LC_VERSION_MIN_WATCHOS:
9096      LoadCmdName = "LC_VERSION_MIN_WATCHOS";
9097      break;
9098    default:
9099      llvm_unreachable("Unknown version min load command");
9100    }
9101  
9102    outs() << "      cmd " << LoadCmdName << '\n';
9103    outs() << "  cmdsize " << vd.cmdsize;
9104    if (vd.cmdsize != sizeof(struct MachO::version_min_command))
9105      outs() << " Incorrect size\n";
9106    else
9107      outs() << "\n";
9108    outs() << "  version "
9109           << MachOObjectFile::getVersionMinMajor(vd, false) << "."
9110           << MachOObjectFile::getVersionMinMinor(vd, false);
9111    uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
9112    if (Update != 0)
9113      outs() << "." << Update;
9114    outs() << "\n";
9115    if (vd.sdk == 0)
9116      outs() << "      sdk n/a";
9117    else {
9118      outs() << "      sdk "
9119             << MachOObjectFile::getVersionMinMajor(vd, true) << "."
9120             << MachOObjectFile::getVersionMinMinor(vd, true);
9121    }
9122    Update = MachOObjectFile::getVersionMinUpdate(vd, true);
9123    if (Update != 0)
9124      outs() << "." << Update;
9125    outs() << "\n";
9126  }
9127  
PrintNoteLoadCommand(MachO::note_command Nt)9128  static void PrintNoteLoadCommand(MachO::note_command Nt) {
9129    outs() << "       cmd LC_NOTE\n";
9130    outs() << "   cmdsize " << Nt.cmdsize;
9131    if (Nt.cmdsize != sizeof(struct MachO::note_command))
9132      outs() << " Incorrect size\n";
9133    else
9134      outs() << "\n";
9135    const char *d = Nt.data_owner;
9136    outs() << "data_owner " << format("%.16s\n", d);
9137    outs() << "    offset " << Nt.offset << "\n";
9138    outs() << "      size " << Nt.size << "\n";
9139  }
9140  
PrintBuildToolVersion(MachO::build_tool_version bv,bool verbose)9141  static void PrintBuildToolVersion(MachO::build_tool_version bv, bool verbose) {
9142    outs() << "      tool ";
9143    if (verbose)
9144      outs() << MachOObjectFile::getBuildTool(bv.tool);
9145    else
9146      outs() << bv.tool;
9147    outs() << "\n";
9148    outs() << "   version " << MachOObjectFile::getVersionString(bv.version)
9149           << "\n";
9150  }
9151  
PrintBuildVersionLoadCommand(const MachOObjectFile * obj,MachO::build_version_command bd,bool verbose)9152  static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj,
9153                                           MachO::build_version_command bd,
9154                                           bool verbose) {
9155    outs() << "       cmd LC_BUILD_VERSION\n";
9156    outs() << "   cmdsize " << bd.cmdsize;
9157    if (bd.cmdsize !=
9158        sizeof(struct MachO::build_version_command) +
9159            bd.ntools * sizeof(struct MachO::build_tool_version))
9160      outs() << " Incorrect size\n";
9161    else
9162      outs() << "\n";
9163    outs() << "  platform ";
9164    if (verbose)
9165      outs() << MachOObjectFile::getBuildPlatform(bd.platform);
9166    else
9167      outs() << bd.platform;
9168    outs() << "\n";
9169    if (bd.sdk)
9170      outs() << "       sdk " << MachOObjectFile::getVersionString(bd.sdk)
9171             << "\n";
9172    else
9173      outs() << "       sdk n/a\n";
9174    outs() << "     minos " << MachOObjectFile::getVersionString(bd.minos)
9175           << "\n";
9176    outs() << "    ntools " << bd.ntools << "\n";
9177    for (unsigned i = 0; i < bd.ntools; ++i) {
9178      MachO::build_tool_version bv = obj->getBuildToolVersion(i);
9179      PrintBuildToolVersion(bv, verbose);
9180    }
9181  }
9182  
PrintSourceVersionCommand(MachO::source_version_command sd)9183  static void PrintSourceVersionCommand(MachO::source_version_command sd) {
9184    outs() << "      cmd LC_SOURCE_VERSION\n";
9185    outs() << "  cmdsize " << sd.cmdsize;
9186    if (sd.cmdsize != sizeof(struct MachO::source_version_command))
9187      outs() << " Incorrect size\n";
9188    else
9189      outs() << "\n";
9190    uint64_t a = (sd.version >> 40) & 0xffffff;
9191    uint64_t b = (sd.version >> 30) & 0x3ff;
9192    uint64_t c = (sd.version >> 20) & 0x3ff;
9193    uint64_t d = (sd.version >> 10) & 0x3ff;
9194    uint64_t e = sd.version & 0x3ff;
9195    outs() << "  version " << a << "." << b;
9196    if (e != 0)
9197      outs() << "." << c << "." << d << "." << e;
9198    else if (d != 0)
9199      outs() << "." << c << "." << d;
9200    else if (c != 0)
9201      outs() << "." << c;
9202    outs() << "\n";
9203  }
9204  
PrintEntryPointCommand(MachO::entry_point_command ep)9205  static void PrintEntryPointCommand(MachO::entry_point_command ep) {
9206    outs() << "       cmd LC_MAIN\n";
9207    outs() << "   cmdsize " << ep.cmdsize;
9208    if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
9209      outs() << " Incorrect size\n";
9210    else
9211      outs() << "\n";
9212    outs() << "  entryoff " << ep.entryoff << "\n";
9213    outs() << " stacksize " << ep.stacksize << "\n";
9214  }
9215  
PrintEncryptionInfoCommand(MachO::encryption_info_command ec,uint32_t object_size)9216  static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
9217                                         uint32_t object_size) {
9218    outs() << "          cmd LC_ENCRYPTION_INFO\n";
9219    outs() << "      cmdsize " << ec.cmdsize;
9220    if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
9221      outs() << " Incorrect size\n";
9222    else
9223      outs() << "\n";
9224    outs() << "     cryptoff " << ec.cryptoff;
9225    if (ec.cryptoff > object_size)
9226      outs() << " (past end of file)\n";
9227    else
9228      outs() << "\n";
9229    outs() << "    cryptsize " << ec.cryptsize;
9230    if (ec.cryptsize > object_size)
9231      outs() << " (past end of file)\n";
9232    else
9233      outs() << "\n";
9234    outs() << "      cryptid " << ec.cryptid << "\n";
9235  }
9236  
PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,uint32_t object_size)9237  static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
9238                                           uint32_t object_size) {
9239    outs() << "          cmd LC_ENCRYPTION_INFO_64\n";
9240    outs() << "      cmdsize " << ec.cmdsize;
9241    if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
9242      outs() << " Incorrect size\n";
9243    else
9244      outs() << "\n";
9245    outs() << "     cryptoff " << ec.cryptoff;
9246    if (ec.cryptoff > object_size)
9247      outs() << " (past end of file)\n";
9248    else
9249      outs() << "\n";
9250    outs() << "    cryptsize " << ec.cryptsize;
9251    if (ec.cryptsize > object_size)
9252      outs() << " (past end of file)\n";
9253    else
9254      outs() << "\n";
9255    outs() << "      cryptid " << ec.cryptid << "\n";
9256    outs() << "          pad " << ec.pad << "\n";
9257  }
9258  
PrintLinkerOptionCommand(MachO::linker_option_command lo,const char * Ptr)9259  static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
9260                                       const char *Ptr) {
9261    outs() << "     cmd LC_LINKER_OPTION\n";
9262    outs() << " cmdsize " << lo.cmdsize;
9263    if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
9264      outs() << " Incorrect size\n";
9265    else
9266      outs() << "\n";
9267    outs() << "   count " << lo.count << "\n";
9268    const char *string = Ptr + sizeof(struct MachO::linker_option_command);
9269    uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
9270    uint32_t i = 0;
9271    while (left > 0) {
9272      while (*string == '\0' && left > 0) {
9273        string++;
9274        left--;
9275      }
9276      if (left > 0) {
9277        i++;
9278        outs() << "  string #" << i << " " << format("%.*s\n", left, string);
9279        uint32_t NullPos = StringRef(string, left).find('\0');
9280        uint32_t len = std::min(NullPos, left) + 1;
9281        string += len;
9282        left -= len;
9283      }
9284    }
9285    if (lo.count != i)
9286      outs() << "   count " << lo.count << " does not match number of strings "
9287             << i << "\n";
9288  }
9289  
PrintSubFrameworkCommand(MachO::sub_framework_command sub,const char * Ptr)9290  static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
9291                                       const char *Ptr) {
9292    outs() << "          cmd LC_SUB_FRAMEWORK\n";
9293    outs() << "      cmdsize " << sub.cmdsize;
9294    if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
9295      outs() << " Incorrect size\n";
9296    else
9297      outs() << "\n";
9298    if (sub.umbrella < sub.cmdsize) {
9299      const char *P = Ptr + sub.umbrella;
9300      outs() << "     umbrella " << P << " (offset " << sub.umbrella << ")\n";
9301    } else {
9302      outs() << "     umbrella ?(bad offset " << sub.umbrella << ")\n";
9303    }
9304  }
9305  
PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,const char * Ptr)9306  static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
9307                                      const char *Ptr) {
9308    outs() << "          cmd LC_SUB_UMBRELLA\n";
9309    outs() << "      cmdsize " << sub.cmdsize;
9310    if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
9311      outs() << " Incorrect size\n";
9312    else
9313      outs() << "\n";
9314    if (sub.sub_umbrella < sub.cmdsize) {
9315      const char *P = Ptr + sub.sub_umbrella;
9316      outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
9317    } else {
9318      outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
9319    }
9320  }
9321  
PrintSubLibraryCommand(MachO::sub_library_command sub,const char * Ptr)9322  static void PrintSubLibraryCommand(MachO::sub_library_command sub,
9323                                     const char *Ptr) {
9324    outs() << "          cmd LC_SUB_LIBRARY\n";
9325    outs() << "      cmdsize " << sub.cmdsize;
9326    if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
9327      outs() << " Incorrect size\n";
9328    else
9329      outs() << "\n";
9330    if (sub.sub_library < sub.cmdsize) {
9331      const char *P = Ptr + sub.sub_library;
9332      outs() << "  sub_library " << P << " (offset " << sub.sub_library << ")\n";
9333    } else {
9334      outs() << "  sub_library ?(bad offset " << sub.sub_library << ")\n";
9335    }
9336  }
9337  
PrintSubClientCommand(MachO::sub_client_command sub,const char * Ptr)9338  static void PrintSubClientCommand(MachO::sub_client_command sub,
9339                                    const char *Ptr) {
9340    outs() << "          cmd LC_SUB_CLIENT\n";
9341    outs() << "      cmdsize " << sub.cmdsize;
9342    if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
9343      outs() << " Incorrect size\n";
9344    else
9345      outs() << "\n";
9346    if (sub.client < sub.cmdsize) {
9347      const char *P = Ptr + sub.client;
9348      outs() << "       client " << P << " (offset " << sub.client << ")\n";
9349    } else {
9350      outs() << "       client ?(bad offset " << sub.client << ")\n";
9351    }
9352  }
9353  
PrintRoutinesCommand(MachO::routines_command r)9354  static void PrintRoutinesCommand(MachO::routines_command r) {
9355    outs() << "          cmd LC_ROUTINES\n";
9356    outs() << "      cmdsize " << r.cmdsize;
9357    if (r.cmdsize != sizeof(struct MachO::routines_command))
9358      outs() << " Incorrect size\n";
9359    else
9360      outs() << "\n";
9361    outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
9362    outs() << "  init_module " << r.init_module << "\n";
9363    outs() << "    reserved1 " << r.reserved1 << "\n";
9364    outs() << "    reserved2 " << r.reserved2 << "\n";
9365    outs() << "    reserved3 " << r.reserved3 << "\n";
9366    outs() << "    reserved4 " << r.reserved4 << "\n";
9367    outs() << "    reserved5 " << r.reserved5 << "\n";
9368    outs() << "    reserved6 " << r.reserved6 << "\n";
9369  }
9370  
PrintRoutinesCommand64(MachO::routines_command_64 r)9371  static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
9372    outs() << "          cmd LC_ROUTINES_64\n";
9373    outs() << "      cmdsize " << r.cmdsize;
9374    if (r.cmdsize != sizeof(struct MachO::routines_command_64))
9375      outs() << " Incorrect size\n";
9376    else
9377      outs() << "\n";
9378    outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
9379    outs() << "  init_module " << r.init_module << "\n";
9380    outs() << "    reserved1 " << r.reserved1 << "\n";
9381    outs() << "    reserved2 " << r.reserved2 << "\n";
9382    outs() << "    reserved3 " << r.reserved3 << "\n";
9383    outs() << "    reserved4 " << r.reserved4 << "\n";
9384    outs() << "    reserved5 " << r.reserved5 << "\n";
9385    outs() << "    reserved6 " << r.reserved6 << "\n";
9386  }
9387  
Print_x86_thread_state32_t(MachO::x86_thread_state32_t & cpu32)9388  static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) {
9389    outs() << "\t    eax " << format("0x%08" PRIx32, cpu32.eax);
9390    outs() << " ebx    " << format("0x%08" PRIx32, cpu32.ebx);
9391    outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx);
9392    outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n";
9393    outs() << "\t    edi " << format("0x%08" PRIx32, cpu32.edi);
9394    outs() << " esi    " << format("0x%08" PRIx32, cpu32.esi);
9395    outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp);
9396    outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n";
9397    outs() << "\t    ss  " << format("0x%08" PRIx32, cpu32.ss);
9398    outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags);
9399    outs() << " eip " << format("0x%08" PRIx32, cpu32.eip);
9400    outs() << " cs  " << format("0x%08" PRIx32, cpu32.cs) << "\n";
9401    outs() << "\t    ds  " << format("0x%08" PRIx32, cpu32.ds);
9402    outs() << " es     " << format("0x%08" PRIx32, cpu32.es);
9403    outs() << " fs  " << format("0x%08" PRIx32, cpu32.fs);
9404    outs() << " gs  " << format("0x%08" PRIx32, cpu32.gs) << "\n";
9405  }
9406  
Print_x86_thread_state64_t(MachO::x86_thread_state64_t & cpu64)9407  static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
9408    outs() << "   rax  " << format("0x%016" PRIx64, cpu64.rax);
9409    outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
9410    outs() << " rcx  " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
9411    outs() << "   rdx  " << format("0x%016" PRIx64, cpu64.rdx);
9412    outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
9413    outs() << " rsi  " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
9414    outs() << "   rbp  " << format("0x%016" PRIx64, cpu64.rbp);
9415    outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
9416    outs() << " r8   " << format("0x%016" PRIx64, cpu64.r8) << "\n";
9417    outs() << "    r9  " << format("0x%016" PRIx64, cpu64.r9);
9418    outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
9419    outs() << " r11  " << format("0x%016" PRIx64, cpu64.r11) << "\n";
9420    outs() << "   r12  " << format("0x%016" PRIx64, cpu64.r12);
9421    outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
9422    outs() << " r14  " << format("0x%016" PRIx64, cpu64.r14) << "\n";
9423    outs() << "   r15  " << format("0x%016" PRIx64, cpu64.r15);
9424    outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
9425    outs() << "rflags  " << format("0x%016" PRIx64, cpu64.rflags);
9426    outs() << " cs  " << format("0x%016" PRIx64, cpu64.cs);
9427    outs() << " fs   " << format("0x%016" PRIx64, cpu64.fs) << "\n";
9428    outs() << "    gs  " << format("0x%016" PRIx64, cpu64.gs) << "\n";
9429  }
9430  
Print_mmst_reg(MachO::mmst_reg_t & r)9431  static void Print_mmst_reg(MachO::mmst_reg_t &r) {
9432    uint32_t f;
9433    outs() << "\t      mmst_reg  ";
9434    for (f = 0; f < 10; f++)
9435      outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
9436    outs() << "\n";
9437    outs() << "\t      mmst_rsrv ";
9438    for (f = 0; f < 6; f++)
9439      outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
9440    outs() << "\n";
9441  }
9442  
Print_xmm_reg(MachO::xmm_reg_t & r)9443  static void Print_xmm_reg(MachO::xmm_reg_t &r) {
9444    uint32_t f;
9445    outs() << "\t      xmm_reg ";
9446    for (f = 0; f < 16; f++)
9447      outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
9448    outs() << "\n";
9449  }
9450  
Print_x86_float_state_t(MachO::x86_float_state64_t & fpu)9451  static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
9452    outs() << "\t    fpu_reserved[0] " << fpu.fpu_reserved[0];
9453    outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
9454    outs() << "\t    control: invalid " << fpu.fpu_fcw.invalid;
9455    outs() << " denorm " << fpu.fpu_fcw.denorm;
9456    outs() << " zdiv " << fpu.fpu_fcw.zdiv;
9457    outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
9458    outs() << " undfl " << fpu.fpu_fcw.undfl;
9459    outs() << " precis " << fpu.fpu_fcw.precis << "\n";
9460    outs() << "\t\t     pc ";
9461    if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
9462      outs() << "FP_PREC_24B ";
9463    else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
9464      outs() << "FP_PREC_53B ";
9465    else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
9466      outs() << "FP_PREC_64B ";
9467    else
9468      outs() << fpu.fpu_fcw.pc << " ";
9469    outs() << "rc ";
9470    if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
9471      outs() << "FP_RND_NEAR ";
9472    else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
9473      outs() << "FP_RND_DOWN ";
9474    else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
9475      outs() << "FP_RND_UP ";
9476    else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
9477      outs() << "FP_CHOP ";
9478    outs() << "\n";
9479    outs() << "\t    status: invalid " << fpu.fpu_fsw.invalid;
9480    outs() << " denorm " << fpu.fpu_fsw.denorm;
9481    outs() << " zdiv " << fpu.fpu_fsw.zdiv;
9482    outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
9483    outs() << " undfl " << fpu.fpu_fsw.undfl;
9484    outs() << " precis " << fpu.fpu_fsw.precis;
9485    outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
9486    outs() << "\t            errsumm " << fpu.fpu_fsw.errsumm;
9487    outs() << " c0 " << fpu.fpu_fsw.c0;
9488    outs() << " c1 " << fpu.fpu_fsw.c1;
9489    outs() << " c2 " << fpu.fpu_fsw.c2;
9490    outs() << " tos " << fpu.fpu_fsw.tos;
9491    outs() << " c3 " << fpu.fpu_fsw.c3;
9492    outs() << " busy " << fpu.fpu_fsw.busy << "\n";
9493    outs() << "\t    fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
9494    outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
9495    outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
9496    outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
9497    outs() << "\t    fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
9498    outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
9499    outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
9500    outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
9501    outs() << "\t    fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
9502    outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
9503    outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
9504    outs() << "\n";
9505    outs() << "\t    fpu_stmm0:\n";
9506    Print_mmst_reg(fpu.fpu_stmm0);
9507    outs() << "\t    fpu_stmm1:\n";
9508    Print_mmst_reg(fpu.fpu_stmm1);
9509    outs() << "\t    fpu_stmm2:\n";
9510    Print_mmst_reg(fpu.fpu_stmm2);
9511    outs() << "\t    fpu_stmm3:\n";
9512    Print_mmst_reg(fpu.fpu_stmm3);
9513    outs() << "\t    fpu_stmm4:\n";
9514    Print_mmst_reg(fpu.fpu_stmm4);
9515    outs() << "\t    fpu_stmm5:\n";
9516    Print_mmst_reg(fpu.fpu_stmm5);
9517    outs() << "\t    fpu_stmm6:\n";
9518    Print_mmst_reg(fpu.fpu_stmm6);
9519    outs() << "\t    fpu_stmm7:\n";
9520    Print_mmst_reg(fpu.fpu_stmm7);
9521    outs() << "\t    fpu_xmm0:\n";
9522    Print_xmm_reg(fpu.fpu_xmm0);
9523    outs() << "\t    fpu_xmm1:\n";
9524    Print_xmm_reg(fpu.fpu_xmm1);
9525    outs() << "\t    fpu_xmm2:\n";
9526    Print_xmm_reg(fpu.fpu_xmm2);
9527    outs() << "\t    fpu_xmm3:\n";
9528    Print_xmm_reg(fpu.fpu_xmm3);
9529    outs() << "\t    fpu_xmm4:\n";
9530    Print_xmm_reg(fpu.fpu_xmm4);
9531    outs() << "\t    fpu_xmm5:\n";
9532    Print_xmm_reg(fpu.fpu_xmm5);
9533    outs() << "\t    fpu_xmm6:\n";
9534    Print_xmm_reg(fpu.fpu_xmm6);
9535    outs() << "\t    fpu_xmm7:\n";
9536    Print_xmm_reg(fpu.fpu_xmm7);
9537    outs() << "\t    fpu_xmm8:\n";
9538    Print_xmm_reg(fpu.fpu_xmm8);
9539    outs() << "\t    fpu_xmm9:\n";
9540    Print_xmm_reg(fpu.fpu_xmm9);
9541    outs() << "\t    fpu_xmm10:\n";
9542    Print_xmm_reg(fpu.fpu_xmm10);
9543    outs() << "\t    fpu_xmm11:\n";
9544    Print_xmm_reg(fpu.fpu_xmm11);
9545    outs() << "\t    fpu_xmm12:\n";
9546    Print_xmm_reg(fpu.fpu_xmm12);
9547    outs() << "\t    fpu_xmm13:\n";
9548    Print_xmm_reg(fpu.fpu_xmm13);
9549    outs() << "\t    fpu_xmm14:\n";
9550    Print_xmm_reg(fpu.fpu_xmm14);
9551    outs() << "\t    fpu_xmm15:\n";
9552    Print_xmm_reg(fpu.fpu_xmm15);
9553    outs() << "\t    fpu_rsrv4:\n";
9554    for (uint32_t f = 0; f < 6; f++) {
9555      outs() << "\t            ";
9556      for (uint32_t g = 0; g < 16; g++)
9557        outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
9558      outs() << "\n";
9559    }
9560    outs() << "\t    fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
9561    outs() << "\n";
9562  }
9563  
Print_x86_exception_state_t(MachO::x86_exception_state64_t & exc64)9564  static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
9565    outs() << "\t    trapno " << format("0x%08" PRIx32, exc64.trapno);
9566    outs() << " err " << format("0x%08" PRIx32, exc64.err);
9567    outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
9568  }
9569  
Print_arm_thread_state32_t(MachO::arm_thread_state32_t & cpu32)9570  static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
9571    outs() << "\t    r0  " << format("0x%08" PRIx32, cpu32.r[0]);
9572    outs() << " r1     "   << format("0x%08" PRIx32, cpu32.r[1]);
9573    outs() << " r2  "      << format("0x%08" PRIx32, cpu32.r[2]);
9574    outs() << " r3  "      << format("0x%08" PRIx32, cpu32.r[3]) << "\n";
9575    outs() << "\t    r4  " << format("0x%08" PRIx32, cpu32.r[4]);
9576    outs() << " r5     "   << format("0x%08" PRIx32, cpu32.r[5]);
9577    outs() << " r6  "      << format("0x%08" PRIx32, cpu32.r[6]);
9578    outs() << " r7  "      << format("0x%08" PRIx32, cpu32.r[7]) << "\n";
9579    outs() << "\t    r8  " << format("0x%08" PRIx32, cpu32.r[8]);
9580    outs() << " r9     "   << format("0x%08" PRIx32, cpu32.r[9]);
9581    outs() << " r10 "      << format("0x%08" PRIx32, cpu32.r[10]);
9582    outs() << " r11 "      << format("0x%08" PRIx32, cpu32.r[11]) << "\n";
9583    outs() << "\t    r12 " << format("0x%08" PRIx32, cpu32.r[12]);
9584    outs() << " sp     "   << format("0x%08" PRIx32, cpu32.sp);
9585    outs() << " lr  "      << format("0x%08" PRIx32, cpu32.lr);
9586    outs() << " pc  "      << format("0x%08" PRIx32, cpu32.pc) << "\n";
9587    outs() << "\t   cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n";
9588  }
9589  
Print_arm_thread_state64_t(MachO::arm_thread_state64_t & cpu64)9590  static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
9591    outs() << "\t    x0  " << format("0x%016" PRIx64, cpu64.x[0]);
9592    outs() << " x1  "      << format("0x%016" PRIx64, cpu64.x[1]);
9593    outs() << " x2  "      << format("0x%016" PRIx64, cpu64.x[2]) << "\n";
9594    outs() << "\t    x3  " << format("0x%016" PRIx64, cpu64.x[3]);
9595    outs() << " x4  "      << format("0x%016" PRIx64, cpu64.x[4]);
9596    outs() << " x5  "      << format("0x%016" PRIx64, cpu64.x[5]) << "\n";
9597    outs() << "\t    x6  " << format("0x%016" PRIx64, cpu64.x[6]);
9598    outs() << " x7  "      << format("0x%016" PRIx64, cpu64.x[7]);
9599    outs() << " x8  "      << format("0x%016" PRIx64, cpu64.x[8]) << "\n";
9600    outs() << "\t    x9  " << format("0x%016" PRIx64, cpu64.x[9]);
9601    outs() << " x10 "      << format("0x%016" PRIx64, cpu64.x[10]);
9602    outs() << " x11 "      << format("0x%016" PRIx64, cpu64.x[11]) << "\n";
9603    outs() << "\t    x12 " << format("0x%016" PRIx64, cpu64.x[12]);
9604    outs() << " x13 "      << format("0x%016" PRIx64, cpu64.x[13]);
9605    outs() << " x14 "      << format("0x%016" PRIx64, cpu64.x[14]) << "\n";
9606    outs() << "\t    x15 " << format("0x%016" PRIx64, cpu64.x[15]);
9607    outs() << " x16 "      << format("0x%016" PRIx64, cpu64.x[16]);
9608    outs() << " x17 "      << format("0x%016" PRIx64, cpu64.x[17]) << "\n";
9609    outs() << "\t    x18 " << format("0x%016" PRIx64, cpu64.x[18]);
9610    outs() << " x19 "      << format("0x%016" PRIx64, cpu64.x[19]);
9611    outs() << " x20 "      << format("0x%016" PRIx64, cpu64.x[20]) << "\n";
9612    outs() << "\t    x21 " << format("0x%016" PRIx64, cpu64.x[21]);
9613    outs() << " x22 "      << format("0x%016" PRIx64, cpu64.x[22]);
9614    outs() << " x23 "      << format("0x%016" PRIx64, cpu64.x[23]) << "\n";
9615    outs() << "\t    x24 " << format("0x%016" PRIx64, cpu64.x[24]);
9616    outs() << " x25 "      << format("0x%016" PRIx64, cpu64.x[25]);
9617    outs() << " x26 "      << format("0x%016" PRIx64, cpu64.x[26]) << "\n";
9618    outs() << "\t    x27 " << format("0x%016" PRIx64, cpu64.x[27]);
9619    outs() << " x28 "      << format("0x%016" PRIx64, cpu64.x[28]);
9620    outs() << "  fp "      << format("0x%016" PRIx64, cpu64.fp) << "\n";
9621    outs() << "\t     lr " << format("0x%016" PRIx64, cpu64.lr);
9622    outs() << " sp  "      << format("0x%016" PRIx64, cpu64.sp);
9623    outs() << "  pc "      << format("0x%016" PRIx64, cpu64.pc) << "\n";
9624    outs() << "\t   cpsr " << format("0x%08"  PRIx32, cpu64.cpsr) << "\n";
9625  }
9626  
PrintThreadCommand(MachO::thread_command t,const char * Ptr,bool isLittleEndian,uint32_t cputype)9627  static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
9628                                 bool isLittleEndian, uint32_t cputype) {
9629    if (t.cmd == MachO::LC_THREAD)
9630      outs() << "        cmd LC_THREAD\n";
9631    else if (t.cmd == MachO::LC_UNIXTHREAD)
9632      outs() << "        cmd LC_UNIXTHREAD\n";
9633    else
9634      outs() << "        cmd " << t.cmd << " (unknown)\n";
9635    outs() << "    cmdsize " << t.cmdsize;
9636    if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
9637      outs() << " Incorrect size\n";
9638    else
9639      outs() << "\n";
9640  
9641    const char *begin = Ptr + sizeof(struct MachO::thread_command);
9642    const char *end = Ptr + t.cmdsize;
9643    uint32_t flavor, count, left;
9644    if (cputype == MachO::CPU_TYPE_I386) {
9645      while (begin < end) {
9646        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9647          memcpy((char *)&flavor, begin, sizeof(uint32_t));
9648          begin += sizeof(uint32_t);
9649        } else {
9650          flavor = 0;
9651          begin = end;
9652        }
9653        if (isLittleEndian != sys::IsLittleEndianHost)
9654          sys::swapByteOrder(flavor);
9655        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9656          memcpy((char *)&count, begin, sizeof(uint32_t));
9657          begin += sizeof(uint32_t);
9658        } else {
9659          count = 0;
9660          begin = end;
9661        }
9662        if (isLittleEndian != sys::IsLittleEndianHost)
9663          sys::swapByteOrder(count);
9664        if (flavor == MachO::x86_THREAD_STATE32) {
9665          outs() << "     flavor i386_THREAD_STATE\n";
9666          if (count == MachO::x86_THREAD_STATE32_COUNT)
9667            outs() << "      count i386_THREAD_STATE_COUNT\n";
9668          else
9669            outs() << "      count " << count
9670                   << " (not x86_THREAD_STATE32_COUNT)\n";
9671          MachO::x86_thread_state32_t cpu32;
9672          left = end - begin;
9673          if (left >= sizeof(MachO::x86_thread_state32_t)) {
9674            memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t));
9675            begin += sizeof(MachO::x86_thread_state32_t);
9676          } else {
9677            memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t));
9678            memcpy(&cpu32, begin, left);
9679            begin += left;
9680          }
9681          if (isLittleEndian != sys::IsLittleEndianHost)
9682            swapStruct(cpu32);
9683          Print_x86_thread_state32_t(cpu32);
9684        } else if (flavor == MachO::x86_THREAD_STATE) {
9685          outs() << "     flavor x86_THREAD_STATE\n";
9686          if (count == MachO::x86_THREAD_STATE_COUNT)
9687            outs() << "      count x86_THREAD_STATE_COUNT\n";
9688          else
9689            outs() << "      count " << count
9690                   << " (not x86_THREAD_STATE_COUNT)\n";
9691          struct MachO::x86_thread_state_t ts;
9692          left = end - begin;
9693          if (left >= sizeof(MachO::x86_thread_state_t)) {
9694            memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9695            begin += sizeof(MachO::x86_thread_state_t);
9696          } else {
9697            memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9698            memcpy(&ts, begin, left);
9699            begin += left;
9700          }
9701          if (isLittleEndian != sys::IsLittleEndianHost)
9702            swapStruct(ts);
9703          if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) {
9704            outs() << "\t    tsh.flavor x86_THREAD_STATE32 ";
9705            if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT)
9706              outs() << "tsh.count x86_THREAD_STATE32_COUNT\n";
9707            else
9708              outs() << "tsh.count " << ts.tsh.count
9709                     << " (not x86_THREAD_STATE32_COUNT\n";
9710            Print_x86_thread_state32_t(ts.uts.ts32);
9711          } else {
9712            outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9713                   << ts.tsh.count << "\n";
9714          }
9715        } else {
9716          outs() << "     flavor " << flavor << " (unknown)\n";
9717          outs() << "      count " << count << "\n";
9718          outs() << "      state (unknown)\n";
9719          begin += count * sizeof(uint32_t);
9720        }
9721      }
9722    } else if (cputype == MachO::CPU_TYPE_X86_64) {
9723      while (begin < end) {
9724        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9725          memcpy((char *)&flavor, begin, sizeof(uint32_t));
9726          begin += sizeof(uint32_t);
9727        } else {
9728          flavor = 0;
9729          begin = end;
9730        }
9731        if (isLittleEndian != sys::IsLittleEndianHost)
9732          sys::swapByteOrder(flavor);
9733        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9734          memcpy((char *)&count, begin, sizeof(uint32_t));
9735          begin += sizeof(uint32_t);
9736        } else {
9737          count = 0;
9738          begin = end;
9739        }
9740        if (isLittleEndian != sys::IsLittleEndianHost)
9741          sys::swapByteOrder(count);
9742        if (flavor == MachO::x86_THREAD_STATE64) {
9743          outs() << "     flavor x86_THREAD_STATE64\n";
9744          if (count == MachO::x86_THREAD_STATE64_COUNT)
9745            outs() << "      count x86_THREAD_STATE64_COUNT\n";
9746          else
9747            outs() << "      count " << count
9748                   << " (not x86_THREAD_STATE64_COUNT)\n";
9749          MachO::x86_thread_state64_t cpu64;
9750          left = end - begin;
9751          if (left >= sizeof(MachO::x86_thread_state64_t)) {
9752            memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
9753            begin += sizeof(MachO::x86_thread_state64_t);
9754          } else {
9755            memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
9756            memcpy(&cpu64, begin, left);
9757            begin += left;
9758          }
9759          if (isLittleEndian != sys::IsLittleEndianHost)
9760            swapStruct(cpu64);
9761          Print_x86_thread_state64_t(cpu64);
9762        } else if (flavor == MachO::x86_THREAD_STATE) {
9763          outs() << "     flavor x86_THREAD_STATE\n";
9764          if (count == MachO::x86_THREAD_STATE_COUNT)
9765            outs() << "      count x86_THREAD_STATE_COUNT\n";
9766          else
9767            outs() << "      count " << count
9768                   << " (not x86_THREAD_STATE_COUNT)\n";
9769          struct MachO::x86_thread_state_t ts;
9770          left = end - begin;
9771          if (left >= sizeof(MachO::x86_thread_state_t)) {
9772            memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9773            begin += sizeof(MachO::x86_thread_state_t);
9774          } else {
9775            memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9776            memcpy(&ts, begin, left);
9777            begin += left;
9778          }
9779          if (isLittleEndian != sys::IsLittleEndianHost)
9780            swapStruct(ts);
9781          if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
9782            outs() << "\t    tsh.flavor x86_THREAD_STATE64 ";
9783            if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
9784              outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
9785            else
9786              outs() << "tsh.count " << ts.tsh.count
9787                     << " (not x86_THREAD_STATE64_COUNT\n";
9788            Print_x86_thread_state64_t(ts.uts.ts64);
9789          } else {
9790            outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9791                   << ts.tsh.count << "\n";
9792          }
9793        } else if (flavor == MachO::x86_FLOAT_STATE) {
9794          outs() << "     flavor x86_FLOAT_STATE\n";
9795          if (count == MachO::x86_FLOAT_STATE_COUNT)
9796            outs() << "      count x86_FLOAT_STATE_COUNT\n";
9797          else
9798            outs() << "      count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
9799          struct MachO::x86_float_state_t fs;
9800          left = end - begin;
9801          if (left >= sizeof(MachO::x86_float_state_t)) {
9802            memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
9803            begin += sizeof(MachO::x86_float_state_t);
9804          } else {
9805            memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
9806            memcpy(&fs, begin, left);
9807            begin += left;
9808          }
9809          if (isLittleEndian != sys::IsLittleEndianHost)
9810            swapStruct(fs);
9811          if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
9812            outs() << "\t    fsh.flavor x86_FLOAT_STATE64 ";
9813            if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
9814              outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
9815            else
9816              outs() << "fsh.count " << fs.fsh.count
9817                     << " (not x86_FLOAT_STATE64_COUNT\n";
9818            Print_x86_float_state_t(fs.ufs.fs64);
9819          } else {
9820            outs() << "\t    fsh.flavor " << fs.fsh.flavor << "  fsh.count "
9821                   << fs.fsh.count << "\n";
9822          }
9823        } else if (flavor == MachO::x86_EXCEPTION_STATE) {
9824          outs() << "     flavor x86_EXCEPTION_STATE\n";
9825          if (count == MachO::x86_EXCEPTION_STATE_COUNT)
9826            outs() << "      count x86_EXCEPTION_STATE_COUNT\n";
9827          else
9828            outs() << "      count " << count
9829                   << " (not x86_EXCEPTION_STATE_COUNT)\n";
9830          struct MachO::x86_exception_state_t es;
9831          left = end - begin;
9832          if (left >= sizeof(MachO::x86_exception_state_t)) {
9833            memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
9834            begin += sizeof(MachO::x86_exception_state_t);
9835          } else {
9836            memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
9837            memcpy(&es, begin, left);
9838            begin += left;
9839          }
9840          if (isLittleEndian != sys::IsLittleEndianHost)
9841            swapStruct(es);
9842          if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
9843            outs() << "\t    esh.flavor x86_EXCEPTION_STATE64\n";
9844            if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
9845              outs() << "\t    esh.count x86_EXCEPTION_STATE64_COUNT\n";
9846            else
9847              outs() << "\t    esh.count " << es.esh.count
9848                     << " (not x86_EXCEPTION_STATE64_COUNT\n";
9849            Print_x86_exception_state_t(es.ues.es64);
9850          } else {
9851            outs() << "\t    esh.flavor " << es.esh.flavor << "  esh.count "
9852                   << es.esh.count << "\n";
9853          }
9854        } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
9855          outs() << "     flavor x86_EXCEPTION_STATE64\n";
9856          if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
9857            outs() << "      count x86_EXCEPTION_STATE64_COUNT\n";
9858          else
9859            outs() << "      count " << count
9860                   << " (not x86_EXCEPTION_STATE64_COUNT)\n";
9861          struct MachO::x86_exception_state64_t es64;
9862          left = end - begin;
9863          if (left >= sizeof(MachO::x86_exception_state64_t)) {
9864            memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
9865            begin += sizeof(MachO::x86_exception_state64_t);
9866          } else {
9867            memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
9868            memcpy(&es64, begin, left);
9869            begin += left;
9870          }
9871          if (isLittleEndian != sys::IsLittleEndianHost)
9872            swapStruct(es64);
9873          Print_x86_exception_state_t(es64);
9874        } else {
9875          outs() << "     flavor " << flavor << " (unknown)\n";
9876          outs() << "      count " << count << "\n";
9877          outs() << "      state (unknown)\n";
9878          begin += count * sizeof(uint32_t);
9879        }
9880      }
9881    } else if (cputype == MachO::CPU_TYPE_ARM) {
9882      while (begin < end) {
9883        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9884          memcpy((char *)&flavor, begin, sizeof(uint32_t));
9885          begin += sizeof(uint32_t);
9886        } else {
9887          flavor = 0;
9888          begin = end;
9889        }
9890        if (isLittleEndian != sys::IsLittleEndianHost)
9891          sys::swapByteOrder(flavor);
9892        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9893          memcpy((char *)&count, begin, sizeof(uint32_t));
9894          begin += sizeof(uint32_t);
9895        } else {
9896          count = 0;
9897          begin = end;
9898        }
9899        if (isLittleEndian != sys::IsLittleEndianHost)
9900          sys::swapByteOrder(count);
9901        if (flavor == MachO::ARM_THREAD_STATE) {
9902          outs() << "     flavor ARM_THREAD_STATE\n";
9903          if (count == MachO::ARM_THREAD_STATE_COUNT)
9904            outs() << "      count ARM_THREAD_STATE_COUNT\n";
9905          else
9906            outs() << "      count " << count
9907                   << " (not ARM_THREAD_STATE_COUNT)\n";
9908          MachO::arm_thread_state32_t cpu32;
9909          left = end - begin;
9910          if (left >= sizeof(MachO::arm_thread_state32_t)) {
9911            memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t));
9912            begin += sizeof(MachO::arm_thread_state32_t);
9913          } else {
9914            memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t));
9915            memcpy(&cpu32, begin, left);
9916            begin += left;
9917          }
9918          if (isLittleEndian != sys::IsLittleEndianHost)
9919            swapStruct(cpu32);
9920          Print_arm_thread_state32_t(cpu32);
9921        } else {
9922          outs() << "     flavor " << flavor << " (unknown)\n";
9923          outs() << "      count " << count << "\n";
9924          outs() << "      state (unknown)\n";
9925          begin += count * sizeof(uint32_t);
9926        }
9927      }
9928    } else if (cputype == MachO::CPU_TYPE_ARM64 ||
9929               cputype == MachO::CPU_TYPE_ARM64_32) {
9930      while (begin < end) {
9931        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9932          memcpy((char *)&flavor, begin, sizeof(uint32_t));
9933          begin += sizeof(uint32_t);
9934        } else {
9935          flavor = 0;
9936          begin = end;
9937        }
9938        if (isLittleEndian != sys::IsLittleEndianHost)
9939          sys::swapByteOrder(flavor);
9940        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9941          memcpy((char *)&count, begin, sizeof(uint32_t));
9942          begin += sizeof(uint32_t);
9943        } else {
9944          count = 0;
9945          begin = end;
9946        }
9947        if (isLittleEndian != sys::IsLittleEndianHost)
9948          sys::swapByteOrder(count);
9949        if (flavor == MachO::ARM_THREAD_STATE64) {
9950          outs() << "     flavor ARM_THREAD_STATE64\n";
9951          if (count == MachO::ARM_THREAD_STATE64_COUNT)
9952            outs() << "      count ARM_THREAD_STATE64_COUNT\n";
9953          else
9954            outs() << "      count " << count
9955                   << " (not ARM_THREAD_STATE64_COUNT)\n";
9956          MachO::arm_thread_state64_t cpu64;
9957          left = end - begin;
9958          if (left >= sizeof(MachO::arm_thread_state64_t)) {
9959            memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
9960            begin += sizeof(MachO::arm_thread_state64_t);
9961          } else {
9962            memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
9963            memcpy(&cpu64, begin, left);
9964            begin += left;
9965          }
9966          if (isLittleEndian != sys::IsLittleEndianHost)
9967            swapStruct(cpu64);
9968          Print_arm_thread_state64_t(cpu64);
9969        } else {
9970          outs() << "     flavor " << flavor << " (unknown)\n";
9971          outs() << "      count " << count << "\n";
9972          outs() << "      state (unknown)\n";
9973          begin += count * sizeof(uint32_t);
9974        }
9975      }
9976    } else {
9977      while (begin < end) {
9978        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9979          memcpy((char *)&flavor, begin, sizeof(uint32_t));
9980          begin += sizeof(uint32_t);
9981        } else {
9982          flavor = 0;
9983          begin = end;
9984        }
9985        if (isLittleEndian != sys::IsLittleEndianHost)
9986          sys::swapByteOrder(flavor);
9987        if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9988          memcpy((char *)&count, begin, sizeof(uint32_t));
9989          begin += sizeof(uint32_t);
9990        } else {
9991          count = 0;
9992          begin = end;
9993        }
9994        if (isLittleEndian != sys::IsLittleEndianHost)
9995          sys::swapByteOrder(count);
9996        outs() << "     flavor " << flavor << "\n";
9997        outs() << "      count " << count << "\n";
9998        outs() << "      state (Unknown cputype/cpusubtype)\n";
9999        begin += count * sizeof(uint32_t);
10000      }
10001    }
10002  }
10003  
PrintDylibCommand(MachO::dylib_command dl,const char * Ptr)10004  static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
10005    if (dl.cmd == MachO::LC_ID_DYLIB)
10006      outs() << "          cmd LC_ID_DYLIB\n";
10007    else if (dl.cmd == MachO::LC_LOAD_DYLIB)
10008      outs() << "          cmd LC_LOAD_DYLIB\n";
10009    else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
10010      outs() << "          cmd LC_LOAD_WEAK_DYLIB\n";
10011    else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
10012      outs() << "          cmd LC_REEXPORT_DYLIB\n";
10013    else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
10014      outs() << "          cmd LC_LAZY_LOAD_DYLIB\n";
10015    else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
10016      outs() << "          cmd LC_LOAD_UPWARD_DYLIB\n";
10017    else
10018      outs() << "          cmd " << dl.cmd << " (unknown)\n";
10019    outs() << "      cmdsize " << dl.cmdsize;
10020    if (dl.cmdsize < sizeof(struct MachO::dylib_command))
10021      outs() << " Incorrect size\n";
10022    else
10023      outs() << "\n";
10024    if (dl.dylib.name < dl.cmdsize) {
10025      const char *P = (const char *)(Ptr) + dl.dylib.name;
10026      outs() << "         name " << P << " (offset " << dl.dylib.name << ")\n";
10027    } else {
10028      outs() << "         name ?(bad offset " << dl.dylib.name << ")\n";
10029    }
10030    outs() << "   time stamp " << dl.dylib.timestamp << " ";
10031    time_t t = dl.dylib.timestamp;
10032    outs() << ctime(&t);
10033    outs() << "      current version ";
10034    if (dl.dylib.current_version == 0xffffffff)
10035      outs() << "n/a\n";
10036    else
10037      outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
10038             << ((dl.dylib.current_version >> 8) & 0xff) << "."
10039             << (dl.dylib.current_version & 0xff) << "\n";
10040    outs() << "compatibility version ";
10041    if (dl.dylib.compatibility_version == 0xffffffff)
10042      outs() << "n/a\n";
10043    else
10044      outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
10045             << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
10046             << (dl.dylib.compatibility_version & 0xff) << "\n";
10047  }
10048  
PrintLinkEditDataCommand(MachO::linkedit_data_command ld,uint32_t object_size)10049  static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
10050                                       uint32_t object_size) {
10051    if (ld.cmd == MachO::LC_CODE_SIGNATURE)
10052      outs() << "      cmd LC_CODE_SIGNATURE\n";
10053    else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
10054      outs() << "      cmd LC_SEGMENT_SPLIT_INFO\n";
10055    else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
10056      outs() << "      cmd LC_FUNCTION_STARTS\n";
10057    else if (ld.cmd == MachO::LC_DATA_IN_CODE)
10058      outs() << "      cmd LC_DATA_IN_CODE\n";
10059    else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
10060      outs() << "      cmd LC_DYLIB_CODE_SIGN_DRS\n";
10061    else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
10062      outs() << "      cmd LC_LINKER_OPTIMIZATION_HINT\n";
10063    else if (ld.cmd == MachO::LC_DYLD_EXPORTS_TRIE)
10064      outs() << "      cmd LC_DYLD_EXPORTS_TRIE\n";
10065    else if (ld.cmd == MachO::LC_DYLD_CHAINED_FIXUPS)
10066      outs() << "      cmd LC_DYLD_CHAINED_FIXUPS\n";
10067    else if (ld.cmd == MachO::LC_ATOM_INFO)
10068      outs() << "      cmd LC_ATOM_INFO\n";
10069    else
10070      outs() << "      cmd " << ld.cmd << " (?)\n";
10071    outs() << "  cmdsize " << ld.cmdsize;
10072    if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
10073      outs() << " Incorrect size\n";
10074    else
10075      outs() << "\n";
10076    outs() << "  dataoff " << ld.dataoff;
10077    if (ld.dataoff > object_size)
10078      outs() << " (past end of file)\n";
10079    else
10080      outs() << "\n";
10081    outs() << " datasize " << ld.datasize;
10082    uint64_t big_size = ld.dataoff;
10083    big_size += ld.datasize;
10084    if (big_size > object_size)
10085      outs() << " (past end of file)\n";
10086    else
10087      outs() << "\n";
10088  }
10089  
PrintLoadCommands(const MachOObjectFile * Obj,uint32_t filetype,uint32_t cputype,bool verbose)10090  static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
10091                                uint32_t cputype, bool verbose) {
10092    StringRef Buf = Obj->getData();
10093    unsigned Index = 0;
10094    for (const auto &Command : Obj->load_commands()) {
10095      outs() << "Load command " << Index++ << "\n";
10096      if (Command.C.cmd == MachO::LC_SEGMENT) {
10097        MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
10098        const char *sg_segname = SLC.segname;
10099        PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
10100                            SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
10101                            SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
10102                            verbose);
10103        for (unsigned j = 0; j < SLC.nsects; j++) {
10104          MachO::section S = Obj->getSection(Command, j);
10105          PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
10106                       S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
10107                       SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
10108        }
10109      } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
10110        MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
10111        const char *sg_segname = SLC_64.segname;
10112        PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
10113                            SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
10114                            SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
10115                            SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
10116        for (unsigned j = 0; j < SLC_64.nsects; j++) {
10117          MachO::section_64 S_64 = Obj->getSection64(Command, j);
10118          PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
10119                       S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
10120                       S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
10121                       sg_segname, filetype, Buf.size(), verbose);
10122        }
10123      } else if (Command.C.cmd == MachO::LC_SYMTAB) {
10124        MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10125        PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
10126      } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
10127        MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
10128        MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10129        PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
10130                                 Obj->is64Bit());
10131      } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
10132                 Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
10133        MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
10134        PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
10135      } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
10136                 Command.C.cmd == MachO::LC_ID_DYLINKER ||
10137                 Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
10138        MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
10139        PrintDyldLoadCommand(Dyld, Command.Ptr);
10140      } else if (Command.C.cmd == MachO::LC_UUID) {
10141        MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
10142        PrintUuidLoadCommand(Uuid);
10143      } else if (Command.C.cmd == MachO::LC_RPATH) {
10144        MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
10145        PrintRpathLoadCommand(Rpath, Command.Ptr);
10146      } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
10147                 Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
10148                 Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
10149                 Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
10150        MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
10151        PrintVersionMinLoadCommand(Vd);
10152      } else if (Command.C.cmd == MachO::LC_NOTE) {
10153        MachO::note_command Nt = Obj->getNoteLoadCommand(Command);
10154        PrintNoteLoadCommand(Nt);
10155      } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) {
10156        MachO::build_version_command Bv =
10157            Obj->getBuildVersionLoadCommand(Command);
10158        PrintBuildVersionLoadCommand(Obj, Bv, verbose);
10159      } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
10160        MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
10161        PrintSourceVersionCommand(Sd);
10162      } else if (Command.C.cmd == MachO::LC_MAIN) {
10163        MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
10164        PrintEntryPointCommand(Ep);
10165      } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
10166        MachO::encryption_info_command Ei =
10167            Obj->getEncryptionInfoCommand(Command);
10168        PrintEncryptionInfoCommand(Ei, Buf.size());
10169      } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
10170        MachO::encryption_info_command_64 Ei =
10171            Obj->getEncryptionInfoCommand64(Command);
10172        PrintEncryptionInfoCommand64(Ei, Buf.size());
10173      } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
10174        MachO::linker_option_command Lo =
10175            Obj->getLinkerOptionLoadCommand(Command);
10176        PrintLinkerOptionCommand(Lo, Command.Ptr);
10177      } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
10178        MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
10179        PrintSubFrameworkCommand(Sf, Command.Ptr);
10180      } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
10181        MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
10182        PrintSubUmbrellaCommand(Sf, Command.Ptr);
10183      } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
10184        MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
10185        PrintSubLibraryCommand(Sl, Command.Ptr);
10186      } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
10187        MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
10188        PrintSubClientCommand(Sc, Command.Ptr);
10189      } else if (Command.C.cmd == MachO::LC_ROUTINES) {
10190        MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
10191        PrintRoutinesCommand(Rc);
10192      } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
10193        MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
10194        PrintRoutinesCommand64(Rc);
10195      } else if (Command.C.cmd == MachO::LC_THREAD ||
10196                 Command.C.cmd == MachO::LC_UNIXTHREAD) {
10197        MachO::thread_command Tc = Obj->getThreadCommand(Command);
10198        PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
10199      } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
10200                 Command.C.cmd == MachO::LC_ID_DYLIB ||
10201                 Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
10202                 Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
10203                 Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
10204                 Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
10205        MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
10206        PrintDylibCommand(Dl, Command.Ptr);
10207      } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
10208                 Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
10209                 Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
10210                 Command.C.cmd == MachO::LC_DATA_IN_CODE ||
10211                 Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
10212                 Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT ||
10213                 Command.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE ||
10214                 Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS ||
10215                 Command.C.cmd == MachO::LC_ATOM_INFO) {
10216        MachO::linkedit_data_command Ld =
10217            Obj->getLinkeditDataLoadCommand(Command);
10218        PrintLinkEditDataCommand(Ld, Buf.size());
10219      } else {
10220        outs() << "      cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
10221               << ")\n";
10222        outs() << "  cmdsize " << Command.C.cmdsize << "\n";
10223        // TODO: get and print the raw bytes of the load command.
10224      }
10225      // TODO: print all the other kinds of load commands.
10226    }
10227  }
10228  
PrintMachHeader(const MachOObjectFile * Obj,bool verbose)10229  static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
10230    if (Obj->is64Bit()) {
10231      MachO::mach_header_64 H_64;
10232      H_64 = Obj->getHeader64();
10233      PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
10234                      H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
10235    } else {
10236      MachO::mach_header H;
10237      H = Obj->getHeader();
10238      PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
10239                      H.sizeofcmds, H.flags, verbose);
10240    }
10241  }
10242  
printMachOFileHeader(const object::ObjectFile * Obj)10243  void objdump::printMachOFileHeader(const object::ObjectFile *Obj) {
10244    const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10245    PrintMachHeader(file, Verbose);
10246  }
10247  
printPrivateHeaders()10248  void MachODumper::printPrivateHeaders() {
10249    printMachOFileHeader(&Obj);
10250    if (!FirstPrivateHeader)
10251      printMachOLoadCommands(&Obj);
10252  }
10253  
printMachOLoadCommands(const object::ObjectFile * Obj)10254  void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) {
10255    const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10256    uint32_t filetype = 0;
10257    uint32_t cputype = 0;
10258    if (file->is64Bit()) {
10259      MachO::mach_header_64 H_64;
10260      H_64 = file->getHeader64();
10261      filetype = H_64.filetype;
10262      cputype = H_64.cputype;
10263    } else {
10264      MachO::mach_header H;
10265      H = file->getHeader();
10266      filetype = H.filetype;
10267      cputype = H.cputype;
10268    }
10269    PrintLoadCommands(file, filetype, cputype, Verbose);
10270  }
10271  
10272  //===----------------------------------------------------------------------===//
10273  // export trie dumping
10274  //===----------------------------------------------------------------------===//
10275  
printMachOExportsTrie(const object::MachOObjectFile * Obj)10276  static void printMachOExportsTrie(const object::MachOObjectFile *Obj) {
10277    uint64_t BaseSegmentAddress = 0;
10278    for (const auto &Command : Obj->load_commands()) {
10279      if (Command.C.cmd == MachO::LC_SEGMENT) {
10280        MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command);
10281        if (Seg.fileoff == 0 && Seg.filesize != 0) {
10282          BaseSegmentAddress = Seg.vmaddr;
10283          break;
10284        }
10285      } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
10286        MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command);
10287        if (Seg.fileoff == 0 && Seg.filesize != 0) {
10288          BaseSegmentAddress = Seg.vmaddr;
10289          break;
10290        }
10291      }
10292    }
10293    Error Err = Error::success();
10294    for (const object::ExportEntry &Entry : Obj->exports(Err)) {
10295      uint64_t Flags = Entry.flags();
10296      bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
10297      bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
10298      bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10299                          MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
10300      bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10301                  MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
10302      bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
10303      if (ReExport)
10304        outs() << "[re-export] ";
10305      else
10306        outs() << format("0x%08llX  ",
10307                         Entry.address() + BaseSegmentAddress);
10308      outs() << Entry.name();
10309      if (WeakDef || ThreadLocal || Resolver || Abs) {
10310        ListSeparator LS;
10311        outs() << " [";
10312        if (WeakDef)
10313          outs() << LS << "weak_def";
10314        if (ThreadLocal)
10315          outs() << LS << "per-thread";
10316        if (Abs)
10317          outs() << LS << "absolute";
10318        if (Resolver)
10319          outs() << LS << format("resolver=0x%08llX", Entry.other());
10320        outs() << "]";
10321      }
10322      if (ReExport) {
10323        StringRef DylibName = "unknown";
10324        int Ordinal = Entry.other() - 1;
10325        Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
10326        if (Entry.otherName().empty())
10327          outs() << " (from " << DylibName << ")";
10328        else
10329          outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
10330      }
10331      outs() << "\n";
10332    }
10333    if (Err)
10334      reportError(std::move(Err), Obj->getFileName());
10335  }
10336  
10337  //===----------------------------------------------------------------------===//
10338  // rebase table dumping
10339  //===----------------------------------------------------------------------===//
10340  
printMachORebaseTable(object::MachOObjectFile * Obj)10341  static void printMachORebaseTable(object::MachOObjectFile *Obj) {
10342    outs() << "segment  section            address     type\n";
10343    Error Err = Error::success();
10344    for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) {
10345      StringRef SegmentName = Entry.segmentName();
10346      StringRef SectionName = Entry.sectionName();
10347      uint64_t Address = Entry.address();
10348  
10349      // Table lines look like: __DATA  __nl_symbol_ptr  0x0000F00C  pointer
10350      outs() << format("%-8s %-18s 0x%08" PRIX64 "  %s\n",
10351                       SegmentName.str().c_str(), SectionName.str().c_str(),
10352                       Address, Entry.typeName().str().c_str());
10353    }
10354    if (Err)
10355      reportError(std::move(Err), Obj->getFileName());
10356  }
10357  
ordinalName(const object::MachOObjectFile * Obj,int Ordinal)10358  static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
10359    StringRef DylibName;
10360    switch (Ordinal) {
10361    case MachO::BIND_SPECIAL_DYLIB_SELF:
10362      return "this-image";
10363    case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
10364      return "main-executable";
10365    case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
10366      return "flat-namespace";
10367    case MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP:
10368      return "weak";
10369    default:
10370      if (Ordinal > 0) {
10371        std::error_code EC =
10372            Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
10373        if (EC)
10374          return "<<bad library ordinal>>";
10375        return DylibName;
10376      }
10377    }
10378    return "<<unknown special ordinal>>";
10379  }
10380  
10381  //===----------------------------------------------------------------------===//
10382  // bind table dumping
10383  //===----------------------------------------------------------------------===//
10384  
printMachOBindTable(object::MachOObjectFile * Obj)10385  static void printMachOBindTable(object::MachOObjectFile *Obj) {
10386    // Build table of sections so names can used in final output.
10387    outs() << "segment  section            address    type       "
10388              "addend dylib            symbol\n";
10389    Error Err = Error::success();
10390    for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) {
10391      StringRef SegmentName = Entry.segmentName();
10392      StringRef SectionName = Entry.sectionName();
10393      uint64_t Address = Entry.address();
10394  
10395      // Table lines look like:
10396      //  __DATA  __got  0x00012010    pointer   0 libSystem ___stack_chk_guard
10397      StringRef Attr;
10398      if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
10399        Attr = " (weak_import)";
10400      outs() << left_justify(SegmentName, 8) << " "
10401             << left_justify(SectionName, 18) << " "
10402             << format_hex(Address, 10, true) << " "
10403             << left_justify(Entry.typeName(), 8) << " "
10404             << format_decimal(Entry.addend(), 8) << " "
10405             << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10406             << Entry.symbolName() << Attr << "\n";
10407    }
10408    if (Err)
10409      reportError(std::move(Err), Obj->getFileName());
10410  }
10411  
10412  //===----------------------------------------------------------------------===//
10413  // lazy bind table dumping
10414  //===----------------------------------------------------------------------===//
10415  
printMachOLazyBindTable(object::MachOObjectFile * Obj)10416  static void printMachOLazyBindTable(object::MachOObjectFile *Obj) {
10417    outs() << "segment  section            address     "
10418              "dylib            symbol\n";
10419    Error Err = Error::success();
10420    for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) {
10421      StringRef SegmentName = Entry.segmentName();
10422      StringRef SectionName = Entry.sectionName();
10423      uint64_t Address = Entry.address();
10424  
10425      // Table lines look like:
10426      //  __DATA  __got  0x00012010 libSystem ___stack_chk_guard
10427      outs() << left_justify(SegmentName, 8) << " "
10428             << left_justify(SectionName, 18) << " "
10429             << format_hex(Address, 10, true) << " "
10430             << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10431             << Entry.symbolName() << "\n";
10432    }
10433    if (Err)
10434      reportError(std::move(Err), Obj->getFileName());
10435  }
10436  
10437  //===----------------------------------------------------------------------===//
10438  // weak bind table dumping
10439  //===----------------------------------------------------------------------===//
10440  
printMachOWeakBindTable(object::MachOObjectFile * Obj)10441  static void printMachOWeakBindTable(object::MachOObjectFile *Obj) {
10442    outs() << "segment  section            address     "
10443              "type       addend   symbol\n";
10444    Error Err = Error::success();
10445    for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) {
10446      // Strong symbols don't have a location to update.
10447      if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
10448        outs() << "                                        strong              "
10449               << Entry.symbolName() << "\n";
10450        continue;
10451      }
10452      StringRef SegmentName = Entry.segmentName();
10453      StringRef SectionName = Entry.sectionName();
10454      uint64_t Address = Entry.address();
10455  
10456      // Table lines look like:
10457      // __DATA  __data  0x00001000  pointer    0   _foo
10458      outs() << left_justify(SegmentName, 8) << " "
10459             << left_justify(SectionName, 18) << " "
10460             << format_hex(Address, 10, true) << " "
10461             << left_justify(Entry.typeName(), 8) << " "
10462             << format_decimal(Entry.addend(), 8) << "   " << Entry.symbolName()
10463             << "\n";
10464    }
10465    if (Err)
10466      reportError(std::move(Err), Obj->getFileName());
10467  }
10468  
10469  // get_dyld_bind_info_symbolname() is used for disassembly and passed an
10470  // address, ReferenceValue, in the Mach-O file and looks in the dyld bind
10471  // information for that address. If the address is found its binding symbol
10472  // name is returned.  If not nullptr is returned.
get_dyld_bind_info_symbolname(uint64_t ReferenceValue,struct DisassembleInfo * info)10473  static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
10474                                                   struct DisassembleInfo *info) {
10475    if (info->bindtable == nullptr) {
10476      info->bindtable = std::make_unique<SymbolAddressMap>();
10477      Error Err = Error::success();
10478      for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) {
10479        uint64_t Address = Entry.address();
10480        StringRef name = Entry.symbolName();
10481        if (!name.empty())
10482          (*info->bindtable)[Address] = name;
10483      }
10484      if (Err)
10485        reportError(std::move(Err), info->O->getFileName());
10486    }
10487    auto name = info->bindtable->lookup(ReferenceValue);
10488    return !name.empty() ? name.data() : nullptr;
10489  }
10490  
printLazyBindTable(ObjectFile * o)10491  void objdump::printLazyBindTable(ObjectFile *o) {
10492    outs() << "\nLazy bind table:\n";
10493    if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10494      printMachOLazyBindTable(MachO);
10495    else
10496      WithColor::error()
10497          << "This operation is only currently supported "
10498             "for Mach-O executable files.\n";
10499  }
10500  
printWeakBindTable(ObjectFile * o)10501  void objdump::printWeakBindTable(ObjectFile *o) {
10502    outs() << "\nWeak bind table:\n";
10503    if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10504      printMachOWeakBindTable(MachO);
10505    else
10506      WithColor::error()
10507          << "This operation is only currently supported "
10508             "for Mach-O executable files.\n";
10509  }
10510  
printExportsTrie(const ObjectFile * o)10511  void objdump::printExportsTrie(const ObjectFile *o) {
10512    outs() << "\nExports trie:\n";
10513    if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10514      printMachOExportsTrie(MachO);
10515    else
10516      WithColor::error()
10517          << "This operation is only currently supported "
10518             "for Mach-O executable files.\n";
10519  }
10520  
printRebaseTable(ObjectFile * o)10521  void objdump::printRebaseTable(ObjectFile *o) {
10522    outs() << "\nRebase table:\n";
10523    if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10524      printMachORebaseTable(MachO);
10525    else
10526      WithColor::error()
10527          << "This operation is only currently supported "
10528             "for Mach-O executable files.\n";
10529  }
10530  
printBindTable(ObjectFile * o)10531  void objdump::printBindTable(ObjectFile *o) {
10532    outs() << "\nBind table:\n";
10533    if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10534      printMachOBindTable(MachO);
10535    else
10536      WithColor::error()
10537          << "This operation is only currently supported "
10538             "for Mach-O executable files.\n";
10539  }
10540