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 ()__anon3ed9bcb80111::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.equals("__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__anon3ed9bcb80611::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 struct method_list64_t {
3665   uint32_t entsize;
3666   uint32_t count;
3667   /* struct method64_t first;  These structures follow inline */
3668 };
3669 
3670 struct method_list32_t {
3671   uint32_t entsize;
3672   uint32_t count;
3673   /* struct method32_t first;  These structures follow inline */
3674 };
3675 
3676 struct method64_t {
3677   uint64_t name;  /* SEL (64-bit pointer) */
3678   uint64_t types; /* const char * (64-bit pointer) */
3679   uint64_t imp;   /* IMP (64-bit pointer) */
3680 };
3681 
3682 struct method32_t {
3683   uint32_t name;  /* SEL (32-bit pointer) */
3684   uint32_t types; /* const char * (32-bit pointer) */
3685   uint32_t imp;   /* IMP (32-bit pointer) */
3686 };
3687 
3688 struct protocol_list64_t {
3689   uint64_t count; /* uintptr_t (a 64-bit value) */
3690   /* struct protocol64_t * list[0];  These pointers follow inline */
3691 };
3692 
3693 struct protocol_list32_t {
3694   uint32_t count; /* uintptr_t (a 32-bit value) */
3695   /* struct protocol32_t * list[0];  These pointers follow inline */
3696 };
3697 
3698 struct protocol64_t {
3699   uint64_t isa;                     /* id * (64-bit pointer) */
3700   uint64_t name;                    /* const char * (64-bit pointer) */
3701   uint64_t protocols;               /* struct protocol_list64_t *
3702                                                     (64-bit pointer) */
3703   uint64_t instanceMethods;         /* method_list_t * (64-bit pointer) */
3704   uint64_t classMethods;            /* method_list_t * (64-bit pointer) */
3705   uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
3706   uint64_t optionalClassMethods;    /* method_list_t * (64-bit pointer) */
3707   uint64_t instanceProperties;      /* struct objc_property_list *
3708                                                        (64-bit pointer) */
3709 };
3710 
3711 struct protocol32_t {
3712   uint32_t isa;                     /* id * (32-bit pointer) */
3713   uint32_t name;                    /* const char * (32-bit pointer) */
3714   uint32_t protocols;               /* struct protocol_list_t *
3715                                                     (32-bit pointer) */
3716   uint32_t instanceMethods;         /* method_list_t * (32-bit pointer) */
3717   uint32_t classMethods;            /* method_list_t * (32-bit pointer) */
3718   uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
3719   uint32_t optionalClassMethods;    /* method_list_t * (32-bit pointer) */
3720   uint32_t instanceProperties;      /* struct objc_property_list *
3721                                                        (32-bit pointer) */
3722 };
3723 
3724 struct ivar_list64_t {
3725   uint32_t entsize;
3726   uint32_t count;
3727   /* struct ivar64_t first;  These structures follow inline */
3728 };
3729 
3730 struct ivar_list32_t {
3731   uint32_t entsize;
3732   uint32_t count;
3733   /* struct ivar32_t first;  These structures follow inline */
3734 };
3735 
3736 struct ivar64_t {
3737   uint64_t offset; /* uintptr_t * (64-bit pointer) */
3738   uint64_t name;   /* const char * (64-bit pointer) */
3739   uint64_t type;   /* const char * (64-bit pointer) */
3740   uint32_t alignment;
3741   uint32_t size;
3742 };
3743 
3744 struct ivar32_t {
3745   uint32_t offset; /* uintptr_t * (32-bit pointer) */
3746   uint32_t name;   /* const char * (32-bit pointer) */
3747   uint32_t type;   /* const char * (32-bit pointer) */
3748   uint32_t alignment;
3749   uint32_t size;
3750 };
3751 
3752 struct objc_property_list64 {
3753   uint32_t entsize;
3754   uint32_t count;
3755   /* struct objc_property64 first;  These structures follow inline */
3756 };
3757 
3758 struct objc_property_list32 {
3759   uint32_t entsize;
3760   uint32_t count;
3761   /* struct objc_property32 first;  These structures follow inline */
3762 };
3763 
3764 struct objc_property64 {
3765   uint64_t name;       /* const char * (64-bit pointer) */
3766   uint64_t attributes; /* const char * (64-bit pointer) */
3767 };
3768 
3769 struct objc_property32 {
3770   uint32_t name;       /* const char * (32-bit pointer) */
3771   uint32_t attributes; /* const char * (32-bit pointer) */
3772 };
3773 
3774 struct category64_t {
3775   uint64_t name;               /* const char * (64-bit pointer) */
3776   uint64_t cls;                /* struct class_t * (64-bit pointer) */
3777   uint64_t instanceMethods;    /* struct method_list_t * (64-bit pointer) */
3778   uint64_t classMethods;       /* struct method_list_t * (64-bit pointer) */
3779   uint64_t protocols;          /* struct protocol_list_t * (64-bit pointer) */
3780   uint64_t instanceProperties; /* struct objc_property_list *
3781                                   (64-bit pointer) */
3782 };
3783 
3784 struct category32_t {
3785   uint32_t name;               /* const char * (32-bit pointer) */
3786   uint32_t cls;                /* struct class_t * (32-bit pointer) */
3787   uint32_t instanceMethods;    /* struct method_list_t * (32-bit pointer) */
3788   uint32_t classMethods;       /* struct method_list_t * (32-bit pointer) */
3789   uint32_t protocols;          /* struct protocol_list_t * (32-bit pointer) */
3790   uint32_t instanceProperties; /* struct objc_property_list *
3791                                   (32-bit pointer) */
3792 };
3793 
3794 struct objc_image_info64 {
3795   uint32_t version;
3796   uint32_t flags;
3797 };
3798 struct objc_image_info32 {
3799   uint32_t version;
3800   uint32_t flags;
3801 };
3802 struct imageInfo_t {
3803   uint32_t version;
3804   uint32_t flags;
3805 };
3806 /* masks for objc_image_info.flags */
3807 #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
3808 #define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
3809 #define OBJC_IMAGE_IS_SIMULATED (1 << 5)
3810 #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)
3811 
3812 struct message_ref64 {
3813   uint64_t imp; /* IMP (64-bit pointer) */
3814   uint64_t sel; /* SEL (64-bit pointer) */
3815 };
3816 
3817 struct message_ref32 {
3818   uint32_t imp; /* IMP (32-bit pointer) */
3819   uint32_t sel; /* SEL (32-bit pointer) */
3820 };
3821 
3822 // Objective-C 1 (32-bit only) meta data structs.
3823 
3824 struct objc_module_t {
3825   uint32_t version;
3826   uint32_t size;
3827   uint32_t name;   /* char * (32-bit pointer) */
3828   uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
3829 };
3830 
3831 struct objc_symtab_t {
3832   uint32_t sel_ref_cnt;
3833   uint32_t refs; /* SEL * (32-bit pointer) */
3834   uint16_t cls_def_cnt;
3835   uint16_t cat_def_cnt;
3836   // uint32_t defs[1];        /* void * (32-bit pointer) variable size */
3837 };
3838 
3839 struct objc_class_t {
3840   uint32_t isa;         /* struct objc_class * (32-bit pointer) */
3841   uint32_t super_class; /* struct objc_class * (32-bit pointer) */
3842   uint32_t name;        /* const char * (32-bit pointer) */
3843   int32_t version;
3844   int32_t info;
3845   int32_t instance_size;
3846   uint32_t ivars;       /* struct objc_ivar_list * (32-bit pointer) */
3847   uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
3848   uint32_t cache;       /* struct objc_cache * (32-bit pointer) */
3849   uint32_t protocols;   /* struct objc_protocol_list * (32-bit pointer) */
3850 };
3851 
3852 #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
3853 // class is not a metaclass
3854 #define CLS_CLASS 0x1
3855 // class is a metaclass
3856 #define CLS_META 0x2
3857 
3858 struct objc_category_t {
3859   uint32_t category_name;    /* char * (32-bit pointer) */
3860   uint32_t class_name;       /* char * (32-bit pointer) */
3861   uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
3862   uint32_t class_methods;    /* struct objc_method_list * (32-bit pointer) */
3863   uint32_t protocols;        /* struct objc_protocol_list * (32-bit ptr) */
3864 };
3865 
3866 struct objc_ivar_t {
3867   uint32_t ivar_name; /* char * (32-bit pointer) */
3868   uint32_t ivar_type; /* char * (32-bit pointer) */
3869   int32_t ivar_offset;
3870 };
3871 
3872 struct objc_ivar_list_t {
3873   int32_t ivar_count;
3874   // struct objc_ivar_t ivar_list[1];          /* variable length structure */
3875 };
3876 
3877 struct objc_method_list_t {
3878   uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
3879   int32_t method_count;
3880   // struct objc_method_t method_list[1];      /* variable length structure */
3881 };
3882 
3883 struct objc_method_t {
3884   uint32_t method_name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3885   uint32_t method_types; /* char * (32-bit pointer) */
3886   uint32_t method_imp;   /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
3887                             (32-bit pointer) */
3888 };
3889 
3890 struct objc_protocol_list_t {
3891   uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
3892   int32_t count;
3893   // uint32_t list[1];   /* Protocol *, aka struct objc_protocol_t *
3894   //                        (32-bit pointer) */
3895 };
3896 
3897 struct objc_protocol_t {
3898   uint32_t isa;              /* struct objc_class * (32-bit pointer) */
3899   uint32_t protocol_name;    /* char * (32-bit pointer) */
3900   uint32_t protocol_list;    /* struct objc_protocol_list * (32-bit pointer) */
3901   uint32_t instance_methods; /* struct objc_method_description_list *
3902                                 (32-bit pointer) */
3903   uint32_t class_methods;    /* struct objc_method_description_list *
3904                                 (32-bit pointer) */
3905 };
3906 
3907 struct objc_method_description_list_t {
3908   int32_t count;
3909   // struct objc_method_description_t list[1];
3910 };
3911 
3912 struct objc_method_description_t {
3913   uint32_t name;  /* SEL, aka struct objc_selector * (32-bit pointer) */
3914   uint32_t types; /* char * (32-bit pointer) */
3915 };
3916 
swapStruct(struct cfstring64_t & cfs)3917 inline void swapStruct(struct cfstring64_t &cfs) {
3918   sys::swapByteOrder(cfs.isa);
3919   sys::swapByteOrder(cfs.flags);
3920   sys::swapByteOrder(cfs.characters);
3921   sys::swapByteOrder(cfs.length);
3922 }
3923 
swapStruct(struct class64_t & c)3924 inline void swapStruct(struct class64_t &c) {
3925   sys::swapByteOrder(c.isa);
3926   sys::swapByteOrder(c.superclass);
3927   sys::swapByteOrder(c.cache);
3928   sys::swapByteOrder(c.vtable);
3929   sys::swapByteOrder(c.data);
3930 }
3931 
swapStruct(struct class32_t & c)3932 inline void swapStruct(struct class32_t &c) {
3933   sys::swapByteOrder(c.isa);
3934   sys::swapByteOrder(c.superclass);
3935   sys::swapByteOrder(c.cache);
3936   sys::swapByteOrder(c.vtable);
3937   sys::swapByteOrder(c.data);
3938 }
3939 
swapStruct(struct class_ro64_t & cro)3940 inline void swapStruct(struct class_ro64_t &cro) {
3941   sys::swapByteOrder(cro.flags);
3942   sys::swapByteOrder(cro.instanceStart);
3943   sys::swapByteOrder(cro.instanceSize);
3944   sys::swapByteOrder(cro.reserved);
3945   sys::swapByteOrder(cro.ivarLayout);
3946   sys::swapByteOrder(cro.name);
3947   sys::swapByteOrder(cro.baseMethods);
3948   sys::swapByteOrder(cro.baseProtocols);
3949   sys::swapByteOrder(cro.ivars);
3950   sys::swapByteOrder(cro.weakIvarLayout);
3951   sys::swapByteOrder(cro.baseProperties);
3952 }
3953 
swapStruct(struct class_ro32_t & cro)3954 inline void swapStruct(struct class_ro32_t &cro) {
3955   sys::swapByteOrder(cro.flags);
3956   sys::swapByteOrder(cro.instanceStart);
3957   sys::swapByteOrder(cro.instanceSize);
3958   sys::swapByteOrder(cro.ivarLayout);
3959   sys::swapByteOrder(cro.name);
3960   sys::swapByteOrder(cro.baseMethods);
3961   sys::swapByteOrder(cro.baseProtocols);
3962   sys::swapByteOrder(cro.ivars);
3963   sys::swapByteOrder(cro.weakIvarLayout);
3964   sys::swapByteOrder(cro.baseProperties);
3965 }
3966 
swapStruct(struct method_list64_t & ml)3967 inline void swapStruct(struct method_list64_t &ml) {
3968   sys::swapByteOrder(ml.entsize);
3969   sys::swapByteOrder(ml.count);
3970 }
3971 
swapStruct(struct method_list32_t & ml)3972 inline void swapStruct(struct method_list32_t &ml) {
3973   sys::swapByteOrder(ml.entsize);
3974   sys::swapByteOrder(ml.count);
3975 }
3976 
swapStruct(struct method64_t & m)3977 inline void swapStruct(struct method64_t &m) {
3978   sys::swapByteOrder(m.name);
3979   sys::swapByteOrder(m.types);
3980   sys::swapByteOrder(m.imp);
3981 }
3982 
swapStruct(struct method32_t & m)3983 inline void swapStruct(struct method32_t &m) {
3984   sys::swapByteOrder(m.name);
3985   sys::swapByteOrder(m.types);
3986   sys::swapByteOrder(m.imp);
3987 }
3988 
swapStruct(struct protocol_list64_t & pl)3989 inline void swapStruct(struct protocol_list64_t &pl) {
3990   sys::swapByteOrder(pl.count);
3991 }
3992 
swapStruct(struct protocol_list32_t & pl)3993 inline void swapStruct(struct protocol_list32_t &pl) {
3994   sys::swapByteOrder(pl.count);
3995 }
3996 
swapStruct(struct protocol64_t & p)3997 inline void swapStruct(struct protocol64_t &p) {
3998   sys::swapByteOrder(p.isa);
3999   sys::swapByteOrder(p.name);
4000   sys::swapByteOrder(p.protocols);
4001   sys::swapByteOrder(p.instanceMethods);
4002   sys::swapByteOrder(p.classMethods);
4003   sys::swapByteOrder(p.optionalInstanceMethods);
4004   sys::swapByteOrder(p.optionalClassMethods);
4005   sys::swapByteOrder(p.instanceProperties);
4006 }
4007 
swapStruct(struct protocol32_t & p)4008 inline void swapStruct(struct protocol32_t &p) {
4009   sys::swapByteOrder(p.isa);
4010   sys::swapByteOrder(p.name);
4011   sys::swapByteOrder(p.protocols);
4012   sys::swapByteOrder(p.instanceMethods);
4013   sys::swapByteOrder(p.classMethods);
4014   sys::swapByteOrder(p.optionalInstanceMethods);
4015   sys::swapByteOrder(p.optionalClassMethods);
4016   sys::swapByteOrder(p.instanceProperties);
4017 }
4018 
swapStruct(struct ivar_list64_t & il)4019 inline void swapStruct(struct ivar_list64_t &il) {
4020   sys::swapByteOrder(il.entsize);
4021   sys::swapByteOrder(il.count);
4022 }
4023 
swapStruct(struct ivar_list32_t & il)4024 inline void swapStruct(struct ivar_list32_t &il) {
4025   sys::swapByteOrder(il.entsize);
4026   sys::swapByteOrder(il.count);
4027 }
4028 
swapStruct(struct ivar64_t & i)4029 inline void swapStruct(struct ivar64_t &i) {
4030   sys::swapByteOrder(i.offset);
4031   sys::swapByteOrder(i.name);
4032   sys::swapByteOrder(i.type);
4033   sys::swapByteOrder(i.alignment);
4034   sys::swapByteOrder(i.size);
4035 }
4036 
swapStruct(struct ivar32_t & i)4037 inline void swapStruct(struct ivar32_t &i) {
4038   sys::swapByteOrder(i.offset);
4039   sys::swapByteOrder(i.name);
4040   sys::swapByteOrder(i.type);
4041   sys::swapByteOrder(i.alignment);
4042   sys::swapByteOrder(i.size);
4043 }
4044 
swapStruct(struct objc_property_list64 & pl)4045 inline void swapStruct(struct objc_property_list64 &pl) {
4046   sys::swapByteOrder(pl.entsize);
4047   sys::swapByteOrder(pl.count);
4048 }
4049 
swapStruct(struct objc_property_list32 & pl)4050 inline void swapStruct(struct objc_property_list32 &pl) {
4051   sys::swapByteOrder(pl.entsize);
4052   sys::swapByteOrder(pl.count);
4053 }
4054 
swapStruct(struct objc_property64 & op)4055 inline void swapStruct(struct objc_property64 &op) {
4056   sys::swapByteOrder(op.name);
4057   sys::swapByteOrder(op.attributes);
4058 }
4059 
swapStruct(struct objc_property32 & op)4060 inline void swapStruct(struct objc_property32 &op) {
4061   sys::swapByteOrder(op.name);
4062   sys::swapByteOrder(op.attributes);
4063 }
4064 
swapStruct(struct category64_t & c)4065 inline void swapStruct(struct category64_t &c) {
4066   sys::swapByteOrder(c.name);
4067   sys::swapByteOrder(c.cls);
4068   sys::swapByteOrder(c.instanceMethods);
4069   sys::swapByteOrder(c.classMethods);
4070   sys::swapByteOrder(c.protocols);
4071   sys::swapByteOrder(c.instanceProperties);
4072 }
4073 
swapStruct(struct category32_t & c)4074 inline void swapStruct(struct category32_t &c) {
4075   sys::swapByteOrder(c.name);
4076   sys::swapByteOrder(c.cls);
4077   sys::swapByteOrder(c.instanceMethods);
4078   sys::swapByteOrder(c.classMethods);
4079   sys::swapByteOrder(c.protocols);
4080   sys::swapByteOrder(c.instanceProperties);
4081 }
4082 
swapStruct(struct objc_image_info64 & o)4083 inline void swapStruct(struct objc_image_info64 &o) {
4084   sys::swapByteOrder(o.version);
4085   sys::swapByteOrder(o.flags);
4086 }
4087 
swapStruct(struct objc_image_info32 & o)4088 inline void swapStruct(struct objc_image_info32 &o) {
4089   sys::swapByteOrder(o.version);
4090   sys::swapByteOrder(o.flags);
4091 }
4092 
swapStruct(struct imageInfo_t & o)4093 inline void swapStruct(struct imageInfo_t &o) {
4094   sys::swapByteOrder(o.version);
4095   sys::swapByteOrder(o.flags);
4096 }
4097 
swapStruct(struct message_ref64 & mr)4098 inline void swapStruct(struct message_ref64 &mr) {
4099   sys::swapByteOrder(mr.imp);
4100   sys::swapByteOrder(mr.sel);
4101 }
4102 
swapStruct(struct message_ref32 & mr)4103 inline void swapStruct(struct message_ref32 &mr) {
4104   sys::swapByteOrder(mr.imp);
4105   sys::swapByteOrder(mr.sel);
4106 }
4107 
swapStruct(struct objc_module_t & module)4108 inline void swapStruct(struct objc_module_t &module) {
4109   sys::swapByteOrder(module.version);
4110   sys::swapByteOrder(module.size);
4111   sys::swapByteOrder(module.name);
4112   sys::swapByteOrder(module.symtab);
4113 }
4114 
swapStruct(struct objc_symtab_t & symtab)4115 inline void swapStruct(struct objc_symtab_t &symtab) {
4116   sys::swapByteOrder(symtab.sel_ref_cnt);
4117   sys::swapByteOrder(symtab.refs);
4118   sys::swapByteOrder(symtab.cls_def_cnt);
4119   sys::swapByteOrder(symtab.cat_def_cnt);
4120 }
4121 
swapStruct(struct objc_class_t & objc_class)4122 inline void swapStruct(struct objc_class_t &objc_class) {
4123   sys::swapByteOrder(objc_class.isa);
4124   sys::swapByteOrder(objc_class.super_class);
4125   sys::swapByteOrder(objc_class.name);
4126   sys::swapByteOrder(objc_class.version);
4127   sys::swapByteOrder(objc_class.info);
4128   sys::swapByteOrder(objc_class.instance_size);
4129   sys::swapByteOrder(objc_class.ivars);
4130   sys::swapByteOrder(objc_class.methodLists);
4131   sys::swapByteOrder(objc_class.cache);
4132   sys::swapByteOrder(objc_class.protocols);
4133 }
4134 
swapStruct(struct objc_category_t & objc_category)4135 inline void swapStruct(struct objc_category_t &objc_category) {
4136   sys::swapByteOrder(objc_category.category_name);
4137   sys::swapByteOrder(objc_category.class_name);
4138   sys::swapByteOrder(objc_category.instance_methods);
4139   sys::swapByteOrder(objc_category.class_methods);
4140   sys::swapByteOrder(objc_category.protocols);
4141 }
4142 
swapStruct(struct objc_ivar_list_t & objc_ivar_list)4143 inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
4144   sys::swapByteOrder(objc_ivar_list.ivar_count);
4145 }
4146 
swapStruct(struct objc_ivar_t & objc_ivar)4147 inline void swapStruct(struct objc_ivar_t &objc_ivar) {
4148   sys::swapByteOrder(objc_ivar.ivar_name);
4149   sys::swapByteOrder(objc_ivar.ivar_type);
4150   sys::swapByteOrder(objc_ivar.ivar_offset);
4151 }
4152 
swapStruct(struct objc_method_list_t & method_list)4153 inline void swapStruct(struct objc_method_list_t &method_list) {
4154   sys::swapByteOrder(method_list.obsolete);
4155   sys::swapByteOrder(method_list.method_count);
4156 }
4157 
swapStruct(struct objc_method_t & method)4158 inline void swapStruct(struct objc_method_t &method) {
4159   sys::swapByteOrder(method.method_name);
4160   sys::swapByteOrder(method.method_types);
4161   sys::swapByteOrder(method.method_imp);
4162 }
4163 
swapStruct(struct objc_protocol_list_t & protocol_list)4164 inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
4165   sys::swapByteOrder(protocol_list.next);
4166   sys::swapByteOrder(protocol_list.count);
4167 }
4168 
swapStruct(struct objc_protocol_t & protocol)4169 inline void swapStruct(struct objc_protocol_t &protocol) {
4170   sys::swapByteOrder(protocol.isa);
4171   sys::swapByteOrder(protocol.protocol_name);
4172   sys::swapByteOrder(protocol.protocol_list);
4173   sys::swapByteOrder(protocol.instance_methods);
4174   sys::swapByteOrder(protocol.class_methods);
4175 }
4176 
swapStruct(struct objc_method_description_list_t & mdl)4177 inline void swapStruct(struct objc_method_description_list_t &mdl) {
4178   sys::swapByteOrder(mdl.count);
4179 }
4180 
swapStruct(struct objc_method_description_t & md)4181 inline void swapStruct(struct objc_method_description_t &md) {
4182   sys::swapByteOrder(md.name);
4183   sys::swapByteOrder(md.types);
4184 }
4185 
4186 } // namespace
4187 
4188 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
4189                                                  struct DisassembleInfo *info);
4190 
4191 // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
4192 // to an Objective-C class and returns the class name.  It is also passed the
4193 // address of the pointer, so when the pointer is zero as it can be in an .o
4194 // file, that is used to look for an external relocation entry with a symbol
4195 // name.
get_objc2_64bit_class_name(uint64_t pointer_value,uint64_t ReferenceValue,struct DisassembleInfo * info)4196 static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
4197                                               uint64_t ReferenceValue,
4198                                               struct DisassembleInfo *info) {
4199   const char *r;
4200   uint32_t offset, left;
4201   SectionRef S;
4202 
4203   // The pointer_value can be 0 in an object file and have a relocation
4204   // entry for the class symbol at the ReferenceValue (the address of the
4205   // pointer).
4206   if (pointer_value == 0) {
4207     r = get_pointer_64(ReferenceValue, offset, left, S, info);
4208     if (r == nullptr || left < sizeof(uint64_t))
4209       return nullptr;
4210     uint64_t n_value;
4211     const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4212     if (symbol_name == nullptr)
4213       return nullptr;
4214     const char *class_name = strrchr(symbol_name, '$');
4215     if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
4216       return class_name + 2;
4217     else
4218       return nullptr;
4219   }
4220 
4221   // The case were the pointer_value is non-zero and points to a class defined
4222   // in this Mach-O file.
4223   r = get_pointer_64(pointer_value, offset, left, S, info);
4224   if (r == nullptr || left < sizeof(struct class64_t))
4225     return nullptr;
4226   struct class64_t c;
4227   memcpy(&c, r, sizeof(struct class64_t));
4228   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4229     swapStruct(c);
4230   if (c.data == 0)
4231     return nullptr;
4232   r = get_pointer_64(c.data, offset, left, S, info);
4233   if (r == nullptr || left < sizeof(struct class_ro64_t))
4234     return nullptr;
4235   struct class_ro64_t cro;
4236   memcpy(&cro, r, sizeof(struct class_ro64_t));
4237   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4238     swapStruct(cro);
4239   if (cro.name == 0)
4240     return nullptr;
4241   const char *name = get_pointer_64(cro.name, offset, left, S, info);
4242   return name;
4243 }
4244 
4245 // get_objc2_64bit_cfstring_name is used for disassembly and is passed a
4246 // pointer to a cfstring and returns its name or nullptr.
get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,struct DisassembleInfo * info)4247 static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
4248                                                  struct DisassembleInfo *info) {
4249   const char *r, *name;
4250   uint32_t offset, left;
4251   SectionRef S;
4252   struct cfstring64_t cfs;
4253   uint64_t cfs_characters;
4254 
4255   r = get_pointer_64(ReferenceValue, offset, left, S, info);
4256   if (r == nullptr || left < sizeof(struct cfstring64_t))
4257     return nullptr;
4258   memcpy(&cfs, r, sizeof(struct cfstring64_t));
4259   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4260     swapStruct(cfs);
4261   if (cfs.characters == 0) {
4262     uint64_t n_value;
4263     const char *symbol_name = get_symbol_64(
4264         offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
4265     if (symbol_name == nullptr)
4266       return nullptr;
4267     cfs_characters = n_value;
4268   } else
4269     cfs_characters = cfs.characters;
4270   name = get_pointer_64(cfs_characters, offset, left, S, info);
4271 
4272   return name;
4273 }
4274 
4275 // get_objc2_64bit_selref() is used for disassembly and is passed a the address
4276 // of a pointer to an Objective-C selector reference when the pointer value is
4277 // zero as in a .o file and is likely to have a external relocation entry with
4278 // who's symbol's n_value is the real pointer to the selector name.  If that is
4279 // the case the real pointer to the selector name is returned else 0 is
4280 // returned
get_objc2_64bit_selref(uint64_t ReferenceValue,struct DisassembleInfo * info)4281 static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
4282                                        struct DisassembleInfo *info) {
4283   uint32_t offset, left;
4284   SectionRef S;
4285 
4286   const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
4287   if (r == nullptr || left < sizeof(uint64_t))
4288     return 0;
4289   uint64_t n_value;
4290   const char *symbol_name = get_symbol_64(offset, S, info, n_value);
4291   if (symbol_name == nullptr)
4292     return 0;
4293   return n_value;
4294 }
4295 
get_section(MachOObjectFile * O,const char * segname,const char * sectname)4296 static const SectionRef get_section(MachOObjectFile *O, const char *segname,
4297                                     const char *sectname) {
4298   for (const SectionRef &Section : O->sections()) {
4299     StringRef SectName;
4300     Expected<StringRef> SecNameOrErr = Section.getName();
4301     if (SecNameOrErr)
4302       SectName = *SecNameOrErr;
4303     else
4304       consumeError(SecNameOrErr.takeError());
4305 
4306     DataRefImpl Ref = Section.getRawDataRefImpl();
4307     StringRef SegName = O->getSectionFinalSegmentName(Ref);
4308     if (SegName == segname && SectName == sectname)
4309       return Section;
4310   }
4311   return SectionRef();
4312 }
4313 
4314 static void
walk_pointer_list_64(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint64_t,struct DisassembleInfo * info))4315 walk_pointer_list_64(const char *listname, const SectionRef S,
4316                      MachOObjectFile *O, struct DisassembleInfo *info,
4317                      void (*func)(uint64_t, struct DisassembleInfo *info)) {
4318   if (S == SectionRef())
4319     return;
4320 
4321   StringRef SectName;
4322   Expected<StringRef> SecNameOrErr = S.getName();
4323   if (SecNameOrErr)
4324     SectName = *SecNameOrErr;
4325   else
4326     consumeError(SecNameOrErr.takeError());
4327 
4328   DataRefImpl Ref = S.getRawDataRefImpl();
4329   StringRef SegName = O->getSectionFinalSegmentName(Ref);
4330   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4331 
4332   StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4333   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4334 
4335   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
4336     uint32_t left = S.getSize() - i;
4337     uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
4338     uint64_t p = 0;
4339     memcpy(&p, Contents + i, size);
4340     if (i + sizeof(uint64_t) > S.getSize())
4341       outs() << listname << " list pointer extends past end of (" << SegName
4342              << "," << SectName << ") section\n";
4343     outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
4344 
4345     if (O->isLittleEndian() != sys::IsLittleEndianHost)
4346       sys::swapByteOrder(p);
4347 
4348     uint64_t n_value = 0;
4349     const char *name = get_symbol_64(i, S, info, n_value, p);
4350     if (name == nullptr)
4351       name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
4352 
4353     if (n_value != 0) {
4354       outs() << format("0x%" PRIx64, n_value);
4355       if (p != 0)
4356         outs() << " + " << format("0x%" PRIx64, p);
4357     } else
4358       outs() << format("0x%" PRIx64, p);
4359     if (name != nullptr)
4360       outs() << " " << name;
4361     outs() << "\n";
4362 
4363     p += n_value;
4364     if (func)
4365       func(p, info);
4366   }
4367 }
4368 
4369 static void
walk_pointer_list_32(const char * listname,const SectionRef S,MachOObjectFile * O,struct DisassembleInfo * info,void (* func)(uint32_t,struct DisassembleInfo * info))4370 walk_pointer_list_32(const char *listname, const SectionRef S,
4371                      MachOObjectFile *O, struct DisassembleInfo *info,
4372                      void (*func)(uint32_t, struct DisassembleInfo *info)) {
4373   if (S == SectionRef())
4374     return;
4375 
4376   StringRef SectName = unwrapOrError(S.getName(), O->getFileName());
4377   DataRefImpl Ref = S.getRawDataRefImpl();
4378   StringRef SegName = O->getSectionFinalSegmentName(Ref);
4379   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
4380 
4381   StringRef BytesStr = unwrapOrError(S.getContents(), O->getFileName());
4382   const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
4383 
4384   for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
4385     uint32_t left = S.getSize() - i;
4386     uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
4387     uint32_t p = 0;
4388     memcpy(&p, Contents + i, size);
4389     if (i + sizeof(uint32_t) > S.getSize())
4390       outs() << listname << " list pointer extends past end of (" << SegName
4391              << "," << SectName << ") section\n";
4392     uint32_t Address = S.getAddress() + i;
4393     outs() << format("%08" PRIx32, Address) << " ";
4394 
4395     if (O->isLittleEndian() != sys::IsLittleEndianHost)
4396       sys::swapByteOrder(p);
4397     outs() << format("0x%" PRIx32, p);
4398 
4399     const char *name = get_symbol_32(i, S, info, p);
4400     if (name != nullptr)
4401       outs() << " " << name;
4402     outs() << "\n";
4403 
4404     if (func)
4405       func(p, info);
4406   }
4407 }
4408 
print_layout_map(const char * layout_map,uint32_t left)4409 static void print_layout_map(const char *layout_map, uint32_t left) {
4410   if (layout_map == nullptr)
4411     return;
4412   outs() << "                layout map: ";
4413   do {
4414     outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
4415     left--;
4416     layout_map++;
4417   } while (*layout_map != '\0' && left != 0);
4418   outs() << "\n";
4419 }
4420 
print_layout_map64(uint64_t p,struct DisassembleInfo * info)4421 static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
4422   uint32_t offset, left;
4423   SectionRef S;
4424   const char *layout_map;
4425 
4426   if (p == 0)
4427     return;
4428   layout_map = get_pointer_64(p, offset, left, S, info);
4429   print_layout_map(layout_map, left);
4430 }
4431 
print_layout_map32(uint32_t p,struct DisassembleInfo * info)4432 static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
4433   uint32_t offset, left;
4434   SectionRef S;
4435   const char *layout_map;
4436 
4437   if (p == 0)
4438     return;
4439   layout_map = get_pointer_32(p, offset, left, S, info);
4440   print_layout_map(layout_map, left);
4441 }
4442 
print_method_list64_t(uint64_t p,struct DisassembleInfo * info,const char * indent)4443 static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
4444                                   const char *indent) {
4445   struct method_list64_t ml;
4446   struct method64_t m;
4447   const char *r;
4448   uint32_t offset, xoffset, left, i;
4449   SectionRef S, xS;
4450   const char *name, *sym_name;
4451   uint64_t n_value;
4452 
4453   r = get_pointer_64(p, offset, left, S, info);
4454   if (r == nullptr)
4455     return;
4456   memset(&ml, '\0', sizeof(struct method_list64_t));
4457   if (left < sizeof(struct method_list64_t)) {
4458     memcpy(&ml, r, left);
4459     outs() << "   (method_list_t entends past the end of the section)\n";
4460   } else
4461     memcpy(&ml, r, sizeof(struct method_list64_t));
4462   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4463     swapStruct(ml);
4464   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4465   outs() << indent << "\t\t     count " << ml.count << "\n";
4466 
4467   p += sizeof(struct method_list64_t);
4468   offset += sizeof(struct method_list64_t);
4469   for (i = 0; i < ml.count; i++) {
4470     r = get_pointer_64(p, offset, left, S, info);
4471     if (r == nullptr)
4472       return;
4473     memset(&m, '\0', sizeof(struct method64_t));
4474     if (left < sizeof(struct method64_t)) {
4475       memcpy(&m, r, left);
4476       outs() << indent << "   (method_t extends past the end of the section)\n";
4477     } else
4478       memcpy(&m, r, sizeof(struct method64_t));
4479     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4480       swapStruct(m);
4481 
4482     outs() << indent << "\t\t      name ";
4483     sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
4484                              info, n_value, m.name);
4485     if (n_value != 0) {
4486       if (info->verbose && sym_name != nullptr)
4487         outs() << sym_name;
4488       else
4489         outs() << format("0x%" PRIx64, n_value);
4490       if (m.name != 0)
4491         outs() << " + " << format("0x%" PRIx64, m.name);
4492     } else
4493       outs() << format("0x%" PRIx64, m.name);
4494     name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
4495     if (name != nullptr)
4496       outs() << format(" %.*s", left, name);
4497     outs() << "\n";
4498 
4499     outs() << indent << "\t\t     types ";
4500     sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
4501                              info, n_value, m.types);
4502     if (n_value != 0) {
4503       if (info->verbose && sym_name != nullptr)
4504         outs() << sym_name;
4505       else
4506         outs() << format("0x%" PRIx64, n_value);
4507       if (m.types != 0)
4508         outs() << " + " << format("0x%" PRIx64, m.types);
4509     } else
4510       outs() << format("0x%" PRIx64, m.types);
4511     name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
4512     if (name != nullptr)
4513       outs() << format(" %.*s", left, name);
4514     outs() << "\n";
4515 
4516     outs() << indent << "\t\t       imp ";
4517     name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
4518                          n_value, m.imp);
4519     if (info->verbose && name == nullptr) {
4520       if (n_value != 0) {
4521         outs() << format("0x%" PRIx64, n_value) << " ";
4522         if (m.imp != 0)
4523           outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
4524       } else
4525         outs() << format("0x%" PRIx64, m.imp) << " ";
4526     }
4527     if (name != nullptr)
4528       outs() << name;
4529     outs() << "\n";
4530 
4531     p += sizeof(struct method64_t);
4532     offset += sizeof(struct method64_t);
4533   }
4534 }
4535 
print_method_list32_t(uint64_t p,struct DisassembleInfo * info,const char * indent)4536 static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
4537                                   const char *indent) {
4538   struct method_list32_t ml;
4539   struct method32_t m;
4540   const char *r, *name;
4541   uint32_t offset, xoffset, left, i;
4542   SectionRef S, xS;
4543 
4544   r = get_pointer_32(p, offset, left, S, info);
4545   if (r == nullptr)
4546     return;
4547   memset(&ml, '\0', sizeof(struct method_list32_t));
4548   if (left < sizeof(struct method_list32_t)) {
4549     memcpy(&ml, r, left);
4550     outs() << "   (method_list_t entends past the end of the section)\n";
4551   } else
4552     memcpy(&ml, r, sizeof(struct method_list32_t));
4553   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4554     swapStruct(ml);
4555   outs() << indent << "\t\t   entsize " << ml.entsize << "\n";
4556   outs() << indent << "\t\t     count " << ml.count << "\n";
4557 
4558   p += sizeof(struct method_list32_t);
4559   offset += sizeof(struct method_list32_t);
4560   for (i = 0; i < ml.count; i++) {
4561     r = get_pointer_32(p, offset, left, S, info);
4562     if (r == nullptr)
4563       return;
4564     memset(&m, '\0', sizeof(struct method32_t));
4565     if (left < sizeof(struct method32_t)) {
4566       memcpy(&ml, r, left);
4567       outs() << indent << "   (method_t entends past the end of the section)\n";
4568     } else
4569       memcpy(&m, r, sizeof(struct method32_t));
4570     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4571       swapStruct(m);
4572 
4573     outs() << indent << "\t\t      name " << format("0x%" PRIx32, m.name);
4574     name = get_pointer_32(m.name, xoffset, left, xS, info);
4575     if (name != nullptr)
4576       outs() << format(" %.*s", left, name);
4577     outs() << "\n";
4578 
4579     outs() << indent << "\t\t     types " << format("0x%" PRIx32, m.types);
4580     name = get_pointer_32(m.types, xoffset, left, xS, info);
4581     if (name != nullptr)
4582       outs() << format(" %.*s", left, name);
4583     outs() << "\n";
4584 
4585     outs() << indent << "\t\t       imp " << format("0x%" PRIx32, m.imp);
4586     name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
4587                          m.imp);
4588     if (name != nullptr)
4589       outs() << " " << name;
4590     outs() << "\n";
4591 
4592     p += sizeof(struct method32_t);
4593     offset += sizeof(struct method32_t);
4594   }
4595 }
4596 
print_method_list(uint32_t p,struct DisassembleInfo * info)4597 static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
4598   uint32_t offset, left, xleft;
4599   SectionRef S;
4600   struct objc_method_list_t method_list;
4601   struct objc_method_t method;
4602   const char *r, *methods, *name, *SymbolName;
4603   int32_t i;
4604 
4605   r = get_pointer_32(p, offset, left, S, info, true);
4606   if (r == nullptr)
4607     return true;
4608 
4609   outs() << "\n";
4610   if (left > sizeof(struct objc_method_list_t)) {
4611     memcpy(&method_list, r, sizeof(struct objc_method_list_t));
4612   } else {
4613     outs() << "\t\t objc_method_list extends past end of the section\n";
4614     memset(&method_list, '\0', sizeof(struct objc_method_list_t));
4615     memcpy(&method_list, r, left);
4616   }
4617   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4618     swapStruct(method_list);
4619 
4620   outs() << "\t\t         obsolete "
4621          << format("0x%08" PRIx32, method_list.obsolete) << "\n";
4622   outs() << "\t\t     method_count " << method_list.method_count << "\n";
4623 
4624   methods = r + sizeof(struct objc_method_list_t);
4625   for (i = 0; i < method_list.method_count; i++) {
4626     if ((i + 1) * sizeof(struct objc_method_t) > left) {
4627       outs() << "\t\t remaining method's extend past the of the section\n";
4628       break;
4629     }
4630     memcpy(&method, methods + i * sizeof(struct objc_method_t),
4631            sizeof(struct objc_method_t));
4632     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4633       swapStruct(method);
4634 
4635     outs() << "\t\t      method_name "
4636            << format("0x%08" PRIx32, method.method_name);
4637     if (info->verbose) {
4638       name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
4639       if (name != nullptr)
4640         outs() << format(" %.*s", xleft, name);
4641       else
4642         outs() << " (not in an __OBJC section)";
4643     }
4644     outs() << "\n";
4645 
4646     outs() << "\t\t     method_types "
4647            << format("0x%08" PRIx32, method.method_types);
4648     if (info->verbose) {
4649       name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
4650       if (name != nullptr)
4651         outs() << format(" %.*s", xleft, name);
4652       else
4653         outs() << " (not in an __OBJC section)";
4654     }
4655     outs() << "\n";
4656 
4657     outs() << "\t\t       method_imp "
4658            << format("0x%08" PRIx32, method.method_imp) << " ";
4659     if (info->verbose) {
4660       SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
4661       if (SymbolName != nullptr)
4662         outs() << SymbolName;
4663     }
4664     outs() << "\n";
4665   }
4666   return false;
4667 }
4668 
print_protocol_list64_t(uint64_t p,struct DisassembleInfo * info)4669 static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
4670   struct protocol_list64_t pl;
4671   uint64_t q, n_value;
4672   struct protocol64_t pc;
4673   const char *r;
4674   uint32_t offset, xoffset, left, i;
4675   SectionRef S, xS;
4676   const char *name, *sym_name;
4677 
4678   r = get_pointer_64(p, offset, left, S, info);
4679   if (r == nullptr)
4680     return;
4681   memset(&pl, '\0', sizeof(struct protocol_list64_t));
4682   if (left < sizeof(struct protocol_list64_t)) {
4683     memcpy(&pl, r, left);
4684     outs() << "   (protocol_list_t entends past the end of the section)\n";
4685   } else
4686     memcpy(&pl, r, sizeof(struct protocol_list64_t));
4687   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4688     swapStruct(pl);
4689   outs() << "                      count " << pl.count << "\n";
4690 
4691   p += sizeof(struct protocol_list64_t);
4692   offset += sizeof(struct protocol_list64_t);
4693   for (i = 0; i < pl.count; i++) {
4694     r = get_pointer_64(p, offset, left, S, info);
4695     if (r == nullptr)
4696       return;
4697     q = 0;
4698     if (left < sizeof(uint64_t)) {
4699       memcpy(&q, r, left);
4700       outs() << "   (protocol_t * entends past the end of the section)\n";
4701     } else
4702       memcpy(&q, r, sizeof(uint64_t));
4703     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4704       sys::swapByteOrder(q);
4705 
4706     outs() << "\t\t      list[" << i << "] ";
4707     sym_name = get_symbol_64(offset, S, info, n_value, q);
4708     if (n_value != 0) {
4709       if (info->verbose && sym_name != nullptr)
4710         outs() << sym_name;
4711       else
4712         outs() << format("0x%" PRIx64, n_value);
4713       if (q != 0)
4714         outs() << " + " << format("0x%" PRIx64, q);
4715     } else
4716       outs() << format("0x%" PRIx64, q);
4717     outs() << " (struct protocol_t *)\n";
4718 
4719     r = get_pointer_64(q + n_value, offset, left, S, info);
4720     if (r == nullptr)
4721       return;
4722     memset(&pc, '\0', sizeof(struct protocol64_t));
4723     if (left < sizeof(struct protocol64_t)) {
4724       memcpy(&pc, r, left);
4725       outs() << "   (protocol_t entends past the end of the section)\n";
4726     } else
4727       memcpy(&pc, r, sizeof(struct protocol64_t));
4728     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4729       swapStruct(pc);
4730 
4731     outs() << "\t\t\t      isa " << format("0x%" PRIx64, pc.isa) << "\n";
4732 
4733     outs() << "\t\t\t     name ";
4734     sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
4735                              info, n_value, pc.name);
4736     if (n_value != 0) {
4737       if (info->verbose && sym_name != nullptr)
4738         outs() << sym_name;
4739       else
4740         outs() << format("0x%" PRIx64, n_value);
4741       if (pc.name != 0)
4742         outs() << " + " << format("0x%" PRIx64, pc.name);
4743     } else
4744       outs() << format("0x%" PRIx64, pc.name);
4745     name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
4746     if (name != nullptr)
4747       outs() << format(" %.*s", left, name);
4748     outs() << "\n";
4749 
4750     outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
4751 
4752     outs() << "\t\t  instanceMethods ";
4753     sym_name =
4754         get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
4755                       S, info, n_value, pc.instanceMethods);
4756     if (n_value != 0) {
4757       if (info->verbose && sym_name != nullptr)
4758         outs() << sym_name;
4759       else
4760         outs() << format("0x%" PRIx64, n_value);
4761       if (pc.instanceMethods != 0)
4762         outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
4763     } else
4764       outs() << format("0x%" PRIx64, pc.instanceMethods);
4765     outs() << " (struct method_list_t *)\n";
4766     if (pc.instanceMethods + n_value != 0)
4767       print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
4768 
4769     outs() << "\t\t     classMethods ";
4770     sym_name =
4771         get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
4772                       info, n_value, pc.classMethods);
4773     if (n_value != 0) {
4774       if (info->verbose && sym_name != nullptr)
4775         outs() << sym_name;
4776       else
4777         outs() << format("0x%" PRIx64, n_value);
4778       if (pc.classMethods != 0)
4779         outs() << " + " << format("0x%" PRIx64, pc.classMethods);
4780     } else
4781       outs() << format("0x%" PRIx64, pc.classMethods);
4782     outs() << " (struct method_list_t *)\n";
4783     if (pc.classMethods + n_value != 0)
4784       print_method_list64_t(pc.classMethods + n_value, info, "\t");
4785 
4786     outs() << "\t  optionalInstanceMethods "
4787            << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
4788     outs() << "\t     optionalClassMethods "
4789            << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
4790     outs() << "\t       instanceProperties "
4791            << format("0x%" PRIx64, pc.instanceProperties) << "\n";
4792 
4793     p += sizeof(uint64_t);
4794     offset += sizeof(uint64_t);
4795   }
4796 }
4797 
print_protocol_list32_t(uint32_t p,struct DisassembleInfo * info)4798 static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
4799   struct protocol_list32_t pl;
4800   uint32_t q;
4801   struct protocol32_t pc;
4802   const char *r;
4803   uint32_t offset, xoffset, left, i;
4804   SectionRef S, xS;
4805   const char *name;
4806 
4807   r = get_pointer_32(p, offset, left, S, info);
4808   if (r == nullptr)
4809     return;
4810   memset(&pl, '\0', sizeof(struct protocol_list32_t));
4811   if (left < sizeof(struct protocol_list32_t)) {
4812     memcpy(&pl, r, left);
4813     outs() << "   (protocol_list_t entends past the end of the section)\n";
4814   } else
4815     memcpy(&pl, r, sizeof(struct protocol_list32_t));
4816   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4817     swapStruct(pl);
4818   outs() << "                      count " << pl.count << "\n";
4819 
4820   p += sizeof(struct protocol_list32_t);
4821   offset += sizeof(struct protocol_list32_t);
4822   for (i = 0; i < pl.count; i++) {
4823     r = get_pointer_32(p, offset, left, S, info);
4824     if (r == nullptr)
4825       return;
4826     q = 0;
4827     if (left < sizeof(uint32_t)) {
4828       memcpy(&q, r, left);
4829       outs() << "   (protocol_t * entends past the end of the section)\n";
4830     } else
4831       memcpy(&q, r, sizeof(uint32_t));
4832     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4833       sys::swapByteOrder(q);
4834     outs() << "\t\t      list[" << i << "] " << format("0x%" PRIx32, q)
4835            << " (struct protocol_t *)\n";
4836     r = get_pointer_32(q, offset, left, S, info);
4837     if (r == nullptr)
4838       return;
4839     memset(&pc, '\0', sizeof(struct protocol32_t));
4840     if (left < sizeof(struct protocol32_t)) {
4841       memcpy(&pc, r, left);
4842       outs() << "   (protocol_t entends past the end of the section)\n";
4843     } else
4844       memcpy(&pc, r, sizeof(struct protocol32_t));
4845     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4846       swapStruct(pc);
4847     outs() << "\t\t\t      isa " << format("0x%" PRIx32, pc.isa) << "\n";
4848     outs() << "\t\t\t     name " << format("0x%" PRIx32, pc.name);
4849     name = get_pointer_32(pc.name, xoffset, left, xS, info);
4850     if (name != nullptr)
4851       outs() << format(" %.*s", left, name);
4852     outs() << "\n";
4853     outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
4854     outs() << "\t\t  instanceMethods "
4855            << format("0x%" PRIx32, pc.instanceMethods)
4856            << " (struct method_list_t *)\n";
4857     if (pc.instanceMethods != 0)
4858       print_method_list32_t(pc.instanceMethods, info, "\t");
4859     outs() << "\t\t     classMethods " << format("0x%" PRIx32, pc.classMethods)
4860            << " (struct method_list_t *)\n";
4861     if (pc.classMethods != 0)
4862       print_method_list32_t(pc.classMethods, info, "\t");
4863     outs() << "\t  optionalInstanceMethods "
4864            << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
4865     outs() << "\t     optionalClassMethods "
4866            << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
4867     outs() << "\t       instanceProperties "
4868            << format("0x%" PRIx32, pc.instanceProperties) << "\n";
4869     p += sizeof(uint32_t);
4870     offset += sizeof(uint32_t);
4871   }
4872 }
4873 
print_indent(uint32_t indent)4874 static void print_indent(uint32_t indent) {
4875   for (uint32_t i = 0; i < indent;) {
4876     if (indent - i >= 8) {
4877       outs() << "\t";
4878       i += 8;
4879     } else {
4880       for (uint32_t j = i; j < indent; j++)
4881         outs() << " ";
4882       return;
4883     }
4884   }
4885 }
4886 
print_method_description_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)4887 static bool print_method_description_list(uint32_t p, uint32_t indent,
4888                                           struct DisassembleInfo *info) {
4889   uint32_t offset, left, xleft;
4890   SectionRef S;
4891   struct objc_method_description_list_t mdl;
4892   struct objc_method_description_t md;
4893   const char *r, *list, *name;
4894   int32_t i;
4895 
4896   r = get_pointer_32(p, offset, left, S, info, true);
4897   if (r == nullptr)
4898     return true;
4899 
4900   outs() << "\n";
4901   if (left > sizeof(struct objc_method_description_list_t)) {
4902     memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
4903   } else {
4904     print_indent(indent);
4905     outs() << " objc_method_description_list extends past end of the section\n";
4906     memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
4907     memcpy(&mdl, r, left);
4908   }
4909   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4910     swapStruct(mdl);
4911 
4912   print_indent(indent);
4913   outs() << "        count " << mdl.count << "\n";
4914 
4915   list = r + sizeof(struct objc_method_description_list_t);
4916   for (i = 0; i < mdl.count; i++) {
4917     if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
4918       print_indent(indent);
4919       outs() << " remaining list entries extend past the of the section\n";
4920       break;
4921     }
4922     print_indent(indent);
4923     outs() << "        list[" << i << "]\n";
4924     memcpy(&md, list + i * sizeof(struct objc_method_description_t),
4925            sizeof(struct objc_method_description_t));
4926     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4927       swapStruct(md);
4928 
4929     print_indent(indent);
4930     outs() << "             name " << format("0x%08" PRIx32, md.name);
4931     if (info->verbose) {
4932       name = get_pointer_32(md.name, offset, xleft, S, info, true);
4933       if (name != nullptr)
4934         outs() << format(" %.*s", xleft, name);
4935       else
4936         outs() << " (not in an __OBJC section)";
4937     }
4938     outs() << "\n";
4939 
4940     print_indent(indent);
4941     outs() << "            types " << format("0x%08" PRIx32, md.types);
4942     if (info->verbose) {
4943       name = get_pointer_32(md.types, offset, xleft, S, info, true);
4944       if (name != nullptr)
4945         outs() << format(" %.*s", xleft, name);
4946       else
4947         outs() << " (not in an __OBJC section)";
4948     }
4949     outs() << "\n";
4950   }
4951   return false;
4952 }
4953 
4954 static bool print_protocol_list(uint32_t p, uint32_t indent,
4955                                 struct DisassembleInfo *info);
4956 
print_protocol(uint32_t p,uint32_t indent,struct DisassembleInfo * info)4957 static bool print_protocol(uint32_t p, uint32_t indent,
4958                            struct DisassembleInfo *info) {
4959   uint32_t offset, left;
4960   SectionRef S;
4961   struct objc_protocol_t protocol;
4962   const char *r, *name;
4963 
4964   r = get_pointer_32(p, offset, left, S, info, true);
4965   if (r == nullptr)
4966     return true;
4967 
4968   outs() << "\n";
4969   if (left >= sizeof(struct objc_protocol_t)) {
4970     memcpy(&protocol, r, sizeof(struct objc_protocol_t));
4971   } else {
4972     print_indent(indent);
4973     outs() << "            Protocol extends past end of the section\n";
4974     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
4975     memcpy(&protocol, r, left);
4976   }
4977   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
4978     swapStruct(protocol);
4979 
4980   print_indent(indent);
4981   outs() << "              isa " << format("0x%08" PRIx32, protocol.isa)
4982          << "\n";
4983 
4984   print_indent(indent);
4985   outs() << "    protocol_name "
4986          << format("0x%08" PRIx32, protocol.protocol_name);
4987   if (info->verbose) {
4988     name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
4989     if (name != nullptr)
4990       outs() << format(" %.*s", left, name);
4991     else
4992       outs() << " (not in an __OBJC section)";
4993   }
4994   outs() << "\n";
4995 
4996   print_indent(indent);
4997   outs() << "    protocol_list "
4998          << format("0x%08" PRIx32, protocol.protocol_list);
4999   if (print_protocol_list(protocol.protocol_list, indent + 4, info))
5000     outs() << " (not in an __OBJC section)\n";
5001 
5002   print_indent(indent);
5003   outs() << " instance_methods "
5004          << format("0x%08" PRIx32, protocol.instance_methods);
5005   if (print_method_description_list(protocol.instance_methods, indent, info))
5006     outs() << " (not in an __OBJC section)\n";
5007 
5008   print_indent(indent);
5009   outs() << "    class_methods "
5010          << format("0x%08" PRIx32, protocol.class_methods);
5011   if (print_method_description_list(protocol.class_methods, indent, info))
5012     outs() << " (not in an __OBJC section)\n";
5013 
5014   return false;
5015 }
5016 
print_protocol_list(uint32_t p,uint32_t indent,struct DisassembleInfo * info)5017 static bool print_protocol_list(uint32_t p, uint32_t indent,
5018                                 struct DisassembleInfo *info) {
5019   uint32_t offset, left, l;
5020   SectionRef S;
5021   struct objc_protocol_list_t protocol_list;
5022   const char *r, *list;
5023   int32_t i;
5024 
5025   r = get_pointer_32(p, offset, left, S, info, true);
5026   if (r == nullptr)
5027     return true;
5028 
5029   outs() << "\n";
5030   if (left > sizeof(struct objc_protocol_list_t)) {
5031     memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
5032   } else {
5033     outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
5034     memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
5035     memcpy(&protocol_list, r, left);
5036   }
5037   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5038     swapStruct(protocol_list);
5039 
5040   print_indent(indent);
5041   outs() << "         next " << format("0x%08" PRIx32, protocol_list.next)
5042          << "\n";
5043   print_indent(indent);
5044   outs() << "        count " << protocol_list.count << "\n";
5045 
5046   list = r + sizeof(struct objc_protocol_list_t);
5047   for (i = 0; i < protocol_list.count; i++) {
5048     if ((i + 1) * sizeof(uint32_t) > left) {
5049       outs() << "\t\t remaining list entries extend past the of the section\n";
5050       break;
5051     }
5052     memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
5053     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5054       sys::swapByteOrder(l);
5055 
5056     print_indent(indent);
5057     outs() << "      list[" << i << "] " << format("0x%08" PRIx32, l);
5058     if (print_protocol(l, indent, info))
5059       outs() << "(not in an __OBJC section)\n";
5060   }
5061   return false;
5062 }
5063 
print_ivar_list64_t(uint64_t p,struct DisassembleInfo * info)5064 static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
5065   struct ivar_list64_t il;
5066   struct ivar64_t i;
5067   const char *r;
5068   uint32_t offset, xoffset, left, j;
5069   SectionRef S, xS;
5070   const char *name, *sym_name, *ivar_offset_p;
5071   uint64_t ivar_offset, n_value;
5072 
5073   r = get_pointer_64(p, offset, left, S, info);
5074   if (r == nullptr)
5075     return;
5076   memset(&il, '\0', sizeof(struct ivar_list64_t));
5077   if (left < sizeof(struct ivar_list64_t)) {
5078     memcpy(&il, r, left);
5079     outs() << "   (ivar_list_t entends past the end of the section)\n";
5080   } else
5081     memcpy(&il, r, sizeof(struct ivar_list64_t));
5082   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5083     swapStruct(il);
5084   outs() << "                    entsize " << il.entsize << "\n";
5085   outs() << "                      count " << il.count << "\n";
5086 
5087   p += sizeof(struct ivar_list64_t);
5088   offset += sizeof(struct ivar_list64_t);
5089   for (j = 0; j < il.count; j++) {
5090     r = get_pointer_64(p, offset, left, S, info);
5091     if (r == nullptr)
5092       return;
5093     memset(&i, '\0', sizeof(struct ivar64_t));
5094     if (left < sizeof(struct ivar64_t)) {
5095       memcpy(&i, r, left);
5096       outs() << "   (ivar_t entends past the end of the section)\n";
5097     } else
5098       memcpy(&i, r, sizeof(struct ivar64_t));
5099     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5100       swapStruct(i);
5101 
5102     outs() << "\t\t\t   offset ";
5103     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
5104                              info, n_value, i.offset);
5105     if (n_value != 0) {
5106       if (info->verbose && sym_name != nullptr)
5107         outs() << sym_name;
5108       else
5109         outs() << format("0x%" PRIx64, n_value);
5110       if (i.offset != 0)
5111         outs() << " + " << format("0x%" PRIx64, i.offset);
5112     } else
5113       outs() << format("0x%" PRIx64, i.offset);
5114     ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
5115     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5116       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5117       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5118         sys::swapByteOrder(ivar_offset);
5119       outs() << " " << ivar_offset << "\n";
5120     } else
5121       outs() << "\n";
5122 
5123     outs() << "\t\t\t     name ";
5124     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
5125                              n_value, i.name);
5126     if (n_value != 0) {
5127       if (info->verbose && sym_name != nullptr)
5128         outs() << sym_name;
5129       else
5130         outs() << format("0x%" PRIx64, n_value);
5131       if (i.name != 0)
5132         outs() << " + " << format("0x%" PRIx64, i.name);
5133     } else
5134       outs() << format("0x%" PRIx64, i.name);
5135     name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
5136     if (name != nullptr)
5137       outs() << format(" %.*s", left, name);
5138     outs() << "\n";
5139 
5140     outs() << "\t\t\t     type ";
5141     sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
5142                              n_value, i.name);
5143     name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
5144     if (n_value != 0) {
5145       if (info->verbose && sym_name != nullptr)
5146         outs() << sym_name;
5147       else
5148         outs() << format("0x%" PRIx64, n_value);
5149       if (i.type != 0)
5150         outs() << " + " << format("0x%" PRIx64, i.type);
5151     } else
5152       outs() << format("0x%" PRIx64, i.type);
5153     if (name != nullptr)
5154       outs() << format(" %.*s", left, name);
5155     outs() << "\n";
5156 
5157     outs() << "\t\t\talignment " << i.alignment << "\n";
5158     outs() << "\t\t\t     size " << i.size << "\n";
5159 
5160     p += sizeof(struct ivar64_t);
5161     offset += sizeof(struct ivar64_t);
5162   }
5163 }
5164 
print_ivar_list32_t(uint32_t p,struct DisassembleInfo * info)5165 static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
5166   struct ivar_list32_t il;
5167   struct ivar32_t i;
5168   const char *r;
5169   uint32_t offset, xoffset, left, j;
5170   SectionRef S, xS;
5171   const char *name, *ivar_offset_p;
5172   uint32_t ivar_offset;
5173 
5174   r = get_pointer_32(p, offset, left, S, info);
5175   if (r == nullptr)
5176     return;
5177   memset(&il, '\0', sizeof(struct ivar_list32_t));
5178   if (left < sizeof(struct ivar_list32_t)) {
5179     memcpy(&il, r, left);
5180     outs() << "   (ivar_list_t entends past the end of the section)\n";
5181   } else
5182     memcpy(&il, r, sizeof(struct ivar_list32_t));
5183   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5184     swapStruct(il);
5185   outs() << "                    entsize " << il.entsize << "\n";
5186   outs() << "                      count " << il.count << "\n";
5187 
5188   p += sizeof(struct ivar_list32_t);
5189   offset += sizeof(struct ivar_list32_t);
5190   for (j = 0; j < il.count; j++) {
5191     r = get_pointer_32(p, offset, left, S, info);
5192     if (r == nullptr)
5193       return;
5194     memset(&i, '\0', sizeof(struct ivar32_t));
5195     if (left < sizeof(struct ivar32_t)) {
5196       memcpy(&i, r, left);
5197       outs() << "   (ivar_t entends past the end of the section)\n";
5198     } else
5199       memcpy(&i, r, sizeof(struct ivar32_t));
5200     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5201       swapStruct(i);
5202 
5203     outs() << "\t\t\t   offset " << format("0x%" PRIx32, i.offset);
5204     ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
5205     if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
5206       memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
5207       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5208         sys::swapByteOrder(ivar_offset);
5209       outs() << " " << ivar_offset << "\n";
5210     } else
5211       outs() << "\n";
5212 
5213     outs() << "\t\t\t     name " << format("0x%" PRIx32, i.name);
5214     name = get_pointer_32(i.name, xoffset, left, xS, info);
5215     if (name != nullptr)
5216       outs() << format(" %.*s", left, name);
5217     outs() << "\n";
5218 
5219     outs() << "\t\t\t     type " << format("0x%" PRIx32, i.type);
5220     name = get_pointer_32(i.type, xoffset, left, xS, info);
5221     if (name != nullptr)
5222       outs() << format(" %.*s", left, name);
5223     outs() << "\n";
5224 
5225     outs() << "\t\t\talignment " << i.alignment << "\n";
5226     outs() << "\t\t\t     size " << i.size << "\n";
5227 
5228     p += sizeof(struct ivar32_t);
5229     offset += sizeof(struct ivar32_t);
5230   }
5231 }
5232 
print_objc_property_list64(uint64_t p,struct DisassembleInfo * info)5233 static void print_objc_property_list64(uint64_t p,
5234                                        struct DisassembleInfo *info) {
5235   struct objc_property_list64 opl;
5236   struct objc_property64 op;
5237   const char *r;
5238   uint32_t offset, xoffset, left, j;
5239   SectionRef S, xS;
5240   const char *name, *sym_name;
5241   uint64_t n_value;
5242 
5243   r = get_pointer_64(p, offset, left, S, info);
5244   if (r == nullptr)
5245     return;
5246   memset(&opl, '\0', sizeof(struct objc_property_list64));
5247   if (left < sizeof(struct objc_property_list64)) {
5248     memcpy(&opl, r, left);
5249     outs() << "   (objc_property_list entends past the end of the section)\n";
5250   } else
5251     memcpy(&opl, r, sizeof(struct objc_property_list64));
5252   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5253     swapStruct(opl);
5254   outs() << "                    entsize " << opl.entsize << "\n";
5255   outs() << "                      count " << opl.count << "\n";
5256 
5257   p += sizeof(struct objc_property_list64);
5258   offset += sizeof(struct objc_property_list64);
5259   for (j = 0; j < opl.count; j++) {
5260     r = get_pointer_64(p, offset, left, S, info);
5261     if (r == nullptr)
5262       return;
5263     memset(&op, '\0', sizeof(struct objc_property64));
5264     if (left < sizeof(struct objc_property64)) {
5265       memcpy(&op, r, left);
5266       outs() << "   (objc_property entends past the end of the section)\n";
5267     } else
5268       memcpy(&op, r, sizeof(struct objc_property64));
5269     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5270       swapStruct(op);
5271 
5272     outs() << "\t\t\t     name ";
5273     sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
5274                              info, n_value, op.name);
5275     if (n_value != 0) {
5276       if (info->verbose && sym_name != nullptr)
5277         outs() << sym_name;
5278       else
5279         outs() << format("0x%" PRIx64, n_value);
5280       if (op.name != 0)
5281         outs() << " + " << format("0x%" PRIx64, op.name);
5282     } else
5283       outs() << format("0x%" PRIx64, op.name);
5284     name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
5285     if (name != nullptr)
5286       outs() << format(" %.*s", left, name);
5287     outs() << "\n";
5288 
5289     outs() << "\t\t\tattributes ";
5290     sym_name =
5291         get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
5292                       info, n_value, op.attributes);
5293     if (n_value != 0) {
5294       if (info->verbose && sym_name != nullptr)
5295         outs() << sym_name;
5296       else
5297         outs() << format("0x%" PRIx64, n_value);
5298       if (op.attributes != 0)
5299         outs() << " + " << format("0x%" PRIx64, op.attributes);
5300     } else
5301       outs() << format("0x%" PRIx64, op.attributes);
5302     name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
5303     if (name != nullptr)
5304       outs() << format(" %.*s", left, name);
5305     outs() << "\n";
5306 
5307     p += sizeof(struct objc_property64);
5308     offset += sizeof(struct objc_property64);
5309   }
5310 }
5311 
print_objc_property_list32(uint32_t p,struct DisassembleInfo * info)5312 static void print_objc_property_list32(uint32_t p,
5313                                        struct DisassembleInfo *info) {
5314   struct objc_property_list32 opl;
5315   struct objc_property32 op;
5316   const char *r;
5317   uint32_t offset, xoffset, left, j;
5318   SectionRef S, xS;
5319   const char *name;
5320 
5321   r = get_pointer_32(p, offset, left, S, info);
5322   if (r == nullptr)
5323     return;
5324   memset(&opl, '\0', sizeof(struct objc_property_list32));
5325   if (left < sizeof(struct objc_property_list32)) {
5326     memcpy(&opl, r, left);
5327     outs() << "   (objc_property_list entends past the end of the section)\n";
5328   } else
5329     memcpy(&opl, r, sizeof(struct objc_property_list32));
5330   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5331     swapStruct(opl);
5332   outs() << "                    entsize " << opl.entsize << "\n";
5333   outs() << "                      count " << opl.count << "\n";
5334 
5335   p += sizeof(struct objc_property_list32);
5336   offset += sizeof(struct objc_property_list32);
5337   for (j = 0; j < opl.count; j++) {
5338     r = get_pointer_32(p, offset, left, S, info);
5339     if (r == nullptr)
5340       return;
5341     memset(&op, '\0', sizeof(struct objc_property32));
5342     if (left < sizeof(struct objc_property32)) {
5343       memcpy(&op, r, left);
5344       outs() << "   (objc_property entends past the end of the section)\n";
5345     } else
5346       memcpy(&op, r, sizeof(struct objc_property32));
5347     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5348       swapStruct(op);
5349 
5350     outs() << "\t\t\t     name " << format("0x%" PRIx32, op.name);
5351     name = get_pointer_32(op.name, xoffset, left, xS, info);
5352     if (name != nullptr)
5353       outs() << format(" %.*s", left, name);
5354     outs() << "\n";
5355 
5356     outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
5357     name = get_pointer_32(op.attributes, xoffset, left, xS, info);
5358     if (name != nullptr)
5359       outs() << format(" %.*s", left, name);
5360     outs() << "\n";
5361 
5362     p += sizeof(struct objc_property32);
5363     offset += sizeof(struct objc_property32);
5364   }
5365 }
5366 
print_class_ro64_t(uint64_t p,struct DisassembleInfo * info,bool & is_meta_class)5367 static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
5368                                bool &is_meta_class) {
5369   struct class_ro64_t cro;
5370   const char *r;
5371   uint32_t offset, xoffset, left;
5372   SectionRef S, xS;
5373   const char *name, *sym_name;
5374   uint64_t n_value;
5375 
5376   r = get_pointer_64(p, offset, left, S, info);
5377   if (r == nullptr || left < sizeof(struct class_ro64_t))
5378     return false;
5379   memcpy(&cro, r, sizeof(struct class_ro64_t));
5380   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5381     swapStruct(cro);
5382   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5383   if (cro.flags & RO_META)
5384     outs() << " RO_META";
5385   if (cro.flags & RO_ROOT)
5386     outs() << " RO_ROOT";
5387   if (cro.flags & RO_HAS_CXX_STRUCTORS)
5388     outs() << " RO_HAS_CXX_STRUCTORS";
5389   outs() << "\n";
5390   outs() << "            instanceStart " << cro.instanceStart << "\n";
5391   outs() << "             instanceSize " << cro.instanceSize << "\n";
5392   outs() << "                 reserved " << format("0x%" PRIx32, cro.reserved)
5393          << "\n";
5394   outs() << "               ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
5395          << "\n";
5396   print_layout_map64(cro.ivarLayout, info);
5397 
5398   outs() << "                     name ";
5399   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
5400                            info, n_value, cro.name);
5401   if (n_value != 0) {
5402     if (info->verbose && sym_name != nullptr)
5403       outs() << sym_name;
5404     else
5405       outs() << format("0x%" PRIx64, n_value);
5406     if (cro.name != 0)
5407       outs() << " + " << format("0x%" PRIx64, cro.name);
5408   } else
5409     outs() << format("0x%" PRIx64, cro.name);
5410   name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
5411   if (name != nullptr)
5412     outs() << format(" %.*s", left, name);
5413   outs() << "\n";
5414 
5415   outs() << "              baseMethods ";
5416   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
5417                            S, info, n_value, cro.baseMethods);
5418   if (n_value != 0) {
5419     if (info->verbose && sym_name != nullptr)
5420       outs() << sym_name;
5421     else
5422       outs() << format("0x%" PRIx64, n_value);
5423     if (cro.baseMethods != 0)
5424       outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
5425   } else
5426     outs() << format("0x%" PRIx64, cro.baseMethods);
5427   outs() << " (struct method_list_t *)\n";
5428   if (cro.baseMethods + n_value != 0)
5429     print_method_list64_t(cro.baseMethods + n_value, info, "");
5430 
5431   outs() << "            baseProtocols ";
5432   sym_name =
5433       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
5434                     info, n_value, cro.baseProtocols);
5435   if (n_value != 0) {
5436     if (info->verbose && sym_name != nullptr)
5437       outs() << sym_name;
5438     else
5439       outs() << format("0x%" PRIx64, n_value);
5440     if (cro.baseProtocols != 0)
5441       outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
5442   } else
5443     outs() << format("0x%" PRIx64, cro.baseProtocols);
5444   outs() << "\n";
5445   if (cro.baseProtocols + n_value != 0)
5446     print_protocol_list64_t(cro.baseProtocols + n_value, info);
5447 
5448   outs() << "                    ivars ";
5449   sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
5450                            info, n_value, cro.ivars);
5451   if (n_value != 0) {
5452     if (info->verbose && sym_name != nullptr)
5453       outs() << sym_name;
5454     else
5455       outs() << format("0x%" PRIx64, n_value);
5456     if (cro.ivars != 0)
5457       outs() << " + " << format("0x%" PRIx64, cro.ivars);
5458   } else
5459     outs() << format("0x%" PRIx64, cro.ivars);
5460   outs() << "\n";
5461   if (cro.ivars + n_value != 0)
5462     print_ivar_list64_t(cro.ivars + n_value, info);
5463 
5464   outs() << "           weakIvarLayout ";
5465   sym_name =
5466       get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
5467                     info, n_value, cro.weakIvarLayout);
5468   if (n_value != 0) {
5469     if (info->verbose && sym_name != nullptr)
5470       outs() << sym_name;
5471     else
5472       outs() << format("0x%" PRIx64, n_value);
5473     if (cro.weakIvarLayout != 0)
5474       outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
5475   } else
5476     outs() << format("0x%" PRIx64, cro.weakIvarLayout);
5477   outs() << "\n";
5478   print_layout_map64(cro.weakIvarLayout + n_value, info);
5479 
5480   outs() << "           baseProperties ";
5481   sym_name =
5482       get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
5483                     info, n_value, cro.baseProperties);
5484   if (n_value != 0) {
5485     if (info->verbose && sym_name != nullptr)
5486       outs() << sym_name;
5487     else
5488       outs() << format("0x%" PRIx64, n_value);
5489     if (cro.baseProperties != 0)
5490       outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
5491   } else
5492     outs() << format("0x%" PRIx64, cro.baseProperties);
5493   outs() << "\n";
5494   if (cro.baseProperties + n_value != 0)
5495     print_objc_property_list64(cro.baseProperties + n_value, info);
5496 
5497   is_meta_class = (cro.flags & RO_META) != 0;
5498   return true;
5499 }
5500 
print_class_ro32_t(uint32_t p,struct DisassembleInfo * info,bool & is_meta_class)5501 static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
5502                                bool &is_meta_class) {
5503   struct class_ro32_t cro;
5504   const char *r;
5505   uint32_t offset, xoffset, left;
5506   SectionRef S, xS;
5507   const char *name;
5508 
5509   r = get_pointer_32(p, offset, left, S, info);
5510   if (r == nullptr)
5511     return false;
5512   memset(&cro, '\0', sizeof(struct class_ro32_t));
5513   if (left < sizeof(struct class_ro32_t)) {
5514     memcpy(&cro, r, left);
5515     outs() << "   (class_ro_t entends past the end of the section)\n";
5516   } else
5517     memcpy(&cro, r, sizeof(struct class_ro32_t));
5518   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5519     swapStruct(cro);
5520   outs() << "                    flags " << format("0x%" PRIx32, cro.flags);
5521   if (cro.flags & RO_META)
5522     outs() << " RO_META";
5523   if (cro.flags & RO_ROOT)
5524     outs() << " RO_ROOT";
5525   if (cro.flags & RO_HAS_CXX_STRUCTORS)
5526     outs() << " RO_HAS_CXX_STRUCTORS";
5527   outs() << "\n";
5528   outs() << "            instanceStart " << cro.instanceStart << "\n";
5529   outs() << "             instanceSize " << cro.instanceSize << "\n";
5530   outs() << "               ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
5531          << "\n";
5532   print_layout_map32(cro.ivarLayout, info);
5533 
5534   outs() << "                     name " << format("0x%" PRIx32, cro.name);
5535   name = get_pointer_32(cro.name, xoffset, left, xS, info);
5536   if (name != nullptr)
5537     outs() << format(" %.*s", left, name);
5538   outs() << "\n";
5539 
5540   outs() << "              baseMethods "
5541          << format("0x%" PRIx32, cro.baseMethods)
5542          << " (struct method_list_t *)\n";
5543   if (cro.baseMethods != 0)
5544     print_method_list32_t(cro.baseMethods, info, "");
5545 
5546   outs() << "            baseProtocols "
5547          << format("0x%" PRIx32, cro.baseProtocols) << "\n";
5548   if (cro.baseProtocols != 0)
5549     print_protocol_list32_t(cro.baseProtocols, info);
5550   outs() << "                    ivars " << format("0x%" PRIx32, cro.ivars)
5551          << "\n";
5552   if (cro.ivars != 0)
5553     print_ivar_list32_t(cro.ivars, info);
5554   outs() << "           weakIvarLayout "
5555          << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
5556   print_layout_map32(cro.weakIvarLayout, info);
5557   outs() << "           baseProperties "
5558          << format("0x%" PRIx32, cro.baseProperties) << "\n";
5559   if (cro.baseProperties != 0)
5560     print_objc_property_list32(cro.baseProperties, info);
5561   is_meta_class = (cro.flags & RO_META) != 0;
5562   return true;
5563 }
5564 
print_class64_t(uint64_t p,struct DisassembleInfo * info)5565 static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
5566   struct class64_t c;
5567   const char *r;
5568   uint32_t offset, left;
5569   SectionRef S;
5570   const char *name;
5571   uint64_t isa_n_value, n_value;
5572 
5573   r = get_pointer_64(p, offset, left, S, info);
5574   if (r == nullptr || left < sizeof(struct class64_t))
5575     return;
5576   memcpy(&c, r, sizeof(struct class64_t));
5577   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5578     swapStruct(c);
5579 
5580   outs() << "           isa " << format("0x%" PRIx64, c.isa);
5581   name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
5582                        isa_n_value, c.isa);
5583   if (name != nullptr)
5584     outs() << " " << name;
5585   outs() << "\n";
5586 
5587   outs() << "    superclass " << format("0x%" PRIx64, c.superclass);
5588   name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
5589                        n_value, c.superclass);
5590   if (name != nullptr)
5591     outs() << " " << name;
5592   else {
5593     name = get_dyld_bind_info_symbolname(S.getAddress() +
5594              offset + offsetof(struct class64_t, superclass), info);
5595     if (name != nullptr)
5596       outs() << " " << name;
5597   }
5598   outs() << "\n";
5599 
5600   outs() << "         cache " << format("0x%" PRIx64, c.cache);
5601   name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
5602                        n_value, c.cache);
5603   if (name != nullptr)
5604     outs() << " " << name;
5605   outs() << "\n";
5606 
5607   outs() << "        vtable " << format("0x%" PRIx64, c.vtable);
5608   name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
5609                        n_value, c.vtable);
5610   if (name != nullptr)
5611     outs() << " " << name;
5612   outs() << "\n";
5613 
5614   name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
5615                        n_value, c.data);
5616   outs() << "          data ";
5617   if (n_value != 0) {
5618     if (info->verbose && name != nullptr)
5619       outs() << name;
5620     else
5621       outs() << format("0x%" PRIx64, n_value);
5622     if (c.data != 0)
5623       outs() << " + " << format("0x%" PRIx64, c.data);
5624   } else
5625     outs() << format("0x%" PRIx64, c.data);
5626   outs() << " (struct class_ro_t *)";
5627 
5628   // This is a Swift class if some of the low bits of the pointer are set.
5629   if ((c.data + n_value) & 0x7)
5630     outs() << " Swift class";
5631   outs() << "\n";
5632   bool is_meta_class;
5633   if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
5634     return;
5635 
5636   if (!is_meta_class &&
5637       c.isa + isa_n_value != p &&
5638       c.isa + isa_n_value != 0 &&
5639       info->depth < 100) {
5640       info->depth++;
5641       outs() << "Meta Class\n";
5642       print_class64_t(c.isa + isa_n_value, info);
5643   }
5644 }
5645 
print_class32_t(uint32_t p,struct DisassembleInfo * info)5646 static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
5647   struct class32_t c;
5648   const char *r;
5649   uint32_t offset, left;
5650   SectionRef S;
5651   const char *name;
5652 
5653   r = get_pointer_32(p, offset, left, S, info);
5654   if (r == nullptr)
5655     return;
5656   memset(&c, '\0', sizeof(struct class32_t));
5657   if (left < sizeof(struct class32_t)) {
5658     memcpy(&c, r, left);
5659     outs() << "   (class_t entends past the end of the section)\n";
5660   } else
5661     memcpy(&c, r, sizeof(struct class32_t));
5662   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5663     swapStruct(c);
5664 
5665   outs() << "           isa " << format("0x%" PRIx32, c.isa);
5666   name =
5667       get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
5668   if (name != nullptr)
5669     outs() << " " << name;
5670   outs() << "\n";
5671 
5672   outs() << "    superclass " << format("0x%" PRIx32, c.superclass);
5673   name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
5674                        c.superclass);
5675   if (name != nullptr)
5676     outs() << " " << name;
5677   outs() << "\n";
5678 
5679   outs() << "         cache " << format("0x%" PRIx32, c.cache);
5680   name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
5681                        c.cache);
5682   if (name != nullptr)
5683     outs() << " " << name;
5684   outs() << "\n";
5685 
5686   outs() << "        vtable " << format("0x%" PRIx32, c.vtable);
5687   name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
5688                        c.vtable);
5689   if (name != nullptr)
5690     outs() << " " << name;
5691   outs() << "\n";
5692 
5693   name =
5694       get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
5695   outs() << "          data " << format("0x%" PRIx32, c.data)
5696          << " (struct class_ro_t *)";
5697 
5698   // This is a Swift class if some of the low bits of the pointer are set.
5699   if (c.data & 0x3)
5700     outs() << " Swift class";
5701   outs() << "\n";
5702   bool is_meta_class;
5703   if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
5704     return;
5705 
5706   if (!is_meta_class) {
5707     outs() << "Meta Class\n";
5708     print_class32_t(c.isa, info);
5709   }
5710 }
5711 
print_objc_class_t(struct objc_class_t * objc_class,struct DisassembleInfo * info)5712 static void print_objc_class_t(struct objc_class_t *objc_class,
5713                                struct DisassembleInfo *info) {
5714   uint32_t offset, left, xleft;
5715   const char *name, *p, *ivar_list;
5716   SectionRef S;
5717   int32_t i;
5718   struct objc_ivar_list_t objc_ivar_list;
5719   struct objc_ivar_t ivar;
5720 
5721   outs() << "\t\t      isa " << format("0x%08" PRIx32, objc_class->isa);
5722   if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
5723     name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
5724     if (name != nullptr)
5725       outs() << format(" %.*s", left, name);
5726     else
5727       outs() << " (not in an __OBJC section)";
5728   }
5729   outs() << "\n";
5730 
5731   outs() << "\t      super_class "
5732          << format("0x%08" PRIx32, objc_class->super_class);
5733   if (info->verbose) {
5734     name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
5735     if (name != nullptr)
5736       outs() << format(" %.*s", left, name);
5737     else
5738       outs() << " (not in an __OBJC section)";
5739   }
5740   outs() << "\n";
5741 
5742   outs() << "\t\t     name " << format("0x%08" PRIx32, objc_class->name);
5743   if (info->verbose) {
5744     name = get_pointer_32(objc_class->name, offset, left, S, info, true);
5745     if (name != nullptr)
5746       outs() << format(" %.*s", left, name);
5747     else
5748       outs() << " (not in an __OBJC section)";
5749   }
5750   outs() << "\n";
5751 
5752   outs() << "\t\t  version " << format("0x%08" PRIx32, objc_class->version)
5753          << "\n";
5754 
5755   outs() << "\t\t     info " << format("0x%08" PRIx32, objc_class->info);
5756   if (info->verbose) {
5757     if (CLS_GETINFO(objc_class, CLS_CLASS))
5758       outs() << " CLS_CLASS";
5759     else if (CLS_GETINFO(objc_class, CLS_META))
5760       outs() << " CLS_META";
5761   }
5762   outs() << "\n";
5763 
5764   outs() << "\t    instance_size "
5765          << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
5766 
5767   p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
5768   outs() << "\t\t    ivars " << format("0x%08" PRIx32, objc_class->ivars);
5769   if (p != nullptr) {
5770     if (left > sizeof(struct objc_ivar_list_t)) {
5771       outs() << "\n";
5772       memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
5773     } else {
5774       outs() << " (entends past the end of the section)\n";
5775       memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
5776       memcpy(&objc_ivar_list, p, left);
5777     }
5778     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5779       swapStruct(objc_ivar_list);
5780     outs() << "\t\t       ivar_count " << objc_ivar_list.ivar_count << "\n";
5781     ivar_list = p + sizeof(struct objc_ivar_list_t);
5782     for (i = 0; i < objc_ivar_list.ivar_count; i++) {
5783       if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
5784         outs() << "\t\t remaining ivar's extend past the of the section\n";
5785         break;
5786       }
5787       memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
5788              sizeof(struct objc_ivar_t));
5789       if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5790         swapStruct(ivar);
5791 
5792       outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
5793       if (info->verbose) {
5794         name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
5795         if (name != nullptr)
5796           outs() << format(" %.*s", xleft, name);
5797         else
5798           outs() << " (not in an __OBJC section)";
5799       }
5800       outs() << "\n";
5801 
5802       outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
5803       if (info->verbose) {
5804         name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
5805         if (name != nullptr)
5806           outs() << format(" %.*s", xleft, name);
5807         else
5808           outs() << " (not in an __OBJC section)";
5809       }
5810       outs() << "\n";
5811 
5812       outs() << "\t\t      ivar_offset "
5813              << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
5814     }
5815   } else {
5816     outs() << " (not in an __OBJC section)\n";
5817   }
5818 
5819   outs() << "\t\t  methods " << format("0x%08" PRIx32, objc_class->methodLists);
5820   if (print_method_list(objc_class->methodLists, info))
5821     outs() << " (not in an __OBJC section)\n";
5822 
5823   outs() << "\t\t    cache " << format("0x%08" PRIx32, objc_class->cache)
5824          << "\n";
5825 
5826   outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
5827   if (print_protocol_list(objc_class->protocols, 16, info))
5828     outs() << " (not in an __OBJC section)\n";
5829 }
5830 
print_objc_objc_category_t(struct objc_category_t * objc_category,struct DisassembleInfo * info)5831 static void print_objc_objc_category_t(struct objc_category_t *objc_category,
5832                                        struct DisassembleInfo *info) {
5833   uint32_t offset, left;
5834   const char *name;
5835   SectionRef S;
5836 
5837   outs() << "\t       category name "
5838          << format("0x%08" PRIx32, objc_category->category_name);
5839   if (info->verbose) {
5840     name = get_pointer_32(objc_category->category_name, offset, left, S, info,
5841                           true);
5842     if (name != nullptr)
5843       outs() << format(" %.*s", left, name);
5844     else
5845       outs() << " (not in an __OBJC section)";
5846   }
5847   outs() << "\n";
5848 
5849   outs() << "\t\t  class name "
5850          << format("0x%08" PRIx32, objc_category->class_name);
5851   if (info->verbose) {
5852     name =
5853         get_pointer_32(objc_category->class_name, offset, left, S, info, true);
5854     if (name != nullptr)
5855       outs() << format(" %.*s", left, name);
5856     else
5857       outs() << " (not in an __OBJC section)";
5858   }
5859   outs() << "\n";
5860 
5861   outs() << "\t    instance methods "
5862          << format("0x%08" PRIx32, objc_category->instance_methods);
5863   if (print_method_list(objc_category->instance_methods, info))
5864     outs() << " (not in an __OBJC section)\n";
5865 
5866   outs() << "\t       class methods "
5867          << format("0x%08" PRIx32, objc_category->class_methods);
5868   if (print_method_list(objc_category->class_methods, info))
5869     outs() << " (not in an __OBJC section)\n";
5870 }
5871 
print_category64_t(uint64_t p,struct DisassembleInfo * info)5872 static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
5873   struct category64_t c;
5874   const char *r;
5875   uint32_t offset, xoffset, left;
5876   SectionRef S, xS;
5877   const char *name, *sym_name;
5878   uint64_t n_value;
5879 
5880   r = get_pointer_64(p, offset, left, S, info);
5881   if (r == nullptr)
5882     return;
5883   memset(&c, '\0', sizeof(struct category64_t));
5884   if (left < sizeof(struct category64_t)) {
5885     memcpy(&c, r, left);
5886     outs() << "   (category_t entends past the end of the section)\n";
5887   } else
5888     memcpy(&c, r, sizeof(struct category64_t));
5889   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
5890     swapStruct(c);
5891 
5892   outs() << "              name ";
5893   sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
5894                            info, n_value, c.name);
5895   if (n_value != 0) {
5896     if (info->verbose && sym_name != nullptr)
5897       outs() << sym_name;
5898     else
5899       outs() << format("0x%" PRIx64, n_value);
5900     if (c.name != 0)
5901       outs() << " + " << format("0x%" PRIx64, c.name);
5902   } else
5903     outs() << format("0x%" PRIx64, c.name);
5904   name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
5905   if (name != nullptr)
5906     outs() << format(" %.*s", left, name);
5907   outs() << "\n";
5908 
5909   outs() << "               cls ";
5910   sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
5911                            n_value, c.cls);
5912   if (n_value != 0) {
5913     if (info->verbose && sym_name != nullptr)
5914       outs() << sym_name;
5915     else
5916       outs() << format("0x%" PRIx64, n_value);
5917     if (c.cls != 0)
5918       outs() << " + " << format("0x%" PRIx64, c.cls);
5919   } else
5920     outs() << format("0x%" PRIx64, c.cls);
5921   outs() << "\n";
5922   if (c.cls + n_value != 0)
5923     print_class64_t(c.cls + n_value, info);
5924 
5925   outs() << "   instanceMethods ";
5926   sym_name =
5927       get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
5928                     info, n_value, c.instanceMethods);
5929   if (n_value != 0) {
5930     if (info->verbose && sym_name != nullptr)
5931       outs() << sym_name;
5932     else
5933       outs() << format("0x%" PRIx64, n_value);
5934     if (c.instanceMethods != 0)
5935       outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
5936   } else
5937     outs() << format("0x%" PRIx64, c.instanceMethods);
5938   outs() << "\n";
5939   if (c.instanceMethods + n_value != 0)
5940     print_method_list64_t(c.instanceMethods + n_value, info, "");
5941 
5942   outs() << "      classMethods ";
5943   sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
5944                            S, info, n_value, c.classMethods);
5945   if (n_value != 0) {
5946     if (info->verbose && sym_name != nullptr)
5947       outs() << sym_name;
5948     else
5949       outs() << format("0x%" PRIx64, n_value);
5950     if (c.classMethods != 0)
5951       outs() << " + " << format("0x%" PRIx64, c.classMethods);
5952   } else
5953     outs() << format("0x%" PRIx64, c.classMethods);
5954   outs() << "\n";
5955   if (c.classMethods + n_value != 0)
5956     print_method_list64_t(c.classMethods + n_value, info, "");
5957 
5958   outs() << "         protocols ";
5959   sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
5960                            info, n_value, c.protocols);
5961   if (n_value != 0) {
5962     if (info->verbose && sym_name != nullptr)
5963       outs() << sym_name;
5964     else
5965       outs() << format("0x%" PRIx64, n_value);
5966     if (c.protocols != 0)
5967       outs() << " + " << format("0x%" PRIx64, c.protocols);
5968   } else
5969     outs() << format("0x%" PRIx64, c.protocols);
5970   outs() << "\n";
5971   if (c.protocols + n_value != 0)
5972     print_protocol_list64_t(c.protocols + n_value, info);
5973 
5974   outs() << "instanceProperties ";
5975   sym_name =
5976       get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
5977                     S, info, n_value, c.instanceProperties);
5978   if (n_value != 0) {
5979     if (info->verbose && sym_name != nullptr)
5980       outs() << sym_name;
5981     else
5982       outs() << format("0x%" PRIx64, n_value);
5983     if (c.instanceProperties != 0)
5984       outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
5985   } else
5986     outs() << format("0x%" PRIx64, c.instanceProperties);
5987   outs() << "\n";
5988   if (c.instanceProperties + n_value != 0)
5989     print_objc_property_list64(c.instanceProperties + n_value, info);
5990 }
5991 
print_category32_t(uint32_t p,struct DisassembleInfo * info)5992 static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
5993   struct category32_t c;
5994   const char *r;
5995   uint32_t offset, left;
5996   SectionRef S, xS;
5997   const char *name;
5998 
5999   r = get_pointer_32(p, offset, left, S, info);
6000   if (r == nullptr)
6001     return;
6002   memset(&c, '\0', sizeof(struct category32_t));
6003   if (left < sizeof(struct category32_t)) {
6004     memcpy(&c, r, left);
6005     outs() << "   (category_t entends past the end of the section)\n";
6006   } else
6007     memcpy(&c, r, sizeof(struct category32_t));
6008   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6009     swapStruct(c);
6010 
6011   outs() << "              name " << format("0x%" PRIx32, c.name);
6012   name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
6013                        c.name);
6014   if (name)
6015     outs() << " " << name;
6016   outs() << "\n";
6017 
6018   outs() << "               cls " << format("0x%" PRIx32, c.cls) << "\n";
6019   if (c.cls != 0)
6020     print_class32_t(c.cls, info);
6021   outs() << "   instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
6022          << "\n";
6023   if (c.instanceMethods != 0)
6024     print_method_list32_t(c.instanceMethods, info, "");
6025   outs() << "      classMethods " << format("0x%" PRIx32, c.classMethods)
6026          << "\n";
6027   if (c.classMethods != 0)
6028     print_method_list32_t(c.classMethods, info, "");
6029   outs() << "         protocols " << format("0x%" PRIx32, c.protocols) << "\n";
6030   if (c.protocols != 0)
6031     print_protocol_list32_t(c.protocols, info);
6032   outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
6033          << "\n";
6034   if (c.instanceProperties != 0)
6035     print_objc_property_list32(c.instanceProperties, info);
6036 }
6037 
print_message_refs64(SectionRef S,struct DisassembleInfo * info)6038 static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
6039   uint32_t i, left, offset, xoffset;
6040   uint64_t p, n_value;
6041   struct message_ref64 mr;
6042   const char *name, *sym_name;
6043   const char *r;
6044   SectionRef xS;
6045 
6046   if (S == SectionRef())
6047     return;
6048 
6049   StringRef SectName;
6050   Expected<StringRef> SecNameOrErr = S.getName();
6051   if (SecNameOrErr)
6052     SectName = *SecNameOrErr;
6053   else
6054     consumeError(SecNameOrErr.takeError());
6055 
6056   DataRefImpl Ref = S.getRawDataRefImpl();
6057   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6058   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6059   offset = 0;
6060   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6061     p = S.getAddress() + i;
6062     r = get_pointer_64(p, offset, left, S, info);
6063     if (r == nullptr)
6064       return;
6065     memset(&mr, '\0', sizeof(struct message_ref64));
6066     if (left < sizeof(struct message_ref64)) {
6067       memcpy(&mr, r, left);
6068       outs() << "   (message_ref entends past the end of the section)\n";
6069     } else
6070       memcpy(&mr, r, sizeof(struct message_ref64));
6071     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6072       swapStruct(mr);
6073 
6074     outs() << "  imp ";
6075     name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
6076                          n_value, mr.imp);
6077     if (n_value != 0) {
6078       outs() << format("0x%" PRIx64, n_value) << " ";
6079       if (mr.imp != 0)
6080         outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
6081     } else
6082       outs() << format("0x%" PRIx64, mr.imp) << " ";
6083     if (name != nullptr)
6084       outs() << " " << name;
6085     outs() << "\n";
6086 
6087     outs() << "  sel ";
6088     sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
6089                              info, n_value, mr.sel);
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 (mr.sel != 0)
6096         outs() << " + " << format("0x%" PRIx64, mr.sel);
6097     } else
6098       outs() << format("0x%" PRIx64, mr.sel);
6099     name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
6100     if (name != nullptr)
6101       outs() << format(" %.*s", left, name);
6102     outs() << "\n";
6103 
6104     offset += sizeof(struct message_ref64);
6105   }
6106 }
6107 
print_message_refs32(SectionRef S,struct DisassembleInfo * info)6108 static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
6109   uint32_t i, left, offset, xoffset, p;
6110   struct message_ref32 mr;
6111   const char *name, *r;
6112   SectionRef xS;
6113 
6114   if (S == SectionRef())
6115     return;
6116 
6117   StringRef SectName;
6118   Expected<StringRef> SecNameOrErr = S.getName();
6119   if (SecNameOrErr)
6120     SectName = *SecNameOrErr;
6121   else
6122     consumeError(SecNameOrErr.takeError());
6123 
6124   DataRefImpl Ref = S.getRawDataRefImpl();
6125   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6126   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6127   offset = 0;
6128   for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
6129     p = S.getAddress() + i;
6130     r = get_pointer_32(p, offset, left, S, info);
6131     if (r == nullptr)
6132       return;
6133     memset(&mr, '\0', sizeof(struct message_ref32));
6134     if (left < sizeof(struct message_ref32)) {
6135       memcpy(&mr, r, left);
6136       outs() << "   (message_ref entends past the end of the section)\n";
6137     } else
6138       memcpy(&mr, r, sizeof(struct message_ref32));
6139     if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6140       swapStruct(mr);
6141 
6142     outs() << "  imp " << format("0x%" PRIx32, mr.imp);
6143     name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
6144                          mr.imp);
6145     if (name != nullptr)
6146       outs() << " " << name;
6147     outs() << "\n";
6148 
6149     outs() << "  sel " << format("0x%" PRIx32, mr.sel);
6150     name = get_pointer_32(mr.sel, xoffset, left, xS, info);
6151     if (name != nullptr)
6152       outs() << " " << name;
6153     outs() << "\n";
6154 
6155     offset += sizeof(struct message_ref32);
6156   }
6157 }
6158 
print_image_info64(SectionRef S,struct DisassembleInfo * info)6159 static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
6160   uint32_t left, offset, swift_version;
6161   uint64_t p;
6162   struct objc_image_info64 o;
6163   const char *r;
6164 
6165   if (S == SectionRef())
6166     return;
6167 
6168   StringRef SectName;
6169   Expected<StringRef> SecNameOrErr = S.getName();
6170   if (SecNameOrErr)
6171     SectName = *SecNameOrErr;
6172   else
6173     consumeError(SecNameOrErr.takeError());
6174 
6175   DataRefImpl Ref = S.getRawDataRefImpl();
6176   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6177   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6178   p = S.getAddress();
6179   r = get_pointer_64(p, offset, left, S, info);
6180   if (r == nullptr)
6181     return;
6182   memset(&o, '\0', sizeof(struct objc_image_info64));
6183   if (left < sizeof(struct objc_image_info64)) {
6184     memcpy(&o, r, left);
6185     outs() << "   (objc_image_info entends past the end of the section)\n";
6186   } else
6187     memcpy(&o, r, sizeof(struct objc_image_info64));
6188   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6189     swapStruct(o);
6190   outs() << "  version " << o.version << "\n";
6191   outs() << "    flags " << format("0x%" PRIx32, o.flags);
6192   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6193     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6194   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6195     outs() << " OBJC_IMAGE_SUPPORTS_GC";
6196   if (o.flags & OBJC_IMAGE_IS_SIMULATED)
6197     outs() << " OBJC_IMAGE_IS_SIMULATED";
6198   if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES)
6199     outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";
6200   swift_version = (o.flags >> 8) & 0xff;
6201   if (swift_version != 0) {
6202     if (swift_version == 1)
6203       outs() << " Swift 1.0";
6204     else if (swift_version == 2)
6205       outs() << " Swift 1.1";
6206     else if(swift_version == 3)
6207       outs() << " Swift 2.0";
6208     else if(swift_version == 4)
6209       outs() << " Swift 3.0";
6210     else if(swift_version == 5)
6211       outs() << " Swift 4.0";
6212     else if(swift_version == 6)
6213       outs() << " Swift 4.1/Swift 4.2";
6214     else if(swift_version == 7)
6215       outs() << " Swift 5 or later";
6216     else
6217       outs() << " unknown future Swift version (" << swift_version << ")";
6218   }
6219   outs() << "\n";
6220 }
6221 
print_image_info32(SectionRef S,struct DisassembleInfo * info)6222 static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
6223   uint32_t left, offset, swift_version, p;
6224   struct objc_image_info32 o;
6225   const char *r;
6226 
6227   if (S == SectionRef())
6228     return;
6229 
6230   StringRef SectName;
6231   Expected<StringRef> SecNameOrErr = S.getName();
6232   if (SecNameOrErr)
6233     SectName = *SecNameOrErr;
6234   else
6235     consumeError(SecNameOrErr.takeError());
6236 
6237   DataRefImpl Ref = S.getRawDataRefImpl();
6238   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6239   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6240   p = S.getAddress();
6241   r = get_pointer_32(p, offset, left, S, info);
6242   if (r == nullptr)
6243     return;
6244   memset(&o, '\0', sizeof(struct objc_image_info32));
6245   if (left < sizeof(struct objc_image_info32)) {
6246     memcpy(&o, r, left);
6247     outs() << "   (objc_image_info entends past the end of the section)\n";
6248   } else
6249     memcpy(&o, r, sizeof(struct objc_image_info32));
6250   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6251     swapStruct(o);
6252   outs() << "  version " << o.version << "\n";
6253   outs() << "    flags " << format("0x%" PRIx32, o.flags);
6254   if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
6255     outs() << " OBJC_IMAGE_IS_REPLACEMENT";
6256   if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
6257     outs() << " OBJC_IMAGE_SUPPORTS_GC";
6258   swift_version = (o.flags >> 8) & 0xff;
6259   if (swift_version != 0) {
6260     if (swift_version == 1)
6261       outs() << " Swift 1.0";
6262     else if (swift_version == 2)
6263       outs() << " Swift 1.1";
6264     else if(swift_version == 3)
6265       outs() << " Swift 2.0";
6266     else if(swift_version == 4)
6267       outs() << " Swift 3.0";
6268     else if(swift_version == 5)
6269       outs() << " Swift 4.0";
6270     else if(swift_version == 6)
6271       outs() << " Swift 4.1/Swift 4.2";
6272     else if(swift_version == 7)
6273       outs() << " Swift 5 or later";
6274     else
6275       outs() << " unknown future Swift version (" << swift_version << ")";
6276   }
6277   outs() << "\n";
6278 }
6279 
print_image_info(SectionRef S,struct DisassembleInfo * info)6280 static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
6281   uint32_t left, offset, p;
6282   struct imageInfo_t o;
6283   const char *r;
6284 
6285   StringRef SectName;
6286   Expected<StringRef> SecNameOrErr = S.getName();
6287   if (SecNameOrErr)
6288     SectName = *SecNameOrErr;
6289   else
6290     consumeError(SecNameOrErr.takeError());
6291 
6292   DataRefImpl Ref = S.getRawDataRefImpl();
6293   StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
6294   outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
6295   p = S.getAddress();
6296   r = get_pointer_32(p, offset, left, S, info);
6297   if (r == nullptr)
6298     return;
6299   memset(&o, '\0', sizeof(struct imageInfo_t));
6300   if (left < sizeof(struct imageInfo_t)) {
6301     memcpy(&o, r, left);
6302     outs() << " (imageInfo entends past the end of the section)\n";
6303   } else
6304     memcpy(&o, r, sizeof(struct imageInfo_t));
6305   if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
6306     swapStruct(o);
6307   outs() << "  version " << o.version << "\n";
6308   outs() << "    flags " << format("0x%" PRIx32, o.flags);
6309   if (o.flags & 0x1)
6310     outs() << "  F&C";
6311   if (o.flags & 0x2)
6312     outs() << " GC";
6313   if (o.flags & 0x4)
6314     outs() << " GC-only";
6315   else
6316     outs() << " RR";
6317   outs() << "\n";
6318 }
6319 
printObjc2_64bit_MetaData(MachOObjectFile * O,bool verbose)6320 static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
6321   SymbolAddressMap AddrMap;
6322   if (verbose)
6323     CreateSymbolAddressMap(O, &AddrMap);
6324 
6325   std::vector<SectionRef> Sections;
6326   append_range(Sections, O->sections());
6327 
6328   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6329 
6330   SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6331   if (CL == SectionRef())
6332     CL = get_section(O, "__DATA", "__objc_classlist");
6333   if (CL == SectionRef())
6334     CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6335   if (CL == SectionRef())
6336     CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6337   info.S = CL;
6338   walk_pointer_list_64("class", CL, O, &info, print_class64_t);
6339 
6340   SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6341   if (CR == SectionRef())
6342     CR = get_section(O, "__DATA", "__objc_classrefs");
6343   if (CR == SectionRef())
6344     CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6345   if (CR == SectionRef())
6346     CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6347   info.S = CR;
6348   walk_pointer_list_64("class refs", CR, O, &info, nullptr);
6349 
6350   SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6351   if (SR == SectionRef())
6352     SR = get_section(O, "__DATA", "__objc_superrefs");
6353   if (SR == SectionRef())
6354     SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6355   if (SR == SectionRef())
6356     SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6357   info.S = SR;
6358   walk_pointer_list_64("super refs", SR, O, &info, nullptr);
6359 
6360   SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6361   if (CA == SectionRef())
6362     CA = get_section(O, "__DATA", "__objc_catlist");
6363   if (CA == SectionRef())
6364     CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6365   if (CA == SectionRef())
6366     CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6367   info.S = CA;
6368   walk_pointer_list_64("category", CA, O, &info, print_category64_t);
6369 
6370   SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6371   if (PL == SectionRef())
6372     PL = get_section(O, "__DATA", "__objc_protolist");
6373   if (PL == SectionRef())
6374     PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6375   if (PL == SectionRef())
6376     PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6377   info.S = PL;
6378   walk_pointer_list_64("protocol", PL, O, &info, nullptr);
6379 
6380   SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6381   if (MR == SectionRef())
6382     MR = get_section(O, "__DATA", "__objc_msgrefs");
6383   if (MR == SectionRef())
6384     MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6385   if (MR == SectionRef())
6386     MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6387   info.S = MR;
6388   print_message_refs64(MR, &info);
6389 
6390   SectionRef II = get_section(O, "__OBJC2", "__image_info");
6391   if (II == SectionRef())
6392     II = get_section(O, "__DATA", "__objc_imageinfo");
6393   if (II == SectionRef())
6394     II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6395   if (II == SectionRef())
6396     II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6397   info.S = II;
6398   print_image_info64(II, &info);
6399 }
6400 
printObjc2_32bit_MetaData(MachOObjectFile * O,bool verbose)6401 static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6402   SymbolAddressMap AddrMap;
6403   if (verbose)
6404     CreateSymbolAddressMap(O, &AddrMap);
6405 
6406   std::vector<SectionRef> Sections;
6407   append_range(Sections, O->sections());
6408 
6409   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6410 
6411   SectionRef CL = get_section(O, "__OBJC2", "__class_list");
6412   if (CL == SectionRef())
6413     CL = get_section(O, "__DATA", "__objc_classlist");
6414   if (CL == SectionRef())
6415     CL = get_section(O, "__DATA_CONST", "__objc_classlist");
6416   if (CL == SectionRef())
6417     CL = get_section(O, "__DATA_DIRTY", "__objc_classlist");
6418   info.S = CL;
6419   walk_pointer_list_32("class", CL, O, &info, print_class32_t);
6420 
6421   SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
6422   if (CR == SectionRef())
6423     CR = get_section(O, "__DATA", "__objc_classrefs");
6424   if (CR == SectionRef())
6425     CR = get_section(O, "__DATA_CONST", "__objc_classrefs");
6426   if (CR == SectionRef())
6427     CR = get_section(O, "__DATA_DIRTY", "__objc_classrefs");
6428   info.S = CR;
6429   walk_pointer_list_32("class refs", CR, O, &info, nullptr);
6430 
6431   SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
6432   if (SR == SectionRef())
6433     SR = get_section(O, "__DATA", "__objc_superrefs");
6434   if (SR == SectionRef())
6435     SR = get_section(O, "__DATA_CONST", "__objc_superrefs");
6436   if (SR == SectionRef())
6437     SR = get_section(O, "__DATA_DIRTY", "__objc_superrefs");
6438   info.S = SR;
6439   walk_pointer_list_32("super refs", SR, O, &info, nullptr);
6440 
6441   SectionRef CA = get_section(O, "__OBJC2", "__category_list");
6442   if (CA == SectionRef())
6443     CA = get_section(O, "__DATA", "__objc_catlist");
6444   if (CA == SectionRef())
6445     CA = get_section(O, "__DATA_CONST", "__objc_catlist");
6446   if (CA == SectionRef())
6447     CA = get_section(O, "__DATA_DIRTY", "__objc_catlist");
6448   info.S = CA;
6449   walk_pointer_list_32("category", CA, O, &info, print_category32_t);
6450 
6451   SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
6452   if (PL == SectionRef())
6453     PL = get_section(O, "__DATA", "__objc_protolist");
6454   if (PL == SectionRef())
6455     PL = get_section(O, "__DATA_CONST", "__objc_protolist");
6456   if (PL == SectionRef())
6457     PL = get_section(O, "__DATA_DIRTY", "__objc_protolist");
6458   info.S = PL;
6459   walk_pointer_list_32("protocol", PL, O, &info, nullptr);
6460 
6461   SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
6462   if (MR == SectionRef())
6463     MR = get_section(O, "__DATA", "__objc_msgrefs");
6464   if (MR == SectionRef())
6465     MR = get_section(O, "__DATA_CONST", "__objc_msgrefs");
6466   if (MR == SectionRef())
6467     MR = get_section(O, "__DATA_DIRTY", "__objc_msgrefs");
6468   info.S = MR;
6469   print_message_refs32(MR, &info);
6470 
6471   SectionRef II = get_section(O, "__OBJC2", "__image_info");
6472   if (II == SectionRef())
6473     II = get_section(O, "__DATA", "__objc_imageinfo");
6474   if (II == SectionRef())
6475     II = get_section(O, "__DATA_CONST", "__objc_imageinfo");
6476   if (II == SectionRef())
6477     II = get_section(O, "__DATA_DIRTY", "__objc_imageinfo");
6478   info.S = II;
6479   print_image_info32(II, &info);
6480 }
6481 
printObjc1_32bit_MetaData(MachOObjectFile * O,bool verbose)6482 static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
6483   uint32_t i, j, p, offset, xoffset, left, defs_left, def;
6484   const char *r, *name, *defs;
6485   struct objc_module_t module;
6486   SectionRef S, xS;
6487   struct objc_symtab_t symtab;
6488   struct objc_class_t objc_class;
6489   struct objc_category_t objc_category;
6490 
6491   outs() << "Objective-C segment\n";
6492   S = get_section(O, "__OBJC", "__module_info");
6493   if (S == SectionRef())
6494     return false;
6495 
6496   SymbolAddressMap AddrMap;
6497   if (verbose)
6498     CreateSymbolAddressMap(O, &AddrMap);
6499 
6500   std::vector<SectionRef> Sections;
6501   append_range(Sections, O->sections());
6502 
6503   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
6504 
6505   for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
6506     p = S.getAddress() + i;
6507     r = get_pointer_32(p, offset, left, S, &info, true);
6508     if (r == nullptr)
6509       return true;
6510     memset(&module, '\0', sizeof(struct objc_module_t));
6511     if (left < sizeof(struct objc_module_t)) {
6512       memcpy(&module, r, left);
6513       outs() << "   (module extends past end of __module_info section)\n";
6514     } else
6515       memcpy(&module, r, sizeof(struct objc_module_t));
6516     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6517       swapStruct(module);
6518 
6519     outs() << "Module " << format("0x%" PRIx32, p) << "\n";
6520     outs() << "    version " << module.version << "\n";
6521     outs() << "       size " << module.size << "\n";
6522     outs() << "       name ";
6523     name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
6524     if (name != nullptr)
6525       outs() << format("%.*s", left, name);
6526     else
6527       outs() << format("0x%08" PRIx32, module.name)
6528              << "(not in an __OBJC section)";
6529     outs() << "\n";
6530 
6531     r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
6532     if (module.symtab == 0 || r == nullptr) {
6533       outs() << "     symtab " << format("0x%08" PRIx32, module.symtab)
6534              << " (not in an __OBJC section)\n";
6535       continue;
6536     }
6537     outs() << "     symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
6538     memset(&symtab, '\0', sizeof(struct objc_symtab_t));
6539     defs_left = 0;
6540     defs = nullptr;
6541     if (left < sizeof(struct objc_symtab_t)) {
6542       memcpy(&symtab, r, left);
6543       outs() << "\tsymtab extends past end of an __OBJC section)\n";
6544     } else {
6545       memcpy(&symtab, r, sizeof(struct objc_symtab_t));
6546       if (left > sizeof(struct objc_symtab_t)) {
6547         defs_left = left - sizeof(struct objc_symtab_t);
6548         defs = r + sizeof(struct objc_symtab_t);
6549       }
6550     }
6551     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6552       swapStruct(symtab);
6553 
6554     outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
6555     r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
6556     outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
6557     if (r == nullptr)
6558       outs() << " (not in an __OBJC section)";
6559     outs() << "\n";
6560     outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
6561     outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
6562     if (symtab.cls_def_cnt > 0)
6563       outs() << "\tClass Definitions\n";
6564     for (j = 0; j < symtab.cls_def_cnt; j++) {
6565       if ((j + 1) * sizeof(uint32_t) > defs_left) {
6566         outs() << "\t(remaining class defs entries entends past the end of the "
6567                << "section)\n";
6568         break;
6569       }
6570       memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
6571       if (O->isLittleEndian() != sys::IsLittleEndianHost)
6572         sys::swapByteOrder(def);
6573 
6574       r = get_pointer_32(def, xoffset, left, xS, &info, true);
6575       outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
6576       if (r != nullptr) {
6577         if (left > sizeof(struct objc_class_t)) {
6578           outs() << "\n";
6579           memcpy(&objc_class, r, sizeof(struct objc_class_t));
6580         } else {
6581           outs() << " (entends past the end of the section)\n";
6582           memset(&objc_class, '\0', sizeof(struct objc_class_t));
6583           memcpy(&objc_class, r, left);
6584         }
6585         if (O->isLittleEndian() != sys::IsLittleEndianHost)
6586           swapStruct(objc_class);
6587         print_objc_class_t(&objc_class, &info);
6588       } else {
6589         outs() << "(not in an __OBJC section)\n";
6590       }
6591 
6592       if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
6593         outs() << "\tMeta Class";
6594         r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
6595         if (r != nullptr) {
6596           if (left > sizeof(struct objc_class_t)) {
6597             outs() << "\n";
6598             memcpy(&objc_class, r, sizeof(struct objc_class_t));
6599           } else {
6600             outs() << " (entends past the end of the section)\n";
6601             memset(&objc_class, '\0', sizeof(struct objc_class_t));
6602             memcpy(&objc_class, r, left);
6603           }
6604           if (O->isLittleEndian() != sys::IsLittleEndianHost)
6605             swapStruct(objc_class);
6606           print_objc_class_t(&objc_class, &info);
6607         } else {
6608           outs() << "(not in an __OBJC section)\n";
6609         }
6610       }
6611     }
6612     if (symtab.cat_def_cnt > 0)
6613       outs() << "\tCategory Definitions\n";
6614     for (j = 0; j < symtab.cat_def_cnt; j++) {
6615       if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
6616         outs() << "\t(remaining category defs entries entends past the end of "
6617                << "the section)\n";
6618         break;
6619       }
6620       memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
6621              sizeof(uint32_t));
6622       if (O->isLittleEndian() != sys::IsLittleEndianHost)
6623         sys::swapByteOrder(def);
6624 
6625       r = get_pointer_32(def, xoffset, left, xS, &info, true);
6626       outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
6627              << format("0x%08" PRIx32, def);
6628       if (r != nullptr) {
6629         if (left > sizeof(struct objc_category_t)) {
6630           outs() << "\n";
6631           memcpy(&objc_category, r, sizeof(struct objc_category_t));
6632         } else {
6633           outs() << " (entends past the end of the section)\n";
6634           memset(&objc_category, '\0', sizeof(struct objc_category_t));
6635           memcpy(&objc_category, r, left);
6636         }
6637         if (O->isLittleEndian() != sys::IsLittleEndianHost)
6638           swapStruct(objc_category);
6639         print_objc_objc_category_t(&objc_category, &info);
6640       } else {
6641         outs() << "(not in an __OBJC section)\n";
6642       }
6643     }
6644   }
6645   const SectionRef II = get_section(O, "__OBJC", "__image_info");
6646   if (II != SectionRef())
6647     print_image_info(II, &info);
6648 
6649   return true;
6650 }
6651 
DumpProtocolSection(MachOObjectFile * O,const char * sect,uint32_t size,uint32_t addr)6652 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
6653                                 uint32_t size, uint32_t addr) {
6654   SymbolAddressMap AddrMap;
6655   CreateSymbolAddressMap(O, &AddrMap);
6656 
6657   std::vector<SectionRef> Sections;
6658   append_range(Sections, O->sections());
6659 
6660   struct DisassembleInfo info(O, &AddrMap, &Sections, true);
6661 
6662   const char *p;
6663   struct objc_protocol_t protocol;
6664   uint32_t left, paddr;
6665   for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
6666     memset(&protocol, '\0', sizeof(struct objc_protocol_t));
6667     left = size - (p - sect);
6668     if (left < sizeof(struct objc_protocol_t)) {
6669       outs() << "Protocol extends past end of __protocol section\n";
6670       memcpy(&protocol, p, left);
6671     } else
6672       memcpy(&protocol, p, sizeof(struct objc_protocol_t));
6673     if (O->isLittleEndian() != sys::IsLittleEndianHost)
6674       swapStruct(protocol);
6675     paddr = addr + (p - sect);
6676     outs() << "Protocol " << format("0x%" PRIx32, paddr);
6677     if (print_protocol(paddr, 0, &info))
6678       outs() << "(not in an __OBJC section)\n";
6679   }
6680 }
6681 
printObjcMetaData(MachOObjectFile * O,bool verbose)6682 static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
6683   if (O->is64Bit())
6684     printObjc2_64bit_MetaData(O, verbose);
6685   else {
6686     MachO::mach_header H;
6687     H = O->getHeader();
6688     if (H.cputype == MachO::CPU_TYPE_ARM)
6689       printObjc2_32bit_MetaData(O, verbose);
6690     else {
6691       // This is the 32-bit non-arm cputype case.  Which is normally
6692       // the first Objective-C ABI.  But it may be the case of a
6693       // binary for the iOS simulator which is the second Objective-C
6694       // ABI.  In that case printObjc1_32bit_MetaData() will determine that
6695       // and return false.
6696       if (!printObjc1_32bit_MetaData(O, verbose))
6697         printObjc2_32bit_MetaData(O, verbose);
6698     }
6699   }
6700 }
6701 
6702 // GuessLiteralPointer returns a string which for the item in the Mach-O file
6703 // for the address passed in as ReferenceValue for printing as a comment with
6704 // the instruction and also returns the corresponding type of that item
6705 // indirectly through ReferenceType.
6706 //
6707 // If ReferenceValue is an address of literal cstring then a pointer to the
6708 // cstring is returned and ReferenceType is set to
6709 // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
6710 //
6711 // If ReferenceValue is an address of an Objective-C CFString, Selector ref or
6712 // Class ref that name is returned and the ReferenceType is set accordingly.
6713 //
6714 // Lastly, literals which are Symbol address in a literal pool are looked for
6715 // and if found the symbol name is returned and ReferenceType is set to
6716 // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
6717 //
6718 // If there is no item in the Mach-O file for the address passed in as
6719 // ReferenceValue nullptr is returned and ReferenceType is unchanged.
GuessLiteralPointer(uint64_t ReferenceValue,uint64_t ReferencePC,uint64_t * ReferenceType,struct DisassembleInfo * info)6720 static const char *GuessLiteralPointer(uint64_t ReferenceValue,
6721                                        uint64_t ReferencePC,
6722                                        uint64_t *ReferenceType,
6723                                        struct DisassembleInfo *info) {
6724   // First see if there is an external relocation entry at the ReferencePC.
6725   if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
6726     uint64_t sect_addr = info->S.getAddress();
6727     uint64_t sect_offset = ReferencePC - sect_addr;
6728     bool reloc_found = false;
6729     DataRefImpl Rel;
6730     MachO::any_relocation_info RE;
6731     bool isExtern = false;
6732     SymbolRef Symbol;
6733     for (const RelocationRef &Reloc : info->S.relocations()) {
6734       uint64_t RelocOffset = Reloc.getOffset();
6735       if (RelocOffset == sect_offset) {
6736         Rel = Reloc.getRawDataRefImpl();
6737         RE = info->O->getRelocation(Rel);
6738         if (info->O->isRelocationScattered(RE))
6739           continue;
6740         isExtern = info->O->getPlainRelocationExternal(RE);
6741         if (isExtern) {
6742           symbol_iterator RelocSym = Reloc.getSymbol();
6743           Symbol = *RelocSym;
6744         }
6745         reloc_found = true;
6746         break;
6747       }
6748     }
6749     // If there is an external relocation entry for a symbol in a section
6750     // then used that symbol's value for the value of the reference.
6751     if (reloc_found && isExtern) {
6752       if (info->O->getAnyRelocationPCRel(RE)) {
6753         unsigned Type = info->O->getAnyRelocationType(RE);
6754         if (Type == MachO::X86_64_RELOC_SIGNED) {
6755           ReferenceValue = cantFail(Symbol.getValue());
6756         }
6757       }
6758     }
6759   }
6760 
6761   // Look for literals such as Objective-C CFStrings refs, Selector refs,
6762   // Message refs and Class refs.
6763   bool classref, selref, msgref, cfstring;
6764   uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
6765                                                selref, msgref, cfstring);
6766   if (classref && pointer_value == 0) {
6767     // Note the ReferenceValue is a pointer into the __objc_classrefs section.
6768     // And the pointer_value in that section is typically zero as it will be
6769     // set by dyld as part of the "bind information".
6770     const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
6771     if (name != nullptr) {
6772       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6773       const char *class_name = strrchr(name, '$');
6774       if (class_name != nullptr && class_name[1] == '_' &&
6775           class_name[2] != '\0') {
6776         info->class_name = class_name + 2;
6777         return name;
6778       }
6779     }
6780   }
6781 
6782   if (classref) {
6783     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
6784     const char *name =
6785         get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
6786     if (name != nullptr)
6787       info->class_name = name;
6788     else
6789       name = "bad class ref";
6790     return name;
6791   }
6792 
6793   if (cfstring) {
6794     *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
6795     const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
6796     return name;
6797   }
6798 
6799   if (selref && pointer_value == 0)
6800     pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
6801 
6802   if (pointer_value != 0)
6803     ReferenceValue = pointer_value;
6804 
6805   const char *name = GuessCstringPointer(ReferenceValue, info);
6806   if (name) {
6807     if (pointer_value != 0 && selref) {
6808       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
6809       info->selector_name = name;
6810     } else if (pointer_value != 0 && msgref) {
6811       info->class_name = nullptr;
6812       *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
6813       info->selector_name = name;
6814     } else
6815       *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
6816     return name;
6817   }
6818 
6819   // Lastly look for an indirect symbol with this ReferenceValue which is in
6820   // a literal pool.  If found return that symbol name.
6821   name = GuessIndirectSymbol(ReferenceValue, info);
6822   if (name) {
6823     *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
6824     return name;
6825   }
6826 
6827   return nullptr;
6828 }
6829 
6830 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
6831 // the Symbolizer.  It looks up the ReferenceValue using the info passed via the
6832 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
6833 // is created and returns the symbol name that matches the ReferenceValue or
6834 // nullptr if none.  The ReferenceType is passed in for the IN type of
6835 // reference the instruction is making from the values in defined in the header
6836 // "llvm-c/Disassembler.h".  On return the ReferenceType can set to a specific
6837 // Out type and the ReferenceName will also be set which is added as a comment
6838 // to the disassembled instruction.
6839 //
6840 // If the symbol name is a C++ mangled name then the demangled name is
6841 // returned through ReferenceName and ReferenceType is set to
6842 // LLVMDisassembler_ReferenceType_DeMangled_Name .
6843 //
6844 // When this is called to get a symbol name for a branch target then the
6845 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
6846 // SymbolValue will be looked for in the indirect symbol table to determine if
6847 // it is an address for a symbol stub.  If so then the symbol name for that
6848 // stub is returned indirectly through ReferenceName and then ReferenceType is
6849 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
6850 //
6851 // When this is called with an value loaded via a PC relative load then
6852 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
6853 // SymbolValue is checked to be an address of literal pointer, symbol pointer,
6854 // or an Objective-C meta data reference.  If so the output ReferenceType is
6855 // 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)6856 static const char *SymbolizerSymbolLookUp(void *DisInfo,
6857                                           uint64_t ReferenceValue,
6858                                           uint64_t *ReferenceType,
6859                                           uint64_t ReferencePC,
6860                                           const char **ReferenceName) {
6861   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
6862   // If no verbose symbolic information is wanted then just return nullptr.
6863   if (!info->verbose) {
6864     *ReferenceName = nullptr;
6865     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6866     return nullptr;
6867   }
6868 
6869   const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
6870 
6871   if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
6872     *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
6873     if (*ReferenceName != nullptr) {
6874       method_reference(info, ReferenceType, ReferenceName);
6875       if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
6876         *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
6877     } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6878       if (info->demangled_name != nullptr)
6879         free(info->demangled_name);
6880       info->demangled_name = itaniumDemangle(SymbolName + 1);
6881       if (info->demangled_name != nullptr) {
6882         *ReferenceName = info->demangled_name;
6883         *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
6884       } else
6885         *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6886     } else
6887       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6888   } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
6889     *ReferenceName =
6890         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6891     if (*ReferenceName)
6892       method_reference(info, ReferenceType, ReferenceName);
6893     else
6894       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6895     // If this is arm64 and the reference is an adrp instruction save the
6896     // instruction, passed in ReferenceValue and the address of the instruction
6897     // for use later if we see and add immediate instruction.
6898   } else if (info->O->getArch() == Triple::aarch64 &&
6899              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
6900     info->adrp_inst = ReferenceValue;
6901     info->adrp_addr = ReferencePC;
6902     SymbolName = nullptr;
6903     *ReferenceName = nullptr;
6904     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6905     // If this is arm64 and reference is an add immediate instruction and we
6906     // have
6907     // seen an adrp instruction just before it and the adrp's Xd register
6908     // matches
6909     // this add's Xn register reconstruct the value being referenced and look to
6910     // see if it is a literal pointer.  Note the add immediate instruction is
6911     // passed in ReferenceValue.
6912   } else if (info->O->getArch() == Triple::aarch64 &&
6913              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
6914              ReferencePC - 4 == info->adrp_addr &&
6915              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6916              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6917     uint32_t addxri_inst;
6918     uint64_t adrp_imm, addxri_imm;
6919 
6920     adrp_imm =
6921         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6922     if (info->adrp_inst & 0x0200000)
6923       adrp_imm |= 0xfffffffffc000000LL;
6924 
6925     addxri_inst = ReferenceValue;
6926     addxri_imm = (addxri_inst >> 10) & 0xfff;
6927     if (((addxri_inst >> 22) & 0x3) == 1)
6928       addxri_imm <<= 12;
6929 
6930     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6931                      (adrp_imm << 12) + addxri_imm;
6932 
6933     *ReferenceName =
6934         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6935     if (*ReferenceName == nullptr)
6936       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6937     // If this is arm64 and the reference is a load register instruction and we
6938     // have seen an adrp instruction just before it and the adrp's Xd register
6939     // matches this add's Xn register reconstruct the value being referenced and
6940     // look to see if it is a literal pointer.  Note the load register
6941     // instruction is passed in ReferenceValue.
6942   } else if (info->O->getArch() == Triple::aarch64 &&
6943              *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
6944              ReferencePC - 4 == info->adrp_addr &&
6945              (info->adrp_inst & 0x9f000000) == 0x90000000 &&
6946              (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
6947     uint32_t ldrxui_inst;
6948     uint64_t adrp_imm, ldrxui_imm;
6949 
6950     adrp_imm =
6951         ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
6952     if (info->adrp_inst & 0x0200000)
6953       adrp_imm |= 0xfffffffffc000000LL;
6954 
6955     ldrxui_inst = ReferenceValue;
6956     ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
6957 
6958     ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
6959                      (adrp_imm << 12) + (ldrxui_imm << 3);
6960 
6961     *ReferenceName =
6962         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6963     if (*ReferenceName == nullptr)
6964       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6965   }
6966   // If this arm64 and is an load register (PC-relative) instruction the
6967   // ReferenceValue is the PC plus the immediate value.
6968   else if (info->O->getArch() == Triple::aarch64 &&
6969            (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
6970             *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
6971     *ReferenceName =
6972         GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
6973     if (*ReferenceName == nullptr)
6974       *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6975   } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
6976     if (info->demangled_name != nullptr)
6977       free(info->demangled_name);
6978     info->demangled_name = itaniumDemangle(SymbolName + 1);
6979     if (info->demangled_name != nullptr) {
6980       *ReferenceName = info->demangled_name;
6981       *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
6982     }
6983   }
6984   else {
6985     *ReferenceName = nullptr;
6986     *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
6987   }
6988 
6989   return SymbolName;
6990 }
6991 
6992 /// Emits the comments that are stored in the CommentStream.
6993 /// 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)6994 static void emitComments(raw_svector_ostream &CommentStream,
6995                          SmallString<128> &CommentsToEmit,
6996                          formatted_raw_ostream &FormattedOS,
6997                          const MCAsmInfo &MAI) {
6998   // Flush the stream before taking its content.
6999   StringRef Comments = CommentsToEmit.str();
7000   // Get the default information for printing a comment.
7001   StringRef CommentBegin = MAI.getCommentString();
7002   unsigned CommentColumn = MAI.getCommentColumn();
7003   ListSeparator LS("\n");
7004   while (!Comments.empty()) {
7005     FormattedOS << LS;
7006     // Emit a line of comments.
7007     FormattedOS.PadToColumn(CommentColumn);
7008     size_t Position = Comments.find('\n');
7009     FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
7010     // Move after the newline character.
7011     Comments = Comments.substr(Position + 1);
7012   }
7013   FormattedOS.flush();
7014 
7015   // Tell the comment stream that the vector changed underneath it.
7016   CommentsToEmit.clear();
7017 }
7018 
7019 const MachOObjectFile *
getMachODSymObject(const MachOObjectFile * MachOOF,StringRef Filename,std::unique_ptr<Binary> & DSYMBinary,std::unique_ptr<MemoryBuffer> & DSYMBuf)7020 objdump::getMachODSymObject(const MachOObjectFile *MachOOF, StringRef Filename,
7021                             std::unique_ptr<Binary> &DSYMBinary,
7022                             std::unique_ptr<MemoryBuffer> &DSYMBuf) {
7023   const MachOObjectFile *DbgObj = MachOOF;
7024   std::string DSYMPath;
7025 
7026   // Auto-detect w/o --dsym.
7027   if (DSYMFile.empty()) {
7028     sys::fs::file_status DSYMStatus;
7029     Twine FilenameDSYM = Filename + ".dSYM";
7030     if (!status(FilenameDSYM, DSYMStatus)) {
7031       if (sys::fs::is_directory(DSYMStatus)) {
7032         SmallString<1024> Path;
7033         FilenameDSYM.toVector(Path);
7034         sys::path::append(Path, "Contents", "Resources", "DWARF",
7035                           sys::path::filename(Filename));
7036         DSYMPath = std::string(Path);
7037       } else if (sys::fs::is_regular_file(DSYMStatus)) {
7038         DSYMPath = FilenameDSYM.str();
7039       }
7040     }
7041   }
7042 
7043   if (DSYMPath.empty() && !DSYMFile.empty()) {
7044     // If DSYMPath is a .dSYM directory, append the Mach-O file.
7045     if (sys::fs::is_directory(DSYMFile) &&
7046         sys::path::extension(DSYMFile) == ".dSYM") {
7047       SmallString<128> ShortName(sys::path::filename(DSYMFile));
7048       sys::path::replace_extension(ShortName, "");
7049       SmallString<1024> FullPath(DSYMFile);
7050       sys::path::append(FullPath, "Contents", "Resources", "DWARF", ShortName);
7051       DSYMPath = FullPath.str();
7052     } else {
7053       DSYMPath = DSYMFile;
7054     }
7055   }
7056 
7057   if (!DSYMPath.empty()) {
7058     // Load the file.
7059     ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
7060         MemoryBuffer::getFileOrSTDIN(DSYMPath);
7061     if (std::error_code EC = BufOrErr.getError()) {
7062       reportError(errorCodeToError(EC), DSYMPath);
7063       return nullptr;
7064     }
7065 
7066     // We need to keep the file alive, because we're replacing DbgObj with it.
7067     DSYMBuf = std::move(BufOrErr.get());
7068 
7069     Expected<std::unique_ptr<Binary>> BinaryOrErr =
7070         createBinary(DSYMBuf.get()->getMemBufferRef());
7071     if (!BinaryOrErr) {
7072       reportError(BinaryOrErr.takeError(), DSYMPath);
7073       return nullptr;
7074     }
7075 
7076     // We need to keep the Binary alive with the buffer
7077     DSYMBinary = std::move(BinaryOrErr.get());
7078     if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) {
7079       // this is a Mach-O object file, use it
7080       if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) {
7081         DbgObj = MachDSYM;
7082       } else {
7083         WithColor::error(errs(), "llvm-objdump")
7084             << DSYMPath << " is not a Mach-O file type.\n";
7085         return nullptr;
7086       }
7087     } else if (auto *UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())) {
7088       // this is a Universal Binary, find a Mach-O for this architecture
7089       uint32_t CPUType, CPUSubType;
7090       const char *ArchFlag;
7091       if (MachOOF->is64Bit()) {
7092         const MachO::mach_header_64 H_64 = MachOOF->getHeader64();
7093         CPUType = H_64.cputype;
7094         CPUSubType = H_64.cpusubtype;
7095       } else {
7096         const MachO::mach_header H = MachOOF->getHeader();
7097         CPUType = H.cputype;
7098         CPUSubType = H.cpusubtype;
7099       }
7100       Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr,
7101                                                 &ArchFlag);
7102       Expected<std::unique_ptr<MachOObjectFile>> MachDSYM =
7103           UB->getMachOObjectForArch(ArchFlag);
7104       if (!MachDSYM) {
7105         reportError(MachDSYM.takeError(), DSYMPath);
7106         return nullptr;
7107       }
7108 
7109       // We need to keep the Binary alive with the buffer
7110       DbgObj = &*MachDSYM.get();
7111       DSYMBinary = std::move(*MachDSYM);
7112     } else {
7113       WithColor::error(errs(), "llvm-objdump")
7114           << DSYMPath << " is not a Mach-O or Universal file type.\n";
7115       return nullptr;
7116     }
7117   }
7118   return DbgObj;
7119 }
7120 
DisassembleMachO(StringRef Filename,MachOObjectFile * MachOOF,StringRef DisSegName,StringRef DisSectName)7121 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
7122                              StringRef DisSegName, StringRef DisSectName) {
7123   const char *McpuDefault = nullptr;
7124   const Target *ThumbTarget = nullptr;
7125   const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
7126   if (!TheTarget) {
7127     // GetTarget prints out stuff.
7128     return;
7129   }
7130   std::string MachOMCPU;
7131   if (MCPU.empty() && McpuDefault)
7132     MachOMCPU = McpuDefault;
7133   else
7134     MachOMCPU = MCPU;
7135 
7136 #define CHECK_TARGET_INFO_CREATION(NAME)                                       \
7137   do {                                                                         \
7138     if (!NAME) {                                                               \
7139       WithColor::error(errs(), "llvm-objdump")                                 \
7140           << "couldn't initialize disassembler for target " << TripleName      \
7141           << '\n';                                                             \
7142       return;                                                                  \
7143     }                                                                          \
7144   } while (false)
7145 #define CHECK_THUMB_TARGET_INFO_CREATION(NAME)                                 \
7146   do {                                                                         \
7147     if (!NAME) {                                                               \
7148       WithColor::error(errs(), "llvm-objdump")                                 \
7149           << "couldn't initialize disassembler for target " << ThumbTripleName \
7150           << '\n';                                                             \
7151       return;                                                                  \
7152     }                                                                          \
7153   } while (false)
7154 
7155   std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
7156   CHECK_TARGET_INFO_CREATION(InstrInfo);
7157   std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
7158   if (ThumbTarget) {
7159     ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
7160     CHECK_THUMB_TARGET_INFO_CREATION(ThumbInstrInfo);
7161   }
7162 
7163   // Package up features to be passed to target/subtarget
7164   std::string FeaturesStr;
7165   if (!MAttrs.empty()) {
7166     SubtargetFeatures Features;
7167     for (unsigned i = 0; i != MAttrs.size(); ++i)
7168       Features.AddFeature(MAttrs[i]);
7169     FeaturesStr = Features.getString();
7170   }
7171 
7172   MCTargetOptions MCOptions;
7173   // Set up disassembler.
7174   std::unique_ptr<const MCRegisterInfo> MRI(
7175       TheTarget->createMCRegInfo(TripleName));
7176   CHECK_TARGET_INFO_CREATION(MRI);
7177   std::unique_ptr<const MCAsmInfo> AsmInfo(
7178       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
7179   CHECK_TARGET_INFO_CREATION(AsmInfo);
7180   std::unique_ptr<const MCSubtargetInfo> STI(
7181       TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
7182   CHECK_TARGET_INFO_CREATION(STI);
7183   MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
7184   std::unique_ptr<MCDisassembler> DisAsm(
7185       TheTarget->createMCDisassembler(*STI, Ctx));
7186   CHECK_TARGET_INFO_CREATION(DisAsm);
7187   std::unique_ptr<MCSymbolizer> Symbolizer;
7188   struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);
7189   std::unique_ptr<MCRelocationInfo> RelInfo(
7190       TheTarget->createMCRelocationInfo(TripleName, Ctx));
7191   if (RelInfo) {
7192     Symbolizer.reset(TheTarget->createMCSymbolizer(
7193         TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7194         &SymbolizerInfo, &Ctx, std::move(RelInfo)));
7195     DisAsm->setSymbolizer(std::move(Symbolizer));
7196   }
7197   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
7198   std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
7199       Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
7200   CHECK_TARGET_INFO_CREATION(IP);
7201   // Set the display preference for hex vs. decimal immediates.
7202   IP->setPrintImmHex(PrintImmHex);
7203   // Comment stream and backing vector.
7204   SmallString<128> CommentsToEmit;
7205   raw_svector_ostream CommentStream(CommentsToEmit);
7206   // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
7207   // if it is done then arm64 comments for string literals don't get printed
7208   // and some constant get printed instead and not setting it causes intel
7209   // (32-bit and 64-bit) comments printed with different spacing before the
7210   // comment causing different diffs with the 'C' disassembler library API.
7211   // IP->setCommentStream(CommentStream);
7212 
7213   // Set up separate thumb disassembler if needed.
7214   std::unique_ptr<const MCRegisterInfo> ThumbMRI;
7215   std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
7216   std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
7217   std::unique_ptr<MCDisassembler> ThumbDisAsm;
7218   std::unique_ptr<MCInstPrinter> ThumbIP;
7219   std::unique_ptr<MCContext> ThumbCtx;
7220   std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
7221   struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);
7222   std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
7223   if (ThumbTarget) {
7224     ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
7225     CHECK_THUMB_TARGET_INFO_CREATION(ThumbMRI);
7226     ThumbAsmInfo.reset(
7227         ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName, MCOptions));
7228     CHECK_THUMB_TARGET_INFO_CREATION(ThumbAsmInfo);
7229     ThumbSTI.reset(
7230         ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
7231                                            FeaturesStr));
7232     CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI);
7233     ThumbCtx.reset(new MCContext(Triple(ThumbTripleName), ThumbAsmInfo.get(),
7234                                  ThumbMRI.get(), ThumbSTI.get()));
7235     ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
7236     CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm);
7237     MCContext *PtrThumbCtx = ThumbCtx.get();
7238     ThumbRelInfo.reset(
7239         ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
7240     if (ThumbRelInfo) {
7241       ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
7242           ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
7243           &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
7244       ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
7245     }
7246     int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
7247     ThumbIP.reset(ThumbTarget->createMCInstPrinter(
7248         Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
7249         *ThumbInstrInfo, *ThumbMRI));
7250     CHECK_THUMB_TARGET_INFO_CREATION(ThumbIP);
7251     // Set the display preference for hex vs. decimal immediates.
7252     ThumbIP->setPrintImmHex(PrintImmHex);
7253   }
7254 
7255 #undef CHECK_TARGET_INFO_CREATION
7256 #undef CHECK_THUMB_TARGET_INFO_CREATION
7257 
7258   MachO::mach_header Header = MachOOF->getHeader();
7259 
7260   // FIXME: Using the -cfg command line option, this code used to be able to
7261   // annotate relocations with the referenced symbol's name, and if this was
7262   // inside a __[cf]string section, the data it points to. This is now replaced
7263   // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
7264   std::vector<SectionRef> Sections;
7265   std::vector<SymbolRef> Symbols;
7266   SmallVector<uint64_t, 8> FoundFns;
7267   uint64_t BaseSegmentAddress = 0;
7268 
7269   getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
7270                         BaseSegmentAddress);
7271 
7272   // Sort the symbols by address, just in case they didn't come in that way.
7273   llvm::stable_sort(Symbols, SymbolSorter());
7274 
7275   // Build a data in code table that is sorted on by the address of each entry.
7276   uint64_t BaseAddress = 0;
7277   if (Header.filetype == MachO::MH_OBJECT)
7278     BaseAddress = Sections[0].getAddress();
7279   else
7280     BaseAddress = BaseSegmentAddress;
7281   DiceTable Dices;
7282   for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
7283        DI != DE; ++DI) {
7284     uint32_t Offset;
7285     DI->getOffset(Offset);
7286     Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
7287   }
7288   array_pod_sort(Dices.begin(), Dices.end());
7289 
7290   // Try to find debug info and set up the DIContext for it.
7291   std::unique_ptr<DIContext> diContext;
7292   std::unique_ptr<Binary> DSYMBinary;
7293   std::unique_ptr<MemoryBuffer> DSYMBuf;
7294   if (UseDbg) {
7295     // If separate DSym file path was specified, parse it as a macho file,
7296     // get the sections and supply it to the section name parsing machinery.
7297     if (const ObjectFile *DbgObj =
7298             getMachODSymObject(MachOOF, Filename, DSYMBinary, DSYMBuf)) {
7299       // Setup the DIContext
7300       diContext = DWARFContext::create(*DbgObj);
7301     } else {
7302       return;
7303     }
7304   }
7305 
7306   if (FilterSections.empty())
7307     outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
7308 
7309   for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
7310     Expected<StringRef> SecNameOrErr = Sections[SectIdx].getName();
7311     if (!SecNameOrErr) {
7312       consumeError(SecNameOrErr.takeError());
7313       continue;
7314     }
7315     if (*SecNameOrErr != DisSectName)
7316       continue;
7317 
7318     DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
7319 
7320     StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
7321     if (SegmentName != DisSegName)
7322       continue;
7323 
7324     StringRef BytesStr =
7325         unwrapOrError(Sections[SectIdx].getContents(), Filename);
7326     ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(BytesStr);
7327     uint64_t SectAddress = Sections[SectIdx].getAddress();
7328 
7329     bool symbolTableWorked = false;
7330 
7331     // Create a map of symbol addresses to symbol names for use by
7332     // the SymbolizerSymbolLookUp() routine.
7333     SymbolAddressMap AddrMap;
7334     bool DisSymNameFound = false;
7335     for (const SymbolRef &Symbol : MachOOF->symbols()) {
7336       SymbolRef::Type ST =
7337           unwrapOrError(Symbol.getType(), MachOOF->getFileName());
7338       if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
7339           ST == SymbolRef::ST_Other) {
7340         uint64_t Address = cantFail(Symbol.getValue());
7341         StringRef SymName =
7342             unwrapOrError(Symbol.getName(), MachOOF->getFileName());
7343         AddrMap[Address] = SymName;
7344         if (!DisSymName.empty() && DisSymName == SymName)
7345           DisSymNameFound = true;
7346       }
7347     }
7348     if (!DisSymName.empty() && !DisSymNameFound) {
7349       outs() << "Can't find -dis-symname: " << DisSymName << "\n";
7350       return;
7351     }
7352     // Set up the block of info used by the Symbolizer call backs.
7353     SymbolizerInfo.verbose = SymbolicOperands;
7354     SymbolizerInfo.O = MachOOF;
7355     SymbolizerInfo.S = Sections[SectIdx];
7356     SymbolizerInfo.AddrMap = &AddrMap;
7357     SymbolizerInfo.Sections = &Sections;
7358     // Same for the ThumbSymbolizer
7359     ThumbSymbolizerInfo.verbose = SymbolicOperands;
7360     ThumbSymbolizerInfo.O = MachOOF;
7361     ThumbSymbolizerInfo.S = Sections[SectIdx];
7362     ThumbSymbolizerInfo.AddrMap = &AddrMap;
7363     ThumbSymbolizerInfo.Sections = &Sections;
7364 
7365     unsigned int Arch = MachOOF->getArch();
7366 
7367     // Skip all symbols if this is a stubs file.
7368     if (Bytes.empty())
7369       return;
7370 
7371     // If the section has symbols but no symbol at the start of the section
7372     // these are used to make sure the bytes before the first symbol are
7373     // disassembled.
7374     bool FirstSymbol = true;
7375     bool FirstSymbolAtSectionStart = true;
7376 
7377     // Disassemble symbol by symbol.
7378     for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
7379       StringRef SymName =
7380           unwrapOrError(Symbols[SymIdx].getName(), MachOOF->getFileName());
7381       SymbolRef::Type ST =
7382           unwrapOrError(Symbols[SymIdx].getType(), MachOOF->getFileName());
7383       if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
7384         continue;
7385 
7386       // Make sure the symbol is defined in this section.
7387       bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
7388       if (!containsSym) {
7389         if (!DisSymName.empty() && DisSymName == SymName) {
7390           outs() << "-dis-symname: " << DisSymName << " not in the section\n";
7391           return;
7392         }
7393         continue;
7394       }
7395       // The __mh_execute_header is special and we need to deal with that fact
7396       // this symbol is before the start of the (__TEXT,__text) section and at the
7397       // address of the start of the __TEXT segment.  This is because this symbol
7398       // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
7399       // start of the section in a standard MH_EXECUTE filetype.
7400       if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
7401         outs() << "-dis-symname: __mh_execute_header not in any section\n";
7402         return;
7403       }
7404       // When this code is trying to disassemble a symbol at a time and in the
7405       // case there is only the __mh_execute_header symbol left as in a stripped
7406       // executable, we need to deal with this by ignoring this symbol so the
7407       // whole section is disassembled and this symbol is then not displayed.
7408       if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
7409           SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
7410           SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
7411         continue;
7412 
7413       // If we are only disassembling one symbol see if this is that symbol.
7414       if (!DisSymName.empty() && DisSymName != SymName)
7415         continue;
7416 
7417       // Start at the address of the symbol relative to the section's address.
7418       uint64_t SectSize = Sections[SectIdx].getSize();
7419       uint64_t Start = cantFail(Symbols[SymIdx].getValue());
7420       uint64_t SectionAddress = Sections[SectIdx].getAddress();
7421       Start -= SectionAddress;
7422 
7423       if (Start > SectSize) {
7424         outs() << "section data ends, " << SymName
7425                << " lies outside valid range\n";
7426         return;
7427       }
7428 
7429       // Stop disassembling either at the beginning of the next symbol or at
7430       // the end of the section.
7431       bool containsNextSym = false;
7432       uint64_t NextSym = 0;
7433       uint64_t NextSymIdx = SymIdx + 1;
7434       while (Symbols.size() > NextSymIdx) {
7435         SymbolRef::Type NextSymType = unwrapOrError(
7436             Symbols[NextSymIdx].getType(), MachOOF->getFileName());
7437         if (NextSymType == SymbolRef::ST_Function) {
7438           containsNextSym =
7439               Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
7440           NextSym = cantFail(Symbols[NextSymIdx].getValue());
7441           NextSym -= SectionAddress;
7442           break;
7443         }
7444         ++NextSymIdx;
7445       }
7446 
7447       uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
7448       uint64_t Size;
7449 
7450       symbolTableWorked = true;
7451 
7452       DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
7453       uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb));
7454       bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb;
7455 
7456       // We only need the dedicated Thumb target if there's a real choice
7457       // (i.e. we're not targeting M-class) and the function is Thumb.
7458       bool UseThumbTarget = IsThumb && ThumbTarget;
7459 
7460       // If we are not specifying a symbol to start disassembly with and this
7461       // is the first symbol in the section but not at the start of the section
7462       // then move the disassembly index to the start of the section and
7463       // don't print the symbol name just yet.  This is so the bytes before the
7464       // first symbol are disassembled.
7465       uint64_t SymbolStart = Start;
7466       if (DisSymName.empty() && FirstSymbol && Start != 0) {
7467         FirstSymbolAtSectionStart = false;
7468         Start = 0;
7469       }
7470       else
7471         outs() << SymName << ":\n";
7472 
7473       DILineInfo lastLine;
7474       for (uint64_t Index = Start; Index < End; Index += Size) {
7475         MCInst Inst;
7476 
7477         // If this is the first symbol in the section and it was not at the
7478         // start of the section, see if we are at its Index now and if so print
7479         // the symbol name.
7480         if (FirstSymbol && !FirstSymbolAtSectionStart && Index == SymbolStart)
7481           outs() << SymName << ":\n";
7482 
7483         uint64_t PC = SectAddress + Index;
7484         if (LeadingAddr) {
7485           if (FullLeadingAddr) {
7486             if (MachOOF->is64Bit())
7487               outs() << format("%016" PRIx64, PC);
7488             else
7489               outs() << format("%08" PRIx64, PC);
7490           } else {
7491             outs() << format("%8" PRIx64 ":", PC);
7492           }
7493         }
7494         if (ShowRawInsn || Arch == Triple::arm)
7495           outs() << "\t";
7496 
7497         if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size))
7498           continue;
7499 
7500         SmallVector<char, 64> AnnotationsBytes;
7501         raw_svector_ostream Annotations(AnnotationsBytes);
7502 
7503         bool gotInst;
7504         if (UseThumbTarget)
7505           gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
7506                                                 PC, Annotations);
7507         else
7508           gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
7509                                            Annotations);
7510         if (gotInst) {
7511           if (ShowRawInsn || Arch == Triple::arm) {
7512             dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs());
7513           }
7514           formatted_raw_ostream FormattedOS(outs());
7515           StringRef AnnotationsStr = Annotations.str();
7516           if (UseThumbTarget)
7517             ThumbIP->printInst(&Inst, PC, AnnotationsStr, *ThumbSTI,
7518                                FormattedOS);
7519           else
7520             IP->printInst(&Inst, PC, AnnotationsStr, *STI, FormattedOS);
7521           emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
7522 
7523           // Print debug info.
7524           if (diContext) {
7525             DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx});
7526             // Print valid line info if it changed.
7527             if (dli != lastLine && dli.Line != 0)
7528               outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
7529                      << dli.Column;
7530             lastLine = dli;
7531           }
7532           outs() << "\n";
7533         } else {
7534           if (MachOOF->getArchTriple().isX86()) {
7535             outs() << format("\t.byte 0x%02x #bad opcode\n",
7536                              *(Bytes.data() + Index) & 0xff);
7537             Size = 1; // skip exactly one illegible byte and move on.
7538           } else if (Arch == Triple::aarch64 ||
7539                      (Arch == Triple::arm && !IsThumb)) {
7540             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7541                               (*(Bytes.data() + Index + 1) & 0xff) << 8 |
7542                               (*(Bytes.data() + Index + 2) & 0xff) << 16 |
7543                               (*(Bytes.data() + Index + 3) & 0xff) << 24;
7544             outs() << format("\t.long\t0x%08x\n", opcode);
7545             Size = 4;
7546           } else if (Arch == Triple::arm) {
7547             assert(IsThumb && "ARM mode should have been dealt with above");
7548             uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
7549                               (*(Bytes.data() + Index + 1) & 0xff) << 8;
7550             outs() << format("\t.short\t0x%04x\n", opcode);
7551             Size = 2;
7552           } else{
7553             WithColor::warning(errs(), "llvm-objdump")
7554                 << "invalid instruction encoding\n";
7555             if (Size == 0)
7556               Size = 1; // skip illegible bytes
7557           }
7558         }
7559       }
7560       // Now that we are done disassembled the first symbol set the bool that
7561       // were doing this to false.
7562       FirstSymbol = false;
7563     }
7564     if (!symbolTableWorked) {
7565       // Reading the symbol table didn't work, disassemble the whole section.
7566       uint64_t SectAddress = Sections[SectIdx].getAddress();
7567       uint64_t SectSize = Sections[SectIdx].getSize();
7568       uint64_t InstSize;
7569       for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
7570         MCInst Inst;
7571 
7572         uint64_t PC = SectAddress + Index;
7573 
7574         if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, InstSize))
7575           continue;
7576 
7577         SmallVector<char, 64> AnnotationsBytes;
7578         raw_svector_ostream Annotations(AnnotationsBytes);
7579         if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
7580                                    Annotations)) {
7581           if (LeadingAddr) {
7582             if (FullLeadingAddr) {
7583               if (MachOOF->is64Bit())
7584                 outs() << format("%016" PRIx64, PC);
7585               else
7586                 outs() << format("%08" PRIx64, PC);
7587             } else {
7588               outs() << format("%8" PRIx64 ":", PC);
7589             }
7590           }
7591           if (ShowRawInsn || Arch == Triple::arm) {
7592             outs() << "\t";
7593             dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs());
7594           }
7595           StringRef AnnotationsStr = Annotations.str();
7596           IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs());
7597           outs() << "\n";
7598         } else {
7599           if (MachOOF->getArchTriple().isX86()) {
7600             outs() << format("\t.byte 0x%02x #bad opcode\n",
7601                              *(Bytes.data() + Index) & 0xff);
7602             InstSize = 1; // skip exactly one illegible byte and move on.
7603           } else {
7604             WithColor::warning(errs(), "llvm-objdump")
7605                 << "invalid instruction encoding\n";
7606             if (InstSize == 0)
7607               InstSize = 1; // skip illegible bytes
7608           }
7609         }
7610       }
7611     }
7612     // The TripleName's need to be reset if we are called again for a different
7613     // architecture.
7614     TripleName = "";
7615     ThumbTripleName = "";
7616 
7617     if (SymbolizerInfo.demangled_name != nullptr)
7618       free(SymbolizerInfo.demangled_name);
7619     if (ThumbSymbolizerInfo.demangled_name != nullptr)
7620       free(ThumbSymbolizerInfo.demangled_name);
7621   }
7622 }
7623 
7624 //===----------------------------------------------------------------------===//
7625 // __compact_unwind section dumping
7626 //===----------------------------------------------------------------------===//
7627 
7628 namespace {
7629 
7630 template <typename T>
read(StringRef Contents,ptrdiff_t Offset)7631 static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
7632   if (Offset + sizeof(T) > Contents.size()) {
7633     outs() << "warning: attempt to read past end of buffer\n";
7634     return T();
7635   }
7636 
7637   uint64_t Val = support::endian::read<T, llvm::endianness::little>(
7638       Contents.data() + Offset);
7639   return Val;
7640 }
7641 
7642 template <typename T>
readNext(StringRef Contents,ptrdiff_t & Offset)7643 static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) {
7644   T Val = read<T>(Contents, Offset);
7645   Offset += sizeof(T);
7646   return Val;
7647 }
7648 
7649 struct CompactUnwindEntry {
7650   uint32_t OffsetInSection;
7651 
7652   uint64_t FunctionAddr;
7653   uint32_t Length;
7654   uint32_t CompactEncoding;
7655   uint64_t PersonalityAddr;
7656   uint64_t LSDAAddr;
7657 
7658   RelocationRef FunctionReloc;
7659   RelocationRef PersonalityReloc;
7660   RelocationRef LSDAReloc;
7661 
CompactUnwindEntry__anon3ed9bcb80a11::CompactUnwindEntry7662   CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
7663       : OffsetInSection(Offset) {
7664     if (Is64)
7665       read<uint64_t>(Contents, Offset);
7666     else
7667       read<uint32_t>(Contents, Offset);
7668   }
7669 
7670 private:
read__anon3ed9bcb80a11::CompactUnwindEntry7671   template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) {
7672     FunctionAddr = readNext<UIntPtr>(Contents, Offset);
7673     Length = readNext<uint32_t>(Contents, Offset);
7674     CompactEncoding = readNext<uint32_t>(Contents, Offset);
7675     PersonalityAddr = readNext<UIntPtr>(Contents, Offset);
7676     LSDAAddr = readNext<UIntPtr>(Contents, Offset);
7677   }
7678 };
7679 }
7680 
7681 /// Given a relocation from __compact_unwind, consisting of the RelocationRef
7682 /// and data being relocated, determine the best base Name and Addend to use for
7683 /// display purposes.
7684 ///
7685 /// 1. An Extern relocation will directly reference a symbol (and the data is
7686 ///    then already an addend), so use that.
7687 /// 2. Otherwise the data is an offset in the object file's layout; try to find
7688 //     a symbol before it in the same section, and use the offset from there.
7689 /// 3. Finally, if all that fails, fall back to an offset from the start of the
7690 ///    referenced section.
findUnwindRelocNameAddend(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr,StringRef & Name,uint64_t & Addend)7691 static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
7692                                       std::map<uint64_t, SymbolRef> &Symbols,
7693                                       const RelocationRef &Reloc, uint64_t Addr,
7694                                       StringRef &Name, uint64_t &Addend) {
7695   if (Reloc.getSymbol() != Obj->symbol_end()) {
7696     Name = unwrapOrError(Reloc.getSymbol()->getName(), Obj->getFileName());
7697     Addend = Addr;
7698     return;
7699   }
7700 
7701   auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
7702   SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
7703 
7704   uint64_t SectionAddr = RelocSection.getAddress();
7705 
7706   auto Sym = Symbols.upper_bound(Addr);
7707   if (Sym == Symbols.begin()) {
7708     // The first symbol in the object is after this reference, the best we can
7709     // do is section-relative notation.
7710     if (Expected<StringRef> NameOrErr = RelocSection.getName())
7711       Name = *NameOrErr;
7712     else
7713       consumeError(NameOrErr.takeError());
7714 
7715     Addend = Addr - SectionAddr;
7716     return;
7717   }
7718 
7719   // Go back one so that SymbolAddress <= Addr.
7720   --Sym;
7721 
7722   section_iterator SymSection =
7723       unwrapOrError(Sym->second.getSection(), Obj->getFileName());
7724   if (RelocSection == *SymSection) {
7725     // There's a valid symbol in the same section before this reference.
7726     Name = unwrapOrError(Sym->second.getName(), Obj->getFileName());
7727     Addend = Addr - Sym->first;
7728     return;
7729   }
7730 
7731   // There is a symbol before this reference, but it's in a different
7732   // section. Probably not helpful to mention it, so use the section name.
7733   if (Expected<StringRef> NameOrErr = RelocSection.getName())
7734     Name = *NameOrErr;
7735   else
7736     consumeError(NameOrErr.takeError());
7737 
7738   Addend = Addr - SectionAddr;
7739 }
7740 
printUnwindRelocDest(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const RelocationRef & Reloc,uint64_t Addr)7741 static void printUnwindRelocDest(const MachOObjectFile *Obj,
7742                                  std::map<uint64_t, SymbolRef> &Symbols,
7743                                  const RelocationRef &Reloc, uint64_t Addr) {
7744   StringRef Name;
7745   uint64_t Addend;
7746 
7747   if (!Reloc.getObject())
7748     return;
7749 
7750   findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
7751 
7752   outs() << Name;
7753   if (Addend)
7754     outs() << " + " << format("0x%" PRIx64, Addend);
7755 }
7756 
7757 static void
printMachOCompactUnwindSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & CompactUnwind)7758 printMachOCompactUnwindSection(const MachOObjectFile *Obj,
7759                                std::map<uint64_t, SymbolRef> &Symbols,
7760                                const SectionRef &CompactUnwind) {
7761 
7762   if (!Obj->isLittleEndian()) {
7763     outs() << "Skipping big-endian __compact_unwind section\n";
7764     return;
7765   }
7766 
7767   bool Is64 = Obj->is64Bit();
7768   uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
7769   uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
7770 
7771   StringRef Contents =
7772       unwrapOrError(CompactUnwind.getContents(), Obj->getFileName());
7773   SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
7774 
7775   // First populate the initial raw offsets, encodings and so on from the entry.
7776   for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
7777     CompactUnwindEntry Entry(Contents, Offset, Is64);
7778     CompactUnwinds.push_back(Entry);
7779   }
7780 
7781   // Next we need to look at the relocations to find out what objects are
7782   // actually being referred to.
7783   for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
7784     uint64_t RelocAddress = Reloc.getOffset();
7785 
7786     uint32_t EntryIdx = RelocAddress / EntrySize;
7787     uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
7788     CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
7789 
7790     if (OffsetInEntry == 0)
7791       Entry.FunctionReloc = Reloc;
7792     else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
7793       Entry.PersonalityReloc = Reloc;
7794     else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
7795       Entry.LSDAReloc = Reloc;
7796     else {
7797       outs() << "Invalid relocation in __compact_unwind section\n";
7798       return;
7799     }
7800   }
7801 
7802   // Finally, we're ready to print the data we've gathered.
7803   outs() << "Contents of __compact_unwind section:\n";
7804   for (auto &Entry : CompactUnwinds) {
7805     outs() << "  Entry at offset "
7806            << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
7807 
7808     // 1. Start of the region this entry applies to.
7809     outs() << "    start:                " << format("0x%" PRIx64,
7810                                                      Entry.FunctionAddr) << ' ';
7811     printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
7812     outs() << '\n';
7813 
7814     // 2. Length of the region this entry applies to.
7815     outs() << "    length:               " << format("0x%" PRIx32, Entry.Length)
7816            << '\n';
7817     // 3. The 32-bit compact encoding.
7818     outs() << "    compact encoding:     "
7819            << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
7820 
7821     // 4. The personality function, if present.
7822     if (Entry.PersonalityReloc.getObject()) {
7823       outs() << "    personality function: "
7824              << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
7825       printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
7826                            Entry.PersonalityAddr);
7827       outs() << '\n';
7828     }
7829 
7830     // 5. This entry's language-specific data area.
7831     if (Entry.LSDAReloc.getObject()) {
7832       outs() << "    LSDA:                 " << format("0x%" PRIx64,
7833                                                        Entry.LSDAAddr) << ' ';
7834       printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
7835       outs() << '\n';
7836     }
7837   }
7838 }
7839 
7840 //===----------------------------------------------------------------------===//
7841 // __unwind_info section dumping
7842 //===----------------------------------------------------------------------===//
7843 
printRegularSecondLevelUnwindPage(StringRef PageData)7844 static void printRegularSecondLevelUnwindPage(StringRef PageData) {
7845   ptrdiff_t Pos = 0;
7846   uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7847   (void)Kind;
7848   assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
7849 
7850   uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7851   uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7852 
7853   Pos = EntriesStart;
7854   for (unsigned i = 0; i < NumEntries; ++i) {
7855     uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos);
7856     uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
7857 
7858     outs() << "      [" << i << "]: "
7859            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7860            << ", "
7861            << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
7862   }
7863 }
7864 
printCompressedSecondLevelUnwindPage(StringRef PageData,uint32_t FunctionBase,const SmallVectorImpl<uint32_t> & CommonEncodings)7865 static void printCompressedSecondLevelUnwindPage(
7866     StringRef PageData, uint32_t FunctionBase,
7867     const SmallVectorImpl<uint32_t> &CommonEncodings) {
7868   ptrdiff_t Pos = 0;
7869   uint32_t Kind = readNext<uint32_t>(PageData, Pos);
7870   (void)Kind;
7871   assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
7872 
7873   uint32_t NumCommonEncodings = CommonEncodings.size();
7874   uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
7875   uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
7876 
7877   uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos);
7878   uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos);
7879   SmallVector<uint32_t, 64> PageEncodings;
7880   if (NumPageEncodings) {
7881     outs() << "      Page encodings: (count = " << NumPageEncodings << ")\n";
7882     Pos = PageEncodingsStart;
7883     for (unsigned i = 0; i < NumPageEncodings; ++i) {
7884       uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
7885       PageEncodings.push_back(Encoding);
7886       outs() << "        encoding[" << (i + NumCommonEncodings)
7887              << "]: " << format("0x%08" PRIx32, Encoding) << '\n';
7888     }
7889   }
7890 
7891   Pos = EntriesStart;
7892   for (unsigned i = 0; i < NumEntries; ++i) {
7893     uint32_t Entry = readNext<uint32_t>(PageData, Pos);
7894     uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
7895     uint32_t EncodingIdx = Entry >> 24;
7896 
7897     uint32_t Encoding;
7898     if (EncodingIdx < NumCommonEncodings)
7899       Encoding = CommonEncodings[EncodingIdx];
7900     else
7901       Encoding = PageEncodings[EncodingIdx - NumCommonEncodings];
7902 
7903     outs() << "      [" << i << "]: "
7904            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
7905            << ", "
7906            << "encoding[" << EncodingIdx
7907            << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
7908   }
7909 }
7910 
printMachOUnwindInfoSection(const MachOObjectFile * Obj,std::map<uint64_t,SymbolRef> & Symbols,const SectionRef & UnwindInfo)7911 static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
7912                                         std::map<uint64_t, SymbolRef> &Symbols,
7913                                         const SectionRef &UnwindInfo) {
7914 
7915   if (!Obj->isLittleEndian()) {
7916     outs() << "Skipping big-endian __unwind_info section\n";
7917     return;
7918   }
7919 
7920   outs() << "Contents of __unwind_info section:\n";
7921 
7922   StringRef Contents =
7923       unwrapOrError(UnwindInfo.getContents(), Obj->getFileName());
7924   ptrdiff_t Pos = 0;
7925 
7926   //===----------------------------------
7927   // Section header
7928   //===----------------------------------
7929 
7930   uint32_t Version = readNext<uint32_t>(Contents, Pos);
7931   outs() << "  Version:                                   "
7932          << format("0x%" PRIx32, Version) << '\n';
7933   if (Version != 1) {
7934     outs() << "    Skipping section with unknown version\n";
7935     return;
7936   }
7937 
7938   uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);
7939   outs() << "  Common encodings array section offset:     "
7940          << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
7941   uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);
7942   outs() << "  Number of common encodings in array:       "
7943          << format("0x%" PRIx32, NumCommonEncodings) << '\n';
7944 
7945   uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);
7946   outs() << "  Personality function array section offset: "
7947          << format("0x%" PRIx32, PersonalitiesStart) << '\n';
7948   uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);
7949   outs() << "  Number of personality functions in array:  "
7950          << format("0x%" PRIx32, NumPersonalities) << '\n';
7951 
7952   uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);
7953   outs() << "  Index array section offset:                "
7954          << format("0x%" PRIx32, IndicesStart) << '\n';
7955   uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);
7956   outs() << "  Number of indices in array:                "
7957          << format("0x%" PRIx32, NumIndices) << '\n';
7958 
7959   //===----------------------------------
7960   // A shared list of common encodings
7961   //===----------------------------------
7962 
7963   // These occupy indices in the range [0, N] whenever an encoding is referenced
7964   // from a compressed 2nd level index table. In practice the linker only
7965   // creates ~128 of these, so that indices are available to embed encodings in
7966   // the 2nd level index.
7967 
7968   SmallVector<uint32_t, 64> CommonEncodings;
7969   outs() << "  Common encodings: (count = " << NumCommonEncodings << ")\n";
7970   Pos = CommonEncodingsStart;
7971   for (unsigned i = 0; i < NumCommonEncodings; ++i) {
7972     uint32_t Encoding = readNext<uint32_t>(Contents, Pos);
7973     CommonEncodings.push_back(Encoding);
7974 
7975     outs() << "    encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
7976            << '\n';
7977   }
7978 
7979   //===----------------------------------
7980   // Personality functions used in this executable
7981   //===----------------------------------
7982 
7983   // There should be only a handful of these (one per source language,
7984   // roughly). Particularly since they only get 2 bits in the compact encoding.
7985 
7986   outs() << "  Personality functions: (count = " << NumPersonalities << ")\n";
7987   Pos = PersonalitiesStart;
7988   for (unsigned i = 0; i < NumPersonalities; ++i) {
7989     uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);
7990     outs() << "    personality[" << i + 1
7991            << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
7992   }
7993 
7994   //===----------------------------------
7995   // The level 1 index entries
7996   //===----------------------------------
7997 
7998   // These specify an approximate place to start searching for the more detailed
7999   // information, sorted by PC.
8000 
8001   struct IndexEntry {
8002     uint32_t FunctionOffset;
8003     uint32_t SecondLevelPageStart;
8004     uint32_t LSDAStart;
8005   };
8006 
8007   SmallVector<IndexEntry, 4> IndexEntries;
8008 
8009   outs() << "  Top level indices: (count = " << NumIndices << ")\n";
8010   Pos = IndicesStart;
8011   for (unsigned i = 0; i < NumIndices; ++i) {
8012     IndexEntry Entry;
8013 
8014     Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos);
8015     Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos);
8016     Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);
8017     IndexEntries.push_back(Entry);
8018 
8019     outs() << "    [" << i << "]: "
8020            << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
8021            << ", "
8022            << "2nd level page offset="
8023            << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
8024            << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
8025   }
8026 
8027   //===----------------------------------
8028   // Next come the LSDA tables
8029   //===----------------------------------
8030 
8031   // The LSDA layout is rather implicit: it's a contiguous array of entries from
8032   // the first top-level index's LSDAOffset to the last (sentinel).
8033 
8034   outs() << "  LSDA descriptors:\n";
8035   Pos = IndexEntries[0].LSDAStart;
8036   const uint32_t LSDASize = 2 * sizeof(uint32_t);
8037   int NumLSDAs =
8038       (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize;
8039 
8040   for (int i = 0; i < NumLSDAs; ++i) {
8041     uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos);
8042     uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);
8043     outs() << "    [" << i << "]: "
8044            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
8045            << ", "
8046            << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
8047   }
8048 
8049   //===----------------------------------
8050   // Finally, the 2nd level indices
8051   //===----------------------------------
8052 
8053   // Generally these are 4K in size, and have 2 possible forms:
8054   //   + Regular stores up to 511 entries with disparate encodings
8055   //   + Compressed stores up to 1021 entries if few enough compact encoding
8056   //     values are used.
8057   outs() << "  Second level indices:\n";
8058   for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
8059     // The final sentinel top-level index has no associated 2nd level page
8060     if (IndexEntries[i].SecondLevelPageStart == 0)
8061       break;
8062 
8063     outs() << "    Second level index[" << i << "]: "
8064            << "offset in section="
8065            << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
8066            << ", "
8067            << "base function offset="
8068            << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
8069 
8070     Pos = IndexEntries[i].SecondLevelPageStart;
8071     if (Pos + sizeof(uint32_t) > Contents.size()) {
8072       outs() << "warning: invalid offset for second level page: " << Pos << '\n';
8073       continue;
8074     }
8075 
8076     uint32_t Kind =
8077         *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);
8078     if (Kind == 2)
8079       printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));
8080     else if (Kind == 3)
8081       printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096),
8082                                            IndexEntries[i].FunctionOffset,
8083                                            CommonEncodings);
8084     else
8085       outs() << "    Skipping 2nd level page with unknown kind " << Kind
8086              << '\n';
8087   }
8088 }
8089 
printMachOUnwindInfo(const MachOObjectFile * Obj)8090 void objdump::printMachOUnwindInfo(const MachOObjectFile *Obj) {
8091   std::map<uint64_t, SymbolRef> Symbols;
8092   for (const SymbolRef &SymRef : Obj->symbols()) {
8093     // Discard any undefined or absolute symbols. They're not going to take part
8094     // in the convenience lookup for unwind info and just take up resources.
8095     auto SectOrErr = SymRef.getSection();
8096     if (!SectOrErr) {
8097       // TODO: Actually report errors helpfully.
8098       consumeError(SectOrErr.takeError());
8099       continue;
8100     }
8101     section_iterator Section = *SectOrErr;
8102     if (Section == Obj->section_end())
8103       continue;
8104 
8105     uint64_t Addr = cantFail(SymRef.getValue());
8106     Symbols.insert(std::make_pair(Addr, SymRef));
8107   }
8108 
8109   for (const SectionRef &Section : Obj->sections()) {
8110     StringRef SectName;
8111     if (Expected<StringRef> NameOrErr = Section.getName())
8112       SectName = *NameOrErr;
8113     else
8114       consumeError(NameOrErr.takeError());
8115 
8116     if (SectName == "__compact_unwind")
8117       printMachOCompactUnwindSection(Obj, Symbols, Section);
8118     else if (SectName == "__unwind_info")
8119       printMachOUnwindInfoSection(Obj, Symbols, Section);
8120   }
8121 }
8122 
PrintMachHeader(uint32_t magic,uint32_t cputype,uint32_t cpusubtype,uint32_t filetype,uint32_t ncmds,uint32_t sizeofcmds,uint32_t flags,bool verbose)8123 static void PrintMachHeader(uint32_t magic, uint32_t cputype,
8124                             uint32_t cpusubtype, uint32_t filetype,
8125                             uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
8126                             bool verbose) {
8127   outs() << "Mach header\n";
8128   outs() << "      magic cputype cpusubtype  caps    filetype ncmds "
8129             "sizeofcmds      flags\n";
8130   if (verbose) {
8131     if (magic == MachO::MH_MAGIC)
8132       outs() << "   MH_MAGIC";
8133     else if (magic == MachO::MH_MAGIC_64)
8134       outs() << "MH_MAGIC_64";
8135     else
8136       outs() << format(" 0x%08" PRIx32, magic);
8137     switch (cputype) {
8138     case MachO::CPU_TYPE_I386:
8139       outs() << "    I386";
8140       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8141       case MachO::CPU_SUBTYPE_I386_ALL:
8142         outs() << "        ALL";
8143         break;
8144       default:
8145         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8146         break;
8147       }
8148       break;
8149     case MachO::CPU_TYPE_X86_64:
8150       outs() << "  X86_64";
8151       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8152       case MachO::CPU_SUBTYPE_X86_64_ALL:
8153         outs() << "        ALL";
8154         break;
8155       case MachO::CPU_SUBTYPE_X86_64_H:
8156         outs() << "    Haswell";
8157         break;
8158       default:
8159         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8160         break;
8161       }
8162       break;
8163     case MachO::CPU_TYPE_ARM:
8164       outs() << "     ARM";
8165       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8166       case MachO::CPU_SUBTYPE_ARM_ALL:
8167         outs() << "        ALL";
8168         break;
8169       case MachO::CPU_SUBTYPE_ARM_V4T:
8170         outs() << "        V4T";
8171         break;
8172       case MachO::CPU_SUBTYPE_ARM_V5TEJ:
8173         outs() << "      V5TEJ";
8174         break;
8175       case MachO::CPU_SUBTYPE_ARM_XSCALE:
8176         outs() << "     XSCALE";
8177         break;
8178       case MachO::CPU_SUBTYPE_ARM_V6:
8179         outs() << "         V6";
8180         break;
8181       case MachO::CPU_SUBTYPE_ARM_V6M:
8182         outs() << "        V6M";
8183         break;
8184       case MachO::CPU_SUBTYPE_ARM_V7:
8185         outs() << "         V7";
8186         break;
8187       case MachO::CPU_SUBTYPE_ARM_V7EM:
8188         outs() << "       V7EM";
8189         break;
8190       case MachO::CPU_SUBTYPE_ARM_V7K:
8191         outs() << "        V7K";
8192         break;
8193       case MachO::CPU_SUBTYPE_ARM_V7M:
8194         outs() << "        V7M";
8195         break;
8196       case MachO::CPU_SUBTYPE_ARM_V7S:
8197         outs() << "        V7S";
8198         break;
8199       default:
8200         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8201         break;
8202       }
8203       break;
8204     case MachO::CPU_TYPE_ARM64:
8205       outs() << "   ARM64";
8206       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8207       case MachO::CPU_SUBTYPE_ARM64_ALL:
8208         outs() << "        ALL";
8209         break;
8210       case MachO::CPU_SUBTYPE_ARM64_V8:
8211         outs() << "         V8";
8212         break;
8213       case MachO::CPU_SUBTYPE_ARM64E:
8214         outs() << "          E";
8215         break;
8216       default:
8217         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8218         break;
8219       }
8220       break;
8221     case MachO::CPU_TYPE_ARM64_32:
8222       outs() << " ARM64_32";
8223       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8224       case MachO::CPU_SUBTYPE_ARM64_32_V8:
8225         outs() << "        V8";
8226         break;
8227       default:
8228         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8229         break;
8230       }
8231       break;
8232     case MachO::CPU_TYPE_POWERPC:
8233       outs() << "     PPC";
8234       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8235       case MachO::CPU_SUBTYPE_POWERPC_ALL:
8236         outs() << "        ALL";
8237         break;
8238       default:
8239         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8240         break;
8241       }
8242       break;
8243     case MachO::CPU_TYPE_POWERPC64:
8244       outs() << "   PPC64";
8245       switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
8246       case MachO::CPU_SUBTYPE_POWERPC_ALL:
8247         outs() << "        ALL";
8248         break;
8249       default:
8250         outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8251         break;
8252       }
8253       break;
8254     default:
8255       outs() << format(" %7d", cputype);
8256       outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8257       break;
8258     }
8259     if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
8260       outs() << " LIB64";
8261     } else {
8262       outs() << format("  0x%02" PRIx32,
8263                        (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8264     }
8265     switch (filetype) {
8266     case MachO::MH_OBJECT:
8267       outs() << "      OBJECT";
8268       break;
8269     case MachO::MH_EXECUTE:
8270       outs() << "     EXECUTE";
8271       break;
8272     case MachO::MH_FVMLIB:
8273       outs() << "      FVMLIB";
8274       break;
8275     case MachO::MH_CORE:
8276       outs() << "        CORE";
8277       break;
8278     case MachO::MH_PRELOAD:
8279       outs() << "     PRELOAD";
8280       break;
8281     case MachO::MH_DYLIB:
8282       outs() << "       DYLIB";
8283       break;
8284     case MachO::MH_DYLIB_STUB:
8285       outs() << "  DYLIB_STUB";
8286       break;
8287     case MachO::MH_DYLINKER:
8288       outs() << "    DYLINKER";
8289       break;
8290     case MachO::MH_BUNDLE:
8291       outs() << "      BUNDLE";
8292       break;
8293     case MachO::MH_DSYM:
8294       outs() << "        DSYM";
8295       break;
8296     case MachO::MH_KEXT_BUNDLE:
8297       outs() << "  KEXTBUNDLE";
8298       break;
8299     case MachO::MH_FILESET:
8300       outs() << "     FILESET";
8301       break;
8302     default:
8303       outs() << format("  %10u", filetype);
8304       break;
8305     }
8306     outs() << format(" %5u", ncmds);
8307     outs() << format(" %10u", sizeofcmds);
8308     uint32_t f = flags;
8309     if (f & MachO::MH_NOUNDEFS) {
8310       outs() << "   NOUNDEFS";
8311       f &= ~MachO::MH_NOUNDEFS;
8312     }
8313     if (f & MachO::MH_INCRLINK) {
8314       outs() << " INCRLINK";
8315       f &= ~MachO::MH_INCRLINK;
8316     }
8317     if (f & MachO::MH_DYLDLINK) {
8318       outs() << " DYLDLINK";
8319       f &= ~MachO::MH_DYLDLINK;
8320     }
8321     if (f & MachO::MH_BINDATLOAD) {
8322       outs() << " BINDATLOAD";
8323       f &= ~MachO::MH_BINDATLOAD;
8324     }
8325     if (f & MachO::MH_PREBOUND) {
8326       outs() << " PREBOUND";
8327       f &= ~MachO::MH_PREBOUND;
8328     }
8329     if (f & MachO::MH_SPLIT_SEGS) {
8330       outs() << " SPLIT_SEGS";
8331       f &= ~MachO::MH_SPLIT_SEGS;
8332     }
8333     if (f & MachO::MH_LAZY_INIT) {
8334       outs() << " LAZY_INIT";
8335       f &= ~MachO::MH_LAZY_INIT;
8336     }
8337     if (f & MachO::MH_TWOLEVEL) {
8338       outs() << " TWOLEVEL";
8339       f &= ~MachO::MH_TWOLEVEL;
8340     }
8341     if (f & MachO::MH_FORCE_FLAT) {
8342       outs() << " FORCE_FLAT";
8343       f &= ~MachO::MH_FORCE_FLAT;
8344     }
8345     if (f & MachO::MH_NOMULTIDEFS) {
8346       outs() << " NOMULTIDEFS";
8347       f &= ~MachO::MH_NOMULTIDEFS;
8348     }
8349     if (f & MachO::MH_NOFIXPREBINDING) {
8350       outs() << " NOFIXPREBINDING";
8351       f &= ~MachO::MH_NOFIXPREBINDING;
8352     }
8353     if (f & MachO::MH_PREBINDABLE) {
8354       outs() << " PREBINDABLE";
8355       f &= ~MachO::MH_PREBINDABLE;
8356     }
8357     if (f & MachO::MH_ALLMODSBOUND) {
8358       outs() << " ALLMODSBOUND";
8359       f &= ~MachO::MH_ALLMODSBOUND;
8360     }
8361     if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
8362       outs() << " SUBSECTIONS_VIA_SYMBOLS";
8363       f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
8364     }
8365     if (f & MachO::MH_CANONICAL) {
8366       outs() << " CANONICAL";
8367       f &= ~MachO::MH_CANONICAL;
8368     }
8369     if (f & MachO::MH_WEAK_DEFINES) {
8370       outs() << " WEAK_DEFINES";
8371       f &= ~MachO::MH_WEAK_DEFINES;
8372     }
8373     if (f & MachO::MH_BINDS_TO_WEAK) {
8374       outs() << " BINDS_TO_WEAK";
8375       f &= ~MachO::MH_BINDS_TO_WEAK;
8376     }
8377     if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
8378       outs() << " ALLOW_STACK_EXECUTION";
8379       f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
8380     }
8381     if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
8382       outs() << " DEAD_STRIPPABLE_DYLIB";
8383       f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
8384     }
8385     if (f & MachO::MH_PIE) {
8386       outs() << " PIE";
8387       f &= ~MachO::MH_PIE;
8388     }
8389     if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
8390       outs() << " NO_REEXPORTED_DYLIBS";
8391       f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
8392     }
8393     if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
8394       outs() << " MH_HAS_TLV_DESCRIPTORS";
8395       f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
8396     }
8397     if (f & MachO::MH_NO_HEAP_EXECUTION) {
8398       outs() << " MH_NO_HEAP_EXECUTION";
8399       f &= ~MachO::MH_NO_HEAP_EXECUTION;
8400     }
8401     if (f & MachO::MH_APP_EXTENSION_SAFE) {
8402       outs() << " APP_EXTENSION_SAFE";
8403       f &= ~MachO::MH_APP_EXTENSION_SAFE;
8404     }
8405     if (f & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
8406       outs() << " NLIST_OUTOFSYNC_WITH_DYLDINFO";
8407       f &= ~MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO;
8408     }
8409     if (f != 0 || flags == 0)
8410       outs() << format(" 0x%08" PRIx32, f);
8411   } else {
8412     outs() << format(" 0x%08" PRIx32, magic);
8413     outs() << format(" %7d", cputype);
8414     outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
8415     outs() << format("  0x%02" PRIx32,
8416                      (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
8417     outs() << format("  %10u", filetype);
8418     outs() << format(" %5u", ncmds);
8419     outs() << format(" %10u", sizeofcmds);
8420     outs() << format(" 0x%08" PRIx32, flags);
8421   }
8422   outs() << "\n";
8423 }
8424 
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)8425 static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
8426                                 StringRef SegName, uint64_t vmaddr,
8427                                 uint64_t vmsize, uint64_t fileoff,
8428                                 uint64_t filesize, uint32_t maxprot,
8429                                 uint32_t initprot, uint32_t nsects,
8430                                 uint32_t flags, uint32_t object_size,
8431                                 bool verbose) {
8432   uint64_t expected_cmdsize;
8433   if (cmd == MachO::LC_SEGMENT) {
8434     outs() << "      cmd LC_SEGMENT\n";
8435     expected_cmdsize = nsects;
8436     expected_cmdsize *= sizeof(struct MachO::section);
8437     expected_cmdsize += sizeof(struct MachO::segment_command);
8438   } else {
8439     outs() << "      cmd LC_SEGMENT_64\n";
8440     expected_cmdsize = nsects;
8441     expected_cmdsize *= sizeof(struct MachO::section_64);
8442     expected_cmdsize += sizeof(struct MachO::segment_command_64);
8443   }
8444   outs() << "  cmdsize " << cmdsize;
8445   if (cmdsize != expected_cmdsize)
8446     outs() << " Inconsistent size\n";
8447   else
8448     outs() << "\n";
8449   outs() << "  segname " << SegName << "\n";
8450   if (cmd == MachO::LC_SEGMENT_64) {
8451     outs() << "   vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
8452     outs() << "   vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
8453   } else {
8454     outs() << "   vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
8455     outs() << "   vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
8456   }
8457   outs() << "  fileoff " << fileoff;
8458   if (fileoff > object_size)
8459     outs() << " (past end of file)\n";
8460   else
8461     outs() << "\n";
8462   outs() << " filesize " << filesize;
8463   if (fileoff + filesize > object_size)
8464     outs() << " (past end of file)\n";
8465   else
8466     outs() << "\n";
8467   if (verbose) {
8468     if ((maxprot &
8469          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8470            MachO::VM_PROT_EXECUTE)) != 0)
8471       outs() << "  maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
8472     else {
8473       outs() << "  maxprot ";
8474       outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
8475       outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8476       outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8477     }
8478     if ((initprot &
8479          ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
8480            MachO::VM_PROT_EXECUTE)) != 0)
8481       outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
8482     else {
8483       outs() << " initprot ";
8484       outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
8485       outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
8486       outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
8487     }
8488   } else {
8489     outs() << "  maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
8490     outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
8491   }
8492   outs() << "   nsects " << nsects << "\n";
8493   if (verbose) {
8494     outs() << "    flags";
8495     if (flags == 0)
8496       outs() << " (none)\n";
8497     else {
8498       if (flags & MachO::SG_HIGHVM) {
8499         outs() << " HIGHVM";
8500         flags &= ~MachO::SG_HIGHVM;
8501       }
8502       if (flags & MachO::SG_FVMLIB) {
8503         outs() << " FVMLIB";
8504         flags &= ~MachO::SG_FVMLIB;
8505       }
8506       if (flags & MachO::SG_NORELOC) {
8507         outs() << " NORELOC";
8508         flags &= ~MachO::SG_NORELOC;
8509       }
8510       if (flags & MachO::SG_PROTECTED_VERSION_1) {
8511         outs() << " PROTECTED_VERSION_1";
8512         flags &= ~MachO::SG_PROTECTED_VERSION_1;
8513       }
8514       if (flags & MachO::SG_READ_ONLY) {
8515         // Apple's otool prints the SG_ prefix for this flag, but not for the
8516         // others.
8517         outs() << " SG_READ_ONLY";
8518         flags &= ~MachO::SG_READ_ONLY;
8519       }
8520       if (flags)
8521         outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
8522       else
8523         outs() << "\n";
8524     }
8525   } else {
8526     outs() << "    flags " << format("0x%" PRIx32, flags) << "\n";
8527   }
8528 }
8529 
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)8530 static void PrintSection(const char *sectname, const char *segname,
8531                          uint64_t addr, uint64_t size, uint32_t offset,
8532                          uint32_t align, uint32_t reloff, uint32_t nreloc,
8533                          uint32_t flags, uint32_t reserved1, uint32_t reserved2,
8534                          uint32_t cmd, const char *sg_segname,
8535                          uint32_t filetype, uint32_t object_size,
8536                          bool verbose) {
8537   outs() << "Section\n";
8538   outs() << "  sectname " << format("%.16s\n", sectname);
8539   outs() << "   segname " << format("%.16s", segname);
8540   if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
8541     outs() << " (does not match segment)\n";
8542   else
8543     outs() << "\n";
8544   if (cmd == MachO::LC_SEGMENT_64) {
8545     outs() << "      addr " << format("0x%016" PRIx64, addr) << "\n";
8546     outs() << "      size " << format("0x%016" PRIx64, size);
8547   } else {
8548     outs() << "      addr " << format("0x%08" PRIx64, addr) << "\n";
8549     outs() << "      size " << format("0x%08" PRIx64, size);
8550   }
8551   if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
8552     outs() << " (past end of file)\n";
8553   else
8554     outs() << "\n";
8555   outs() << "    offset " << offset;
8556   if (offset > object_size)
8557     outs() << " (past end of file)\n";
8558   else
8559     outs() << "\n";
8560   uint32_t align_shifted = 1 << align;
8561   outs() << "     align 2^" << align << " (" << align_shifted << ")\n";
8562   outs() << "    reloff " << reloff;
8563   if (reloff > object_size)
8564     outs() << " (past end of file)\n";
8565   else
8566     outs() << "\n";
8567   outs() << "    nreloc " << nreloc;
8568   if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
8569     outs() << " (past end of file)\n";
8570   else
8571     outs() << "\n";
8572   uint32_t section_type = flags & MachO::SECTION_TYPE;
8573   if (verbose) {
8574     outs() << "      type";
8575     if (section_type == MachO::S_REGULAR)
8576       outs() << " S_REGULAR\n";
8577     else if (section_type == MachO::S_ZEROFILL)
8578       outs() << " S_ZEROFILL\n";
8579     else if (section_type == MachO::S_CSTRING_LITERALS)
8580       outs() << " S_CSTRING_LITERALS\n";
8581     else if (section_type == MachO::S_4BYTE_LITERALS)
8582       outs() << " S_4BYTE_LITERALS\n";
8583     else if (section_type == MachO::S_8BYTE_LITERALS)
8584       outs() << " S_8BYTE_LITERALS\n";
8585     else if (section_type == MachO::S_16BYTE_LITERALS)
8586       outs() << " S_16BYTE_LITERALS\n";
8587     else if (section_type == MachO::S_LITERAL_POINTERS)
8588       outs() << " S_LITERAL_POINTERS\n";
8589     else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
8590       outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
8591     else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
8592       outs() << " S_LAZY_SYMBOL_POINTERS\n";
8593     else if (section_type == MachO::S_SYMBOL_STUBS)
8594       outs() << " S_SYMBOL_STUBS\n";
8595     else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
8596       outs() << " S_MOD_INIT_FUNC_POINTERS\n";
8597     else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
8598       outs() << " S_MOD_TERM_FUNC_POINTERS\n";
8599     else if (section_type == MachO::S_COALESCED)
8600       outs() << " S_COALESCED\n";
8601     else if (section_type == MachO::S_INTERPOSING)
8602       outs() << " S_INTERPOSING\n";
8603     else if (section_type == MachO::S_DTRACE_DOF)
8604       outs() << " S_DTRACE_DOF\n";
8605     else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
8606       outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
8607     else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
8608       outs() << " S_THREAD_LOCAL_REGULAR\n";
8609     else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
8610       outs() << " S_THREAD_LOCAL_ZEROFILL\n";
8611     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
8612       outs() << " S_THREAD_LOCAL_VARIABLES\n";
8613     else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8614       outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
8615     else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
8616       outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
8617     else if (section_type == MachO::S_INIT_FUNC_OFFSETS)
8618       outs() << " S_INIT_FUNC_OFFSETS\n";
8619     else
8620       outs() << format("0x%08" PRIx32, section_type) << "\n";
8621     outs() << "attributes";
8622     uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
8623     if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
8624       outs() << " PURE_INSTRUCTIONS";
8625     if (section_attributes & MachO::S_ATTR_NO_TOC)
8626       outs() << " NO_TOC";
8627     if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
8628       outs() << " STRIP_STATIC_SYMS";
8629     if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
8630       outs() << " NO_DEAD_STRIP";
8631     if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
8632       outs() << " LIVE_SUPPORT";
8633     if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
8634       outs() << " SELF_MODIFYING_CODE";
8635     if (section_attributes & MachO::S_ATTR_DEBUG)
8636       outs() << " DEBUG";
8637     if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
8638       outs() << " SOME_INSTRUCTIONS";
8639     if (section_attributes & MachO::S_ATTR_EXT_RELOC)
8640       outs() << " EXT_RELOC";
8641     if (section_attributes & MachO::S_ATTR_LOC_RELOC)
8642       outs() << " LOC_RELOC";
8643     if (section_attributes == 0)
8644       outs() << " (none)";
8645     outs() << "\n";
8646   } else
8647     outs() << "     flags " << format("0x%08" PRIx32, flags) << "\n";
8648   outs() << " reserved1 " << reserved1;
8649   if (section_type == MachO::S_SYMBOL_STUBS ||
8650       section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
8651       section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
8652       section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
8653       section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
8654     outs() << " (index into indirect symbol table)\n";
8655   else
8656     outs() << "\n";
8657   outs() << " reserved2 " << reserved2;
8658   if (section_type == MachO::S_SYMBOL_STUBS)
8659     outs() << " (size of stubs)\n";
8660   else
8661     outs() << "\n";
8662 }
8663 
PrintSymtabLoadCommand(MachO::symtab_command st,bool Is64Bit,uint32_t object_size)8664 static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
8665                                    uint32_t object_size) {
8666   outs() << "     cmd LC_SYMTAB\n";
8667   outs() << " cmdsize " << st.cmdsize;
8668   if (st.cmdsize != sizeof(struct MachO::symtab_command))
8669     outs() << " Incorrect size\n";
8670   else
8671     outs() << "\n";
8672   outs() << "  symoff " << st.symoff;
8673   if (st.symoff > object_size)
8674     outs() << " (past end of file)\n";
8675   else
8676     outs() << "\n";
8677   outs() << "   nsyms " << st.nsyms;
8678   uint64_t big_size;
8679   if (Is64Bit) {
8680     big_size = st.nsyms;
8681     big_size *= sizeof(struct MachO::nlist_64);
8682     big_size += st.symoff;
8683     if (big_size > object_size)
8684       outs() << " (past end of file)\n";
8685     else
8686       outs() << "\n";
8687   } else {
8688     big_size = st.nsyms;
8689     big_size *= sizeof(struct MachO::nlist);
8690     big_size += st.symoff;
8691     if (big_size > object_size)
8692       outs() << " (past end of file)\n";
8693     else
8694       outs() << "\n";
8695   }
8696   outs() << "  stroff " << st.stroff;
8697   if (st.stroff > object_size)
8698     outs() << " (past end of file)\n";
8699   else
8700     outs() << "\n";
8701   outs() << " strsize " << st.strsize;
8702   big_size = st.stroff;
8703   big_size += st.strsize;
8704   if (big_size > object_size)
8705     outs() << " (past end of file)\n";
8706   else
8707     outs() << "\n";
8708 }
8709 
PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,uint32_t nsyms,uint32_t object_size,bool Is64Bit)8710 static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
8711                                      uint32_t nsyms, uint32_t object_size,
8712                                      bool Is64Bit) {
8713   outs() << "            cmd LC_DYSYMTAB\n";
8714   outs() << "        cmdsize " << dyst.cmdsize;
8715   if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
8716     outs() << " Incorrect size\n";
8717   else
8718     outs() << "\n";
8719   outs() << "      ilocalsym " << dyst.ilocalsym;
8720   if (dyst.ilocalsym > nsyms)
8721     outs() << " (greater than the number of symbols)\n";
8722   else
8723     outs() << "\n";
8724   outs() << "      nlocalsym " << dyst.nlocalsym;
8725   uint64_t big_size;
8726   big_size = dyst.ilocalsym;
8727   big_size += dyst.nlocalsym;
8728   if (big_size > nsyms)
8729     outs() << " (past the end of the symbol table)\n";
8730   else
8731     outs() << "\n";
8732   outs() << "     iextdefsym " << dyst.iextdefsym;
8733   if (dyst.iextdefsym > nsyms)
8734     outs() << " (greater than the number of symbols)\n";
8735   else
8736     outs() << "\n";
8737   outs() << "     nextdefsym " << dyst.nextdefsym;
8738   big_size = dyst.iextdefsym;
8739   big_size += dyst.nextdefsym;
8740   if (big_size > nsyms)
8741     outs() << " (past the end of the symbol table)\n";
8742   else
8743     outs() << "\n";
8744   outs() << "      iundefsym " << dyst.iundefsym;
8745   if (dyst.iundefsym > nsyms)
8746     outs() << " (greater than the number of symbols)\n";
8747   else
8748     outs() << "\n";
8749   outs() << "      nundefsym " << dyst.nundefsym;
8750   big_size = dyst.iundefsym;
8751   big_size += dyst.nundefsym;
8752   if (big_size > nsyms)
8753     outs() << " (past the end of the symbol table)\n";
8754   else
8755     outs() << "\n";
8756   outs() << "         tocoff " << dyst.tocoff;
8757   if (dyst.tocoff > object_size)
8758     outs() << " (past end of file)\n";
8759   else
8760     outs() << "\n";
8761   outs() << "           ntoc " << dyst.ntoc;
8762   big_size = dyst.ntoc;
8763   big_size *= sizeof(struct MachO::dylib_table_of_contents);
8764   big_size += dyst.tocoff;
8765   if (big_size > object_size)
8766     outs() << " (past end of file)\n";
8767   else
8768     outs() << "\n";
8769   outs() << "      modtaboff " << dyst.modtaboff;
8770   if (dyst.modtaboff > object_size)
8771     outs() << " (past end of file)\n";
8772   else
8773     outs() << "\n";
8774   outs() << "        nmodtab " << dyst.nmodtab;
8775   uint64_t modtabend;
8776   if (Is64Bit) {
8777     modtabend = dyst.nmodtab;
8778     modtabend *= sizeof(struct MachO::dylib_module_64);
8779     modtabend += dyst.modtaboff;
8780   } else {
8781     modtabend = dyst.nmodtab;
8782     modtabend *= sizeof(struct MachO::dylib_module);
8783     modtabend += dyst.modtaboff;
8784   }
8785   if (modtabend > object_size)
8786     outs() << " (past end of file)\n";
8787   else
8788     outs() << "\n";
8789   outs() << "   extrefsymoff " << dyst.extrefsymoff;
8790   if (dyst.extrefsymoff > object_size)
8791     outs() << " (past end of file)\n";
8792   else
8793     outs() << "\n";
8794   outs() << "    nextrefsyms " << dyst.nextrefsyms;
8795   big_size = dyst.nextrefsyms;
8796   big_size *= sizeof(struct MachO::dylib_reference);
8797   big_size += dyst.extrefsymoff;
8798   if (big_size > object_size)
8799     outs() << " (past end of file)\n";
8800   else
8801     outs() << "\n";
8802   outs() << " indirectsymoff " << dyst.indirectsymoff;
8803   if (dyst.indirectsymoff > object_size)
8804     outs() << " (past end of file)\n";
8805   else
8806     outs() << "\n";
8807   outs() << "  nindirectsyms " << dyst.nindirectsyms;
8808   big_size = dyst.nindirectsyms;
8809   big_size *= sizeof(uint32_t);
8810   big_size += dyst.indirectsymoff;
8811   if (big_size > object_size)
8812     outs() << " (past end of file)\n";
8813   else
8814     outs() << "\n";
8815   outs() << "      extreloff " << dyst.extreloff;
8816   if (dyst.extreloff > object_size)
8817     outs() << " (past end of file)\n";
8818   else
8819     outs() << "\n";
8820   outs() << "        nextrel " << dyst.nextrel;
8821   big_size = dyst.nextrel;
8822   big_size *= sizeof(struct MachO::relocation_info);
8823   big_size += dyst.extreloff;
8824   if (big_size > object_size)
8825     outs() << " (past end of file)\n";
8826   else
8827     outs() << "\n";
8828   outs() << "      locreloff " << dyst.locreloff;
8829   if (dyst.locreloff > object_size)
8830     outs() << " (past end of file)\n";
8831   else
8832     outs() << "\n";
8833   outs() << "        nlocrel " << dyst.nlocrel;
8834   big_size = dyst.nlocrel;
8835   big_size *= sizeof(struct MachO::relocation_info);
8836   big_size += dyst.locreloff;
8837   if (big_size > object_size)
8838     outs() << " (past end of file)\n";
8839   else
8840     outs() << "\n";
8841 }
8842 
PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,uint32_t object_size)8843 static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
8844                                      uint32_t object_size) {
8845   if (dc.cmd == MachO::LC_DYLD_INFO)
8846     outs() << "            cmd LC_DYLD_INFO\n";
8847   else
8848     outs() << "            cmd LC_DYLD_INFO_ONLY\n";
8849   outs() << "        cmdsize " << dc.cmdsize;
8850   if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
8851     outs() << " Incorrect size\n";
8852   else
8853     outs() << "\n";
8854   outs() << "     rebase_off " << dc.rebase_off;
8855   if (dc.rebase_off > object_size)
8856     outs() << " (past end of file)\n";
8857   else
8858     outs() << "\n";
8859   outs() << "    rebase_size " << dc.rebase_size;
8860   uint64_t big_size;
8861   big_size = dc.rebase_off;
8862   big_size += dc.rebase_size;
8863   if (big_size > object_size)
8864     outs() << " (past end of file)\n";
8865   else
8866     outs() << "\n";
8867   outs() << "       bind_off " << dc.bind_off;
8868   if (dc.bind_off > object_size)
8869     outs() << " (past end of file)\n";
8870   else
8871     outs() << "\n";
8872   outs() << "      bind_size " << dc.bind_size;
8873   big_size = dc.bind_off;
8874   big_size += dc.bind_size;
8875   if (big_size > object_size)
8876     outs() << " (past end of file)\n";
8877   else
8878     outs() << "\n";
8879   outs() << "  weak_bind_off " << dc.weak_bind_off;
8880   if (dc.weak_bind_off > object_size)
8881     outs() << " (past end of file)\n";
8882   else
8883     outs() << "\n";
8884   outs() << " weak_bind_size " << dc.weak_bind_size;
8885   big_size = dc.weak_bind_off;
8886   big_size += dc.weak_bind_size;
8887   if (big_size > object_size)
8888     outs() << " (past end of file)\n";
8889   else
8890     outs() << "\n";
8891   outs() << "  lazy_bind_off " << dc.lazy_bind_off;
8892   if (dc.lazy_bind_off > object_size)
8893     outs() << " (past end of file)\n";
8894   else
8895     outs() << "\n";
8896   outs() << " lazy_bind_size " << dc.lazy_bind_size;
8897   big_size = dc.lazy_bind_off;
8898   big_size += dc.lazy_bind_size;
8899   if (big_size > object_size)
8900     outs() << " (past end of file)\n";
8901   else
8902     outs() << "\n";
8903   outs() << "     export_off " << dc.export_off;
8904   if (dc.export_off > object_size)
8905     outs() << " (past end of file)\n";
8906   else
8907     outs() << "\n";
8908   outs() << "    export_size " << dc.export_size;
8909   big_size = dc.export_off;
8910   big_size += dc.export_size;
8911   if (big_size > object_size)
8912     outs() << " (past end of file)\n";
8913   else
8914     outs() << "\n";
8915 }
8916 
PrintDyldLoadCommand(MachO::dylinker_command dyld,const char * Ptr)8917 static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
8918                                  const char *Ptr) {
8919   if (dyld.cmd == MachO::LC_ID_DYLINKER)
8920     outs() << "          cmd LC_ID_DYLINKER\n";
8921   else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
8922     outs() << "          cmd LC_LOAD_DYLINKER\n";
8923   else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
8924     outs() << "          cmd LC_DYLD_ENVIRONMENT\n";
8925   else
8926     outs() << "          cmd ?(" << dyld.cmd << ")\n";
8927   outs() << "      cmdsize " << dyld.cmdsize;
8928   if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
8929     outs() << " Incorrect size\n";
8930   else
8931     outs() << "\n";
8932   if (dyld.name >= dyld.cmdsize)
8933     outs() << "         name ?(bad offset " << dyld.name << ")\n";
8934   else {
8935     const char *P = (const char *)(Ptr) + dyld.name;
8936     outs() << "         name " << P << " (offset " << dyld.name << ")\n";
8937   }
8938 }
8939 
PrintUuidLoadCommand(MachO::uuid_command uuid)8940 static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
8941   outs() << "     cmd LC_UUID\n";
8942   outs() << " cmdsize " << uuid.cmdsize;
8943   if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
8944     outs() << " Incorrect size\n";
8945   else
8946     outs() << "\n";
8947   outs() << "    uuid ";
8948   for (int i = 0; i < 16; ++i) {
8949     outs() << format("%02" PRIX32, uuid.uuid[i]);
8950     if (i == 3 || i == 5 || i == 7 || i == 9)
8951       outs() << "-";
8952   }
8953   outs() << "\n";
8954 }
8955 
PrintRpathLoadCommand(MachO::rpath_command rpath,const char * Ptr)8956 static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
8957   outs() << "          cmd LC_RPATH\n";
8958   outs() << "      cmdsize " << rpath.cmdsize;
8959   if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
8960     outs() << " Incorrect size\n";
8961   else
8962     outs() << "\n";
8963   if (rpath.path >= rpath.cmdsize)
8964     outs() << "         path ?(bad offset " << rpath.path << ")\n";
8965   else {
8966     const char *P = (const char *)(Ptr) + rpath.path;
8967     outs() << "         path " << P << " (offset " << rpath.path << ")\n";
8968   }
8969 }
8970 
PrintVersionMinLoadCommand(MachO::version_min_command vd)8971 static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
8972   StringRef LoadCmdName;
8973   switch (vd.cmd) {
8974   case MachO::LC_VERSION_MIN_MACOSX:
8975     LoadCmdName = "LC_VERSION_MIN_MACOSX";
8976     break;
8977   case MachO::LC_VERSION_MIN_IPHONEOS:
8978     LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
8979     break;
8980   case MachO::LC_VERSION_MIN_TVOS:
8981     LoadCmdName = "LC_VERSION_MIN_TVOS";
8982     break;
8983   case MachO::LC_VERSION_MIN_WATCHOS:
8984     LoadCmdName = "LC_VERSION_MIN_WATCHOS";
8985     break;
8986   default:
8987     llvm_unreachable("Unknown version min load command");
8988   }
8989 
8990   outs() << "      cmd " << LoadCmdName << '\n';
8991   outs() << "  cmdsize " << vd.cmdsize;
8992   if (vd.cmdsize != sizeof(struct MachO::version_min_command))
8993     outs() << " Incorrect size\n";
8994   else
8995     outs() << "\n";
8996   outs() << "  version "
8997          << MachOObjectFile::getVersionMinMajor(vd, false) << "."
8998          << MachOObjectFile::getVersionMinMinor(vd, false);
8999   uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
9000   if (Update != 0)
9001     outs() << "." << Update;
9002   outs() << "\n";
9003   if (vd.sdk == 0)
9004     outs() << "      sdk n/a";
9005   else {
9006     outs() << "      sdk "
9007            << MachOObjectFile::getVersionMinMajor(vd, true) << "."
9008            << MachOObjectFile::getVersionMinMinor(vd, true);
9009   }
9010   Update = MachOObjectFile::getVersionMinUpdate(vd, true);
9011   if (Update != 0)
9012     outs() << "." << Update;
9013   outs() << "\n";
9014 }
9015 
PrintNoteLoadCommand(MachO::note_command Nt)9016 static void PrintNoteLoadCommand(MachO::note_command Nt) {
9017   outs() << "       cmd LC_NOTE\n";
9018   outs() << "   cmdsize " << Nt.cmdsize;
9019   if (Nt.cmdsize != sizeof(struct MachO::note_command))
9020     outs() << " Incorrect size\n";
9021   else
9022     outs() << "\n";
9023   const char *d = Nt.data_owner;
9024   outs() << "data_owner " << format("%.16s\n", d);
9025   outs() << "    offset " << Nt.offset << "\n";
9026   outs() << "      size " << Nt.size << "\n";
9027 }
9028 
PrintBuildToolVersion(MachO::build_tool_version bv,bool verbose)9029 static void PrintBuildToolVersion(MachO::build_tool_version bv, bool verbose) {
9030   outs() << "      tool ";
9031   if (verbose)
9032     outs() << MachOObjectFile::getBuildTool(bv.tool);
9033   else
9034     outs() << bv.tool;
9035   outs() << "\n";
9036   outs() << "   version " << MachOObjectFile::getVersionString(bv.version)
9037          << "\n";
9038 }
9039 
PrintBuildVersionLoadCommand(const MachOObjectFile * obj,MachO::build_version_command bd,bool verbose)9040 static void PrintBuildVersionLoadCommand(const MachOObjectFile *obj,
9041                                          MachO::build_version_command bd,
9042                                          bool verbose) {
9043   outs() << "       cmd LC_BUILD_VERSION\n";
9044   outs() << "   cmdsize " << bd.cmdsize;
9045   if (bd.cmdsize !=
9046       sizeof(struct MachO::build_version_command) +
9047           bd.ntools * sizeof(struct MachO::build_tool_version))
9048     outs() << " Incorrect size\n";
9049   else
9050     outs() << "\n";
9051   outs() << "  platform ";
9052   if (verbose)
9053     outs() << MachOObjectFile::getBuildPlatform(bd.platform);
9054   else
9055     outs() << bd.platform;
9056   outs() << "\n";
9057   if (bd.sdk)
9058     outs() << "       sdk " << MachOObjectFile::getVersionString(bd.sdk)
9059            << "\n";
9060   else
9061     outs() << "       sdk n/a\n";
9062   outs() << "     minos " << MachOObjectFile::getVersionString(bd.minos)
9063          << "\n";
9064   outs() << "    ntools " << bd.ntools << "\n";
9065   for (unsigned i = 0; i < bd.ntools; ++i) {
9066     MachO::build_tool_version bv = obj->getBuildToolVersion(i);
9067     PrintBuildToolVersion(bv, verbose);
9068   }
9069 }
9070 
PrintSourceVersionCommand(MachO::source_version_command sd)9071 static void PrintSourceVersionCommand(MachO::source_version_command sd) {
9072   outs() << "      cmd LC_SOURCE_VERSION\n";
9073   outs() << "  cmdsize " << sd.cmdsize;
9074   if (sd.cmdsize != sizeof(struct MachO::source_version_command))
9075     outs() << " Incorrect size\n";
9076   else
9077     outs() << "\n";
9078   uint64_t a = (sd.version >> 40) & 0xffffff;
9079   uint64_t b = (sd.version >> 30) & 0x3ff;
9080   uint64_t c = (sd.version >> 20) & 0x3ff;
9081   uint64_t d = (sd.version >> 10) & 0x3ff;
9082   uint64_t e = sd.version & 0x3ff;
9083   outs() << "  version " << a << "." << b;
9084   if (e != 0)
9085     outs() << "." << c << "." << d << "." << e;
9086   else if (d != 0)
9087     outs() << "." << c << "." << d;
9088   else if (c != 0)
9089     outs() << "." << c;
9090   outs() << "\n";
9091 }
9092 
PrintEntryPointCommand(MachO::entry_point_command ep)9093 static void PrintEntryPointCommand(MachO::entry_point_command ep) {
9094   outs() << "       cmd LC_MAIN\n";
9095   outs() << "   cmdsize " << ep.cmdsize;
9096   if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
9097     outs() << " Incorrect size\n";
9098   else
9099     outs() << "\n";
9100   outs() << "  entryoff " << ep.entryoff << "\n";
9101   outs() << " stacksize " << ep.stacksize << "\n";
9102 }
9103 
PrintEncryptionInfoCommand(MachO::encryption_info_command ec,uint32_t object_size)9104 static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
9105                                        uint32_t object_size) {
9106   outs() << "          cmd LC_ENCRYPTION_INFO\n";
9107   outs() << "      cmdsize " << ec.cmdsize;
9108   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
9109     outs() << " Incorrect size\n";
9110   else
9111     outs() << "\n";
9112   outs() << "     cryptoff " << ec.cryptoff;
9113   if (ec.cryptoff > object_size)
9114     outs() << " (past end of file)\n";
9115   else
9116     outs() << "\n";
9117   outs() << "    cryptsize " << ec.cryptsize;
9118   if (ec.cryptsize > object_size)
9119     outs() << " (past end of file)\n";
9120   else
9121     outs() << "\n";
9122   outs() << "      cryptid " << ec.cryptid << "\n";
9123 }
9124 
PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,uint32_t object_size)9125 static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
9126                                          uint32_t object_size) {
9127   outs() << "          cmd LC_ENCRYPTION_INFO_64\n";
9128   outs() << "      cmdsize " << ec.cmdsize;
9129   if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
9130     outs() << " Incorrect size\n";
9131   else
9132     outs() << "\n";
9133   outs() << "     cryptoff " << ec.cryptoff;
9134   if (ec.cryptoff > object_size)
9135     outs() << " (past end of file)\n";
9136   else
9137     outs() << "\n";
9138   outs() << "    cryptsize " << ec.cryptsize;
9139   if (ec.cryptsize > object_size)
9140     outs() << " (past end of file)\n";
9141   else
9142     outs() << "\n";
9143   outs() << "      cryptid " << ec.cryptid << "\n";
9144   outs() << "          pad " << ec.pad << "\n";
9145 }
9146 
PrintLinkerOptionCommand(MachO::linker_option_command lo,const char * Ptr)9147 static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
9148                                      const char *Ptr) {
9149   outs() << "     cmd LC_LINKER_OPTION\n";
9150   outs() << " cmdsize " << lo.cmdsize;
9151   if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
9152     outs() << " Incorrect size\n";
9153   else
9154     outs() << "\n";
9155   outs() << "   count " << lo.count << "\n";
9156   const char *string = Ptr + sizeof(struct MachO::linker_option_command);
9157   uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
9158   uint32_t i = 0;
9159   while (left > 0) {
9160     while (*string == '\0' && left > 0) {
9161       string++;
9162       left--;
9163     }
9164     if (left > 0) {
9165       i++;
9166       outs() << "  string #" << i << " " << format("%.*s\n", left, string);
9167       uint32_t NullPos = StringRef(string, left).find('\0');
9168       uint32_t len = std::min(NullPos, left) + 1;
9169       string += len;
9170       left -= len;
9171     }
9172   }
9173   if (lo.count != i)
9174     outs() << "   count " << lo.count << " does not match number of strings "
9175            << i << "\n";
9176 }
9177 
PrintSubFrameworkCommand(MachO::sub_framework_command sub,const char * Ptr)9178 static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
9179                                      const char *Ptr) {
9180   outs() << "          cmd LC_SUB_FRAMEWORK\n";
9181   outs() << "      cmdsize " << sub.cmdsize;
9182   if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
9183     outs() << " Incorrect size\n";
9184   else
9185     outs() << "\n";
9186   if (sub.umbrella < sub.cmdsize) {
9187     const char *P = Ptr + sub.umbrella;
9188     outs() << "     umbrella " << P << " (offset " << sub.umbrella << ")\n";
9189   } else {
9190     outs() << "     umbrella ?(bad offset " << sub.umbrella << ")\n";
9191   }
9192 }
9193 
PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,const char * Ptr)9194 static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
9195                                     const char *Ptr) {
9196   outs() << "          cmd LC_SUB_UMBRELLA\n";
9197   outs() << "      cmdsize " << sub.cmdsize;
9198   if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
9199     outs() << " Incorrect size\n";
9200   else
9201     outs() << "\n";
9202   if (sub.sub_umbrella < sub.cmdsize) {
9203     const char *P = Ptr + sub.sub_umbrella;
9204     outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
9205   } else {
9206     outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
9207   }
9208 }
9209 
PrintSubLibraryCommand(MachO::sub_library_command sub,const char * Ptr)9210 static void PrintSubLibraryCommand(MachO::sub_library_command sub,
9211                                    const char *Ptr) {
9212   outs() << "          cmd LC_SUB_LIBRARY\n";
9213   outs() << "      cmdsize " << sub.cmdsize;
9214   if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
9215     outs() << " Incorrect size\n";
9216   else
9217     outs() << "\n";
9218   if (sub.sub_library < sub.cmdsize) {
9219     const char *P = Ptr + sub.sub_library;
9220     outs() << "  sub_library " << P << " (offset " << sub.sub_library << ")\n";
9221   } else {
9222     outs() << "  sub_library ?(bad offset " << sub.sub_library << ")\n";
9223   }
9224 }
9225 
PrintSubClientCommand(MachO::sub_client_command sub,const char * Ptr)9226 static void PrintSubClientCommand(MachO::sub_client_command sub,
9227                                   const char *Ptr) {
9228   outs() << "          cmd LC_SUB_CLIENT\n";
9229   outs() << "      cmdsize " << sub.cmdsize;
9230   if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
9231     outs() << " Incorrect size\n";
9232   else
9233     outs() << "\n";
9234   if (sub.client < sub.cmdsize) {
9235     const char *P = Ptr + sub.client;
9236     outs() << "       client " << P << " (offset " << sub.client << ")\n";
9237   } else {
9238     outs() << "       client ?(bad offset " << sub.client << ")\n";
9239   }
9240 }
9241 
PrintRoutinesCommand(MachO::routines_command r)9242 static void PrintRoutinesCommand(MachO::routines_command r) {
9243   outs() << "          cmd LC_ROUTINES\n";
9244   outs() << "      cmdsize " << r.cmdsize;
9245   if (r.cmdsize != sizeof(struct MachO::routines_command))
9246     outs() << " Incorrect size\n";
9247   else
9248     outs() << "\n";
9249   outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
9250   outs() << "  init_module " << r.init_module << "\n";
9251   outs() << "    reserved1 " << r.reserved1 << "\n";
9252   outs() << "    reserved2 " << r.reserved2 << "\n";
9253   outs() << "    reserved3 " << r.reserved3 << "\n";
9254   outs() << "    reserved4 " << r.reserved4 << "\n";
9255   outs() << "    reserved5 " << r.reserved5 << "\n";
9256   outs() << "    reserved6 " << r.reserved6 << "\n";
9257 }
9258 
PrintRoutinesCommand64(MachO::routines_command_64 r)9259 static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
9260   outs() << "          cmd LC_ROUTINES_64\n";
9261   outs() << "      cmdsize " << r.cmdsize;
9262   if (r.cmdsize != sizeof(struct MachO::routines_command_64))
9263     outs() << " Incorrect size\n";
9264   else
9265     outs() << "\n";
9266   outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
9267   outs() << "  init_module " << r.init_module << "\n";
9268   outs() << "    reserved1 " << r.reserved1 << "\n";
9269   outs() << "    reserved2 " << r.reserved2 << "\n";
9270   outs() << "    reserved3 " << r.reserved3 << "\n";
9271   outs() << "    reserved4 " << r.reserved4 << "\n";
9272   outs() << "    reserved5 " << r.reserved5 << "\n";
9273   outs() << "    reserved6 " << r.reserved6 << "\n";
9274 }
9275 
Print_x86_thread_state32_t(MachO::x86_thread_state32_t & cpu32)9276 static void Print_x86_thread_state32_t(MachO::x86_thread_state32_t &cpu32) {
9277   outs() << "\t    eax " << format("0x%08" PRIx32, cpu32.eax);
9278   outs() << " ebx    " << format("0x%08" PRIx32, cpu32.ebx);
9279   outs() << " ecx " << format("0x%08" PRIx32, cpu32.ecx);
9280   outs() << " edx " << format("0x%08" PRIx32, cpu32.edx) << "\n";
9281   outs() << "\t    edi " << format("0x%08" PRIx32, cpu32.edi);
9282   outs() << " esi    " << format("0x%08" PRIx32, cpu32.esi);
9283   outs() << " ebp " << format("0x%08" PRIx32, cpu32.ebp);
9284   outs() << " esp " << format("0x%08" PRIx32, cpu32.esp) << "\n";
9285   outs() << "\t    ss  " << format("0x%08" PRIx32, cpu32.ss);
9286   outs() << " eflags " << format("0x%08" PRIx32, cpu32.eflags);
9287   outs() << " eip " << format("0x%08" PRIx32, cpu32.eip);
9288   outs() << " cs  " << format("0x%08" PRIx32, cpu32.cs) << "\n";
9289   outs() << "\t    ds  " << format("0x%08" PRIx32, cpu32.ds);
9290   outs() << " es     " << format("0x%08" PRIx32, cpu32.es);
9291   outs() << " fs  " << format("0x%08" PRIx32, cpu32.fs);
9292   outs() << " gs  " << format("0x%08" PRIx32, cpu32.gs) << "\n";
9293 }
9294 
Print_x86_thread_state64_t(MachO::x86_thread_state64_t & cpu64)9295 static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
9296   outs() << "   rax  " << format("0x%016" PRIx64, cpu64.rax);
9297   outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
9298   outs() << " rcx  " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
9299   outs() << "   rdx  " << format("0x%016" PRIx64, cpu64.rdx);
9300   outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
9301   outs() << " rsi  " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
9302   outs() << "   rbp  " << format("0x%016" PRIx64, cpu64.rbp);
9303   outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
9304   outs() << " r8   " << format("0x%016" PRIx64, cpu64.r8) << "\n";
9305   outs() << "    r9  " << format("0x%016" PRIx64, cpu64.r9);
9306   outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
9307   outs() << " r11  " << format("0x%016" PRIx64, cpu64.r11) << "\n";
9308   outs() << "   r12  " << format("0x%016" PRIx64, cpu64.r12);
9309   outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
9310   outs() << " r14  " << format("0x%016" PRIx64, cpu64.r14) << "\n";
9311   outs() << "   r15  " << format("0x%016" PRIx64, cpu64.r15);
9312   outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
9313   outs() << "rflags  " << format("0x%016" PRIx64, cpu64.rflags);
9314   outs() << " cs  " << format("0x%016" PRIx64, cpu64.cs);
9315   outs() << " fs   " << format("0x%016" PRIx64, cpu64.fs) << "\n";
9316   outs() << "    gs  " << format("0x%016" PRIx64, cpu64.gs) << "\n";
9317 }
9318 
Print_mmst_reg(MachO::mmst_reg_t & r)9319 static void Print_mmst_reg(MachO::mmst_reg_t &r) {
9320   uint32_t f;
9321   outs() << "\t      mmst_reg  ";
9322   for (f = 0; f < 10; f++)
9323     outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
9324   outs() << "\n";
9325   outs() << "\t      mmst_rsrv ";
9326   for (f = 0; f < 6; f++)
9327     outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
9328   outs() << "\n";
9329 }
9330 
Print_xmm_reg(MachO::xmm_reg_t & r)9331 static void Print_xmm_reg(MachO::xmm_reg_t &r) {
9332   uint32_t f;
9333   outs() << "\t      xmm_reg ";
9334   for (f = 0; f < 16; f++)
9335     outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
9336   outs() << "\n";
9337 }
9338 
Print_x86_float_state_t(MachO::x86_float_state64_t & fpu)9339 static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
9340   outs() << "\t    fpu_reserved[0] " << fpu.fpu_reserved[0];
9341   outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
9342   outs() << "\t    control: invalid " << fpu.fpu_fcw.invalid;
9343   outs() << " denorm " << fpu.fpu_fcw.denorm;
9344   outs() << " zdiv " << fpu.fpu_fcw.zdiv;
9345   outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
9346   outs() << " undfl " << fpu.fpu_fcw.undfl;
9347   outs() << " precis " << fpu.fpu_fcw.precis << "\n";
9348   outs() << "\t\t     pc ";
9349   if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
9350     outs() << "FP_PREC_24B ";
9351   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
9352     outs() << "FP_PREC_53B ";
9353   else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
9354     outs() << "FP_PREC_64B ";
9355   else
9356     outs() << fpu.fpu_fcw.pc << " ";
9357   outs() << "rc ";
9358   if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
9359     outs() << "FP_RND_NEAR ";
9360   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
9361     outs() << "FP_RND_DOWN ";
9362   else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
9363     outs() << "FP_RND_UP ";
9364   else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
9365     outs() << "FP_CHOP ";
9366   outs() << "\n";
9367   outs() << "\t    status: invalid " << fpu.fpu_fsw.invalid;
9368   outs() << " denorm " << fpu.fpu_fsw.denorm;
9369   outs() << " zdiv " << fpu.fpu_fsw.zdiv;
9370   outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
9371   outs() << " undfl " << fpu.fpu_fsw.undfl;
9372   outs() << " precis " << fpu.fpu_fsw.precis;
9373   outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
9374   outs() << "\t            errsumm " << fpu.fpu_fsw.errsumm;
9375   outs() << " c0 " << fpu.fpu_fsw.c0;
9376   outs() << " c1 " << fpu.fpu_fsw.c1;
9377   outs() << " c2 " << fpu.fpu_fsw.c2;
9378   outs() << " tos " << fpu.fpu_fsw.tos;
9379   outs() << " c3 " << fpu.fpu_fsw.c3;
9380   outs() << " busy " << fpu.fpu_fsw.busy << "\n";
9381   outs() << "\t    fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
9382   outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
9383   outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
9384   outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
9385   outs() << "\t    fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
9386   outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
9387   outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
9388   outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
9389   outs() << "\t    fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
9390   outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
9391   outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
9392   outs() << "\n";
9393   outs() << "\t    fpu_stmm0:\n";
9394   Print_mmst_reg(fpu.fpu_stmm0);
9395   outs() << "\t    fpu_stmm1:\n";
9396   Print_mmst_reg(fpu.fpu_stmm1);
9397   outs() << "\t    fpu_stmm2:\n";
9398   Print_mmst_reg(fpu.fpu_stmm2);
9399   outs() << "\t    fpu_stmm3:\n";
9400   Print_mmst_reg(fpu.fpu_stmm3);
9401   outs() << "\t    fpu_stmm4:\n";
9402   Print_mmst_reg(fpu.fpu_stmm4);
9403   outs() << "\t    fpu_stmm5:\n";
9404   Print_mmst_reg(fpu.fpu_stmm5);
9405   outs() << "\t    fpu_stmm6:\n";
9406   Print_mmst_reg(fpu.fpu_stmm6);
9407   outs() << "\t    fpu_stmm7:\n";
9408   Print_mmst_reg(fpu.fpu_stmm7);
9409   outs() << "\t    fpu_xmm0:\n";
9410   Print_xmm_reg(fpu.fpu_xmm0);
9411   outs() << "\t    fpu_xmm1:\n";
9412   Print_xmm_reg(fpu.fpu_xmm1);
9413   outs() << "\t    fpu_xmm2:\n";
9414   Print_xmm_reg(fpu.fpu_xmm2);
9415   outs() << "\t    fpu_xmm3:\n";
9416   Print_xmm_reg(fpu.fpu_xmm3);
9417   outs() << "\t    fpu_xmm4:\n";
9418   Print_xmm_reg(fpu.fpu_xmm4);
9419   outs() << "\t    fpu_xmm5:\n";
9420   Print_xmm_reg(fpu.fpu_xmm5);
9421   outs() << "\t    fpu_xmm6:\n";
9422   Print_xmm_reg(fpu.fpu_xmm6);
9423   outs() << "\t    fpu_xmm7:\n";
9424   Print_xmm_reg(fpu.fpu_xmm7);
9425   outs() << "\t    fpu_xmm8:\n";
9426   Print_xmm_reg(fpu.fpu_xmm8);
9427   outs() << "\t    fpu_xmm9:\n";
9428   Print_xmm_reg(fpu.fpu_xmm9);
9429   outs() << "\t    fpu_xmm10:\n";
9430   Print_xmm_reg(fpu.fpu_xmm10);
9431   outs() << "\t    fpu_xmm11:\n";
9432   Print_xmm_reg(fpu.fpu_xmm11);
9433   outs() << "\t    fpu_xmm12:\n";
9434   Print_xmm_reg(fpu.fpu_xmm12);
9435   outs() << "\t    fpu_xmm13:\n";
9436   Print_xmm_reg(fpu.fpu_xmm13);
9437   outs() << "\t    fpu_xmm14:\n";
9438   Print_xmm_reg(fpu.fpu_xmm14);
9439   outs() << "\t    fpu_xmm15:\n";
9440   Print_xmm_reg(fpu.fpu_xmm15);
9441   outs() << "\t    fpu_rsrv4:\n";
9442   for (uint32_t f = 0; f < 6; f++) {
9443     outs() << "\t            ";
9444     for (uint32_t g = 0; g < 16; g++)
9445       outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
9446     outs() << "\n";
9447   }
9448   outs() << "\t    fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
9449   outs() << "\n";
9450 }
9451 
Print_x86_exception_state_t(MachO::x86_exception_state64_t & exc64)9452 static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
9453   outs() << "\t    trapno " << format("0x%08" PRIx32, exc64.trapno);
9454   outs() << " err " << format("0x%08" PRIx32, exc64.err);
9455   outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
9456 }
9457 
Print_arm_thread_state32_t(MachO::arm_thread_state32_t & cpu32)9458 static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
9459   outs() << "\t    r0  " << format("0x%08" PRIx32, cpu32.r[0]);
9460   outs() << " r1     "   << format("0x%08" PRIx32, cpu32.r[1]);
9461   outs() << " r2  "      << format("0x%08" PRIx32, cpu32.r[2]);
9462   outs() << " r3  "      << format("0x%08" PRIx32, cpu32.r[3]) << "\n";
9463   outs() << "\t    r4  " << format("0x%08" PRIx32, cpu32.r[4]);
9464   outs() << " r5     "   << format("0x%08" PRIx32, cpu32.r[5]);
9465   outs() << " r6  "      << format("0x%08" PRIx32, cpu32.r[6]);
9466   outs() << " r7  "      << format("0x%08" PRIx32, cpu32.r[7]) << "\n";
9467   outs() << "\t    r8  " << format("0x%08" PRIx32, cpu32.r[8]);
9468   outs() << " r9     "   << format("0x%08" PRIx32, cpu32.r[9]);
9469   outs() << " r10 "      << format("0x%08" PRIx32, cpu32.r[10]);
9470   outs() << " r11 "      << format("0x%08" PRIx32, cpu32.r[11]) << "\n";
9471   outs() << "\t    r12 " << format("0x%08" PRIx32, cpu32.r[12]);
9472   outs() << " sp     "   << format("0x%08" PRIx32, cpu32.sp);
9473   outs() << " lr  "      << format("0x%08" PRIx32, cpu32.lr);
9474   outs() << " pc  "      << format("0x%08" PRIx32, cpu32.pc) << "\n";
9475   outs() << "\t   cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n";
9476 }
9477 
Print_arm_thread_state64_t(MachO::arm_thread_state64_t & cpu64)9478 static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
9479   outs() << "\t    x0  " << format("0x%016" PRIx64, cpu64.x[0]);
9480   outs() << " x1  "      << format("0x%016" PRIx64, cpu64.x[1]);
9481   outs() << " x2  "      << format("0x%016" PRIx64, cpu64.x[2]) << "\n";
9482   outs() << "\t    x3  " << format("0x%016" PRIx64, cpu64.x[3]);
9483   outs() << " x4  "      << format("0x%016" PRIx64, cpu64.x[4]);
9484   outs() << " x5  "      << format("0x%016" PRIx64, cpu64.x[5]) << "\n";
9485   outs() << "\t    x6  " << format("0x%016" PRIx64, cpu64.x[6]);
9486   outs() << " x7  "      << format("0x%016" PRIx64, cpu64.x[7]);
9487   outs() << " x8  "      << format("0x%016" PRIx64, cpu64.x[8]) << "\n";
9488   outs() << "\t    x9  " << format("0x%016" PRIx64, cpu64.x[9]);
9489   outs() << " x10 "      << format("0x%016" PRIx64, cpu64.x[10]);
9490   outs() << " x11 "      << format("0x%016" PRIx64, cpu64.x[11]) << "\n";
9491   outs() << "\t    x12 " << format("0x%016" PRIx64, cpu64.x[12]);
9492   outs() << " x13 "      << format("0x%016" PRIx64, cpu64.x[13]);
9493   outs() << " x14 "      << format("0x%016" PRIx64, cpu64.x[14]) << "\n";
9494   outs() << "\t    x15 " << format("0x%016" PRIx64, cpu64.x[15]);
9495   outs() << " x16 "      << format("0x%016" PRIx64, cpu64.x[16]);
9496   outs() << " x17 "      << format("0x%016" PRIx64, cpu64.x[17]) << "\n";
9497   outs() << "\t    x18 " << format("0x%016" PRIx64, cpu64.x[18]);
9498   outs() << " x19 "      << format("0x%016" PRIx64, cpu64.x[19]);
9499   outs() << " x20 "      << format("0x%016" PRIx64, cpu64.x[20]) << "\n";
9500   outs() << "\t    x21 " << format("0x%016" PRIx64, cpu64.x[21]);
9501   outs() << " x22 "      << format("0x%016" PRIx64, cpu64.x[22]);
9502   outs() << " x23 "      << format("0x%016" PRIx64, cpu64.x[23]) << "\n";
9503   outs() << "\t    x24 " << format("0x%016" PRIx64, cpu64.x[24]);
9504   outs() << " x25 "      << format("0x%016" PRIx64, cpu64.x[25]);
9505   outs() << " x26 "      << format("0x%016" PRIx64, cpu64.x[26]) << "\n";
9506   outs() << "\t    x27 " << format("0x%016" PRIx64, cpu64.x[27]);
9507   outs() << " x28 "      << format("0x%016" PRIx64, cpu64.x[28]);
9508   outs() << "  fp "      << format("0x%016" PRIx64, cpu64.fp) << "\n";
9509   outs() << "\t     lr " << format("0x%016" PRIx64, cpu64.lr);
9510   outs() << " sp  "      << format("0x%016" PRIx64, cpu64.sp);
9511   outs() << "  pc "      << format("0x%016" PRIx64, cpu64.pc) << "\n";
9512   outs() << "\t   cpsr " << format("0x%08"  PRIx32, cpu64.cpsr) << "\n";
9513 }
9514 
PrintThreadCommand(MachO::thread_command t,const char * Ptr,bool isLittleEndian,uint32_t cputype)9515 static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
9516                                bool isLittleEndian, uint32_t cputype) {
9517   if (t.cmd == MachO::LC_THREAD)
9518     outs() << "        cmd LC_THREAD\n";
9519   else if (t.cmd == MachO::LC_UNIXTHREAD)
9520     outs() << "        cmd LC_UNIXTHREAD\n";
9521   else
9522     outs() << "        cmd " << t.cmd << " (unknown)\n";
9523   outs() << "    cmdsize " << t.cmdsize;
9524   if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
9525     outs() << " Incorrect size\n";
9526   else
9527     outs() << "\n";
9528 
9529   const char *begin = Ptr + sizeof(struct MachO::thread_command);
9530   const char *end = Ptr + t.cmdsize;
9531   uint32_t flavor, count, left;
9532   if (cputype == MachO::CPU_TYPE_I386) {
9533     while (begin < end) {
9534       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9535         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9536         begin += sizeof(uint32_t);
9537       } else {
9538         flavor = 0;
9539         begin = end;
9540       }
9541       if (isLittleEndian != sys::IsLittleEndianHost)
9542         sys::swapByteOrder(flavor);
9543       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9544         memcpy((char *)&count, begin, sizeof(uint32_t));
9545         begin += sizeof(uint32_t);
9546       } else {
9547         count = 0;
9548         begin = end;
9549       }
9550       if (isLittleEndian != sys::IsLittleEndianHost)
9551         sys::swapByteOrder(count);
9552       if (flavor == MachO::x86_THREAD_STATE32) {
9553         outs() << "     flavor i386_THREAD_STATE\n";
9554         if (count == MachO::x86_THREAD_STATE32_COUNT)
9555           outs() << "      count i386_THREAD_STATE_COUNT\n";
9556         else
9557           outs() << "      count " << count
9558                  << " (not x86_THREAD_STATE32_COUNT)\n";
9559         MachO::x86_thread_state32_t cpu32;
9560         left = end - begin;
9561         if (left >= sizeof(MachO::x86_thread_state32_t)) {
9562           memcpy(&cpu32, begin, sizeof(MachO::x86_thread_state32_t));
9563           begin += sizeof(MachO::x86_thread_state32_t);
9564         } else {
9565           memset(&cpu32, '\0', sizeof(MachO::x86_thread_state32_t));
9566           memcpy(&cpu32, begin, left);
9567           begin += left;
9568         }
9569         if (isLittleEndian != sys::IsLittleEndianHost)
9570           swapStruct(cpu32);
9571         Print_x86_thread_state32_t(cpu32);
9572       } else if (flavor == MachO::x86_THREAD_STATE) {
9573         outs() << "     flavor x86_THREAD_STATE\n";
9574         if (count == MachO::x86_THREAD_STATE_COUNT)
9575           outs() << "      count x86_THREAD_STATE_COUNT\n";
9576         else
9577           outs() << "      count " << count
9578                  << " (not x86_THREAD_STATE_COUNT)\n";
9579         struct MachO::x86_thread_state_t ts;
9580         left = end - begin;
9581         if (left >= sizeof(MachO::x86_thread_state_t)) {
9582           memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9583           begin += sizeof(MachO::x86_thread_state_t);
9584         } else {
9585           memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9586           memcpy(&ts, begin, left);
9587           begin += left;
9588         }
9589         if (isLittleEndian != sys::IsLittleEndianHost)
9590           swapStruct(ts);
9591         if (ts.tsh.flavor == MachO::x86_THREAD_STATE32) {
9592           outs() << "\t    tsh.flavor x86_THREAD_STATE32 ";
9593           if (ts.tsh.count == MachO::x86_THREAD_STATE32_COUNT)
9594             outs() << "tsh.count x86_THREAD_STATE32_COUNT\n";
9595           else
9596             outs() << "tsh.count " << ts.tsh.count
9597                    << " (not x86_THREAD_STATE32_COUNT\n";
9598           Print_x86_thread_state32_t(ts.uts.ts32);
9599         } else {
9600           outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9601                  << ts.tsh.count << "\n";
9602         }
9603       } else {
9604         outs() << "     flavor " << flavor << " (unknown)\n";
9605         outs() << "      count " << count << "\n";
9606         outs() << "      state (unknown)\n";
9607         begin += count * sizeof(uint32_t);
9608       }
9609     }
9610   } else if (cputype == MachO::CPU_TYPE_X86_64) {
9611     while (begin < end) {
9612       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9613         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9614         begin += sizeof(uint32_t);
9615       } else {
9616         flavor = 0;
9617         begin = end;
9618       }
9619       if (isLittleEndian != sys::IsLittleEndianHost)
9620         sys::swapByteOrder(flavor);
9621       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9622         memcpy((char *)&count, begin, sizeof(uint32_t));
9623         begin += sizeof(uint32_t);
9624       } else {
9625         count = 0;
9626         begin = end;
9627       }
9628       if (isLittleEndian != sys::IsLittleEndianHost)
9629         sys::swapByteOrder(count);
9630       if (flavor == MachO::x86_THREAD_STATE64) {
9631         outs() << "     flavor x86_THREAD_STATE64\n";
9632         if (count == MachO::x86_THREAD_STATE64_COUNT)
9633           outs() << "      count x86_THREAD_STATE64_COUNT\n";
9634         else
9635           outs() << "      count " << count
9636                  << " (not x86_THREAD_STATE64_COUNT)\n";
9637         MachO::x86_thread_state64_t cpu64;
9638         left = end - begin;
9639         if (left >= sizeof(MachO::x86_thread_state64_t)) {
9640           memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
9641           begin += sizeof(MachO::x86_thread_state64_t);
9642         } else {
9643           memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
9644           memcpy(&cpu64, begin, left);
9645           begin += left;
9646         }
9647         if (isLittleEndian != sys::IsLittleEndianHost)
9648           swapStruct(cpu64);
9649         Print_x86_thread_state64_t(cpu64);
9650       } else if (flavor == MachO::x86_THREAD_STATE) {
9651         outs() << "     flavor x86_THREAD_STATE\n";
9652         if (count == MachO::x86_THREAD_STATE_COUNT)
9653           outs() << "      count x86_THREAD_STATE_COUNT\n";
9654         else
9655           outs() << "      count " << count
9656                  << " (not x86_THREAD_STATE_COUNT)\n";
9657         struct MachO::x86_thread_state_t ts;
9658         left = end - begin;
9659         if (left >= sizeof(MachO::x86_thread_state_t)) {
9660           memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
9661           begin += sizeof(MachO::x86_thread_state_t);
9662         } else {
9663           memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
9664           memcpy(&ts, begin, left);
9665           begin += left;
9666         }
9667         if (isLittleEndian != sys::IsLittleEndianHost)
9668           swapStruct(ts);
9669         if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
9670           outs() << "\t    tsh.flavor x86_THREAD_STATE64 ";
9671           if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
9672             outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
9673           else
9674             outs() << "tsh.count " << ts.tsh.count
9675                    << " (not x86_THREAD_STATE64_COUNT\n";
9676           Print_x86_thread_state64_t(ts.uts.ts64);
9677         } else {
9678           outs() << "\t    tsh.flavor " << ts.tsh.flavor << "  tsh.count "
9679                  << ts.tsh.count << "\n";
9680         }
9681       } else if (flavor == MachO::x86_FLOAT_STATE) {
9682         outs() << "     flavor x86_FLOAT_STATE\n";
9683         if (count == MachO::x86_FLOAT_STATE_COUNT)
9684           outs() << "      count x86_FLOAT_STATE_COUNT\n";
9685         else
9686           outs() << "      count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
9687         struct MachO::x86_float_state_t fs;
9688         left = end - begin;
9689         if (left >= sizeof(MachO::x86_float_state_t)) {
9690           memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
9691           begin += sizeof(MachO::x86_float_state_t);
9692         } else {
9693           memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
9694           memcpy(&fs, begin, left);
9695           begin += left;
9696         }
9697         if (isLittleEndian != sys::IsLittleEndianHost)
9698           swapStruct(fs);
9699         if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
9700           outs() << "\t    fsh.flavor x86_FLOAT_STATE64 ";
9701           if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
9702             outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
9703           else
9704             outs() << "fsh.count " << fs.fsh.count
9705                    << " (not x86_FLOAT_STATE64_COUNT\n";
9706           Print_x86_float_state_t(fs.ufs.fs64);
9707         } else {
9708           outs() << "\t    fsh.flavor " << fs.fsh.flavor << "  fsh.count "
9709                  << fs.fsh.count << "\n";
9710         }
9711       } else if (flavor == MachO::x86_EXCEPTION_STATE) {
9712         outs() << "     flavor x86_EXCEPTION_STATE\n";
9713         if (count == MachO::x86_EXCEPTION_STATE_COUNT)
9714           outs() << "      count x86_EXCEPTION_STATE_COUNT\n";
9715         else
9716           outs() << "      count " << count
9717                  << " (not x86_EXCEPTION_STATE_COUNT)\n";
9718         struct MachO::x86_exception_state_t es;
9719         left = end - begin;
9720         if (left >= sizeof(MachO::x86_exception_state_t)) {
9721           memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
9722           begin += sizeof(MachO::x86_exception_state_t);
9723         } else {
9724           memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
9725           memcpy(&es, begin, left);
9726           begin += left;
9727         }
9728         if (isLittleEndian != sys::IsLittleEndianHost)
9729           swapStruct(es);
9730         if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
9731           outs() << "\t    esh.flavor x86_EXCEPTION_STATE64\n";
9732           if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
9733             outs() << "\t    esh.count x86_EXCEPTION_STATE64_COUNT\n";
9734           else
9735             outs() << "\t    esh.count " << es.esh.count
9736                    << " (not x86_EXCEPTION_STATE64_COUNT\n";
9737           Print_x86_exception_state_t(es.ues.es64);
9738         } else {
9739           outs() << "\t    esh.flavor " << es.esh.flavor << "  esh.count "
9740                  << es.esh.count << "\n";
9741         }
9742       } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
9743         outs() << "     flavor x86_EXCEPTION_STATE64\n";
9744         if (count == MachO::x86_EXCEPTION_STATE64_COUNT)
9745           outs() << "      count x86_EXCEPTION_STATE64_COUNT\n";
9746         else
9747           outs() << "      count " << count
9748                  << " (not x86_EXCEPTION_STATE64_COUNT)\n";
9749         struct MachO::x86_exception_state64_t es64;
9750         left = end - begin;
9751         if (left >= sizeof(MachO::x86_exception_state64_t)) {
9752           memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t));
9753           begin += sizeof(MachO::x86_exception_state64_t);
9754         } else {
9755           memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t));
9756           memcpy(&es64, begin, left);
9757           begin += left;
9758         }
9759         if (isLittleEndian != sys::IsLittleEndianHost)
9760           swapStruct(es64);
9761         Print_x86_exception_state_t(es64);
9762       } else {
9763         outs() << "     flavor " << flavor << " (unknown)\n";
9764         outs() << "      count " << count << "\n";
9765         outs() << "      state (unknown)\n";
9766         begin += count * sizeof(uint32_t);
9767       }
9768     }
9769   } else if (cputype == MachO::CPU_TYPE_ARM) {
9770     while (begin < end) {
9771       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9772         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9773         begin += sizeof(uint32_t);
9774       } else {
9775         flavor = 0;
9776         begin = end;
9777       }
9778       if (isLittleEndian != sys::IsLittleEndianHost)
9779         sys::swapByteOrder(flavor);
9780       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9781         memcpy((char *)&count, begin, sizeof(uint32_t));
9782         begin += sizeof(uint32_t);
9783       } else {
9784         count = 0;
9785         begin = end;
9786       }
9787       if (isLittleEndian != sys::IsLittleEndianHost)
9788         sys::swapByteOrder(count);
9789       if (flavor == MachO::ARM_THREAD_STATE) {
9790         outs() << "     flavor ARM_THREAD_STATE\n";
9791         if (count == MachO::ARM_THREAD_STATE_COUNT)
9792           outs() << "      count ARM_THREAD_STATE_COUNT\n";
9793         else
9794           outs() << "      count " << count
9795                  << " (not ARM_THREAD_STATE_COUNT)\n";
9796         MachO::arm_thread_state32_t cpu32;
9797         left = end - begin;
9798         if (left >= sizeof(MachO::arm_thread_state32_t)) {
9799           memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t));
9800           begin += sizeof(MachO::arm_thread_state32_t);
9801         } else {
9802           memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t));
9803           memcpy(&cpu32, begin, left);
9804           begin += left;
9805         }
9806         if (isLittleEndian != sys::IsLittleEndianHost)
9807           swapStruct(cpu32);
9808         Print_arm_thread_state32_t(cpu32);
9809       } else {
9810         outs() << "     flavor " << flavor << " (unknown)\n";
9811         outs() << "      count " << count << "\n";
9812         outs() << "      state (unknown)\n";
9813         begin += count * sizeof(uint32_t);
9814       }
9815     }
9816   } else if (cputype == MachO::CPU_TYPE_ARM64 ||
9817              cputype == MachO::CPU_TYPE_ARM64_32) {
9818     while (begin < end) {
9819       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9820         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9821         begin += sizeof(uint32_t);
9822       } else {
9823         flavor = 0;
9824         begin = end;
9825       }
9826       if (isLittleEndian != sys::IsLittleEndianHost)
9827         sys::swapByteOrder(flavor);
9828       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9829         memcpy((char *)&count, begin, sizeof(uint32_t));
9830         begin += sizeof(uint32_t);
9831       } else {
9832         count = 0;
9833         begin = end;
9834       }
9835       if (isLittleEndian != sys::IsLittleEndianHost)
9836         sys::swapByteOrder(count);
9837       if (flavor == MachO::ARM_THREAD_STATE64) {
9838         outs() << "     flavor ARM_THREAD_STATE64\n";
9839         if (count == MachO::ARM_THREAD_STATE64_COUNT)
9840           outs() << "      count ARM_THREAD_STATE64_COUNT\n";
9841         else
9842           outs() << "      count " << count
9843                  << " (not ARM_THREAD_STATE64_COUNT)\n";
9844         MachO::arm_thread_state64_t cpu64;
9845         left = end - begin;
9846         if (left >= sizeof(MachO::arm_thread_state64_t)) {
9847           memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
9848           begin += sizeof(MachO::arm_thread_state64_t);
9849         } else {
9850           memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
9851           memcpy(&cpu64, begin, left);
9852           begin += left;
9853         }
9854         if (isLittleEndian != sys::IsLittleEndianHost)
9855           swapStruct(cpu64);
9856         Print_arm_thread_state64_t(cpu64);
9857       } else {
9858         outs() << "     flavor " << flavor << " (unknown)\n";
9859         outs() << "      count " << count << "\n";
9860         outs() << "      state (unknown)\n";
9861         begin += count * sizeof(uint32_t);
9862       }
9863     }
9864   } else {
9865     while (begin < end) {
9866       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9867         memcpy((char *)&flavor, begin, sizeof(uint32_t));
9868         begin += sizeof(uint32_t);
9869       } else {
9870         flavor = 0;
9871         begin = end;
9872       }
9873       if (isLittleEndian != sys::IsLittleEndianHost)
9874         sys::swapByteOrder(flavor);
9875       if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
9876         memcpy((char *)&count, begin, sizeof(uint32_t));
9877         begin += sizeof(uint32_t);
9878       } else {
9879         count = 0;
9880         begin = end;
9881       }
9882       if (isLittleEndian != sys::IsLittleEndianHost)
9883         sys::swapByteOrder(count);
9884       outs() << "     flavor " << flavor << "\n";
9885       outs() << "      count " << count << "\n";
9886       outs() << "      state (Unknown cputype/cpusubtype)\n";
9887       begin += count * sizeof(uint32_t);
9888     }
9889   }
9890 }
9891 
PrintDylibCommand(MachO::dylib_command dl,const char * Ptr)9892 static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
9893   if (dl.cmd == MachO::LC_ID_DYLIB)
9894     outs() << "          cmd LC_ID_DYLIB\n";
9895   else if (dl.cmd == MachO::LC_LOAD_DYLIB)
9896     outs() << "          cmd LC_LOAD_DYLIB\n";
9897   else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
9898     outs() << "          cmd LC_LOAD_WEAK_DYLIB\n";
9899   else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
9900     outs() << "          cmd LC_REEXPORT_DYLIB\n";
9901   else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
9902     outs() << "          cmd LC_LAZY_LOAD_DYLIB\n";
9903   else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
9904     outs() << "          cmd LC_LOAD_UPWARD_DYLIB\n";
9905   else
9906     outs() << "          cmd " << dl.cmd << " (unknown)\n";
9907   outs() << "      cmdsize " << dl.cmdsize;
9908   if (dl.cmdsize < sizeof(struct MachO::dylib_command))
9909     outs() << " Incorrect size\n";
9910   else
9911     outs() << "\n";
9912   if (dl.dylib.name < dl.cmdsize) {
9913     const char *P = (const char *)(Ptr) + dl.dylib.name;
9914     outs() << "         name " << P << " (offset " << dl.dylib.name << ")\n";
9915   } else {
9916     outs() << "         name ?(bad offset " << dl.dylib.name << ")\n";
9917   }
9918   outs() << "   time stamp " << dl.dylib.timestamp << " ";
9919   time_t t = dl.dylib.timestamp;
9920   outs() << ctime(&t);
9921   outs() << "      current version ";
9922   if (dl.dylib.current_version == 0xffffffff)
9923     outs() << "n/a\n";
9924   else
9925     outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
9926            << ((dl.dylib.current_version >> 8) & 0xff) << "."
9927            << (dl.dylib.current_version & 0xff) << "\n";
9928   outs() << "compatibility version ";
9929   if (dl.dylib.compatibility_version == 0xffffffff)
9930     outs() << "n/a\n";
9931   else
9932     outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
9933            << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
9934            << (dl.dylib.compatibility_version & 0xff) << "\n";
9935 }
9936 
PrintLinkEditDataCommand(MachO::linkedit_data_command ld,uint32_t object_size)9937 static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
9938                                      uint32_t object_size) {
9939   if (ld.cmd == MachO::LC_CODE_SIGNATURE)
9940     outs() << "      cmd LC_CODE_SIGNATURE\n";
9941   else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
9942     outs() << "      cmd LC_SEGMENT_SPLIT_INFO\n";
9943   else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
9944     outs() << "      cmd LC_FUNCTION_STARTS\n";
9945   else if (ld.cmd == MachO::LC_DATA_IN_CODE)
9946     outs() << "      cmd LC_DATA_IN_CODE\n";
9947   else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
9948     outs() << "      cmd LC_DYLIB_CODE_SIGN_DRS\n";
9949   else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
9950     outs() << "      cmd LC_LINKER_OPTIMIZATION_HINT\n";
9951   else if (ld.cmd == MachO::LC_DYLD_EXPORTS_TRIE)
9952     outs() << "      cmd LC_DYLD_EXPORTS_TRIE\n";
9953   else if (ld.cmd == MachO::LC_DYLD_CHAINED_FIXUPS)
9954     outs() << "      cmd LC_DYLD_CHAINED_FIXUPS\n";
9955   else if (ld.cmd == MachO::LC_ATOM_INFO)
9956     outs() << "      cmd LC_ATOM_INFO\n";
9957   else
9958     outs() << "      cmd " << ld.cmd << " (?)\n";
9959   outs() << "  cmdsize " << ld.cmdsize;
9960   if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
9961     outs() << " Incorrect size\n";
9962   else
9963     outs() << "\n";
9964   outs() << "  dataoff " << ld.dataoff;
9965   if (ld.dataoff > object_size)
9966     outs() << " (past end of file)\n";
9967   else
9968     outs() << "\n";
9969   outs() << " datasize " << ld.datasize;
9970   uint64_t big_size = ld.dataoff;
9971   big_size += ld.datasize;
9972   if (big_size > object_size)
9973     outs() << " (past end of file)\n";
9974   else
9975     outs() << "\n";
9976 }
9977 
PrintLoadCommands(const MachOObjectFile * Obj,uint32_t filetype,uint32_t cputype,bool verbose)9978 static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
9979                               uint32_t cputype, bool verbose) {
9980   StringRef Buf = Obj->getData();
9981   unsigned Index = 0;
9982   for (const auto &Command : Obj->load_commands()) {
9983     outs() << "Load command " << Index++ << "\n";
9984     if (Command.C.cmd == MachO::LC_SEGMENT) {
9985       MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
9986       const char *sg_segname = SLC.segname;
9987       PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
9988                           SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
9989                           SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
9990                           verbose);
9991       for (unsigned j = 0; j < SLC.nsects; j++) {
9992         MachO::section S = Obj->getSection(Command, j);
9993         PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
9994                      S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
9995                      SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
9996       }
9997     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
9998       MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
9999       const char *sg_segname = SLC_64.segname;
10000       PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
10001                           SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
10002                           SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
10003                           SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
10004       for (unsigned j = 0; j < SLC_64.nsects; j++) {
10005         MachO::section_64 S_64 = Obj->getSection64(Command, j);
10006         PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
10007                      S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
10008                      S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
10009                      sg_segname, filetype, Buf.size(), verbose);
10010       }
10011     } else if (Command.C.cmd == MachO::LC_SYMTAB) {
10012       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10013       PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
10014     } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
10015       MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
10016       MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
10017       PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
10018                                Obj->is64Bit());
10019     } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
10020                Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
10021       MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
10022       PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
10023     } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
10024                Command.C.cmd == MachO::LC_ID_DYLINKER ||
10025                Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
10026       MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
10027       PrintDyldLoadCommand(Dyld, Command.Ptr);
10028     } else if (Command.C.cmd == MachO::LC_UUID) {
10029       MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
10030       PrintUuidLoadCommand(Uuid);
10031     } else if (Command.C.cmd == MachO::LC_RPATH) {
10032       MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
10033       PrintRpathLoadCommand(Rpath, Command.Ptr);
10034     } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
10035                Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
10036                Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
10037                Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
10038       MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
10039       PrintVersionMinLoadCommand(Vd);
10040     } else if (Command.C.cmd == MachO::LC_NOTE) {
10041       MachO::note_command Nt = Obj->getNoteLoadCommand(Command);
10042       PrintNoteLoadCommand(Nt);
10043     } else if (Command.C.cmd == MachO::LC_BUILD_VERSION) {
10044       MachO::build_version_command Bv =
10045           Obj->getBuildVersionLoadCommand(Command);
10046       PrintBuildVersionLoadCommand(Obj, Bv, verbose);
10047     } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
10048       MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
10049       PrintSourceVersionCommand(Sd);
10050     } else if (Command.C.cmd == MachO::LC_MAIN) {
10051       MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
10052       PrintEntryPointCommand(Ep);
10053     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
10054       MachO::encryption_info_command Ei =
10055           Obj->getEncryptionInfoCommand(Command);
10056       PrintEncryptionInfoCommand(Ei, Buf.size());
10057     } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
10058       MachO::encryption_info_command_64 Ei =
10059           Obj->getEncryptionInfoCommand64(Command);
10060       PrintEncryptionInfoCommand64(Ei, Buf.size());
10061     } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
10062       MachO::linker_option_command Lo =
10063           Obj->getLinkerOptionLoadCommand(Command);
10064       PrintLinkerOptionCommand(Lo, Command.Ptr);
10065     } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
10066       MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
10067       PrintSubFrameworkCommand(Sf, Command.Ptr);
10068     } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
10069       MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
10070       PrintSubUmbrellaCommand(Sf, Command.Ptr);
10071     } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
10072       MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
10073       PrintSubLibraryCommand(Sl, Command.Ptr);
10074     } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
10075       MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
10076       PrintSubClientCommand(Sc, Command.Ptr);
10077     } else if (Command.C.cmd == MachO::LC_ROUTINES) {
10078       MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
10079       PrintRoutinesCommand(Rc);
10080     } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
10081       MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
10082       PrintRoutinesCommand64(Rc);
10083     } else if (Command.C.cmd == MachO::LC_THREAD ||
10084                Command.C.cmd == MachO::LC_UNIXTHREAD) {
10085       MachO::thread_command Tc = Obj->getThreadCommand(Command);
10086       PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
10087     } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
10088                Command.C.cmd == MachO::LC_ID_DYLIB ||
10089                Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
10090                Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
10091                Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
10092                Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
10093       MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
10094       PrintDylibCommand(Dl, Command.Ptr);
10095     } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
10096                Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
10097                Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
10098                Command.C.cmd == MachO::LC_DATA_IN_CODE ||
10099                Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
10100                Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT ||
10101                Command.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE ||
10102                Command.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS ||
10103                Command.C.cmd == MachO::LC_ATOM_INFO) {
10104       MachO::linkedit_data_command Ld =
10105           Obj->getLinkeditDataLoadCommand(Command);
10106       PrintLinkEditDataCommand(Ld, Buf.size());
10107     } else {
10108       outs() << "      cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
10109              << ")\n";
10110       outs() << "  cmdsize " << Command.C.cmdsize << "\n";
10111       // TODO: get and print the raw bytes of the load command.
10112     }
10113     // TODO: print all the other kinds of load commands.
10114   }
10115 }
10116 
PrintMachHeader(const MachOObjectFile * Obj,bool verbose)10117 static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
10118   if (Obj->is64Bit()) {
10119     MachO::mach_header_64 H_64;
10120     H_64 = Obj->getHeader64();
10121     PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
10122                     H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
10123   } else {
10124     MachO::mach_header H;
10125     H = Obj->getHeader();
10126     PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
10127                     H.sizeofcmds, H.flags, verbose);
10128   }
10129 }
10130 
printMachOFileHeader(const object::ObjectFile * Obj)10131 void objdump::printMachOFileHeader(const object::ObjectFile *Obj) {
10132   const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10133   PrintMachHeader(file, Verbose);
10134 }
10135 
printPrivateHeaders()10136 void MachODumper::printPrivateHeaders() {
10137   printMachOFileHeader(&Obj);
10138   if (!FirstPrivateHeader)
10139     printMachOLoadCommands(&Obj);
10140 }
10141 
printMachOLoadCommands(const object::ObjectFile * Obj)10142 void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) {
10143   const MachOObjectFile *file = cast<const MachOObjectFile>(Obj);
10144   uint32_t filetype = 0;
10145   uint32_t cputype = 0;
10146   if (file->is64Bit()) {
10147     MachO::mach_header_64 H_64;
10148     H_64 = file->getHeader64();
10149     filetype = H_64.filetype;
10150     cputype = H_64.cputype;
10151   } else {
10152     MachO::mach_header H;
10153     H = file->getHeader();
10154     filetype = H.filetype;
10155     cputype = H.cputype;
10156   }
10157   PrintLoadCommands(file, filetype, cputype, Verbose);
10158 }
10159 
10160 //===----------------------------------------------------------------------===//
10161 // export trie dumping
10162 //===----------------------------------------------------------------------===//
10163 
printMachOExportsTrie(const object::MachOObjectFile * Obj)10164 static void printMachOExportsTrie(const object::MachOObjectFile *Obj) {
10165   uint64_t BaseSegmentAddress = 0;
10166   for (const auto &Command : Obj->load_commands()) {
10167     if (Command.C.cmd == MachO::LC_SEGMENT) {
10168       MachO::segment_command Seg = Obj->getSegmentLoadCommand(Command);
10169       if (Seg.fileoff == 0 && Seg.filesize != 0) {
10170         BaseSegmentAddress = Seg.vmaddr;
10171         break;
10172       }
10173     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
10174       MachO::segment_command_64 Seg = Obj->getSegment64LoadCommand(Command);
10175       if (Seg.fileoff == 0 && Seg.filesize != 0) {
10176         BaseSegmentAddress = Seg.vmaddr;
10177         break;
10178       }
10179     }
10180   }
10181   Error Err = Error::success();
10182   for (const object::ExportEntry &Entry : Obj->exports(Err)) {
10183     uint64_t Flags = Entry.flags();
10184     bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
10185     bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
10186     bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10187                         MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
10188     bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
10189                 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
10190     bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
10191     if (ReExport)
10192       outs() << "[re-export] ";
10193     else
10194       outs() << format("0x%08llX  ",
10195                        Entry.address() + BaseSegmentAddress);
10196     outs() << Entry.name();
10197     if (WeakDef || ThreadLocal || Resolver || Abs) {
10198       ListSeparator LS;
10199       outs() << " [";
10200       if (WeakDef)
10201         outs() << LS << "weak_def";
10202       if (ThreadLocal)
10203         outs() << LS << "per-thread";
10204       if (Abs)
10205         outs() << LS << "absolute";
10206       if (Resolver)
10207         outs() << LS << format("resolver=0x%08llX", Entry.other());
10208       outs() << "]";
10209     }
10210     if (ReExport) {
10211       StringRef DylibName = "unknown";
10212       int Ordinal = Entry.other() - 1;
10213       Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
10214       if (Entry.otherName().empty())
10215         outs() << " (from " << DylibName << ")";
10216       else
10217         outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
10218     }
10219     outs() << "\n";
10220   }
10221   if (Err)
10222     reportError(std::move(Err), Obj->getFileName());
10223 }
10224 
10225 //===----------------------------------------------------------------------===//
10226 // rebase table dumping
10227 //===----------------------------------------------------------------------===//
10228 
printMachORebaseTable(object::MachOObjectFile * Obj)10229 static void printMachORebaseTable(object::MachOObjectFile *Obj) {
10230   outs() << "segment  section            address     type\n";
10231   Error Err = Error::success();
10232   for (const object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) {
10233     StringRef SegmentName = Entry.segmentName();
10234     StringRef SectionName = Entry.sectionName();
10235     uint64_t Address = Entry.address();
10236 
10237     // Table lines look like: __DATA  __nl_symbol_ptr  0x0000F00C  pointer
10238     outs() << format("%-8s %-18s 0x%08" PRIX64 "  %s\n",
10239                      SegmentName.str().c_str(), SectionName.str().c_str(),
10240                      Address, Entry.typeName().str().c_str());
10241   }
10242   if (Err)
10243     reportError(std::move(Err), Obj->getFileName());
10244 }
10245 
ordinalName(const object::MachOObjectFile * Obj,int Ordinal)10246 static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
10247   StringRef DylibName;
10248   switch (Ordinal) {
10249   case MachO::BIND_SPECIAL_DYLIB_SELF:
10250     return "this-image";
10251   case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
10252     return "main-executable";
10253   case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
10254     return "flat-namespace";
10255   case MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP:
10256     return "weak";
10257   default:
10258     if (Ordinal > 0) {
10259       std::error_code EC =
10260           Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
10261       if (EC)
10262         return "<<bad library ordinal>>";
10263       return DylibName;
10264     }
10265   }
10266   return "<<unknown special ordinal>>";
10267 }
10268 
10269 //===----------------------------------------------------------------------===//
10270 // bind table dumping
10271 //===----------------------------------------------------------------------===//
10272 
printMachOBindTable(object::MachOObjectFile * Obj)10273 static void printMachOBindTable(object::MachOObjectFile *Obj) {
10274   // Build table of sections so names can used in final output.
10275   outs() << "segment  section            address    type       "
10276             "addend dylib            symbol\n";
10277   Error Err = Error::success();
10278   for (const object::MachOBindEntry &Entry : Obj->bindTable(Err)) {
10279     StringRef SegmentName = Entry.segmentName();
10280     StringRef SectionName = Entry.sectionName();
10281     uint64_t Address = Entry.address();
10282 
10283     // Table lines look like:
10284     //  __DATA  __got  0x00012010    pointer   0 libSystem ___stack_chk_guard
10285     StringRef Attr;
10286     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
10287       Attr = " (weak_import)";
10288     outs() << left_justify(SegmentName, 8) << " "
10289            << left_justify(SectionName, 18) << " "
10290            << format_hex(Address, 10, true) << " "
10291            << left_justify(Entry.typeName(), 8) << " "
10292            << format_decimal(Entry.addend(), 8) << " "
10293            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10294            << Entry.symbolName() << Attr << "\n";
10295   }
10296   if (Err)
10297     reportError(std::move(Err), Obj->getFileName());
10298 }
10299 
10300 //===----------------------------------------------------------------------===//
10301 // lazy bind table dumping
10302 //===----------------------------------------------------------------------===//
10303 
printMachOLazyBindTable(object::MachOObjectFile * Obj)10304 static void printMachOLazyBindTable(object::MachOObjectFile *Obj) {
10305   outs() << "segment  section            address     "
10306             "dylib            symbol\n";
10307   Error Err = Error::success();
10308   for (const object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) {
10309     StringRef SegmentName = Entry.segmentName();
10310     StringRef SectionName = Entry.sectionName();
10311     uint64_t Address = Entry.address();
10312 
10313     // Table lines look like:
10314     //  __DATA  __got  0x00012010 libSystem ___stack_chk_guard
10315     outs() << left_justify(SegmentName, 8) << " "
10316            << left_justify(SectionName, 18) << " "
10317            << format_hex(Address, 10, true) << " "
10318            << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
10319            << Entry.symbolName() << "\n";
10320   }
10321   if (Err)
10322     reportError(std::move(Err), Obj->getFileName());
10323 }
10324 
10325 //===----------------------------------------------------------------------===//
10326 // weak bind table dumping
10327 //===----------------------------------------------------------------------===//
10328 
printMachOWeakBindTable(object::MachOObjectFile * Obj)10329 static void printMachOWeakBindTable(object::MachOObjectFile *Obj) {
10330   outs() << "segment  section            address     "
10331             "type       addend   symbol\n";
10332   Error Err = Error::success();
10333   for (const object::MachOBindEntry &Entry : Obj->weakBindTable(Err)) {
10334     // Strong symbols don't have a location to update.
10335     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
10336       outs() << "                                        strong              "
10337              << Entry.symbolName() << "\n";
10338       continue;
10339     }
10340     StringRef SegmentName = Entry.segmentName();
10341     StringRef SectionName = Entry.sectionName();
10342     uint64_t Address = Entry.address();
10343 
10344     // Table lines look like:
10345     // __DATA  __data  0x00001000  pointer    0   _foo
10346     outs() << left_justify(SegmentName, 8) << " "
10347            << left_justify(SectionName, 18) << " "
10348            << format_hex(Address, 10, true) << " "
10349            << left_justify(Entry.typeName(), 8) << " "
10350            << format_decimal(Entry.addend(), 8) << "   " << Entry.symbolName()
10351            << "\n";
10352   }
10353   if (Err)
10354     reportError(std::move(Err), Obj->getFileName());
10355 }
10356 
10357 // get_dyld_bind_info_symbolname() is used for disassembly and passed an
10358 // address, ReferenceValue, in the Mach-O file and looks in the dyld bind
10359 // information for that address. If the address is found its binding symbol
10360 // name is returned.  If not nullptr is returned.
get_dyld_bind_info_symbolname(uint64_t ReferenceValue,struct DisassembleInfo * info)10361 static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
10362                                                  struct DisassembleInfo *info) {
10363   if (info->bindtable == nullptr) {
10364     info->bindtable = std::make_unique<SymbolAddressMap>();
10365     Error Err = Error::success();
10366     for (const object::MachOBindEntry &Entry : info->O->bindTable(Err)) {
10367       uint64_t Address = Entry.address();
10368       StringRef name = Entry.symbolName();
10369       if (!name.empty())
10370         (*info->bindtable)[Address] = name;
10371     }
10372     if (Err)
10373       reportError(std::move(Err), info->O->getFileName());
10374   }
10375   auto name = info->bindtable->lookup(ReferenceValue);
10376   return !name.empty() ? name.data() : nullptr;
10377 }
10378 
printLazyBindTable(ObjectFile * o)10379 void objdump::printLazyBindTable(ObjectFile *o) {
10380   outs() << "\nLazy bind table:\n";
10381   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10382     printMachOLazyBindTable(MachO);
10383   else
10384     WithColor::error()
10385         << "This operation is only currently supported "
10386            "for Mach-O executable files.\n";
10387 }
10388 
printWeakBindTable(ObjectFile * o)10389 void objdump::printWeakBindTable(ObjectFile *o) {
10390   outs() << "\nWeak bind table:\n";
10391   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10392     printMachOWeakBindTable(MachO);
10393   else
10394     WithColor::error()
10395         << "This operation is only currently supported "
10396            "for Mach-O executable files.\n";
10397 }
10398 
printExportsTrie(const ObjectFile * o)10399 void objdump::printExportsTrie(const ObjectFile *o) {
10400   outs() << "\nExports trie:\n";
10401   if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10402     printMachOExportsTrie(MachO);
10403   else
10404     WithColor::error()
10405         << "This operation is only currently supported "
10406            "for Mach-O executable files.\n";
10407 }
10408 
printRebaseTable(ObjectFile * o)10409 void objdump::printRebaseTable(ObjectFile *o) {
10410   outs() << "\nRebase table:\n";
10411   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10412     printMachORebaseTable(MachO);
10413   else
10414     WithColor::error()
10415         << "This operation is only currently supported "
10416            "for Mach-O executable files.\n";
10417 }
10418 
printBindTable(ObjectFile * o)10419 void objdump::printBindTable(ObjectFile *o) {
10420   outs() << "\nBind table:\n";
10421   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
10422     printMachOBindTable(MachO);
10423   else
10424     WithColor::error()
10425         << "This operation is only currently supported "
10426            "for Mach-O executable files.\n";
10427 }
10428