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